def draw_contact(self, nick): iter_ = self._get_contact_iter(nick) if not iter_: return gc_contact = app.contacts.get_gc_contact(self._account, self.room_jid, nick) self.draw_avatar(gc_contact) if app.events.get_events(self._account, self.room_jid + '/' + nick): self._store[iter_][Column.EVENT] = True else: self._store[iter_][Column.EVENT] = False name = GLib.markup_escape_text(gc_contact.name) # Strike name if blocked fjid = self.room_jid + '/' + nick if jid_is_blocked(self._account, fjid): name = '<span strikethrough="true">%s</span>' % name # add status msg, if not empty, under contact name status = gc_contact.status if status is not None: status = status.strip() if status and app.settings.get('show_status_msgs_in_roster'): # Display only first line status = status.split('\n', 1)[0] # escape markup entities and make them small italic and fg color name += ('\n<span size="small" style="italic" alpha="70%">' '{}</span>'.format(GLib.markup_escape_text(status))) self._store[iter_][Column.TEXT] = name
def populate(self, contacts, account, typ): """ Populate the Tooltip Grid with data of from the contact """ self.current_row = 0 self.account = account if self.last_widget: self.last_widget.set_vexpand(False) self.clear_tooltip() if account == 'all': # Tooltip for merged accounts row accounts = helpers.get_notification_icon_tooltip_dict() self.spacer_label = '' self.fill_table_with_accounts(accounts) self.tooltip_grid.attach(self.table, 0, 3, 2, 1) self.table.show_all() return if typ == 'account': jid = app.get_jid_from_account(account) contacts = [] connection = app.connections[account] # get our current contact info nbr_on, nbr_total = app.\ contacts.get_nb_online_total_contacts( accounts=[account]) account_name = account if app.account_is_connected(account): account_name += ' (%s/%s)' % (repr(nbr_on), repr(nbr_total)) contact = app.contacts.create_self_contact(jid=jid, account=account, name=account_name, show=connection.get_status(), status=connection.status, resource=connection.server_resource, priority=connection.priority) if app.connections[account].gpg: contact.keyID = app.config.get_per('accounts', connection.name, 'keyid') contacts.append(contact) # if we're online ... if connection.connection: roster = connection.connection.getRoster() # in threadless connection when no roster stanza is sent # 'roster' is None if roster and roster.getItem(jid): resources = roster.getResources(jid) # ...get the contact info for our other online # resources for resource in resources: # Check if we already have this resource found = False for contact_ in contacts: if contact_.resource == resource: found = True break if found: continue show = roster.getShow(jid + '/' + resource) if not show: show = 'online' contact = app.contacts.create_self_contact( jid=jid, account=account, show=show, status=roster.getStatus( jid + '/' + resource), priority=roster.getPriority( jid + '/' + resource), resource=resource) contacts.append(contact) # Username/Account/Groupchat self.prim_contact = app.contacts.get_highest_prio_contact_from_contacts( contacts) self.contact_jid = self.prim_contact.jid name = GLib.markup_escape_text(self.prim_contact.get_shown_name()) name_markup = '<b>{}</b>'.format(name) if app.config.get('mergeaccounts'): color = app.config.get('tooltip_account_name_color') account_name = GLib.markup_escape_text(self.prim_contact.account.name) name_markup += " <span foreground='{}'>({})</span>".format( color, account_name) if account and helpers.jid_is_blocked(account, self.prim_contact.jid): name_markup += _(' [blocked]') try: if self.prim_contact.jid in app.interface.minimized_controls[account]: name_markup += _(' [minimized]') except KeyError: pass self.name.set_markup(name_markup) self.name.show() self.num_resources = 0 # put contacts in dict, where key is priority contacts_dict = {} for contact in contacts: if contact.resource: self.num_resources += 1 priority = int(contact.priority) if priority in contacts_dict: contacts_dict[priority].append(contact) else: contacts_dict[priority] = [contact] if self.num_resources > 1: self.status_label.show() transport = app.get_transport_name_from_jid(self.prim_contact.jid) if transport: file_path = os.path.join(helpers.get_transport_path(transport), '16x16') else: iconset = app.config.get('iconset') if not iconset: iconset = 'dcraven' file_path = os.path.join(helpers.get_iconset_path(iconset), '16x16') contact_keys = sorted(contacts_dict.keys()) contact_keys.reverse() for priority in contact_keys: for acontact in contacts_dict[priority]: icon_name = self._get_icon_name_for_tooltip(acontact) if acontact.status and len(acontact.status) > 25: status = '' add_text = True else: status = acontact.status add_text = False status_line = self.get_status_info(acontact.resource, acontact.priority, acontact.show, status) self.add_status_row(file_path, icon_name, status_line) if add_text: self.add_text_row(acontact.status, 2) self.tooltip_grid.attach(self.table, 0, 3, 2, 1) self.table.show_all() else: # only one resource if contact.show and contact.status: status = contact.status.strip() if status: self.status.set_text(status) self.status.show() self.status_label.show() # PEP Info self._append_pep_info(contact) # JID self.jid.set_text(self.prim_contact.jid) self.jid.show() self.jid_label.show() # contact has only one ressource if self.num_resources == 1 and contact.resource: res = GLib.markup_escape_text(contact.resource) prio = str(contact.priority) self.resource.set_text("{} ({})".format(res, prio)) self.resource.show() self.resource_label.show() if self.prim_contact.jid not in app.gc_connected[account]: if (account and self.prim_contact.sub and self.prim_contact.sub != 'both'): # ('both' is the normal sub so we don't show it) self.sub.set_text(helpers.get_uf_sub(self.prim_contact.sub)) self.sub.show() self.sub_label.show() if self.prim_contact.keyID: keyID = None if len(self.prim_contact.keyID) == 8: keyID = self.prim_contact.keyID elif len(self.prim_contact.keyID) == 16: keyID = self.prim_contact.keyID[8:] if keyID: self.pgp.set_text(keyID) self.pgp.show() self.pgp_label.show() self._set_idle_time(contact) # Avatar pixbuf = app.contacts.get_avatar( account, self.prim_contact.jid, AvatarSize.TOOLTIP) if pixbuf is None: return self.avatar.set_from_pixbuf(pixbuf) self.avatar.show() # Sets the Widget that is at the bottom to expand. # This is needed in case the Picture takes more Space then the Labels i = 1 while i < 15: if self.tooltip_grid.get_child_at(0, i): if self.tooltip_grid.get_child_at(0, i).get_visible(): self.last_widget = self.tooltip_grid.get_child_at(0, i) i += 1 self.last_widget.set_vexpand(True)
def get_transport_menu(contact, account): roster = app.interface.roster jid = contact.jid menu = Gtk.Menu() # Send single message item = Gtk.MenuItem.new_with_mnemonic(_('Send Single _Message…')) item.connect('activate', roster.on_send_single_message_menuitem_activate, account, contact) menu.append(item) if app.account_is_disconnected(account): item.set_sensitive(False) blocked = False if helpers.jid_is_blocked(account, jid): blocked = True item = Gtk.SeparatorMenuItem.new() # separator menu.append(item) # Execute Command item = Gtk.MenuItem.new_with_mnemonic(_('E_xecute Command…')) menu.append(item) item.connect('activate', roster.on_execute_command, contact, account, contact.resource) if app.account_is_disconnected(account): item.set_sensitive(False) # Manage Transport submenu item = Gtk.MenuItem.new_with_mnemonic(_('_Manage Transport')) manage_transport_submenu = Gtk.Menu() item.set_submenu(manage_transport_submenu) menu.append(item) # Modify Transport item = Gtk.MenuItem.new_with_mnemonic(_('_Modify Transport')) manage_transport_submenu.append(item) item.connect('activate', roster.on_edit_agent, contact, account) if app.account_is_disconnected(account): item.set_sensitive(False) # Rename item = Gtk.MenuItem.new_with_mnemonic(_('_Rename…')) manage_transport_submenu.append(item) item.connect('activate', roster.on_rename, 'agent', jid, account) if app.account_is_disconnected(account): item.set_sensitive(False) item = Gtk.SeparatorMenuItem.new() # separator manage_transport_submenu.append(item) # Block if blocked: item = Gtk.MenuItem.new_with_mnemonic(_('_Unblock')) item.connect('activate', roster.on_unblock, [(contact, account)]) else: item = Gtk.MenuItem.new_with_mnemonic(_('_Block')) item.connect('activate', roster.on_block, [(contact, account)]) manage_transport_submenu.append(item) if app.account_is_disconnected(account): item.set_sensitive(False) # Remove item = Gtk.MenuItem.new_with_mnemonic(_('Remo_ve')) manage_transport_submenu.append(item) item.connect('activate', roster.on_remove_agent, [(contact, account)]) if app.account_is_disconnected(account): item.set_sensitive(False) item = Gtk.SeparatorMenuItem.new() # separator menu.append(item) # Information information_menuitem = Gtk.MenuItem.new_with_mnemonic(_('_Information')) menu.append(information_menuitem) information_menuitem.connect('activate', roster.on_info, contact, account) if app.account_is_disconnected(account): information_menuitem.set_sensitive(False) menu.connect('selection-done', gtkgui_helpers.destroy_widget) menu.show_all() return menu
def get_contact_menu(contact, account, use_multiple_contacts=True, show_start_chat=True, show_encryption=False, show_buttonbar_items=True, control=None, gc_contact=None, is_anonymous=True): """ Build contact popup menu for roster and chat window. If control is not set, we hide invite_contacts_menuitem """ if not contact: return jid = contact.jid our_jid = jid == app.get_jid_from_account(account) roster = app.interface.roster xml = get_builder('contact_context_menu.ui') contact_context_menu = xml.get_object('contact_context_menu') start_chat_menuitem = xml.get_object('start_chat_menuitem') execute_command_menuitem = xml.get_object('execute_command_menuitem') rename_menuitem = xml.get_object('rename_menuitem') edit_groups_menuitem = xml.get_object('edit_groups_menuitem') send_file_menuitem = xml.get_object('send_file_menuitem') information_menuitem = xml.get_object('information_menuitem') history_menuitem = xml.get_object('history_menuitem') send_single_message_menuitem = xml.get_object('send_single_message_menuitem') invite_menuitem = xml.get_object('invite_menuitem') block_menuitem = xml.get_object('block_menuitem') unblock_menuitem = xml.get_object('unblock_menuitem') ignore_menuitem = xml.get_object('ignore_menuitem') unignore_menuitem = xml.get_object('unignore_menuitem') # Subscription submenu subscription_menuitem = xml.get_object('subscription_menuitem') send_auth_menuitem, ask_auth_menuitem, revoke_auth_menuitem = \ subscription_menuitem.get_submenu().get_children() add_to_roster_menuitem = xml.get_object('add_to_roster_menuitem') remove_from_roster_menuitem = xml.get_object( 'remove_from_roster_menuitem') manage_contact_menuitem = xml.get_object('manage_contact') convert_to_gc_menuitem = xml.get_object('convert_to_groupchat_menuitem') last_separator = xml.get_object('last_separator') items_to_hide = [] contacts = app.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, app.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', app.interface.on_open_chat_window, contact, account) if contact.supports(NS_FILE) or contact.supports(NS_JINGLE_FILE_TRANSFER_5): 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 contact.supports(NS_COMMANDS): execute_command_menuitem.set_sensitive(True) if gc_contact and gc_contact.jid and not is_anonymous: execute_command_menuitem.connect('activate', roster.on_execute_command, gc_contact, account, gc_contact.resource) else: 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.set_action_name('app.browse-history') dict_ = {'jid': GLib.Variant('s', contact.jid), 'account': GLib.Variant('s', account)} variant = GLib.Variant('a{sv}', dict_) history_menuitem.set_action_target_value(variant) if control: convert_to_gc_menuitem.connect('activate', control._on_convert_to_gc_menuitem_activate) else: items_to_hide.append(convert_to_gc_menuitem) if _('Not in contact list') not in contact.get_shown_groups(): # contact is in normal group edit_groups_menuitem.connect('activate', roster.on_edit_groups, [(contact, account)]) else: # contact is in group 'Not in contact list' edit_groups_menuitem.set_sensitive(False) # Hide items when it's self contact row if our_jid: items_to_hide += [rename_menuitem, edit_groups_menuitem] # Unsensitive many items when account is offline if app.account_is_disconnected(account): for widget in (start_chat_menuitem, rename_menuitem, edit_groups_menuitem, send_file_menuitem, convert_to_gc_menuitem, information_menuitem): widget.set_sensitive(False) if not show_start_chat: items_to_hide.append(start_chat_menuitem) 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) # Hide items when it's a pm if gc_contact: items_to_hide += [rename_menuitem, edit_groups_menuitem, subscription_menuitem, remove_from_roster_menuitem] for item in items_to_hide: item.set_no_show_all(True) item.hide() # Zeroconf Account if app.config.get_per('accounts', account, 'is_zeroconf'): for item in (send_single_message_menuitem, invite_menuitem, block_menuitem, unblock_menuitem, ignore_menuitem, unignore_menuitem, subscription_menuitem, manage_contact_menuitem, convert_to_gc_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) 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 if gc_contact: if not gc_contact.jid: # it's a pm and we don't know real JID invite_menuitem.set_sensitive(False) else: bookmarked = False c_ = app.contacts.get_contact(account, gc_contact.jid, gc_contact.resource) if c_ and c_.supports(NS_CONFERENCE): bookmarked = True build_invite_submenu(invite_menuitem, [(gc_contact, account)], show_bookmarked=bookmarked) else: force_resource = False if control and control.resource: force_resource = True build_invite_submenu(invite_menuitem, [(contact, account)], show_bookmarked=contact.supports(NS_CONFERENCE), force_resource=force_resource) if app.account_is_disconnected(account): invite_menuitem.set_sensitive(False) 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 contact list') 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) else: ask_auth_menuitem.connect('activate', roster.req_sub, jid, _('I would like to add you to my contact list'), account, contact.groups, contact.name) transport = app.get_transport_name_from_jid(jid, use_config_setting=False) if contact.sub in ('to', 'none') or transport not in ['jabber', None]: revoke_auth_menuitem.set_sensitive(False) else: revoke_auth_menuitem.connect('activate', roster.revoke_auth, jid, account) elif app.connections[account].roster_supported: # contact is in group 'Not in contact list' 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) else: add_to_roster_menuitem.hide() add_to_roster_menuitem.set_no_show_all(True) subscription_menuitem.set_sensitive(False) # Hide items when it's self contact row if our_jid: manage_contact_menuitem.set_sensitive(False) # Unsensitive items when account is offline if app.account_is_disconnected(account): for widget in (send_single_message_menuitem, subscription_menuitem, add_to_roster_menuitem, remove_from_roster_menuitem, execute_command_menuitem): widget.set_sensitive(False) con = app.connections[account] if con and (con.get_module('PrivacyLists').supported or con.get_module('Blocking').supported): transport = app.get_transport_name_from_jid(jid, use_config_setting=False) if helpers.jid_is_blocked(account, jid): block_menuitem.set_no_show_all(True) block_menuitem.hide() if transport != 'jabber': 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 transport != 'jabber': 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
def get_groupchat_roster_menu(account, control_id, self_contact, contact): menu = Gtk.Menu() item = Gtk.MenuItem(label=_('Information')) action = 'win.contact-information-%s::%s' % (control_id, contact.name) item.set_detailed_action_name(action) menu.append(item) item = Gtk.MenuItem(label=_('Add to Contact List')) action = 'app.{account}-add-contact(["{account}", "{jid}"])'.format( account=account, jid=contact.jid or '') if contact.jid is None: item.set_sensitive(False) else: item.set_detailed_action_name(action) menu.append(item) item = Gtk.MenuItem(label=_('Invite')) if contact.jid is not None: build_invite_submenu(item, ((contact, account),), show_bookmarked=True) else: item.set_sensitive(False) menu.append(item) item = Gtk.MenuItem(label=_('Execute command')) action = 'win.execute-command-%s::%s' % (control_id, contact.name) item.set_detailed_action_name(action) menu.append(item) menu.append(Gtk.SeparatorMenuItem()) if helpers.jid_is_blocked(account, contact.get_full_jid()): action = 'win.unblock-%s::%s' % (control_id, contact.name) label = _('Unblock') else: action = 'win.block-%s::%s' % (control_id, contact.name) label = _('Block') item = Gtk.MenuItem(label=label) item.set_detailed_action_name(action) menu.append(item) item = Gtk.MenuItem(label=_('Kick')) action = 'win.kick-%s::%s' % (control_id, contact.name) if is_role_change_allowed(self_contact, contact): item.set_detailed_action_name(action) else: item.set_sensitive(False) menu.append(item) item = Gtk.MenuItem(label=_('Ban')) action = 'win.ban-%s::%s' % (control_id, contact.jid or '') if is_affiliation_change_allowed(self_contact, contact, 'outcast'): item.set_detailed_action_name(action) else: item.set_sensitive(False) menu.append(item) menu.append(Gtk.SeparatorMenuItem()) item = Gtk.MenuItem(label=_('Make Owner')) action = 'win.change-affiliation-%s(["%s", "owner"])' % (control_id, contact.jid) if is_affiliation_change_allowed(self_contact, contact, 'owner'): item.set_detailed_action_name(action) else: item.set_sensitive(False) menu.append(item) item = Gtk.MenuItem(label=_('Make Admin')) action = 'win.change-affiliation-%s(["%s", "admin"])' % (control_id, contact.jid) if is_affiliation_change_allowed(self_contact, contact, 'admin'): item.set_detailed_action_name(action) else: item.set_sensitive(False) menu.append(item) item = Gtk.MenuItem(label=_('Make Member')) action = 'win.change-affiliation-%s(["%s", "member"])' % (control_id, contact.jid) if is_affiliation_change_allowed(self_contact, contact, 'member'): item.set_detailed_action_name(action) else: item.set_sensitive(False) menu.append(item) item = Gtk.MenuItem(label=_('Revoke Member')) action = 'win.change-affiliation-%s(["%s", "none"])' % (control_id, contact.jid) if is_affiliation_change_allowed(self_contact, contact, 'none'): item.set_detailed_action_name(action) else: item.set_sensitive(False) menu.append(item) if contact.role.is_visitor: label = _('Grant Voice') role = 'participant' else: label = _('Revoke Voice') role = 'visitor' item = Gtk.MenuItem(label=label) action = 'win.change-role-%s(["%s", "%s"])' % (control_id, contact.name, role) if is_role_change_allowed(self_contact, contact): item.set_detailed_action_name(action) else: item.set_sensitive(False) menu.append(item) menu.show_all() return menu
def _populate_grid(self, contacts, account, typ): """ Populate the Tooltip Grid with data of from the contact """ self.current_row = 0 self.account = account if self.last_widget: self.last_widget.set_vexpand(False) self.clear_tooltip() if account == 'all': # Tooltip for merged accounts row accounts = helpers.get_notification_icon_tooltip_dict() self.spacer_label = '' self.fill_table_with_accounts(accounts) self._ui.tooltip_grid.attach(self.table, 1, 3, 2, 1) self.table.show_all() return if typ == 'account': jid = app.get_jid_from_account(account) contacts = [] connection = app.connections[account] # get our current contact info nbr_on, nbr_total = app.\ contacts.get_nb_online_total_contacts(accounts=[account]) account_name = app.get_account_label(account) if app.account_is_connected(account): account_name += ' (%s/%s)' % (repr(nbr_on), repr(nbr_total)) contact = app.contacts.create_self_contact( jid=jid, account=account, name=account_name, show=connection.get_status(), status=connection.status, resource=connection.server_resource, priority=connection.priority) contacts.append(contact) # Username/Account/Groupchat self.prim_contact = app.contacts.get_highest_prio_contact_from_contacts( contacts) if self.prim_contact is None: log.error('No contact for Roster tooltip found') log.error('contacts: %s, typ: %s, account: %s', contacts, typ, account) return self.contact_jid = self.prim_contact.jid name = GLib.markup_escape_text(self.prim_contact.get_shown_name()) name_markup = '<b>{}</b>'.format(name) if app.config.get('mergeaccounts'): color = app.config.get('tooltip_account_name_color') account_name = GLib.markup_escape_text(self.prim_contact.account.name) name_markup += " <span foreground='{}'>({})</span>".format( color, account_name) if account and helpers.jid_is_blocked(account, self.prim_contact.jid): name_markup += _(' [blocked]') try: if self.prim_contact.jid in app.interface.minimized_controls[account]: name_markup += _(' [minimized]') except KeyError: pass self._ui.name.set_markup(name_markup) self._ui.name.show() self.num_resources = 0 # put contacts in dict, where key is priority contacts_dict = {} for contact in contacts: if contact.resource: self.num_resources += 1 priority = int(contact.priority) if priority in contacts_dict: contacts_dict[priority].append(contact) else: contacts_dict[priority] = [contact] if self.num_resources > 1: transport = app.get_transport_name_from_jid(self.prim_contact.jid) if transport == 'jabber': transport = None contact_keys = sorted(contacts_dict.keys()) contact_keys.reverse() for priority in contact_keys: for acontact in contacts_dict[priority]: show = self._get_icon_name_for_tooltip(acontact) if acontact.status and len(acontact.status) > 25: status = '' add_text = True else: status = acontact.status add_text = False status_line = self.get_status_info( acontact.resource, acontact.priority, acontact.show, status) self.add_status_row(show, status_line, transport=transport) if add_text: self.add_text_row(acontact.status, 2) self._ui.tooltip_grid.attach(self.table, 1, 3, 2, 1) self.table.show_all() else: # only one resource if contact.show and contact.status: status = contact.status.strip() if status: self._ui.status.set_text(status) self._ui.status.show() # PEP Info self._append_pep_info(contact) # JID self._ui.jid.set_text(self.prim_contact.jid) self._ui.jid.show() # contact has only one resource if self.num_resources == 1 and contact.resource: res = GLib.markup_escape_text(contact.resource) prio = str(contact.priority) self._ui.resource.set_text("{} ({})".format(res, prio)) self._ui.resource.show() self._ui.resource_label.show() if self.prim_contact.jid not in app.gc_connected[account]: if (account and self.prim_contact.sub and self.prim_contact.sub != 'both'): # ('both' is the normal sub so we don't show it) self._ui.sub.set_text(helpers.get_uf_sub(self.prim_contact.sub)) self._ui.sub.show() self._ui.sub_label.show() self._set_idle_time(contact) # Avatar scale = self._ui.tooltip_grid.get_scale_factor() surface = app.contacts.get_avatar( account, self.prim_contact.jid, AvatarSize.TOOLTIP, scale) self._ui.avatar.set_from_surface(surface) self._ui.avatar.show() app.plugin_manager.gui_extension_point( 'roster_tooltip_populate', self, contacts, self._ui.tooltip_grid) # Sets the Widget that is at the bottom to expand. # This is needed in case the Picture takes more Space than the Labels i = 1 while i < 15: if self._ui.tooltip_grid.get_child_at(1, i): if self._ui.tooltip_grid.get_child_at(1, i).get_visible(): self.last_widget = self._ui.tooltip_grid.get_child_at(1, i) i += 1 self.last_widget.set_vexpand(True)
def get_contact_menu(contact, account, use_multiple_contacts=True, show_start_chat=True, show_encryption=False, show_buttonbar_items=True, control=None, gc_contact=None, is_anonymous=True): """ Build contact popup menu for roster and chat window. If control is not set, we hide invite_contacts_menuitem """ if not contact: return jid = contact.jid our_jid = jid == app.get_jid_from_account(account) roster = app.interface.roster xml = gtkgui_helpers.get_gtk_builder('contact_context_menu.ui') contact_context_menu = xml.get_object('contact_context_menu') start_chat_menuitem = xml.get_object('start_chat_menuitem') execute_command_menuitem = xml.get_object('execute_command_menuitem') rename_menuitem = xml.get_object('rename_menuitem') edit_groups_menuitem = xml.get_object('edit_groups_menuitem') send_file_menuitem = xml.get_object('send_file_menuitem') assign_openpgp_key_menuitem = xml.get_object('assign_openpgp_key_menuitem') add_special_notification_menuitem = xml.get_object( 'add_special_notification_menuitem') information_menuitem = xml.get_object('information_menuitem') history_menuitem = xml.get_object('history_menuitem') send_custom_status_menuitem = xml.get_object('send_custom_status_menuitem') send_single_message_menuitem = xml.get_object( 'send_single_message_menuitem') invite_menuitem = xml.get_object('invite_menuitem') block_menuitem = xml.get_object('block_menuitem') unblock_menuitem = xml.get_object('unblock_menuitem') ignore_menuitem = xml.get_object('ignore_menuitem') unignore_menuitem = xml.get_object('unignore_menuitem') # Subscription submenu subscription_menuitem = xml.get_object('subscription_menuitem') send_auth_menuitem, ask_auth_menuitem, revoke_auth_menuitem = \ subscription_menuitem.get_submenu().get_children() add_to_roster_menuitem = xml.get_object('add_to_roster_menuitem') remove_from_roster_menuitem = xml.get_object('remove_from_roster_menuitem') manage_contact_menuitem = xml.get_object('manage_contact') convert_to_gc_menuitem = xml.get_object('convert_to_groupchat_menuitem') last_separator = xml.get_object('last_separator') items_to_hide = [] contacts = app.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, app.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', app.interface.on_open_chat_window, contact, account) if contact.supports(NS_FILE) or contact.supports( NS_JINGLE_FILE_TRANSFER_5): 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 contact.supports(NS_COMMANDS): execute_command_menuitem.set_sensitive(True) if gc_contact and gc_contact.jid and not is_anonymous: execute_command_menuitem.connect('activate', roster.on_execute_command, gc_contact, account, gc_contact.resource) else: 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 control: convert_to_gc_menuitem.connect( 'activate', control._on_convert_to_gc_menuitem_activate) else: items_to_hide.append(convert_to_gc_menuitem) 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 app.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: items_to_hide += [rename_menuitem, edit_groups_menuitem] # Unsensitive many items when account is offline if app.account_is_disconnected(account): for widget in (start_chat_menuitem, rename_menuitem, edit_groups_menuitem, send_file_menuitem, convert_to_gc_menuitem, information_menuitem): widget.set_sensitive(False) if not show_start_chat: items_to_hide.append(start_chat_menuitem) 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) # Hide items when it's a pm if gc_contact: items_to_hide += [ rename_menuitem, edit_groups_menuitem, subscription_menuitem, remove_from_roster_menuitem ] for item in items_to_hide: item.set_no_show_all(True) item.hide() # Zeroconf Account if app.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, subscription_menuitem, manage_contact_menuitem, convert_to_gc_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) 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 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 transport = app.get_transport_name_from_jid(jid, use_config_setting=False) if transport and transport != 'jabber': # Transport contact, send custom status unavailable send_custom_status_menuitem.set_sensitive(False) elif blocked: send_custom_status_menuitem.set_sensitive(False) if gc_contact: if not gc_contact.jid: # it's a pm and we don't know real JID invite_menuitem.set_sensitive(False) else: bookmarked = False c_ = app.contacts.get_contact(account, gc_contact.jid, gc_contact.resource) if c_ and c_.supports(NS_CONFERENCE): bookmarked = True build_invite_submenu(invite_menuitem, [(gc_contact, account)], show_bookmarked=bookmarked) else: force_resource = False if control and control.resource: force_resource = True build_invite_submenu(invite_menuitem, [(contact, account)], show_bookmarked=contact.supports(NS_CONFERENCE), force_resource=force_resource) if app.account_is_disconnected(account): invite_menuitem.set_sensitive(False) # One or several resource, we do the same for send_custom_status status_menuitems = Gtk.Menu() send_custom_status_menuitem.set_submenu(status_menuitems) for s in ('online', 'chat', 'away', 'xa', 'dnd', 'offline'): # icon MUST be different instance for every item status_menuitem = Gtk.MenuItem.new_with_label(helpers.get_uf_show(s)) status_menuitem.connect('activate', roster.on_send_custom_status, [(contact, account)], s) 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) transport = app.get_transport_name_from_jid(jid, use_config_setting=False) if contact.sub in ('to', 'none') or transport not in ['jabber', None]: revoke_auth_menuitem.set_sensitive(False) else: revoke_auth_menuitem.connect('activate', roster.revoke_auth, jid, account) elif app.connections[account].roster_supported: # 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) else: add_to_roster_menuitem.hide() add_to_roster_menuitem.set_no_show_all(True) subscription_menuitem.set_sensitive(False) # Hide items when it's self contact row if our_jid: manage_contact_menuitem.set_sensitive(False) # Unsensitive items when account is offline if app.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 app.connections[account] and (app.connections[account].\ privacy_rules_supported or app.connections[account].blocking_supported): if helpers.jid_is_blocked(account, jid): block_menuitem.set_no_show_all(True) block_menuitem.hide() if app.get_transport_name_from_jid(jid, use_config_setting=False)\ and transport != 'jabber': 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 app.get_transport_name_from_jid(jid, use_config_setting=False)\ and transport != 'jabber': 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