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

Commits:

8 changed files:

Changes:

  • gajim/application.py
    ... ... @@ -39,6 +39,8 @@ from pathlib import Path
    39 39
     from urllib.parse import unquote
    
    40 40
     
    
    41 41
     import nbxmpp
    
    42
    +from nbxmpp import JID
    
    43
    +from nbxmpp.protocol import InvalidJid
    
    42 44
     from gi.repository import Gio
    
    43 45
     from gi.repository import GLib
    
    44 46
     from gi.repository import Gtk
    
    ... ... @@ -236,6 +238,10 @@ class GajimApplication(Gtk.Application):
    236 238
                                            self._on_feature_discovered)
    
    237 239
     
    
    238 240
         def _open_uris(self, uris):
    
    241
    +        accounts = list(app.connections.keys())
    
    242
    +        if not accounts:
    
    243
    +            return
    
    244
    +
    
    239 245
             for uri in uris:
    
    240 246
                 app.log('uri_handler').info('open %s', uri)
    
    241 247
                 if not uri.startswith('xmpp:'):
    
    ... ... @@ -247,10 +253,30 @@ class GajimApplication(Gtk.Application):
    247 253
                 except ValueError:
    
    248 254
                     # No query argument
    
    249 255
                     jid, cmd = uri, 'message'
    
    256
    +
    
    257
    +            try:
    
    258
    +                jid = JID(jid)
    
    259
    +            except InvalidJid as error:
    
    260
    +                app.log('uri_handler').warning('Invalid JID %s: %s', uri, error)
    
    261
    +                continue
    
    262
    +
    
    263
    +            if cmd == 'join' and jid.getResource():
    
    264
    +                app.log('uri_handler').warning('Invalid MUC JID %s', uri)
    
    265
    +                continue
    
    266
    +
    
    267
    +            jid = str(jid)
    
    268
    +
    
    250 269
                 if cmd == 'join':
    
    251
    -                self.interface.join_gc_minimal(None, jid)
    
    270
    +                if len(accounts) == 1:
    
    271
    +                    self.activate_action(
    
    272
    +                        'groupchat-join',
    
    273
    +                        GLib.Variant('as', [accounts[0], jid]))
    
    274
    +                else:
    
    275
    +                    self.activate_action('start-chat', GLib.Variant('s', jid))
    
    276
    +
    
    252 277
                 elif cmd == 'roster':
    
    253 278
                     self.activate_action('add-contact', GLib.Variant('s', jid))
    
    279
    +
    
    254 280
                 elif cmd.startswith('message'):
    
    255 281
                     attributes = cmd.split(';')
    
    256 282
                     message = None
    
    ... ... @@ -261,15 +287,11 @@ class GajimApplication(Gtk.Application):
    261 287
                             message = unquote(key.split('=')[1])
    
    262 288
                         except Exception:
    
    263 289
                             app.log('uri_handler').error('Invalid URI: %s', cmd)
    
    264
    -                accounts = list(app.connections.keys())
    
    265
    -                if not accounts:
    
    266
    -                    continue
    
    290
    +
    
    267 291
                     if len(accounts) == 1:
    
    268 292
                         app.interface.new_chat_from_jid(accounts[0], jid, message)
    
    269 293
                     else:
    
    270
    -                    self.activate_action('start-chat', GLib.Variant('s', ''))
    
    271
    -                    start_chat = app.get_app_window('StartChatDialog')
    
    272
    -                    start_chat.set_search_text(jid)
    
    294
    +                    self.activate_action('start-chat', GLib.Variant('s', jid))
    
    273 295
     
    
    274 296
         def do_shutdown(self, *args):
    
    275 297
             Gtk.Application.do_shutdown(self)
    

  • gajim/data/gui/start_chat_dialog.ui
    ... ... @@ -2,57 +2,6 @@
    2 2
     <!-- Generated with glade 3.22.1 -->
    
    3 3
     <interface>
    
    4 4
       <requires lib="gtk+" version="3.20"/>
    
    5
    -  <object class="GtkBox" id="box">
    
    6
    -    <property name="visible">True</property>
    
    7
    -    <property name="can_focus">False</property>
    
    8
    -    <property name="border_width">18</property>
    
    9
    -    <property name="orientation">vertical</property>
    
    10
    -    <property name="spacing">6</property>
    
    11
    -    <child>
    
    12
    -      <object class="GtkSearchEntry" id="search_entry">
    
    13
    -        <property name="visible">True</property>
    
    14
    -        <property name="can_focus">True</property>
    
    15
    -        <property name="has_focus">True</property>
    
    16
    -        <property name="is_focus">True</property>
    
    17
    -        <property name="primary_icon_name">edit-find-symbolic</property>
    
    18
    -        <property name="primary_icon_activatable">False</property>
    
    19
    -        <property name="primary_icon_sensitive">False</property>
    
    20
    -      </object>
    
    21
    -      <packing>
    
    22
    -        <property name="expand">False</property>
    
    23
    -        <property name="fill">True</property>
    
    24
    -        <property name="position">0</property>
    
    25
    -      </packing>
    
    26
    -    </child>
    
    27
    -    <child>
    
    28
    -      <object class="GtkScrolledWindow" id="scrolledwindow">
    
    29
    -        <property name="visible">True</property>
    
    30
    -        <property name="can_focus">True</property>
    
    31
    -        <property name="hscrollbar_policy">never</property>
    
    32
    -        <property name="shadow_type">in</property>
    
    33
    -        <child>
    
    34
    -          <object class="GtkViewport">
    
    35
    -            <property name="visible">True</property>
    
    36
    -            <property name="can_focus">False</property>
    
    37
    -            <child>
    
    38
    -              <object class="GtkListBox" id="listbox">
    
    39
    -                <property name="name">StartChatListBox</property>
    
    40
    -                <property name="visible">True</property>
    
    41
    -                <property name="can_focus">False</property>
    
    42
    -                <property name="selection_mode">browse</property>
    
    43
    -                <property name="activate_on_single_click">False</property>
    
    44
    -              </object>
    
    45
    -            </child>
    
    46
    -          </object>
    
    47
    -        </child>
    
    48
    -      </object>
    
    49
    -      <packing>
    
    50
    -        <property name="expand">True</property>
    
    51
    -        <property name="fill">True</property>
    
    52
    -        <property name="position">1</property>
    
    53
    -      </packing>
    
    54
    -    </child>
    
    55
    -  </object>
    
    56 5
       <object class="GtkGrid" id="search_result_grid">
    
    57 6
         <property name="visible">True</property>
    
    58 7
         <property name="can_focus">False</property>
    
    ... ... @@ -128,6 +77,234 @@
    128 77
           </packing>
    
    129 78
         </child>
    
    130 79
       </object>
    
    80
    +  <object class="GtkStack" id="stack">
    
    81
    +    <property name="visible">True</property>
    
    82
    +    <property name="can_focus">False</property>
    
    83
    +    <child>
    
    84
    +      <object class="GtkBox" id="box">
    
    85
    +        <property name="visible">True</property>
    
    86
    +        <property name="can_focus">False</property>
    
    87
    +        <property name="border_width">18</property>
    
    88
    +        <property name="orientation">vertical</property>
    
    89
    +        <property name="spacing">6</property>
    
    90
    +        <child>
    
    91
    +          <object class="GtkSearchEntry" id="search_entry">
    
    92
    +            <property name="visible">True</property>
    
    93
    +            <property name="can_focus">True</property>
    
    94
    +            <property name="has_focus">True</property>
    
    95
    +            <property name="is_focus">True</property>
    
    96
    +            <property name="primary_icon_name">edit-find-symbolic</property>
    
    97
    +            <property name="primary_icon_activatable">False</property>
    
    98
    +            <property name="primary_icon_sensitive">False</property>
    
    99
    +          </object>
    
    100
    +          <packing>
    
    101
    +            <property name="expand">False</property>
    
    102
    +            <property name="fill">True</property>
    
    103
    +            <property name="position">0</property>
    
    104
    +          </packing>
    
    105
    +        </child>
    
    106
    +        <child>
    
    107
    +          <object class="GtkScrolledWindow" id="scrolledwindow">
    
    108
    +            <property name="visible">True</property>
    
    109
    +            <property name="can_focus">True</property>
    
    110
    +            <property name="hscrollbar_policy">never</property>
    
    111
    +            <property name="shadow_type">in</property>
    
    112
    +            <child>
    
    113
    +              <object class="GtkViewport">
    
    114
    +                <property name="visible">True</property>
    
    115
    +                <property name="can_focus">False</property>
    
    116
    +                <child>
    
    117
    +                  <object class="GtkListBox" id="listbox">
    
    118
    +                    <property name="name">StartChatListBox</property>
    
    119
    +                    <property name="visible">True</property>
    
    120
    +                    <property name="can_focus">False</property>
    
    121
    +                    <property name="selection_mode">browse</property>
    
    122
    +                    <property name="activate_on_single_click">False</property>
    
    123
    +                  </object>
    
    124
    +                </child>
    
    125
    +              </object>
    
    126
    +            </child>
    
    127
    +          </object>
    
    128
    +          <packing>
    
    129
    +            <property name="expand">True</property>
    
    130
    +            <property name="fill">True</property>
    
    131
    +            <property name="position">1</property>
    
    132
    +          </packing>
    
    133
    +        </child>
    
    134
    +      </object>
    
    135
    +      <packing>
    
    136
    +        <property name="name">search</property>
    
    137
    +      </packing>
    
    138
    +    </child>
    
    139
    +    <child>
    
    140
    +      <object class="GtkBox">
    
    141
    +        <property name="visible">True</property>
    
    142
    +        <property name="can_focus">False</property>
    
    143
    +        <property name="orientation">vertical</property>
    
    144
    +        <child>
    
    145
    +          <object class="GtkSpinner" id="spinner">
    
    146
    +            <property name="visible">True</property>
    
    147
    +            <property name="can_focus">False</property>
    
    148
    +            <property name="halign">center</property>
    
    149
    +            <property name="valign">center</property>
    
    150
    +            <property name="vexpand">True</property>
    
    151
    +            <property name="active">True</property>
    
    152
    +          </object>
    
    153
    +          <packing>
    
    154
    +            <property name="expand">False</property>
    
    155
    +            <property name="fill">True</property>
    
    156
    +            <property name="position">0</property>
    
    157
    +          </packing>
    
    158
    +        </child>
    
    159
    +      </object>
    
    160
    +      <packing>
    
    161
    +        <property name="name">progress</property>
    
    162
    +        <property name="position">1</property>
    
    163
    +      </packing>
    
    164
    +    </child>
    
    165
    +    <child>
    
    166
    +      <object class="GtkBox">
    
    167
    +        <property name="visible">True</property>
    
    168
    +        <property name="can_focus">False</property>
    
    169
    +        <property name="orientation">vertical</property>
    
    170
    +        <child>
    
    171
    +          <object class="GtkBox">
    
    172
    +            <property name="visible">True</property>
    
    173
    +            <property name="can_focus">False</property>
    
    174
    +            <property name="orientation">vertical</property>
    
    175
    +            <property name="spacing">12</property>
    
    176
    +            <property name="homogeneous">True</property>
    
    177
    +            <child>
    
    178
    +              <object class="GtkImage">
    
    179
    +                <property name="visible">True</property>
    
    180
    +                <property name="can_focus">False</property>
    
    181
    +                <property name="valign">end</property>
    
    182
    +                <property name="icon_name">dialog-error</property>
    
    183
    +                <property name="icon_size">6</property>
    
    184
    +              </object>
    
    185
    +              <packing>
    
    186
    +                <property name="expand">False</property>
    
    187
    +                <property name="fill">True</property>
    
    188
    +                <property name="position">0</property>
    
    189
    +              </packing>
    
    190
    +            </child>
    
    191
    +            <child>
    
    192
    +              <object class="GtkLabel" id="error_label">
    
    193
    +                <property name="visible">True</property>
    
    194
    +                <property name="can_focus">False</property>
    
    195
    +                <property name="valign">start</property>
    
    196
    +                <property name="justify">center</property>
    
    197
    +                <property name="wrap">True</property>
    
    198
    +                <style>
    
    199
    +                  <class name="bold16"/>
    
    200
    +                </style>
    
    201
    +              </object>
    
    202
    +              <packing>
    
    203
    +                <property name="expand">False</property>
    
    204
    +                <property name="fill">True</property>
    
    205
    +                <property name="position">1</property>
    
    206
    +              </packing>
    
    207
    +            </child>
    
    208
    +          </object>
    
    209
    +          <packing>
    
    210
    +            <property name="expand">True</property>
    
    211
    +            <property name="fill">True</property>
    
    212
    +            <property name="position">0</property>
    
    213
    +          </packing>
    
    214
    +        </child>
    
    215
    +        <child>
    
    216
    +          <object class="GtkButton">
    
    217
    +            <property name="label" translatable="yes">_Back</property>
    
    218
    +            <property name="visible">True</property>
    
    219
    +            <property name="can_focus">True</property>
    
    220
    +            <property name="receives_default">True</property>
    
    221
    +            <property name="halign">start</property>
    
    222
    +            <property name="use_underline">True</property>
    
    223
    +            <signal name="clicked" handler="_on_back_clicked" swapped="no"/>
    
    224
    +          </object>
    
    225
    +          <packing>
    
    226
    +            <property name="expand">False</property>
    
    227
    +            <property name="fill">True</property>
    
    228
    +            <property name="pack_type">end</property>
    
    229
    +            <property name="position">1</property>
    
    230
    +          </packing>
    
    231
    +        </child>
    
    232
    +        <style>
    
    233
    +          <class name="margin-18"/>
    
    234
    +        </style>
    
    235
    +      </object>
    
    236
    +      <packing>
    
    237
    +        <property name="name">error</property>
    
    238
    +        <property name="position">2</property>
    
    239
    +      </packing>
    
    240
    +    </child>
    
    241
    +    <child>
    
    242
    +      <object class="GtkBox" id="info_box">
    
    243
    +        <property name="visible">True</property>
    
    244
    +        <property name="can_focus">False</property>
    
    245
    +        <property name="orientation">vertical</property>
    
    246
    +        <property name="spacing">6</property>
    
    247
    +        <child>
    
    248
    +          <placeholder/>
    
    249
    +        </child>
    
    250
    +        <child>
    
    251
    +          <object class="GtkBox">
    
    252
    +            <property name="visible">True</property>
    
    253
    +            <property name="can_focus">False</property>
    
    254
    +            <property name="homogeneous">True</property>
    
    255
    +            <child>
    
    256
    +              <object class="GtkButton">
    
    257
    +                <property name="label" translatable="yes">_Back</property>
    
    258
    +                <property name="visible">True</property>
    
    259
    +                <property name="can_focus">True</property>
    
    260
    +                <property name="receives_default">True</property>
    
    261
    +                <property name="halign">start</property>
    
    262
    +                <property name="use_underline">True</property>
    
    263
    +                <signal name="clicked" handler="_on_back_clicked" swapped="no"/>
    
    264
    +              </object>
    
    265
    +              <packing>
    
    266
    +                <property name="expand">False</property>
    
    267
    +                <property name="fill">True</property>
    
    268
    +                <property name="position">0</property>
    
    269
    +              </packing>
    
    270
    +            </child>
    
    271
    +            <child>
    
    272
    +              <object class="GtkButton">
    
    273
    +                <property name="label" translatable="yes">_Join</property>
    
    274
    +                <property name="visible">True</property>
    
    275
    +                <property name="can_focus">True</property>
    
    276
    +                <property name="receives_default">True</property>
    
    277
    +                <property name="halign">end</property>
    
    278
    +                <property name="use_underline">True</property>
    
    279
    +                <signal name="clicked" handler="_on_join_clicked" swapped="no"/>
    
    280
    +                <style>
    
    281
    +                  <class name="suggested-action"/>
    
    282
    +                </style>
    
    283
    +              </object>
    
    284
    +              <packing>
    
    285
    +                <property name="expand">False</property>
    
    286
    +                <property name="fill">True</property>
    
    287
    +                <property name="position">1</property>
    
    288
    +              </packing>
    
    289
    +            </child>
    
    290
    +          </object>
    
    291
    +          <packing>
    
    292
    +            <property name="expand">False</property>
    
    293
    +            <property name="fill">True</property>
    
    294
    +            <property name="pack_type">end</property>
    
    295
    +            <property name="position">1</property>
    
    296
    +          </packing>
    
    297
    +        </child>
    
    298
    +        <style>
    
    299
    +          <class name="margin-18"/>
    
    300
    +        </style>
    
    301
    +      </object>
    
    302
    +      <packing>
    
    303
    +        <property name="name">info</property>
    
    304
    +        <property name="position">3</property>
    
    305
    +      </packing>
    
    306
    +    </child>
    
    307
    +  </object>
    
    131 308
       <object class="GtkGrid" id="tooltip">
    
    132 309
         <property name="visible">True</property>
    
    133 310
         <property name="can_focus">False</property>
    

  • gajim/data/style/gajim.css
    ... ... @@ -227,6 +227,7 @@ list.settings > row > box {
    227 227
     /* Padding/Margins */
    
    228 228
     .margin-top6 { margin-top: 6px; }
    
    229 229
     .margin-12 { margin: 12px; }
    
    230
    +.margin-18 { margin: 18px; }
    
    230 231
     
    
    231 232
     /* Treeview */
    
    232 233
     treeview.space { padding: 6px; }
    

  • gajim/dialog_messages.py
    ... ... @@ -27,11 +27,6 @@ from gajim.gtk.dialogs import InformationDialog
    27 27
     Message = namedtuple('Message', ['title', 'text', 'dialog'])
    
    28 28
     
    
    29 29
     messages = {
    
    30
    -    'start-chat-not-connected': Message(
    
    31
    -        _('You are not connected to the server'),
    
    32
    -        _('You can not start a new conversation unless you are connected.'),
    
    33
    -        ErrorDialog),
    
    34
    -
    
    35 30
         'invalid-jid-with-error': Message(
    
    36 31
             _('Invalid JID'),
    
    37 32
             '%s',
    

  • gajim/gtk/groupchat_info.py
    ... ... @@ -93,9 +93,10 @@ MUC_FEATURES = {
    93 93
     
    
    94 94
     
    
    95 95
     class GroupChatInfoScrolled(Gtk.ScrolledWindow):
    
    96
    -    def __init__(self, account):
    
    96
    +    def __init__(self, account=None):
    
    97 97
             Gtk.ScrolledWindow.__init__(self)
    
    98 98
             self.set_size_request(400, -1)
    
    99
    +        self.set_vexpand(True)
    
    99 100
             self.set_min_content_height(400)
    
    100 101
             self.set_policy(Gtk.PolicyType.NEVER,
    
    101 102
                             Gtk.PolicyType.AUTOMATIC)
    
    ... ... @@ -105,6 +106,9 @@ class GroupChatInfoScrolled(Gtk.ScrolledWindow):
    105 106
             self._ui.connect_signals(self)
    
    106 107
             self.show_all()
    
    107 108
     
    
    109
    +    def set_account(self, account):
    
    110
    +        self._account = account
    
    111
    +
    
    108 112
         def set_author(self, author, epoch_timestamp=None):
    
    109 113
             if not author:
    
    110 114
                 return
    
    ... ... @@ -181,6 +185,11 @@ class GroupChatInfoScrolled(Gtk.ScrolledWindow):
    181 185
     
    
    182 186
         def _add_features(self, features):
    
    183 187
             grid = self._ui.info_grid
    
    188
    +        for row in range(30, 9, -1):
    
    189
    +            # Remove everything from row 30 to 10
    
    190
    +            # We probably will never have 30 rows and
    
    191
    +            # there is no method to count grid rows
    
    192
    +            grid.remove_row(row)
    
    184 193
             features = list(features)
    
    185 194
     
    
    186 195
             has_mam = NS_MAM_2 in features or NS_MAM_1 in features
    

  • gajim/gtk/start_chat.py
    ... ... @@ -20,6 +20,8 @@ from gi.repository import Gtk
    20 20
     from gi.repository import GLib
    
    21 21
     from gi.repository import Pango
    
    22 22
     
    
    23
    +from nbxmpp.protocol import InvalidJid
    
    24
    +from nbxmpp.protocol import JID
    
    23 25
     from nbxmpp.util import is_error_result
    
    24 26
     from nbxmpp.const import AnonymityMode
    
    25 27
     
    
    ... ... @@ -27,7 +29,9 @@ from gajim.common import app
    27 29
     from gajim.common import helpers
    
    28 30
     from gajim.common.i18n import _
    
    29 31
     from gajim.common.const import AvatarSize
    
    32
    +from gajim.common.const import MUC_DISCO_ERRORS
    
    30 33
     
    
    34
    +from gajim.gtk.groupchat_info import GroupChatInfoScrolled
    
    31 35
     from gajim.gtk.util import get_icon_name
    
    32 36
     from gajim.gtk.util import get_builder
    
    33 37
     from gajim.gtk.util import ensure_not_destroyed
    
    ... ... @@ -56,7 +60,7 @@ class StartChatDialog(Gtk.ApplicationWindow):
    56 60
             self._search_stopped = False
    
    57 61
     
    
    58 62
             self._ui = get_builder('start_chat_dialog.ui')
    
    59
    -        self.add(self._ui.box)
    
    63
    +        self.add(self._ui.stack)
    
    60 64
     
    
    61 65
             self.new_contact_row_visible = False
    
    62 66
             self.new_contact_rows = {}
    
    ... ... @@ -81,10 +85,14 @@ class StartChatDialog(Gtk.ApplicationWindow):
    81 85
             self._muc_search_listbox = MUCSearch()
    
    82 86
             self._current_listbox = self._ui.listbox
    
    83 87
     
    
    88
    +        self._muc_info_box = GroupChatInfoScrolled()
    
    89
    +        self._ui.info_box.add(self._muc_info_box)
    
    90
    +
    
    84 91
             self.connect('key-press-event', self._on_key_press)
    
    85 92
             self.connect('destroy', self._destroy)
    
    86 93
     
    
    87 94
             self.select_first_row()
    
    95
    +        self._ui.connect_signals(self)
    
    88 96
             self.show_all()
    
    89 97
     
    
    90 98
         def set_search_text(self, text):
    
    ... ... @@ -126,64 +134,131 @@ class StartChatDialog(Gtk.ApplicationWindow):
    126 134
                                      show_account, True)
    
    127 135
                     self._ui.listbox.add(row)
    
    128 136
     
    
    129
    -    def _on_row_activated(self, listbox, row):
    
    137
    +    def _on_row_activated(self, _listbox, row):
    
    130 138
             row = row.get_child()
    
    131 139
             self._start_new_chat(row)
    
    132 140
     
    
    133
    -    def _on_key_press(self, widget, event):
    
    141
    +    def _on_key_press(self, _widget, event):
    
    142
    +        is_search = self._ui.stack.get_visible_child_name() == 'search'
    
    134 143
             if event.keyval in (Gdk.KEY_Down, Gdk.KEY_Tab):
    
    135
    -            self._ui.search_entry.emit('next-match')
    
    136
    -            return True
    
    144
    +            if is_search:
    
    145
    +                self._ui.search_entry.emit('next-match')
    
    146
    +                return Gdk.EVENT_STOP
    
    147
    +            return Gdk.EVENT_PROPAGATE
    
    137 148
     
    
    138 149
             if (event.state == Gdk.ModifierType.SHIFT_MASK and
    
    139 150
                     event.keyval == Gdk.KEY_ISO_Left_Tab):
    
    140
    -            self._ui.search_entry.emit('previous-match')
    
    141
    -            return True
    
    151
    +            if is_search:
    
    152
    +                self._ui.search_entry.emit('previous-match')
    
    153
    +                return Gdk.EVENT_STOP
    
    154
    +            return Gdk.EVENT_PROPAGATE
    
    142 155
     
    
    143 156
             if event.keyval == Gdk.KEY_Up:
    
    144
    -            self._ui.search_entry.emit('previous-match')
    
    145
    -            return True
    
    157
    +            if is_search:
    
    158
    +                self._ui.search_entry.emit('previous-match')
    
    159
    +                return Gdk.EVENT_STOP
    
    160
    +            return Gdk.EVENT_PROPAGATE
    
    146 161
     
    
    147 162
             if event.keyval == Gdk.KEY_Escape:
    
    163
    +            if self._ui.stack.get_visible_child_name() == 'progress':
    
    164
    +                self.destroy()
    
    165
    +                return Gdk.EVENT_STOP
    
    166
    +
    
    167
    +            if self._ui.stack.get_visible_child_name() in ('error', 'info'):
    
    168
    +                self._ui.stack.set_visible_child_name('search')
    
    169
    +                return Gdk.EVENT_STOP
    
    170
    +
    
    148 171
                 self._search_stopped = True
    
    149 172
                 self._muc_search_listbox.remove_all()
    
    150 173
                 if self._ui.search_entry.get_text() != '':
    
    151 174
                     self._ui.search_entry.emit('stop-search')
    
    152 175
                 else:
    
    153 176
                     self.destroy()
    
    154
    -            return True
    
    177
    +            return Gdk.EVENT_STOP
    
    155 178
     
    
    156 179
             if event.keyval == Gdk.KEY_Return:
    
    180
    +            if self._ui.stack.get_visible_child_name() == 'progress':
    
    181
    +                return Gdk.EVENT_STOP
    
    182
    +
    
    183
    +            if self._ui.stack.get_visible_child_name() == 'error':
    
    184
    +                self._ui.stack.set_visible_child_name('search')
    
    185
    +                return Gdk.EVENT_STOP
    
    186
    +
    
    187
    +            if self._ui.stack.get_visible_child_name() == 'info':
    
    188
    +                self._on_join_clicked()
    
    189
    +                return Gdk.EVENT_STOP
    
    190
    +
    
    157 191
                 if self._current_listbox_is(Search.MUC):
    
    158 192
                     self._muc_search_listbox.remove_all()
    
    159 193
                     self._start_search()
    
    160
    -                return True
    
    194
    +                return Gdk.EVENT_STOP
    
    161 195
     
    
    162 196
                 row = self._ui.listbox.get_selected_row()
    
    163 197
                 if row is not None:
    
    164 198
                     row.emit('activate')
    
    165
    -            return True
    
    199
    +            return Gdk.EVENT_STOP
    
    166 200
     
    
    167
    -        self._ui.search_entry.grab_focus_without_selecting()
    
    201
    +        if is_search:
    
    202
    +            self._ui.search_entry.grab_focus_without_selecting()
    
    203
    +        return Gdk.EVENT_PROPAGATE
    
    168 204
     
    
    169 205
         def _start_new_chat(self, row):
    
    170 206
             if row.new:
    
    171
    -            if not app.account_is_connected(row.account):
    
    172
    -                app.interface.raise_dialog('start-chat-not-connected')
    
    173
    -                return
    
    174 207
                 try:
    
    175
    -                helpers.parse_jid(row.jid)
    
    176
    -            except helpers.InvalidFormat as e:
    
    177
    -                app.interface.raise_dialog('invalid-jid-with-error', str(e))
    
    208
    +                JID(row.jid)
    
    209
    +            except InvalidJid as error:
    
    210
    +                self._show_error_page(str(error))
    
    178 211
                     return
    
    179 212
     
    
    180 213
             if row.groupchat:
    
    181
    -            app.interface.join_gc_minimal(row.account, row.jid)
    
    214
    +            if not app.account_is_connected(row.account):
    
    215
    +                self._show_error_page(_('You can not join a group chat '
    
    216
    +                                        'unless you are connected.'))
    
    217
    +                return
    
    218
    +            self._disco_muc(row.account, row.jid)
    
    182 219
             else:
    
    183 220
                 app.interface.new_chat_from_jid(row.account, row.jid)
    
    184 221
     
    
    185 222
             self.ready_to_destroy = True
    
    186 223
     
    
    224
    +    def _disco_muc(self, account, jid):
    
    225
    +        self._ui.stack.set_visible_child_name('progress')
    
    226
    +        con = app.connections[account]
    
    227
    +        con.get_module('Discovery').disco_info(
    
    228
    +            jid, callback=self._disco_info_received, user_data=account)
    
    229
    +
    
    230
    +    @ensure_not_destroyed
    
    231
    +    def _disco_info_received(self, result, account):
    
    232
    +        if is_error_result(result):
    
    233
    +            self._set_error(result)
    
    234
    +
    
    235
    +        elif result.is_muc:
    
    236
    +            self._muc_info_box.set_account(account)
    
    237
    +            self._muc_info_box.set_from_disco_info(result)
    
    238
    +            self._ui.stack.set_visible_child_name('info')
    
    239
    +
    
    240
    +        else:
    
    241
    +            self._set_error_from_code('not-muc-service')
    
    242
    +
    
    243
    +    def _set_error(self, error):
    
    244
    +        text = MUC_DISCO_ERRORS.get(error.type, str(error))
    
    245
    +        self._show_error_page(text)
    
    246
    +
    
    247
    +    def _set_error_from_code(self, error_code):
    
    248
    +        self._show_error_page(MUC_DISCO_ERRORS[error_code])
    
    249
    +
    
    250
    +    def _show_error_page(self, text):
    
    251
    +        self._ui.error_label.set_text(text)
    
    252
    +        self._ui.stack.set_visible_child_name('error')
    
    253
    +
    
    254
    +    def _on_join_clicked(self, _button=None):
    
    255
    +        row = self._ui.listbox.get_selected_row().get_child()
    
    256
    +        app.interface.join_gc_minimal(row.account, row.jid)
    
    257
    +        self.ready_to_destroy = True
    
    258
    +
    
    259
    +    def _on_back_clicked(self, _button):
    
    260
    +        self._ui.stack.set_visible_child_name('search')
    
    261
    +
    
    187 262
         def _set_listbox(self, listbox):
    
    188 263
             if self._current_listbox == listbox:
    
    189 264
                 return
    
    ... ... @@ -241,7 +316,7 @@ class StartChatDialog(Gtk.ApplicationWindow):
    241 316
                 self.new_contact_rows[account].update_jid(search_text)
    
    242 317
                 self.new_groupchat_rows[account].update_jid(search_text)
    
    243 318
     
    
    244
    -    def _select_new_match(self, entry, direction):
    
    319
    +    def _select_new_match(self, _entry, direction):
    
    245 320
             selected_row = self._ui.listbox.get_selected_row()
    
    246 321
             if selected_row is None:
    
    247 322
                 return
    
    ... ... @@ -270,19 +345,19 @@ class StartChatDialog(Gtk.ApplicationWindow):
    270 345
             first_row = self._ui.listbox.get_row_at_y(0)
    
    271 346
             self._ui.listbox.select_row(first_row)
    
    272 347
     
    
    273
    -    def _filter_func(self, row, user_data):
    
    348
    +    def _filter_func(self, row, _user_data):
    
    274 349
             search_text = self._ui.search_entry.get_text().lower()
    
    275 350
             search_text_list = search_text.split()
    
    276 351
             row_text = row.get_child().get_search_text().lower()
    
    277 352
             for text in search_text_list:
    
    278 353
                 if text not in row_text:
    
    279 354
                     GLib.timeout_add(50, self.select_first_row)
    
    280
    -                return
    
    355
    +                return None
    
    281 356
             GLib.timeout_add(50, self.select_first_row)
    
    282 357
             return True
    
    283 358
     
    
    284 359
         @staticmethod
    
    285
    -    def _sort_func(row1, row2, user_data):
    
    360
    +    def _sort_func(row1, row2, _user_data):
    
    286 361
             name1 = row1.get_child().get_search_text()
    
    287 362
             name2 = row2.get_child().get_search_text()
    
    288 363
             account1 = row1.get_child().account
    
    ... ... @@ -539,7 +614,8 @@ class MUCSearch(Gtk.ListBox):
    539 614
             self._ui.tooltip_name.hide()
    
    540 615
             self._ui.tooltip_name_label.hide()
    
    541 616
     
    
    542
    -    def _on_row_activated(self, _listbox, row):
    
    617
    +    @staticmethod
    
    618
    +    def _on_row_activated(_listbox, row):
    
    543 619
             app.interface.join_gc_minimal(None, row.item.jid)
    
    544 620
     
    
    545 621
     
    

  • gajim/gui_interface.py
    ... ... @@ -1441,7 +1441,7 @@ class Interface:
    1441 1441
                 bookmark = con.get_module('Bookmarks').get_bookmark_from_jid(room_jid)
    
    1442 1442
                 if bookmark is not None:
    
    1443 1443
                     app.interface.join_gc_room(
    
    1444
    -                    account, bookmark.jid, bookmark.nick, bookmark.password)
    
    1444
    +                    account, str(bookmark.jid), bookmark.nick, bookmark.password)
    
    1445 1445
                     return
    
    1446 1446
     
    
    1447 1447
             try:
    

  • gajim/remote_control.py
    ... ... @@ -221,7 +221,7 @@ class GajimRemote(Server):
    221 221
                 <method name='show_next_pending_event' />
    
    222 222
                 <method name='show_roster' />
    
    223 223
                 <method name='start_chat'>
    
    224
    -                <arg name='account' type='s' />
    
    224
    +                <arg name='jid' type='s' />
    
    225 225
                     <arg direction='out' type='b' />
    
    226 226
                 </method>
    
    227 227
                 <method name='toggle_ipython' />
    
    ... ... @@ -884,11 +884,8 @@ class GajimRemote(Server):
    884 884
                     unread -= 1
    
    885 885
             return str(unread)
    
    886 886
     
    
    887
    -    def start_chat(self, account):
    
    888
    -        if not account:
    
    889
    -            # error is shown in gajim-remote check_arguments(..)
    
    890
    -            return False
    
    891
    -        app.app.activate_action('start-chat', GLib.Variant('s', ''))
    
    887
    +    def start_chat(self, jid=''):
    
    888
    +        app.app.activate_action('start-chat', GLib.Variant('s', jid))
    
    892 889
             return True
    
    893 890
     
    
    894 891
         def send_xml(self, xml, account):