Ad-Hoc commands window now uses new dataform wrapper. /me dances

This commit is contained in:
Tomasz Melcer 2006-07-07 15:49:44 +00:00
parent 8c9711d7ea
commit c75bdcb63c
5 changed files with 233 additions and 190 deletions

View File

@ -208,7 +208,7 @@
<property name="window_placement">GTK_CORNER_TOP_LEFT</property> <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child> <child>
<widget class="GtkVBox" id="vbox111"> <widget class="GtkVBox" id="container_vbox">
<property name="border_width">5</property> <property name="border_width">5</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="homogeneous">False</property> <property name="homogeneous">False</property>
@ -251,19 +251,7 @@
</child> </child>
<child> <child>
<widget class="GtkTable" id="form_table"> <placeholder/>
<property name="visible">True</property>
<property name="n_rows">1</property>
<property name="n_columns">3</property>
<property name="homogeneous">False</property>
<property name="row_spacing">0</property>
<property name="column_spacing">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child> </child>
</widget> </widget>
</child> </child>

View File

@ -26,11 +26,10 @@
import gobject import gobject
import gtk import gtk
import common.xmpp as xmpp from common import xmpp, gajim, dataforms
import common.gajim as gajim
import gtkgui_helpers import gtkgui_helpers
import dataforms import dataforms as dataformwidget
class CommandWindow: class CommandWindow:
'''Class for a window for single ad-hoc commands session. Note, that '''Class for a window for single ad-hoc commands session. Note, that
@ -38,7 +37,9 @@ class CommandWindow:
TODO: maybe put this window into MessageWindow? consider this when TODO: maybe put this window into MessageWindow? consider this when
TODO: it will be possible to manage more than one window of one TODO: it will be possible to manage more than one window of one
TODO: account/jid pair in MessageWindowMgr.''' TODO: account/jid pair in MessageWindowMgr.
TODO: gtk 2.10 has a special wizard-widget, consider using it...'''
def __init__(self, account, jid): def __init__(self, account, jid):
'''Create new window.''' '''Create new window.'''
@ -68,7 +69,8 @@ class CommandWindow:
self.__dict__[name] = self.xml.get_widget(name) self.__dict__[name] = self.xml.get_widget(name)
# creating data forms widget # creating data forms widget
self.data_form_widget = dataforms.DataFormWidget() self.data_form_widget = dataformwidget.DataFormWidget()
self.data_form_widget.show()
self.sending_form_stage_vbox.pack_start(self.data_form_widget) self.sending_form_stage_vbox.pack_start(self.data_form_widget)
# setting initial stage # setting initial stage
@ -264,13 +266,14 @@ class CommandWindow:
self.remove_pulsing() self.remove_pulsing()
self.sending_form_progressbar.hide() self.sending_form_progressbar.hide()
self.sessionid = command.getAttr('sessionid') if self.sessionid is None:
self.sessionid = command.getAttr('sessionid')
self.dataform = xmpp.DataForm(node=command.getTag('x')) self.dataform = dataforms.DataForm(node=command.getTag('x'))
self.data_form_widget.show()
self.data_form_widget.set_sensitive(True) self.data_form_widget.set_sensitive(True)
self.data_form_widget.set_data_form(self.dataform) self.data_form_widget.set_data_form(self.dataform)
self.data_form_widget.show()
action = command.getTag('action') action = command.getTag('action')
if action is None: if action is None:
@ -367,6 +370,7 @@ class CommandWindow:
def callback(response): def callback(response):
'''Called on response to query.''' '''Called on response to query.'''
# TODO: move to connection_handlers.py
# is error => error stage # is error => error stage
error = response.getError() error = response.getError()
if error is not None: if error is not None:
@ -405,10 +409,11 @@ class CommandWindow:
cmdnode.setAttr('sessionid', self.sessionid) cmdnode.setAttr('sessionid', self.sessionid)
if self.data_form_widget.data_form is not None: if self.data_form_widget.data_form is not None:
cmdnode.addChild(node=self.data_form_widget.filled_data_form()) cmdnode.addChild(node=dataforms.DataForm(tofill=self.data_form_widget.data_form))
def callback(response): def callback(response):
# TODO: error handling # TODO: error handling
# TODO: move to connection_handlers.py
self.stage3_next_form(response.getTag('command')) self.stage3_next_form(response.getTag('command'))
print stanza print stanza

View File

@ -37,7 +37,10 @@ def del_multiple_tag_value(node, childname):
childname in node. childname in node.
""" """
while node.delChild(childname): try:
while node.delChild(childname):
pass
except ValueError:
pass pass
def iter_elements(node, childname): def iter_elements(node, childname):
@ -65,7 +68,7 @@ class DataForm(xmpp.Node, object):
assert (isinstance(tofill, DataForm) or tofill is None) assert (isinstance(tofill, DataForm) or tofill is None)
assert not (node is not None and tofill is not None) assert not (node is not None and tofill is not None)
assert typ in (None, 'form', 'submit', 'cancel', 'return') assert typ in (None, 'form', 'submit', 'cancel', 'result')
assert isinstance(title, basestring) or title is None assert isinstance(title, basestring) or title is None
assert isinstance(instructions, basestring) or instructions is None assert isinstance(instructions, basestring) or instructions is None
assert (fields is None or fields.__iter__) assert (fields is None or fields.__iter__)
@ -94,11 +97,16 @@ class DataForm(xmpp.Node, object):
self._mode = DATAFORM_SINGLE self._mode = DATAFORM_SINGLE
# change every <field/> to DataField object # change every <field/> to DataField object
toadd=[]
for field in self.getChildren(): for field in self.getChildren():
if not isinstance(field, xmpp.Node): continue if not isinstance(field, xmpp.Node): continue
if not field.getName()=='field': continue if not field.getName()=='field': continue
self.delChild(field) toadd.append(DataField(node=field))
self.addChild(node=DataField(node=field)
del_multiple_tag_value(self, 'field')
for field in toadd:
self.addChild(node=field)
else: # neither tofill nor node has a Node else: # neither tofill nor node has a Node
if typ is None: typ='result' if typ is None: typ='result'
if records is not None and len(records)>1: if records is not None and len(records)>1:
@ -133,7 +141,10 @@ class DataForm(xmpp.Node, object):
self.setTagData('title') self.setTagData('title')
def del_title(self): def del_title(self):
self.delChild('title') try:
self.delChild('title')
except ValueError:
pass
title = property(get_title, set_title, del_title, title = property(get_title, set_title, del_title,
"Form title, in unicode, from <title/> element.") "Form title, in unicode, from <title/> element.")
@ -168,22 +179,22 @@ class DataForm(xmpp.Node, object):
def iter_records(self): def iter_records(self):
if self.mode is DATAFORM_SINGLE: if self.mode is DATAFORM_SINGLE:
yield DataRecord(self) yield DataRecord(node=self)
else: else:
for item in self.getChildren(): for item in self.getChildren():
if not isinstance(item, xmpp.Node): continue if not isinstance(item, xmpp.Node): continue
if not item.getName()=='item': continue if not item.getName()=='item': continue
yield DataRecord(item) yield DataRecord(node=item)
def get_records(self): def get_records(self):
if self.mode is DATAFORM_SINGLE: if self.mode is DATAFORM_SINGLE:
return [DataRecord(self),] return [DataRecord(node=self),]
else: else:
items = [] items = []
for node in self.getChildren(): for node in self.getChildren():
if not isinstance(node, xmpp.Node): continue if not isinstance(node, xmpp.Node): continue
if not node.getName()=='item': continue if not node.getName()=='item': continue
items.append(DataRecord(node)) items.append(DataRecord(node=node))
return items return items
def set_records(self, records): def set_records(self, records):
@ -191,9 +202,9 @@ class DataForm(xmpp.Node, object):
assert len(records)==1 assert len(records)==1
record = records[0] record = records[0]
assert isinstance(record, dict) assert isinstance(record, DataRecord)
for name, value in record.iteritems(): for field in record.iter_fields():
self[name]=value self[field.var]=field.value
else: else:
self.del_records(self) self.del_records(self)
for record in records: for record in records:
@ -229,19 +240,48 @@ class DataForm(xmpp.Node, object):
self.addChild(node=field) self.addChild(node=field)
else: else:
assert len(self.records)==0 assert len(self.records)==0
self.delChild('recorded') try:
self.delChild('recorded')
except ValueError:
pass
self.addChild('recorded', None, fields) self.addChild('recorded', None, fields)
def del_fields(self): def del_fields(self):
if self.mode is DATAFORM_SINGLE: if self.mode is DATAFORM_SINGLE:
del_multiple_tag_value(self, "field") del_multiple_tag_value(self, "field")
else: else:
self.delChild('recorded') try:
self.delChild('recorded')
except ValueError:
pass
def iter_fields(self):
if self.mode is DATAFORM_SINGLE:
container = self
else:
container = self.getTag("recorded")
for child in container.getChildren():
if isinstance(child, DataField):
yield child
fields = property(get_fields, set_fields, del_fields, fields = property(get_fields, set_fields, del_fields,
"""Fields in this form; a list; if in DATAFORM_SINGLE mode, you should not """Fields in this form; a list; if in DATAFORM_SINGLE mode, you should not
set their values directly.""") set their values directly.""")
def __getitem__(self, var):
for field in self.iter_fields():
if field.var==var:
return field.value
raise KeyError, "This form does not contain %r field." % var
def __setitem__(self, var, value):
for field in self.iter_fields():
if field.var==var:
field.value=value
return
raise KeyError, "This form does not contain %r field." % var
class DataField(xmpp.Node, object): class DataField(xmpp.Node, object):
def __init__(self, typ='text-single', desc=None, required=None, value=None, options=None, node=None): def __init__(self, typ='text-single', desc=None, required=None, value=None, options=None, node=None):
assert typ in ('boolean', 'fixed', 'hidden', 'jid-multi', 'jid-single', 'list-multi', assert typ in ('boolean', 'fixed', 'hidden', 'jid-multi', 'jid-single', 'list-multi',
@ -306,7 +346,10 @@ class DataField(xmpp.Node, object):
self.setTagData('desc', desc) self.setTagData('desc', desc)
def del_description(self): def del_description(self):
self.delChild('desc') try:
self.delChild('desc')
except ValueError:
pass
description = property(get_description, set_description, del_description, description = property(get_description, set_description, del_description,
""" A natural-language description of the field. It should not contain """ A natural-language description of the field. It should not contain
@ -369,16 +412,30 @@ class DataField(xmpp.Node, object):
""" The value of field. Depending on the type, it is a boolean, a unicode string or a list """ The value of field. Depending on the type, it is a boolean, a unicode string or a list
of stings. """) of stings. """)
def iter_options(self):
""" Yields a pair: label, value """
for element in self.getChildren():
if not isinstance(element, xmpp.Node): continue
if not element.getName()=='option': continue
yield element.getAttr('label'), element.getTag('value').getData()
def get_options(self): def get_options(self):
return [tag.getData() for tag in self.getTags('option')] """ Returns a list of tuples: (label, value). """
return [(tag.getAttr('label'), tag.getTag('value').getData()) for tag in self.getTags('option')]
def set_options(self, options): def set_options(self, options):
""" Options need to be a list of tuples (label, value), both unicode. """
assert options.__iter__ assert options.__iter__
del_multiple_tag_value(self, 'option') del_multiple_tag_value(self, 'option')
for option in options: for option in options:
assert isinstance(option, basestring) assert option[0] is None or isinstance(option[0], unicode)
self.addChild('option', None, (option,)) assert isinstance(option[1], unicode)
if option[0] is None:
attr=None
else:
attr={'label': option[0].encode('utf-8')}
self.addChild('option', attr, (option[1].encode('utf-8'),))
def del_options(self): def del_options(self):
del_multiple_tag_value(self, 'option') del_multiple_tag_value(self, 'option')
@ -386,22 +443,30 @@ class DataField(xmpp.Node, object):
options = property(get_options, set_options, del_options, options = property(get_options, set_options, del_options,
""" Options to choose between in list-* fields. """) """ Options to choose between in list-* fields. """)
class DataRecord(xmpp.Node, dict): class DataRecord(xmpp.Node):
""" Class to store fields. May be used as temporary storage (for example when reading a list of """ Class to store fields. May be used as temporary storage (for example when reading a list of
fields from DataForm in DATAFORM_SINGLE mode), may be used as permanent storage place (for example fields from DataForm in DATAFORM_SINGLE mode), may be used as permanent storage place (for example
for DataForms in DATAFORM_MULTIPLE mode).""" for DataForms in DATAFORM_MULTIPLE mode). It expects that every <field/> element is actually
a DataField instance."""
def __init__(self, fields=None, node=None): def __init__(self, fields=None, node=None):
assert (fields is None) or (node is None) assert (fields is None) or (node is None)
assert (fields is None) or (fields.__iter__) assert (fields is None) or (fields.__iter__)
assert (node is None) or (isinstance(node, xmpp.Node)) assert (node is None) or (isinstance(node, xmpp.Node))
dict.__init__(self) self.vars = {}
xmpp.Node.__init__(self, node=node) xmpp.Node.__init__(self, node=node)
if node is not None:
for field in node.getTags('field'):
assert isinstance(field, DataField)
self.vars[field.var] = field
if fields is not None: if fields is not None:
for field in fields: for field in fields:
assert isinstance(field, DataField) assert isinstance(field, DataField)
self.addChild(node=field) self.addChild(node=field)
self[field.name] = field self.vars[field.var] = field
# if there will be ever needed access to all fields as a list, write it here, in form of property # if there will be ever needed access to all fields as a list, write it here, in form of property
@ -409,3 +474,6 @@ class DataRecord(xmpp.Node, dict):
for field in self.getChildren(): for field in self.getChildren():
if not isinstance(field, xmpp.DataField): continue if not isinstance(field, xmpp.DataField): continue
yield field yield field
def __getitem__(self, item):
return self.vars[item]

View File

@ -58,9 +58,9 @@ class Node:
"node" and other arguments is provided then the node initially created as replica of "node" "node" and other arguments is provided then the node initially created as replica of "node"
provided and then modified to be compliant with other arguments.""" provided and then modified to be compliant with other arguments."""
if node: if node:
if self.FORCE_NODE_RECREATION and type(node)==type(self): if self.FORCE_NODE_RECREATION and isinstance(node, Node):
node=str(node) node=str(node)
if type(node)<>type(self): if not isinstance(node, Node):
node=NodeBuilder(node,self) node=NodeBuilder(node,self)
else: else:
self.name,self.namespace,self.attrs,self.data,self.kids,self.parent = node.name,node.namespace,{},[],[],node.parent self.name,self.namespace,self.attrs,self.data,self.kids,self.parent = node.name,node.namespace,{},[],[],node.parent

View File

@ -20,8 +20,9 @@ import gtk
import gtkgui_helpers import gtkgui_helpers
import common.xmpp as xmpp import common.xmpp as xmpp
import common.dataforms as dataforms
class DataFormWidget(gtk.Alignment): class DataFormWidget(gtk.Alignment, object):
# "public" interface # "public" interface
""" Data Form widget. Use like any other widget. """ """ Data Form widget. Use like any other widget. """
def __init__(self, dataformnode=None): def __init__(self, dataformnode=None):
@ -32,25 +33,40 @@ class DataFormWidget(gtk.Alignment):
self.xml=gtkgui_helpers.get_glade('data_form_window.glade', 'data_form_scrolledwindow') self.xml=gtkgui_helpers.get_glade('data_form_window.glade', 'data_form_scrolledwindow')
self.instructions = self.xml.get_widget('form_instructions_label') self.instructions = self.xml.get_widget('form_instructions_label')
self.form = self.xml.get_widget('form_table') self.container = self.xml.get_widget('container_vbox')
self.add(self.xml.get_widget('data_form_scrolledwindow')) self.add(self.xml.get_widget('data_form_scrolledwindow'))
self.set_data_form(dataformnode) if dataformnode is not None:
self.set_data_form(dataformnode)
def set_data_form(self, dataform=None): def set_data_form(self, dataform=None):
""" Set the data form (xmpp.DataForm) displayed in widget. """ Set the data form (xmpp.DataForm) displayed in widget.
Set to None to erase the form. """ Set to None to erase the form. """
assert (isinstance(dataform, xmpp.Node) or (dataform is None)) assert isinstance(dataform, dataforms.DataForm)
if self._data_form is not None: self._cleanWidgets() self.del_data_form()
self._data_form = dataform self._data_form = dataform
if self._data_form is not None: self._buildWidgets() if dataform.mode==dataforms.DATAFORM_SINGLE:
self.form = self.__class__.SingleForm(dataform)
else:
self.form = self.__class__.MultipleForm(dataform)
self.form.show()
self.container.pack_end(self.form)
def get_data_form(self): def get_data_form(self):
""" Data form displayed in the widget or None if no form. """ """ Data form displayed in the widget or None if no form. """
return self._data_form return self._data_form
def del_data_form(self):
if self._data_form is not None:
self.container.remove(self.form)
self.form = None
self._data_form = None
data_form = property(get_data_form, set_data_form, del_data_form,
"Data form presented in a widget")
def get_title(self): def get_title(self):
""" Get the title of data form, as a unicode object. If no """ Get the title of data form, as a unicode object. If no
title or no form, returns u''. Useful for setting window title. """ title or no form, returns u''. Useful for setting window title. """
@ -59,17 +75,19 @@ class DataFormWidget(gtk.Alignment):
return self._data_form['title'].encode('utf-8') return self._data_form['title'].encode('utf-8')
return u'' return u''
title = property(get_title, None, None, "Data form title")
def show(self): def show(self):
""" Treat 'us' as one widget. """ """ Treat 'us' as one widget. """
self.show_all() self.show_all()
def filled_data_form(self): def filled_data_form(self):
""" Generates form that contains values filled by user. This """ Generates form that contains values filled by user. """
won't be DataForm object, as the DataFields seem to be uncapable assert isinstance(self._data_form, dataforms.DataForm)
of some things. """
assert isinstance(self._data_form, xmpp.DataForm)
form = xmpp.Node('x', {'xmlns':xmpp.NS_DATA, 'type':'submit'}) form = xmpp.Node('x', {'xmlns':xmpp.NS_DATA, 'type':'submit'})
for field in self._data_form.kids: for field in self._data_form.kids:
if not isinstance(field, xmpp.DataField): continue if not isinstance(field, xmpp.DataField): continue
@ -96,158 +114,122 @@ class DataFormWidget(gtk.Alignment):
return form return form
data_form = property(get_data_form, set_data_form, None, "Data form presented in a widget")
title = property(get_title, None, None, "Data form title")
# "private" methods # "private" methods
def _buildWidgets(self):
""" Create all sub-widgets according to self._data_form and
JEP-0004. """
assert self._data_form is not None
assert len(self.form.get_children())==0
# it is *very* often used here # we have actually two different kinds of data forms: one is a simple form to fill,
df = self._data_form # second is a table with several records; we will treat second as read-only, but still
# we should have a way to show it
instructions = df.getInstructions() # we will place both types in two different private classes, so the code will be clean;
if instructions is not None: # both will have the same interface
self.instructions.set_text(instructions)
linecounter = 0 class SingleForm(gtk.Table, object):
""" Widget that represent DATAFORM_SINGLE mode form. """
def __init__(self, dataform):
assert dataform.mode==dataforms.DATAFORM_SINGLE
for field in df.kids: gtk.Table.__init__(self)
if not isinstance(field, xmpp.DataField): continue
# TODO: rewrite that when xmpp.DataField will be rewritten self._data_form = dataform
ftype = field.getType()
if ftype not in ('boolean', 'fixed', 'hidden', 'jid-multi',
'jid-single', 'list-multi', 'list-single',
'text-multi', 'text-private', 'text-single'):
ftype = 'text-single'
if ftype == 'hidden': continue # building widget
linecounter = 0
# field label # for each field...
flabel = field.getAttr('label') for field in self._data_form.iter_fields():
if flabel is None: if field.type=='hidden': continue
flabel = field.getVar()
# field description commonlabel = True
fdesc = field.getDesc() commondesc = True
commonwidget = True
widget = None
# field value (if one) if field.type=='boolean':
fvalue = field.getValue() widget = gtk.CheckButton()
widget.connect('toggled', self.on_boolean_checkbutton_toggled, field)
widget.set_active(field.value)
# field values (if one or more) elif field.type=='fixed':
fvalues = field.getValues() leftattach = 1
rightattach = 2
if field.label is None:
commonlabel = False
leftattach = 0
if field.description is None:
commondesc = False
rightattach = 3
commonwidget=False
widget = gtk.Label(field.value)
widget.set_line_wrap(True)
self.attach(widget, leftattach, rightattach, linecounter, linecounter+1)
# field options elif field.type in ('jid-multi', 'jid-single', 'list-multi', 'text-multi',
foptions = field.getOptions() 'text-private'):
widget = gtk.Label(field.type)
commonlabel = True elif field.type == 'list-single':
commondesc = True # TODO: When more than few choices, make a list
commonwidget = True # TODO: Think of moving that to another function (it could be used
# TODO: in stage2 of adhoc commands too).
# TODO: What if we have radio buttons and non-required field?
# TODO: We cannot deactivate them all...
widget = gtk.VBox()
first_radio = None
for label, value in field.iter_options():
radio = gtk.RadioButton(first_radio, label=label)
radio.connect('toggled', self.on_list_single_radiobutton_toggled,
field, value)
if first_radio is None:
first_radio = radio
if field.value is None:
field.value = value
if value == field.value:
radio.set_active(True)
widget.pack_start(radio, expand=False)
if ftype == 'boolean': else:# field.type == 'text-single' or field.type is nonstandard:
widget = gtk.CheckButton() # JEP says that if we don't understand some type, we
widget.connect('toggled', self.on_boolean_checkbutton_toggled, field) # should handle it as text-single
if fvalue in ('1', 'true'): widget = gtk.Entry()
widget.set_active(True) widget.connect('changed', self.on_text_single_entry_changed, field)
else: if field.value is None:
field.setValue('0') field.value = u''
widget.set_text(field.value)
elif ftype == 'fixed': if commonlabel and field.label is not None:
leftattach = 1 label = gtk.Label(field.label)
rightattach = 2 label.set_justify(gtk.JUSTIFY_RIGHT)
if flabel is None: self.attach(label, 0, 1, linecounter, linecounter+1)
commonlabel = False
leftattach = 0
if fdesc is None:
commondesc = False
rightattach = 3
commonwidget = False
widget = gtk.Label(fvalue)
widget.set_line_wrap(True)
self.form.attach(widget, leftattach, rightattach, linecounter, linecounter+1)
elif ftype == 'jid-multi': if commonwidget:
widget = gtk.Label('jid-multi field') assert widget is not None
self.attach(widget, 1, 2, linecounter, linecounter+1)
widget.show_all()
elif ftype == 'jid-single': if commondesc and field.description is not None:
widget = gtk.Label('jid-single field') # TODO: with smaller font
label = gtk.Label(field.description)
label.set_line_wrap(True)
self.attach(label, 2, 3, linecounter, linecounter+1)
elif ftype == 'list-multi': linecounter+=1
widget = gtk.Label('list-multi field') if self.get_property('visible'):
self.show_all()
elif ftype == 'list-single': def show(self):
# TODO: When more than few choices, make a list # simulate that we are one widget
widget = gtk.VBox() self.show_all()
first_radio = None
right_value = False
for label, value in foptions:
radio = gtk.RadioButton(first_radio, label=label)
radio.connect('toggled', self.on_list_single_radiobutton_toggled,
field, value)
if first_radio is None:
first_radio = radio
first_value = value
if value == fvalue:
right_value = True
widget.pack_end(radio, expand=False)
if not right_value:
field.setValue(first_value)
elif ftype == 'text-multi': def on_boolean_checkbutton_toggled(self, widget, field):
widget = gtk.Label('text-multi field') field.value = widget.get_active()
elif ftype == 'text-private': def on_list_single_radiobutton_toggled(self, widget, field, value):
widget = gtk.Label('text-private field') field.value = value
elif ftype == 'text-single': def on_text_single_entry_changed(self, widget, field):
widget = gtk.Entry() field.value = widget.get_text()
widget.connect('changed', self.on_text_single_entry_changed, field)
if fvalue is None:
field.setValue('')
fvalue = ''
widget.set_text(fvalue)
else:
widget = gtk.Label('Unhandled widget type!')
if commonlabel and flabel is not None: class MultipleForm(gtk.Alignment, object):
label = gtk.Label(flabel) def __init__(self, dataform):
label.set_justify(gtk.JUSTIFY_RIGHT) assert dataform.mode==dataforms.DATAFORM_MULTIPLE
self.form.attach(label, 0, 1, linecounter, linecounter+1)
if commonwidget:
self.form.attach(widget, 1, 2, linecounter, linecounter+1)
if commondesc and fdesc is not None:
label = gtk.Label(fdesc)
label.set_line_wrap(True)
self.form.attach(label, 2, 3, linecounter, linecounter+1)
linecounter += 1
self.form.show_all()
def _cleanWidgets(self):
""" Destroy all sub-widgets used to build current data form. """
def remove(widget):
self.form.remove(widget)
self.form.foreach(remove)
self.instructions.set_text(u"")
def on_boolean_checkbutton_toggled(self, widget, field):
if widget.get_active():
field.setValue('true')
else:
field.setValue('false')
def on_list_single_radiobutton_toggled(self, widget, field, value):
field.setValue(value)
def on_text_single_entry_changed(self, widget, field):
# TODO: check for encoding?
field.setValue(widget.get_text())