diff --git a/src/gui_menu_builder.py b/src/gui_menu_builder.py new file mode 100644 index 000000000..09fd5efd3 --- /dev/null +++ b/src/gui_menu_builder.py @@ -0,0 +1,407 @@ +# -*- coding:utf-8 -*- +## src/gui_menu_builder.py +## +## Copyright (C) 2009 Yann Leboulanger +## +## This file is part of Gajim. +## +## Gajim is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; version 3 only. +## +## Gajim is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Gajim. If not, see . +## + +import gtk +import os +import gtkgui_helpers +import message_control + +from common import gajim +from common import helpers +from common.xmpp.protocol import NS_COMMANDS, NS_FILE, NS_MUC + +def build_resources_submenu(contacts, account, action, room_jid=None, +room_account=None, cap=None): + ''' Build a submenu with contact's resources. + room_jid and room_account are for action self.on_invite_to_room ''' + sub_menu = gtk.Menu() + + iconset = gajim.config.get('iconset') + if not iconset: + iconset = gajim.config.DEFAULT_ICONSET + path = os.path.join(helpers.get_iconset_path(iconset), '16x16') + for c in contacts: + # icon MUST be different instance for every item + state_images = gtkgui_helpers.load_iconset(path) + item = gtk.ImageMenuItem('%s (%s)' % (c.resource, str(c.priority))) + icon_name = helpers.get_icon_name_to_show(c, account) + icon = state_images[icon_name] + item.set_image(icon) + sub_menu.append(item) + + if action == roster.on_invite_to_room: + item.connect('activate', action, [(c, account)], room_jid, + room_account, c.resource) + elif action == roster.on_invite_to_new_room: + item.connect('activate', action, [(c, account)], c.resource) + else: # start_chat, execute_command, send_file + item.connect('activate', action, c, account, c.resource) + + if cap and not gajim.capscache.is_supported(c, cap): + item.set_sensitive(False) + + return sub_menu + +def build_invite_submenu(invite_menuitem, list_): + '''list_ in a list of (contact, account)''' + roster = gajim.interface.roster + # used if we invite only one contact with several resources + contact_list = [] + if len(list_) == 1: + contact, account = list_[0] + contact_list = gajim.contacts.get_contacts(account, contact.jid) + contacts_transport = -1 + connected_accounts = [] + # -1 is at start, False when not from the same, None when jabber + for (contact, account) in list_: + if not account in connected_accounts: + connected_accounts.append(account) + transport = gajim.get_transport_name_from_jid(contact.jid) + if contacts_transport == -1: + contacts_transport = transport + elif contacts_transport != transport: + contacts_transport = False + + if contacts_transport == False: + # they are not all from the same transport + invite_menuitem.set_sensitive(False) + return + invite_to_submenu = gtk.Menu() + invite_menuitem.set_submenu(invite_to_submenu) + invite_to_new_room_menuitem = gtk.ImageMenuItem(_('_New Group Chat')) + icon = gtk.image_new_from_stock(gtk.STOCK_NEW, gtk.ICON_SIZE_MENU) + invite_to_new_room_menuitem.set_image(icon) + if len(contact_list) > 1: # several resources + invite_to_new_room_menuitem.set_submenu(build_resources_submenu( + contact_list, account, roster.on_invite_to_new_room, cap=NS_MUC)) + elif len(list_) == 1 and gajim.capscache.is_supported(contact, NS_MUC): + invite_menuitem.set_sensitive(True) + # use resource if it's self contact + if contact.jid == gajim.get_jid_from_account(account): + resource = contact.resource + else: + resource = None + invite_to_new_room_menuitem.connect('activate', + roster.on_invite_to_new_room, list_, resource) + else: + invite_menuitem.set_sensitive(False) + # transform None in 'jabber' + c_t = contacts_transport or 'jabber' + muc_jid = {} + for account in connected_accounts: + for t in gajim.connections[account].muc_jid: + muc_jid[t] = gajim.connections[account].muc_jid[t] + if c_t not in muc_jid: + invite_to_new_room_menuitem.set_sensitive(False) + rooms = [] # a list of (room_jid, account) tuple + invite_to_submenu.append(invite_to_new_room_menuitem) + rooms = [] # a list of (room_jid, account) tuple + minimized_controls = [] + for account in connected_accounts: + minimized_controls += gajim.interface.minimized_controls[account].values() + for gc_control in gajim.interface.msg_win_mgr.get_controls( + message_control.TYPE_GC) + minimized_controls: + acct = gc_control.account + room_jid = gc_control.room_jid + if room_jid in gajim.gc_connected[acct] and \ + gajim.gc_connected[acct][room_jid] and \ + contacts_transport == gajim.get_transport_name_from_jid(room_jid): + rooms.append((room_jid, acct)) + if len(rooms): + item = gtk.SeparatorMenuItem() # separator + invite_to_submenu.append(item) + for (room_jid, account) in rooms: + menuitem = gtk.MenuItem(room_jid.split('@')[0]) + if len(contact_list) > 1: # several resources + menuitem.set_submenu(build_resources_submenu( + contact_list, account, roster.on_invite_to_room, room_jid, + account)) + else: + # use resource if it's self contact + if contact.jid == gajim.get_jid_from_account(account): + resource = contact.resource + else: + resource = None + menuitem.connect('activate', roster.on_invite_to_room, list_, + room_jid, account, resource) + invite_to_submenu.append(menuitem) + +def get_contact_menu(contact, account, use_multiple_contacts=True): + if not contact: + return + + jid = contact.jid + 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') + + start_chat_menuitem = xml.get_widget('start_chat_menuitem') + execute_command_menuitem = xml.get_widget('execute_command_menuitem') + rename_menuitem = xml.get_widget('rename_menuitem') + edit_groups_menuitem = xml.get_widget('edit_groups_menuitem') + send_file_menuitem = xml.get_widget('send_file_menuitem') + assign_openpgp_key_menuitem = xml.get_widget('assign_openpgp_key_menuitem') + add_special_notification_menuitem = xml.get_widget( + 'add_special_notification_menuitem') + information_menuitem = xml.get_widget('information_menuitem') + history_menuitem = xml.get_widget('history_menuitem') + + # 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) + + if not our_jid: + # add a special img for rename menuitem + path_to_kbd_input_img = os.path.join(gajim.DATA_DIR, 'pixmaps', + 'kbd_input.png') + img = gtk.Image() + img.set_from_file(path_to_kbd_input_img) + rename_menuitem.set_image(img) + + 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, + account, gajim.interface.on_open_chat_window)) + send_file_menuitem.set_submenu(build_resources_submenu(contacts, + account, roster.on_send_file_menuitem_activate, cap=NS_FILE)) + execute_command_menuitem.set_submenu(build_resources_submenu( + contacts, account, roster.on_execute_command, cap=NS_COMMANDS)) + else: + start_chat_menuitem.connect('activate', + gajim.interface.on_open_chat_window, contact, account) + if gajim.capscache.is_supported(contact, NS_FILE): + send_file_menuitem.set_sensitive(True) + send_file_menuitem.connect('activate', + roster.on_send_file_menuitem_activate, contact, account) + else: + send_file_menuitem.set_sensitive(False) + + if gajim.capscache.is_supported(contact, NS_COMMANDS): + execute_command_menuitem.set_sensitive(True) + execute_command_menuitem.connect('activate', roster.on_execute_command, + contact, account, contact.resource) + else: + execute_command_menuitem.set_sensitive(False) + + rename_menuitem.connect('activate', roster.on_rename, 'contact', jid, + account) + history_menuitem.connect('activate', roster.on_history, contact, account) + + if _('Not in Roster') not in contact.get_shown_groups(): + # contact is in normal group + edit_groups_menuitem.connect('activate', roster.on_edit_groups, [(contact, + account)]) + + if gajim.connections[account].gpg: + assign_openpgp_key_menuitem.connect('activate', + roster.on_assign_pgp_key, contact, account) + else: + assign_openpgp_key_menuitem.set_sensitive(False) + else: + # contact is in group 'Not in Roster' + edit_groups_menuitem.set_sensitive(False) + assign_openpgp_key_menuitem.set_sensitive(False) + + # 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() + + # Unsensitive many items when account is offline + if gajim.account_is_disconnected(account): + for widget in (start_chat_menuitem, rename_menuitem, + edit_groups_menuitem, send_file_menuitem): + widget.set_sensitive(False) + + # Zeroconf Account + if gajim.config.get_per('accounts', account, 'is_zeroconf'): + if contact.show in ('offline', 'error'): + information_menuitem.set_sensitive(False) + send_file_menuitem.set_sensitive(False) + else: + information_menuitem.connect('activate', roster.on_info_zeroconf, + contact, account) + + contact_context_menu.connect('selection-done', + gtkgui_helpers.destroy_widget) + contact_context_menu.show_all() + 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 + if helpers.jid_is_blocked(account, jid): + blocked = True + else: + for group in contact.get_shown_groups(): + if helpers.group_is_blocked(account, group): + blocked = True + break + if gajim.get_transport_name_from_jid(jid, use_config_setting=False): + # Transport contact, send custom status unavailable + send_custom_status_menuitem.set_sensitive(False) + elif blocked: + send_custom_status_menuitem.set_image(gtkgui_helpers.load_icon('offline')) + send_custom_status_menuitem.set_sensitive(False) + elif account in gajim.interface.status_sent_to_users and \ + jid in gajim.interface.status_sent_to_users[account]: + send_custom_status_menuitem.set_image(gtkgui_helpers.load_icon( + gajim.interface.status_sent_to_users[account][jid])) + else: + icon = gtk.image_new_from_stock(gtk.STOCK_NETWORK, gtk.ICON_SIZE_MENU) + send_custom_status_menuitem.set_image(icon) + + muc_icon = gtkgui_helpers.load_icon('muc_active') + if muc_icon: + invite_menuitem.set_image(muc_icon) + + 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) + iconset = gajim.config.get('iconset') + path = os.path.join(helpers.get_iconset_path(iconset), '16x16') + for s in ('online', 'chat', 'away', 'xa', 'dnd', 'offline'): + # icon MUST be different instance for every item + state_images = gtkgui_helpers.load_iconset(path) + status_menuitem = gtk.ImageMenuItem(helpers.get_uf_show(s)) + status_menuitem.connect('activate', roster.on_send_custom_status, + [(contact, account)], s) + icon = state_images[s] + status_menuitem.set_image(icon) + status_menuitems.append(status_menuitem) + + send_single_message_menuitem.connect('activate', + roster.on_send_single_message_menuitem_activate, account, contact) + + remove_from_roster_menuitem.connect('activate', roster.on_req_usub, + [(contact, account)]) + information_menuitem.connect('activate', roster.on_info, contact, account) + + if _('Not in Roster') not in contact.get_shown_groups(): + # contact is in normal group + add_to_roster_menuitem.hide() + add_to_roster_menuitem.set_no_show_all(True) + + if contact.sub in ('from', 'both'): + send_auth_menuitem.set_sensitive(False) + else: + send_auth_menuitem.connect('activate', roster.authorize, jid, account) + if contact.sub in ('to', 'both'): + ask_auth_menuitem.set_sensitive(False) + add_special_notification_menuitem.connect('activate', + roster.on_add_special_notification_menuitem_activate, jid) + else: + ask_auth_menuitem.connect('activate', roster.req_sub, jid, + _('I would like to add you to my roster'), account, + contact.groups, contact.name) + if contact.sub in ('to', 'none') or gajim.get_transport_name_from_jid( + jid, use_config_setting=False): + revoke_auth_menuitem.set_sensitive(False) + else: + revoke_auth_menuitem.connect('activate', roster.revoke_auth, jid, + account) + + else: + # contact is in group 'Not in Roster' + add_to_roster_menuitem.set_no_show_all(False) + subscription_menuitem.set_sensitive(False) + + add_to_roster_menuitem.connect('activate', roster.on_add_to_roster, + contact, account) + + set_custom_avatar_menuitem.connect('activate', + roster.on_set_custom_avatar_activate, contact, account) + + # Hide items when it's self contact row + if our_jid: + menuitem = xml.get_widget('manage_contact') + menuitem.set_sensitive(False) + + # Unsensitive items when account is offline + if gajim.account_is_disconnected(account): + for widget in (send_single_message_menuitem, subscription_menuitem, + add_to_roster_menuitem, remove_from_roster_menuitem, + execute_command_menuitem, send_custom_status_menuitem): + widget.set_sensitive(False) + + if gajim.connections[account] and gajim.connections[account].\ + privacy_rules_supported: + if helpers.jid_is_blocked(account, jid): + block_menuitem.set_no_show_all(True) + block_menuitem.hide() + if gajim.get_transport_name_from_jid(jid, use_config_setting=False): + unblock_menuitem.set_no_show_all(True) + unblock_menuitem.hide() + unignore_menuitem.set_no_show_all(False) + unignore_menuitem.connect('activate', roster.on_unblock, [(contact, + account)]) + else: + unblock_menuitem.connect('activate', roster.on_unblock, [(contact, + account)]) + else: + unblock_menuitem.set_no_show_all(True) + unblock_menuitem.hide() + if gajim.get_transport_name_from_jid(jid, use_config_setting=False): + block_menuitem.set_no_show_all(True) + block_menuitem.hide() + ignore_menuitem.set_no_show_all(False) + ignore_menuitem.connect('activate', roster.on_block, [(contact, + account)]) + else: + block_menuitem.connect('activate', roster.on_block, [(contact, + account)]) + else: + unblock_menuitem.set_no_show_all(True) + block_menuitem.set_sensitive(False) + unblock_menuitem.hide() + + contact_context_menu.connect('selection-done', gtkgui_helpers.destroy_widget) + contact_context_menu.show_all() + return contact_context_menu + +# vim: se ts=3: diff --git a/src/roster_window.py b/src/roster_window.py index 9043a9b9f..d0d2a5fe1 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -46,6 +46,7 @@ import vcard import config import disco import gtkgui_helpers +import gui_menu_builder import cell_renderer_image import tooltips import message_control @@ -64,7 +65,7 @@ from common import dbus_support if dbus_support.supported: import dbus -from common.xmpp.protocol import NS_COMMANDS, NS_FILE, NS_MUC +from common.xmpp.protocol import NS_FILE from common.pep import MOODS, ACTIVITIES #(icon, name, type, jid, account, editable, second pixbuf) @@ -5250,7 +5251,7 @@ class RosterWindow: if muc_icon: invite_menuitem.set_image(muc_icon) - self.build_invite_submenu(invite_menuitem, list_online) + gui_menu_builder.build_invite_submenu(invite_menuitem, list_online) menu.append(invite_menuitem) # Send Custom Status @@ -5357,373 +5358,11 @@ class RosterWindow: jid = model[titer][C_JID].decode('utf-8') tree_path = model.get_path(titer) account = model[titer][C_ACCOUNT].decode('utf-8') - our_jid = jid == gajim.get_jid_from_account(account) contact = gajim.contacts.get_contact_with_highest_priority(account, jid) - if not contact: - return - - # Zeroconf Account - if gajim.config.get_per('accounts', account, 'is_zeroconf'): - xml = gtkgui_helpers.get_glade('zeroconf_contact_context_menu.glade') - zeroconf_contact_context_menu = xml.get_widget( - 'zeroconf_contact_context_menu') - - start_chat_menuitem = xml.get_widget('start_chat_menuitem') - execute_command_menuitem = xml.get_widget('execute_command_menuitem') - rename_menuitem = xml.get_widget('rename_menuitem') - edit_groups_menuitem = xml.get_widget('edit_groups_menuitem') - send_file_menuitem = xml.get_widget('send_file_menuitem') - assign_openpgp_key_menuitem = xml.get_widget( - 'assign_openpgp_key_menuitem') - add_special_notification_menuitem = xml.get_widget( - 'add_special_notification_menuitem') - - # 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) - - if not our_jid: - # add a special img for rename menuitem - path_to_kbd_input_img = os.path.join(gajim.DATA_DIR, 'pixmaps', - 'kbd_input.png') - img = gtk.Image() - img.set_from_file(path_to_kbd_input_img) - rename_menuitem.set_image(img) - - above_information_separator = xml.get_widget( - 'above_information_separator') - - information_menuitem = xml.get_widget('information_menuitem') - history_menuitem = xml.get_widget('history_menuitem') - - contacts = gajim.contacts.get_contacts(account, jid) - if len(contacts) > 1: # several resources - sub_menu = gtk.Menu() - start_chat_menuitem.set_submenu(sub_menu) - - iconset = gajim.config.get('iconset') - path = os.path.join(helpers.get_iconset_path(iconset), '16x16') - for c in contacts: - # icon MUST be different instance for every item - state_images = gtkgui_helpers.load_iconset(path) - item = gtk.ImageMenuItem('%s (%s)' % (c.resource, - str(c.priority))) - icon_name = helpers.get_icon_name_to_show(c, account) - icon = state_images[icon_name] - item.set_image(icon) - sub_menu.append(item) - item.connect('activate', gajim.interface.on_open_chat_window, \ - c, account, c.resource) - - else: # one resource - start_chat_menuitem.connect('activate', - self.on_roster_treeview_row_activated, tree_path) - - if gajim.capscache.is_supported(contact, NS_FILE): - send_file_menuitem.set_sensitive(True) - send_file_menuitem.connect('activate', - self.on_send_file_menuitem_activate, contact, account) - else: - send_file_menuitem.set_sensitive(False) - - execute_command_menuitem.connect('activate', - self.on_execute_command, contact, account) - - rename_menuitem.connect('activate', self.on_rename, 'contact', jid, - account) - if contact.show in ('offline', 'error'): - information_menuitem.set_sensitive(False) - send_file_menuitem.set_sensitive(False) - else: - information_menuitem.connect('activate', self.on_info_zeroconf, - contact, account) - history_menuitem.connect('activate', self.on_history, contact, - account) - - if _('Not in Roster') not in contact.get_shown_groups(): - # contact is in normal group - edit_groups_menuitem.set_no_show_all(False) - assign_openpgp_key_menuitem.set_no_show_all(False) - edit_groups_menuitem.connect('activate', self.on_edit_groups, [( - contact,account)]) - - if gajim.connections[account].gpg: - assign_openpgp_key_menuitem.connect('activate', - self.on_assign_pgp_key, contact, account) - else: - assign_openpgp_key_menuitem.set_sensitive(False) - - else: # contact is in group 'Not in Roster' - edit_groups_menuitem.set_sensitive(False) - edit_groups_menuitem.set_no_show_all(True) - assign_openpgp_key_menuitem.set_sensitive(False) - - # Remove many items when it's self contact row - if our_jid: - for menuitem in (rename_menuitem, edit_groups_menuitem, - above_information_separator): - menuitem.set_no_show_all(True) - menuitem.hide() - - # Unsensitive many items when account is offline - if gajim.connections[account].connected < 2: - for widget in (start_chat_menuitem, rename_menuitem, - edit_groups_menuitem, send_file_menuitem): - widget.set_sensitive(False) - - event_button = gtkgui_helpers.get_possible_button_event(event) - - zeroconf_contact_context_menu.attach_to_widget(self.tree, None) - zeroconf_contact_context_menu.connect('selection-done', - gtkgui_helpers.destroy_widget) - zeroconf_contact_context_menu.show_all() - zeroconf_contact_context_menu.popup(None, None, None, event_button, - event.time) - return - - # normal account - xml = gtkgui_helpers.get_glade('roster_contact_context_menu.glade') - roster_contact_context_menu = xml.get_widget( - 'roster_contact_context_menu') - - start_chat_menuitem = xml.get_widget('start_chat_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') - rename_menuitem = xml.get_widget('rename_menuitem') - edit_groups_menuitem = xml.get_widget('edit_groups_menuitem') - send_file_menuitem = xml.get_widget('send_file_menuitem') - assign_openpgp_key_menuitem = xml.get_widget( - 'assign_openpgp_key_menuitem') - set_custom_avatar_menuitem = xml.get_widget('set_custom_avatar_menuitem') - add_special_notification_menuitem = xml.get_widget( - 'add_special_notification_menuitem') - execute_command_menuitem = xml.get_widget( - 'execute_command_menuitem') - - # 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) - - # send custom status icon - blocked = False - if helpers.jid_is_blocked(account, jid): - blocked = True - else: - for group in contact.get_shown_groups(): - if helpers.group_is_blocked(account, group): - blocked = True - break - if gajim.get_transport_name_from_jid(jid, use_config_setting=False): - # Transport contact, send custom status unavailable - send_custom_status_menuitem.set_sensitive(False) - elif blocked: - send_custom_status_menuitem.set_image( \ - gtkgui_helpers.load_icon('offline')) - send_custom_status_menuitem.set_sensitive(False) - elif account in gajim.interface.status_sent_to_users and \ - jid in gajim.interface.status_sent_to_users[account]: - send_custom_status_menuitem.set_image( - gtkgui_helpers.load_icon( \ - gajim.interface.status_sent_to_users[account][jid])) - else: - icon = gtk.image_new_from_stock(gtk.STOCK_NETWORK, gtk.ICON_SIZE_MENU) - send_custom_status_menuitem.set_image(icon) - - if not our_jid: - # add a special img for rename menuitem - path_to_kbd_input_img = os.path.join(gajim.DATA_DIR, 'pixmaps', - 'kbd_input.png') - img = gtk.Image() - 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: - invite_menuitem.set_image(muc_icon) - - self.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') - - information_menuitem = xml.get_widget('information_menuitem') - history_menuitem = xml.get_widget('history_menuitem') - - contacts = gajim.contacts.get_contacts(account, jid) - - # One or several resource, we do the same for send_custom_status - status_menuitems = gtk.Menu() - send_custom_status_menuitem.set_submenu(status_menuitems) - iconset = gajim.config.get('iconset') - path = os.path.join(helpers.get_iconset_path(iconset), '16x16') - for s in ('online', 'chat', 'away', 'xa', 'dnd', 'offline'): - # icon MUST be different instance for every item - state_images = gtkgui_helpers.load_iconset(path) - status_menuitem = gtk.ImageMenuItem(helpers.get_uf_show(s)) - status_menuitem.connect('activate', self.on_send_custom_status, - [(contact, account)], s) - icon = state_images[s] - status_menuitem.set_image(icon) - status_menuitems.append(status_menuitem) - if len(contacts) > 1: # several resources - start_chat_menuitem.set_submenu(self.build_resources_submenu(contacts, - account, gajim.interface.on_open_chat_window)) - send_file_menuitem.set_submenu(self.build_resources_submenu(contacts, - account, self.on_send_file_menuitem_activate, - cap=NS_FILE)) - execute_command_menuitem.set_submenu(self.build_resources_submenu( - contacts, account, self.on_execute_command, - cap=NS_COMMANDS)) - - else: # one resource - start_chat_menuitem.connect('activate', - gajim.interface.on_open_chat_window, contact, account) - if gajim.capscache.is_supported(contact, NS_COMMANDS): - execute_command_menuitem.set_sensitive(True) - execute_command_menuitem.connect('activate', self.on_execute_command, - contact, account, contact.resource) - else: - execute_command_menuitem.set_sensitive(False) - - # This does nothing: - # our_jid_other_resource = None - # if our_jid: - # # It's another resource of us, be sure to send invite to her - # our_jid_other_resource = contact.resource - # Else this var is useless but harmless in next connect calls - - if gajim.capscache.is_supported(contact, NS_FILE): - send_file_menuitem.set_sensitive(True) - send_file_menuitem.connect('activate', - self.on_send_file_menuitem_activate, contact, account) - else: - send_file_menuitem.set_sensitive(False) - - send_single_message_menuitem.connect('activate', - self.on_send_single_message_menuitem_activate, account, contact) - - rename_menuitem.connect('activate', self.on_rename, 'contact', jid, - account) - remove_from_roster_menuitem.connect('activate', self.on_req_usub, - [(contact, account)]) - information_menuitem.connect('activate', self.on_info, contact, - account) - history_menuitem.connect('activate', self.on_history, contact, - account) - - if _('Not in Roster') not in contact.get_shown_groups(): - # contact is in normal group - add_to_roster_menuitem.hide() - add_to_roster_menuitem.set_no_show_all(True) - edit_groups_menuitem.connect('activate', self.on_edit_groups, [( - contact,account)]) - - if gajim.connections[account].gpg: - assign_openpgp_key_menuitem.connect('activate', - self.on_assign_pgp_key, contact, account) - else: - assign_openpgp_key_menuitem.set_sensitive(False) - - if contact.sub in ('from', 'both'): - send_auth_menuitem.set_sensitive(False) - else: - send_auth_menuitem.connect('activate', self.authorize, jid, account) - if contact.sub in ('to', 'both'): - ask_auth_menuitem.set_sensitive(False) - add_special_notification_menuitem.connect('activate', - self.on_add_special_notification_menuitem_activate, jid) - else: - ask_auth_menuitem.connect('activate', self.req_sub, jid, - _('I would like to add you to my roster'), account, - contact.groups, contact.name) - if contact.sub in ('to', 'none') or gajim.get_transport_name_from_jid( - jid, use_config_setting=False): - revoke_auth_menuitem.set_sensitive(False) - else: - revoke_auth_menuitem.connect('activate', self.revoke_auth, jid, - account) - - else: # contact is in group 'Not in Roster' - add_to_roster_menuitem.set_no_show_all(False) - edit_groups_menuitem.set_sensitive(False) - assign_openpgp_key_menuitem.set_sensitive(False) - subscription_menuitem.set_sensitive(False) - - add_to_roster_menuitem.connect('activate', - self.on_add_to_roster, contact, account) - - set_custom_avatar_menuitem.connect('activate', - self.on_set_custom_avatar_activate, contact, account) - # Hide items when it's self contact row - if our_jid: - menuitem = xml.get_widget('manage_contact') - menuitem.set_sensitive(False) - - # Unsensitive many items when account is offline - if gajim.connections[account].connected < 2: - for widget in (start_chat_menuitem, send_single_message_menuitem, - rename_menuitem, edit_groups_menuitem, send_file_menuitem, - subscription_menuitem, add_to_roster_menuitem, - remove_from_roster_menuitem, execute_command_menuitem, - send_custom_status_menuitem): - widget.set_sensitive(False) - - if gajim.connections[account] and gajim.connections[account].\ - privacy_rules_supported: - if helpers.jid_is_blocked(account, jid): - block_menuitem.set_no_show_all(True) - block_menuitem.hide() - if gajim.get_transport_name_from_jid(jid, use_config_setting=False): - unblock_menuitem.set_no_show_all(True) - unblock_menuitem.hide() - unignore_menuitem.set_no_show_all(False) - unignore_menuitem.connect('activate', self.on_unblock, [(contact, - account)]) - else: - unblock_menuitem.connect('activate', self.on_unblock, [(contact, - account)]) - else: - unblock_menuitem.set_no_show_all(True) - unblock_menuitem.hide() - if gajim.get_transport_name_from_jid(jid, use_config_setting=False): - block_menuitem.set_no_show_all(True) - block_menuitem.hide() - ignore_menuitem.set_no_show_all(False) - ignore_menuitem.connect('activate', self.on_block, [(contact, - account)]) - else: - block_menuitem.connect('activate', self.on_block, [(contact, - account)]) - else: - unblock_menuitem.set_no_show_all(True) - block_menuitem.set_sensitive(False) - unblock_menuitem.hide() - + menu = gui_menu_builder.get_contact_menu(contact, account) event_button = gtkgui_helpers.get_possible_button_event(event) - - roster_contact_context_menu.attach_to_widget(self.tree, None) - roster_contact_context_menu.connect('selection-done', - gtkgui_helpers.destroy_widget) - roster_contact_context_menu.show_all() - roster_contact_context_menu.popup(None, None, None, event_button, - event.time) + menu.attach_to_widget(self.tree, None) + menu.popup(None, None, None, event_button, event.time) def make_multiple_contact_menu(self, event, iters): '''Make group's popup menu''' @@ -5767,7 +5406,7 @@ class RosterWindow: if muc_icon: invite_item.set_image(muc_icon) - self.build_invite_submenu(invite_item, list_) + gui_menu_builder.build_invite_submenu(invite_item, list_) menu.append(invite_item) item = gtk.SeparatorMenuItem() # separator @@ -6012,120 +5651,6 @@ class RosterWindow: menu.show_all() menu.popup(None, None, None, event_button, event.time) - def build_resources_submenu(self, contacts, account, action, room_jid=None, - room_account=None, cap=None): - ''' Build a submenu with contact's resources. - room_jid and room_account are for action self.on_invite_to_room ''' - sub_menu = gtk.Menu() - - iconset = gajim.config.get('iconset') - if not iconset: - iconset = gajim.config.DEFAULT_ICONSET - path = os.path.join(helpers.get_iconset_path(iconset), '16x16') - for c in contacts: - # icon MUST be different instance for every item - state_images = gtkgui_helpers.load_iconset(path) - item = gtk.ImageMenuItem('%s (%s)' % (c.resource, str(c.priority))) - icon_name = helpers.get_icon_name_to_show(c, account) - icon = state_images[icon_name] - item.set_image(icon) - sub_menu.append(item) - if action == self.on_invite_to_room: - item.connect('activate', action, [(c, account)], - room_jid, room_account, c.resource) - elif action == self.on_invite_to_new_room: - item.connect('activate', action, [(c, account)], c.resource) - else: # start_chat, execute_command, send_file - item.connect('activate', action, c, account, c.resource) - if cap and \ - not gajim.capscache.is_supported(c, cap): - item.set_sensitive(False) - return sub_menu - - def build_invite_submenu(self, invite_menuitem, list_): - '''list_ in a list of (contact, account)''' - # used if we invite only one contact with several resources - contact_list = [] - if len(list_) == 1: - contact, account = list_[0] - contact_list = gajim.contacts.get_contacts(account, contact.jid) - contacts_transport = -1 - connected_accounts = [] - # -1 is at start, False when not from the same, None when jabber - for (contact, account) in list_: - if not account in connected_accounts: - connected_accounts.append(account) - transport = gajim.get_transport_name_from_jid(contact.jid) - if contacts_transport == -1: - contacts_transport = transport - elif contacts_transport != transport: - contacts_transport = False - - if contacts_transport == False: - # they are not all from the same transport - invite_menuitem.set_sensitive(False) - return - invite_to_submenu = gtk.Menu() - invite_menuitem.set_submenu(invite_to_submenu) - invite_to_new_room_menuitem = gtk.ImageMenuItem(_('_New Group Chat')) - icon = gtk.image_new_from_stock(gtk.STOCK_NEW, gtk.ICON_SIZE_MENU) - invite_to_new_room_menuitem.set_image(icon) - if len(contact_list) > 1: # several resources - invite_to_new_room_menuitem.set_submenu(self.build_resources_submenu( - contact_list, account, self.on_invite_to_new_room, cap=NS_MUC)) - elif len(list_) == 1 and gajim.capscache.is_supported(contact, NS_MUC): - invite_menuitem.set_sensitive(True) - # use resource if it's self contact - if contact.jid == gajim.get_jid_from_account(account): - resource = contact.resource - else: - resource = None - invite_to_new_room_menuitem.connect('activate', - self.on_invite_to_new_room, list_, resource) - else: - invite_menuitem.set_sensitive(False) - # transform None in 'jabber' - c_t = contacts_transport or 'jabber' - muc_jid = {} - for account in connected_accounts: - for t in gajim.connections[account].muc_jid: - muc_jid[t] = gajim.connections[account].muc_jid[t] - if c_t not in muc_jid: - invite_to_new_room_menuitem.set_sensitive(False) - rooms = [] # a list of (room_jid, account) tuple - invite_to_submenu.append(invite_to_new_room_menuitem) - rooms = [] # a list of (room_jid, account) tuple - minimized_controls = [] - for account in connected_accounts: - minimized_controls += \ - gajim.interface.minimized_controls[account].values() - for gc_control in gajim.interface.msg_win_mgr.get_controls( - message_control.TYPE_GC) + minimized_controls: - acct = gc_control.account - room_jid = gc_control.room_jid - if room_jid in gajim.gc_connected[acct] and \ - gajim.gc_connected[acct][room_jid] and \ - contacts_transport == gajim.get_transport_name_from_jid(room_jid): - rooms.append((room_jid, acct)) - if len(rooms): - item = gtk.SeparatorMenuItem() # separator - invite_to_submenu.append(item) - for (room_jid, account) in rooms: - menuitem = gtk.MenuItem(room_jid.split('@')[0]) - if len(contact_list) > 1: # several resources - menuitem.set_submenu(self.build_resources_submenu( - contact_list, account, self.on_invite_to_room, room_jid, - account)) - else: - # use resource if it's self contact - if contact.jid == gajim.get_jid_from_account(account): - resource = contact.resource - else: - resource = None - menuitem.connect('activate', self.on_invite_to_room, list_, - room_jid, account, resource) - invite_to_submenu.append(menuitem) - def get_and_connect_advanced_menuitem_menu(self, account): '''adds FOR ACCOUNT options''' xml = gtkgui_helpers.get_glade('advanced_menuitem_menu.glade')