Jid-multi almost works.

This commit is contained in:
Tomasz Melcer 2006-07-12 14:19:58 +00:00
parent aed92d21b7
commit db089f103d
5 changed files with 420 additions and 132 deletions

View file

@ -286,11 +286,11 @@
<property name="spacing">0</property> <property name="spacing">0</property>
<child> <child>
<widget class="GtkLabel" id="instructions_label"> <widget class="GtkLabel" id="notes_label">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Fill in the form&lt;/b&gt;</property> <property name="label" translatable="yes">Please wait while the command is sending...</property>
<property name="use_underline">False</property> <property name="use_underline">False</property>
<property name="use_markup">True</property> <property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property> <property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property> <property name="wrap">False</property>
<property name="selectable">False</property> <property name="selectable">False</property>
@ -651,26 +651,39 @@
<property name="spacing">0</property> <property name="spacing">0</property>
<child> <child>
<widget class="GtkButton" id="cancel_button"> <widget class="GtkHBox" id="hbox2958">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="homogeneous">False</property>
<property name="label">gtk-cancel</property> <property name="spacing">0</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property> <child>
<property name="focus_on_click">True</property> <widget class="GtkButton" id="cancel_button">
<signal name="clicked" handler="on_cancel_button_clicked" last_modification_time="Thu, 22 Jun 2006 19:56:06 GMT"/> <property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-cancel</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_cancel_button_clicked" last_modification_time="Mon, 10 Jul 2006 16:24:32 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</widget> </widget>
<packing> <packing>
<property name="padding">3</property> <property name="padding">3</property>
<property name="expand">False</property> <property name="expand">True</property>
<property name="fill">False</property> <property name="fill">True</property>
</packing> </packing>
</child> </child>
<child>
<placeholder/>
</child>
<child> <child>
<widget class="GtkButton" id="back_button"> <widget class="GtkButton" id="back_button">
<property name="visible">True</property> <property name="visible">True</property>
@ -679,10 +692,10 @@
<property name="use_stock">True</property> <property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property> <property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property> <property name="focus_on_click">True</property>
<signal name="clicked" handler="on_back_button_clicked" last_modification_time="Thu, 22 Jun 2006 19:56:13 GMT"/> <signal name="clicked" handler="on_back_button_clicked" last_modification_time="Mon, 10 Jul 2006 16:24:50 GMT"/>
</widget> </widget>
<packing> <packing>
<property name="padding">3</property> <property name="padding">0</property>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">False</property> <property name="fill">False</property>
</packing> </packing>
@ -696,7 +709,7 @@
<property name="use_stock">True</property> <property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property> <property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property> <property name="focus_on_click">True</property>
<signal name="clicked" handler="on_forward_button_clicked" last_modification_time="Thu, 22 Jun 2006 19:56:18 GMT"/> <signal name="clicked" handler="on_forward_button_clicked" last_modification_time="Mon, 10 Jul 2006 16:24:47 GMT"/>
</widget> </widget>
<packing> <packing>
<property name="padding">3</property> <property name="padding">3</property>
@ -713,7 +726,23 @@
<property name="use_stock">True</property> <property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property> <property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property> <property name="focus_on_click">True</property>
<signal name="clicked" handler="on_execute_button_clicked" last_modification_time="Thu, 22 Jun 2006 19:56:23 GMT"/> <signal name="clicked" handler="on_execute_button_clicked" last_modification_time="Mon, 10 Jul 2006 16:24:42 GMT"/>
</widget>
<packing>
<property name="padding">3</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="close_button">
<property name="can_focus">True</property>
<property name="label">gtk-close</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_close_button_clicked" last_modification_time="Mon, 10 Jul 2006 16:24:38 GMT"/>
</widget> </widget>
<packing> <packing>
<property name="padding">3</property> <property name="padding">3</property>

View file

@ -199,61 +199,214 @@
<property name="focus_on_map">True</property> <property name="focus_on_map">True</property>
<child> <child>
<widget class="GtkScrolledWindow" id="data_form_scrolledwindow"> <widget class="GtkVBox" id="vbox111">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="homogeneous">False</property>
<property name="hscrollbar_policy">GTK_POLICY_NEVER</property> <property name="spacing">10</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_NONE</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child> <child>
<widget class="GtkVBox" id="container_vbox"> <widget class="GtkScrolledWindow" id="data_form_scrolledwindow">
<property name="border_width">5</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="homogeneous">False</property> <property name="can_focus">True</property>
<property name="spacing">5</property> <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child> <child>
<widget class="GtkLabel" id="form_instructions_label"> <widget class="GtkViewport" id="viewport2">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes"></property> <property name="shadow_type">GTK_SHADOW_IN</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">True</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">5</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child> <child>
<widget class="GtkHSeparator" id="hseparator16"> <widget class="GtkVBox" id="container_vbox">
<property name="visible">True</property> <property name="border_width">5</property>
</widget> <property name="visible">True</property>
<packing> <property name="homogeneous">False</property>
<property name="padding">5</property> <property name="spacing">5</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
<child> <child>
<placeholder/> <widget class="GtkLabel" id="form_instructions_label">
<property name="visible">True</property>
<property name="label" translatable="yes"></property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">True</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">5</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkHSeparator" id="form_instructions_hseparator">
<property name="visible">True</property>
</widget>
<packing>
<property name="padding">5</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</widget>
</child>
</widget>
</child> </child>
</widget> </widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkTable" id="item_list_table">
<property name="visible">True</property>
<property name="n_rows">1</property>
<property name="n_columns">2</property>
<property name="homogeneous">False</property>
<property name="row_spacing">0</property>
<property name="column_spacing">0</property>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow36">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
<property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTreeView" id="item_treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">False</property>
<property name="rules_hint">False</property>
<property name="reorderable">False</property>
<property name="enable_search">True</property>
<property name="fixed_height_mode">False</property>
<property name="hover_selection">False</property>
<property name="hover_expand">False</property>
</widget>
</child>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox112">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkButton" id="clear_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-clear</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="remove_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-remove</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="add_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-add</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="edit_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-edit</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options">fill</property>
<property name="y_options">fill</property>
</packing>
</child>
</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

@ -61,11 +61,11 @@ class CommandWindow:
self.xml = gtkgui_helpers.get_glade('adhoc_commands_window.glade') self.xml = gtkgui_helpers.get_glade('adhoc_commands_window.glade')
self.window = self.xml.get_widget('adhoc_commands_window') self.window = self.xml.get_widget('adhoc_commands_window')
for name in ('cancel_button', 'back_button', 'forward_button', for name in ('cancel_button', 'back_button', 'forward_button',
'execute_button','stages_notebook', 'execute_button','close_button','stages_notebook',
'retrieving_commands_stage_vbox', 'retrieving_commands_stage_vbox',
'command_list_stage_vbox','command_list_vbox', 'command_list_stage_vbox','command_list_vbox',
'sending_form_stage_vbox','sending_form_progressbar', 'sending_form_stage_vbox','sending_form_progressbar',
'no_commands_stage_vbox','error_stage_vbox', 'notes_label','no_commands_stage_vbox','error_stage_vbox',
'error_description_label'): 'error_description_label'):
self.__dict__[name] = self.xml.get_widget(name) self.__dict__[name] = self.xml.get_widget(name)
@ -75,6 +75,7 @@ class CommandWindow:
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
self.close_button.set_no_show_all(True)
self.stage1() self.stage1()
# displaying the window # displaying the window
@ -87,6 +88,7 @@ class CommandWindow:
def stage_back_button_clicked(self, *anything): assert False def stage_back_button_clicked(self, *anything): assert False
def stage_forward_button_clicked(self, *anything): assert False def stage_forward_button_clicked(self, *anything): assert False
def stage_execute_button_clicked(self, *anything): assert False def stage_execute_button_clicked(self, *anything): assert False
def stage_close_button_clicked(self, *anything): assert False
def stage_adhoc_commands_window_delete_event(self, *anything): assert False def stage_adhoc_commands_window_delete_event(self, *anything): assert False
def do_nothing(self, *anything): return False def do_nothing(self, *anything): return False
@ -103,8 +105,11 @@ class CommandWindow:
def on_execute_button_clicked(self, *anything): def on_execute_button_clicked(self, *anything):
return self.stage_execute_button_clicked(*anything) return self.stage_execute_button_clicked(*anything)
def on_close_button_clicked(self, *anything):
return self.stage_close_button_clicked(*anything)
def on_adhoc_commands_window_destroy(self, *anything): def on_adhoc_commands_window_destroy(self, *anything):
# do all actions that are needed to remove this object from memory... # TODO: do all actions that are needed to remove this object from memory...
self.remove_pulsing() self.remove_pulsing()
def on_adhoc_commands_window_delete_event(self, *anything): def on_adhoc_commands_window_delete_event(self, *anything):
@ -215,6 +220,8 @@ class CommandWindow:
assert isinstance(self.commandnode, unicode) assert isinstance(self.commandnode, unicode)
self.form_status = None
self.stages_notebook.set_current_page( self.stages_notebook.set_current_page(
self.stages_notebook.page_num( self.stages_notebook.page_num(
self.sending_form_stage_vbox)) self.sending_form_stage_vbox))
@ -231,6 +238,7 @@ class CommandWindow:
self.stage_back_button_clicked = self.stage3_back_button_clicked self.stage_back_button_clicked = self.stage3_back_button_clicked
self.stage_forward_button_clicked = self.stage3_forward_button_clicked self.stage_forward_button_clicked = self.stage3_forward_button_clicked
self.stage_execute_button_clicked = self.stage3_execute_button_clicked self.stage_execute_button_clicked = self.stage3_execute_button_clicked
self.stage_close_button_clicked = self.stage3_close_button_clicked
self.stage_adhoc_commands_window_delete_event = self.stage3_cancel_button_clicked self.stage_adhoc_commands_window_delete_event = self.stage3_cancel_button_clicked
def stage3_finish(self): def stage3_finish(self):
@ -255,6 +263,14 @@ class CommandWindow:
return False return False
return True return True
def stage3_close_button_clicked(self, widget):
# this works also as a handler for window_delete_event, so we have to return appropriate
# values
if widget==self.window:
return False
else:
self.window.destroy()
def stage3_back_button_clicked(self, widget): def stage3_back_button_clicked(self, widget):
self.stage3_submit_form('prev') self.stage3_submit_form('prev')
@ -287,23 +303,24 @@ class CommandWindow:
if self.sessionid is None: if self.sessionid is None:
self.sessionid = command.getAttr('sessionid') self.sessionid = command.getAttr('sessionid')
self.dataform = dataforms.DataForm(node=command.getTag('x')) self.form_status = command.getAttr('status')
self.data_form_widget.set_sensitive(True) if command.getTag('x') is not None:
try: self.dataform = dataforms.DataForm(node=command.getTag('x'))
self.data_form_widget.data_form=self.dataform
except dataforms.BadDataFormNode: self.data_form_widget.set_sensitive(True)
# TODO: translate try:
self.stage5('Service sent malformed data', senderror=True) self.data_form_widget.data_form=self.dataform
self.data_form_widget.show() except dataforms.BadDataFormNode:
# TODO: translate
self.stage5('Service sent malformed data', senderror=True)
self.data_form_widget.show()
else:
self.data_form_widget.hide()
action = command.getTag('action') action = command.getTag('action')
if action is None: if action is None:
# no action tag? check if that's last stage... self.cancel_button.set_sensitive(True)
if command.getAttr('status')=='completed':
self.cancel_button.set_sensitive(False)
else:
self.cancel_button.set_sensitive(True)
self.back_button.set_sensitive(False) self.back_button.set_sensitive(False)
self.forward_button.set_sensitive(False) self.forward_button.set_sensitive(False)
self.execute_button.set_sensitive(True) self.execute_button.set_sensitive(True)
@ -314,6 +331,25 @@ class CommandWindow:
self.forward_button.set_sensitive(action.getTag('next') is not None) self.forward_button.set_sensitive(action.getTag('next') is not None)
self.execute_button.set_sensitive(True) self.execute_button.set_sensitive(True)
if self.form_status == 'completed':
self.cancel_button.set_sensitive(False)
self.back_button.set_sensitive(False)
self.forward_button.set_sensitive(False)
self.execute_button.set_no_show_all(True)
self.execute_button.hide()
self.close_button.set_no_show_all(False)
self.close_button.show()
self.stage_adhoc_commands_window_delete_event = self.stage3_close_button_clicked
note = command.getTag('note')
if note is not None:
self.notes_label.set_text(note.getData().decode('utf-8'))
self.notes_label.set_no_show_all(False)
self.notes_label.show()
else:
self.notes_label.set_no_show_all(True)
self.notes_label.hide()
# stage 4: no commands are exposed # stage 4: no commands are exposed
def stage4(self): def stage4(self):
'''Display the message. Wait for user to close the window''' '''Display the message. Wait for user to close the window'''

View file

@ -249,7 +249,7 @@ class DataForm(xmpp.Node, object):
self.delChild('recorded') self.delChild('recorded')
except ValueError: except ValueError:
pass pass
self.addChild('recorded', None, fields) self.addChild('recorded', {}, fields)
def del_fields(self): def del_fields(self):
if self.mode is DATAFORM_SINGLE: if self.mode is DATAFORM_SINGLE:
@ -335,7 +335,10 @@ class DataField(xmpp.Node, object):
self.setAttr('var', var) self.setAttr('var', var)
def del_var(self): def del_var(self):
self.delAttr('var') try:
self.delAttr('var')
except KeyError:
pass
var = property(get_var, set_var, del_var, var = property(get_var, set_var, del_var,
""" Field name. """) """ Field name. """)
@ -347,7 +350,10 @@ class DataField(xmpp.Node, object):
self.setAttr('label', label) self.setAttr('label', label)
def del_label(self): def del_label(self):
self.delAttr('label') try:
self.delAttr('label')
except KeyError:
pass
label = property(get_label, set_label, del_label, label = property(get_label, set_label, del_label,
""" Human-readable name for field. """) """ Human-readable name for field. """)
@ -384,6 +390,14 @@ class DataField(xmpp.Node, object):
required = property(get_required, set_required, None, required = property(get_required, set_required, None,
""" If this is set to True, the field is required for form to be valid. """) """ If this is set to True, the field is required for form to be valid. """)
def iter_values(self):
assert self.type in ('list-single', 'list-multi', 'jid-multi')
for element in self.getChildren():
if not isinstance(element, xmpp.Node): continue
if not element.getName()=='value': continue
yield element.getData().decode('utf-8')
def get_value(self): def get_value(self):
if self.type in ('boolean',): if self.type in ('boolean',):
if self.getTagData('value') in (1, 'true'): if self.getTagData('value') in (1, 'true'):
@ -430,8 +444,10 @@ class DataField(xmpp.Node, object):
for element in self.getChildren(): for element in self.getChildren():
if not isinstance(element, xmpp.Node): continue if not isinstance(element, xmpp.Node): continue
if not element.getName()=='option': continue if not element.getName()=='option': continue
if element.getTag('value') is None: raise BadDataFormNode try:
yield element.getAttr('label'), element.getTag('value').getData() yield element.getAttr('label'), element.getTag('value').getData()
except TypeError:
raise BadDataFormNode
def get_options(self): def get_options(self):
""" Returns a list of tuples: (label, value). """ """ Returns a list of tuples: (label, value). """

View file

@ -17,6 +17,8 @@
""" This module contains widget that can display data form (JEP-0004). """ """ This module contains widget that can display data form (JEP-0004). """
import gtk import gtk
import pango
import gtkgui_helpers import gtkgui_helpers
import common.xmpp as xmpp import common.xmpp as xmpp
@ -27,12 +29,13 @@ class DataFormWidget(gtk.Alignment, object):
""" 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):
""" Create a widget. """ """ Create a widget. """
gtk.Alignment.__init__(self) gtk.Alignment.__init__(self, xscale=1.0, yscale=1.0)
self._data_form = None self._data_form = None
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.separator = self.xml.get_widget('form_instructions_hseparator')
self.container = self.xml.get_widget('container_vbox') 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'))
@ -54,6 +57,18 @@ class DataFormWidget(gtk.Alignment, object):
self.form.show() self.form.show()
self.container.pack_end(self.form, expand=True, fill=True) self.container.pack_end(self.form, expand=True, fill=True)
if dataform.instructions is None:
self.instructions.set_no_show_all(True)
self.instructions.hide()
self.separator.set_no_show_all(True)
self.separator.hide()
else:
self.instructions.set_text(dataform.instructions)
self.instructions.set_no_show_all(False)
self.instructions.show()
self.separator.set_no_show_all(False)
self.separator.show()
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
@ -81,39 +96,6 @@ class DataFormWidget(gtk.Alignment, object):
""" Treat 'us' as one widget. """ """ Treat 'us' as one widget. """
self.show_all() self.show_all()
#? def filled_data_form(self):
#? """ Generates form that contains values filled by user. """
#? assert isinstance(self._data_form, dataforms.DataForm)
#?
#? form = xmpp.Node('x', {'xmlns':xmpp.NS_DATA, 'type':'submit'})
#?
#?
#? for field in self._data_form.kids:
#? if not isinstance(field, xmpp.DataField): continue
#?
#? 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 in ('fixed',):
#? continue
#?
#? newfield = xmpp.Node('field', {'var': field.getVar()})
#?
#? if ftype in ('jid-multi', 'list-multi', 'text-multi'):
#? for value in field.getValues():
#? newvalue = xmpp.Node('value', {}, [value])
#? newfield.addChild(node=newvalue)
#? else:
#? newvalue = xmpp.Node('value', {}, [field.getValue()])
#? newfield.addChild(node=newvalue)
#?
#? form.addChild(node=newfield)
#?
#? return form
# "private" methods # "private" methods
# we have actually two different kinds of data forms: one is a simple form to fill, # we have actually two different kinds of data forms: one is a simple form to fill,
@ -129,6 +111,8 @@ class DataFormWidget(gtk.Alignment, object):
assert dataform.mode==dataforms.DATAFORM_SINGLE assert dataform.mode==dataforms.DATAFORM_SINGLE
gtk.Table.__init__(self) gtk.Table.__init__(self)
self.set_col_spacings(6)
self.set_row_spacings(6)
self._data_form = dataform self._data_form = dataform
@ -162,10 +146,8 @@ class DataFormWidget(gtk.Alignment, object):
commonwidget=False commonwidget=False
widget = gtk.Label(field.value) widget = gtk.Label(field.value)
widget.set_line_wrap(True) widget.set_line_wrap(True)
self.attach(widget, leftattach, rightattach, linecounter, linecounter+1) self.attach(widget, leftattach, rightattach, linecounter, linecounter+1,
xoptions=gtk.FILL, yoptions=gtk.FILL)
elif field.type in ('jid-multi'):
widget = gtk.Label(field.type)
elif field.type == 'list-single': elif field.type == 'list-single':
# TODO: When more than few choices, make a list # TODO: When more than few choices, make a list
@ -204,6 +186,42 @@ class DataFormWidget(gtk.Alignment, object):
field.value = u'' field.value = u''
widget.set_text(field.value) widget.set_text(field.value)
elif field.type == 'jid-multi':
commonwidget = False
xml = gtkgui_helpers.get_glade('data_form_window.glade', 'item_list_table')
widget = xml.get_widget('item_list_table')
treeview = xml.get_widget('item_treeview')
listmodel = gtk.ListStore(str, bool)
for value in field.iter_values():
# nobody will create several megabytes long stanza
listmodel.insert(999999, (value,False))
treeview.set_model(listmodel)
renderer = gtk.CellRendererText()
renderer.set_property('ellipsize', pango.ELLIPSIZE_START)
renderer.set_property('editable', True)
renderer.connect('edited',
self.on_jid_multi_cellrenderertext_edited, listmodel, field)
treeview.append_column(gtk.TreeViewColumn(None, renderer,
text=0, editable=1))
xml.get_widget('add_button').connect('clicked',
self.on_jid_multi_add_button_clicked, listmodel, field)
xml.get_widget('edit_button').connect('clicked',
self.on_jid_multi_edit_button_clicked, treeview)
xml.get_widget('remove_button').connect('clicked',
self.on_jid_multi_remove_button_clicked, treeview)
xml.get_widget('clear_button').connect('clicked',
self.on_jid_multi_clean_button_clicked, listmodel, field)
self.attach(widget, 1, 2, linecounter, linecounter+1)
del xml
elif field.type == 'text-private': elif field.type == 'text-private':
widget = gtk.Entry() widget = gtk.Entry()
widget.connect('changed', self.on_text_single_entry_changed, field) widget.connect('changed', self.on_text_single_entry_changed, field)
@ -214,13 +232,20 @@ class DataFormWidget(gtk.Alignment, object):
elif field.type == 'text-multi': elif field.type == 'text-multi':
# TODO: bigger text view # TODO: bigger text view
widget = gtk.TextView() commonwidget = False
widget.set_wrap_mode(gtk.WRAP_WORD)
widget.get_buffer().connect('changed', self.on_text_multi_textbuffer_changed, textwidget = gtk.TextView()
textwidget.set_wrap_mode(gtk.WRAP_WORD)
textwidget.get_buffer().connect('changed', self.on_text_multi_textbuffer_changed,
field) field)
if field.value is None: if field.value is None:
field.value = u'' field.value = u''
widget.get_buffer().set_text(field.value) textwidget.get_buffer().set_text(field.value)
widget = gtk.ScrolledWindow()
widget.add(textwidget)
self.attach(widget, 1, 2, linecounter, linecounter+1)
else:# field.type == 'text-single' or field.type is nonstandard: else:# field.type == 'text-single' or field.type is nonstandard:
# JEP says that if we don't understand some type, we # JEP says that if we don't understand some type, we
@ -234,11 +259,13 @@ class DataFormWidget(gtk.Alignment, object):
if commonlabel and field.label is not None: if commonlabel and field.label is not None:
label = gtk.Label(field.label) label = gtk.Label(field.label)
label.set_alignment(1.0, 0.5) label.set_alignment(1.0, 0.5)
self.attach(label, 0, 1, linecounter, linecounter+1) self.attach(label, 0, 1, linecounter, linecounter+1,
xoptions=gtk.FILL, yoptions=gtk.FILL)
if commonwidget: if commonwidget:
assert widget is not None assert widget is not None
self.attach(widget, 1, 2, linecounter, linecounter+1) self.attach(widget, 1, 2, linecounter, linecounter+1,
yoptions=gtk.FILL)
widget.show_all() widget.show_all()
if commondesc and field.description is not None: if commondesc and field.description is not None:
@ -247,7 +274,8 @@ class DataFormWidget(gtk.Alignment, object):
gtkgui_helpers.escape_for_pango_markup(field.description)+\ gtkgui_helpers.escape_for_pango_markup(field.description)+\
'</small>') '</small>')
label.set_line_wrap(True) label.set_line_wrap(True)
self.attach(label, 2, 3, linecounter, linecounter+1) self.attach(label, 2, 3, linecounter, linecounter+1,
xoptions=gtk.FILL|gtk.SHRINK, yoptions=gtk.FILL|gtk.SHRINK)
linecounter+=1 linecounter+=1
if self.get_property('visible'): if self.get_property('visible'):
@ -264,10 +292,11 @@ class DataFormWidget(gtk.Alignment, object):
field.value = value field.value = value
def on_list_multi_checkbutton_toggled(self, widget, field, value): def on_list_multi_checkbutton_toggled(self, widget, field, value):
# TODO: make some methods like add_value and remove_value
if widget.get_active() and value not in field.value: if widget.get_active() and value not in field.value:
field.value.append(value) field.value += [value]
elif not widget.get_active() and value in field.value: elif not widget.get_active() and value in field.value:
field.value.remove(value) field.value = [v for v in field.value if v!=value]
def on_text_single_entry_changed(self, widget, field): def on_text_single_entry_changed(self, widget, field):
field.value = widget.get_text() field.value = widget.get_text()
@ -277,6 +306,31 @@ class DataFormWidget(gtk.Alignment, object):
widget.get_start_iter(), widget.get_start_iter(),
widget.get_end_iter()) widget.get_end_iter())
def on_jid_multi_cellrenderertext_edited(self, cell, path, newtext, model, field):
old=model[path][0]
model[path][0]=newtext
values = field.values
values[values.index(old)]=newtext
field.values = values
def on_jid_multi_add_button_clicked(self, widget, model, field):
iter = model.insert(999999, ("new@jid",))
field.value += ["new@jid"]
def on_jid_multi_edit_button_clicked(self, widget, treeview):
model, iter = treeview.get_selection().get_selected()
assert iter is not None
model[iter][1]=True
def on_jid_multi_remove_button_clicked(self, widget, model, field):
pass
def on_jid_multi_clean_button_clicked(self, widget, model, field):
model.clear()
del field.value
class MultipleForm(gtk.Alignment, object): class MultipleForm(gtk.Alignment, object):
def __init__(self, dataform): def __init__(self, dataform):
assert dataform.mode==dataforms.DATAFORM_MULTIPLE assert dataform.mode==dataforms.DATAFORM_MULTIPLE