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

Commits:

9 changed files:

Changes:

  • gajim/chat_control.py
    ... ... @@ -33,6 +33,7 @@ from gi.repository import Gtk
    33 33
     from gi.repository import Gio
    
    34 34
     from gi.repository import Pango
    
    35 35
     from gi.repository import GLib
    
    36
    +from gi.repository import Gdk
    
    36 37
     from nbxmpp.protocol import NS_XHTML, NS_XHTML_IM, NS_FILE, NS_MUC
    
    37 38
     from nbxmpp.protocol import NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO
    
    38 39
     from nbxmpp.protocol import NS_JINGLE_ICE_UDP, NS_JINGLE_FILE_TRANSFER_5
    
    ... ... @@ -358,6 +359,28 @@ class ChatControl(ChatControlBase):
    358 359
             win.lookup_action(
    
    359 360
                 'information-' + self.control_id).set_enabled(online)
    
    360 361
     
    
    362
    +    def delegate_action(self, action):
    
    363
    +        res = super().delegate_action(action)
    
    364
    +        if res == Gdk.EVENT_STOP:
    
    365
    +            return res
    
    366
    +
    
    367
    +        if action == 'show-contact-info':
    
    368
    +            self.parent_win.window.lookup_action(
    
    369
    +                'information-%s' % self.control_id).activate()
    
    370
    +            return Gdk.EVENT_STOP
    
    371
    +
    
    372
    +        if action == 'send-file':
    
    373
    +            if app.interface.msg_win_mgr.mode == \
    
    374
    +            app.interface.msg_win_mgr.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER:
    
    375
    +                app.interface.roster.tree.grab_focus()
    
    376
    +                return Gdk.EVENT_PROPAGATE
    
    377
    +
    
    378
    +            self.parent_win.window.lookup_action(
    
    379
    +                'send-file-%s' % self.control_id).activate()
    
    380
    +            return Gdk.EVENT_STOP
    
    381
    +
    
    382
    +        return Gdk.EVENT_PROPAGATE
    
    383
    +
    
    361 384
         def _on_add_to_roster(self, action, param):
    
    362 385
             AddNewContactWindow(self.account, self.contact.jid)
    
    363 386
     
    

  • gajim/chat_control_base.py
    ... ... @@ -390,6 +390,28 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
    390 390
             # to properly use the super, because of the old code.
    
    391 391
             CommandTools.__init__(self)
    
    392 392
     
    
    393
    +    def delegate_action(self, action):
    
    394
    +        if action == 'browse-history':
    
    395
    +            dict_ = {'jid': GLib.Variant('s', self.contact.jid),
    
    396
    +                     'account': GLib.Variant('s', self.account)}
    
    397
    +            variant = GLib.Variant('a{sv}', dict_)
    
    398
    +            app.app.activate_action('browse-history', variant)
    
    399
    +            return Gdk.EVENT_STOP
    
    400
    +
    
    401
    +        if action == 'clear-chat':
    
    402
    +            self.conv_textview.clear()
    
    403
    +            return Gdk.EVENT_STOP
    
    404
    +
    
    405
    +        if action == 'delete-line':
    
    406
    +            self.clear(self.msg_textview)
    
    407
    +            return Gdk.EVENT_STOP
    
    408
    +
    
    409
    +        if action == 'show-emoji-chooser':
    
    410
    +            self.emoticons_button.get_popover().show()
    
    411
    +            return Gdk.EVENT_STOP
    
    412
    +
    
    413
    +        return Gdk.EVENT_PROPAGATE
    
    414
    +
    
    393 415
         def add_actions(self):
    
    394 416
             action = Gio.SimpleAction.new_stateful(
    
    395 417
                 "set-encryption-%s" % self.control_id,
    

  • gajim/data/gui/groupchat_control.ui
    ... ... @@ -81,374 +81,515 @@
    81 81
       <object class="GtkBox" id="groupchat_control_hbox">
    
    82 82
         <property name="can_focus">True</property>
    
    83 83
         <child>
    
    84
    -      <object class="GtkBox" id="groupchat_control_vbox">
    
    85
    -        <property name="can_focus">True</property>
    
    86
    -        <property name="margin_left">7</property>
    
    87
    -        <property name="margin_right">7</property>
    
    88
    -        <property name="margin_top">5</property>
    
    89
    -        <property name="margin_bottom">7</property>
    
    90
    -        <property name="orientation">vertical</property>
    
    91
    -        <property name="spacing">5</property>
    
    84
    +      <object class="GtkStack" id="stack">
    
    85
    +        <property name="visible">True</property>
    
    86
    +        <property name="can_focus">False</property>
    
    92 87
             <child>
    
    93
    -          <object class="GtkPaned" id="hpaned">
    
    94
    -            <property name="visible">True</property>
    
    88
    +          <object class="GtkBox" id="groupchat_control_vbox">
    
    95 89
                 <property name="can_focus">True</property>
    
    96
    -            <property name="position">495</property>
    
    97
    -            <property name="position_set">True</property>
    
    98
    -            <signal name="button-release-event" handler="_on_hpaned_release_button" swapped="no"/>
    
    99
    -            <signal name="notify::position" handler="_on_hpaned_handle_change" swapped="no"/>
    
    90
    +            <property name="margin_left">7</property>
    
    91
    +            <property name="margin_right">7</property>
    
    92
    +            <property name="margin_top">5</property>
    
    93
    +            <property name="margin_bottom">7</property>
    
    94
    +            <property name="orientation">vertical</property>
    
    95
    +            <property name="spacing">5</property>
    
    100 96
                 <child>
    
    101
    -              <object class="GtkOverlay" id="overlay">
    
    97
    +              <object class="GtkPaned" id="hpaned">
    
    102 98
                     <property name="visible">True</property>
    
    103
    -                <property name="can_focus">False</property>
    
    99
    +                <property name="can_focus">True</property>
    
    100
    +                <property name="position">495</property>
    
    101
    +                <property name="position_set">True</property>
    
    102
    +                <signal name="button-release-event" handler="_on_hpaned_release_button" swapped="no"/>
    
    103
    +                <signal name="notify::position" handler="_on_hpaned_handle_change" swapped="no"/>
    
    104 104
                     <child>
    
    105
    -                  <object class="GtkBox" id="gc_textviews_vbox">
    
    106
    -                    <property name="width_request">0</property>
    
    105
    +                  <object class="GtkOverlay" id="overlay">
    
    107 106
                         <property name="visible">True</property>
    
    108 107
                         <property name="can_focus">False</property>
    
    109
    -                    <property name="margin_right">4</property>
    
    110
    -                    <property name="orientation">vertical</property>
    
    111 108
                         <child>
    
    112
    -                      <object class="GtkEventBox" id="banner_eventbox">
    
    113
    -                        <property name="name">GroupChatControl-BannerEventBox</property>
    
    109
    +                      <object class="GtkBox" id="gc_textviews_vbox">
    
    110
    +                        <property name="width_request">0</property>
    
    114 111
                             <property name="visible">True</property>
    
    115 112
                             <property name="can_focus">False</property>
    
    113
    +                        <property name="margin_right">4</property>
    
    114
    +                        <property name="orientation">vertical</property>
    
    116 115
                             <child>
    
    117
    -                          <object class="GtkBox" id="hbox3024">
    
    116
    +                          <object class="GtkEventBox" id="banner_eventbox">
    
    117
    +                            <property name="name">GroupChatControl-BannerEventBox</property>
    
    118 118
                                 <property name="visible">True</property>
    
    119 119
                                 <property name="can_focus">False</property>
    
    120 120
                                 <child>
    
    121
    -                              <object class="GtkImage" id="gc_banner_status_image">
    
    122
    -                                <property name="visible">True</property>
    
    123
    -                                <property name="can_focus">False</property>
    
    124
    -                                <property name="stock">gtk-missing-image</property>
    
    125
    -                              </object>
    
    126
    -                              <packing>
    
    127
    -                                <property name="expand">False</property>
    
    128
    -                                <property name="fill">False</property>
    
    129
    -                                <property name="padding">5</property>
    
    130
    -                                <property name="position">0</property>
    
    131
    -                              </packing>
    
    132
    -                            </child>
    
    133
    -                            <child>
    
    134
    -                              <object class="GtkLabel" id="banner_name_label">
    
    135
    -                                <property name="name">GroupChatControl-BannerNameLabel</property>
    
    136
    -                                <property name="visible">True</property>
    
    137
    -                                <property name="can_focus">False</property>
    
    138
    -                                <property name="label">&lt;span weight="heavy" size="large"&gt;room jid&lt;/span&gt;</property>
    
    139
    -                                <property name="use_markup">True</property>
    
    140
    -                                <property name="selectable">True</property>
    
    141
    -                                <property name="xalign">0</property>
    
    142
    -                              </object>
    
    143
    -                              <packing>
    
    144
    -                                <property name="expand">False</property>
    
    145
    -                                <property name="fill">True</property>
    
    146
    -                                <property name="position">1</property>
    
    147
    -                              </packing>
    
    148
    -                            </child>
    
    149
    -                            <child>
    
    150
    -                              <object class="GtkActionBar" id="banner_actionbar">
    
    121
    +                              <object class="GtkBox" id="hbox3024">
    
    151 122
                                     <property name="visible">True</property>
    
    152 123
                                     <property name="can_focus">False</property>
    
    153
    -                                <style>
    
    154
    -                                  <class name="actionbar-no-border"/>
    
    155
    -                                </style>
    
    156
    -                              </object>
    
    157
    -                              <packing>
    
    158
    -                                <property name="expand">True</property>
    
    159
    -                                <property name="fill">True</property>
    
    160
    -                                <property name="pack_type">end</property>
    
    161
    -                                <property name="position">2</property>
    
    162
    -                              </packing>
    
    163
    -                            </child>
    
    164
    -                          </object>
    
    165
    -                        </child>
    
    166
    -                        <style>
    
    167
    -                          <class name="gajim-banner"/>
    
    168
    -                        </style>
    
    169
    -                      </object>
    
    170
    -                      <packing>
    
    171
    -                        <property name="expand">False</property>
    
    172
    -                        <property name="fill">True</property>
    
    173
    -                        <property name="position">0</property>
    
    174
    -                      </packing>
    
    175
    -                    </child>
    
    176
    -                    <child>
    
    177
    -                      <object class="GtkSeparator">
    
    178
    -                        <property name="visible">True</property>
    
    179
    -                        <property name="can_focus">False</property>
    
    180
    -                        <style>
    
    181
    -                          <class name="chatcontrol-separator-top"/>
    
    182
    -                        </style>
    
    183
    -                      </object>
    
    184
    -                      <packing>
    
    185
    -                        <property name="expand">False</property>
    
    186
    -                        <property name="fill">True</property>
    
    187
    -                        <property name="position">1</property>
    
    188
    -                      </packing>
    
    189
    -                    </child>
    
    190
    -                    <child>
    
    191
    -                      <object class="GtkScrolledWindow" id="conversation_scrolledwindow">
    
    192
    -                        <property name="width_request">200</property>
    
    193
    -                        <property name="height_request">60</property>
    
    194
    -                        <property name="visible">True</property>
    
    195
    -                        <property name="can_focus">True</property>
    
    196
    -                        <property name="shadow_type">in</property>
    
    197
    -                        <property name="overlay_scrolling">False</property>
    
    198
    -                        <signal name="edge-reached" handler="_on_edge_reached" swapped="no"/>
    
    199
    -                        <signal name="scroll-event" handler="_on_scroll" swapped="no"/>
    
    200
    -                        <child>
    
    201
    -                          <placeholder/>
    
    202
    -                        </child>
    
    203
    -                        <style>
    
    204
    -                          <class name="scrolled-no-border"/>
    
    205
    -                          <class name="no-scroll-indicator"/>
    
    206
    -                          <class name="scrollbar-style"/>
    
    207
    -                        </style>
    
    208
    -                      </object>
    
    209
    -                      <packing>
    
    210
    -                        <property name="expand">True</property>
    
    211
    -                        <property name="fill">True</property>
    
    212
    -                        <property name="position">2</property>
    
    213
    -                      </packing>
    
    214
    -                    </child>
    
    215
    -                    <child>
    
    216
    -                      <object class="GtkSeparator">
    
    217
    -                        <property name="visible">True</property>
    
    218
    -                        <property name="can_focus">False</property>
    
    219
    -                        <style>
    
    220
    -                          <class name="chatcontrol-separator"/>
    
    221
    -                        </style>
    
    222
    -                      </object>
    
    223
    -                      <packing>
    
    224
    -                        <property name="expand">False</property>
    
    225
    -                        <property name="fill">True</property>
    
    226
    -                        <property name="position">3</property>
    
    227
    -                      </packing>
    
    228
    -                    </child>
    
    229
    -                    <child>
    
    230
    -                      <object class="GtkBox" id="hbox">
    
    231
    -                        <property name="visible">True</property>
    
    232
    -                        <property name="can_focus">False</property>
    
    233
    -                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
    
    234
    -                        <child>
    
    235
    -                          <object class="GtkMenuButton" id="settings_menu">
    
    236
    -                            <property name="visible">True</property>
    
    237
    -                            <property name="can_focus">True</property>
    
    238
    -                            <property name="receives_default">True</property>
    
    239
    -                            <property name="relief">none</property>
    
    240
    -                            <child>
    
    241
    -                              <object class="GtkImage">
    
    242
    -                                <property name="visible">True</property>
    
    243
    -                                <property name="can_focus">False</property>
    
    244
    -                                <property name="icon_name">open-menu-symbolic</property>
    
    124
    +                                <child>
    
    125
    +                                  <object class="GtkImage" id="gc_banner_status_image">
    
    126
    +                                    <property name="visible">True</property>
    
    127
    +                                    <property name="can_focus">False</property>
    
    128
    +                                    <property name="stock">gtk-missing-image</property>
    
    129
    +                                  </object>
    
    130
    +                                  <packing>
    
    131
    +                                    <property name="expand">False</property>
    
    132
    +                                    <property name="fill">False</property>
    
    133
    +                                    <property name="padding">5</property>
    
    134
    +                                    <property name="position">0</property>
    
    135
    +                                  </packing>
    
    136
    +                                </child>
    
    137
    +                                <child>
    
    138
    +                                  <object class="GtkLabel" id="banner_name_label">
    
    139
    +                                    <property name="name">GroupChatControl-BannerNameLabel</property>
    
    140
    +                                    <property name="visible">True</property>
    
    141
    +                                    <property name="can_focus">False</property>
    
    142
    +                                    <property name="label">&lt;span weight="heavy" size="large"&gt;room jid&lt;/span&gt;</property>
    
    143
    +                                    <property name="use_markup">True</property>
    
    144
    +                                    <property name="selectable">True</property>
    
    145
    +                                    <property name="xalign">0</property>
    
    146
    +                                  </object>
    
    147
    +                                  <packing>
    
    148
    +                                    <property name="expand">False</property>
    
    149
    +                                    <property name="fill">True</property>
    
    150
    +                                    <property name="position">1</property>
    
    151
    +                                  </packing>
    
    152
    +                                </child>
    
    153
    +                                <child>
    
    154
    +                                  <object class="GtkActionBar" id="banner_actionbar">
    
    155
    +                                    <property name="visible">True</property>
    
    156
    +                                    <property name="can_focus">False</property>
    
    157
    +                                    <style>
    
    158
    +                                      <class name="actionbar-no-border"/>
    
    159
    +                                    </style>
    
    160
    +                                  </object>
    
    161
    +                                  <packing>
    
    162
    +                                    <property name="expand">True</property>
    
    163
    +                                    <property name="fill">True</property>
    
    164
    +                                    <property name="pack_type">end</property>
    
    165
    +                                    <property name="position">2</property>
    
    166
    +                                  </packing>
    
    167
    +                                </child>
    
    245 168
                                   </object>
    
    246 169
                                 </child>
    
    247 170
                                 <style>
    
    248
    -                              <class name="chatcontrol-actionbar-button"/>
    
    171
    +                              <class name="gajim-banner"/>
    
    249 172
                                 </style>
    
    250 173
                               </object>
    
    251 174
                               <packing>
    
    252 175
                                 <property name="expand">False</property>
    
    253 176
                                 <property name="fill">True</property>
    
    254
    -                            <property name="pack_type">end</property>
    
    255 177
                                 <property name="position">0</property>
    
    256 178
                               </packing>
    
    257 179
                             </child>
    
    258 180
                             <child>
    
    259
    -                          <object class="GtkButton" id="authentication_button">
    
    260
    -                            <property name="can_focus">True</property>
    
    261
    -                            <property name="focus_on_click">False</property>
    
    262
    -                            <property name="receives_default">True</property>
    
    263
    -                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
    
    264
    -                            <property name="no_show_all">True</property>
    
    265
    -                            <property name="relief">none</property>
    
    266
    -                            <child>
    
    267
    -                              <object class="GtkImage" id="lock_image">
    
    268
    -                                <property name="visible">True</property>
    
    269
    -                                <property name="can_focus">False</property>
    
    270
    -                                <property name="stock">gtk-dialog-authentication</property>
    
    271
    -                                <property name="icon_size">1</property>
    
    272
    -                              </object>
    
    273
    -                            </child>
    
    181
    +                          <object class="GtkSeparator">
    
    182
    +                            <property name="visible">True</property>
    
    183
    +                            <property name="can_focus">False</property>
    
    274 184
                                 <style>
    
    275
    -                              <class name="chatcontrol-actionbar-button"/>
    
    185
    +                              <class name="chatcontrol-separator-top"/>
    
    276 186
                                 </style>
    
    277 187
                               </object>
    
    278 188
                               <packing>
    
    279 189
                                 <property name="expand">False</property>
    
    280
    -                            <property name="fill">False</property>
    
    281
    -                            <property name="pack_type">end</property>
    
    190
    +                            <property name="fill">True</property>
    
    282 191
                                 <property name="position">1</property>
    
    283 192
                               </packing>
    
    284 193
                             </child>
    
    285 194
                             <child>
    
    286
    -                          <object class="GtkMenuButton" id="encryption_menu">
    
    195
    +                          <object class="GtkScrolledWindow" id="conversation_scrolledwindow">
    
    196
    +                            <property name="width_request">200</property>
    
    197
    +                            <property name="height_request">60</property>
    
    287 198
                                 <property name="visible">True</property>
    
    288 199
                                 <property name="can_focus">True</property>
    
    289
    -                            <property name="receives_default">True</property>
    
    290
    -                            <property name="tooltip_text" translatable="yes">Choose encryption</property>
    
    291
    -                            <property name="relief">none</property>
    
    200
    +                            <property name="shadow_type">in</property>
    
    201
    +                            <property name="overlay_scrolling">False</property>
    
    202
    +                            <signal name="edge-reached" handler="_on_edge_reached" swapped="no"/>
    
    203
    +                            <signal name="scroll-event" handler="_on_scroll" swapped="no"/>
    
    292 204
                                 <child>
    
    293 205
                                   <placeholder/>
    
    294 206
                                 </child>
    
    295 207
                                 <style>
    
    296
    -                              <class name="chatcontrol-actionbar-button"/>
    
    208
    +                              <class name="scrolled-no-border"/>
    
    209
    +                              <class name="no-scroll-indicator"/>
    
    210
    +                              <class name="scrollbar-style"/>
    
    297 211
                                 </style>
    
    298 212
                               </object>
    
    299 213
                               <packing>
    
    300
    -                            <property name="expand">False</property>
    
    214
    +                            <property name="expand">True</property>
    
    301 215
                                 <property name="fill">True</property>
    
    302
    -                            <property name="pack_type">end</property>
    
    303 216
                                 <property name="position">2</property>
    
    304 217
                               </packing>
    
    305 218
                             </child>
    
    306 219
                             <child>
    
    307
    -                          <object class="GtkButton" id="sendfile_button">
    
    220
    +                          <object class="GtkSeparator">
    
    308 221
                                 <property name="visible">True</property>
    
    309
    -                            <property name="can_focus">True</property>
    
    310
    -                            <property name="focus_on_click">False</property>
    
    311
    -                            <property name="receives_default">True</property>
    
    312
    -                            <property name="relief">none</property>
    
    313
    -                            <child>
    
    314
    -                              <object class="GtkImage">
    
    315
    -                                <property name="visible">True</property>
    
    316
    -                                <property name="can_focus">False</property>
    
    317
    -                                <property name="icon_name">mail-attachment-symbolic</property>
    
    318
    -                              </object>
    
    319
    -                            </child>
    
    222
    +                            <property name="can_focus">False</property>
    
    320 223
                                 <style>
    
    321
    -                              <class name="chatcontrol-actionbar-button"/>
    
    224
    +                              <class name="chatcontrol-separator"/>
    
    322 225
                                 </style>
    
    323 226
                               </object>
    
    324 227
                               <packing>
    
    325 228
                                 <property name="expand">False</property>
    
    326
    -                            <property name="fill">False</property>
    
    327
    -                            <property name="pack_type">end</property>
    
    229
    +                            <property name="fill">True</property>
    
    328 230
                                 <property name="position">3</property>
    
    329 231
                               </packing>
    
    330 232
                             </child>
    
    331 233
                             <child>
    
    332
    -                          <object class="GtkMenuButton" id="emoticons_button">
    
    234
    +                          <object class="GtkBox" id="hbox">
    
    333 235
                                 <property name="visible">True</property>
    
    334
    -                            <property name="can_focus">True</property>
    
    335
    -                            <property name="receives_default">True</property>
    
    336
    -                            <property name="tooltip_text" translatable="yes">Show a list of emojis (Alt+M)</property>
    
    337
    -                            <property name="relief">none</property>
    
    236
    +                            <property name="can_focus">False</property>
    
    237
    +                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
    
    338 238
                                 <child>
    
    339
    -                              <object class="GtkImage">
    
    239
    +                              <object class="GtkMenuButton" id="settings_menu">
    
    340 240
                                     <property name="visible">True</property>
    
    341
    -                                <property name="can_focus">False</property>
    
    342
    -                                <property name="icon_name">face-smile-symbolic</property>
    
    241
    +                                <property name="can_focus">True</property>
    
    242
    +                                <property name="receives_default">True</property>
    
    243
    +                                <property name="relief">none</property>
    
    244
    +                                <child>
    
    245
    +                                  <object class="GtkImage">
    
    246
    +                                    <property name="visible">True</property>
    
    247
    +                                    <property name="can_focus">False</property>
    
    248
    +                                    <property name="icon_name">open-menu-symbolic</property>
    
    249
    +                                  </object>
    
    250
    +                                </child>
    
    251
    +                                <style>
    
    252
    +                                  <class name="chatcontrol-actionbar-button"/>
    
    253
    +                                </style>
    
    343 254
                                   </object>
    
    255
    +                              <packing>
    
    256
    +                                <property name="expand">False</property>
    
    257
    +                                <property name="fill">True</property>
    
    258
    +                                <property name="pack_type">end</property>
    
    259
    +                                <property name="position">0</property>
    
    260
    +                              </packing>
    
    261
    +                            </child>
    
    262
    +                            <child>
    
    263
    +                              <object class="GtkButton" id="authentication_button">
    
    264
    +                                <property name="can_focus">True</property>
    
    265
    +                                <property name="focus_on_click">False</property>
    
    266
    +                                <property name="receives_default">True</property>
    
    267
    +                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
    
    268
    +                                <property name="no_show_all">True</property>
    
    269
    +                                <property name="relief">none</property>
    
    270
    +                                <child>
    
    271
    +                                  <object class="GtkImage" id="lock_image">
    
    272
    +                                    <property name="visible">True</property>
    
    273
    +                                    <property name="can_focus">False</property>
    
    274
    +                                    <property name="stock">gtk-dialog-authentication</property>
    
    275
    +                                    <property name="icon_size">1</property>
    
    276
    +                                  </object>
    
    277
    +                                </child>
    
    278
    +                                <style>
    
    279
    +                                  <class name="chatcontrol-actionbar-button"/>
    
    280
    +                                </style>
    
    281
    +                              </object>
    
    282
    +                              <packing>
    
    283
    +                                <property name="expand">False</property>
    
    284
    +                                <property name="fill">False</property>
    
    285
    +                                <property name="pack_type">end</property>
    
    286
    +                                <property name="position">1</property>
    
    287
    +                              </packing>
    
    288
    +                            </child>
    
    289
    +                            <child>
    
    290
    +                              <object class="GtkMenuButton" id="encryption_menu">
    
    291
    +                                <property name="visible">True</property>
    
    292
    +                                <property name="can_focus">True</property>
    
    293
    +                                <property name="receives_default">True</property>
    
    294
    +                                <property name="tooltip_text" translatable="yes">Choose encryption</property>
    
    295
    +                                <property name="relief">none</property>
    
    296
    +                                <child>
    
    297
    +                                  <placeholder/>
    
    298
    +                                </child>
    
    299
    +                                <style>
    
    300
    +                                  <class name="chatcontrol-actionbar-button"/>
    
    301
    +                                </style>
    
    302
    +                              </object>
    
    303
    +                              <packing>
    
    304
    +                                <property name="expand">False</property>
    
    305
    +                                <property name="fill">True</property>
    
    306
    +                                <property name="pack_type">end</property>
    
    307
    +                                <property name="position">2</property>
    
    308
    +                              </packing>
    
    309
    +                            </child>
    
    310
    +                            <child>
    
    311
    +                              <object class="GtkButton" id="sendfile_button">
    
    312
    +                                <property name="visible">True</property>
    
    313
    +                                <property name="can_focus">True</property>
    
    314
    +                                <property name="focus_on_click">False</property>
    
    315
    +                                <property name="receives_default">True</property>
    
    316
    +                                <property name="relief">none</property>
    
    317
    +                                <child>
    
    318
    +                                  <object class="GtkImage">
    
    319
    +                                    <property name="visible">True</property>
    
    320
    +                                    <property name="can_focus">False</property>
    
    321
    +                                    <property name="icon_name">mail-attachment-symbolic</property>
    
    322
    +                                  </object>
    
    323
    +                                </child>
    
    324
    +                                <style>
    
    325
    +                                  <class name="chatcontrol-actionbar-button"/>
    
    326
    +                                </style>
    
    327
    +                              </object>
    
    328
    +                              <packing>
    
    329
    +                                <property name="expand">False</property>
    
    330
    +                                <property name="fill">False</property>
    
    331
    +                                <property name="pack_type">end</property>
    
    332
    +                                <property name="position">3</property>
    
    333
    +                              </packing>
    
    334
    +                            </child>
    
    335
    +                            <child>
    
    336
    +                              <object class="GtkMenuButton" id="emoticons_button">
    
    337
    +                                <property name="visible">True</property>
    
    338
    +                                <property name="can_focus">True</property>
    
    339
    +                                <property name="receives_default">True</property>
    
    340
    +                                <property name="tooltip_text" translatable="yes">Show a list of emojis (Alt+M)</property>
    
    341
    +                                <property name="relief">none</property>
    
    342
    +                                <child>
    
    343
    +                                  <object class="GtkImage">
    
    344
    +                                    <property name="visible">True</property>
    
    345
    +                                    <property name="can_focus">False</property>
    
    346
    +                                    <property name="icon_name">face-smile-symbolic</property>
    
    347
    +                                  </object>
    
    348
    +                                </child>
    
    349
    +                                <style>
    
    350
    +                                  <class name="chatcontrol-actionbar-button"/>
    
    351
    +                                </style>
    
    352
    +                              </object>
    
    353
    +                              <packing>
    
    354
    +                                <property name="expand">False</property>
    
    355
    +                                <property name="fill">True</property>
    
    356
    +                                <property name="position">4</property>
    
    357
    +                              </packing>
    
    344 358
                                 </child>
    
    345
    -                            <style>
    
    346
    -                              <class name="chatcontrol-actionbar-button"/>
    
    347
    -                            </style>
    
    348
    -                          </object>
    
    349
    -                          <packing>
    
    350
    -                            <property name="expand">False</property>
    
    351
    -                            <property name="fill">True</property>
    
    352
    -                            <property name="position">4</property>
    
    353
    -                          </packing>
    
    354
    -                        </child>
    
    355
    -                        <child>
    
    356
    -                          <object class="GtkMenuButton" id="formattings_button">
    
    357
    -                            <property name="visible">True</property>
    
    358
    -                            <property name="can_focus">True</property>
    
    359
    -                            <property name="focus_on_click">False</property>
    
    360
    -                            <property name="receives_default">True</property>
    
    361
    -                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
    
    362
    -                            <property name="has_tooltip">True</property>
    
    363
    -                            <property name="relief">none</property>
    
    364
    -                            <property name="popup">formattings_menu</property>
    
    365 359
                                 <child>
    
    366
    -                              <object class="GtkImage" id="image10">
    
    360
    +                              <object class="GtkMenuButton" id="formattings_button">
    
    361
    +                                <property name="visible">True</property>
    
    362
    +                                <property name="can_focus">True</property>
    
    363
    +                                <property name="focus_on_click">False</property>
    
    364
    +                                <property name="receives_default">True</property>
    
    365
    +                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
    
    366
    +                                <property name="has_tooltip">True</property>
    
    367
    +                                <property name="relief">none</property>
    
    368
    +                                <property name="popup">formattings_menu</property>
    
    369
    +                                <child>
    
    370
    +                                  <object class="GtkImage" id="image10">
    
    371
    +                                    <property name="visible">True</property>
    
    372
    +                                    <property name="can_focus">False</property>
    
    373
    +                                    <property name="icon_name">format-text-bold-symbolic</property>
    
    374
    +                                    <property name="icon_size">1</property>
    
    375
    +                                  </object>
    
    376
    +                                </child>
    
    377
    +                                <style>
    
    378
    +                                  <class name="chatcontrol-actionbar-button"/>
    
    379
    +                                </style>
    
    380
    +                              </object>
    
    381
    +                              <packing>
    
    382
    +                                <property name="expand">False</property>
    
    383
    +                                <property name="fill">True</property>
    
    384
    +                                <property name="position">5</property>
    
    385
    +                              </packing>
    
    386
    +                            </child>
    
    387
    +                            <child>
    
    388
    +                              <placeholder/>
    
    389
    +                            </child>
    
    390
    +                            <child>
    
    391
    +                              <object class="GtkComboBox" id="label_selector">
    
    367 392
                                     <property name="visible">True</property>
    
    368 393
                                     <property name="can_focus">False</property>
    
    369
    -                                <property name="icon_name">format-text-bold-symbolic</property>
    
    370
    -                                <property name="icon_size">1</property>
    
    394
    +                                <property name="no_show_all">True</property>
    
    371 395
                                   </object>
    
    396
    +                              <packing>
    
    397
    +                                <property name="expand">False</property>
    
    398
    +                                <property name="fill">True</property>
    
    399
    +                                <property name="position">7</property>
    
    400
    +                              </packing>
    
    372 401
                                 </child>
    
    373
    -                            <style>
    
    374
    -                              <class name="chatcontrol-actionbar-button"/>
    
    375
    -                            </style>
    
    376
    -                          </object>
    
    377
    -                          <packing>
    
    378
    -                            <property name="expand">False</property>
    
    379
    -                            <property name="fill">True</property>
    
    380
    -                            <property name="position">5</property>
    
    381
    -                          </packing>
    
    382
    -                        </child>
    
    383
    -                        <child>
    
    384
    -                          <placeholder/>
    
    385
    -                        </child>
    
    386
    -                        <child>
    
    387
    -                          <object class="GtkComboBox" id="label_selector">
    
    388
    -                            <property name="visible">True</property>
    
    389
    -                            <property name="can_focus">False</property>
    
    390
    -                            <property name="no_show_all">True</property>
    
    391 402
                               </object>
    
    392 403
                               <packing>
    
    393 404
                                 <property name="expand">False</property>
    
    394
    -                            <property name="fill">True</property>
    
    395
    -                            <property name="position">7</property>
    
    405
    +                            <property name="fill">False</property>
    
    406
    +                            <property name="position">4</property>
    
    396 407
                               </packing>
    
    397 408
                             </child>
    
    398 409
                           </object>
    
    399 410
                           <packing>
    
    400
    -                        <property name="expand">False</property>
    
    401
    -                        <property name="fill">False</property>
    
    402
    -                        <property name="position">4</property>
    
    411
    +                        <property name="index">-1</property>
    
    403 412
                           </packing>
    
    404 413
                         </child>
    
    405 414
                       </object>
    
    406 415
                       <packing>
    
    407
    -                    <property name="index">-1</property>
    
    416
    +                    <property name="resize">False</property>
    
    417
    +                    <property name="shrink">False</property>
    
    418
    +                  </packing>
    
    419
    +                </child>
    
    420
    +                <child>
    
    421
    +                  <object class="GtkScrolledWindow" id="list_scrolledwindow">
    
    422
    +                    <property name="width_request">100</property>
    
    423
    +                    <property name="visible">True</property>
    
    424
    +                    <property name="can_focus">True</property>
    
    425
    +                    <property name="no_show_all">True</property>
    
    426
    +                    <property name="margin_left">4</property>
    
    427
    +                    <property name="margin_bottom">5</property>
    
    428
    +                    <property name="hscrollbar_policy">never</property>
    
    429
    +                    <property name="shadow_type">in</property>
    
    430
    +                    <child>
    
    431
    +                      <object class="GtkTreeView" id="list_treeview">
    
    432
    +                        <property name="visible">True</property>
    
    433
    +                        <property name="can_focus">True</property>
    
    434
    +                        <property name="border_width">1</property>
    
    435
    +                        <property name="headers_visible">False</property>
    
    436
    +                        <child internal-child="selection">
    
    437
    +                          <object class="GtkTreeSelection" id="treeview-selection1"/>
    
    438
    +                        </child>
    
    439
    +                      </object>
    
    440
    +                    </child>
    
    441
    +                    <style>
    
    442
    +                      <class name="scrolled-no-border"/>
    
    443
    +                      <class name="no-scroll-indicator"/>
    
    444
    +                    </style>
    
    445
    +                  </object>
    
    446
    +                  <packing>
    
    447
    +                    <property name="resize">False</property>
    
    448
    +                    <property name="shrink">False</property>
    
    408 449
                       </packing>
    
    409 450
                     </child>
    
    410 451
                   </object>
    
    411 452
                   <packing>
    
    412
    -                <property name="resize">False</property>
    
    413
    -                <property name="shrink">False</property>
    
    453
    +                <property name="expand">True</property>
    
    454
    +                <property name="fill">True</property>
    
    455
    +                <property name="position">1</property>
    
    414 456
                   </packing>
    
    415 457
                 </child>
    
    458
    +          </object>
    
    459
    +          <packing>
    
    460
    +            <property name="name">groupchat</property>
    
    461
    +          </packing>
    
    462
    +        </child>
    
    463
    +        <child>
    
    464
    +          <object class="GtkBox">
    
    465
    +            <property name="visible">True</property>
    
    466
    +            <property name="can_focus">False</property>
    
    467
    +            <property name="orientation">vertical</property>
    
    416 468
                 <child>
    
    417
    -              <object class="GtkScrolledWindow" id="list_scrolledwindow">
    
    418
    -                <property name="width_request">100</property>
    
    469
    +              <object class="GtkSpinner" id="spinner">
    
    419 470
                     <property name="visible">True</property>
    
    420
    -                <property name="can_focus">True</property>
    
    421
    -                <property name="no_show_all">True</property>
    
    422
    -                <property name="margin_left">4</property>
    
    423
    -                <property name="margin_bottom">5</property>
    
    424
    -                <property name="hscrollbar_policy">never</property>
    
    425
    -                <property name="shadow_type">in</property>
    
    471
    +                <property name="can_focus">False</property>
    
    472
    +                <property name="halign">center</property>
    
    473
    +                <property name="valign">center</property>
    
    474
    +                <property name="vexpand">True</property>
    
    475
    +              </object>
    
    476
    +              <packing>
    
    477
    +                <property name="expand">False</property>
    
    478
    +                <property name="fill">True</property>
    
    479
    +                <property name="position">0</property>
    
    480
    +              </packing>
    
    481
    +            </child>
    
    482
    +          </object>
    
    483
    +          <packing>
    
    484
    +            <property name="name">progress</property>
    
    485
    +            <property name="position">1</property>
    
    486
    +          </packing>
    
    487
    +        </child>
    
    488
    +        <child>
    
    489
    +          <object class="GtkBox">
    
    490
    +            <property name="visible">True</property>
    
    491
    +            <property name="can_focus">False</property>
    
    492
    +            <property name="orientation">vertical</property>
    
    493
    +            <child>
    
    494
    +              <object class="GtkGrid">
    
    495
    +                <property name="visible">True</property>
    
    496
    +                <property name="can_focus">False</property>
    
    497
    +                <property name="halign">center</property>
    
    498
    +                <property name="valign">center</property>
    
    499
    +                <property name="hexpand">True</property>
    
    500
    +                <property name="vexpand">True</property>
    
    501
    +                <property name="row_spacing">12</property>
    
    426 502
                     <child>
    
    427
    -                  <object class="GtkTreeView" id="list_treeview">
    
    503
    +                  <object class="GtkLabel">
    
    504
    +                    <property name="visible">True</property>
    
    505
    +                    <property name="can_focus">False</property>
    
    506
    +                    <property name="label" translatable="yes">Enter new nickname</property>
    
    507
    +                    <property name="xalign">0</property>
    
    508
    +                    <style>
    
    509
    +                      <class name="bold16"/>
    
    510
    +                    </style>
    
    511
    +                  </object>
    
    512
    +                  <packing>
    
    513
    +                    <property name="left_attach">0</property>
    
    514
    +                    <property name="top_attach">0</property>
    
    515
    +                  </packing>
    
    516
    +                </child>
    
    517
    +                <child>
    
    518
    +                  <object class="GtkEntry" id="nickname_entry">
    
    519
    +                    <property name="width_request">200</property>
    
    428 520
                         <property name="visible">True</property>
    
    429 521
                         <property name="can_focus">True</property>
    
    430
    -                    <property name="border_width">1</property>
    
    431
    -                    <property name="headers_visible">False</property>
    
    432
    -                    <child internal-child="selection">
    
    433
    -                      <object class="GtkTreeSelection" id="treeview-selection1"/>
    
    522
    +                    <property name="activates_default">True</property>
    
    523
    +                    <property name="caps_lock_warning">False</property>
    
    524
    +                    <property name="show_emoji_icon">True</property>
    
    525
    +                    <signal name="notify::text" handler="_on_nickname_text_changed" swapped="no"/>
    
    526
    +                  </object>
    
    527
    +                  <packing>
    
    528
    +                    <property name="left_attach">0</property>
    
    529
    +                    <property name="top_attach">1</property>
    
    530
    +                  </packing>
    
    531
    +                </child>
    
    532
    +                <child>
    
    533
    +                  <object class="GtkBox">
    
    534
    +                    <property name="visible">True</property>
    
    535
    +                    <property name="can_focus">False</property>
    
    536
    +                    <property name="homogeneous">True</property>
    
    537
    +                    <child>
    
    538
    +                      <object class="GtkButton">
    
    539
    +                        <property name="label" translatable="yes">_Cancel</property>
    
    540
    +                        <property name="visible">True</property>
    
    541
    +                        <property name="can_focus">True</property>
    
    542
    +                        <property name="receives_default">True</property>
    
    543
    +                        <property name="halign">start</property>
    
    544
    +                        <property name="valign">start</property>
    
    545
    +                        <property name="use_underline">True</property>
    
    546
    +                        <signal name="clicked" handler="_on_nickname_cancel_clicked" swapped="no"/>
    
    547
    +                      </object>
    
    548
    +                      <packing>
    
    549
    +                        <property name="expand">False</property>
    
    550
    +                        <property name="fill">True</property>
    
    551
    +                        <property name="position">0</property>
    
    552
    +                      </packing>
    
    553
    +                    </child>
    
    554
    +                    <child>
    
    555
    +                      <object class="GtkButton" id="nickname_change_button">
    
    556
    +                        <property name="label" translatable="yes">Ch_ange</property>
    
    557
    +                        <property name="visible">True</property>
    
    558
    +                        <property name="sensitive">False</property>
    
    559
    +                        <property name="can_focus">True</property>
    
    560
    +                        <property name="can_default">True</property>
    
    561
    +                        <property name="receives_default">True</property>
    
    562
    +                        <property name="halign">end</property>
    
    563
    +                        <property name="valign">start</property>
    
    564
    +                        <property name="use_underline">True</property>
    
    565
    +                        <signal name="clicked" handler="_on_nickname_change_clicked" swapped="no"/>
    
    566
    +                        <style>
    
    567
    +                          <class name="suggested-action"/>
    
    568
    +                        </style>
    
    569
    +                      </object>
    
    570
    +                      <packing>
    
    571
    +                        <property name="expand">False</property>
    
    572
    +                        <property name="fill">True</property>
    
    573
    +                        <property name="position">1</property>
    
    574
    +                      </packing>
    
    434 575
                         </child>
    
    435 576
                       </object>
    
    577
    +                  <packing>
    
    578
    +                    <property name="left_attach">0</property>
    
    579
    +                    <property name="top_attach">2</property>
    
    580
    +                  </packing>
    
    436 581
                     </child>
    
    437
    -                <style>
    
    438
    -                  <class name="scrolled-no-border"/>
    
    439
    -                  <class name="no-scroll-indicator"/>
    
    440
    -                </style>
    
    441 582
                   </object>
    
    442 583
                   <packing>
    
    443
    -                <property name="resize">False</property>
    
    444
    -                <property name="shrink">False</property>
    
    584
    +                <property name="expand">False</property>
    
    585
    +                <property name="fill">True</property>
    
    586
    +                <property name="position">0</property>
    
    445 587
                   </packing>
    
    446 588
                 </child>
    
    447 589
               </object>
    
    448 590
               <packing>
    
    449
    -            <property name="expand">True</property>
    
    450
    -            <property name="fill">True</property>
    
    451
    -            <property name="position">1</property>
    
    591
    +            <property name="name">nickname</property>
    
    592
    +            <property name="position">2</property>
    
    452 593
               </packing>
    
    453 594
             </child>
    
    454 595
           </object>
    

  • gajim/data/gui/shortcuts_window.ui
    ... ... @@ -109,7 +109,7 @@
    109 109
                 <child>
    
    110 110
                   <object class="GtkShortcutsShortcut">
    
    111 111
                     <property name="visible">1</property>
    
    112
    -                <property name="accelerator">&lt;alt&gt;Left  &lt;ctrl&gt;Page_Up</property>
    
    112
    +                <property name="accelerator">&lt;alt&gt;Left &lt;ctrl&gt;Page_Up</property>
    
    113 113
                     <property name="title" translatable="yes">Switch to the previous tab</property>
    
    114 114
                   </object>
    
    115 115
                 </child>
    
    ... ... @@ -121,13 +121,6 @@
    121 121
                   </object>
    
    122 122
                 </child>
    
    123 123
                 <child>
    
    124
    -              <object class="GtkShortcutsShortcut">
    
    125
    -                <property name="visible">1</property>
    
    126
    -                <property name="accelerator">&lt;Alt&gt;1...9</property>
    
    127
    -                <property name="title" translatable="yes">Switch to the first - ninth tab</property>
    
    128
    -              </object>
    
    129
    -            </child>
    
    130
    -              <child>
    
    131 124
                   <object class="GtkShortcutsShortcut">
    
    132 125
                     <property name="visible">1</property>
    
    133 126
                     <property name="accelerator">&lt;ctrl&gt;&lt;shift&gt;Tab</property>
    
    ... ... @@ -158,7 +151,7 @@
    158 151
                 <child>
    
    159 152
                   <object class="GtkShortcutsShortcut">
    
    160 153
                     <property name="visible">1</property>
    
    161
    -                <property name="accelerator">Escape &lt;ctrl&gt;w &lt;ctrl&gt;F4</property>
    
    154
    +                <property name="accelerator">Escape &lt;ctrl&gt;w</property>
    
    162 155
                     <property name="title" translatable="yes">Close chat</property>
    
    163 156
                   </object>
    
    164 157
                 </child>
    

  • gajim/groupchat_control.py
    ... ... @@ -33,7 +33,8 @@ import logging
    33 33
     from enum import IntEnum, unique
    
    34 34
     
    
    35 35
     import nbxmpp
    
    36
    -from nbxmpp.protocol import JID
    
    36
    +from nbxmpp.protocol import InvalidJid
    
    37
    +from nbxmpp.protocol import validate_resourcepart
    
    37 38
     from nbxmpp.const import StatusCode
    
    38 39
     from nbxmpp.const import Affiliation
    
    39 40
     from nbxmpp.const import Role
    
    ... ... @@ -76,7 +77,6 @@ from gajim.gtk.dialogs import ErrorDialog
    76 77
     from gajim.gtk.dialogs import InputTextDialog
    
    77 78
     from gajim.gtk.dialogs import DestroyMucDialog
    
    78 79
     from gajim.gtk.dialogs import InputDialog
    
    79
    -from gajim.gtk.dialogs import ChangeNickDialog
    
    80 80
     from gajim.gtk.single_message import SingleMessageWindow
    
    81 81
     from gajim.gtk.filechoosers import AvatarChooserDialog
    
    82 82
     from gajim.gtk.add_contact import AddNewContactWindow
    
    ... ... @@ -346,9 +346,14 @@ class GroupchatControl(ChatControlBase):
    346 346
             # disable win, we are not connected yet
    
    347 347
             ChatControlBase.got_disconnected(self)
    
    348 348
     
    
    349
    +        # Stack
    
    350
    +        self.xml.stack.show_all()
    
    351
    +        self.xml.stack.set_visible_child_name('groupchat')
    
    352
    +
    
    349 353
             self.update_ui()
    
    350 354
             self.widget.show_all()
    
    351 355
     
    
    356
    +
    
    352 357
             if app.config.get('hide_groupchat_occupants_list'):
    
    353 358
                 # Roster is shown by default, so toggle the roster button to hide it
    
    354 359
                 self.show_roster()
    
    ... ... @@ -361,11 +366,10 @@ class GroupchatControl(ChatControlBase):
    361 366
             super().add_actions()
    
    362 367
             actions = [
    
    363 368
                 ('change-subject-', self._on_change_subject),
    
    364
    -            ('change-nick-', self._on_change_nick),
    
    369
    +            ('change-nickname-', self._on_change_nick),
    
    365 370
                 ('disconnect-', self._on_disconnect),
    
    366 371
                 ('destroy-', self._on_destroy_room),
    
    367 372
                 ('configure-', self._on_configure_room),
    
    368
    -            ('bookmark-', self._on_bookmark_room),
    
    369 373
                 ('request-voice-', self._on_request_voice),
    
    370 374
                 ('execute-command-', self._on_execute_command),
    
    371 375
                 ('upload-avatar-', self._on_upload_avatar),
    
    ... ... @@ -466,12 +470,6 @@ class GroupchatControl(ChatControlBase):
    466 470
                 self.is_connected and contact.affiliation in (Affiliation.ADMIN,
    
    467 471
                                                               Affiliation.OWNER))
    
    468 472
     
    
    469
    -        # Bookmarks
    
    470
    -        con = app.connections[self.account]
    
    471
    -        bookmarked = con.get_module('Bookmarks').is_bookmark(self.room_jid)
    
    472
    -        self._get_action('bookmark-').set_enabled(self.is_connected and
    
    473
    -                                                  not bookmarked)
    
    474
    -
    
    475 473
             # Request Voice
    
    476 474
             role = self.get_role(self.nick)
    
    477 475
             self._get_action('request-voice-').set_enabled(self.is_connected and
    
    ... ... @@ -486,7 +484,7 @@ class GroupchatControl(ChatControlBase):
    486 484
                                                             subject)
    
    487 485
     
    
    488 486
             # Change Nick
    
    489
    -        self._get_action('change-nick-').set_enabled(self.is_connected)
    
    487
    +        self._get_action('change-nickname-').set_enabled(self.is_connected)
    
    490 488
     
    
    491 489
             # Execute command
    
    492 490
             self._get_action('execute-command-').set_enabled(self.is_connected)
    
    ... ... @@ -537,6 +535,15 @@ class GroupchatControl(ChatControlBase):
    537 535
             win = self.parent_win.window
    
    538 536
             return win.lookup_action(name + self.control_id)
    
    539 537
     
    
    538
    +    def _show_page(self, name):
    
    539
    +        transition = Gtk.StackTransitionType.SLIDE_DOWN
    
    540
    +        if name == 'groupchat':
    
    541
    +            transition = Gtk.StackTransitionType.SLIDE_UP
    
    542
    +        self.xml.stack.set_visible_child_full(name, transition)
    
    543
    +
    
    544
    +    def _get_current_page(self):
    
    545
    +        return self.xml.stack.get_visible_child_name()
    
    546
    +
    
    540 547
         def _cell_data_func(self, column, renderer, model, iter_, user_data):
    
    541 548
             # Background color has to be rendered for all cells
    
    542 549
             theme = app.config.get('roster_theme')
    
    ... ... @@ -632,16 +639,6 @@ class GroupchatControl(ChatControlBase):
    632 639
                 _('Please specify the new subject:'), input_str=self.subject,
    
    633 640
                 ok_handler=on_ok, transient_for=self.parent_win.window)
    
    634 641
     
    
    635
    -    def _on_change_nick(self, action, param):
    
    636
    -        if 'change_nick_dialog' in app.interface.instances:
    
    637
    -            app.interface.instances['change_nick_dialog'].dialog.present()
    
    638
    -        else:
    
    639
    -            title = _('Changing Nickname')
    
    640
    -            prompt = _('Please specify the new nickname you want to use:')
    
    641
    -            app.interface.instances['change_nick_dialog'] = \
    
    642
    -                ChangeNickDialog(self.account, self.room_jid, title,
    
    643
    -                prompt, change_nick=True, transient_for=self.parent_win.window)
    
    644
    -
    
    645 642
         def _on_disconnect(self, action, param):
    
    646 643
             app.connections[self.account].get_module('MUC').leave(self.room_jid)
    
    647 644
             self.force_non_minimizable = True
    
    ... ... @@ -700,19 +697,6 @@ class GroupchatControl(ChatControlBase):
    700 697
             app.config.set_per('rooms', self.contact.jid,
    
    701 698
                                'print_status', param.get_boolean())
    
    702 699
     
    
    703
    -    def _on_bookmark_room(self, action, param):
    
    704
    -        """
    
    705
    -        Bookmark the room, without autojoin and not minimized
    
    706
    -        """
    
    707
    -        password = app.gc_passwords.get(self.room_jid, '')
    
    708
    -        con = app.connections[self.account]
    
    709
    -        con.get_module('Bookmarks').add_bookmark(self.name,
    
    710
    -                                                 JID(self.room_jid),
    
    711
    -                                                 True,
    
    712
    -                                                 password,
    
    713
    -                                                 self.nick)
    
    714
    -        self.update_actions()
    
    715
    -
    
    716 700
         def _on_request_voice(self, action, param):
    
    717 701
             """
    
    718 702
             Request voice in the current room
    
    ... ... @@ -2500,6 +2484,29 @@ class GroupchatControl(ChatControlBase):
    2500 2484
                     widget.get_selection().unselect_all()
    
    2501 2485
                     return True
    
    2502 2486
     
    
    2487
    +    def delegate_action(self, action):
    
    2488
    +        res = super().delegate_action(action)
    
    2489
    +        if res == Gdk.EVENT_STOP:
    
    2490
    +            return res
    
    2491
    +
    
    2492
    +        if action == 'change-nickname':
    
    2493
    +            control_action = '%s-%s' % (action, self.control_id)
    
    2494
    +            self.parent_win.window.lookup_action(control_action).activate()
    
    2495
    +            return Gdk.EVENT_STOP
    
    2496
    +
    
    2497
    +        if action == 'escape':
    
    2498
    +            if self._get_current_page() == 'groupchat':
    
    2499
    +                return Gdk.EVENT_PROPAGATE
    
    2500
    +            self._show_page('groupchat')
    
    2501
    +            return Gdk.EVENT_STOP
    
    2502
    +
    
    2503
    +        if action == 'change-subject':
    
    2504
    +            control_action = '%s-%s' % (action, self.control_id)
    
    2505
    +            self.parent_win.window.lookup_action(control_action).activate()
    
    2506
    +            return Gdk.EVENT_STOP
    
    2507
    +
    
    2508
    +        return Gdk.EVENT_PROPAGATE
    
    2509
    +
    
    2503 2510
         def on_list_treeview_row_expanded(self, widget, iter_, path):
    
    2504 2511
             """
    
    2505 2512
             When a row is expanded: change the icon of the arrow
    
    ... ... @@ -2941,6 +2948,33 @@ class GroupchatControl(ChatControlBase):
    2941 2948
             else:
    
    2942 2949
                 self.revoke_owner(widget, jid)
    
    2943 2950
     
    
    2951
    +    def _on_change_nick(self, _action, _param):
    
    2952
    +        self.xml.nickname_entry.set_text(self.nick)
    
    2953
    +        self.xml.nickname_entry.grab_focus()
    
    2954
    +        self.xml.nickname_change_button.grab_default()
    
    2955
    +        self._show_page('nickname')
    
    2956
    +
    
    2957
    +    def _on_nickname_text_changed(self, entry, _param):
    
    2958
    +        text = entry.get_text()
    
    2959
    +        if not text or text == self.nick:
    
    2960
    +            self.xml.nickname_change_button.set_sensitive(False)
    
    2961
    +        else:
    
    2962
    +            try:
    
    2963
    +                validate_resourcepart(text)
    
    2964
    +            except InvalidJid:
    
    2965
    +                self.xml.nickname_change_button.set_sensitive(False)
    
    2966
    +            else:
    
    2967
    +                self.xml.nickname_change_button.set_sensitive(True)
    
    2968
    +
    
    2969
    +    def _on_nickname_change_clicked(self, _button):
    
    2970
    +        new_nick = self.xml.nickname_entry.get_text()
    
    2971
    +        app.connections[self.account].get_module('MUC').change_nick(
    
    2972
    +            self.room_jid, new_nick)
    
    2973
    +        self._show_page('groupchat')
    
    2974
    +
    
    2975
    +    def _on_nickname_cancel_clicked(self, _button):
    
    2976
    +        self._show_page('groupchat')
    
    2977
    +
    
    2944 2978
     
    
    2945 2979
     class SubjectPopover(Gtk.Popover):
    
    2946 2980
         def __init__(self):
    

  • gajim/gtk/dialogs.py
    ... ... @@ -22,7 +22,6 @@ from gi.repository import Gdk
    22 22
     from gi.repository import Pango
    
    23 23
     
    
    24 24
     from gajim.common import app
    
    25
    -from gajim.common import helpers
    
    26 25
     from gajim.common.i18n import _
    
    27 26
     from gajim.common.const import ButtonAction
    
    28 27
     
    
    ... ... @@ -526,91 +525,6 @@ class InputDialogCheck(InputDialog):
    526 525
                 return False
    
    527 526
     
    
    528 527
     
    
    529
    -class ChangeNickDialog(InputDialogCheck):
    
    530
    -    """
    
    531
    -    Class for changing room nickname in case of conflict
    
    532
    -    """
    
    533
    -
    
    534
    -    def __init__(self, account, room_jid, title, prompt, check_text=None,
    
    535
    -                 change_nick=False, transient_for=None):
    
    536
    -        """
    
    537
    -        change_nick must be set to True when we are already occupant of the room
    
    538
    -        and we are changing our nick
    
    539
    -        """
    
    540
    -        InputDialogCheck.__init__(self, title, '',
    
    541
    -                                  input_str='', is_modal=True, ok_handler=None,
    
    542
    -                                  cancel_handler=None,
    
    543
    -                                  transient_for=transient_for)
    
    544
    -        self.room_queue = [(account, room_jid, prompt, change_nick)]
    
    545
    -        self.check_next()
    
    546
    -
    
    547
    -    def on_input_dialog_delete_event(self, widget, event):
    
    548
    -        self.on_cancelbutton_clicked(widget)
    
    549
    -        return True
    
    550
    -
    
    551
    -    def setup_dialog(self):
    
    552
    -        self.gc_control = app.interface.msg_win_mgr.get_gc_control(
    
    553
    -                self.room_jid, self.account)
    
    554
    -        if not self.gc_control and \
    
    555
    -        self.room_jid in app.interface.minimized_controls[self.account]:
    
    556
    -            self.gc_control = \
    
    557
    -                app.interface.minimized_controls[self.account][self.room_jid]
    
    558
    -        if not self.gc_control:
    
    559
    -            self.check_next()
    
    560
    -            return
    
    561
    -        label = self.xml.get_object('label')
    
    562
    -        label.set_markup(self.prompt)
    
    563
    -        self.set_entry(self.gc_control.nick + \
    
    564
    -                app.config.get('gc_proposed_nick_char'))
    
    565
    -
    
    566
    -    def check_next(self):
    
    567
    -        if not self.room_queue:
    
    568
    -            self.cancel_handler = None
    
    569
    -            self.dialog.destroy()
    
    570
    -            if 'change_nick_dialog' in app.interface.instances:
    
    571
    -                del app.interface.instances['change_nick_dialog']
    
    572
    -            return
    
    573
    -        self.account, self.room_jid, self.prompt, self.change_nick = \
    
    574
    -            self.room_queue.pop(0)
    
    575
    -        self.setup_dialog()
    
    576
    -        self.dialog.show()
    
    577
    -
    
    578
    -    def on_okbutton_clicked(self, widget):
    
    579
    -        nick = self.get_text()
    
    580
    -        if nick:
    
    581
    -            nick = nick
    
    582
    -        # send presence to room
    
    583
    -        try:
    
    584
    -            nick = helpers.parse_resource(nick)
    
    585
    -        except Exception:
    
    586
    -            # invalid char
    
    587
    -            ErrorDialog(_('Invalid nickname'),
    
    588
    -                    _('The nickname contains invalid characters.'))
    
    589
    -            return
    
    590
    -        self.on_ok(nick, self.is_checked())
    
    591
    -
    
    592
    -    def on_ok(self, nick, is_checked):
    
    593
    -        app.connections[self.account].get_module('MUC').change_nick(
    
    594
    -            self.room_jid, nick)
    
    595
    -        if app.gc_connected[self.account][self.room_jid]:
    
    596
    -            # We are changing nick, we will change self.nick when we receive
    
    597
    -            # presence that inform that it works
    
    598
    -            self.gc_control.new_nick = nick
    
    599
    -        else:
    
    600
    -            # We are connecting, we will not get a changed nick presence so
    
    601
    -            # change it NOW. We don't already have a nick so it's harmless
    
    602
    -            self.gc_control.nick = nick
    
    603
    -        self.check_next()
    
    604
    -
    
    605
    -    def on_cancelbutton_clicked(self, widget):
    
    606
    -        self.gc_control.new_nick = ''
    
    607
    -        self.check_next()
    
    608
    -
    
    609
    -    def add_room(self, account, room_jid, prompt, change_nick=False):
    
    610
    -        if (account, room_jid, prompt, change_nick) not in self.room_queue:
    
    611
    -            self.room_queue.append((account, room_jid, prompt, change_nick))
    
    612
    -
    
    613
    -
    
    614 528
     class InputTextDialog(CommonInputDialog):
    
    615 529
         """
    
    616 530
         Class for multilines Input dialog (more place than InputDialog)
    

  • gajim/gtk/discovery.py
    ... ... @@ -46,7 +46,6 @@ import weakref
    46 46
     import uuid
    
    47 47
     
    
    48 48
     import nbxmpp
    
    49
    -from nbxmpp.protocol import JID
    
    50 49
     from nbxmpp.util import is_error_result
    
    51 50
     from nbxmpp.structs import DiscoIdentity
    
    52 51
     
    
    ... ... @@ -61,7 +60,6 @@ from gajim.common.const import StyleAttr
    61 60
     
    
    62 61
     from gajim.gtk.adhoc import AdHocCommand
    
    63 62
     from gajim.gtk.dialogs import ErrorDialog
    
    64
    -from gajim.gtk.dialogs import InformationDialog
    
    65 63
     from gajim.gtk.search import Search
    
    66 64
     from gajim.gtk.service_registration import ServiceRegistration
    
    67 65
     from gajim.gtk.util import icon_exists
    
    ... ... @@ -1637,7 +1635,6 @@ class MucBrowser(AgentBrowser):
    1637 1635
         def __init__(self, *args, **kwargs):
    
    1638 1636
             AgentBrowser.__init__(self, *args, **kwargs)
    
    1639 1637
             self.join_button = None
    
    1640
    -        self.bookmark_button = None
    
    1641 1638
     
    
    1642 1639
         def _create_treemodel(self):
    
    1643 1640
             # JID, node, name, users_int, users_str, description, fetched
    
    ... ... @@ -1703,55 +1700,16 @@ class MucBrowser(AgentBrowser):
    1703 1700
             AgentBrowser._clean_treemodel(self)
    
    1704 1701
     
    
    1705 1702
         def _add_actions(self):
    
    1706
    -        self.bookmark_button = Gtk.Button(label=_('_Bookmark'),
    
    1707
    -                                          use_underline=True)
    
    1708
    -        self.bookmark_button.connect(
    
    1709
    -            'clicked', self._on_bookmark_button_clicked)
    
    1710
    -        image = Gtk.Image.new_from_icon_name(
    
    1711
    -            'bookmark-new-symbolic', Gtk.IconSize.BUTTON)
    
    1712
    -        self.bookmark_button.set_image(image)
    
    1713
    -        self.window.action_buttonbox.add(self.bookmark_button)
    
    1714
    -        self.bookmark_button.show_all()
    
    1715 1703
             self.join_button = Gtk.Button(label=_('_Join'), use_underline=True)
    
    1716 1704
             self.join_button.connect('clicked', self._on_join_button_clicked)
    
    1717 1705
             self.window.action_buttonbox.add(self.join_button)
    
    1718 1706
             self.join_button.show_all()
    
    1719 1707
     
    
    1720 1708
         def _clean_actions(self):
    
    1721
    -        if self.bookmark_button:
    
    1722
    -            self.bookmark_button.destroy()
    
    1723
    -            self.bookmark_button = None
    
    1724 1709
             if self.join_button:
    
    1725 1710
                 self.join_button.destroy()
    
    1726 1711
                 self.join_button = None
    
    1727 1712
     
    
    1728
    -    def _on_bookmark_button_clicked(self, *args):
    
    1729
    -        con = app.connections[self.account]
    
    1730
    -        model, iter_ = \
    
    1731
    -            self.window.services_treeview.get_selection().get_selected()
    
    1732
    -        if not iter_:
    
    1733
    -            return
    
    1734
    -
    
    1735
    -        room_jid = model[iter_][0]
    
    1736
    -        if con.get_module('Bookmarks').is_bookmark(room_jid):
    
    1737
    -            ErrorDialog(
    
    1738
    -                _('Bookmark already set'),
    
    1739
    -                _('Group Chat \'%s\' is already in your bookmarks.') % room_jid,
    
    1740
    -                transient_for=self.window.window)
    
    1741
    -            return
    
    1742
    -
    
    1743
    -        con.get_module('Bookmarks').add_bookmark(room_jid.split('@')[0],
    
    1744
    -                                                 JID(room_jid),
    
    1745
    -                                                 False,
    
    1746
    -                                                 '',
    
    1747
    -                                                 '')
    
    1748
    -
    
    1749
    -        InformationDialog(
    
    1750
    -            _('Bookmark has been added successfully'),
    
    1751
    -            _('You can manage your bookmarks by clicking the Bookmarks menu '
    
    1752
    -              'item in your contact list.'),
    
    1753
    -            transient_for=self.window.window)
    
    1754
    -
    
    1755 1713
         def _on_join_button_clicked(self, *args):
    
    1756 1714
             """
    
    1757 1715
             When we want to join a conference: ask specific informations about the
    
    ... ... @@ -1773,8 +1731,6 @@ class MucBrowser(AgentBrowser):
    1773 1731
         def update_actions(self):
    
    1774 1732
             sens = \
    
    1775 1733
                 self.window.services_treeview.get_selection().count_selected_rows()
    
    1776
    -        if self.bookmark_button:
    
    1777
    -            self.bookmark_button.set_sensitive(sens > 0)
    
    1778 1734
             if self.join_button:
    
    1779 1735
                 self.join_button.set_sensitive(sens > 0)
    
    1780 1736
     
    

  • gajim/gui_menu_builder.py
    ... ... @@ -594,7 +594,7 @@ def get_groupchat_menu(control_id, account, jid):
    594 594
                 (_('Send Chatstate'), ['chatstate']),
    
    595 595
             ]),
    
    596 596
             (_('Sync Threshold'), ['sync']),
    
    597
    -        ('win.change-nick-', _('Change Nick')),
    
    597
    +        ('win.change-nickname-', _('Change Nick')),
    
    598 598
             ('win.request-voice-', _('Request Voice')),
    
    599 599
             ('win.execute-command-', _('Execute command')),
    
    600 600
             ('app.browse-history', _('History')),
    

  • gajim/message_window.py
    ... ... @@ -23,12 +23,13 @@
    23 23
     # You should have received a copy of the GNU General Public License
    
    24 24
     # along with Gajim. If not, see <http://www.gnu.org/licenses/>.
    
    25 25
     
    
    26
    -import time
    
    26
    +import logging
    
    27 27
     
    
    28 28
     from gi.repository import Gtk
    
    29 29
     from gi.repository import Gdk
    
    30 30
     from gi.repository import GObject
    
    31 31
     from gi.repository import GLib
    
    32
    +from gi.repository import Gio
    
    32 33
     
    
    33 34
     from gajim import common
    
    34 35
     from gajim.common import app
    
    ... ... @@ -49,6 +50,9 @@ from gajim.gtk.util import get_app_icon_list
    49 50
     from gajim.gtk.util import get_builder
    
    50 51
     from gajim.gtk.util import set_urgency_hint
    
    51 52
     
    
    53
    +
    
    54
    +log = logging.getLogger('gajim.message_window')
    
    55
    +
    
    52 56
     ####################
    
    53 57
     
    
    54 58
     class MessageWindow:
    
    ... ... @@ -119,19 +123,7 @@ class MessageWindow:
    119 123
             id_ = self.window.connect('focus-in-event', self._on_window_focus)
    
    120 124
             self.handlers[id_] = self.window
    
    121 125
     
    
    122
    -        keys = ['<Control>f', '<Control>g', '<Control>h', '<Control>i',
    
    123
    -                '<Control>l', '<Control>L', '<Control><Shift>n', '<Control>u',
    
    124
    -                '<Control>b', '<Control>F4',
    
    125
    -                '<Control><Shift>Page_Up', '<Control><Shift>Page_Down',
    
    126
    -                '<Control>w', '<Control>Page_Up', '<Control>Page_Down', '<Alt>Right',
    
    127
    -                '<Alt>Left', '<Alt>d', '<Alt>c', '<Alt>m', '<Alt>t', 'Escape'] + \
    
    128
    -                ['<Alt>'+str(i) for i in range(10)]
    
    129
    -        accel_group = Gtk.AccelGroup()
    
    130
    -        for key in keys:
    
    131
    -            keyval, mod = Gtk.accelerator_parse(key)
    
    132
    -            accel_group.connect(keyval, mod, Gtk.AccelFlags.VISIBLE,
    
    133
    -                self.accel_group_func)
    
    134
    -        self.window.add_accel_group(accel_group)
    
    126
    +        self._add_actions()
    
    135 127
     
    
    136 128
             # gtk+ doesn't make use of the motion notify on gtkwindow by default
    
    137 129
             # so this line adds that
    
    ... ... @@ -164,6 +156,118 @@ class MessageWindow:
    164 156
             self.notebook.set_show_border(app.config.get('tabs_border'))
    
    165 157
             self.show_icon()
    
    166 158
     
    
    159
    +    def _add_actions(self):
    
    160
    +        actions = [
    
    161
    +            ('change-nickname', ['<Control><Shift>n']),
    
    162
    +            ('change-subject', ['<Alt>t']),
    
    163
    +            ('escape', ['Escape']),
    
    164
    +            ('browse-history', ['<Control>h']),
    
    165
    +            ('send-file', ['<Control>f']),
    
    166
    +            ('show-contact-info', ['<Control>i']),
    
    167
    +            ('show-emoji-chooser', ['<Alt>m']),
    
    168
    +            ('clear-chat', ['<Control>l']),
    
    169
    +            ('delete-line', ['<Control>u']),
    
    170
    +            ('close-tab', ['<Control>w']),
    
    171
    +            ('move-tab-up', ['<Control><Shift>Page_Up']),
    
    172
    +            ('move-tab-down', ['<Control><Shift>Page_Down']),
    
    173
    +            ('switch-next-tab', ['<Alt>Right']),
    
    174
    +            ('switch-prev-tab', ['<Alt>Left']),
    
    175
    +            ('switch-next-unread-tab-right', ['<Control>Tab',
    
    176
    +                                              '<Control>Page_Down']),
    
    177
    +            ('switch-next-unread-tab-left', ['<Control>ISO_Left_Tab',
    
    178
    +                                             '<Control>Page_Up']),
    
    179
    +        ]
    
    180
    +
    
    181
    +        disabled_for_emacs = (
    
    182
    +            'browse-history',
    
    183
    +            'send-file',
    
    184
    +            'close-tab'
    
    185
    +        )
    
    186
    +
    
    187
    +        key_theme = Gtk.Settings.get_default().get_property(
    
    188
    +            'gtk-key-theme-name')
    
    189
    +
    
    190
    +        for action, keys in actions:
    
    191
    +            if key_theme == 'Emacs' and action in disabled_for_emacs:
    
    192
    +                continue
    
    193
    +            act = Gio.SimpleAction.new(action, None)
    
    194
    +            act.connect('activate', self._on_action)
    
    195
    +            self.window.add_action(act)
    
    196
    +            app.app.set_accels_for_action('win.%s' % action, keys)
    
    197
    +
    
    198
    +    def _on_action(self, action, _param):
    
    199
    +        control = self.get_active_control()
    
    200
    +        if not control:
    
    201
    +            # No more control in this window
    
    202
    +            return
    
    203
    +
    
    204
    +        log.info('Activate action: %s, active control: %s',
    
    205
    +                 action.get_name(), control.contact.jid)
    
    206
    +
    
    207
    +        action = action.get_name()
    
    208
    +
    
    209
    +        # Pass the event to the control
    
    210
    +        res = control.delegate_action(action)
    
    211
    +        if res != Gdk.EVENT_PROPAGATE:
    
    212
    +            return res
    
    213
    +
    
    214
    +        if action == 'escape' and app.config.get('escape_key_closes'):
    
    215
    +            self.remove_tab(control, self.CLOSE_ESC)
    
    216
    +            return
    
    217
    +
    
    218
    +        if action == 'close-tab':
    
    219
    +            self.remove_tab(control, self.CLOSE_CTRL_KEY)
    
    220
    +            return
    
    221
    +
    
    222
    +        if action == 'move-tab-up':
    
    223
    +            old_position = self.notebook.get_current_page()
    
    224
    +            self.notebook.reorder_child(control.widget,
    
    225
    +                                        old_position - 1)
    
    226
    +            return
    
    227
    +
    
    228
    +        if action == 'move-tab-down':
    
    229
    +            old_position = self.notebook.get_current_page()
    
    230
    +            total_pages = self.notebook.get_n_pages()
    
    231
    +            if old_position == total_pages - 1:
    
    232
    +                self.notebook.reorder_child(control.widget, 0)
    
    233
    +            else:
    
    234
    +                self.notebook.reorder_child(control.widget,
    
    235
    +                                            old_position + 1)
    
    236
    +            return
    
    237
    +
    
    238
    +        if action == 'switch-next-tab':
    
    239
    +            new = self.notebook.get_current_page() + 1
    
    240
    +            if new >= self.notebook.get_n_pages():
    
    241
    +                new = 0
    
    242
    +            self.notebook.set_current_page(new)
    
    243
    +            return
    
    244
    +
    
    245
    +        if action == 'switch-prev-tab':
    
    246
    +            new = self.notebook.get_current_page() - 1
    
    247
    +            if new < 0:
    
    248
    +                new = self.notebook.get_n_pages() - 1
    
    249
    +            self.notebook.set_current_page(new)
    
    250
    +            return
    
    251
    +
    
    252
    +        if action == 'switch-next-unread-tab-right':
    
    253
    +            self.move_to_next_unread_tab(True)
    
    254
    +            return
    
    255
    +
    
    256
    +        if action == 'switch-next-unread-tab-left':
    
    257
    +            self.move_to_next_unread_tab(False)
    
    258
    +            return
    
    259
    +
    
    260
    +    def _on_notebook_key_press(self, _widget, event):
    
    261
    +        control = self.get_active_control()
    
    262
    +        if control is None:
    
    263
    +            return
    
    264
    +
    
    265
    +        if isinstance(control, ChatControlBase):
    
    266
    +            # we forwarded it to message textview
    
    267
    +            control.msg_textview.remove_placeholder()
    
    268
    +            control.msg_textview.event(event)
    
    269
    +            control.msg_textview.grab_focus()
    
    270
    +
    
    167 271
         def change_account_name(self, old_name, new_name):
    
    168 272
             if old_name in self._controls:
    
    169 273
                 self._controls[new_name] = self._controls[old_name]
    
    ... ... @@ -353,141 +457,6 @@ class MessageWindow:
    353 457
                 ctrl = self._widget_to_control(child)
    
    354 458
                 GLib.idle_add(ctrl.msg_textview.grab_focus)
    
    355 459
     
    
    356
    -    def accel_group_func(self, accel_group, acceleratable, keyval, modifier):
    
    357
    -        st = '1234567890' # alt+1 means the first tab (tab 0)
    
    358
    -        control = self.get_active_control()
    
    359
    -        if not control:
    
    360
    -            # No more control in this window
    
    361
    -            return
    
    362
    -
    
    363
    -        # CTRL mask
    
    364
    -        if modifier & Gdk.ModifierType.CONTROL_MASK:
    
    365
    -            if keyval == Gdk.KEY_h: # CTRL + h
    
    366
    -                if Gtk.Settings.get_default().get_property(
    
    367
    -                'gtk-key-theme-name') != 'Emacs':
    
    368
    -                    dict_ = {'jid': GLib.Variant('s', control.contact.jid),
    
    369
    -                             'account': GLib.Variant('s', control.account)}
    
    370
    -                    variant = GLib.Variant('a{sv}', dict_)
    
    371
    -                    app.app.activate_action('browse-history', variant)
    
    372
    -                    return True
    
    373
    -            elif control.type_id == message_control.TYPE_CHAT and \
    
    374
    -            keyval == Gdk.KEY_f: # CTRL + f
    
    375
    -                # CTRL + f moves cursor one char forward when user uses Emacs
    
    376
    -                # theme
    
    377
    -                if not Gtk.Settings.get_default().get_property(
    
    378
    -                'gtk-key-theme-name') == 'Emacs':
    
    379
    -                    if app.interface.msg_win_mgr.mode == \
    
    380
    -                    app.interface.msg_win_mgr.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER:
    
    381
    -                        app.interface.roster.tree.grab_focus()
    
    382
    -                        return False
    
    383
    -                    self.window.lookup_action(
    
    384
    -                        'send-file-%s' % control.control_id).activate()
    
    385
    -                    return True
    
    386
    -            elif control.type_id == message_control.TYPE_CHAT and \
    
    387
    -            keyval == Gdk.KEY_g: # CTRL + g
    
    388
    -                control._on_convert_to_gc_menuitem_activate(None)
    
    389
    -                return True
    
    390
    -            elif control.type_id in (message_control.TYPE_CHAT,
    
    391
    -            message_control.TYPE_PM) and keyval == Gdk.KEY_i: # CTRL + i
    
    392
    -                self.window.lookup_action(
    
    393
    -                    'information-%s' % control.control_id).activate()
    
    394
    -                return True
    
    395
    -            elif keyval in (Gdk.KEY_l, Gdk.KEY_L): # CTRL + l|L
    
    396
    -                control.conv_textview.clear()
    
    397
    -                return True
    
    398
    -            elif keyval == Gdk.KEY_u: # CTRL + u: emacs style clear line
    
    399
    -                control.clear(control.msg_textview)
    
    400
    -                return True
    
    401
    -            elif control.type_id == message_control.TYPE_GC and \
    
    402
    -            keyval == Gdk.KEY_b: # CTRL + b
    
    403
    -                # CTRL + b moves cursor one char backward when user uses Emacs
    
    404
    -                # theme
    
    405
    -                if not Gtk.Settings.get_default().get_property(
    
    406
    -                'gtk-key-theme-name') == 'Emacs':
    
    407
    -                    self.window.lookup_action(
    
    408
    -                        'bookmark-%s' % control.control_id).activate()
    
    409
    -                    return True
    
    410
    -            # Tab switch bindings
    
    411
    -            elif keyval == Gdk.KEY_F4: # CTRL + F4
    
    412
    -                self.remove_tab(control, self.CLOSE_CTRL_KEY)
    
    413
    -                return True
    
    414
    -            elif keyval == Gdk.KEY_w: # CTRL + w
    
    415
    -                # CTRL + w removes latest word before cursor when User uses emacs
    
    416
    -                # theme
    
    417
    -                if not Gtk.Settings.get_default().get_property(
    
    418
    -                'gtk-key-theme-name') == 'Emacs':
    
    419
    -                    self.remove_tab(control, self.CLOSE_CTRL_KEY)
    
    420
    -                    return True
    
    421
    -            elif keyval in (Gdk.KEY_Page_Up, Gdk.KEY_Page_Down) and not \
    
    422
    -                modifier & Gdk.ModifierType.SHIFT_MASK:
    
    423
    -                # CTRL + PageUp | PageDown
    
    424
    -                # Create event and send it to notebook
    
    425
    -                event = Gdk.Event.new(Gdk.EventType.KEY_PRESS)
    
    426
    -                event.window = self.window.get_window()
    
    427
    -                event.time = int(time.time())
    
    428
    -                event.state = Gdk.ModifierType.CONTROL_MASK
    
    429
    -                event.keyval = int(keyval)
    
    430
    -                self.notebook.event(event)
    
    431
    -                return True
    
    432
    -
    
    433
    -            if modifier & Gdk.ModifierType.SHIFT_MASK:
    
    434
    -                # CTRL + SHIFT
    
    435
    -                if control.type_id == message_control.TYPE_GC and \
    
    436
    -                keyval == Gdk.KEY_n:  # CTRL + SHIFT + n
    
    437
    -                    self.window.lookup_action(
    
    438
    -                        'change-nick-%s' % control.control_id).activate()
    
    439
    -                    return True
    
    440
    -                # CTRL + SHIFT + PageUp | PageDown
    
    441
    -                old_position = self.notebook.get_current_page()
    
    442
    -                total_pages = self.notebook.get_n_pages()
    
    443
    -                if keyval == Gdk.KEY_Page_Up:
    
    444
    -                    self.notebook.reorder_child(control.widget,
    
    445
    -                                                old_position - 1)
    
    446
    -                    return True
    
    447
    -                if keyval == Gdk.KEY_Page_Down:
    
    448
    -                    if old_position == total_pages - 1:
    
    449
    -                        self.notebook.reorder_child(control.widget, 0)
    
    450
    -                        return True
    
    451
    -                    self.notebook.reorder_child(control.widget,
    
    452
    -                                                old_position + 1)
    
    453
    -                    return True
    
    454
    -        # MOD1 (ALT) mask
    
    455
    -        elif modifier & Gdk.ModifierType.MOD1_MASK:
    
    456
    -            # Tab switch bindings
    
    457
    -            if keyval == Gdk.KEY_Right: # ALT + RIGHT
    
    458
    -                new = self.notebook.get_current_page() + 1
    
    459
    -                if new >= self.notebook.get_n_pages():
    
    460
    -                    new = 0
    
    461
    -                self.notebook.set_current_page(new)
    
    462
    -                return True
    
    463
    -
    
    464
    -            if keyval == Gdk.KEY_Left: # ALT + LEFT
    
    465
    -                new = self.notebook.get_current_page() - 1
    
    466
    -                if new < 0:
    
    467
    -                    new = self.notebook.get_n_pages() - 1
    
    468
    -                self.notebook.set_current_page(new)
    
    469
    -                return True
    
    470
    -
    
    471
    -            if chr(keyval) in st: # ALT + 1,2,3..
    
    472
    -                self.notebook.set_current_page(st.index(chr(keyval)))
    
    473
    -                return True
    
    474
    -
    
    475
    -            if keyval == Gdk.KEY_m: # ALT + M show emoticons menu
    
    476
    -                control.emoticons_button.get_popover().show()
    
    477
    -                return True
    
    478
    -
    
    479
    -            if (control.type_id == message_control.TYPE_GC and
    
    480
    -                    keyval == Gdk.KEY_t): # ALT + t
    
    481
    -                self.window.lookup_action(
    
    482
    -                    'change-subject-%s' % control.control_id).activate()
    
    483
    -                return True
    
    484
    -
    
    485
    -        # Close tab bindings
    
    486
    -        elif keyval == Gdk.KEY_Escape and \
    
    487
    -        app.config.get('escape_key_closes'): # Escape
    
    488
    -            self.remove_tab(control, self.CLOSE_ESC)
    
    489
    -            return True
    
    490
    -
    
    491 460
         def _on_close_button_clicked(self, button, control):
    
    492 461
             """
    
    493 462
             When close button is pressed: close a tab
    
    ... ... @@ -850,50 +819,6 @@ class MessageWindow:
    850 819
             if isinstance(control, ChatControlBase):
    
    851 820
                 control.msg_textview.grab_focus()
    
    852 821
     
    
    853
    -    def _on_notebook_key_press(self, widget, event):
    
    854
    -        # when tab itself is selected,
    
    855
    -        # make sure <- and -> are allowed for navigating between tabs
    
    856
    -        if event.keyval in (Gdk.KEY_Left, Gdk.KEY_Right):
    
    857
    -            return False
    
    858
    -
    
    859
    -        control = self.get_active_control()
    
    860
    -
    
    861
    -        if event.get_state() & Gdk.ModifierType.SHIFT_MASK:
    
    862
    -            # CTRL + SHIFT + TAB
    
    863
    -            if event.get_state() & Gdk.ModifierType.CONTROL_MASK and \
    
    864
    -            event.keyval == Gdk.KEY_ISO_Left_Tab:
    
    865
    -                self.move_to_next_unread_tab(False)
    
    866
    -                return True
    
    867
    -            # SHIFT + PAGE_[UP|DOWN]: send to conv_textview
    
    868
    -            if event.keyval in (Gdk.KEY_Page_Down, Gdk.KEY_Page_Up):
    
    869
    -                control.conv_textview.tv.event(event)
    
    870
    -                return True
    
    871
    -
    
    872
    -        elif event.get_state() & Gdk.ModifierType.CONTROL_MASK:
    
    873
    -            if event.keyval == Gdk.KEY_Tab: # CTRL + TAB
    
    874
    -                self.move_to_next_unread_tab(True)
    
    875
    -                return True
    
    876
    -            # Ctrl+PageUP / DOWN has to be handled by notebook
    
    877
    -            if event.keyval == Gdk.KEY_Page_Down:
    
    878
    -                self.move_to_next_unread_tab(True)
    
    879
    -                return True
    
    880
    -            if event.keyval == Gdk.KEY_Page_Up:
    
    881
    -                self.move_to_next_unread_tab(False)
    
    882
    -                return True
    
    883
    -
    
    884
    -        if event.keyval in (Gdk.KEY_Shift_L, Gdk.KEY_Shift_R,
    
    885
    -        Gdk.KEY_Control_L, Gdk.KEY_Control_R, Gdk.KEY_Caps_Lock,
    
    886
    -        Gdk.KEY_Shift_Lock, Gdk.KEY_Meta_L, Gdk.KEY_Meta_R,
    
    887
    -        Gdk.KEY_Alt_L, Gdk.KEY_Alt_R, Gdk.KEY_Super_L,
    
    888
    -        Gdk.KEY_Super_R, Gdk.KEY_Hyper_L, Gdk.KEY_Hyper_R):
    
    889
    -            return True
    
    890
    -
    
    891
    -        if isinstance(control, ChatControlBase):
    
    892
    -            # we forwarded it to message textview
    
    893
    -            control.msg_textview.remove_placeholder()
    
    894
    -            control.msg_textview.event(event)
    
    895
    -            control.msg_textview.grab_focus()
    
    896
    -
    
    897 822
         def get_tab_at_xy(self, x, y):
    
    898 823
             """
    
    899 824
             Return the tab under xy and if its nearer from left or right side of the