Philipp Hörist pushed to branch master at gajim / gajim
Commits: 358eab4a by Philipp Hörist at 2019-07-16T22:17:59Z Groupchat: Integrate change nickname into control
Use a Stack page to display the change nickname entry instead of a popup dialog
- - - - - 1411c02a by Philipp Hörist at 2019-07-16T22:25:33Z MessageWindow: Refactor shortcut handling
AccelGroup/AccelMap is phased out in GTK3.
Use actions instead because they can also have shortcuts. This makes the code much easier to read because we dont have to deal with keyval and key modifiers.
Handle all actions that are not control specific inside the MessageWindow and delegate all control specific actions to the controls.
- - - - - 8875aff5 by Philipp Hörist at 2019-07-16T22:25:37Z Groupchat: Remove bookmark action
- - - - - e2db0325 by Philipp Hörist at 2019-07-16T22:25:37Z ServiceDiscovery: Remove bookmark option
- - - - -
9 changed files:
- gajim/chat_control.py - gajim/chat_control_base.py - gajim/data/gui/groupchat_control.ui - gajim/data/gui/shortcuts_window.ui - gajim/groupchat_control.py - gajim/gtk/dialogs.py - gajim/gtk/discovery.py - gajim/gui_menu_builder.py - gajim/message_window.py
Changes:
===================================== gajim/chat_control.py ===================================== @@ -33,6 +33,7 @@ from gi.repository import Gtk from gi.repository import Gio from gi.repository import Pango from gi.repository import GLib +from gi.repository import Gdk from nbxmpp.protocol import NS_XHTML, NS_XHTML_IM, NS_FILE, NS_MUC from nbxmpp.protocol import NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO from nbxmpp.protocol import NS_JINGLE_ICE_UDP, NS_JINGLE_FILE_TRANSFER_5 @@ -358,6 +359,28 @@ class ChatControl(ChatControlBase): win.lookup_action( 'information-' + self.control_id).set_enabled(online)
+ def delegate_action(self, action): + res = super().delegate_action(action) + if res == Gdk.EVENT_STOP: + return res + + if action == 'show-contact-info': + self.parent_win.window.lookup_action( + 'information-%s' % self.control_id).activate() + return Gdk.EVENT_STOP + + if action == 'send-file': + if app.interface.msg_win_mgr.mode == \ + app.interface.msg_win_mgr.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER: + app.interface.roster.tree.grab_focus() + return Gdk.EVENT_PROPAGATE + + self.parent_win.window.lookup_action( + 'send-file-%s' % self.control_id).activate() + return Gdk.EVENT_STOP + + return Gdk.EVENT_PROPAGATE + def _on_add_to_roster(self, action, param): AddNewContactWindow(self.account, self.contact.jid)
===================================== gajim/chat_control_base.py ===================================== @@ -390,6 +390,28 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): # to properly use the super, because of the old code. CommandTools.__init__(self)
+ def delegate_action(self, action): + if action == 'browse-history': + dict_ = {'jid': GLib.Variant('s', self.contact.jid), + 'account': GLib.Variant('s', self.account)} + variant = GLib.Variant('a{sv}', dict_) + app.app.activate_action('browse-history', variant) + return Gdk.EVENT_STOP + + if action == 'clear-chat': + self.conv_textview.clear() + return Gdk.EVENT_STOP + + if action == 'delete-line': + self.clear(self.msg_textview) + return Gdk.EVENT_STOP + + if action == 'show-emoji-chooser': + self.emoticons_button.get_popover().show() + return Gdk.EVENT_STOP + + return Gdk.EVENT_PROPAGATE + def add_actions(self): action = Gio.SimpleAction.new_stateful( "set-encryption-%s" % self.control_id,
===================================== gajim/data/gui/groupchat_control.ui ===================================== @@ -81,374 +81,515 @@ <object class="GtkBox" id="groupchat_control_hbox"> <property name="can_focus">True</property> <child> - <object class="GtkBox" id="groupchat_control_vbox"> - <property name="can_focus">True</property> - <property name="margin_left">7</property> - <property name="margin_right">7</property> - <property name="margin_top">5</property> - <property name="margin_bottom">7</property> - <property name="orientation">vertical</property> - <property name="spacing">5</property> + <object class="GtkStack" id="stack"> + <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <object class="GtkPaned" id="hpaned"> - <property name="visible">True</property> + <object class="GtkBox" id="groupchat_control_vbox"> <property name="can_focus">True</property> - <property name="position">495</property> - <property name="position_set">True</property> - <signal name="button-release-event" handler="_on_hpaned_release_button" swapped="no"/> - <signal name="notify::position" handler="_on_hpaned_handle_change" swapped="no"/> + <property name="margin_left">7</property> + <property name="margin_right">7</property> + <property name="margin_top">5</property> + <property name="margin_bottom">7</property> + <property name="orientation">vertical</property> + <property name="spacing">5</property> <child> - <object class="GtkOverlay" id="overlay"> + <object class="GtkPaned" id="hpaned"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can_focus">True</property> + <property name="position">495</property> + <property name="position_set">True</property> + <signal name="button-release-event" handler="_on_hpaned_release_button" swapped="no"/> + <signal name="notify::position" handler="_on_hpaned_handle_change" swapped="no"/> <child> - <object class="GtkBox" id="gc_textviews_vbox"> - <property name="width_request">0</property> + <object class="GtkOverlay" id="overlay"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="margin_right">4</property> - <property name="orientation">vertical</property> <child> - <object class="GtkEventBox" id="banner_eventbox"> - <property name="name">GroupChatControl-BannerEventBox</property> + <object class="GtkBox" id="gc_textviews_vbox"> + <property name="width_request">0</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="margin_right">4</property> + <property name="orientation">vertical</property> <child> - <object class="GtkBox" id="hbox3024"> + <object class="GtkEventBox" id="banner_eventbox"> + <property name="name">GroupChatControl-BannerEventBox</property> <property name="visible">True</property> <property name="can_focus">False</property> <child> - <object class="GtkImage" id="gc_banner_status_image"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-missing-image</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="padding">5</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="banner_name_label"> - <property name="name">GroupChatControl-BannerNameLabel</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label"><span weight="heavy" size="large">room jid</span></property> - <property name="use_markup">True</property> - <property name="selectable">True</property> - <property name="xalign">0</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkActionBar" id="banner_actionbar"> + <object class="GtkBox" id="hbox3024"> <property name="visible">True</property> <property name="can_focus">False</property> - <style> - <class name="actionbar-no-border"/> - </style> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="pack_type">end</property> - <property name="position">2</property> - </packing> - </child> - </object> - </child> - <style> - <class name="gajim-banner"/> - </style> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkSeparator"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <style> - <class name="chatcontrol-separator-top"/> - </style> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkScrolledWindow" id="conversation_scrolledwindow"> - <property name="width_request">200</property> - <property name="height_request">60</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="shadow_type">in</property> - <property name="overlay_scrolling">False</property> - <signal name="edge-reached" handler="_on_edge_reached" swapped="no"/> - <signal name="scroll-event" handler="_on_scroll" swapped="no"/> - <child> - <placeholder/> - </child> - <style> - <class name="scrolled-no-border"/> - <class name="no-scroll-indicator"/> - <class name="scrollbar-style"/> - </style> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkSeparator"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <style> - <class name="chatcontrol-separator"/> - </style> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">3</property> - </packing> - </child> - <child> - <object class="GtkBox" id="hbox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <child> - <object class="GtkMenuButton" id="settings_menu"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="relief">none</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">open-menu-symbolic</property> + <child> + <object class="GtkImage" id="gc_banner_status_image"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="stock">gtk-missing-image</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">5</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="banner_name_label"> + <property name="name">GroupChatControl-BannerNameLabel</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label"><span weight="heavy" size="large">room jid</span></property> + <property name="use_markup">True</property> + <property name="selectable">True</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkActionBar" id="banner_actionbar"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <style> + <class name="actionbar-no-border"/> + </style> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">2</property> + </packing> + </child> </object> </child> <style> - <class name="chatcontrol-actionbar-button"/> + <class name="gajim-banner"/> </style> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="pack_type">end</property> <property name="position">0</property> </packing> </child> <child> - <object class="GtkButton" id="authentication_button"> - <property name="can_focus">True</property> - <property name="focus_on_click">False</property> - <property name="receives_default">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="no_show_all">True</property> - <property name="relief">none</property> - <child> - <object class="GtkImage" id="lock_image"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-dialog-authentication</property> - <property name="icon_size">1</property> - </object> - </child> + <object class="GtkSeparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> <style> - <class name="chatcontrol-actionbar-button"/> + <class name="chatcontrol-separator-top"/> </style> </object> <packing> <property name="expand">False</property> - <property name="fill">False</property> - <property name="pack_type">end</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <object class="GtkMenuButton" id="encryption_menu"> + <object class="GtkScrolledWindow" id="conversation_scrolledwindow"> + <property name="width_request">200</property> + <property name="height_request">60</property> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_text" translatable="yes">Choose encryption</property> - <property name="relief">none</property> + <property name="shadow_type">in</property> + <property name="overlay_scrolling">False</property> + <signal name="edge-reached" handler="_on_edge_reached" swapped="no"/> + <signal name="scroll-event" handler="_on_scroll" swapped="no"/> <child> <placeholder/> </child> <style> - <class name="chatcontrol-actionbar-button"/> + <class name="scrolled-no-border"/> + <class name="no-scroll-indicator"/> + <class name="scrollbar-style"/> </style> </object> <packing> - <property name="expand">False</property> + <property name="expand">True</property> <property name="fill">True</property> - <property name="pack_type">end</property> <property name="position">2</property> </packing> </child> <child> - <object class="GtkButton" id="sendfile_button"> + <object class="GtkSeparator"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="focus_on_click">False</property> - <property name="receives_default">True</property> - <property name="relief">none</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">mail-attachment-symbolic</property> - </object> - </child> + <property name="can_focus">False</property> <style> - <class name="chatcontrol-actionbar-button"/> + <class name="chatcontrol-separator"/> </style> </object> <packing> <property name="expand">False</property> - <property name="fill">False</property> - <property name="pack_type">end</property> + <property name="fill">True</property> <property name="position">3</property> </packing> </child> <child> - <object class="GtkMenuButton" id="emoticons_button"> + <object class="GtkBox" id="hbox"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_text" translatable="yes">Show a list of emojis (Alt+M)</property> - <property name="relief">none</property> + <property name="can_focus">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <child> - <object class="GtkImage"> + <object class="GtkMenuButton" id="settings_menu"> <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">face-smile-symbolic</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="relief">none</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">open-menu-symbolic</property> + </object> + </child> + <style> + <class name="chatcontrol-actionbar-button"/> + </style> </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="authentication_button"> + <property name="can_focus">True</property> + <property name="focus_on_click">False</property> + <property name="receives_default">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="no_show_all">True</property> + <property name="relief">none</property> + <child> + <object class="GtkImage" id="lock_image"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="stock">gtk-dialog-authentication</property> + <property name="icon_size">1</property> + </object> + </child> + <style> + <class name="chatcontrol-actionbar-button"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">end</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkMenuButton" id="encryption_menu"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="tooltip_text" translatable="yes">Choose encryption</property> + <property name="relief">none</property> + <child> + <placeholder/> + </child> + <style> + <class name="chatcontrol-actionbar-button"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkButton" id="sendfile_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="focus_on_click">False</property> + <property name="receives_default">True</property> + <property name="relief">none</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">mail-attachment-symbolic</property> + </object> + </child> + <style> + <class name="chatcontrol-actionbar-button"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">end</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkMenuButton" id="emoticons_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="tooltip_text" translatable="yes">Show a list of emojis (Alt+M)</property> + <property name="relief">none</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">face-smile-symbolic</property> + </object> + </child> + <style> + <class name="chatcontrol-actionbar-button"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> </child> - <style> - <class name="chatcontrol-actionbar-button"/> - </style> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">4</property> - </packing> - </child> - <child> - <object class="GtkMenuButton" id="formattings_button"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="focus_on_click">False</property> - <property name="receives_default">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="has_tooltip">True</property> - <property name="relief">none</property> - <property name="popup">formattings_menu</property> <child> - <object class="GtkImage" id="image10"> + <object class="GtkMenuButton" id="formattings_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="focus_on_click">False</property> + <property name="receives_default">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="has_tooltip">True</property> + <property name="relief">none</property> + <property name="popup">formattings_menu</property> + <child> + <object class="GtkImage" id="image10"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">format-text-bold-symbolic</property> + <property name="icon_size">1</property> + </object> + </child> + <style> + <class name="chatcontrol-actionbar-button"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">5</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <object class="GtkComboBox" id="label_selector"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="icon_name">format-text-bold-symbolic</property> - <property name="icon_size">1</property> + <property name="no_show_all">True</property> </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">7</property> + </packing> </child> - <style> - <class name="chatcontrol-actionbar-button"/> - </style> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">5</property> - </packing> - </child> - <child> - <placeholder/> - </child> - <child> - <object class="GtkComboBox" id="label_selector"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="no_show_all">True</property> </object> <packing> <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">7</property> + <property name="fill">False</property> + <property name="position">4</property> </packing> </child> </object> <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">4</property> + <property name="index">-1</property> </packing> </child> </object> <packing> - <property name="index">-1</property> + <property name="resize">False</property> + <property name="shrink">False</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow" id="list_scrolledwindow"> + <property name="width_request">100</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="no_show_all">True</property> + <property name="margin_left">4</property> + <property name="margin_bottom">5</property> + <property name="hscrollbar_policy">never</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkTreeView" id="list_treeview"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="border_width">1</property> + <property name="headers_visible">False</property> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="treeview-selection1"/> + </child> + </object> + </child> + <style> + <class name="scrolled-no-border"/> + <class name="no-scroll-indicator"/> + </style> + </object> + <packing> + <property name="resize">False</property> + <property name="shrink">False</property> </packing> </child> </object> <packing> - <property name="resize">False</property> - <property name="shrink">False</property> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> </packing> </child> + </object> + <packing> + <property name="name">groupchat</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> <child> - <object class="GtkScrolledWindow" id="list_scrolledwindow"> - <property name="width_request">100</property> + <object class="GtkSpinner" id="spinner"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="no_show_all">True</property> - <property name="margin_left">4</property> - <property name="margin_bottom">5</property> - <property name="hscrollbar_policy">never</property> - <property name="shadow_type">in</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="vexpand">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="name">progress</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="row_spacing">12</property> <child> - <object class="GtkTreeView" id="list_treeview"> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Enter new nickname</property> + <property name="xalign">0</property> + <style> + <class name="bold16"/> + </style> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="nickname_entry"> + <property name="width_request">200</property> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="border_width">1</property> - <property name="headers_visible">False</property> - <child internal-child="selection"> - <object class="GtkTreeSelection" id="treeview-selection1"/> + <property name="activates_default">True</property> + <property name="caps_lock_warning">False</property> + <property name="show_emoji_icon">True</property> + <signal name="notify::text" handler="_on_nickname_text_changed" swapped="no"/> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="homogeneous">True</property> + <child> + <object class="GtkButton"> + <property name="label" translatable="yes">_Cancel</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="halign">start</property> + <property name="valign">start</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="_on_nickname_cancel_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="nickname_change_button"> + <property name="label" translatable="yes">Ch_ange</property> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="receives_default">True</property> + <property name="halign">end</property> + <property name="valign">start</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="_on_nickname_change_clicked" swapped="no"/> + <style> + <class name="suggested-action"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> </child> </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> </child> - <style> - <class name="scrolled-no-border"/> - <class name="no-scroll-indicator"/> - </style> </object> <packing> - <property name="resize">False</property> - <property name="shrink">False</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> </packing> </child> </object> <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> + <property name="name">nickname</property> + <property name="position">2</property> </packing> </child> </object>
===================================== gajim/data/gui/shortcuts_window.ui ===================================== @@ -109,7 +109,7 @@ <child> <object class="GtkShortcutsShortcut"> <property name="visible">1</property> - <property name="accelerator"><alt>Left <ctrl>Page_Up</property> + <property name="accelerator"><alt>Left <ctrl>Page_Up</property> <property name="title" translatable="yes">Switch to the previous tab</property> </object> </child> @@ -121,13 +121,6 @@ </object> </child> <child> - <object class="GtkShortcutsShortcut"> - <property name="visible">1</property> - <property name="accelerator"><Alt>1...9</property> - <property name="title" translatable="yes">Switch to the first - ninth tab</property> - </object> - </child> - <child> <object class="GtkShortcutsShortcut"> <property name="visible">1</property> <property name="accelerator"><ctrl><shift>Tab</property> @@ -158,7 +151,7 @@ <child> <object class="GtkShortcutsShortcut"> <property name="visible">1</property> - <property name="accelerator">Escape <ctrl>w <ctrl>F4</property> + <property name="accelerator">Escape <ctrl>w</property> <property name="title" translatable="yes">Close chat</property> </object> </child>
===================================== gajim/groupchat_control.py ===================================== @@ -33,7 +33,8 @@ import logging from enum import IntEnum, unique
import nbxmpp -from nbxmpp.protocol import JID +from nbxmpp.protocol import InvalidJid +from nbxmpp.protocol import validate_resourcepart from nbxmpp.const import StatusCode from nbxmpp.const import Affiliation from nbxmpp.const import Role @@ -76,7 +77,6 @@ from gajim.gtk.dialogs import ErrorDialog from gajim.gtk.dialogs import InputTextDialog from gajim.gtk.dialogs import DestroyMucDialog from gajim.gtk.dialogs import InputDialog -from gajim.gtk.dialogs import ChangeNickDialog from gajim.gtk.single_message import SingleMessageWindow from gajim.gtk.filechoosers import AvatarChooserDialog from gajim.gtk.add_contact import AddNewContactWindow @@ -346,9 +346,14 @@ class GroupchatControl(ChatControlBase): # disable win, we are not connected yet ChatControlBase.got_disconnected(self)
+ # Stack + self.xml.stack.show_all() + self.xml.stack.set_visible_child_name('groupchat') + self.update_ui() self.widget.show_all()
+ if app.config.get('hide_groupchat_occupants_list'): # Roster is shown by default, so toggle the roster button to hide it self.show_roster() @@ -361,11 +366,10 @@ class GroupchatControl(ChatControlBase): super().add_actions() actions = [ ('change-subject-', self._on_change_subject), - ('change-nick-', self._on_change_nick), + ('change-nickname-', self._on_change_nick), ('disconnect-', self._on_disconnect), ('destroy-', self._on_destroy_room), ('configure-', self._on_configure_room), - ('bookmark-', self._on_bookmark_room), ('request-voice-', self._on_request_voice), ('execute-command-', self._on_execute_command), ('upload-avatar-', self._on_upload_avatar), @@ -466,12 +470,6 @@ class GroupchatControl(ChatControlBase): self.is_connected and contact.affiliation in (Affiliation.ADMIN, Affiliation.OWNER))
- # Bookmarks - con = app.connections[self.account] - bookmarked = con.get_module('Bookmarks').is_bookmark(self.room_jid) - self._get_action('bookmark-').set_enabled(self.is_connected and - not bookmarked) - # Request Voice role = self.get_role(self.nick) self._get_action('request-voice-').set_enabled(self.is_connected and @@ -486,7 +484,7 @@ class GroupchatControl(ChatControlBase): subject)
# Change Nick - self._get_action('change-nick-').set_enabled(self.is_connected) + self._get_action('change-nickname-').set_enabled(self.is_connected)
# Execute command self._get_action('execute-command-').set_enabled(self.is_connected) @@ -537,6 +535,15 @@ class GroupchatControl(ChatControlBase): win = self.parent_win.window return win.lookup_action(name + self.control_id)
+ def _show_page(self, name): + transition = Gtk.StackTransitionType.SLIDE_DOWN + if name == 'groupchat': + transition = Gtk.StackTransitionType.SLIDE_UP + self.xml.stack.set_visible_child_full(name, transition) + + def _get_current_page(self): + return self.xml.stack.get_visible_child_name() + def _cell_data_func(self, column, renderer, model, iter_, user_data): # Background color has to be rendered for all cells theme = app.config.get('roster_theme') @@ -632,16 +639,6 @@ class GroupchatControl(ChatControlBase): _('Please specify the new subject:'), input_str=self.subject, ok_handler=on_ok, transient_for=self.parent_win.window)
- def _on_change_nick(self, action, param): - if 'change_nick_dialog' in app.interface.instances: - app.interface.instances['change_nick_dialog'].dialog.present() - else: - title = _('Changing Nickname') - prompt = _('Please specify the new nickname you want to use:') - app.interface.instances['change_nick_dialog'] = \ - ChangeNickDialog(self.account, self.room_jid, title, - prompt, change_nick=True, transient_for=self.parent_win.window) - def _on_disconnect(self, action, param): app.connections[self.account].get_module('MUC').leave(self.room_jid) self.force_non_minimizable = True @@ -700,19 +697,6 @@ class GroupchatControl(ChatControlBase): app.config.set_per('rooms', self.contact.jid, 'print_status', param.get_boolean())
- def _on_bookmark_room(self, action, param): - """ - Bookmark the room, without autojoin and not minimized - """ - password = app.gc_passwords.get(self.room_jid, '') - con = app.connections[self.account] - con.get_module('Bookmarks').add_bookmark(self.name, - JID(self.room_jid), - True, - password, - self.nick) - self.update_actions() - def _on_request_voice(self, action, param): """ Request voice in the current room @@ -2500,6 +2484,29 @@ class GroupchatControl(ChatControlBase): widget.get_selection().unselect_all() return True
+ def delegate_action(self, action): + res = super().delegate_action(action) + if res == Gdk.EVENT_STOP: + return res + + if action == 'change-nickname': + control_action = '%s-%s' % (action, self.control_id) + self.parent_win.window.lookup_action(control_action).activate() + return Gdk.EVENT_STOP + + if action == 'escape': + if self._get_current_page() == 'groupchat': + return Gdk.EVENT_PROPAGATE + self._show_page('groupchat') + return Gdk.EVENT_STOP + + if action == 'change-subject': + control_action = '%s-%s' % (action, self.control_id) + self.parent_win.window.lookup_action(control_action).activate() + return Gdk.EVENT_STOP + + return Gdk.EVENT_PROPAGATE + def on_list_treeview_row_expanded(self, widget, iter_, path): """ When a row is expanded: change the icon of the arrow @@ -2941,6 +2948,33 @@ class GroupchatControl(ChatControlBase): else: self.revoke_owner(widget, jid)
+ def _on_change_nick(self, _action, _param): + self.xml.nickname_entry.set_text(self.nick) + self.xml.nickname_entry.grab_focus() + self.xml.nickname_change_button.grab_default() + self._show_page('nickname') + + def _on_nickname_text_changed(self, entry, _param): + text = entry.get_text() + if not text or text == self.nick: + self.xml.nickname_change_button.set_sensitive(False) + else: + try: + validate_resourcepart(text) + except InvalidJid: + self.xml.nickname_change_button.set_sensitive(False) + else: + self.xml.nickname_change_button.set_sensitive(True) + + def _on_nickname_change_clicked(self, _button): + new_nick = self.xml.nickname_entry.get_text() + app.connections[self.account].get_module('MUC').change_nick( + self.room_jid, new_nick) + self._show_page('groupchat') + + def _on_nickname_cancel_clicked(self, _button): + self._show_page('groupchat') +
class SubjectPopover(Gtk.Popover): def __init__(self):
===================================== gajim/gtk/dialogs.py ===================================== @@ -22,7 +22,6 @@ from gi.repository import Gdk from gi.repository import Pango
from gajim.common import app -from gajim.common import helpers from gajim.common.i18n import _ from gajim.common.const import ButtonAction
@@ -526,91 +525,6 @@ class InputDialogCheck(InputDialog): return False
-class ChangeNickDialog(InputDialogCheck): - """ - Class for changing room nickname in case of conflict - """ - - def __init__(self, account, room_jid, title, prompt, check_text=None, - change_nick=False, transient_for=None): - """ - change_nick must be set to True when we are already occupant of the room - and we are changing our nick - """ - InputDialogCheck.__init__(self, title, '', - input_str='', is_modal=True, ok_handler=None, - cancel_handler=None, - transient_for=transient_for) - self.room_queue = [(account, room_jid, prompt, change_nick)] - self.check_next() - - def on_input_dialog_delete_event(self, widget, event): - self.on_cancelbutton_clicked(widget) - return True - - def setup_dialog(self): - self.gc_control = app.interface.msg_win_mgr.get_gc_control( - self.room_jid, self.account) - if not self.gc_control and \ - self.room_jid in app.interface.minimized_controls[self.account]: - self.gc_control = \ - app.interface.minimized_controls[self.account][self.room_jid] - if not self.gc_control: - self.check_next() - return - label = self.xml.get_object('label') - label.set_markup(self.prompt) - self.set_entry(self.gc_control.nick + \ - app.config.get('gc_proposed_nick_char')) - - def check_next(self): - if not self.room_queue: - self.cancel_handler = None - self.dialog.destroy() - if 'change_nick_dialog' in app.interface.instances: - del app.interface.instances['change_nick_dialog'] - return - self.account, self.room_jid, self.prompt, self.change_nick = \ - self.room_queue.pop(0) - self.setup_dialog() - self.dialog.show() - - def on_okbutton_clicked(self, widget): - nick = self.get_text() - if nick: - nick = nick - # send presence to room - try: - nick = helpers.parse_resource(nick) - except Exception: - # invalid char - ErrorDialog(_('Invalid nickname'), - _('The nickname contains invalid characters.')) - return - self.on_ok(nick, self.is_checked()) - - def on_ok(self, nick, is_checked): - app.connections[self.account].get_module('MUC').change_nick( - self.room_jid, nick) - if app.gc_connected[self.account][self.room_jid]: - # We are changing nick, we will change self.nick when we receive - # presence that inform that it works - self.gc_control.new_nick = nick - else: - # We are connecting, we will not get a changed nick presence so - # change it NOW. We don't already have a nick so it's harmless - self.gc_control.nick = nick - self.check_next() - - def on_cancelbutton_clicked(self, widget): - self.gc_control.new_nick = '' - self.check_next() - - def add_room(self, account, room_jid, prompt, change_nick=False): - if (account, room_jid, prompt, change_nick) not in self.room_queue: - self.room_queue.append((account, room_jid, prompt, change_nick)) - - class InputTextDialog(CommonInputDialog): """ Class for multilines Input dialog (more place than InputDialog)
===================================== gajim/gtk/discovery.py ===================================== @@ -46,7 +46,6 @@ import weakref import uuid
import nbxmpp -from nbxmpp.protocol import JID from nbxmpp.util import is_error_result from nbxmpp.structs import DiscoIdentity
@@ -61,7 +60,6 @@ from gajim.common.const import StyleAttr
from gajim.gtk.adhoc import AdHocCommand from gajim.gtk.dialogs import ErrorDialog -from gajim.gtk.dialogs import InformationDialog from gajim.gtk.search import Search from gajim.gtk.service_registration import ServiceRegistration from gajim.gtk.util import icon_exists @@ -1637,7 +1635,6 @@ class MucBrowser(AgentBrowser): def __init__(self, *args, **kwargs): AgentBrowser.__init__(self, *args, **kwargs) self.join_button = None - self.bookmark_button = None
def _create_treemodel(self): # JID, node, name, users_int, users_str, description, fetched @@ -1703,55 +1700,16 @@ class MucBrowser(AgentBrowser): AgentBrowser._clean_treemodel(self)
def _add_actions(self): - self.bookmark_button = Gtk.Button(label=_('_Bookmark'), - use_underline=True) - self.bookmark_button.connect( - 'clicked', self._on_bookmark_button_clicked) - image = Gtk.Image.new_from_icon_name( - 'bookmark-new-symbolic', Gtk.IconSize.BUTTON) - self.bookmark_button.set_image(image) - self.window.action_buttonbox.add(self.bookmark_button) - self.bookmark_button.show_all() self.join_button = Gtk.Button(label=_('_Join'), use_underline=True) self.join_button.connect('clicked', self._on_join_button_clicked) self.window.action_buttonbox.add(self.join_button) self.join_button.show_all()
def _clean_actions(self): - if self.bookmark_button: - self.bookmark_button.destroy() - self.bookmark_button = None if self.join_button: self.join_button.destroy() self.join_button = None
- def _on_bookmark_button_clicked(self, *args): - con = app.connections[self.account] - model, iter_ = \ - self.window.services_treeview.get_selection().get_selected() - if not iter_: - return - - room_jid = model[iter_][0] - if con.get_module('Bookmarks').is_bookmark(room_jid): - ErrorDialog( - _('Bookmark already set'), - _('Group Chat '%s' is already in your bookmarks.') % room_jid, - transient_for=self.window.window) - return - - con.get_module('Bookmarks').add_bookmark(room_jid.split('@')[0], - JID(room_jid), - False, - '', - '') - - InformationDialog( - _('Bookmark has been added successfully'), - _('You can manage your bookmarks by clicking the Bookmarks menu ' - 'item in your contact list.'), - transient_for=self.window.window) - def _on_join_button_clicked(self, *args): """ When we want to join a conference: ask specific informations about the @@ -1773,8 +1731,6 @@ class MucBrowser(AgentBrowser): def update_actions(self): sens = \ self.window.services_treeview.get_selection().count_selected_rows() - if self.bookmark_button: - self.bookmark_button.set_sensitive(sens > 0) if self.join_button: self.join_button.set_sensitive(sens > 0)
===================================== gajim/gui_menu_builder.py ===================================== @@ -594,7 +594,7 @@ def get_groupchat_menu(control_id, account, jid): (_('Send Chatstate'), ['chatstate']), ]), (_('Sync Threshold'), ['sync']), - ('win.change-nick-', _('Change Nick')), + ('win.change-nickname-', _('Change Nick')), ('win.request-voice-', _('Request Voice')), ('win.execute-command-', _('Execute command')), ('app.browse-history', _('History')),
===================================== gajim/message_window.py ===================================== @@ -23,12 +23,13 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see http://www.gnu.org/licenses/.
-import time +import logging
from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GObject from gi.repository import GLib +from gi.repository import Gio
from gajim import common from gajim.common import app @@ -49,6 +50,9 @@ from gajim.gtk.util import get_app_icon_list from gajim.gtk.util import get_builder from gajim.gtk.util import set_urgency_hint
+ +log = logging.getLogger('gajim.message_window') + ####################
class MessageWindow: @@ -119,19 +123,7 @@ class MessageWindow: id_ = self.window.connect('focus-in-event', self._on_window_focus) self.handlers[id_] = self.window
- keys = ['<Control>f', '<Control>g', '<Control>h', '<Control>i', - '<Control>l', '<Control>L', '<Control><Shift>n', '<Control>u', - '<Control>b', '<Control>F4', - '<Control><Shift>Page_Up', '<Control><Shift>Page_Down', - '<Control>w', '<Control>Page_Up', '<Control>Page_Down', '<Alt>Right', - '<Alt>Left', '<Alt>d', '<Alt>c', '<Alt>m', '<Alt>t', 'Escape'] + \ - ['<Alt>'+str(i) for i in range(10)] - accel_group = Gtk.AccelGroup() - for key in keys: - keyval, mod = Gtk.accelerator_parse(key) - accel_group.connect(keyval, mod, Gtk.AccelFlags.VISIBLE, - self.accel_group_func) - self.window.add_accel_group(accel_group) + self._add_actions()
# gtk+ doesn't make use of the motion notify on gtkwindow by default # so this line adds that @@ -164,6 +156,118 @@ class MessageWindow: self.notebook.set_show_border(app.config.get('tabs_border')) self.show_icon()
+ def _add_actions(self): + actions = [ + ('change-nickname', ['<Control><Shift>n']), + ('change-subject', ['<Alt>t']), + ('escape', ['Escape']), + ('browse-history', ['<Control>h']), + ('send-file', ['<Control>f']), + ('show-contact-info', ['<Control>i']), + ('show-emoji-chooser', ['<Alt>m']), + ('clear-chat', ['<Control>l']), + ('delete-line', ['<Control>u']), + ('close-tab', ['<Control>w']), + ('move-tab-up', ['<Control><Shift>Page_Up']), + ('move-tab-down', ['<Control><Shift>Page_Down']), + ('switch-next-tab', ['<Alt>Right']), + ('switch-prev-tab', ['<Alt>Left']), + ('switch-next-unread-tab-right', ['<Control>Tab', + '<Control>Page_Down']), + ('switch-next-unread-tab-left', ['<Control>ISO_Left_Tab', + '<Control>Page_Up']), + ] + + disabled_for_emacs = ( + 'browse-history', + 'send-file', + 'close-tab' + ) + + key_theme = Gtk.Settings.get_default().get_property( + 'gtk-key-theme-name') + + for action, keys in actions: + if key_theme == 'Emacs' and action in disabled_for_emacs: + continue + act = Gio.SimpleAction.new(action, None) + act.connect('activate', self._on_action) + self.window.add_action(act) + app.app.set_accels_for_action('win.%s' % action, keys) + + def _on_action(self, action, _param): + control = self.get_active_control() + if not control: + # No more control in this window + return + + log.info('Activate action: %s, active control: %s', + action.get_name(), control.contact.jid) + + action = action.get_name() + + # Pass the event to the control + res = control.delegate_action(action) + if res != Gdk.EVENT_PROPAGATE: + return res + + if action == 'escape' and app.config.get('escape_key_closes'): + self.remove_tab(control, self.CLOSE_ESC) + return + + if action == 'close-tab': + self.remove_tab(control, self.CLOSE_CTRL_KEY) + return + + if action == 'move-tab-up': + old_position = self.notebook.get_current_page() + self.notebook.reorder_child(control.widget, + old_position - 1) + return + + if action == 'move-tab-down': + old_position = self.notebook.get_current_page() + total_pages = self.notebook.get_n_pages() + if old_position == total_pages - 1: + self.notebook.reorder_child(control.widget, 0) + else: + self.notebook.reorder_child(control.widget, + old_position + 1) + return + + if action == 'switch-next-tab': + new = self.notebook.get_current_page() + 1 + if new >= self.notebook.get_n_pages(): + new = 0 + self.notebook.set_current_page(new) + return + + if action == 'switch-prev-tab': + new = self.notebook.get_current_page() - 1 + if new < 0: + new = self.notebook.get_n_pages() - 1 + self.notebook.set_current_page(new) + return + + if action == 'switch-next-unread-tab-right': + self.move_to_next_unread_tab(True) + return + + if action == 'switch-next-unread-tab-left': + self.move_to_next_unread_tab(False) + return + + def _on_notebook_key_press(self, _widget, event): + control = self.get_active_control() + if control is None: + return + + if isinstance(control, ChatControlBase): + # we forwarded it to message textview + control.msg_textview.remove_placeholder() + control.msg_textview.event(event) + control.msg_textview.grab_focus() + def change_account_name(self, old_name, new_name): if old_name in self._controls: self._controls[new_name] = self._controls[old_name] @@ -353,141 +457,6 @@ class MessageWindow: ctrl = self._widget_to_control(child) GLib.idle_add(ctrl.msg_textview.grab_focus)
- def accel_group_func(self, accel_group, acceleratable, keyval, modifier): - st = '1234567890' # alt+1 means the first tab (tab 0) - control = self.get_active_control() - if not control: - # No more control in this window - return - - # CTRL mask - if modifier & Gdk.ModifierType.CONTROL_MASK: - if keyval == Gdk.KEY_h: # CTRL + h - if Gtk.Settings.get_default().get_property( - 'gtk-key-theme-name') != 'Emacs': - dict_ = {'jid': GLib.Variant('s', control.contact.jid), - 'account': GLib.Variant('s', control.account)} - variant = GLib.Variant('a{sv}', dict_) - app.app.activate_action('browse-history', variant) - return True - elif control.type_id == message_control.TYPE_CHAT and \ - keyval == Gdk.KEY_f: # CTRL + f - # CTRL + f moves cursor one char forward when user uses Emacs - # theme - if not Gtk.Settings.get_default().get_property( - 'gtk-key-theme-name') == 'Emacs': - if app.interface.msg_win_mgr.mode == \ - app.interface.msg_win_mgr.ONE_MSG_WINDOW_ALWAYS_WITH_ROSTER: - app.interface.roster.tree.grab_focus() - return False - self.window.lookup_action( - 'send-file-%s' % control.control_id).activate() - return True - elif control.type_id == message_control.TYPE_CHAT and \ - keyval == Gdk.KEY_g: # CTRL + g - control._on_convert_to_gc_menuitem_activate(None) - return True - elif control.type_id in (message_control.TYPE_CHAT, - message_control.TYPE_PM) and keyval == Gdk.KEY_i: # CTRL + i - self.window.lookup_action( - 'information-%s' % control.control_id).activate() - return True - elif keyval in (Gdk.KEY_l, Gdk.KEY_L): # CTRL + l|L - control.conv_textview.clear() - return True - elif keyval == Gdk.KEY_u: # CTRL + u: emacs style clear line - control.clear(control.msg_textview) - return True - elif control.type_id == message_control.TYPE_GC and \ - keyval == Gdk.KEY_b: # CTRL + b - # CTRL + b moves cursor one char backward when user uses Emacs - # theme - if not Gtk.Settings.get_default().get_property( - 'gtk-key-theme-name') == 'Emacs': - self.window.lookup_action( - 'bookmark-%s' % control.control_id).activate() - return True - # Tab switch bindings - elif keyval == Gdk.KEY_F4: # CTRL + F4 - self.remove_tab(control, self.CLOSE_CTRL_KEY) - return True - elif keyval == Gdk.KEY_w: # CTRL + w - # CTRL + w removes latest word before cursor when User uses emacs - # theme - if not Gtk.Settings.get_default().get_property( - 'gtk-key-theme-name') == 'Emacs': - self.remove_tab(control, self.CLOSE_CTRL_KEY) - return True - elif keyval in (Gdk.KEY_Page_Up, Gdk.KEY_Page_Down) and not \ - modifier & Gdk.ModifierType.SHIFT_MASK: - # CTRL + PageUp | PageDown - # Create event and send it to notebook - event = Gdk.Event.new(Gdk.EventType.KEY_PRESS) - event.window = self.window.get_window() - event.time = int(time.time()) - event.state = Gdk.ModifierType.CONTROL_MASK - event.keyval = int(keyval) - self.notebook.event(event) - return True - - if modifier & Gdk.ModifierType.SHIFT_MASK: - # CTRL + SHIFT - if control.type_id == message_control.TYPE_GC and \ - keyval == Gdk.KEY_n: # CTRL + SHIFT + n - self.window.lookup_action( - 'change-nick-%s' % control.control_id).activate() - return True - # CTRL + SHIFT + PageUp | PageDown - old_position = self.notebook.get_current_page() - total_pages = self.notebook.get_n_pages() - if keyval == Gdk.KEY_Page_Up: - self.notebook.reorder_child(control.widget, - old_position - 1) - return True - if keyval == Gdk.KEY_Page_Down: - if old_position == total_pages - 1: - self.notebook.reorder_child(control.widget, 0) - return True - self.notebook.reorder_child(control.widget, - old_position + 1) - return True - # MOD1 (ALT) mask - elif modifier & Gdk.ModifierType.MOD1_MASK: - # Tab switch bindings - if keyval == Gdk.KEY_Right: # ALT + RIGHT - new = self.notebook.get_current_page() + 1 - if new >= self.notebook.get_n_pages(): - new = 0 - self.notebook.set_current_page(new) - return True - - if keyval == Gdk.KEY_Left: # ALT + LEFT - new = self.notebook.get_current_page() - 1 - if new < 0: - new = self.notebook.get_n_pages() - 1 - self.notebook.set_current_page(new) - return True - - if chr(keyval) in st: # ALT + 1,2,3.. - self.notebook.set_current_page(st.index(chr(keyval))) - return True - - if keyval == Gdk.KEY_m: # ALT + M show emoticons menu - control.emoticons_button.get_popover().show() - return True - - if (control.type_id == message_control.TYPE_GC and - keyval == Gdk.KEY_t): # ALT + t - self.window.lookup_action( - 'change-subject-%s' % control.control_id).activate() - return True - - # Close tab bindings - elif keyval == Gdk.KEY_Escape and \ - app.config.get('escape_key_closes'): # Escape - self.remove_tab(control, self.CLOSE_ESC) - return True - def _on_close_button_clicked(self, button, control): """ When close button is pressed: close a tab @@ -850,50 +819,6 @@ class MessageWindow: if isinstance(control, ChatControlBase): control.msg_textview.grab_focus()
- def _on_notebook_key_press(self, widget, event): - # when tab itself is selected, - # make sure <- and -> are allowed for navigating between tabs - if event.keyval in (Gdk.KEY_Left, Gdk.KEY_Right): - return False - - control = self.get_active_control() - - if event.get_state() & Gdk.ModifierType.SHIFT_MASK: - # CTRL + SHIFT + TAB - if event.get_state() & Gdk.ModifierType.CONTROL_MASK and \ - event.keyval == Gdk.KEY_ISO_Left_Tab: - self.move_to_next_unread_tab(False) - return True - # SHIFT + PAGE_[UP|DOWN]: send to conv_textview - if event.keyval in (Gdk.KEY_Page_Down, Gdk.KEY_Page_Up): - control.conv_textview.tv.event(event) - return True - - elif event.get_state() & Gdk.ModifierType.CONTROL_MASK: - if event.keyval == Gdk.KEY_Tab: # CTRL + TAB - self.move_to_next_unread_tab(True) - return True - # Ctrl+PageUP / DOWN has to be handled by notebook - if event.keyval == Gdk.KEY_Page_Down: - self.move_to_next_unread_tab(True) - return True - if event.keyval == Gdk.KEY_Page_Up: - self.move_to_next_unread_tab(False) - return True - - if event.keyval in (Gdk.KEY_Shift_L, Gdk.KEY_Shift_R, - Gdk.KEY_Control_L, Gdk.KEY_Control_R, Gdk.KEY_Caps_Lock, - Gdk.KEY_Shift_Lock, Gdk.KEY_Meta_L, Gdk.KEY_Meta_R, - Gdk.KEY_Alt_L, Gdk.KEY_Alt_R, Gdk.KEY_Super_L, - Gdk.KEY_Super_R, Gdk.KEY_Hyper_L, Gdk.KEY_Hyper_R): - return True - - if isinstance(control, ChatControlBase): - # we forwarded it to message textview - control.msg_textview.remove_placeholder() - control.msg_textview.event(event) - control.msg_textview.grab_focus() - def get_tab_at_xy(self, x, y): """ Return the tab under xy and if its nearer from left or right side of the
View it on GitLab: https://dev.gajim.org/gajim/gajim/compare/37b5be8b005fc653f138d8126296ed5d4f...