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

Commits:

7 changed files:

Changes:

  • gajim/common/modules/adhoc_commands.py
    ... ... @@ -296,6 +296,13 @@ class LeaveGroupchatsCommand(AdHocCommand):
    296 296
     
    
    297 297
     
    
    298 298
     class AdHocCommands(BaseModule):
    
    299
    +
    
    300
    +    _nbxmpp_extends = 'AdHoc'
    
    301
    +    _nbxmpp_methods = [
    
    302
    +        'request_command_list',
    
    303
    +        'execute_command',
    
    304
    +    ]
    
    305
    +
    
    299 306
         def __init__(self, con):
    
    300 307
             BaseModule.__init__(self, con)
    
    301 308
     
    
    ... ... @@ -469,38 +476,6 @@ class AdHocCommands(BaseModule):
    469 476
     
    
    470 477
                 raise nbxmpp.NodeProcessed
    
    471 478
     
    
    472
    -    def request_command_list(self, jid):
    
    473
    -        """
    
    474
    -        Request the command list.
    
    475
    -        """
    
    476
    -        self._log.info('Request Command List: %s', jid)
    
    477
    -        query = nbxmpp.Iq(typ='get', to=jid, queryNS=nbxmpp.NS_DISCO_ITEMS)
    
    478
    -        query.setQuerynode(nbxmpp.NS_COMMANDS)
    
    479
    -
    
    480
    -        self._con.connection.SendAndCallForResponse(
    
    481
    -            query, self._command_list_received)
    
    482
    -
    
    483
    -    def _command_list_received(self, stanza):
    
    484
    -        if not nbxmpp.isResultNode(stanza):
    
    485
    -            self._log.info('Error: %s', stanza.getError())
    
    486
    -
    
    487
    -            app.nec.push_incoming_event(
    
    488
    -                AdHocCommandError(None, conn=self._con,
    
    489
    -                                  error=stanza.getError()))
    
    490
    -            return
    
    491
    -
    
    492
    -        items = stanza.getQueryPayload()
    
    493
    -        commandlist = []
    
    494
    -        if items:
    
    495
    -            commandlist = [
    
    496
    -                (t.getAttr('node'), t.getAttr('name')) for t in items
    
    497
    -            ]
    
    498
    -
    
    499
    -        self._log.info('Received: %s', commandlist)
    
    500
    -        app.nec.push_incoming_event(
    
    501
    -            AdHocCommandListReceived(
    
    502
    -                None, conn=self._con, commandlist=commandlist))
    
    503
    -
    
    504 479
         def send_command(self, jid, node, session_id,
    
    505 480
                          form, action='execute'):
    
    506 481
             """
    
    ... ... @@ -563,10 +538,6 @@ class AdHocCommandError(NetworkIncomingEvent):
    563 538
         name = 'adhoc-command-error'
    
    564 539
     
    
    565 540
     
    
    566
    -class AdHocCommandListReceived(NetworkIncomingEvent):
    
    567
    -    name = 'adhoc-command-list'
    
    568
    -
    
    569
    -
    
    570 541
     class AdHocCommandActionResponse(NetworkIncomingEvent):
    
    571 542
         name = 'adhoc-command-action-response'
    
    572 543
     
    

  • gajim/data/style/gajim.css
    ... ... @@ -244,10 +244,15 @@ button.flat.link { padding: 0; border: 0; }
    244 244
     /*Dataforms*/
    
    245 245
     .field-fixed { font-size: 16px; font-weight: bold; padding-top:5px;}
    
    246 246
     .data-form-title { font-size: 16px; font-weight: bold; }
    
    247
    -.data-form-widget grid { margin: 18px; }
    
    247
    +.data-form-widget grid { margin: 0px 18px 18px 18px; }
    
    248 248
     .data-form-widget treeview { padding: 5px; }
    
    249 249
     .data-form-widget scrolledwindow { border: 1px solid; border-color:@unfocused_borders; }
    
    250 250
     .data-form-widget textview { padding: 5px; }
    
    251 251
     
    
    252 252
     /*Image Preview*/
    
    253 253
     .preview-image { box-shadow: 0px 0px 3px 0px alpha(@theme_text_color, 0.2); }
    
    254
    +
    
    255
    +
    
    256
    +/* Treeview */
    
    257
    +.adhoc-treeview { padding: 5px; }
    
    258
    +.adhoc-scrolled { border: 1px solid; border-color:@unfocused_borders; }

  • gajim/groupchat_control.py
    ... ... @@ -79,7 +79,7 @@ from gajim.gtk.filechoosers import AvatarChooserDialog
    79 79
     from gajim.gtk.add_contact import AddNewContactWindow
    
    80 80
     from gajim.gtk.tooltips import GCTooltip
    
    81 81
     from gajim.gtk.groupchat_config import GroupchatConfig
    
    82
    -from gajim.gtk.adhoc_commands import CommandWindow
    
    82
    +from gajim.gtk.adhoc import AdHocCommand
    
    83 83
     from gajim.gtk.dataform import DataFormWidget
    
    84 84
     from gajim.gtk.util import NickCompletionGenerator
    
    85 85
     from gajim.gtk.util import get_icon_name
    
    ... ... @@ -735,7 +735,7 @@ class GroupchatControl(ChatControlBase):
    735 735
             """
    
    736 736
             Execute AdHoc commands on the current room
    
    737 737
             """
    
    738
    -        CommandWindow(self.account, self.room_jid)
    
    738
    +        AdHocCommand(self.account, self.room_jid)
    
    739 739
     
    
    740 740
         def _on_upload_avatar(self, action, param):
    
    741 741
             def _on_accept(filename):
    
    ... ... @@ -2815,7 +2815,7 @@ class GroupchatControl(ChatControlBase):
    2815 2815
     
    
    2816 2816
         def _on_execute_command_occupant(self, widget, nick):
    
    2817 2817
             jid = self.room_jid + '/' + nick
    
    2818
    -        CommandWindow(self.account, jid)
    
    2818
    +        AdHocCommand(self.account, jid)
    
    2819 2819
     
    
    2820 2820
         def on_row_activated(self, widget, path):
    
    2821 2821
             """
    

  • gajim/gtk/adhoc.py
    1
    +# Copyright (C) 2019 Philipp Hörist <philipp AT hoerist.com>
    
    2
    +#
    
    3
    +# This file is part of the OpenPGP Gajim Plugin.
    
    4
    +#
    
    5
    +# OpenPGP Gajim Plugin is free software; you can redistribute it and/or modify
    
    6
    +# it under the terms of the GNU General Public License as published
    
    7
    +# by the Free Software Foundation; version 3 only.
    
    8
    +#
    
    9
    +# OpenPGP Gajim Plugin is distributed in the hope that it will be useful,
    
    10
    +# but WITHOUT ANY WARRANTY; without even the implied warranty of
    
    11
    +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    
    12
    +# GNU General Public License for more details.
    
    13
    +#
    
    14
    +# You should have received a copy of the GNU General Public License
    
    15
    +# along with OpenPGP Gajim Plugin. If not, see <http://www.gnu.org/licenses/>.
    
    16
    +
    
    17
    +import logging
    
    18
    +from enum import IntEnum
    
    19
    +
    
    20
    +from gi.repository import Gtk
    
    21
    +from nbxmpp.util import is_error_result
    
    22
    +from nbxmpp.const import AdHocAction
    
    23
    +
    
    24
    +from gajim.common import app
    
    25
    +from gajim.common.i18n import _
    
    26
    +
    
    27
    +from gajim.common.modules import dataforms
    
    28
    +
    
    29
    +from gajim.gtk.dataform import DataFormWidget
    
    30
    +from gajim.gtk.util import ensure_not_destroyed
    
    31
    +from gajim.gtk.util import find_widget
    
    32
    +from gajim.gtk.util import MultiLineLabel
    
    33
    +
    
    34
    +log = logging.getLogger('gajim.gtk.adhoc')
    
    35
    +
    
    36
    +
    
    37
    +class Page(IntEnum):
    
    38
    +    REQUEST = 0
    
    39
    +    EXECUTE = 1
    
    40
    +    COMMANDS = 2
    
    41
    +    STAGE = 3
    
    42
    +    COMPLETED = 4
    
    43
    +    ERROR = 5
    
    44
    +
    
    45
    +
    
    46
    +class AdHocCommand(Gtk.Assistant):
    
    47
    +    def __init__(self, account, jid=None):
    
    48
    +        Gtk.Assistant.__init__(self)
    
    49
    +
    
    50
    +        self._con = app.connections[account]
    
    51
    +        self._account = account
    
    52
    +        self._destroyed = False
    
    53
    +
    
    54
    +        self.set_application(app.app)
    
    55
    +        self.set_resizable(True)
    
    56
    +        self.set_position(Gtk.WindowPosition.CENTER)
    
    57
    +
    
    58
    +        self.set_default_size(600, 400)
    
    59
    +        self.get_style_context().add_class('dialog-margin')
    
    60
    +
    
    61
    +        self._add_page(Request())
    
    62
    +        self._add_page(ExecuteCommand())
    
    63
    +        self._add_page(Commands())
    
    64
    +        self._add_page(Stage())
    
    65
    +        self._add_page(Completed())
    
    66
    +        self._add_page(Error())
    
    67
    +
    
    68
    +        self.connect('prepare', self._on_page_change)
    
    69
    +        self.connect('cancel', self._on_cancel)
    
    70
    +        self.connect('close', self._on_cancel)
    
    71
    +        self.connect('destroy', self._on_destroy)
    
    72
    +
    
    73
    +        self._remove_sidebar()
    
    74
    +
    
    75
    +        self._buttons = {}
    
    76
    +        self._add_custom_buttons()
    
    77
    +
    
    78
    +        self.show()
    
    79
    +        self._con.get_module('AdHocCommands').request_command_list(
    
    80
    +            jid, callback=self._received_command_list)
    
    81
    +
    
    82
    +    def _add_custom_buttons(self):
    
    83
    +        action_area = find_widget('action_area', self)
    
    84
    +        for button in list(action_area.get_children()):
    
    85
    +            self.remove_action_widget(button)
    
    86
    +
    
    87
    +        cancel = Gtk.Button(label=_('Cancel'))
    
    88
    +        cancel.connect('clicked', self._abort)
    
    89
    +        cancel.get_style_context().add_class('destructive-action')
    
    90
    +        self._buttons['cancel'] = cancel
    
    91
    +        self.add_action_widget(cancel)
    
    92
    +
    
    93
    +        complete = Gtk.Button(label=_('Finish'))
    
    94
    +        complete.action = AdHocAction.COMPLETE
    
    95
    +        complete.connect('clicked', self._execute_action)
    
    96
    +        self._buttons['complete'] = complete
    
    97
    +        self.add_action_widget(complete)
    
    98
    +
    
    99
    +        commands = Gtk.Button(label=_('Commands'))
    
    100
    +        commands.connect('clicked',
    
    101
    +                       lambda *args: self.set_current_page(Page.COMMANDS))
    
    102
    +        self._buttons['commands'] = commands
    
    103
    +        self.add_action_widget(commands)
    
    104
    +
    
    105
    +        next_ = Gtk.Button(label=_('Next'))
    
    106
    +        next_.action = AdHocAction.NEXT
    
    107
    +        next_.connect('clicked', self._execute_action)
    
    108
    +        self._buttons['next'] = next_
    
    109
    +        self.add_action_widget(next_)
    
    110
    +
    
    111
    +        prev = Gtk.Button(label=_('Previous'))
    
    112
    +        prev.action = AdHocAction.PREV
    
    113
    +        prev.connect('clicked', self._execute_action)
    
    114
    +        self._buttons['prev'] = prev
    
    115
    +        self.add_action_widget(prev)
    
    116
    +
    
    117
    +        execute = Gtk.Button(label=_('Execute'))
    
    118
    +        execute.action = AdHocAction.EXECUTE
    
    119
    +        execute.get_style_context().add_class('suggested-action')
    
    120
    +        execute.connect('clicked', self._execute_action)
    
    121
    +        self._buttons['execute'] = execute
    
    122
    +        self.add_action_widget(execute)
    
    123
    +
    
    124
    +    def _set_button_visibility(self, page):
    
    125
    +        for button in self._buttons.values():
    
    126
    +            button.hide()
    
    127
    +
    
    128
    +        if page == Page.COMMANDS:
    
    129
    +            self._buttons['execute'].show()
    
    130
    +
    
    131
    +        elif page == Page.STAGE:
    
    132
    +            self._buttons['cancel'].show()
    
    133
    +            stage_page = self.get_nth_page(page)
    
    134
    +            if not stage_page.actions:
    
    135
    +                self._buttons['complete'].show()
    
    136
    +            else:
    
    137
    +                for action in stage_page.actions:
    
    138
    +                    button = self._buttons.get(action.value)
    
    139
    +                    if button is not None:
    
    140
    +                        button.show()
    
    141
    +
    
    142
    +        elif page in (Page.ERROR, Page.COMPLETED):
    
    143
    +            self._buttons['commands'].show()
    
    144
    +
    
    145
    +    def _add_page(self, page):
    
    146
    +        self.append_page(page)
    
    147
    +        self.set_page_type(page, page.type_)
    
    148
    +        self.set_page_title(page, page.title)
    
    149
    +        self.set_page_complete(page, page.complete)
    
    150
    +
    
    151
    +    def execute_action(self):
    
    152
    +        self._execute_action(self._buttons['execute'])
    
    153
    +
    
    154
    +    def _execute_action(self, button):
    
    155
    +        action = button.action
    
    156
    +        current_page = self.get_current_page()
    
    157
    +        dataform = None
    
    158
    +        if action == AdHocAction.EXECUTE:
    
    159
    +            command = self.get_nth_page(current_page).get_selected_command()
    
    160
    +        else:
    
    161
    +            command, dataform = self.get_nth_page(current_page).stage_data
    
    162
    +            if action == AdHocAction.PREV:
    
    163
    +                dataform = None
    
    164
    +
    
    165
    +        self.set_current_page(Page.EXECUTE)
    
    166
    +        if current_page == Page.STAGE:
    
    167
    +            self.get_nth_page(current_page).clear()
    
    168
    +        self._con.get_module('AdHocCommands').execute_command(
    
    169
    +            command,
    
    170
    +            action=action,
    
    171
    +            dataform=dataform,
    
    172
    +            callback=self._received_stage)
    
    173
    +
    
    174
    +    def _abort(self, *args):
    
    175
    +        if self.get_current_page() == Page.STAGE:
    
    176
    +            command = self.get_nth_page(Page.STAGE).stage_data[0]
    
    177
    +            self._con.get_module('AdHocCommands').execute_command(
    
    178
    +                command, AdHocAction.CANCEL)
    
    179
    +            self.set_current_page(Page.COMMANDS)
    
    180
    +
    
    181
    +    @ensure_not_destroyed
    
    182
    +    def _received_command_list(self, commands):
    
    183
    +        if is_error_result(commands):
    
    184
    +            self.set_current_page(Page.ERROR)
    
    185
    +            return
    
    186
    +        self.get_nth_page(Page.COMMANDS).add_commands(commands)
    
    187
    +        self.set_current_page(Page.COMMANDS)
    
    188
    +
    
    189
    +    @ensure_not_destroyed
    
    190
    +    def _received_stage(self, stage):
    
    191
    +        if is_error_result(stage):
    
    192
    +            self.get_nth_page(Page.ERROR).set_text(str(stage))
    
    193
    +            self.set_current_page(Page.ERROR)
    
    194
    +            return
    
    195
    +
    
    196
    +        page = Page.STAGE
    
    197
    +        if stage.is_completed:
    
    198
    +            page = Page.COMPLETED
    
    199
    +
    
    200
    +        stage_page = self.get_nth_page(page)
    
    201
    +        stage_page.process_stage(stage)
    
    202
    +        self.set_current_page(page)
    
    203
    +
    
    204
    +    def set_stage_complete(self, is_valid):
    
    205
    +        self._buttons['next'].set_sensitive(is_valid)
    
    206
    +        self._buttons['complete'].set_sensitive(is_valid)
    
    207
    +
    
    208
    +    def _remove_sidebar(self):
    
    209
    +        main_box = self.get_children()[0]
    
    210
    +        sidebar = main_box.get_children()[0]
    
    211
    +        main_box.remove(sidebar)
    
    212
    +
    
    213
    +    def _on_page_change(self, _assistant, _page):
    
    214
    +        self._set_button_visibility(self.get_current_page())
    
    215
    +
    
    216
    +    def _on_error(self, error_text):
    
    217
    +        log.info('Show Error page')
    
    218
    +        page = self.get_nth_page(Page.ERROR)
    
    219
    +        page.set_text(error_text)
    
    220
    +        self.set_current_page(Page.ERROR)
    
    221
    +
    
    222
    +    def _on_cancel(self, _widget):
    
    223
    +        self.destroy()
    
    224
    +
    
    225
    +    def _on_destroy(self, *args):
    
    226
    +        self._destroyed = True
    
    227
    +
    
    228
    +
    
    229
    +class Request(Gtk.Box):
    
    230
    +
    
    231
    +    type_ = Gtk.AssistantPageType.CUSTOM
    
    232
    +    title = _('Request Command List')
    
    233
    +    complete = False
    
    234
    +
    
    235
    +    def __init__(self):
    
    236
    +        super().__init__(orientation=Gtk.Orientation.VERTICAL)
    
    237
    +        self.set_spacing(18)
    
    238
    +        spinner = Gtk.Spinner()
    
    239
    +        self.pack_start(spinner, True, True, 0)
    
    240
    +        spinner.start()
    
    241
    +        self.show_all()
    
    242
    +
    
    243
    +
    
    244
    +class ExecuteCommand(Request):
    
    245
    +
    
    246
    +    type_ = Gtk.AssistantPageType.CUSTOM
    
    247
    +    title = _('Executing…')
    
    248
    +    complete = False
    
    249
    +
    
    250
    +
    
    251
    +class Commands(Gtk.Box):
    
    252
    +
    
    253
    +    type_ = Gtk.AssistantPageType.CUSTOM
    
    254
    +    title = _('Command List')
    
    255
    +    complete = True
    
    256
    +
    
    257
    +    def __init__(self):
    
    258
    +        super().__init__(orientation=Gtk.Orientation.VERTICAL)
    
    259
    +        self.set_spacing(18)
    
    260
    +        self._commands = {}
    
    261
    +        self._scrolled = Gtk.ScrolledWindow()
    
    262
    +        self._scrolled.get_style_context().add_class('adhoc-scrolled')
    
    263
    +        self._scrolled.set_max_content_height(400)
    
    264
    +        self._scrolled.set_max_content_width(400)
    
    265
    +        self._scrolled.set_policy(Gtk.PolicyType.NEVER,
    
    266
    +                                  Gtk.PolicyType.AUTOMATIC)
    
    267
    +        self._treeview = Gtk.TreeView()
    
    268
    +        self._treeview.get_style_context().add_class('adhoc-treeview')
    
    269
    +        self._store = Gtk.ListStore(str, str)
    
    270
    +        self._treeview.set_model(self._store)
    
    271
    +        column = Gtk.TreeViewColumn(_('Commands'))
    
    272
    +        column.set_expand(True)
    
    273
    +        self._treeview.append_column(column)
    
    274
    +        renderer = Gtk.CellRendererText()
    
    275
    +        column.pack_start(renderer, True)
    
    276
    +        column.add_attribute(renderer, 'text', 0)
    
    277
    +
    
    278
    +        self._treeview.connect('row-activated', self._on_row_activate)
    
    279
    +        self._treeview.set_search_equal_func(self._search_func)
    
    280
    +
    
    281
    +        self._scrolled.add(self._treeview)
    
    282
    +        self.pack_start(self._scrolled, True, True, 0)
    
    283
    +        self.show_all()
    
    284
    +
    
    285
    +    def _search_func(self, model, column, search_text, iter_):
    
    286
    +        return search_text.lower() not in model[iter_][0].lower()
    
    287
    +
    
    288
    +    def _on_row_activate(self, tree_view, path, column):
    
    289
    +        self.get_toplevel().execute_action()
    
    290
    +
    
    291
    +    def add_commands(self, commands):
    
    292
    +        self._store.clear()
    
    293
    +        self._commands = {}
    
    294
    +        for command in commands:
    
    295
    +            key = '%s:%s' % (command.jid, command.node)
    
    296
    +            self._commands[key] = command
    
    297
    +            self._store.append((command.name, key))
    
    298
    +
    
    299
    +    def get_selected_command(self):
    
    300
    +        model, treeiter = self._treeview.get_selection().get_selected()
    
    301
    +        key = model[treeiter][1]
    
    302
    +        return self._commands[key]
    
    303
    +
    
    304
    +
    
    305
    +class Stage(Gtk.Box):
    
    306
    +
    
    307
    +    type_ = Gtk.AssistantPageType.CUSTOM
    
    308
    +    title = _('Settings')
    
    309
    +    complete = True
    
    310
    +
    
    311
    +    def __init__(self):
    
    312
    +        super().__init__(orientation=Gtk.Orientation.VERTICAL)
    
    313
    +        self.set_spacing(18)
    
    314
    +        self._dataform_widget = None
    
    315
    +        self._notes = []
    
    316
    +        self._last_stage_data = None
    
    317
    +        self.show_all()
    
    318
    +
    
    319
    +    @property
    
    320
    +    def stage_data(self):
    
    321
    +        return self._last_stage_data, self._dataform_widget.get_submit_form()
    
    322
    +
    
    323
    +    @property
    
    324
    +    def actions(self):
    
    325
    +        return self._last_stage_data.actions
    
    326
    +
    
    327
    +    def clear(self):
    
    328
    +        self._show_form(None)
    
    329
    +        self._show_notes(None)
    
    330
    +        self._last_stage_data = None
    
    331
    +
    
    332
    +    def process_stage(self, stage_data):
    
    333
    +        self._last_stage_data = stage_data
    
    334
    +        self._show_notes(stage_data.notes)
    
    335
    +        self._show_form(stage_data.data)
    
    336
    +
    
    337
    +    def _show_form(self, form):
    
    338
    +        if self._dataform_widget is not None:
    
    339
    +            self.remove(self._dataform_widget)
    
    340
    +            self._dataform_widget.destroy()
    
    341
    +        if form is None:
    
    342
    +            return
    
    343
    +        form = dataforms.extend_form(node=form)
    
    344
    +        self._dataform_widget = DataFormWidget(form)
    
    345
    +        self._dataform_widget.connect('is-valid', self._on_is_valid)
    
    346
    +        self._dataform_widget.validate()
    
    347
    +        self._dataform_widget.show_all()
    
    348
    +        self.add(self._dataform_widget)
    
    349
    +
    
    350
    +    def _show_notes(self, notes):
    
    351
    +        for note in self._notes:
    
    352
    +            self.remove(note)
    
    353
    +        self._notes = []
    
    354
    +
    
    355
    +        if notes is None:
    
    356
    +            return
    
    357
    +
    
    358
    +        for note in notes:
    
    359
    +            label = Gtk.Label(label=note.text)
    
    360
    +            label.show()
    
    361
    +            self._notes.append(label)
    
    362
    +            self.add(label)
    
    363
    +
    
    364
    +    def _on_is_valid(self, _widget, is_valid):
    
    365
    +        self.get_toplevel().set_stage_complete(is_valid)
    
    366
    +
    
    367
    +
    
    368
    +class Completed(Gtk.Box):
    
    369
    +
    
    370
    +    type_ = Gtk.AssistantPageType.CUSTOM
    
    371
    +    title = _('Finished')
    
    372
    +    complete = True
    
    373
    +
    
    374
    +    def __init__(self):
    
    375
    +        super().__init__(orientation=Gtk.Orientation.VERTICAL)
    
    376
    +        self.set_spacing(12)
    
    377
    +        self._notes = []
    
    378
    +        self._dataform_widget = None
    
    379
    +
    
    380
    +        icon = Gtk.Image.new_from_icon_name('object-select-symbolic',
    
    381
    +                                            Gtk.IconSize.DIALOG)
    
    382
    +        icon.get_style_context().add_class('success-color')
    
    383
    +        icon.show()
    
    384
    +
    
    385
    +        label = Gtk.Label(label='Finished')
    
    386
    +        label.show()
    
    387
    +
    
    388
    +        self._icon_text = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
    
    389
    +        self._icon_text.set_spacing(12)
    
    390
    +        self._icon_text.set_halign(Gtk.Align.CENTER)
    
    391
    +        self._icon_text.add(icon)
    
    392
    +        self._icon_text.add(label)
    
    393
    +        self.add(self._icon_text)
    
    394
    +
    
    395
    +        self.show_all()
    
    396
    +
    
    397
    +    def process_stage(self, stage_data):
    
    398
    +        self._show_notes(stage_data.notes)
    
    399
    +        self._show_form(stage_data.data)
    
    400
    +        self._show_icon_text(stage_data.data is None)
    
    401
    +
    
    402
    +    def _show_icon_text(self, show):
    
    403
    +        if show:
    
    404
    +            self.set_valign(Gtk.Align.CENTER)
    
    405
    +            self._icon_text.show_all()
    
    406
    +        else:
    
    407
    +            self.set_valign(Gtk.Align.FILL)
    
    408
    +            self._icon_text.hide()
    
    409
    +
    
    410
    +    def _show_form(self, form):
    
    411
    +        if self._dataform_widget is not None:
    
    412
    +            self.remove(self._dataform_widget)
    
    413
    +            self._dataform_widget.destroy()
    
    414
    +        if form is None:
    
    415
    +            return
    
    416
    +
    
    417
    +        form = dataforms.extend_form(node=form)
    
    418
    +
    
    419
    +        self._dataform_widget = DataFormWidget(
    
    420
    +            form, options={'read-only': True})
    
    421
    +        self._dataform_widget.show_all()
    
    422
    +        self.add(self._dataform_widget)
    
    423
    +
    
    424
    +    def _show_notes(self, notes):
    
    425
    +        for note in self._notes:
    
    426
    +            self.remove(note)
    
    427
    +        self._notes = []
    
    428
    +
    
    429
    +        for note in notes:
    
    430
    +            label = MultiLineLabel(label=note.text)
    
    431
    +            label.set_justify(Gtk.Justification.CENTER)
    
    432
    +            label.show()
    
    433
    +            self._notes.append(label)
    
    434
    +            self.add(label)
    
    435
    +
    
    436
    +
    
    437
    +class Error(Gtk.Box):
    
    438
    +
    
    439
    +    type_ = Gtk.AssistantPageType.CUSTOM
    
    440
    +    title = _('Execution failed')
    
    441
    +    complete = True
    
    442
    +
    
    443
    +    def __init__(self):
    
    444
    +        super().__init__(orientation=Gtk.Orientation.VERTICAL)
    
    445
    +        self.set_spacing(12)
    
    446
    +        self.set_homogeneous(True)
    
    447
    +
    
    448
    +        icon = Gtk.Image.new_from_icon_name('dialog-error-symbolic',
    
    449
    +                                            Gtk.IconSize.DIALOG)
    
    450
    +        icon.get_style_context().add_class('error-color')
    
    451
    +        icon.set_valign(Gtk.Align.END)
    
    452
    +        self._label = Gtk.Label()
    
    453
    +        self._label.get_style_context().add_class('bold16')
    
    454
    +        self._label.set_valign(Gtk.Align.START)
    
    455
    +
    
    456
    +        self.add(icon)
    
    457
    +        self.add(self._label)
    
    458
    +        self.show_all()
    
    459
    +
    
    460
    +    def set_text(self, text):
    
    461
    +        self._label.set_text(text)

  • gajim/gtk/adhoc_commands.py deleted
    1
    -# Copyright (C) 2006 Nikos Kouremenos <kourem AT gmail.com>
    
    2
    -# Copyright (C) 2006-2007 Tomasz Melcer <liori AT exroot.org>
    
    3
    -# Copyright (C) 2006-2014 Yann Leboulanger <asterix AT lagaule.org>
    
    4
    -# Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
    
    5
    -#                    Stephan Erb <steve-e AT h3c.de>
    
    6
    -#
    
    7
    -# This file is part of Gajim.
    
    8
    -#
    
    9
    -# Gajim is free software; you can redistribute it and/or modify
    
    10
    -# it under the terms of the GNU General Public License as published
    
    11
    -# by the Free Software Foundation; version 3 only.
    
    12
    -#
    
    13
    -# Gajim is distributed in the hope that it will be useful,
    
    14
    -# but WITHOUT ANY WARRANTY; without even the implied warranty of
    
    15
    -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    
    16
    -# GNU General Public License for more details.
    
    17
    -#
    
    18
    -# You should have received a copy of the GNU General Public License
    
    19
    -# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
    
    20
    -
    
    21
    -# FIXME: think if we need caching command list. it may be wrong if there will
    
    22
    -# be entities that often change the list, it may be slow to fetch it every time
    
    23
    -
    
    24
    -from gi.repository import Gtk
    
    25
    -import nbxmpp
    
    26
    -
    
    27
    -from gajim.common import app
    
    28
    -from gajim.common.i18n import _
    
    29
    -from gajim.common.modules import dataforms
    
    30
    -from gajim.common import ged
    
    31
    -
    
    32
    -from gajim import dataforms_widget
    
    33
    -
    
    34
    -from gajim.gtk.dialogs import HigDialog
    
    35
    -from gajim.gtk.util import get_builder
    
    36
    -
    
    37
    -
    
    38
    -class CommandWindow:
    
    39
    -    """
    
    40
    -    Class for a window for single ad-hoc commands session
    
    41
    -
    
    42
    -    Note, that there might be more than one for one account/jid pair in one
    
    43
    -    moment.
    
    44
    -
    
    45
    -    TODO: Maybe put this window into MessageWindow? consider this when it will
    
    46
    -    be possible to manage more than one window of one.
    
    47
    -    TODO: Account/jid pair in MessageWindowMgr.
    
    48
    -    TODO: GTK 2.10 has a special wizard-widget, consider using it...
    
    49
    -    """
    
    50
    -
    
    51
    -    def __init__(self, account, jid, commandnode=None):
    
    52
    -        """
    
    53
    -        Create new window
    
    54
    -        """
    
    55
    -
    
    56
    -        # an account object
    
    57
    -        self._con = app.connections[account]
    
    58
    -        self.jid = jid
    
    59
    -        self.commandnode = commandnode
    
    60
    -        self.data_form_widget = None
    
    61
    -        self.stage_finish_cb = None
    
    62
    -        self.stage_back_button_cb = None
    
    63
    -        self.stage_forward_button_cb = None
    
    64
    -        self.stage_execute_button_cb = None
    
    65
    -        self.stage_finish_button_cb = None
    
    66
    -        self.stage_close_button_cb = None
    
    67
    -        self.stage_restart_button_cb = None
    
    68
    -        self.stage_window_delete_cb = None
    
    69
    -
    
    70
    -        # retrieving widgets from xml
    
    71
    -        self.xml = get_builder('adhoc_commands_window.ui')
    
    72
    -        self.window = self.xml.get_object('adhoc_commands_window')
    
    73
    -        self.window.connect('delete-event',
    
    74
    -            self.on_adhoc_commands_window_delete_event)
    
    75
    -        for name in ('restart_button', 'back_button', 'forward_button',
    
    76
    -        'execute_button', 'finish_button', 'close_button', 'stages_notebook',
    
    77
    -        'retrieving_commands_stage_vbox', 'retrieving_commands_spinner',
    
    78
    -        'command_list_stage_vbox', 'command_treeview',
    
    79
    -        'sending_form_stage_vbox', 'sending_form_spinner',
    
    80
    -        'notes_label', 'no_commands_stage_vbox',
    
    81
    -        'error_stage_vbox', 'error_description_label'):
    
    82
    -            setattr(self, name, self.xml.get_object(name))
    
    83
    -
    
    84
    -        self.command_store = Gtk.ListStore(str, str)
    
    85
    -        self.command_treeview.set_model(self.command_store)
    
    86
    -        renderer = Gtk.CellRendererText()
    
    87
    -        column = Gtk.TreeViewColumn("Command", renderer, text=0)
    
    88
    -        self.command_treeview.append_column(column)
    
    89
    -
    
    90
    -        app.ged.register_event_handler(
    
    91
    -            'adhoc-command-error', ged.CORE, self._on_command_error)
    
    92
    -        app.ged.register_event_handler(
    
    93
    -            'adhoc-command-list', ged.CORE, self._on_command_list)
    
    94
    -        app.ged.register_event_handler('adhoc-command-action-response',
    
    95
    -                                       ged.CORE,
    
    96
    -                                       self._on_action_response)
    
    97
    -
    
    98
    -        self.initiate()
    
    99
    -
    
    100
    -    def initiate(self):
    
    101
    -
    
    102
    -        self.commandlist = None   # a list of (commandname, commanddescription)
    
    103
    -
    
    104
    -        # command's data
    
    105
    -        self.sessionid = None
    
    106
    -        self.dataform = None
    
    107
    -        self.allow_stage3_close = False
    
    108
    -
    
    109
    -        # creating data forms widget
    
    110
    -        if self.data_form_widget:
    
    111
    -            self.sending_form_stage_vbox.remove(self.data_form_widget)
    
    112
    -            self.data_form_widget.destroy()
    
    113
    -        self.data_form_widget = dataforms_widget.DataFormWidget()
    
    114
    -        self.data_form_widget.show()
    
    115
    -        self.sending_form_stage_vbox.pack_start(self.data_form_widget, True, True, 0)
    
    116
    -
    
    117
    -        if self.commandnode:
    
    118
    -            # Execute command
    
    119
    -            self.stage3()
    
    120
    -        else:
    
    121
    -            # setting initial stage
    
    122
    -            self.stage1()
    
    123
    -
    
    124
    -        # displaying the window
    
    125
    -        self.window.set_title(_('Ad-hoc Commands - Gajim'))
    
    126
    -        self.xml.connect_signals(self)
    
    127
    -        self.window.show_all()
    
    128
    -
    
    129
    -        self.restart_button.set_sensitive(False)
    
    130
    -
    
    131
    -    # These functions are set up by appropriate stageX methods.
    
    132
    -    def stage_finish(self, *anything):
    
    133
    -        if self.stage_finish_cb:
    
    134
    -            self.stage_finish_cb(*anything)
    
    135
    -
    
    136
    -    # Widget callbacks...
    
    137
    -    def on_back_button_clicked(self, *anything):
    
    138
    -        if self.stage_back_button_cb:
    
    139
    -            return self.stage_back_button_cb(*anything)
    
    140
    -        return False
    
    141
    -
    
    142
    -    def on_forward_button_clicked(self, *anything):
    
    143
    -        if self.stage_forward_button_cb:
    
    144
    -            return self.stage_forward_button_cb(*anything)
    
    145
    -        return False
    
    146
    -
    
    147
    -    def on_execute_button_clicked(self, *anything):
    
    148
    -        if self.stage_execute_button_cb:
    
    149
    -            return self.stage_execute_button_cb(*anything)
    
    150
    -        return False
    
    151
    -
    
    152
    -    def on_finish_button_clicked(self, *anything):
    
    153
    -        if self.stage_finish_button_cb:
    
    154
    -            return self.stage_finish_button_cb(*anything)
    
    155
    -        return False
    
    156
    -
    
    157
    -    def on_close_button_clicked(self, *anything):
    
    158
    -        if self.stage_close_button_cb:
    
    159
    -            return self.stage_close_button_cb(*anything)
    
    160
    -        return False
    
    161
    -
    
    162
    -    def on_restart_button_clicked(self, *anything):
    
    163
    -        if self.stage_restart_button_cb:
    
    164
    -            return self.stage_restart_button_cb(*anything)
    
    165
    -        return False
    
    166
    -
    
    167
    -    def on_adhoc_commands_window_destroy(self, *anything):
    
    168
    -        app.ged.remove_event_handler(
    
    169
    -            'adhoc-command-error', ged.CORE, self._on_command_error)
    
    170
    -        app.ged.remove_event_handler(
    
    171
    -            'adhoc-command-list', ged.CORE, self._on_command_list)
    
    172
    -        app.ged.remove_event_handler('adhoc-command-action-response',
    
    173
    -                                     ged.CORE,
    
    174
    -                                     self._on_action_response)
    
    175
    -
    
    176
    -    def on_adhoc_commands_window_delete_event(self, *anything):
    
    177
    -        if self.stage_window_delete_cb:
    
    178
    -            return self.stage_window_delete_cb(self.window)
    
    179
    -        return False
    
    180
    -
    
    181
    -    def __del__(self):
    
    182
    -        print('Object has been deleted.')
    
    183
    -
    
    184
    -# stage 1: waiting for command list
    
    185
    -    def stage1(self):
    
    186
    -        """
    
    187
    -        Prepare the first stage. Request command list, set appropriate state of
    
    188
    -        widgets
    
    189
    -        """
    
    190
    -        # close old stage...
    
    191
    -        self.stage_finish()
    
    192
    -
    
    193
    -        # show the stage
    
    194
    -        self.stages_notebook.set_current_page(
    
    195
    -                self.stages_notebook.page_num(
    
    196
    -                        self.retrieving_commands_stage_vbox))
    
    197
    -
    
    198
    -        # set widgets' state
    
    199
    -        self.close_button.set_sensitive(True)
    
    200
    -        self.back_button.set_sensitive(False)
    
    201
    -        self.forward_button.set_sensitive(False)
    
    202
    -        self.execute_button.set_sensitive(False)
    
    203
    -        self.finish_button.set_sensitive(False)
    
    204
    -
    
    205
    -        # request command list
    
    206
    -        self._con.get_module('AdHocCommands').request_command_list(self.jid)
    
    207
    -        self.retrieving_commands_spinner.start()
    
    208
    -
    
    209
    -        # setup the callbacks
    
    210
    -        self.stage_finish_cb = self.stage1_finish
    
    211
    -        self.stage_close_button_cb = self.stage1_close_button_clicked
    
    212
    -        self.stage_restart_button_cb = self.stage1_restart_button_clicked
    
    213
    -        self.stage_window_delete_cb = \
    
    214
    -            self.stage1_adhoc_commands_window_delete_event
    
    215
    -
    
    216
    -    def stage1_finish(self):
    
    217
    -        self.retrieving_commands_spinner.stop()
    
    218
    -
    
    219
    -    def stage1_close_button_clicked(self, widget):
    
    220
    -        # cancelling in this stage is not critical, so we don't
    
    221
    -        # show any popups to user
    
    222
    -        self.stage_finish()
    
    223
    -        self.window.destroy()
    
    224
    -
    
    225
    -    def stage1_restart_button_clicked(self, widget):
    
    226
    -        self.stage_finish()
    
    227
    -        self.restart()
    
    228
    -
    
    229
    -    def stage1_adhoc_commands_window_delete_event(self, widget):
    
    230
    -        self.stage1_finish()
    
    231
    -        return True
    
    232
    -
    
    233
    -# stage 2: choosing the command to execute
    
    234
    -    def stage2(self):
    
    235
    -        """
    
    236
    -        Populate the command list
    
    237
    -        """
    
    238
    -        # close old stage
    
    239
    -        self.stage_finish()
    
    240
    -
    
    241
    -        assert self.commandlist
    
    242
    -
    
    243
    -        self.stages_notebook.set_current_page(
    
    244
    -            self.stages_notebook.page_num(self.command_list_stage_vbox))
    
    245
    -
    
    246
    -        self.close_button.set_sensitive(True)
    
    247
    -        self.back_button.set_sensitive(False)
    
    248
    -        self.forward_button.set_sensitive(True)
    
    249
    -        self.execute_button.set_sensitive(False)
    
    250
    -        self.finish_button.set_sensitive(False)
    
    251
    -
    
    252
    -        # build the commands list
    
    253
    -        self.command_store.clear()
    
    254
    -        for (commandnode, commandname) in self.commandlist:
    
    255
    -            self.command_store.append([commandname, commandnode])
    
    256
    -        self.command_treeview.get_selection().select_iter(self.command_store.get_iter_first())
    
    257
    -
    
    258
    -        self.stage_finish_cb = self.stage2_finish
    
    259
    -        self.stage_close_button_cb = self.stage2_close_button_clicked
    
    260
    -        self.stage_restart_button_cb = self.stage2_restart_button_clicked
    
    261
    -        self.stage_forward_button_cb = self.stage2_forward_button_clicked
    
    262
    -        self.stage_window_delete_cb = None
    
    263
    -
    
    264
    -    def stage2_finish(self):
    
    265
    -        """
    
    266
    -        Save selected command to self.commandnode
    
    267
    -        """
    
    268
    -        model, treeiter = self.command_treeview.get_selection().get_selected()
    
    269
    -        self.commandnode = model[treeiter][1]
    
    270
    -
    
    271
    -    def stage2_close_button_clicked(self, widget):
    
    272
    -        self.stage_finish()
    
    273
    -        self.window.destroy()
    
    274
    -
    
    275
    -    def stage2_restart_button_clicked(self, widget):
    
    276
    -        self.stage_finish()
    
    277
    -        self.restart()
    
    278
    -
    
    279
    -    def stage2_forward_button_clicked(self, widget):
    
    280
    -        self.stage3()
    
    281
    -
    
    282
    -    def on_check_commands_1_button_clicked(self, widget):
    
    283
    -        self.stage1()
    
    284
    -
    
    285
    -# stage 3: command invocation
    
    286
    -    def stage3(self):
    
    287
    -        # close old stage
    
    288
    -        self.stage_finish()
    
    289
    -
    
    290
    -        self.form_status = None
    
    291
    -
    
    292
    -        self.stages_notebook.set_current_page(
    
    293
    -                self.stages_notebook.page_num(
    
    294
    -                        self.sending_form_stage_vbox))
    
    295
    -
    
    296
    -        self.restart_button.set_sensitive(True)
    
    297
    -        self.close_button.set_sensitive(True)
    
    298
    -        self.back_button.set_sensitive(False)
    
    299
    -        self.forward_button.set_sensitive(False)
    
    300
    -        self.execute_button.set_sensitive(False)
    
    301
    -        self.finish_button.set_sensitive(False)
    
    302
    -
    
    303
    -        self.stage3_submit_form()
    
    304
    -
    
    305
    -        self.stage_finish_cb = None
    
    306
    -        self.stage_back_button_cb = self.stage3_back_button_clicked
    
    307
    -        self.stage_forward_button_cb = self.stage3_forward_button_clicked
    
    308
    -        self.stage_execute_button_cb = self.stage3_execute_button_clicked
    
    309
    -        self.stage_finish_button_cb = self.stage3_finish_button_clicked
    
    310
    -        self.stage_close_button_cb = self.stage3_close_button_clicked
    
    311
    -        self.stage_restart_button_cb = self.stage3_restart_button_clicked
    
    312
    -        self.stage_window_delete_cb = self.stage3_close_button_clicked
    
    313
    -
    
    314
    -    def stage3_can_close(self, cb):
    
    315
    -        if self.form_status == 'completed':
    
    316
    -            cb()
    
    317
    -            return
    
    318
    -
    
    319
    -        def on_yes(button):
    
    320
    -            self._con.get_module('AdHocCommands').send_cancel(
    
    321
    -                self.jid, self.commandnode, self.sessionid)
    
    322
    -            dialog.destroy()
    
    323
    -            cb()
    
    324
    -
    
    325
    -        dialog = HigDialog(self.window, Gtk.MessageType.WARNING,
    
    326
    -            Gtk.ButtonsType.YES_NO, _('Cancel confirmation'),
    
    327
    -            _('You are in process of executing command. Do you really want to '
    
    328
    -            'cancel it?'), on_response_yes=on_yes)
    
    329
    -        dialog.popup()
    
    330
    -
    
    331
    -    def stage3_close_button_clicked(self, widget):
    
    332
    -        """
    
    333
    -        We are in the middle of executing command. Ask user if he really want to
    
    334
    -        cancel the process, then cancel it
    
    335
    -        """
    
    336
    -        # this works also as a handler for window_delete_event, so we have to
    
    337
    -        # return appropriate values
    
    338
    -        if self.allow_stage3_close:
    
    339
    -            return False
    
    340
    -
    
    341
    -        def on_ok():
    
    342
    -            self.allow_stage3_close = True
    
    343
    -            self.window.destroy()
    
    344
    -
    
    345
    -        self.stage3_can_close(on_ok)
    
    346
    -
    
    347
    -        return True # Block event, don't close window
    
    348
    -
    
    349
    -    def stage3_restart_button_clicked(self, widget):
    
    350
    -        def on_ok():
    
    351
    -            self.restart()
    
    352
    -
    
    353
    -        self.stage3_can_close(on_ok)
    
    354
    -
    
    355
    -    def stage3_back_button_clicked(self, widget):
    
    356
    -        self.stage3_submit_form('prev')
    
    357
    -
    
    358
    -    def stage3_forward_button_clicked(self, widget):
    
    359
    -        self.stage3_submit_form('next')
    
    360
    -
    
    361
    -    def stage3_execute_button_clicked(self, widget):
    
    362
    -        self.stage3_submit_form('execute')
    
    363
    -
    
    364
    -    def stage3_finish_button_clicked(self, widget):
    
    365
    -        self.stage3_submit_form('complete')
    
    366
    -
    
    367
    -    def stage3_submit_form(self, action='execute'):
    
    368
    -        self.data_form_widget.set_sensitive(False)
    
    369
    -
    
    370
    -        if self.data_form_widget.get_data_form():
    
    371
    -            df = self.data_form_widget.get_data_form()
    
    372
    -            if not df.is_valid():
    
    373
    -                app.interface.raise_dialog(
    
    374
    -                    'invalid-form', transient_for=self.window)
    
    375
    -                self.data_form_widget.set_sensitive(True)
    
    376
    -                return
    
    377
    -            self.data_form_widget.data_form.type_ = 'submit'
    
    378
    -        else:
    
    379
    -            self.data_form_widget.hide()
    
    380
    -
    
    381
    -        self.close_button.set_sensitive(True)
    
    382
    -        self.back_button.set_sensitive(False)
    
    383
    -        self.forward_button.set_sensitive(False)
    
    384
    -        self.execute_button.set_sensitive(False)
    
    385
    -        self.finish_button.set_sensitive(False)
    
    386
    -
    
    387
    -        self.sending_form_spinner.start()
    
    388
    -        self._con.get_module('AdHocCommands').send_command(
    
    389
    -            self.jid, self.commandnode, self.sessionid,
    
    390
    -            self.data_form_widget.data_form, action)
    
    391
    -
    
    392
    -    def stage3_next_form(self, command):
    
    393
    -        if not isinstance(command, nbxmpp.Node):
    
    394
    -            self.stage5(error=_('Service sent malformed data'), senderror=True)
    
    395
    -            return
    
    396
    -
    
    397
    -        self.sending_form_spinner.stop()
    
    398
    -
    
    399
    -        if not self.sessionid:
    
    400
    -            self.sessionid = command.getAttr('sessionid')
    
    401
    -        elif self.sessionid != command.getAttr('sessionid'):
    
    402
    -            self.stage5(error=_('Service changed the session identifier.'),
    
    403
    -                    senderror=True)
    
    404
    -            return
    
    405
    -
    
    406
    -        self.form_status = command.getAttr('status')
    
    407
    -
    
    408
    -        self.commandnode = command.getAttr('node')
    
    409
    -        if command.getTag('x'):
    
    410
    -            self.dataform = dataforms.extend_form(node=command.getTag('x'))
    
    411
    -
    
    412
    -            self.data_form_widget.set_sensitive(True)
    
    413
    -            try:
    
    414
    -                self.data_form_widget.selectable = True
    
    415
    -                self.data_form_widget.data_form = self.dataform
    
    416
    -            except dataforms.Error:
    
    417
    -                self.stage5(error=_('Service sent malformed data'),
    
    418
    -                    senderror=True)
    
    419
    -                return
    
    420
    -            self.data_form_widget.show()
    
    421
    -            if self.data_form_widget.title:
    
    422
    -                self.window.set_title(_('%s - Ad-hoc Commands - Gajim') % \
    
    423
    -                        self.data_form_widget.title)
    
    424
    -        else:
    
    425
    -            self.data_form_widget.hide()
    
    426
    -
    
    427
    -        actions = command.getTag('actions')
    
    428
    -        if actions:
    
    429
    -            # actions, actions, actions...
    
    430
    -            self.close_button.set_sensitive(True)
    
    431
    -            self.back_button.set_sensitive(actions.getTag('prev') is not None)
    
    432
    -            self.forward_button.set_sensitive(
    
    433
    -                actions.getTag('next') is not None)
    
    434
    -            self.execute_button.set_sensitive(True)
    
    435
    -            self.finish_button.set_sensitive(actions.getTag('complete') is not \
    
    436
    -                None)
    
    437
    -        else:
    
    438
    -            self.close_button.set_sensitive(True)
    
    439
    -            self.back_button.set_sensitive(False)
    
    440
    -            self.forward_button.set_sensitive(False)
    
    441
    -            self.execute_button.set_sensitive(True)
    
    442
    -            self.finish_button.set_sensitive(False)
    
    443
    -
    
    444
    -        if self.form_status == 'completed':
    
    445
    -            self.close_button.set_sensitive(True)
    
    446
    -            self.back_button.hide()
    
    447
    -            self.forward_button.hide()
    
    448
    -            self.execute_button.hide()
    
    449
    -            self.finish_button.hide()
    
    450
    -            self.close_button.show()
    
    451
    -            self.stage_window_delete_cb = self.stage3_close_button_clicked
    
    452
    -
    
    453
    -        note = command.getTag('note')
    
    454
    -        if note:
    
    455
    -            self.notes_label.set_text(note.getData())
    
    456
    -            self.notes_label.set_no_show_all(False)
    
    457
    -            self.notes_label.show()
    
    458
    -        else:
    
    459
    -            self.notes_label.set_no_show_all(True)
    
    460
    -            self.notes_label.hide()
    
    461
    -
    
    462
    -    def restart(self):
    
    463
    -        self.commandnode = None
    
    464
    -        self.initiate()
    
    465
    -
    
    466
    -# stage 4: no commands are exposed
    
    467
    -    def stage4(self):
    
    468
    -        """
    
    469
    -        Display the message. Wait for user to close the window
    
    470
    -        """
    
    471
    -        # close old stage
    
    472
    -        self.stage_finish()
    
    473
    -
    
    474
    -        self.stages_notebook.set_current_page(
    
    475
    -            self.stages_notebook.page_num(self.no_commands_stage_vbox))
    
    476
    -
    
    477
    -        self.close_button.set_sensitive(True)
    
    478
    -        self.back_button.set_sensitive(False)
    
    479
    -        self.forward_button.set_sensitive(False)
    
    480
    -        self.execute_button.set_sensitive(False)
    
    481
    -        self.finish_button.set_sensitive(False)
    
    482
    -
    
    483
    -        self.stage_finish_cb = None
    
    484
    -        self.stage_close_button_cb = self.stage4_close_button_clicked
    
    485
    -        self.stage_restart_button_cb = self.stage4_restart_button_clicked
    
    486
    -        self.stage_window_delete_cb = None
    
    487
    -
    
    488
    -    def stage4_close_button_clicked(self, widget):
    
    489
    -        self.window.destroy()
    
    490
    -
    
    491
    -    def stage4_restart_button_clicked(self, widget):
    
    492
    -        self.restart()
    
    493
    -
    
    494
    -    def on_check_commands_2_button_clicked(self, widget):
    
    495
    -        self.stage1()
    
    496
    -
    
    497
    -# stage 5: an error has occurred
    
    498
    -    def stage5(self, error=None, errorid=None, senderror=False):
    
    499
    -        """
    
    500
    -        Display the error message. Wait for user to close the window
    
    501
    -        """
    
    502
    -        # FIXME: sending error to responder
    
    503
    -        # close old stage
    
    504
    -        self.stage_finish()
    
    505
    -
    
    506
    -        assert errorid or error
    
    507
    -
    
    508
    -        if errorid:
    
    509
    -            # we've got error code, display appropriate message
    
    510
    -            try:
    
    511
    -                errorname = nbxmpp.NS_STANZAS + ' ' + str(errorid)
    
    512
    -                errordesc = nbxmpp.ERRORS[errorname][2]
    
    513
    -                error = errordesc
    
    514
    -                del errorname, errordesc
    
    515
    -            except KeyError:        # when stanza doesn't have error description
    
    516
    -                error = _('Service returned an error.')
    
    517
    -        elif error:
    
    518
    -            # we've got error message
    
    519
    -            pass
    
    520
    -        else:
    
    521
    -            # we don't know what's that, bailing out
    
    522
    -            assert False
    
    523
    -
    
    524
    -        self.stages_notebook.set_current_page(
    
    525
    -            self.stages_notebook.page_num(self.error_stage_vbox))
    
    526
    -
    
    527
    -        self.close_button.set_sensitive(True)
    
    528
    -        self.back_button.hide()
    
    529
    -        self.forward_button.hide()
    
    530
    -        self.execute_button.hide()
    
    531
    -        self.finish_button.hide()
    
    532
    -
    
    533
    -        self.error_description_label.set_text(error)
    
    534
    -
    
    535
    -        self.stage_finish_cb = None
    
    536
    -        self.stage_close_button_cb = self.stage5_close_button_clicked
    
    537
    -        self.stage_restart_button_cb = self.stage5_restart_button_clicked
    
    538
    -        self.stage_window_delete_cb = None
    
    539
    -
    
    540
    -    def stage5_close_button_clicked(self, widget):
    
    541
    -        self.window.destroy()
    
    542
    -
    
    543
    -    def stage5_restart_button_clicked(self, widget):
    
    544
    -        self.restart()
    
    545
    -
    
    546
    -    def _on_command_error(self, obj):
    
    547
    -        self.stage5(errorid=obj.error)
    
    548
    -
    
    549
    -    def _on_command_list(self, obj):
    
    550
    -        self.commandlist = obj.commandlist
    
    551
    -        if not self.commandlist:
    
    552
    -            self.stage4()
    
    553
    -        else:
    
    554
    -            self.stage2()
    
    555
    -
    
    556
    -    def _on_action_response(self, obj):
    
    557
    -        self.stage3_next_form(obj.command)

  • gajim/gtk/discovery.py
    ... ... @@ -59,7 +59,7 @@ from gajim.gtk.dialogs import ErrorDialog
    59 59
     from gajim.gtk.dialogs import InformationDialog
    
    60 60
     from gajim.gtk.service_registration import ServiceRegistration
    
    61 61
     from gajim.gtk.discovery_search import SearchWindow
    
    62
    -from gajim.gtk.adhoc_commands import CommandWindow
    
    62
    +from gajim.gtk.adhoc import AdHocCommand
    
    63 63
     from gajim.gtk.util import icon_exists
    
    64 64
     from gajim.gtk.util import get_builder
    
    65 65
     
    
    ... ... @@ -1311,7 +1311,7 @@ class ToplevelAgentBrowser(AgentBrowser):
    1311 1311
                 return
    
    1312 1312
             service = model[iter_][0]
    
    1313 1313
             node = model[iter_][1]
    
    1314
    -        CommandWindow(self.account, service, commandnode=node)
    
    1314
    +        AdHocCommand(self.account, service)
    
    1315 1315
     
    
    1316 1316
         def on_register_button_clicked(self, widget=None):
    
    1317 1317
             """
    

  • gajim/roster_window.py
    ... ... @@ -84,7 +84,7 @@ from gajim.gtk.service_registration import ServiceRegistration
    84 84
     from gajim.gtk.discovery import ServiceDiscoveryWindow
    
    85 85
     from gajim.gtk.accounts import AccountsWindow
    
    86 86
     from gajim.gtk.tooltips import RosterTooltip
    
    87
    -from gajim.gtk.adhoc_commands import CommandWindow
    
    87
    +from gajim.gtk.adhoc import AdHocCommand
    
    88 88
     from gajim.gtk.subscription_request import SubscriptionRequestWindow
    
    89 89
     from gajim.gtk.util import get_icon_name
    
    90 90
     from gajim.gtk.util import resize_window
    
    ... ... @@ -3635,7 +3635,7 @@ class RosterWindow:
    3635 3635
             jid = contact.jid
    
    3636 3636
             if resource is not None:
    
    3637 3637
                 jid = jid + '/' + resource
    
    3638
    -        CommandWindow(account, jid)
    
    3638
    +        AdHocCommand(account, jid)
    
    3639 3639
     
    
    3640 3640
         def on_roster_window_focus_in_event(self, widget, event):
    
    3641 3641
             # roster received focus, so if we had urgency REMOVE IT