diff --git a/data/glade/chat_control_popup_menu.glade b/data/glade/chat_control_popup_menu.glade deleted file mode 100644 index 1c923adbd..000000000 --- a/data/glade/chat_control_popup_menu.glade +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - True - _Add to Roster - True - - - - True - gtk-add - 1 - - - - - - - True - Send _File - True - - - - True - gtk-save - 1 - - - - - - - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - Invite _Contacts - True - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-missing-image - - - - - - - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - - True - Toggle Open_PGP Encryption - True - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Toggle End to End Encryption - True - - - - - - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - - True - gtk-info - True - True - - - - - True - _History - True - - - True - gtk-justify-fill - 1 - - - - - - diff --git a/data/glade/roster_contact_context_menu.glade b/data/glade/roster_contact_context_menu.glade index 0629a8029..4ca3a5154 100644 --- a/data/glade/roster_contact_context_menu.glade +++ b/data/glade/roster_contact_context_menu.glade @@ -1,102 +1,150 @@ - - - + + + - True Start _Chat + True True + False - + True gtk-jump-to - 1 + 1 - True Send Single _Message... + True True + False - + True gtk-new - 1 + 1 - True Send _File... + True True + False - + True gtk-save - 1 + 1 - True In_vite to + True True + False - + True - gtk-go-back - 1 + gtk-missing-image + 1 - + + Invite _Contacts + True + True + False + + + True + gtk-missing-image + 1 + + + + + + + True + + + + + True + Toggle Open_PGP Encryption + True + + + + + True + Toggle End to End Encryption + True + + + + True - True Send Cus_tom Status + True True + False True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + gtk-missing-image + 1 + + + E_xecute Command... True - Execute Command... True + False - + True gtk-execute - 1 + 1 + _Manage Contact True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Manage Contact True + False True @@ -105,11 +153,12 @@ _Rename... True + False - + True gtk-refresh - 1 + 1 @@ -118,12 +167,12 @@ Edit _Groups... True + False - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-edit - 1 + 1 @@ -132,42 +181,44 @@ Assign Open_PGP Key... True + False - + True gtk-dialog-authentication - 1 + 1 + Set Custom _Avatar... True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Set Custom _Avatar... True + False - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-orientation-portrait - 1 + 1 - True Add Special _Notification... + True True + False - + True gtk-info - 1 + 1 @@ -182,46 +233,50 @@ _Subscription True + False - True _Allow him/her to see my status + True True + False - + True gtk-go-up - 1 + 1 - True A_sk to see his/her status + True True + False - + True gtk-go-down - 1 + 1 - True _Forbid him/her to see my status + True True + False - + True gtk-stop - 1 + 1 @@ -229,66 +284,70 @@ - + True gtk-dialog-question - 1 + 1 - True _Unblock + True True + False - + True gtk-stop - 1 + 1 - True _Block + True True + False - + True gtk-stop - 1 + 1 - True _Unignore + True True + False - + True gtk-stop - 1 + 1 - True _Ignore + True True + False - + True gtk-stop - 1 + 1 @@ -297,11 +356,12 @@ _Add to Roster... True + False - + True gtk-add - 1 + 1 @@ -310,11 +370,12 @@ Remo_ve True + False - + True gtk-remove - 1 + 1 @@ -322,17 +383,16 @@ - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK gtk-properties - 1 + 1 - + True @@ -347,11 +407,12 @@ _History True + False - + True gtk-justify-fill - 1 + 1 diff --git a/data/glade/zeroconf_contact_context_menu.glade b/data/glade/zeroconf_contact_context_menu.glade deleted file mode 100644 index 93d901f1c..000000000 --- a/data/glade/zeroconf_contact_context_menu.glade +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - - - Start _Chat - True - True - False - - - True - gtk-jump-to - 1 - - - - - - - Send _File - True - True - False - - - True - gtk-save - 1 - - - - - - - True - - - - - Execute Command... - True - False - - - True - gtk-execute - 1 - - - - - - - _Manage Contact - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - False - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - _Rename - True - False - - - True - gtk-refresh - 1 - - - - - - - Edit _Groups - True - False - - - True - gtk-edit - 1 - - - - - - - Assign Open_PGP Key - True - False - - - - True - gtk-dialog-authentication - 1 - - - - - - - Add Special _Notification - True - True - False - - - True - gtk-info - 1 - - - - - - - - - True - gtk-properties - 1 - - - - - - - True - - - - - _Information - True - False - - - True - gtk-info - 1 - - - - - - - _History - True - False - - - True - gtk-justify-fill - 1 - - - - - - diff --git a/src/chat_control.py b/src/chat_control.py index 75ee9ef4a..4881c5cf1 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -33,6 +33,7 @@ import gtk import pango import gobject import gtkgui_helpers +import gui_menu_builder import message_control import dialogs import history_window @@ -874,7 +875,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): def on_actions_button_clicked(self, widget): '''popup action menu''' - menu = self.prepare_context_menu(True) + menu = self.prepare_context_menu(hide_buttonbar_items=True) menu.show_all() gtkgui_helpers.popup_emoticons_under_button(menu, widget, self.parent_win) @@ -2074,138 +2075,19 @@ class ChatControl(ChatControlBase): return tab_img - def prepare_context_menu(self, hide_buttonbar_entries = False): + def prepare_context_menu(self, hide_buttonbar_items=False): '''sets compact view menuitem active state sets active and sensitivity state for toggle_gpg_menuitem sets sensitivity for history_menuitem (False for tranasports) and file_transfer_menuitem and hide()/show() for add_to_roster_menuitem ''' - xml = gtkgui_helpers.get_glade('chat_control_popup_menu.glade') - menu = xml.get_widget('chat_control_popup_menu') - - add_to_roster_menuitem = xml.get_widget('add_to_roster_menuitem') - history_menuitem = xml.get_widget('history_menuitem') - toggle_gpg_menuitem = xml.get_widget('toggle_gpg_menuitem') - toggle_e2e_menuitem = xml.get_widget('toggle_e2e_menuitem') - send_file_menuitem = xml.get_widget('send_file_menuitem') - information_menuitem = xml.get_widget('information_menuitem') - convert_to_gc_menuitem = xml.get_widget('convert_to_groupchat') - separatormenuitem1 = xml.get_widget('separatormenuitem1') - separatormenuitem2 = xml.get_widget('separatormenuitem2') - - # add a special img for send file menuitem - path_to_upload_img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'upload.png') - img = gtk.Image() - img.set_from_file(path_to_upload_img) - send_file_menuitem.set_image(img) - - muc_icon = gtkgui_helpers.load_icon('muc_active') - if muc_icon: - convert_to_gc_menuitem.set_image(muc_icon) - - if not hide_buttonbar_entries: - history_menuitem.show() - send_file_menuitem.show() - information_menuitem.show() - convert_to_gc_menuitem.show() - separatormenuitem1.show() - separatormenuitem2.show() - - ag = gtk.accel_groups_from_object(self.parent_win.window)[0] - send_file_menuitem.add_accelerator('activate', ag, gtk.keysyms.f, gtk.gdk.CONTROL_MASK, - gtk.ACCEL_VISIBLE) - convert_to_gc_menuitem.add_accelerator('activate', ag, gtk.keysyms.g, gtk.gdk.CONTROL_MASK, - gtk.ACCEL_VISIBLE) - history_menuitem.add_accelerator('activate', ag, gtk.keysyms.h, gtk.gdk.CONTROL_MASK, - gtk.ACCEL_VISIBLE) - information_menuitem.add_accelerator('activate', ag, gtk.keysyms.i, - gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) - - contact = self.parent_win.get_active_contact() - jid = contact.jid - - e2e_is_active = self.session is not None and self.session.enable_encryption - - # check if we support and use gpg - if not gajim.config.get_per('accounts', self.account, 'keyid') or\ - not gajim.connections[self.account].USE_GPG or\ - gajim.jid_is_transport(jid): - toggle_gpg_menuitem.set_sensitive(False) - else: - toggle_gpg_menuitem.set_sensitive(self.gpg_is_active or not e2e_is_active) - toggle_gpg_menuitem.set_active(self.gpg_is_active) - - # disable esessions if we or the other client don't support them - # XXX: Once we have fallback to disco, remove notexistant check - if not gajim.HAVE_PYCRYPTO or \ - not gajim.capscache.is_supported(contact, NS_ESESSION) or \ - gajim.capscache.is_supported(contact, 'notexistant') or \ - not gajim.config.get_per('accounts', self.account, 'enable_esessions'): - toggle_e2e_menuitem.set_sensitive(False) - else: - toggle_e2e_menuitem.set_active(e2e_is_active) - toggle_e2e_menuitem.set_sensitive(e2e_is_active or not self.gpg_is_active) - - # add_to_roster_menuitem - if not hide_buttonbar_entries and _('Not in Roster') in contact.groups: - add_to_roster_menuitem.show() - - # check if it's possible to send a file - if gajim.capscache.is_supported(contact, NS_FILE): - send_file_menuitem.set_sensitive(True) - else: - send_file_menuitem.set_sensitive(False) - - # check if it's possible to convert to groupchat - if gajim.capscache.is_supported(contact, NS_MUC): - convert_to_gc_menuitem.set_sensitive(True) - else: - convert_to_gc_menuitem.set_sensitive(False) - - # connect signals - id_ = history_menuitem.connect('activate', - self._on_history_menuitem_activate) - self.handlers[id_] = history_menuitem - id_ = send_file_menuitem.connect('activate', - self._on_send_file_menuitem_activate) - self.handlers[id_] = send_file_menuitem - id_ = add_to_roster_menuitem.connect('activate', - self._on_add_to_roster_menuitem_activate) - self.handlers[id_] = add_to_roster_menuitem - id_ = toggle_gpg_menuitem.connect('activate', - self._on_toggle_gpg_menuitem_activate) - self.handlers[id_] = toggle_gpg_menuitem - id_ = toggle_e2e_menuitem.connect('activate', - self._on_toggle_e2e_menuitem_activate) - self.handlers[id_] = toggle_e2e_menuitem - id_ = information_menuitem.connect('activate', - self._on_contact_information_menuitem_activate) - self.handlers[id_] = information_menuitem - id_ = convert_to_gc_menuitem.connect('activate', - self._on_convert_to_gc_menuitem_activate) - self.handlers[id_] = convert_to_gc_menuitem - - menu.connect('selection-done', self.destroy_menu, - send_file_menuitem, convert_to_gc_menuitem, - information_menuitem, history_menuitem) + menu = gui_menu_builder.get_contact_menu(self.contact, self.account, + use_multiple_contacts=False, show_start_chat=False, + show_encryption=True, control=self, + show_buttonbar_items=not hide_buttonbar_items) return menu - def destroy_menu(self, menu, send_file_menuitem, - convert_to_gc_menuitem, information_menuitem, history_menuitem): - # destroy accelerators - ag = gtk.accel_groups_from_object(self.parent_win.window)[0] - send_file_menuitem.remove_accelerator(ag, gtk.keysyms.f, - gtk.gdk.CONTROL_MASK) - convert_to_gc_menuitem.remove_accelerator(ag, gtk.keysyms.g, - gtk.gdk.CONTROL_MASK) - information_menuitem.remove_accelerator(ag, gtk.keysyms.i, - gtk.gdk.CONTROL_MASK) - history_menuitem.remove_accelerator(ag, gtk.keysyms.h, - gtk.gdk.CONTROL_MASK) - # destroy menu - menu.destroy() - def send_chatstate(self, state, contact = None): ''' sends OUR chatstate as STANDLONE chat state message (eg. no body) to contact only if new chatstate is different from the previous one diff --git a/src/gui_menu_builder.py b/src/gui_menu_builder.py index 09fd5efd3..73b54b8bf 100644 --- a/src/gui_menu_builder.py +++ b/src/gui_menu_builder.py @@ -25,7 +25,7 @@ import message_control from common import gajim from common import helpers -from common.xmpp.protocol import NS_COMMANDS, NS_FILE, NS_MUC +from common.xmpp.protocol import NS_COMMANDS, NS_FILE, NS_MUC, NS_ESESSION def build_resources_submenu(contacts, account, action, room_jid=None, room_account=None, cap=None): @@ -143,7 +143,11 @@ def build_invite_submenu(invite_menuitem, list_): room_jid, account, resource) invite_to_submenu.append(menuitem) -def get_contact_menu(contact, account, use_multiple_contacts=True): +def get_contact_menu(contact, account, use_multiple_contacts=True, +show_start_chat=True, show_encryption=False, show_buttonbar_items=True, +control=None): + ''' Build contact popup menu for roster and chat window. + If control is not set, we hide invite_contacts_menuitem''' if not contact: return @@ -151,12 +155,8 @@ def get_contact_menu(contact, account, use_multiple_contacts=True): our_jid = jid == gajim.get_jid_from_account(account) roster = gajim.interface.roster - if gajim.config.get_per('accounts', account, 'is_zeroconf'): - xml = gtkgui_helpers.get_glade('zeroconf_contact_context_menu.glade') - contact_context_menu = xml.get_widget('zeroconf_contact_context_menu') - else: - xml = gtkgui_helpers.get_glade('roster_contact_context_menu.glade') - contact_context_menu = xml.get_widget('roster_contact_context_menu') + xml = gtkgui_helpers.get_glade('roster_contact_context_menu.glade') + contact_context_menu = xml.get_widget('roster_contact_context_menu') start_chat_menuitem = xml.get_widget('start_chat_menuitem') execute_command_menuitem = xml.get_widget('execute_command_menuitem') @@ -168,6 +168,29 @@ def get_contact_menu(contact, account, use_multiple_contacts=True): 'add_special_notification_menuitem') information_menuitem = xml.get_widget('information_menuitem') history_menuitem = xml.get_widget('history_menuitem') + send_custom_status_menuitem = xml.get_widget('send_custom_status_menuitem') + send_single_message_menuitem = xml.get_widget('send_single_message_menuitem') + invite_menuitem = xml.get_widget('invite_menuitem') + block_menuitem = xml.get_widget('block_menuitem') + unblock_menuitem = xml.get_widget('unblock_menuitem') + ignore_menuitem = xml.get_widget('ignore_menuitem') + unignore_menuitem = xml.get_widget('unignore_menuitem') + set_custom_avatar_menuitem = xml.get_widget('set_custom_avatar_menuitem') + # Subscription submenu + subscription_menuitem = xml.get_widget('subscription_menuitem') + send_auth_menuitem, ask_auth_menuitem, revoke_auth_menuitem = \ + subscription_menuitem.get_submenu().get_children() + add_to_roster_menuitem = xml.get_widget('add_to_roster_menuitem') + remove_from_roster_menuitem = xml.get_widget( + 'remove_from_roster_menuitem') + manage_contact_menuitem = xml.get_widget('manage_contact') + convert_to_gc_menuitem = xml.get_widget('convert_to_groupchat_menuitem') + encryption_separator = xml.get_widget('encryption_separator') + toggle_gpg_menuitem = xml.get_widget('toggle_gpg_menuitem') + toggle_e2e_menuitem = xml.get_widget('toggle_e2e_menuitem') + last_separator = xml.get_widget('last_separator') + + items_to_hide = [] # add a special img for send file menuitem path_to_upload_img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'upload.png') @@ -183,6 +206,10 @@ def get_contact_menu(contact, account, use_multiple_contacts=True): img.set_from_file(path_to_kbd_input_img) rename_menuitem.set_image(img) + muc_icon = gtkgui_helpers.load_icon('muc_active') + if muc_icon: + convert_to_gc_menuitem.set_image(muc_icon) + contacts = gajim.contacts.get_contacts(account, jid) if len(contacts) > 1 and use_multiple_contacts: # several resources start_chat_menuitem.set_submenu(build_resources_submenu(contacts, @@ -229,9 +256,7 @@ def get_contact_menu(contact, account, use_multiple_contacts=True): # Hide items when it's self contact row if our_jid: - for menuitem in (rename_menuitem, edit_groups_menuitem): - menuitem.set_no_show_all(True) - menuitem.hide() + items_to_hide += [rename_menuitem, edit_groups_menuitem] # Unsensitive many items when account is offline if gajim.account_is_disconnected(account): @@ -239,8 +264,58 @@ def get_contact_menu(contact, account, use_multiple_contacts=True): edit_groups_menuitem, send_file_menuitem): widget.set_sensitive(False) + if not show_start_chat: + items_to_hide.append(start_chat_menuitem) + + if not show_encryption or not control: + items_to_hide += [encryption_separator, toggle_gpg_menuitem, + toggle_e2e_menuitem] + else: + e2e_is_active = control.session is not None and \ + control.session.enable_encryption + + # check if we support and use gpg + if not gajim.config.get_per('accounts', account, 'keyid') or \ + not gajim.connections[account].USE_GPG or gajim.jid_is_transport( + contact.jid): + toggle_gpg_menuitem.set_sensitive(False) + else: + toggle_gpg_menuitem.set_sensitive(control.gpg_is_active or \ + not e2e_is_active) + toggle_gpg_menuitem.set_active(control.gpg_is_active) + + # disable esessions if we or the other client don't support them + # XXX: Once we have fallback to disco, remove notexistant check + if not gajim.HAVE_PYCRYPTO or \ + not gajim.capscache.is_supported(contact, NS_ESESSION) or \ + gajim.capscache.is_supported(contact, 'notexistant') or \ + not gajim.config.get_per('accounts', account, 'enable_esessions'): + toggle_e2e_menuitem.set_sensitive(False) + else: + toggle_e2e_menuitem.set_active(e2e_is_active) + toggle_e2e_menuitem.set_sensitive(e2e_is_active or \ + not control.gpg_is_active) + + if not show_buttonbar_items: + items_to_hide += [history_menuitem, send_file_menuitem, + information_menuitem, convert_to_gc_menuitem, last_separator] + + if not control: + items_to_hide.append(convert_to_gc_menuitem) + + for item in items_to_hide: + item.set_no_show_all(True) + item.hide() + # Zeroconf Account if gajim.config.get_per('accounts', account, 'is_zeroconf'): + for item in (send_custom_status_menuitem, send_single_message_menuitem, + invite_menuitem, block_menuitem, unblock_menuitem, ignore_menuitem, + unignore_menuitem, set_custom_avatar_menuitem, subscription_menuitem, + manage_contact_menuitem): + item.set_no_show_all(True) + item.hide() + if contact.show in ('offline', 'error'): information_menuitem.set_sensitive(False) send_file_menuitem.set_sensitive(False) @@ -254,14 +329,6 @@ def get_contact_menu(contact, account, use_multiple_contacts=True): return contact_context_menu # normal account - send_custom_status_menuitem = xml.get_widget('send_custom_status_menuitem') - send_single_message_menuitem = xml.get_widget('send_single_message_menuitem') - invite_menuitem = xml.get_widget('invite_menuitem') - block_menuitem = xml.get_widget('block_menuitem') - unblock_menuitem = xml.get_widget('unblock_menuitem') - ignore_menuitem = xml.get_widget('ignore_menuitem') - unignore_menuitem = xml.get_widget('unignore_menuitem') - set_custom_avatar_menuitem = xml.get_widget('set_custom_avatar_menuitem') # send custom status icon blocked = False @@ -292,14 +359,6 @@ def get_contact_menu(contact, account, use_multiple_contacts=True): build_invite_submenu(invite_menuitem, [(contact, account)]) - # Subscription submenu - subscription_menuitem = xml.get_widget('subscription_menuitem') - send_auth_menuitem, ask_auth_menuitem, revoke_auth_menuitem = \ - subscription_menuitem.get_submenu().get_children() - add_to_roster_menuitem = xml.get_widget('add_to_roster_menuitem') - remove_from_roster_menuitem = xml.get_widget( - 'remove_from_roster_menuitem') - # One or several resource, we do the same for send_custom_status status_menuitems = gtk.Menu() send_custom_status_menuitem.set_submenu(status_menuitems) @@ -359,8 +418,7 @@ def get_contact_menu(contact, account, use_multiple_contacts=True): # Hide items when it's self contact row if our_jid: - menuitem = xml.get_widget('manage_contact') - menuitem.set_sensitive(False) + manage_contact_menuitem.set_sensitive(False) # Unsensitive items when account is offline if gajim.account_is_disconnected(account):