dataforms.py and glade part for that - a Data Form widget

Introduced a widget that will present full data form as in JEP-0004, to make
things easier. Code will just have to create this widget with just-got
xmpp.DataForm form, show it to user, wait a bit and send the modified form
back.
This commit is contained in:
Tomasz Melcer 2006-06-19 21:33:54 +00:00
parent 8a959c846b
commit f1e9574401
2 changed files with 277 additions and 0 deletions

View File

@ -183,4 +183,93 @@
</child>
</widget>
<widget class="GtkWindow" id="data_form_fake_window">
<property name="visible">True</property>
<property name="title" translatable="yes">window1</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<child>
<widget class="GtkScrolledWindow" id="data_form_scrolledwindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_NEVER</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>
<widget class="GtkVBox" id="vbox111">
<property name="border_width">5</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">5</property>
<child>
<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="hseparator16">
<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>
<widget class="GtkVBox" id="form_vbox">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
</widget>
</glade-interface>

188
src/dataforms.py Normal file
View File

@ -0,0 +1,188 @@
## dataforms.py
##
## Copyright (C) 2003-2006 Yann Le Boulanger <asterix@lagaule.org>
## Copyright (C) 2005-2006 Nikos Kouremenos <nkour@jabber.org>
## Copyright (C) 2005 Dimitur Kirov <dkirov@gmail.com>
## Copyright (C) 2003-2005 Vincent Hanquez <tab@snarc.org>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation; version 2 only.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
""" This module contains widget that can display data form (JEP-0004). """
import gtk
class DataFormWidget(gtk.Alignment):
# "public" interface
""" Data Form widget. Use like any other widget. """
def __init__(self, dataformnode=None):
""" Create a widget. """
gtk.Alignment.__init__(self)
self.xml=gtkgui_helpers.get_glade('data_form_window.glade', 'data_form_scrolledwindow')
self.instructions = self.xml.get_widget('form_instructions_label')
self.form = self.xml.get_widget('form_vbox')
self.add(self.xml.get_widget('data_form_scrolledwindow')
self.set_data_form(dataform)
def set_data_form(self, dataform=None):
""" Set the data form (xmpp.DataForm) displayed in widget.
Set to None to erase the form. """
if self._data_form is not None: self._cleanWidgets()
self._data_form = dataform
if self._data_form is not None: self._buildWidgets()
def get_data_form(self):
""" Data form displayed in the widget or None if no form. """
return self._data_form
def get_title(self):
""" Get the title of data form, as a unicode object. If no
title or no form, returns u''. Useful for setting window title. """
if self._data_form is not None:
if self._data_form.has_key('title'):
return self._data_form['title'].encode('utf-8')
return u''
def show(self):
""" Treat 'us' as one widget. """
self.show_all()
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
def _buildWidgets(self):
""" Create all sub-widgets according to self._data_form and
JEP-0004. """
assert self._data_form is not None
assert length(self.form.get_children())==0
# it is *very* often used here
df = self._data_form
if df.has_key('instructions'):
self.instructions.set_text(df['instructions'])
i = -1
while df.has_key(i+1):
i += 1
if not df[i].has_key['type']:
continue
ctype = df[i]['type']
if ctype = 'hidden':
continue
hbox = gtk.HBox(spacing = 5)
label = gtk.Label('')
label.set_line_wrap(True)
label.set_alignment(0.0, 0.5)
label.set_property('width_request', 150)
hbox.pack_start(label, False)
if df[i].has_key('label'):
label.set_text(df[i]['label'])
if ctype == 'boolean':
desc = None
if df[i].has_key('desc'):
desc = df[i]['desc']
widget = gtk.CheckButton(desc, False)
activ = False
if df[i].has_key('values'):
activ = df[i]['values'][0]
widget.set_active(activ)
widget.connect('toggled', self.on_checkbutton_toggled, i)
elif ctype == 'fixed':
widget = gtk.Label('\n'.join(df[i]['values']))
widget.set_line_wrap(True)
widget.set_alignment(0.0, 0.5)
elif ctype == 'jid-multi':
#FIXME
widget = gtk.Label('')
elif ctype == 'jid-single':
#FIXME
widget = gtk.Label('')
elif ctype == 'list-multi':
j = 0
widget = gtk.Table(1, 1)
while df[i]['options'].has_key(j):
widget.resize(j + 1, 1)
child = gtk.CheckButton(df[i]['options'][j]['label'],
False)
if df[i]['options'][j]['values'][0] in \
df[i]['values']:
child.set_active(True)
child.connect('toggled', self.on_checkbutton_toggled2, i, j)
widget.attach(child, 0, 1, j, j+1)
j += 1
elif ctype == 'list-single':
widget = gtk.combo_box_new_text()
widget.connect('changed', self.on_combobox_changed, i)
index = 0
j = 0
while df[i]['options'].has_key(j):
if df[i]['options'][j]['values'][0] == \
df[i]['values'][0]:
index = j
widget.append_text(df[i]['options'][j]['label'])
j += 1
widget.set_active(index)
elif ctype == 'text-multi':
widget = gtk.TextView()
widget.set_size_request(100, -1)
widget.get_buffer().connect('changed', self.on_textbuffer_changed, \
i)
widget.get_buffer().set_text('\n'.join(df[i]['values']))
elif ctype == 'text-private':
widget = gtk.Entry()
widget.connect('changed', self.on_entry_changed, i)
if not df[i].has_key('values'):
df[i]['values'] = ['']
widget.set_text(df[i]['values'][0])
widget.set_visibility(False)
elif ctype == 'text-single':
widget = gtk.Entry()
widget.connect('changed', self.on_entry_changed, i)
if not df[i].has_key('values'):
df[i]['values'] = ['']
widget.set_text(df[i]['values'][0])
hbox.pack_start(widget, False)
hbox.pack_start(gtk.Label('')) # So that widhet doesn't take all space
self.form.pack_start(hbox, False)
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)
def on_checkbutton_toggled(self, widget, index):
self.config[index]['values'][0] = widget.get_active()
def on_checkbutton_toggled2(self, widget, index1, index2):
val = self._data_form[index1]['options'][index2]['values'][0]
if widget.get_active() and val not in self._data_form[index1]['values']:
self._data_form[index1]['values'].append(val)
elif not widget.get_active() and val in self._data_form[index1]['values']:
self._data_form[index1]['values'].remove(val)
def on_combobox_changed(self, widget, index):
self._data_form[index]['values'][0] = self.config[index]['options'][ \
widget.get_active()]['values'][0]
def on_entry_changed(self, widget, index):
self._data_form[index]['values'][0] = widget.get_text().decode('utf-8')
def on_textbuffer_changed(self, widget, index):
begin, end = widget.get_bounds()
self._data_form[index]['values'][0] = widget.get_text(begin, end)