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-09 21:55:56 +0400
committerTomasz Melcer <liori@exroot.org>2006-07-09 21:55:56 +0400
commitaed92d21b76229524268df13a72b3e61d196894b (patch)
treeb4ed050ba870d56566a8230dd567026aefeb3a18 /src
parentc75bdcb63c7e3bd1b3fad1c8201d885ab6b379af (diff)
Some fixes in common/dataforms, new field types...
Now only jid-multi isn't handled.
Diffstat (limited to 'src')
-rw-r--r--src/adhoc_commands.py83
-rw-r--r--src/common/dataforms.py36
-rw-r--r--src/dataforms.py125
3 files changed, 172 insertions, 72 deletions
diff --git a/src/adhoc_commands.py b/src/adhoc_commands.py
index 1282449cf..7519fee3b 100644
--- a/src/adhoc_commands.py
+++ b/src/adhoc_commands.py
@@ -29,6 +29,7 @@ import gtk
from common import xmpp, gajim, dataforms
import gtkgui_helpers
+import dialogs
import dataforms as dataformwidget
class CommandWindow:
@@ -80,18 +81,12 @@ class CommandWindow:
self.xml.signal_autoconnect(self)
self.window.show_all()
- def on_adhoc_commands_window_destroy(self, window):
- ''' The window dissappeared somehow... clean the environment,
- Stop pulsing.'''
- self.remove_pulsing()
-
# these functions are set up by appropriate stageX methods
def stage_finish(self, *anything): pass
def stage_cancel_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_execute_button_clicked(self, *anything): assert False
- def stage_adhoc_commands_window_destroy(self, *anything): assert False
def stage_adhoc_commands_window_delete_event(self, *anything): assert False
def do_nothing(self, *anything): return False
@@ -109,11 +104,15 @@ class CommandWindow:
return self.stage_execute_button_clicked(*anything)
def on_adhoc_commands_window_destroy(self, *anything):
- return self.stage_adhoc_commands_window_destroy(*anything)
+ # do all actions that are needed to remove this object from memory...
+ self.remove_pulsing()
def on_adhoc_commands_window_delete_event(self, *anything):
return self.stage_adhoc_commands_window_delete_event(self, *anything)
+ def __del__(self):
+ print "Object has been deleted."
+
# stage 1: waiting for command list
def stage1(self):
'''Prepare the first stage. Request command list,
@@ -141,7 +140,6 @@ class CommandWindow:
self.stage_finish = self.stage1_finish
self.stage_cancel_button_clicked = self.stage1_cancel_button_clicked
self.stage_adhoc_commands_window_delete_event = self.stage1_adhoc_commands_window_delete_event
- self.stage_adhoc_commands_window_destroy = self.do_nothing
def stage1_finish(self):
self.remove_pulsing()
@@ -183,13 +181,12 @@ class CommandWindow:
if first_radio is None:
first_radio = radio
self.commandnode = commandnode
- self.command_list_vbox.pack_end(radio, expand=False)
+ self.command_list_vbox.pack_start(radio, expand=False)
self.command_list_vbox.show_all()
self.stage_finish = self.stage2_finish
self.stage_cancel_button_clicked = self.stage2_cancel_button_clicked
self.stage_forward_button_clicked = self.stage2_forward_button_clicked
- self.stage_adhoc_commands_window_destroy = self.do_nothing
self.stage_adhoc_commands_window_delete_event = self.do_nothing
def stage2_finish(self):
@@ -234,14 +231,29 @@ 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_adhoc_commands_window_destroy = self.do_nothing
- self.stage_adhoc_commands_window_delete_event = self.do_nothing
+ self.stage_adhoc_commands_window_delete_event = self.stage3_cancel_button_clicked
def stage3_finish(self):
pass
- def stage3_cancel_button_clicked(self, widget):
- pass
+ def stage3_cancel_button_clicked(self, widget, *anything):
+ ''' We are in the middle of executing command. Ask user if he really want to cancel
+ the process, then... cancel it. '''
+ # this works also as a handler for window_delete_event, so we have to return appropriate
+ # values
+ # TODO: translate it
+ dialog = dialogs.HigDialog(self.window, gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_MODAL,
+ gtk.BUTTONS_YES_NO, 'Cancel confirmation',
+ 'You are in process of executing command. Do you really want to cancel it?')
+ dialog.popup()
+ if dialog.get_response()==gtk.RESPONSE_YES:
+ self.send_cancel()
+ if widget==self.window:
+ return False
+ else:
+ self.window.destroy()
+ return False
+ return True
def stage3_back_button_clicked(self, widget):
self.stage3_submit_form('prev')
@@ -256,6 +268,12 @@ class CommandWindow:
self.data_form_widget.set_sensitive(False)
if self.data_form_widget.get_data_form() is None:
self.data_form_widget.hide()
+
+ self.cancel_button.set_sensitive(True)
+ self.back_button.set_sensitive(False)
+ self.forward_button.set_sensitive(False)
+ self.execute_button.set_sensitive(False)
+
self.sending_form_progressbar.show()
self.setup_pulsing(self.sending_form_progressbar)
self.send_command(action)
@@ -272,19 +290,26 @@ class CommandWindow:
self.dataform = dataforms.DataForm(node=command.getTag('x'))
self.data_form_widget.set_sensitive(True)
- self.data_form_widget.set_data_form(self.dataform)
+ 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()
action = command.getTag('action')
if action is None:
- # no action tag? that's last stage...
- self.cancel_button.set_sensitive(False)
+ # 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.back_button.set_sensitive(False)
self.forward_button.set_sensitive(False)
self.execute_button.set_sensitive(True)
else:
# actions, actions, actions...
- self.cancel_button.set_sensitive(False)
+ self.cancel_button.set_sensitive(True)
self.back_button.set_sensitive(action.getTag('prev') is not None)
self.forward_button.set_sensitive(action.getTag('next') is not None)
self.execute_button.set_sensitive(True)
@@ -306,7 +331,6 @@ class CommandWindow:
self.stage_finish = self.do_nothing
self.stage_cancel_button_clicked = self.stage4_cancel_button_clicked
- self.stage_adhoc_commands_window_destroy = self.do_nothing
self.stage_adhoc_commands_window_delete_event = self.do_nothing
def stage4_cancel_button_clicked(self, widget):
@@ -316,12 +340,13 @@ class CommandWindow:
self.stage1()
# stage 5: an error has occured
- def stage5(self, error):
+ def stage5(self, error, senderror=False):
'''Display the error message. Wait for user to close the window'''
+ # TODO: sending error to responder
# close old stage
self.stage_finish()
- assert isinstance(error, unicode)
+ assert isinstance(error, basestring)
self.stages_notebook.set_current_page(
self.stages_notebook.page_num(
@@ -336,7 +361,6 @@ class CommandWindow:
self.stage_finish = self.do_nothing
self.stage_cancel_button_clicked = self.stage5_cancel_button_clicked
- self.stage_adhoc_commands_window_destroy = self.do_nothing
self.stage_adhoc_commands_window_delete_event = self.do_nothing
def stage5_cancel_button_clicked(self, widget):
@@ -419,3 +443,18 @@ class CommandWindow:
print stanza
self.account.connection.SendAndCallForResponse(stanza, callback)
+
+ def send_cancel(self):
+ '''Send the command with action='cancel'. '''
+ assert self.commandnode is not None
+ assert self.sessionid is not None
+
+ stanza = xmpp.Iq(typ='set', to=self.jid)
+ stanza.addChild('command', attrs={
+ 'xmlns':xmpp.NS_COMMANDS,
+ 'node':self.commandnode,
+ 'sessionid':self.sessionid,
+ 'action':'cancel'
+ })
+
+ self.account.connection.send(stanza)
diff --git a/src/common/dataforms.py b/src/common/dataforms.py
index 7113618ec..f1390bf05 100644
--- a/src/common/dataforms.py
+++ b/src/common/dataforms.py
@@ -78,9 +78,14 @@ class DataForm(xmpp.Node, object):
if tofill is not None:
self._mode = tofill.mode
- self.fields = tofill.fields
+ self.fields = (field for field in tofill.fields if field.type!='fixed')
self.records = tofill.records
self.type = 'submit'
+ for field in self.iter_fields():
+ field.required=False
+ del field.label
+ del field.options
+ del field.description
elif node is not None:
# if there is <reported/> element, the form contains multiple records
if self.getTag('reported') is not None:
@@ -138,7 +143,7 @@ class DataForm(xmpp.Node, object):
return self.getTagData('title')
def set_title(self, title):
- self.setTagData('title')
+ self.setTagData('title', title)
def del_title(self):
try:
@@ -283,11 +288,16 @@ class DataForm(xmpp.Node, object):
raise KeyError, "This form does not contain %r field." % var
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=None,var=None, value=None, label=None, desc=None,
+ required=None, options=None, node=None):
+
assert typ in ('boolean', 'fixed', 'hidden', 'jid-multi', 'jid-single', 'list-multi',
- 'list-single', 'text-multi', 'text-private', 'text-single', None)
+ 'list-single', 'text-multi', 'text-private', 'text-single',None)
xmpp.Node.__init__(self, 'field', node=node)
+ if typ is not None: self.type = typ
+ if var is not None: self.var = var
+ if label is not None: self.label = label
if desc is not None: self.description = desc
if required is not None: self.required = required
if value is not None: self.value = value
@@ -309,7 +319,10 @@ class DataField(xmpp.Node, object):
if typ!='text-single':
self.setAttr('type', typ)
else:
- self.delAttr('type')
+ try:
+ self.delAttr('type')
+ except KeyError:
+ pass
type = property(get_type, set_type, None,
""" Field type. One of: 'boolean', 'fixed', 'hidden', 'jid-multi', 'jid-single',
@@ -383,8 +396,8 @@ class DataField(xmpp.Node, object):
elif self.type in ('jid-multi', 'list-multi'):
return [value.getData() for value in self.getTags('value')]
-
- elif self.type in ('hidden', 'jid-single', 'list-single', 'text-single', 'text-private'):
+
+ elif self.type in ('hidden', 'jid-single', 'list-single', 'text-single', 'text-private') or True:
return self.getTagData('value')
def set_value(self, value):
@@ -399,8 +412,8 @@ class DataField(xmpp.Node, object):
elif self.type in ('jid-multi', 'list-multi'):
del_multiple_tag_value(self, 'value')
- for item in self.value:
- self.addChild('value', None, (item,))
+ for item in value:
+ self.addChild('value', {}, (item,))
elif self.type in ('hidden', 'jid-single', 'list-single', 'text-single', 'text-private'):
self.setTagData('value', value)
@@ -417,6 +430,7 @@ 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()
def get_options(self):
@@ -432,10 +446,10 @@ class DataField(xmpp.Node, object):
assert option[0] is None or isinstance(option[0], unicode)
assert isinstance(option[1], unicode)
if option[0] is None:
- attr=None
+ attr={}
else:
attr={'label': option[0].encode('utf-8')}
- self.addChild('option', attr, (option[1].encode('utf-8'),))
+ self.addChild('option', attr, (xmpp.Node('value', {}, (option[1].encode('utf-8'),)),))
def del_options(self):
del_multiple_tag_value(self, 'option')
diff --git a/src/dataforms.py b/src/dataforms.py
index 3ae4c43ee..4d82a5885 100644
--- a/src/dataforms.py
+++ b/src/dataforms.py
@@ -52,7 +52,7 @@ class DataFormWidget(gtk.Alignment, object):
else:
self.form = self.__class__.MultipleForm(dataform)
self.form.show()
- self.container.pack_end(self.form)
+ self.container.pack_end(self.form, expand=True, fill=True)
def get_data_form(self):
""" Data form displayed in the widget or None if no form. """
@@ -81,38 +81,38 @@ 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
+#? 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
@@ -164,8 +164,7 @@ class DataFormWidget(gtk.Alignment, object):
widget.set_line_wrap(True)
self.attach(widget, leftattach, rightattach, linecounter, linecounter+1)
- elif field.type in ('jid-multi', 'jid-single', 'list-multi', 'text-multi',
- 'text-private'):
+ elif field.type in ('jid-multi'):
widget = gtk.Label(field.type)
elif field.type == 'list-single':
@@ -176,7 +175,7 @@ class DataFormWidget(gtk.Alignment, object):
# TODO: We cannot deactivate them all...
widget = gtk.VBox()
first_radio = None
- for label, value in field.iter_options():
+ for value, label in field.iter_options():
radio = gtk.RadioButton(first_radio, label=label)
radio.connect('toggled', self.on_list_single_radiobutton_toggled,
field, value)
@@ -188,6 +187,41 @@ class DataFormWidget(gtk.Alignment, object):
radio.set_active(True)
widget.pack_start(radio, expand=False)
+ elif field.type == 'list-multi':
+ # TODO: When more than few choices, make a list
+ widget = gtk.VBox()
+ for value, label in field.iter_options():
+ check = gtk.CheckButton(label, use_underline=False)
+ check.set_active(value in field.value)
+ check.connect('toggled', self.on_list_multi_checkbutton_toggled,
+ field, value)
+ widget.pack_start(check, expand=False)
+
+ elif field.type == 'jid-single':
+ widget = gtk.Entry()
+ widget.connect('changed', self.on_text_single_entry_changed, field)
+ if field.value is None:
+ field.value = u''
+ widget.set_text(field.value)
+
+ elif field.type == 'text-private':
+ widget = gtk.Entry()
+ widget.connect('changed', self.on_text_single_entry_changed, field)
+ widget.set_visibility(False)
+ if field.value is None:
+ field.value = u''
+ widget.set_text(field.value)
+
+ 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,
+ field)
+ if field.value is None:
+ field.value = u''
+ widget.get_buffer().set_text(field.value)
+
else:# field.type == 'text-single' or field.type is nonstandard:
# JEP says that if we don't understand some type, we
# should handle it as text-single
@@ -199,7 +233,7 @@ class DataFormWidget(gtk.Alignment, object):
if commonlabel and field.label is not None:
label = gtk.Label(field.label)
- label.set_justify(gtk.JUSTIFY_RIGHT)
+ label.set_alignment(1.0, 0.5)
self.attach(label, 0, 1, linecounter, linecounter+1)
if commonwidget:
@@ -208,8 +242,10 @@ class DataFormWidget(gtk.Alignment, object):
widget.show_all()
if commondesc and field.description is not None:
- # TODO: with smaller font
- label = gtk.Label(field.description)
+ label = gtk.Label()
+ label.set_markup('<small>'+\
+ gtkgui_helpers.escape_for_pango_markup(field.description)+\
+ '</small>')
label.set_line_wrap(True)
self.attach(label, 2, 3, linecounter, linecounter+1)
@@ -227,9 +263,20 @@ class DataFormWidget(gtk.Alignment, object):
def on_list_single_radiobutton_toggled(self, widget, field, value):
field.value = value
+ def on_list_multi_checkbutton_toggled(self, widget, field, value):
+ if widget.get_active() and value not in field.value:
+ field.value.append(value)
+ elif not widget.get_active() and value in field.value:
+ field.value.remove(value)
+
def on_text_single_entry_changed(self, widget, field):
field.value = widget.get_text()
+ def on_text_multi_textbuffer_changed(self, widget, field):
+ field.value = widget.get_text(
+ widget.get_start_iter(),
+ widget.get_end_iter())
+
class MultipleForm(gtk.Alignment, object):
def __init__(self, dataform):
assert dataform.mode==dataforms.DATAFORM_MULTIPLE