Philipp Hörist pushed to branch master at gajim / gajim

Commits:

1 changed file:

Changes:

  • gajim/dataforms_widget.py deleted
    1
    -# Copyright (C) 2003-2014 Yann Leboulanger <asterix AT lagaule.org>
    
    2
    -# Copyright (C) 2006 Tomasz Melcer <liori AT exroot.org>
    
    3
    -# Copyright (C) 2006-2007 Jean-Marie Traissard <jim AT lapin.org>
    
    4
    -#
    
    5
    -# This file is part of Gajim.
    
    6
    -#
    
    7
    -# Gajim is free software; you can redistribute it and/or modify
    
    8
    -# it under the terms of the GNU General Public License as published
    
    9
    -# by the Free Software Foundation; version 3 only.
    
    10
    -#
    
    11
    -# Gajim is distributed in the hope that it will be useful,
    
    12
    -# but WITHOUT ANY WARRANTY; without even the implied warranty of
    
    13
    -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    
    14
    -# GNU General Public License for more details.
    
    15
    -#
    
    16
    -# You should have received a copy of the GNU General Public License
    
    17
    -# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
    
    18
    -
    
    19
    -''' This module contains widget that can display data form (XEP-0004).
    
    20
    -Words single and multiple refers here to types of data forms:
    
    21
    -single means these with one record of data (without <reported/> element),
    
    22
    -multiple - these which may contain more data (with <reported/> element).'''
    
    23
    -
    
    24
    -import itertools
    
    25
    -import base64
    
    26
    -
    
    27
    -from gi.repository import Gtk
    
    28
    -from gi.repository import Gdk
    
    29
    -from gi.repository import GdkPixbuf
    
    30
    -from gi.repository import GObject
    
    31
    -from gi.repository import GLib
    
    32
    -
    
    33
    -from nbxmpp.modules import dataforms
    
    34
    -
    
    35
    -from gajim import gtkgui_helpers
    
    36
    -from gajim.common import helpers
    
    37
    -from gajim.common import app
    
    38
    -from gajim.common.i18n import _
    
    39
    -
    
    40
    -from gajim.gtk.util import get_builder
    
    41
    -
    
    42
    -
    
    43
    -class DataFormWidget(Gtk.Alignment):
    
    44
    -# "public" interface
    
    45
    -    """
    
    46
    -    Data Form widget. Use like any other widget
    
    47
    -    """
    
    48
    -
    
    49
    -    __gsignals__ = dict(validated=(
    
    50
    -        GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION, None, ()))
    
    51
    -
    
    52
    -    def __init__(self, dataformnode=None):
    
    53
    -        ''' Create a widget. '''
    
    54
    -        GObject.GObject.__init__(self, xscale=1.0, yscale=1.0)
    
    55
    -
    
    56
    -        self._data_form = None
    
    57
    -        self.selectable = False
    
    58
    -        self.clean_cb = None
    
    59
    -
    
    60
    -        self.xml = get_builder('data_form_window.ui', ['data_form_vbox'])
    
    61
    -        self.xml.connect_signals(self)
    
    62
    -        for name in ('instructions_label', 'instructions_hseparator',
    
    63
    -                        'single_form_viewport', 'data_form_types_notebook',
    
    64
    -                        'single_form_scrolledwindow', 'multiple_form_hbox',
    
    65
    -                        'records_treeview', 'buttons_vbox', 'add_button', 'remove_button',
    
    66
    -                        'edit_button', 'up_button', 'down_button', 'clear_button'):
    
    67
    -            self.__dict__[name] = self.xml.get_object(name)
    
    68
    -
    
    69
    -        self.add(self.xml.get_object('data_form_vbox'))
    
    70
    -
    
    71
    -        if dataformnode is not None:
    
    72
    -            self.set_data_form(dataformnode)
    
    73
    -
    
    74
    -        selection = self.records_treeview.get_selection()
    
    75
    -        selection.connect('changed', self.on_records_selection_changed)
    
    76
    -        selection.set_mode(Gtk.SelectionMode.MULTIPLE)
    
    77
    -
    
    78
    -    def on_data_form_vbox_key_press_event(self, widget, event):
    
    79
    -        print('key pressed')
    
    80
    -
    
    81
    -    def set_data_form(self, dataform):
    
    82
    -        """
    
    83
    -        Set the data form (nbxmpp.DataForm) displayed in widget
    
    84
    -        """
    
    85
    -        assert isinstance(dataform, dataforms.DataForm)
    
    86
    -
    
    87
    -        self.del_data_form()
    
    88
    -        self._data_form = dataform
    
    89
    -        if isinstance(dataform, dataforms.SimpleDataForm):
    
    90
    -            self.build_single_data_form()
    
    91
    -        else:
    
    92
    -            self.build_multiple_data_form()
    
    93
    -
    
    94
    -        # create appropriate description for instructions field if there isn't any
    
    95
    -        if dataform.instructions == '':
    
    96
    -            self.instructions_label.set_no_show_all(True)
    
    97
    -            self.instructions_label.hide()
    
    98
    -        else:
    
    99
    -            self.instructions_label.set_text(dataform.instructions)
    
    100
    -            gtkgui_helpers.label_set_autowrap(self.instructions_label)
    
    101
    -
    
    102
    -    def get_data_form(self):
    
    103
    -        """
    
    104
    -        Data form displayed in the widget or None if no form
    
    105
    -        """
    
    106
    -        return self._data_form
    
    107
    -
    
    108
    -    def del_data_form(self):
    
    109
    -        self.clean_data_form()
    
    110
    -        self._data_form = None
    
    111
    -
    
    112
    -    data_form = property(get_data_form, set_data_form, del_data_form,
    
    113
    -            'Data form presented in a widget')
    
    114
    -
    
    115
    -    def get_title(self):
    
    116
    -        """
    
    117
    -        Get the title of data form. If no title or no form,
    
    118
    -        returns ''. Useful for setting window title
    
    119
    -        """
    
    120
    -        if self._data_form is not None:
    
    121
    -            if self._data_form.title is not None:
    
    122
    -                return self._data_form.title
    
    123
    -        return ''
    
    124
    -
    
    125
    -    title = property(get_title, None, None, 'Data form title')
    
    126
    -
    
    127
    -    def show(self):
    
    128
    -        ''' Treat 'us' as one widget. '''
    
    129
    -        self.show_all()
    
    130
    -
    
    131
    -# "private" methods
    
    132
    -
    
    133
    -# we have actually two different kinds of data forms: one is a simple form to fill,
    
    134
    -# second is a table with several records;
    
    135
    -
    
    136
    -    def empty_method(self):
    
    137
    -        pass
    
    138
    -
    
    139
    -    def clean_data_form(self):
    
    140
    -        """
    
    141
    -        Remove data about existing form. This metod is empty, because it is
    
    142
    -        rewritten by build_*_data_form, according to type of form which is
    
    143
    -        actually displayed
    
    144
    -        """
    
    145
    -        if self.clean_cb:
    
    146
    -            self.clean_cb()
    
    147
    -
    
    148
    -    def build_single_data_form(self):
    
    149
    -        '''Invoked when new single form is to be created.'''
    
    150
    -        assert isinstance(self._data_form, dataforms.SimpleDataForm)
    
    151
    -
    
    152
    -        self.clean_data_form()
    
    153
    -
    
    154
    -        self.singleform = SingleForm(self._data_form,
    
    155
    -            selectable=self.selectable)
    
    156
    -        def _on_validated(widget):
    
    157
    -            self.emit('validated')
    
    158
    -        self.singleform.connect('validated', _on_validated)
    
    159
    -        self.singleform.show()
    
    160
    -        self.single_form_viewport.add(self.singleform)
    
    161
    -        self.data_form_types_notebook.set_current_page(
    
    162
    -                self.data_form_types_notebook.page_num(
    
    163
    -                        self.single_form_scrolledwindow))
    
    164
    -
    
    165
    -        self.clean_cb = self.clean_single_data_form
    
    166
    -
    
    167
    -    def clean_single_data_form(self):
    
    168
    -        """
    
    169
    -        Called as clean_data_form, read the docs of clean_data_form(). Remove
    
    170
    -        form from widget
    
    171
    -        """
    
    172
    -        self.singleform.destroy()
    
    173
    -        self.clean_cb = None # we won't call it twice
    
    174
    -        del self.singleform
    
    175
    -
    
    176
    -    def build_multiple_data_form(self):
    
    177
    -        """
    
    178
    -        Invoked when new multiple form is to be created
    
    179
    -        """
    
    180
    -        assert isinstance(self._data_form, dataforms.MultipleDataForm)
    
    181
    -
    
    182
    -        self.clean_data_form()
    
    183
    -
    
    184
    -        # creating model for form...
    
    185
    -        fieldtypes = []
    
    186
    -        fieldvars = []
    
    187
    -        for field in self._data_form.reported.iter_fields():
    
    188
    -            # note: we store also text-private and hidden fields,
    
    189
    -            # we just do not display them.
    
    190
    -            # TODO: boolean fields
    
    191
    -            #elif field.type_=='boolean': fieldtypes.append(bool)
    
    192
    -            fieldtypes.append(str)
    
    193
    -            fieldvars.append(field.var)
    
    194
    -
    
    195
    -        self.multiplemodel = Gtk.ListStore(*fieldtypes)
    
    196
    -
    
    197
    -        # moving all data to model
    
    198
    -        for item in self._data_form.iter_records():
    
    199
    -            iter_ = self.multiplemodel.append()
    
    200
    -            for field in item.iter_fields():
    
    201
    -                if field.var in fieldvars:
    
    202
    -                    self.multiplemodel.set_value(iter_,
    
    203
    -                        fieldvars.index(field.var), field.value)
    
    204
    -
    
    205
    -        # constructing columns...
    
    206
    -        for field, counter in zip(self._data_form.reported.iter_fields(),
    
    207
    -        itertools.count()):
    
    208
    -            self.records_treeview.append_column(
    
    209
    -                    Gtk.TreeViewColumn(field.label, Gtk.CellRendererText(),
    
    210
    -                            text=counter))
    
    211
    -
    
    212
    -        self.records_treeview.set_model(self.multiplemodel)
    
    213
    -        self.records_treeview.show_all()
    
    214
    -
    
    215
    -        self.data_form_types_notebook.set_current_page(
    
    216
    -                self.data_form_types_notebook.page_num(
    
    217
    -                        self.multiple_form_hbox))
    
    218
    -
    
    219
    -        self.clean_cb = self.clean_multiple_data_form
    
    220
    -
    
    221
    -        readwrite = self._data_form.type_ != 'result'
    
    222
    -        if not readwrite:
    
    223
    -            self.buttons_vbox.set_no_show_all(True)
    
    224
    -            self.buttons_vbox.hide()
    
    225
    -        else:
    
    226
    -            self.buttons_vbox.set_no_show_all(False)
    
    227
    -            # refresh list look
    
    228
    -            self.refresh_multiple_buttons()
    
    229
    -
    
    230
    -    def clean_multiple_data_form(self):
    
    231
    -        """
    
    232
    -        Called as clean_data_form, read the docs of clean_data_form(). Remove
    
    233
    -        form from widget
    
    234
    -        """
    
    235
    -        self.clean_cb = None # we won't call it twice
    
    236
    -        del self.multiplemodel
    
    237
    -
    
    238
    -    def refresh_multiple_buttons(self):
    
    239
    -        """
    
    240
    -        Checks for treeview state and makes control buttons sensitive
    
    241
    -        """
    
    242
    -        selection = self.records_treeview.get_selection()
    
    243
    -        model = self.records_treeview.get_model()
    
    244
    -        count = selection.count_selected_rows()
    
    245
    -        if count == 0:
    
    246
    -            self.remove_button.set_sensitive(False)
    
    247
    -            self.edit_button.set_sensitive(False)
    
    248
    -            self.up_button.set_sensitive(False)
    
    249
    -            self.down_button.set_sensitive(False)
    
    250
    -        elif count == 1:
    
    251
    -            self.remove_button.set_sensitive(True)
    
    252
    -            self.edit_button.set_sensitive(True)
    
    253
    -            _, (path,) = selection.get_selected_rows()
    
    254
    -            iter_ = model.get_iter(path)
    
    255
    -            if model.iter_next(iter_) is None:
    
    256
    -                self.up_button.set_sensitive(True)
    
    257
    -                self.down_button.set_sensitive(False)
    
    258
    -            elif path == (0, ):
    
    259
    -                self.up_button.set_sensitive(False)
    
    260
    -                self.down_button.set_sensitive(True)
    
    261
    -            else:
    
    262
    -                self.up_button.set_sensitive(True)
    
    263
    -                self.down_button.set_sensitive(True)
    
    264
    -        else:
    
    265
    -            self.remove_button.set_sensitive(True)
    
    266
    -            self.edit_button.set_sensitive(True)
    
    267
    -            self.up_button.set_sensitive(False)
    
    268
    -            self.down_button.set_sensitive(False)
    
    269
    -
    
    270
    -        if not model:
    
    271
    -            self.clear_button.set_sensitive(False)
    
    272
    -        else:
    
    273
    -            self.clear_button.set_sensitive(True)
    
    274
    -
    
    275
    -    def on_clear_button_clicked(self, widget):
    
    276
    -        self.records_treeview.get_model().clear()
    
    277
    -
    
    278
    -    def on_remove_button_clicked(self, widget):
    
    279
    -        selection = self.records_treeview.get_selection()
    
    280
    -        model, rowrefs = selection.get_selected_rows()
    
    281
    -        # rowref is a list of paths
    
    282
    -        for index, _path in enumerate(rowrefs):
    
    283
    -            rowrefs[index] = Gtk.TreeRowReference.new(model, rowrefs[index])
    
    284
    -        # rowref is a list of row references; need to convert because we will
    
    285
    -        # modify the model, paths would change
    
    286
    -        for rowref in rowrefs:
    
    287
    -            del model[rowref.get_path()]
    
    288
    -
    
    289
    -    def on_up_button_clicked(self, widget):
    
    290
    -        selection = self.records_treeview.get_selection()
    
    291
    -        model, (path,) = selection.get_selected_rows()
    
    292
    -        iter_ = model.get_iter(path)
    
    293
    -        # constructing path for previous iter
    
    294
    -        previter = model.get_iter((path[0]-1,))
    
    295
    -        model.swap(iter_, previter)
    
    296
    -
    
    297
    -        self.refresh_multiple_buttons()
    
    298
    -
    
    299
    -    def on_down_button_clicked(self, widget):
    
    300
    -        selection = self.records_treeview.get_selection()
    
    301
    -        model, (path,) = selection.get_selected_rows()
    
    302
    -        iter_ = model.get_iter(path)
    
    303
    -        nextiter = model.iter_next(iter_)
    
    304
    -        model.swap(iter_, nextiter)
    
    305
    -
    
    306
    -        self.refresh_multiple_buttons()
    
    307
    -
    
    308
    -    def on_records_selection_changed(self, widget):
    
    309
    -        self.refresh_multiple_buttons()
    
    310
    -
    
    311
    -class SingleForm(Gtk.Table):
    
    312
    -    """
    
    313
    -    Widget that represent DATAFORM_SINGLE mode form. Because this is used not
    
    314
    -    only to display single forms, but to form input windows of multiple-type
    
    315
    -    forms, it is in another class
    
    316
    -    """
    
    317
    -
    
    318
    -    __gsignals__ = dict(validated=(
    
    319
    -        GObject.SignalFlags.RUN_LAST | GObject.SignalFlags.ACTION, None, ())
    
    320
    -    )
    
    321
    -
    
    322
    -    def __init__(self, dataform, selectable=False):
    
    323
    -        assert isinstance(dataform, dataforms.SimpleDataForm)
    
    324
    -
    
    325
    -        GObject.GObject.__init__(self)
    
    326
    -        self.set_col_spacings(12)
    
    327
    -        self.set_row_spacings(6)
    
    328
    -
    
    329
    -        def decorate_with_tooltip(widget, field):
    
    330
    -            """
    
    331
    -            Adds a tooltip containing field's description to a widget.  Creates
    
    332
    -            EventBox if widget doesn't have its own gdk window.  Returns decorated
    
    333
    -            widget
    
    334
    -            """
    
    335
    -            if field.description != '':
    
    336
    -                if not widget.get_window():
    
    337
    -                #if widget.flags() & Gtk.NO_WINDOW:
    
    338
    -                    evbox = Gtk.EventBox()
    
    339
    -                    evbox.add(widget)
    
    340
    -                    widget = evbox
    
    341
    -                widget.set_tooltip_text(field.description)
    
    342
    -            return widget
    
    343
    -
    
    344
    -        self._data_form = dataform
    
    345
    -
    
    346
    -        # building widget
    
    347
    -        linecounter = 0
    
    348
    -
    
    349
    -        # is the form changeable?
    
    350
    -        readwrite = dataform.type_ != 'result'
    
    351
    -
    
    352
    -        # for each field...
    
    353
    -        for field in self._data_form.iter_fields():
    
    354
    -            if field.type_ == 'hidden':
    
    355
    -                continue
    
    356
    -
    
    357
    -            commonlabel = True
    
    358
    -            commonlabelcenter = False
    
    359
    -            commonwidget = True
    
    360
    -            widget = None
    
    361
    -
    
    362
    -            if field.type_ == 'boolean':
    
    363
    -                commonlabelcenter = True
    
    364
    -                widget = Gtk.CheckButton()
    
    365
    -                widget.connect('toggled', self.on_boolean_checkbutton_toggled,
    
    366
    -                        field)
    
    367
    -                widget.set_active(field.value)
    
    368
    -
    
    369
    -            elif field.type_ == 'fixed':
    
    370
    -                leftattach = 1
    
    371
    -                rightattach = 2
    
    372
    -                if field.label is None:
    
    373
    -                    commonlabel = False
    
    374
    -                    leftattach = 0
    
    375
    -
    
    376
    -                commonwidget = False
    
    377
    -                widget = Gtk.Label(label=field.value)
    
    378
    -                widget.set_property('selectable', selectable)
    
    379
    -                widget.set_line_wrap(True)
    
    380
    -                self.attach(widget, leftattach, rightattach, linecounter,
    
    381
    -                    linecounter + 1, xoptions=Gtk.AttachOptions.FILL,
    
    382
    -                    yoptions=Gtk.AttachOptions.FILL)
    
    383
    -
    
    384
    -            elif field.type_ == 'list-single':
    
    385
    -                # TODO: What if we have radio buttons and non-required field?
    
    386
    -                # TODO: We cannot deactivate them all...
    
    387
    -                if len(field.options) < 6:
    
    388
    -                    # 5 option max: show radiobutton
    
    389
    -                    widget = Gtk.VBox()
    
    390
    -                    first_radio = None
    
    391
    -                    for value, label in field.iter_options():
    
    392
    -                        if not label:
    
    393
    -                            label = value
    
    394
    -                        radio = Gtk.RadioButton.new_with_label_from_widget(
    
    395
    -                            first_radio, label)
    
    396
    -                        radio.connect('toggled',
    
    397
    -                            self.on_list_single_radiobutton_toggled, field, value)
    
    398
    -                        if first_radio is None:
    
    399
    -                            first_radio = radio
    
    400
    -                            if field.value == '':   # TODO: is None when done
    
    401
    -                                field.value = value
    
    402
    -                        if value == field.value:
    
    403
    -                            radio.set_active(True)
    
    404
    -                        widget.pack_start(radio, False, True, 0)
    
    405
    -                else:
    
    406
    -                    # more than 5 options: show combobox
    
    407
    -                    def on_list_single_combobox_changed(combobox, f):
    
    408
    -                        iter_ = combobox.get_active_iter()
    
    409
    -                        if iter_:
    
    410
    -                            model = combobox.get_model()
    
    411
    -                            f.value = model[iter_][1]
    
    412
    -                        else:
    
    413
    -                            f.value = ''
    
    414
    -                    widget = gtkgui_helpers.create_combobox(field.options,
    
    415
    -                            field.value)
    
    416
    -                    widget.connect('changed', on_list_single_combobox_changed, field)
    
    417
    -                widget.set_sensitive(readwrite)
    
    418
    -
    
    419
    -            elif field.type_ == 'list-multi':
    
    420
    -                # TODO: When more than few choices, make a list
    
    421
    -                if len(field.options) < 6:
    
    422
    -                    # 5 option max: show checkbutton
    
    423
    -                    widget = Gtk.VBox()
    
    424
    -                    for value, label in field.iter_options():
    
    425
    -                        check = Gtk.CheckButton(label=label,
    
    426
    -                            use_underline=False)
    
    427
    -                        check.set_active(value in field.values)
    
    428
    -                        check.connect('toggled',
    
    429
    -                                self.on_list_multi_checkbutton_toggled, field, value)
    
    430
    -                        widget.pack_start(check, False, True, 0)
    
    431
    -                        widget.set_sensitive(readwrite)
    
    432
    -                else:
    
    433
    -                    # more than 5 options: show combobox
    
    434
    -                    def on_list_multi_treeview_changed(selection, field_):
    
    435
    -                        def for_selected(treemodel, _path, iter_):
    
    436
    -                            vals.append(treemodel[iter_][1])
    
    437
    -                        vals = []
    
    438
    -                        selection.selected_foreach(for_selected)
    
    439
    -                        field_.values = vals[:]
    
    440
    -                    widget = Gtk.ScrolledWindow()
    
    441
    -                    widget.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
    
    442
    -                    tv = gtkgui_helpers.create_list_multi(field.options,
    
    443
    -                            field.values)
    
    444
    -                    widget.add(tv)
    
    445
    -                    widget.set_size_request(-1, 120)
    
    446
    -                    tv.get_selection().connect('changed',
    
    447
    -                            on_list_multi_treeview_changed, field)
    
    448
    -                    tv.set_sensitive(readwrite)
    
    449
    -
    
    450
    -            elif field.type_ == 'jid-single':
    
    451
    -                widget = Gtk.Entry()
    
    452
    -                widget.connect('changed', self.on_text_single_entry_changed, field)
    
    453
    -                widget.set_text(field.value)
    
    454
    -
    
    455
    -            elif field.type_ == 'jid-multi':
    
    456
    -                commonwidget = False
    
    457
    -
    
    458
    -                xml = get_builder('data_form_window.ui', ['multiple_form_hbox'])
    
    459
    -                widget = xml.get_object('multiple_form_hbox')
    
    460
    -                treeview = xml.get_object('records_treeview')
    
    461
    -
    
    462
    -                listmodel = Gtk.ListStore(str)
    
    463
    -                for value in field.iter_values():
    
    464
    -                    # nobody will create several megabytes long stanza
    
    465
    -                    listmodel.insert(999999, (value,))
    
    466
    -
    
    467
    -                treeview.set_model(listmodel)
    
    468
    -
    
    469
    -                renderer = Gtk.CellRendererText()
    
    470
    -                renderer.set_property('editable', True)
    
    471
    -                renderer.connect('edited',
    
    472
    -                        self.on_jid_multi_cellrenderertext_edited, treeview, listmodel,
    
    473
    -                        field)
    
    474
    -
    
    475
    -                treeview.append_column(Gtk.TreeViewColumn(None, renderer,
    
    476
    -                        text=0))
    
    477
    -
    
    478
    -                decorate_with_tooltip(treeview, field)
    
    479
    -
    
    480
    -                add_button = xml.get_object('add_button')
    
    481
    -                add_button.connect('clicked',
    
    482
    -                        self.on_jid_multi_add_button_clicked, treeview, listmodel, field)
    
    483
    -                edit_button = xml.get_object('edit_button')
    
    484
    -                edit_button.connect('clicked',
    
    485
    -                        self.on_jid_multi_edit_button_clicked, treeview)
    
    486
    -                remove_button = xml.get_object('remove_button')
    
    487
    -                remove_button.connect('clicked',
    
    488
    -                        self.on_jid_multi_remove_button_clicked, treeview, field)
    
    489
    -                clear_button = xml.get_object('clear_button')
    
    490
    -                clear_button.connect('clicked',
    
    491
    -                        self.on_jid_multi_clean_button_clicked, listmodel, field)
    
    492
    -                if not readwrite:
    
    493
    -                    add_button.set_no_show_all(True)
    
    494
    -                    edit_button.set_no_show_all(True)
    
    495
    -                    remove_button.set_no_show_all(True)
    
    496
    -                    clear_button.set_no_show_all(True)
    
    497
    -
    
    498
    -                widget.set_sensitive(readwrite)
    
    499
    -                self.attach(widget, 1, 2, linecounter, linecounter+1)
    
    500
    -
    
    501
    -                del xml
    
    502
    -
    
    503
    -            elif field.type_ == 'text-private':
    
    504
    -                commonlabelcenter = True
    
    505
    -                widget = Gtk.Entry()
    
    506
    -                widget.connect('changed', self.on_text_single_entry_changed, field)
    
    507
    -                widget.set_visibility(False)
    
    508
    -                widget.set_text(field.value)
    
    509
    -
    
    510
    -            elif field.type_ == 'text-multi':
    
    511
    -                # TODO: bigger text view
    
    512
    -                commonwidget = False
    
    513
    -
    
    514
    -                textwidget = Gtk.TextView()
    
    515
    -                textwidget.set_wrap_mode(Gtk.WrapMode.WORD)
    
    516
    -                textwidget.get_buffer().connect('changed',
    
    517
    -                        self.on_text_multi_textbuffer_changed, field)
    
    518
    -                textwidget.get_buffer().set_text(field.value)
    
    519
    -                if readwrite:
    
    520
    -                    textwidget.set_sensitive(True)
    
    521
    -                else:
    
    522
    -                    if selectable:
    
    523
    -                        textwidget.set_editable(True)
    
    524
    -                    else:
    
    525
    -                        textwidget.set_sensitive(False)
    
    526
    -
    
    527
    -                widget = Gtk.ScrolledWindow()
    
    528
    -                widget.add(textwidget)
    
    529
    -
    
    530
    -                widget = decorate_with_tooltip(widget, field)
    
    531
    -                self.attach(widget, 1, 2, linecounter, linecounter+1)
    
    532
    -
    
    533
    -            else:
    
    534
    -                # field.type_ == 'text-single' or field.type_ is nonstandard:
    
    535
    -                # JEP says that if we don't understand some type, we
    
    536
    -                # should handle it as text-single
    
    537
    -                commonlabelcenter = True
    
    538
    -                if readwrite:
    
    539
    -                    widget = Gtk.Entry()
    
    540
    -                    def kpe(widget, event):
    
    541
    -                        if event.keyval == Gdk.KEY_Return or \
    
    542
    -                        event.keyval == Gdk.KEY_KP_Enter:
    
    543
    -                            self.emit('validated')
    
    544
    -                    widget.connect('key-press-event', kpe)
    
    545
    -                    widget.connect('changed', self.on_text_single_entry_changed,
    
    546
    -                            field)
    
    547
    -                    widget.set_sensitive(readwrite)
    
    548
    -                    if field.value is None:
    
    549
    -                        field.value = ''
    
    550
    -                    widget.set_text(field.value)
    
    551
    -                else:
    
    552
    -                    commonwidget = False
    
    553
    -                    widget = Gtk.Label(label=field.value)
    
    554
    -                    widget.set_property('selectable', selectable)
    
    555
    -                    widget.set_sensitive(True)
    
    556
    -                    widget.set_halign(Gtk.Align.START)
    
    557
    -                    widget.set_valign(Gtk.Align.CENTER)
    
    558
    -                    widget = decorate_with_tooltip(widget, field)
    
    559
    -                    self.attach(widget, 1, 2, linecounter, linecounter+1,
    
    560
    -                            yoptions=Gtk.AttachOptions.FILL)
    
    561
    -
    
    562
    -            if commonlabel and field.label is not None:
    
    563
    -                label = Gtk.Label(label=field.label)
    
    564
    -                if commonlabelcenter:
    
    565
    -                    label.set_halign(Gtk.Align.START)
    
    566
    -                    label.set_valign(Gtk.Align.CENTER)
    
    567
    -                else:
    
    568
    -                    label.set_halign(Gtk.Align.START)
    
    569
    -                    label.set_valign(Gtk.Align.START)
    
    570
    -                label = decorate_with_tooltip(label, field)
    
    571
    -                self.attach(label, 0, 1, linecounter, linecounter+1,
    
    572
    -                        xoptions=Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.FILL)
    
    573
    -
    
    574
    -            if field.media is not None:
    
    575
    -                for uri in field.media.uris:
    
    576
    -                    if uri.type_.startswith('image/'):
    
    577
    -                        try:
    
    578
    -                            img_data = base64.b64decode(uri.uri_data)
    
    579
    -                            pixbuf_l = GdkPixbuf.PixbufLoader()
    
    580
    -                            pixbuf_l.write(img_data)
    
    581
    -                            pixbuf_l.close()
    
    582
    -                            media = Gtk.Image.new_from_pixbuf(pixbuf_l.\
    
    583
    -                                get_pixbuf())
    
    584
    -                        except Exception:
    
    585
    -                            media = Gtk.Label(label=_('Unable to load image'))
    
    586
    -                    else:
    
    587
    -                        media = Gtk.Label(label=_('Media type not supported: %s') % \
    
    588
    -                            uri.type_)
    
    589
    -                    linecounter += 1
    
    590
    -                    self.attach(media, 0, 1, linecounter, linecounter+1,
    
    591
    -                        xoptions=Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.FILL)
    
    592
    -
    
    593
    -            if commonwidget:
    
    594
    -                assert widget is not None
    
    595
    -                widget.set_sensitive(readwrite)
    
    596
    -                widget = decorate_with_tooltip(widget, field)
    
    597
    -                self.attach(widget, 1, 2, linecounter, linecounter+1,
    
    598
    -                        yoptions=Gtk.AttachOptions.FILL)
    
    599
    -
    
    600
    -            if field.required:
    
    601
    -                label = Gtk.Label(label='*')
    
    602
    -                label.set_tooltip_text(_('This field is required'))
    
    603
    -                self.attach(label, 2, 3, linecounter, linecounter+1, xoptions=0,
    
    604
    -                    yoptions=0)
    
    605
    -
    
    606
    -            linecounter += 1
    
    607
    -        if self.get_property('visible'):
    
    608
    -            self.show_all()
    
    609
    -
    
    610
    -    def show(self):
    
    611
    -        # simulate that we are one widget
    
    612
    -        self.show_all()
    
    613
    -
    
    614
    -    def on_boolean_checkbutton_toggled(self, widget, field):
    
    615
    -        field.value = widget.get_active()
    
    616
    -
    
    617
    -    def on_list_single_radiobutton_toggled(self, widget, field, value):
    
    618
    -        field.value = value
    
    619
    -
    
    620
    -    def on_list_multi_checkbutton_toggled(self, widget, field, value):
    
    621
    -        # TODO: make some methods like add_value and remove_value
    
    622
    -        if widget.get_active() and value not in field.values:
    
    623
    -            field.values += [value]
    
    624
    -        elif not widget.get_active() and value in field.values:
    
    625
    -            field.values = [v for v in field.values if v != value]
    
    626
    -
    
    627
    -    def on_text_single_entry_changed(self, widget, field):
    
    628
    -        field.value = widget.get_text()
    
    629
    -
    
    630
    -    def on_text_multi_textbuffer_changed(self, widget, field):
    
    631
    -        field.value = widget.get_text(widget.get_start_iter(),
    
    632
    -            widget.get_end_iter(), True)
    
    633
    -
    
    634
    -    def on_jid_multi_cellrenderertext_edited(self, cell, path, newtext, treeview,
    
    635
    -    model, field):
    
    636
    -        old = model[path][0]
    
    637
    -        if old == newtext:
    
    638
    -            return
    
    639
    -        try:
    
    640
    -            newtext = helpers.parse_jid(newtext)
    
    641
    -        except helpers.InvalidFormat as s:
    
    642
    -            app.interface.raise_dialog('invalid-jid-with-error', str(s))
    
    643
    -            return
    
    644
    -        if newtext in field.values:
    
    645
    -            app.interface.raise_dialog('jid-in-list')
    
    646
    -            GLib.idle_add(treeview.set_cursor, path)
    
    647
    -            return
    
    648
    -        model[path][0] = newtext
    
    649
    -
    
    650
    -        values = field.values
    
    651
    -        values[values.index(old)] = newtext
    
    652
    -        field.values = values
    
    653
    -
    
    654
    -    def on_jid_multi_add_button_clicked(self, widget, treeview, model, field):
    
    655
    -        #Default jid
    
    656
    -        jid = _('new@jabber.id')
    
    657
    -        if jid in field.values:
    
    658
    -            i = 1
    
    659
    -            while _('new%d@jabber.id') % i in field.values:
    
    660
    -                i += 1
    
    661
    -            jid = _('new%d@jabber.id') % i
    
    662
    -        iter_ = model.insert(999999, (jid,))
    
    663
    -        treeview.set_cursor(model.get_path(iter_), treeview.get_column(0), True)
    
    664
    -        field.values = field.values + [jid]
    
    665
    -
    
    666
    -    def on_jid_multi_edit_button_clicked(self, widget, treeview):
    
    667
    -        model, iter_ = treeview.get_selection().get_selected()
    
    668
    -        assert iter_ is not None
    
    669
    -
    
    670
    -        treeview.set_cursor(model.get_path(iter_), treeview.get_column(0), True)
    
    671
    -
    
    672
    -    def on_jid_multi_remove_button_clicked(self, widget, treeview, field):
    
    673
    -        selection = treeview.get_selection()
    
    674
    -        deleted = []
    
    675
    -
    
    676
    -        def remove(model, path, iter_, deleted):
    
    677
    -            deleted += model[iter_]
    
    678
    -            model.remove(iter_)
    
    679
    -
    
    680
    -        selection.selected_foreach(remove, deleted)
    
    681
    -        field.values = (v for v in field.values if v not in deleted)
    
    682
    -
    
    683
    -    def on_jid_multi_clean_button_clicked(self, widget, model, field):
    
    684
    -        model.clear()
    
    685
    -        del field.values