Esempio n. 1
0
def build_invite_submenu(invite_menuitem, list_, ignore_rooms=[],
show_bookmarked=False, force_resource=False):
    """
    list_ in a list of (contact, account)
    force_resource means we want to send invitation even if there is only one
        resource
    """
    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 transport == 'jabber':
            transport = None
        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.MenuItem.new_with_mnemonic(_(
        '_New Group Chat'))
    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 contact.supports(NS_MUC):
        invite_menuitem.set_sensitive(True)
        # use resource if it's self contact
        if contact.jid == gajim.get_jid_from_account(account) or force_resource:
            resource = contact.resource
        else:
            resource = None
        invite_to_new_room_menuitem.connect('activate',
            roster.on_invite_to_new_room, list_, resource)
    elif len(list_) > 1:
        list2 = []
        for (c, a) in list_:
            if c.supports(NS_MUC):
                list2.append((c, a))
        if len(list2) > 0:
            invite_to_new_room_menuitem.connect('activate',
                roster.on_invite_to_new_room, list2, None)
        else:
            invite_menuitem.set_sensitive(False)
    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)
    minimized_controls = []
    for account in connected_accounts:
        minimized_controls += \
            list(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
        if acct not in connected_accounts:
            continue
        room_jid = gc_control.room_jid
        if room_jid in ignore_rooms:
            continue
        if room_jid in gajim.gc_connected[acct] and \
        gajim.gc_connected[acct][room_jid] and \
        contacts_transport in ['jabber', None]:
            rooms.append((room_jid, acct))
    if len(rooms):
        item = Gtk.SeparatorMenuItem.new() # separator
        invite_to_submenu.append(item)
        for (room_jid, account) in rooms:
            menuitem = Gtk.MenuItem.new_with_label(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)

    if not show_bookmarked:
        return
    rooms2 = [] # a list of (room_jid, account) tuple
    r_jids = [] # list of room jids
    for account in connected_accounts:
        for room in gajim.connections[account].bookmarks:
            r_jid = room['jid']
            if r_jid in r_jids:
                continue
            if r_jid not in gajim.gc_connected[account] or not \
            gajim.gc_connected[account][r_jid]:
                rooms2.append((r_jid, account))
                r_jids.append(r_jid)

    if not rooms2:
        return
    item = Gtk.SeparatorMenuItem.new() # separator
    invite_to_submenu.append(item)
    for (room_jid, account) in rooms2:
        menuitem = Gtk.MenuItem.new_with_label(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)
Esempio n. 2
0
def build_invite_submenu(invite_menuitem,
                         list_,
                         ignore_rooms=[],
                         show_bookmarked=False,
                         force_resource=False):
    """
    list_ in a list of (contact, account)
    force_resource means we want to send invitation even if there is only one
        resource
    """
    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 transport == 'jabber':
            transport = None
        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.MenuItem.new_with_mnemonic(
        _('_New Group Chat'))
    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 contact.supports(NS_MUC):
        invite_menuitem.set_sensitive(True)
        # use resource if it's self contact
        if contact.jid == gajim.get_jid_from_account(
                account) or force_resource:
            resource = contact.resource
        else:
            resource = None
        invite_to_new_room_menuitem.connect('activate',
                                            roster.on_invite_to_new_room,
                                            list_, resource)
    elif len(list_) > 1:
        list2 = []
        for (c, a) in list_:
            if c.supports(NS_MUC):
                list2.append((c, a))
        if len(list2) > 0:
            invite_to_new_room_menuitem.connect('activate',
                                                roster.on_invite_to_new_room,
                                                list2, None)
        else:
            invite_menuitem.set_sensitive(False)
    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)
    minimized_controls = []
    for account in connected_accounts:
        minimized_controls += \
            list(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
        if acct not in connected_accounts:
            continue
        room_jid = gc_control.room_jid
        if room_jid in ignore_rooms:
            continue
        if room_jid in gajim.gc_connected[acct] and \
        gajim.gc_connected[acct][room_jid] and \
        contacts_transport in ['jabber', None]:
            rooms.append((room_jid, acct))
    if len(rooms):
        item = Gtk.SeparatorMenuItem.new()  # separator
        invite_to_submenu.append(item)
        for (room_jid, account) in rooms:
            menuitem = Gtk.MenuItem.new_with_label(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)

    if not show_bookmarked:
        return
    rooms2 = []  # a list of (room_jid, account) tuple
    r_jids = []  # list of room jids
    for account in connected_accounts:
        for room in gajim.connections[account].bookmarks:
            r_jid = room['jid']
            if r_jid in r_jids:
                continue
            if r_jid not in gajim.gc_connected[account] or not \
            gajim.gc_connected[account][r_jid]:
                rooms2.append((r_jid, account))
                r_jids.append(r_jid)

    if not rooms2:
        return
    item = Gtk.SeparatorMenuItem.new()  # separator
    invite_to_submenu.append(item)
    for (room_jid, account) in rooms2:
        menuitem = Gtk.MenuItem.new_with_label(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)
Esempio n. 3
0
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 == gajim.get_jid_from_account(account)
    roster = gajim.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')
    set_custom_avatar_menuitem = xml.get_object('set_custom_avatar_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')
    encryption_separator = xml.get_object('encryption_separator')
    toggle_gpg_menuitem = xml.get_object('toggle_gpg_menuitem')
    toggle_e2e_menuitem = xml.get_object('toggle_e2e_menuitem')
    last_separator = xml.get_object('last_separator')

    items_to_hide = []

    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 contact.supports(NS_FILE) or contact.supports(NS_JINGLE_FILE_TRANSFER):
            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 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:
        items_to_hide += [rename_menuitem, edit_groups_menuitem]

    # 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, 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_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)
            toggle_gpg_menuitem.connect('activate',
                    control._on_toggle_gpg_menuitem_activate)

        # disable esessions if we or the other client don't support them
        if not gajim.HAVE_PYCRYPTO or not contact.supports(NS_ESESSION) 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)
            toggle_e2e_menuitem.connect('activate',
                    control._on_toggle_e2e_menuitem_activate)

    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 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, 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 = gajim.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_ = gajim.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 gajim.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 = gajim.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 gajim.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)

    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:
        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 or gajim.connections[account].blocking_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)\
            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 gajim.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
Esempio n. 4
0
	def populate(self, contacts):
		self.create_window()

		self.create_table()
		if not contacts or len(contacts) == 0:
			# Tooltip for merged accounts row
			accounts = helpers.get_notification_icon_tooltip_dict()
			self.table.resize(2, 1)
			self.spacer_label = ''
			self.fill_table_with_accounts(accounts)
			self.win.add(self.table)
			return
		
		# primary contact
		prim_contact = gajim.contacts.get_highest_prio_contact_from_contacts(
			contacts)
		
		puny_jid = helpers.sanitize_filename(prim_contact.jid)
		table_size = 3

		file = helpers.get_avatar_path(os.path.join(gajim.AVATAR_PATH, puny_jid))
		if file:
			self.avatar_image.set_from_file(file)
			pix = self.avatar_image.get_pixbuf()
			pix = gtkgui_helpers.get_scaled_pixbuf(pix, 'tooltip')
			self.avatar_image.set_from_pixbuf(pix)
			table_size = 4
		else:
			self.avatar_image.set_from_pixbuf(None)
		vcard_table = gtk.Table(table_size, 1)
		vcard_table.set_property('column-spacing', 2)
		vcard_table.set_homogeneous(False)
		vcard_current_row = 1
		properties = []

		name_markup = u'<span weight="bold">' + \
			gobject.markup_escape_text(prim_contact.get_shown_name())\
			+ '</span>'
		if self.account and prim_contact.jid in gajim.connections[
		self.account].blocked_contacts:
			name_markup += _(' [blocked]')
		if self.account and \
		self.account in gajim.interface.minimized_controls and \
		prim_contact.jid in gajim.interface.minimized_controls[self.account]:
			name_markup += _(' [minimized]')
		properties.append((name_markup, None))

		num_resources = 0
		# put contacts in dict, where key is priority
		contacts_dict = {}
		for contact in contacts:
			if contact.resource:
				num_resources += 1
				if contact.priority in contacts_dict:
					contacts_dict[contact.priority].append(contact)
				else:
					contacts_dict[contact.priority] = [contact]

		if num_resources > 1:
			properties.append((_('Status: '),	' '))
			transport = gajim.get_transport_name_from_jid(
				prim_contact.jid)
			if transport:
				file_path = os.path.join(helpers.get_transport_path(transport),
					'16x16')
			else:
				iconset = gajim.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 contact in contacts_dict[priority]:
					status_line = self.get_status_info(contact.resource,
						contact.priority, contact.show, contact.status)
					
					icon_name = self._get_icon_name_for_tooltip(contact)
					self.add_status_row(file_path, icon_name, status_line,
						contact.last_status_time)
			properties.append((self.table,	None))

		else: # only one resource
			if contact.show:
				show = helpers.get_uf_show(contact.show) 
				if contact.last_status_time:
					vcard_current_row += 1
					if contact.show == 'offline':
						text = ' - ' + _('Last status: %s')
					else:
						text = _(' since %s')
					
					if time.strftime('%j', time.localtime())== \
							time.strftime('%j', contact.last_status_time):
					# it's today, show only the locale hour representation
						local_time = time.strftime('%X',
							contact.last_status_time)
					else:
						# time.strftime returns locale encoded string
						local_time = time.strftime('%c',
							contact.last_status_time)
					local_time = local_time.decode(
						locale.getpreferredencoding())
					text = text % local_time 
					show += text
				if self.account and \
				prim_contact.jid in gajim.gc_connected[self.account]:
					if gajim.gc_connected[self.account][prim_contact.jid]:
						show = _('Connected')
					else:
						show = _('Disconnected')
				show = '<i>' + show + '</i>'
				# we append show below
				
				if contact.status:
					status = contact.status.strip()
					if status:
						# reduce long status
						# (no more than 300 chars on line and no more than 5 lines)
						# status is wrapped
						status = helpers.reduce_chars_newlines(status, 300, 5)
						# escape markup entities. 
						status = gobject.markup_escape_text(status)
						properties.append(('<i>%s</i>' % status, None))
				properties.append((show, None))
				
		self._append_pep_info(contact, properties)
		
		properties.append((_('Jabber ID: '), prim_contact.jid ))

		# contact has only one ressource
		if num_resources == 1 and contact.resource:
			properties.append((_('Resource: '),
				gobject.markup_escape_text(contact.resource) +\
				' (' + unicode(contact.priority) + ')'))
		
		if self.account and prim_contact.sub and prim_contact.sub != 'both' and\
		prim_contact.jid not in gajim.gc_connected[self.account]:
			# ('both' is the normal sub so we don't show it)
			properties.append(( _('Subscription: '), 
				gobject.markup_escape_text(helpers.get_uf_sub(prim_contact.sub))))
	
		if prim_contact.keyID:
			keyID = None
			if len(prim_contact.keyID) == 8:
				keyID = prim_contact.keyID
			elif len(prim_contact.keyID) == 16:
				keyID = prim_contact.keyID[8:]
			if keyID:
				properties.append((_('OpenPGP: '),
					gobject.markup_escape_text(keyID)))
		
		while properties:
			property = properties.pop(0)
			vcard_current_row += 1
			vertical_fill = gtk.FILL
			if not properties and table_size == 4:
				vertical_fill |= gtk.EXPAND
			label = gtk.Label()
			label.set_alignment(0, 0)
			if property[1]:
				label.set_markup(property[0])
				vcard_table.attach(label, 1, 2, vcard_current_row,
					vcard_current_row + 1, gtk.FILL, vertical_fill, 0, 0)
				label = gtk.Label()
				label.set_alignment(0, 0)
				label.set_markup(property[1])
				label.set_line_wrap(True)
				vcard_table.attach(label, 2, 3, vcard_current_row,
					vcard_current_row + 1, gtk.EXPAND | gtk.FILL,
						vertical_fill, 0, 0)
			else:
				if isinstance(property[0], (unicode, str)): #FIXME: rm unicode?
					label.set_markup(property[0]) 
					label.set_line_wrap(True)
				else:
					label = property[0]
				vcard_table.attach(label, 1, 3, vcard_current_row,
					vcard_current_row + 1, gtk.FILL, vertical_fill, 0)
		self.avatar_image.set_alignment(0, 0)
		if table_size == 4:
			vcard_table.attach(self.avatar_image, 3, 4, 2,
				vcard_current_row + 1, gtk.FILL, gtk.FILL | gtk.EXPAND, 3, 3)
		self.win.add(vcard_table)
Esempio n. 5
0
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 == gajim.get_jid_from_account(account)
    roster = gajim.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')
    set_custom_avatar_menuitem = xml.get_object('set_custom_avatar_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')
    encryption_separator = xml.get_object('encryption_separator')
    toggle_gpg_menuitem = xml.get_object('toggle_gpg_menuitem')
    toggle_e2e_menuitem = xml.get_object('toggle_e2e_menuitem')
    last_separator = xml.get_object('last_separator')

    items_to_hide = []

    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 contact.supports(NS_FILE) or contact.supports(
                NS_JINGLE_FILE_TRANSFER):
            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 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:
        items_to_hide += [rename_menuitem, edit_groups_menuitem]

    # 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,
                       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_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)
            toggle_gpg_menuitem.connect(
                'activate', control._on_toggle_gpg_menuitem_activate)

        # disable esessions if we or the other client don't support them
        if not gajim.HAVE_PYCRYPTO or not contact.supports(NS_ESESSION) 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)
            toggle_e2e_menuitem.connect(
                'activate', control._on_toggle_e2e_menuitem_activate)

    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 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, 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 = gajim.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_ = gajim.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 gajim.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 = gajim.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 gajim.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)

    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:
        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 or gajim.connections[account].blocking_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)\
            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 gajim.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
Esempio n. 6
0
def notify(event, jid, account, parameters, advanced_notif_num=None):
	'''Check what type of notifications we want, depending on basic
	and the advanced configuration of notifications and do these notifications;
	advanced_notif_num holds the number of the first (top most) advanced
	notification'''
	# First, find what notifications we want
	do_popup = False
	do_sound = False
	do_cmd = False
	if event == 'status_change':
		new_show = parameters[0]
		status_message = parameters[1]
		# Default: No popup for status change
	elif event == 'contact_connected':
		status_message = parameters
		j = gajim.get_jid_without_resource(jid)
		server = gajim.get_server_from_jid(j)
		account_server = account + '/' + server
		block_transport = False
		if account_server in gajim.block_signed_in_notifications and \
		gajim.block_signed_in_notifications[account_server]:
			block_transport = True
		if helpers.allow_showing_notification(account, 'notify_on_signin') and \
		not gajim.block_signed_in_notifications[account] and not block_transport:
			do_popup = True
		if gajim.config.get_per('soundevents', 'contact_connected',
		'enabled') and not gajim.block_signed_in_notifications[account] and \
		not block_transport:
			do_sound = True
	elif event == 'contact_disconnected':
		status_message = parameters
		if helpers.allow_showing_notification(account, 'notify_on_signout'):
			do_popup = True
		if gajim.config.get_per('soundevents', 'contact_disconnected',
			'enabled'):
			do_sound = True
	elif event == 'new_message':
		message_type = parameters[0]
		is_first_message = parameters[1]
		nickname = parameters[2]
		if gajim.config.get('notification_preview_message'):
			message = parameters[3]
			if message.startswith('/me ') or message.startswith('/me\n'):
				message = '* ' + nickname + message[3:]
		else:
			# We don't want message preview, do_preview = False
			message = ''
		focused = parameters[4]
		if helpers.allow_showing_notification(account, 'notify_on_new_message',
		advanced_notif_num, is_first_message):
			do_popup = True
		if is_first_message and helpers.allow_sound_notification(
		'first_message_received', advanced_notif_num):
			do_sound = True
		elif not is_first_message and focused and \
		helpers.allow_sound_notification('next_message_received_focused',
		advanced_notif_num):
			do_sound = True
		elif not is_first_message and not focused and \
		helpers.allow_sound_notification('next_message_received_unfocused',
		advanced_notif_num):
			do_sound = True
	else:
		print '*Event not implemeted yet*'

	if advanced_notif_num is not None and gajim.config.get_per('notifications',
	str(advanced_notif_num), 'run_command'):
		do_cmd = True

	# Do the wanted notifications
	if do_popup:
		if event in ('contact_connected', 'contact_disconnected',
		'status_change'): # Common code for popup for these three events
			if event == 'contact_disconnected':
				show_image = 'offline.png'
				suffix = '_notif_size_bw'
			else: #Status Change or Connected
				# FIXME: for status change,
				# we don't always 'online.png', but we
				# first need 48x48 for all status
				show_image = 'online.png'
				suffix = '_notif_size_colored'
			transport_name = gajim.get_transport_name_from_jid(jid)
			img = None
			if transport_name:
				img = os.path.join(helpers.get_transport_path(transport_name),
					'48x48', show_image)
			if not img or not os.path.isfile(img):
				iconset = gajim.config.get('iconset')
				img = os.path.join(helpers.get_iconset_path(iconset), '48x48',
					show_image)
			path = gtkgui_helpers.get_path_to_generic_or_avatar(img,
				jid = jid, suffix = suffix)
			if event == 'status_change':
				title = _('%(nick)s Changed Status') % \
					{'nick': gajim.get_name_from_jid(account, jid)}
				text = _('%(nick)s is now %(status)s') % \
					{'nick': gajim.get_name_from_jid(account, jid),\
					'status': helpers.get_uf_show(gajim.SHOW_LIST[new_show])}
				if status_message:
					text = text + " : " + status_message
				popup(_('Contact Changed Status'), jid, account,
					path_to_image=path, title=title, text=text)
			elif event == 'contact_connected':
				title = _('%(nickname)s Signed In') % \
					{'nickname': gajim.get_name_from_jid(account, jid)}
				text = ''
				if status_message:
					text = status_message
				popup(_('Contact Signed In'), jid, account,
					path_to_image=path, title=title, text=text)
			elif event == 'contact_disconnected':
				title = _('%(nickname)s Signed Out') % \
					{'nickname': gajim.get_name_from_jid(account, jid)}
				text = ''
				if status_message:
					text = status_message
				popup(_('Contact Signed Out'), jid, account,
					path_to_image=path, title=title, text=text)
		elif event == 'new_message':
			if message_type == 'normal': # single message
				event_type = _('New Single Message')
				img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
					'single_msg_recv.png')
				title = _('New Single Message from %(nickname)s') % \
					{'nickname': nickname}
				text = message
			elif message_type == 'pm': # private message
				event_type = _('New Private Message')
				room_name = gajim.get_nick_from_jid(jid)
				img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
					'priv_msg_recv.png')
				title = _('New Private Message from group chat %s') % room_name
				if message:
					text = _('%(nickname)s: %(message)s') % {'nickname': nickname,
						'message': message}
				else:
					text = _('Messaged by %(nickname)s') % {'nickname': nickname}

			else: # chat message
				event_type = _('New Message')
				img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
					'chat_msg_recv.png')
				title = _('New Message from %(nickname)s') % \
					{'nickname': nickname}
				text = message
			path = gtkgui_helpers.get_path_to_generic_or_avatar(img)
			popup(event_type, jid, account, message_type,
				path_to_image=path, title=title, text=text)

	if do_sound:
		snd_file = None
		snd_event = None # If not snd_file, play the event
		if event == 'new_message':
			if advanced_notif_num is not None and gajim.config.get_per(
			'notifications', str(advanced_notif_num), 'sound') == 'yes':
				snd_file = gajim.config.get_per('notifications',
					str(advanced_notif_num), 'sound_file')
			elif advanced_notif_num is not None and gajim.config.get_per(
			'notifications', str(advanced_notif_num), 'sound') == 'no':
				pass # do not set snd_event
			elif is_first_message:
				snd_event = 'first_message_received'
			elif focused:
				snd_event = 'next_message_received_focused'
			else:
				snd_event = 'next_message_received_unfocused'
		elif event in ('contact_connected', 'contact_disconnected'):
			snd_event = event
		if snd_file:
			helpers.play_sound_file(snd_file)
		if snd_event:
			helpers.play_sound(snd_event)

	if do_cmd:
		command = gajim.config.get_per('notifications', str(advanced_notif_num),
			'command')
		try:
			helpers.exec_command(command)
		except Exception:
			pass
Esempio n. 7
0
    def populate(self, contacts):
        self.create_window()

        self.create_table()
        if not contacts or len(contacts) == 0:
            # Tooltip for merged accounts row
            accounts = helpers.get_notification_icon_tooltip_dict()
            self.spacer_label = ''
            self.fill_table_with_accounts(accounts)
            self.win.add(self.table)
            return

        # primary contact
        prim_contact = gajim.contacts.get_highest_prio_contact_from_contacts(
            contacts)

        puny_jid = helpers.sanitize_filename(prim_contact.jid)
        table_size = 3

        file_ = helpers.get_avatar_path(os.path.join(gajim.AVATAR_PATH,
            puny_jid))
        if file_:
            with open(file_, 'rb') as file_data:
                pix = gtkgui_helpers.get_pixbuf_from_data(file_data.read())
            pix = gtkgui_helpers.get_scaled_pixbuf(pix, 'tooltip')
            self.avatar_image.set_from_pixbuf(pix)
            table_size = 4
        else:
            self.avatar_image.set_from_pixbuf(None)
        vcard_table = Gtk.Grid()
        vcard_table.insert_row(0)
        for i in range(0, table_size):
            vcard_table.insert_column(0)
        vcard_table.set_property('column-spacing', 2)
        vcard_current_row = 1
        properties = []

        name_markup = '<span weight="bold">' + GLib.markup_escape_text(
            prim_contact.get_shown_name()) + '</span>'
        if gajim.config.get('mergeaccounts'):
            name_markup += " <span foreground='%s'>(%s)</span>" % (
                gajim.config.get('tooltip_account_name_color'),
                GLib.markup_escape_text(prim_contact.account.name))

        if self.account and helpers.jid_is_blocked(self.account,
        prim_contact.jid):
            name_markup += _(' [blocked]')
        if self.account and \
        self.account in gajim.interface.minimized_controls and \
        prim_contact.jid in gajim.interface.minimized_controls[self.account]:
            name_markup += _(' [minimized]')
        properties.append((name_markup, None))

        num_resources = 0
        # put contacts in dict, where key is priority
        contacts_dict = {}
        for contact in contacts:
            if contact.resource:
                num_resources += 1
                if contact.priority in contacts_dict:
                    contacts_dict[int(contact.priority)].append(contact)
                else:
                    contacts_dict[int(contact.priority)] = [contact]

        if num_resources > 1:
            properties.append((_('Status: '),       ' '))
            transport = gajim.get_transport_name_from_jid(prim_contact.jid)
            if transport:
                file_path = os.path.join(helpers.get_transport_path(transport),
                    '16x16')
            else:
                iconset = gajim.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]:
                    status_line = self.get_status_info(acontact.resource,
                        acontact.priority, acontact.show, acontact.status)

                    icon_name = self._get_icon_name_for_tooltip(acontact)
                    self.add_status_row(file_path, icon_name, status_line,
                        acontact.last_status_time)
            properties.append((self.table,  None))

        else: # only one resource
            if contact.show:
                show = helpers.get_uf_show(contact.show)
                if not self.check_last_time and self.account:
                    if contact.show == 'offline':
                        if not contact.last_status_time:
                            gajim.connections[self.account].\
                                request_last_status_time(contact.jid, '')
                        else:
                            self.check_last_time = contact.last_status_time
                    elif contact.resource:
                        gajim.connections[self.account].\
                            request_last_status_time(
                            contact.jid, contact.resource)
                        if contact.last_activity_time:
                            self.check_last_time = contact.last_activity_time
                else:
                    self.check_last_time = None
                if contact.last_status_time:
                    vcard_current_row += 1
                    if contact.show == 'offline':
                        text = ' - ' + _('Last status: %s')
                    else:
                        text = _(' since %s')

                    if time.strftime('%j', time.localtime()) == \
                        time.strftime('%j', contact.last_status_time):
                        # it's today, show only the locale hour representation
                        local_time = time.strftime('%X',
                            contact.last_status_time)
                    else:
                        # time.strftime returns locale encoded string
                        local_time = time.strftime('%c',
                            contact.last_status_time)

                    text = text % local_time
                    show += text
                if self.account and \
                prim_contact.jid in gajim.gc_connected[self.account]:
                    if gajim.gc_connected[self.account][prim_contact.jid]:
                        show = _('Connected')
                    else:
                        show = _('Disconnected')
                show = self.colorize_status(show)

                if contact.status:
                    status = contact.status.strip()
                    if status:
                        # reduce long status
                        # (no more than 300 chars on line and no more than
                        # 5 lines)
                        # status is wrapped
                        status = helpers.reduce_chars_newlines(status, 300, 5)
                        # escape markup entities.
                        status = GLib.markup_escape_text(status)
                        properties.append(('<i>%s</i>' % status, None))
                properties.append((show, None))

        self._append_pep_info(contact, properties)

        properties.append((_('Jabber ID: '), '\u200E' + "<b>%s</b>" % \
            prim_contact.jid))

        # contact has only one ressource
        if num_resources == 1 and contact.resource:
            properties.append((_('Resource: '), GLib.markup_escape_text(
                contact.resource) + ' (' + str(contact.priority) + ')'))

        if self.account and prim_contact.sub and prim_contact.sub != 'both' and\
        prim_contact.jid not in gajim.gc_connected[self.account]:
            # ('both' is the normal sub so we don't show it)
            properties.append(( _('Subscription: '), GLib.markup_escape_text(
                helpers.get_uf_sub(prim_contact.sub))))

        if prim_contact.keyID:
            keyID = None
            if len(prim_contact.keyID) == 8:
                keyID = prim_contact.keyID
            elif len(prim_contact.keyID) == 16:
                keyID = prim_contact.keyID[8:]
            if keyID:
                properties.append((_('OpenPGP: '), GLib.markup_escape_text(
                    keyID)))

        if contact.last_activity_time:
            last_active = datetime(*contact.last_activity_time[:6])
            current = datetime.now()

            diff = current - last_active
            diff = timedelta(diff.days, diff.seconds)

            if last_active.date() == current.date():
                formatted = last_active.strftime("%X")
            else:
                formatted = last_active.strftime("%c")

            # Do not show the "Idle since" and "Idle for" items if there
            # is no meaningful difference between last activity time and
            # current time.
            if diff.days > 0 or diff.seconds > 0:
                cs = "<span foreground='%s'>" % gajim.config.get(
                    'tooltip_idle_color')
                cs += '%s</span>'
                properties.append((str(), None))
                idle_since = cs % _("Idle since %s")
                properties.append((idle_since % formatted, None))
                idle_for = cs % _("Idle for %s")
                properties.append((idle_for % str(diff), None))

        while properties:
            property_ = properties.pop(0)
            vcard_current_row += 1
            label = Gtk.Label()
            if not properties and table_size == 4:
                label.set_vexpand(True)
            label.set_halign(Gtk.Align.START)
            label.set_valign(Gtk.Align.START)
            if property_[1]:
                label.set_markup(property_[0])
                vcard_table.attach(label, 1, vcard_current_row, 1, 1)
                label = Gtk.Label()
                if not properties and table_size == 4:
                    label.set_vexpand(True)
                label.set_halign(Gtk.Align.START)
                label.set_valign(Gtk.Align.START)
                label.set_markup(property_[1])
                label.set_line_wrap(True)
                vcard_table.attach(label, 2, vcard_current_row, 1, 1)
            else:
                if isinstance(property_[0], str):
                    label.set_markup(property_[0])
                    label.set_line_wrap(True)
                else:
                    label = property_[0]
                vcard_table.attach(label, 1, vcard_current_row, 2, 1)
        self.avatar_image.set_halign(Gtk.Align.START)
        self.avatar_image.set_valign(Gtk.Align.START)
        if table_size == 4:
            vcard_table.attach(self.avatar_image, 3, 2, 1, vcard_current_row - 1)

        gajim.plugin_manager.gui_extension_point('roster_tooltip_populate',
            self, contacts, vcard_table)
        self.win.add(vcard_table)
Esempio n. 8
0
    def populate(self, contacts):
        self.create_window()

        self.create_table()
        if not contacts or len(contacts) == 0:
            # Tooltip for merged accounts row
            accounts = helpers.get_notification_icon_tooltip_dict()
            self.spacer_label = ''
            self.fill_table_with_accounts(accounts)
            self.win.add(self.table)
            return

        # primary contact
        prim_contact = gajim.contacts.get_highest_prio_contact_from_contacts(
            contacts)

        puny_jid = helpers.sanitize_filename(prim_contact.jid)
        table_size = 3

        file_ = helpers.get_avatar_path(os.path.join(gajim.AVATAR_PATH,
            puny_jid))
        if file_:
            with open(file_, 'rb') as file_data:
                pix = gtkgui_helpers.get_pixbuf_from_data(file_data.read())
            pix = gtkgui_helpers.get_scaled_pixbuf(pix, 'tooltip')
            self.avatar_image.set_from_pixbuf(pix)
            table_size = 4
        else:
            self.avatar_image.set_from_pixbuf(None)
        vcard_table = Gtk.Grid()
        vcard_table.insert_row(0)
        for i in range(0, table_size):
            vcard_table.insert_column(0)
        vcard_table.set_property('column-spacing', 2)
        vcard_current_row = 1
        properties = []

        name_markup = '<span weight="bold">' + GLib.markup_escape_text(
            prim_contact.get_shown_name()) + '</span>'
        if gajim.config.get('mergeaccounts'):
            name_markup += " <span foreground='%s'>(%s)</span>" % (
                gajim.config.get('tooltip_account_name_color'),
                GLib.markup_escape_text(prim_contact.account.name))

        if self.account and helpers.jid_is_blocked(self.account,
        prim_contact.jid):
            name_markup += _(' [blocked]')
        if self.account and \
        self.account in gajim.interface.minimized_controls and \
        prim_contact.jid in gajim.interface.minimized_controls[self.account]:
            name_markup += _(' [minimized]')
        properties.append((name_markup, None))

        num_resources = 0
        # put contacts in dict, where key is priority
        contacts_dict = {}
        for contact in contacts:
            if contact.resource:
                num_resources += 1
                if contact.priority in contacts_dict:
                    contacts_dict[int(contact.priority)].append(contact)
                else:
                    contacts_dict[int(contact.priority)] = [contact]

        if num_resources > 1:
            properties.append((_('Status: '),       ' '))
            transport = gajim.get_transport_name_from_jid(prim_contact.jid)
            if transport:
                file_path = os.path.join(helpers.get_transport_path(transport),
                    '16x16')
            else:
                iconset = gajim.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]:
                    status_line = self.get_status_info(acontact.resource,
                        acontact.priority, acontact.show, acontact.status)

                    icon_name = self._get_icon_name_for_tooltip(acontact)
                    self.add_status_row(file_path, icon_name, status_line,
                        acontact.last_status_time)
            properties.append((self.table,  None))

        else: # only one resource
            if contact.show:
                show = helpers.get_uf_show(contact.show)
                if not self.check_last_time and self.account:
                    if contact.show == 'offline':
                        if not contact.last_status_time:
                            gajim.connections[self.account].\
                                request_last_status_time(contact.jid, '')
                        else:
                            self.check_last_time = contact.last_status_time
                    elif contact.resource:
                        gajim.connections[self.account].\
                            request_last_status_time(
                            contact.jid, contact.resource)
                        if contact.last_activity_time:
                            self.check_last_time = contact.last_activity_time
                else:
                    self.check_last_time = None
                if contact.last_status_time:
                    vcard_current_row += 1
                    if contact.show == 'offline':
                        text = ' - ' + _('Last status: %s')
                    else:
                        text = _(' since %s')

                    if time.strftime('%j', time.localtime()) == \
                        time.strftime('%j', contact.last_status_time):
                        # it's today, show only the locale hour representation
                        local_time = time.strftime('%X',
                            contact.last_status_time)
                    else:
                        # time.strftime returns locale encoded string
                        local_time = time.strftime('%c',
                            contact.last_status_time)

                    text = text % local_time
                    show += text
                if self.account and \
                prim_contact.jid in gajim.gc_connected[self.account]:
                    if gajim.gc_connected[self.account][prim_contact.jid]:
                        show = _('Connected')
                    else:
                        show = _('Disconnected')
                show = self.colorize_status(show)

                if contact.status:
                    status = contact.status.strip()
                    if status:
                        # reduce long status
                        # (no more than 300 chars on line and no more than
                        # 5 lines)
                        # status is wrapped
                        status = helpers.reduce_chars_newlines(status, 300, 5)
                        # escape markup entities.
                        status = GLib.markup_escape_text(status)
                        properties.append(('<i>%s</i>' % status, None))
                properties.append((show, None))

        self._append_pep_info(contact, properties)

        properties.append((_('Jabber ID: '), '\u200E' + "<b>%s</b>" % \
            prim_contact.jid))

        # contact has only one ressource
        if num_resources == 1 and contact.resource:
            properties.append((_('Resource: '), GLib.markup_escape_text(
                contact.resource) + ' (' + str(contact.priority) + ')'))

        if self.account and prim_contact.sub and prim_contact.sub != 'both' and\
        prim_contact.jid not in gajim.gc_connected[self.account]:
            # ('both' is the normal sub so we don't show it)
            properties.append(( _('Subscription: '), GLib.markup_escape_text(
                helpers.get_uf_sub(prim_contact.sub))))

        if prim_contact.keyID:
            keyID = None
            if len(prim_contact.keyID) == 8:
                keyID = prim_contact.keyID
            elif len(prim_contact.keyID) == 16:
                keyID = prim_contact.keyID[8:]
            if keyID:
                properties.append((_('OpenPGP: '), GLib.markup_escape_text(
                    keyID)))

        if contact.last_activity_time:
            last_active = datetime(*contact.last_activity_time[:6])
            current = datetime.now()

            diff = current - last_active
            diff = timedelta(diff.days, diff.seconds)

            if last_active.date() == current.date():
                formatted = last_active.strftime("%X")
            else:
                formatted = last_active.strftime("%c")

            # Do not show the "Idle since" and "Idle for" items if there
            # is no meaningful difference between last activity time and
            # current time.
            if diff.days > 0 or diff.seconds > 0:
                cs = "<span foreground='%s'>" % gajim.config.get(
                    'tooltip_idle_color')
                cs += '%s</span>'
                properties.append((str(), None))
                idle_since = cs % _("Idle since %s")
                properties.append((idle_since % formatted, None))
                idle_for = cs % _("Idle for %s")
                properties.append((idle_for % str(diff), None))

        while properties:
            property_ = properties.pop(0)
            vcard_current_row += 1
            label = Gtk.Label()
            if not properties and table_size == 4:
                label.set_vexpand(True)
            label.set_alignment(0, 0)
            if property_[1]:
                label.set_markup(property_[0])
                vcard_table.attach(label, 1, vcard_current_row, 1, 1)
                label = Gtk.Label()
                if not properties and table_size == 4:
                    label.set_vexpand(True)
                label.set_alignment(0, 0)
                label.set_markup(property_[1])
                label.set_line_wrap(True)
                vcard_table.attach(label, 2, vcard_current_row, 1, 1)
            else:
                if isinstance(property_[0], str):
                    label.set_markup(property_[0])
                    label.set_line_wrap(True)
                else:
                    label = property_[0]
                vcard_table.attach(label, 1, vcard_current_row, 2, 1)
        self.avatar_image.set_alignment(0, 0)
        if table_size == 4:
            vcard_table.attach(self.avatar_image, 3, 2, 1, vcard_current_row - 1)

        gajim.plugin_manager.gui_extension_point('roster_tooltip_populate',
            self, contacts, vcard_table)
        self.win.add(vcard_table)
Esempio n. 9
0
    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 = gajim.get_jid_from_account(account)
            contacts = []
            connection = gajim.connections[account]
            # get our current contact info

            nbr_on, nbr_total = gajim.\
                contacts.get_nb_online_total_contacts(
                accounts=[account])
            account_name = account
            if gajim.account_is_connected(account):
                account_name += ' (%s/%s)' % (repr(nbr_on),
                    repr(nbr_total))
            contact = gajim.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 gajim.connections[account].gpg:
                contact.keyID = gajim.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 = gajim.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 = gajim.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 gajim.config.get('mergeaccounts'):
            color = gajim.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 gajim.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 = gajim.get_transport_name_from_jid(self.prim_contact.jid)
            if transport:
                file_path = os.path.join(helpers.get_transport_path(transport),
                    '16x16')
            else:
                iconset = gajim.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,
                        acontact.last_status_time)
                    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:
                request_time = False
                try:
                    last_time = self.check_last_time[contact]
                    if isinstance(last_time, float) and last_time < time.time() - 60:
                        request_time = True
                except KeyError:
                    request_time = True

                if request_time:
                    if contact.show == 'offline':
                        gajim.connections[account].\
                            request_last_status_time(contact.jid, '')
                    elif contact.resource:
                        gajim.connections[account].\
                            request_last_status_time(
                            contact.jid, contact.resource)
                    self.check_last_time[contact] = time.time()

                if 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 gajim.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
        puny_jid = helpers.sanitize_filename(self.prim_contact.jid)
        file_ = helpers.get_avatar_path(os.path.join(gajim.AVATAR_PATH,
            puny_jid))
        if file_:
            with open(file_, 'rb') as file_data:
                pix = gtkgui_helpers.get_pixbuf_from_data(file_data.read())
            pix = gtkgui_helpers.get_scaled_pixbuf(pix, 'tooltip')
            self.avatar.set_from_pixbuf(pix)
            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)
Esempio n. 10
0
def notify(event, jid, account, parameters, advanced_notif_num=None):
    '''Check what type of notifications we want, depending on basic
	and the advanced configuration of notifications and do these notifications;
	advanced_notif_num holds the number of the first (top most) advanced
	notification'''
    # First, find what notifications we want
    do_popup = False
    do_sound = False
    do_cmd = False
    if event == 'status_change':
        new_show = parameters[0]
        status_message = parameters[1]
        # Default: No popup for status change
    elif event == 'contact_connected':
        status_message = parameters
        j = gajim.get_jid_without_resource(jid)
        server = gajim.get_server_from_jid(j)
        account_server = account + '/' + server
        block_transport = False
        if account_server in gajim.block_signed_in_notifications and \
        gajim.block_signed_in_notifications[account_server]:
            block_transport = True
        if helpers.allow_showing_notification(account, 'notify_on_signin') and \
        not gajim.block_signed_in_notifications[account] and not block_transport:
            do_popup = True
        if gajim.config.get_per('soundevents', 'contact_connected',
        'enabled') and not gajim.block_signed_in_notifications[account] and \
        not block_transport:
            do_sound = True
    elif event == 'contact_disconnected':
        status_message = parameters
        if helpers.allow_showing_notification(account, 'notify_on_signout'):
            do_popup = True
        if gajim.config.get_per('soundevents', 'contact_disconnected',
                                'enabled'):
            do_sound = True
    elif event == 'new_message':
        message_type = parameters[0]
        is_first_message = parameters[1]
        nickname = parameters[2]
        if gajim.config.get('notification_preview_message'):
            message = parameters[3]
            if message.startswith('/me ') or message.startswith('/me\n'):
                message = '* ' + nickname + message[3:]
        else:
            # We don't want message preview, do_preview = False
            message = ''
        focused = parameters[4]
        if helpers.allow_showing_notification(account, 'notify_on_new_message',
                                              advanced_notif_num,
                                              is_first_message):
            do_popup = True
        if is_first_message and helpers.allow_sound_notification(
                'first_message_received', advanced_notif_num):
            do_sound = True
        elif not is_first_message and focused and \
        helpers.allow_sound_notification('next_message_received_focused',
        advanced_notif_num):
            do_sound = True
        elif not is_first_message and not focused and \
        helpers.allow_sound_notification('next_message_received_unfocused',
        advanced_notif_num):
            do_sound = True
    else:
        print '*Event not implemeted yet*'

    if advanced_notif_num is not None and gajim.config.get_per(
            'notifications', str(advanced_notif_num), 'run_command'):
        do_cmd = True

    # Do the wanted notifications
    if do_popup:
        if event in ('contact_connected', 'contact_disconnected',
                     'status_change'
                     ):  # Common code for popup for these three events
            if event == 'contact_disconnected':
                show_image = 'offline.png'
                suffix = '_notif_size_bw'
            else:  #Status Change or Connected
                # FIXME: for status change,
                # we don't always 'online.png', but we
                # first need 48x48 for all status
                show_image = 'online.png'
                suffix = '_notif_size_colored'
            transport_name = gajim.get_transport_name_from_jid(jid)
            img = None
            if transport_name:
                img = os.path.join(helpers.get_transport_path(transport_name),
                                   '48x48', show_image)
            if not img or not os.path.isfile(img):
                iconset = gajim.config.get('iconset')
                img = os.path.join(helpers.get_iconset_path(iconset), '48x48',
                                   show_image)
            path = gtkgui_helpers.get_path_to_generic_or_avatar(img,
                                                                jid=jid,
                                                                suffix=suffix)
            if event == 'status_change':
                title = _('%(nick)s Changed Status') % \
                 {'nick': gajim.get_name_from_jid(account, jid)}
                text = _('%(nick)s is now %(status)s') % \
                 {'nick': gajim.get_name_from_jid(account, jid),\
                 'status': helpers.get_uf_show(gajim.SHOW_LIST[new_show])}
                if status_message:
                    text = text + " : " + status_message
                popup(_('Contact Changed Status'),
                      jid,
                      account,
                      path_to_image=path,
                      title=title,
                      text=text)
            elif event == 'contact_connected':
                title = _('%(nickname)s Signed In') % \
                 {'nickname': gajim.get_name_from_jid(account, jid)}
                text = ''
                if status_message:
                    text = status_message
                popup(_('Contact Signed In'),
                      jid,
                      account,
                      path_to_image=path,
                      title=title,
                      text=text)
            elif event == 'contact_disconnected':
                title = _('%(nickname)s Signed Out') % \
                 {'nickname': gajim.get_name_from_jid(account, jid)}
                text = ''
                if status_message:
                    text = status_message
                popup(_('Contact Signed Out'),
                      jid,
                      account,
                      path_to_image=path,
                      title=title,
                      text=text)
        elif event == 'new_message':
            if message_type == 'normal':  # single message
                event_type = _('New Single Message')
                img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
                                   'single_msg_recv.png')
                title = _('New Single Message from %(nickname)s') % \
                 {'nickname': nickname}
                text = message
            elif message_type == 'pm':  # private message
                event_type = _('New Private Message')
                room_name = gajim.get_nick_from_jid(jid)
                img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
                                   'priv_msg_recv.png')
                title = _('New Private Message from group chat %s') % room_name
                if message:
                    text = _('%(nickname)s: %(message)s') % {
                        'nickname': nickname,
                        'message': message
                    }
                else:
                    text = _('Messaged by %(nickname)s') % {
                        'nickname': nickname
                    }

            else:  # chat message
                event_type = _('New Message')
                img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
                                   'chat_msg_recv.png')
                title = _('New Message from %(nickname)s') % \
                 {'nickname': nickname}
                text = message
            path = gtkgui_helpers.get_path_to_generic_or_avatar(img)
            popup(event_type,
                  jid,
                  account,
                  message_type,
                  path_to_image=path,
                  title=title,
                  text=text)

    if do_sound:
        snd_file = None
        snd_event = None  # If not snd_file, play the event
        if event == 'new_message':
            if advanced_notif_num is not None and gajim.config.get_per(
                    'notifications', str(advanced_notif_num),
                    'sound') == 'yes':
                snd_file = gajim.config.get_per('notifications',
                                                str(advanced_notif_num),
                                                'sound_file')
            elif advanced_notif_num is not None and gajim.config.get_per(
                    'notifications', str(advanced_notif_num), 'sound') == 'no':
                pass  # do not set snd_event
            elif is_first_message:
                snd_event = 'first_message_received'
            elif focused:
                snd_event = 'next_message_received_focused'
            else:
                snd_event = 'next_message_received_unfocused'
        elif event in ('contact_connected', 'contact_disconnected'):
            snd_event = event
        if snd_file:
            helpers.play_sound_file(snd_file)
        if snd_event:
            helpers.play_sound(snd_event)

    if do_cmd:
        command = gajim.config.get_per('notifications',
                                       str(advanced_notif_num), 'command')
        try:
            helpers.exec_command(command)
        except Exception:
            pass
Esempio n. 11
0
    def populate(self, contacts):
        self.create_window()

        self.create_table()
        if not contacts or len(contacts) == 0:
            # Tooltip for merged accounts row
            accounts = helpers.get_notification_icon_tooltip_dict()
            self.table.resize(2, 1)
            self.spacer_label = ''
            self.fill_table_with_accounts(accounts)
            self.win.add(self.table)
            return

        # primary contact
        prim_contact = gajim.contacts.get_highest_prio_contact_from_contacts(
            contacts)

        puny_jid = helpers.sanitize_filename(prim_contact.jid)
        table_size = 3

        file = helpers.get_avatar_path(
            os.path.join(gajim.AVATAR_PATH, puny_jid))
        if file:
            self.avatar_image.set_from_file(file)
            pix = self.avatar_image.get_pixbuf()
            pix = gtkgui_helpers.get_scaled_pixbuf(pix, 'tooltip')
            self.avatar_image.set_from_pixbuf(pix)
            table_size = 4
        else:
            self.avatar_image.set_from_pixbuf(None)
        vcard_table = gtk.Table(table_size, 1)
        vcard_table.set_property('column-spacing', 2)
        vcard_table.set_homogeneous(False)
        vcard_current_row = 1
        properties = []

        name_markup = u'<span weight="bold">' + \
         gobject.markup_escape_text(prim_contact.get_shown_name())\
         + '</span>'
        if self.account and prim_contact.jid in gajim.connections[
                self.account].blocked_contacts:
            name_markup += _(' [blocked]')
        if self.account and \
        self.account in gajim.interface.minimized_controls and \
        prim_contact.jid in gajim.interface.minimized_controls[self.account]:
            name_markup += _(' [minimized]')
        properties.append((name_markup, None))

        num_resources = 0
        # put contacts in dict, where key is priority
        contacts_dict = {}
        for contact in contacts:
            if contact.resource:
                num_resources += 1
                if contact.priority in contacts_dict:
                    contacts_dict[contact.priority].append(contact)
                else:
                    contacts_dict[contact.priority] = [contact]

        if num_resources > 1:
            properties.append((_('Status: '), ' '))
            transport = gajim.get_transport_name_from_jid(prim_contact.jid)
            if transport:
                file_path = os.path.join(helpers.get_transport_path(transport),
                                         '16x16')
            else:
                iconset = gajim.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 contact in contacts_dict[priority]:
                    status_line = self.get_status_info(contact.resource,
                                                       contact.priority,
                                                       contact.show,
                                                       contact.status)

                    icon_name = self._get_icon_name_for_tooltip(contact)
                    self.add_status_row(file_path, icon_name, status_line,
                                        contact.last_status_time)
            properties.append((self.table, None))

        else:  # only one resource
            if contact.show:
                show = helpers.get_uf_show(contact.show)
                if contact.last_status_time:
                    vcard_current_row += 1
                    if contact.show == 'offline':
                        text = ' - ' + _('Last status: %s')
                    else:
                        text = _(' since %s')

                    if time.strftime('%j', time.localtime())== \
                      time.strftime('%j', contact.last_status_time):
                        # it's today, show only the locale hour representation
                        local_time = time.strftime('%X',
                                                   contact.last_status_time)
                    else:
                        # time.strftime returns locale encoded string
                        local_time = time.strftime('%c',
                                                   contact.last_status_time)
                    local_time = local_time.decode(
                        locale.getpreferredencoding())
                    text = text % local_time
                    show += text
                if self.account and \
                prim_contact.jid in gajim.gc_connected[self.account]:
                    if gajim.gc_connected[self.account][prim_contact.jid]:
                        show = _('Connected')
                    else:
                        show = _('Disconnected')
                show = '<i>' + show + '</i>'
                # we append show below

                if contact.status:
                    status = contact.status.strip()
                    if status:
                        # reduce long status
                        # (no more than 300 chars on line and no more than 5 lines)
                        # status is wrapped
                        status = helpers.reduce_chars_newlines(status, 300, 5)
                        # escape markup entities.
                        status = gobject.markup_escape_text(status)
                        properties.append(('<i>%s</i>' % status, None))
                properties.append((show, None))

        self._append_pep_info(contact, properties)

        properties.append((_('Jabber ID: '), prim_contact.jid))

        # contact has only one ressource
        if num_resources == 1 and contact.resource:
            properties.append((_('Resource: '),
             gobject.markup_escape_text(contact.resource) +\
             ' (' + unicode(contact.priority) + ')'))

        if self.account and prim_contact.sub and prim_contact.sub != 'both' and\
        prim_contact.jid not in gajim.gc_connected[self.account]:
            # ('both' is the normal sub so we don't show it)
            properties.append((_('Subscription: '),
                               gobject.markup_escape_text(
                                   helpers.get_uf_sub(prim_contact.sub))))

        if prim_contact.keyID:
            keyID = None
            if len(prim_contact.keyID) == 8:
                keyID = prim_contact.keyID
            elif len(prim_contact.keyID) == 16:
                keyID = prim_contact.keyID[8:]
            if keyID:
                properties.append(
                    (_('OpenPGP: '), gobject.markup_escape_text(keyID)))

        while properties:
            property = properties.pop(0)
            vcard_current_row += 1
            vertical_fill = gtk.FILL
            if not properties and table_size == 4:
                vertical_fill |= gtk.EXPAND
            label = gtk.Label()
            label.set_alignment(0, 0)
            if property[1]:
                label.set_markup(property[0])
                vcard_table.attach(label, 1, 2, vcard_current_row,
                                   vcard_current_row + 1, gtk.FILL,
                                   vertical_fill, 0, 0)
                label = gtk.Label()
                label.set_alignment(0, 0)
                label.set_markup(property[1])
                label.set_line_wrap(True)
                vcard_table.attach(label, 2, 3, vcard_current_row,
                                   vcard_current_row + 1,
                                   gtk.EXPAND | gtk.FILL, vertical_fill, 0, 0)
            else:
                if isinstance(property[0],
                              (unicode, str)):  #FIXME: rm unicode?
                    label.set_markup(property[0])
                    label.set_line_wrap(True)
                else:
                    label = property[0]
                vcard_table.attach(label, 1, 3, vcard_current_row,
                                   vcard_current_row + 1, gtk.FILL,
                                   vertical_fill, 0)
        self.avatar_image.set_alignment(0, 0)
        if table_size == 4:
            vcard_table.attach(self.avatar_image, 3, 4, 2,
                               vcard_current_row + 1, gtk.FILL,
                               gtk.FILL | gtk.EXPAND, 3, 3)
        self.win.add(vcard_table)
Esempio n. 12
0
    def populate(self, contacts):
        self.create_window()
        self.hbox = gtk.HBox()
        self.hbox.set_homogeneous(False)
        self.hbox.set_spacing(0)
        self.create_table()
        if not contacts or len(contacts) == 0:
            # Tooltip for merged accounts row
            accounts = self.get_accounts_info()
            self.current_row = 0
            self.table.resize(2, 1)
            self.spacer_label = ""
            self.fill_table_with_accounts(accounts)
            self.hbox.add(self.table)
            self.win.add(self.hbox)
            return
            # primary contact
        prim_contact = gajim.get_highest_prio_contact_from_contacts(contacts)

        # try to find the image for the contact status
        icon_name = helpers.get_icon_name_to_show(prim_contact)
        state_file = icon_name.replace(" ", "_")
        transport = gajim.get_transport_name_from_jid(prim_contact.jid)
        if transport:
            file_path = os.path.join(gajim.DATA_DIR, "iconsets", "transports", transport, "16x16")
        else:
            iconset = gajim.config.get("iconset")
            if not iconset:
                iconset = "dcraven"
            file_path = os.path.join(gajim.DATA_DIR, "iconsets", iconset, "16x16")

        files = []
        file_full_path = os.path.join(file_path, state_file)
        files.append(file_full_path + ".png")
        files.append(file_full_path + ".gif")
        self.image.set_from_pixbuf(None)
        for file in files:
            if os.path.exists(file):
                self.image.set_from_file(file)
                break

        info = '<span size="large" weight="bold">' + prim_contact.jid + "</span>"
        info += (
            '\n<span weight="bold">'
            + _("Name: ")
            + "</span>"
            + gtkgui_helpers.escape_for_pango_markup(prim_contact.name)
        )
        if prim_contact.sub:
            info += (
                '\n<span weight="bold">'
                + _("Subscription: ")
                + "</span>"
                + gtkgui_helpers.escape_for_pango_markup(prim_contact.sub)
            )

        if prim_contact.keyID:
            keyID = None
            if len(prim_contact.keyID) == 8:
                keyID = prim_contact.keyID
            elif len(prim_contact.keyID) == 16:
                keyID = prim_contact.keyID[8:]
            if keyID:
                info += (
                    '\n<span weight="bold">'
                    + _("OpenPGP: ")
                    + "</span>"
                    + gtkgui_helpers.escape_for_pango_markup(keyID)
                )

        num_resources = 0
        for contact in contacts:
            if contact.resource:
                num_resources += 1
        if num_resources > 1:
            self.current_row = 1
            self.table.resize(2, 1)
            info += '\n<span weight="bold">' + _("Status: ") + "</span>"
            for contact in contacts:
                if contact.resource:
                    status_line = self.get_status_info(contact.resource, contact.priority, contact.show, contact.status)
                    icon_name = helpers.get_icon_name_to_show(contact)
                    self.add_status_row(file_path, icon_name, status_line)

        else:  # only one resource
            if contact.resource:
                info += (
                    '\n<span weight="bold">'
                    + _("Resource: ")
                    + "</span>"
                    + gtkgui_helpers.escape_for_pango_markup(contact.resource)
                    + " ("
                    + unicode(contact.priority)
                    + ")"
                )
            if contact.show:
                info += '\n<span weight="bold">' + _("Status: ") + "</span>" + helpers.get_uf_show(contact.show)
                if contact.status:
                    status = contact.status.strip()
                    if status != "":
                        # reduce long status
                        # (no more than 130 chars on line and no more than 5 lines)
                        status = gtkgui_helpers.reduce_chars_newlines(status, 130, 5)
                        # escape markup entities.
                        info += " - " + gtkgui_helpers.escape_for_pango_markup(status)

        self.text_label.set_markup(info)
        self.hbox.pack_start(self.image, False, False)
        self.hbox.pack_start(self.table, True, True)
        self.win.add(self.hbox)