Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/gajim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTomasz Melcer <liori@exroot.org>2006-07-12 18:19:58 +0400
committerTomasz Melcer <liori@exroot.org>2006-07-12 18:19:58 +0400
commitdb089f103d71fd2c99d08acb3a68493143122b66 (patch)
treef7f3521dcaf30eeba8ac4587d9a8ac2ee886c320 /src
parentaed92d21b76229524268df13a72b3e61d196894b (diff)
Jid-multi almost works.
Diffstat (limited to 'src')
-rw-r--r--src/adhoc_commands.py68
-rw-r--r--src/common/dataforms.py26
-rw-r--r--src/dataforms.py148
3 files changed, 174 insertions, 68 deletions
diff --git a/src/adhoc_commands.py b/src/adhoc_commands.py
index 7519fee3b..7af0ff234 100644
--- a/src/adhoc_commands.py
+++ b/src/adhoc_commands.py
@@ -61,11 +61,11 @@ class CommandWindow:
self.xml = gtkgui_helpers.get_glade('adhoc_commands_window.glade')
self.window = self.xml.get_widget('adhoc_commands_window')
for name in ('cancel_button', 'back_button', 'forward_button',
- 'execute_button','stages_notebook',
+ 'execute_button','close_button','stages_notebook',
'retrieving_commands_stage_vbox',
'command_list_stage_vbox','command_list_vbox',
'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'):
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)
# setting initial stage
+ self.close_button.set_no_show_all(True)
self.stage1()
# displaying the window
@@ -87,6 +88,7 @@ class CommandWindow:
def stage_back_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_close_button_clicked(self, *anything): assert False
def stage_adhoc_commands_window_delete_event(self, *anything): assert False
def do_nothing(self, *anything): return False
@@ -103,8 +105,11 @@ class CommandWindow:
def on_execute_button_clicked(self, *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):
- # 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()
def on_adhoc_commands_window_delete_event(self, *anything):
@@ -215,6 +220,8 @@ class CommandWindow:
assert isinstance(self.commandnode, unicode)
+ self.form_status = None
+
self.stages_notebook.set_current_page(
self.stages_notebook.page_num(
self.sending_form_stage_vbox))
@@ -231,6 +238,7 @@ class CommandWindow:
self.stage_back_button_clicked = self.stage3_back_button_clicked
self.stage_forward_button_clicked = self.stage3_forward_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
def stage3_finish(self):
@@ -255,6 +263,14 @@ class CommandWindow:
return False
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):
self.stage3_submit_form('prev')
@@ -287,23 +303,24 @@ class CommandWindow:
if self.sessionid is None:
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)
- try:
- self.data_form_widget.data_form=self.dataform
- except dataforms.BadDataFormNode:
- # TODO: translate
- self.stage5('Service sent malformed data', senderror=True)
- self.data_form_widget.show()
+ if command.getTag('x') is not None:
+ self.dataform = dataforms.DataForm(node=command.getTag('x'))
+
+ self.data_form_widget.set_sensitive(True)
+ try:
+ self.data_form_widget.data_form=self.dataform
+ 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')
if action is None:
- # no action tag? check if that's last stage...
- if command.getAttr('status')=='completed':
- self.cancel_button.set_sensitive(False)
- else:
- self.cancel_button.set_sensitive(True)
+ self.cancel_button.set_sensitive(True)
self.back_button.set_sensitive(False)
self.forward_button.set_sensitive(False)
self.execute_button.set_sensitive(True)
@@ -314,6 +331,25 @@ class CommandWindow:
self.forward_button.set_sensitive(action.getTag('next') is not None)
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
def stage4(self):
'''Display the message. Wait for user to close the window'''
diff --git a/src/common/dataforms.py b/src/common/dataforms.py
index f1390bf05..5acf452ad 100644
--- a/src/common/dataforms.py
+++ b/src/common/dataforms.py
@@ -249,7 +249,7 @@ class DataForm(xmpp.Node, object):
self.delChild('recorded')
except ValueError:
pass
- self.addChild('recorded', None, fields)
+ self.addChild('recorded', {}, fields)
def del_fields(self):
if self.mode is DATAFORM_SINGLE:
@@ -335,7 +335,10 @@ class DataField(xmpp.Node, object):
self.setAttr('var', var)
def del_var(self):
- self.delAttr('var')
+ try:
+ self.delAttr('var')
+ except KeyError:
+ pass
var = property(get_var, set_var, del_var,
""" Field name. """)
@@ -347,7 +350,10 @@ class DataField(xmpp.Node, object):
self.setAttr('label', label)
def del_label(self):
- self.delAttr('label')
+ try:
+ self.delAttr('label')
+ except KeyError:
+ pass
label = property(get_label, set_label, del_label,
""" Human-readable name for field. """)
@@ -384,6 +390,14 @@ class DataField(xmpp.Node, object):
required = property(get_required, set_required, None,
""" 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):
if self.type in ('boolean',):
if self.getTagData('value') in (1, 'true'):
@@ -430,8 +444,10 @@ class DataField(xmpp.Node, object):
for element in self.getChildren():
if not isinstance(element, xmpp.Node): continue
if not element.getName()=='option': continue
- if element.getTag('value') is None: raise BadDataFormNode
- yield element.getAttr('label'), element.getTag('value').getData()
+ try:
+ yield element.getAttr('label'), element.getTag('value').getData()
+ except TypeError:
+ raise BadDataFormNode
def get_options(self):
""" Returns a list of tuples: (label, value). """
diff --git a/src/dataforms.py b/src/dataforms.py
index 4d82a5885..7fc7f835c 100644
--- a/src/dataforms.py
+++ b/src/dataforms.py
@@ -17,6 +17,8 @@
""" This module contains widget that can display data form (JEP-0004). """
import gtk
+import pango
+
import gtkgui_helpers
import common.xmpp as xmpp
@@ -27,12 +29,13 @@ class DataFormWidget(gtk.Alignment, object):
""" Data Form widget. Use like any other widget. """
def __init__(self, dataformnode=None):
""" Create a widget. """
- gtk.Alignment.__init__(self)
+ gtk.Alignment.__init__(self, xscale=1.0, yscale=1.0)
self._data_form = None
self.xml=gtkgui_helpers.get_glade('data_form_window.glade', 'data_form_scrolledwindow')
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.add(self.xml.get_widget('data_form_scrolledwindow'))
@@ -54,6 +57,18 @@ class DataFormWidget(gtk.Alignment, object):
self.form.show()
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):
""" Data form displayed in the widget or None if no form. """
return self._data_form
@@ -81,39 +96,6 @@ class DataFormWidget(gtk.Alignment, object):
""" Treat 'us' as one widget. """
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
# 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
gtk.Table.__init__(self)
+ self.set_col_spacings(6)
+ self.set_row_spacings(6)
self._data_form = dataform
@@ -162,10 +146,8 @@ class DataFormWidget(gtk.Alignment, object):
commonwidget=False
widget = gtk.Label(field.value)
widget.set_line_wrap(True)
- self.attach(widget, leftattach, rightattach, linecounter, linecounter+1)
-
- elif field.type in ('jid-multi'):
- widget = gtk.Label(field.type)
+ self.attach(widget, leftattach, rightattach, linecounter, linecounter+1,
+ xoptions=gtk.FILL, yoptions=gtk.FILL)
elif field.type == 'list-single':
# TODO: When more than few choices, make a list
@@ -204,6 +186,42 @@ class DataFormWidget(gtk.Alignment, object):
field.value = u''
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':
widget = gtk.Entry()
widget.connect('changed', self.on_text_single_entry_changed, field)
@@ -214,13 +232,20 @@ class DataFormWidget(gtk.Alignment, object):
elif field.type == 'text-multi':
# TODO: bigger text view
- widget = gtk.TextView()
- widget.set_wrap_mode(gtk.WRAP_WORD)
- widget.get_buffer().connect('changed', self.on_text_multi_textbuffer_changed,
+ commonwidget = False
+
+ textwidget = gtk.TextView()
+ textwidget.set_wrap_mode(gtk.WRAP_WORD)
+ textwidget.get_buffer().connect('changed', self.on_text_multi_textbuffer_changed,
field)
if field.value is None:
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:
# 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:
label = gtk.Label(field.label)
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:
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()
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)+\
'</small>')
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
if self.get_property('visible'):
@@ -264,10 +292,11 @@ class DataFormWidget(gtk.Alignment, object):
field.value = 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:
- field.value.append(value)
+ field.value += [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):
field.value = widget.get_text()
@@ -277,6 +306,31 @@ class DataFormWidget(gtk.Alignment, object):
widget.get_start_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):
def __init__(self, dataform):
assert dataform.mode==dataforms.DATAFORM_MULTIPLE