From 1360933ba91a461186487341cca1af5410bb613c Mon Sep 17 00:00:00 2001 From: Travis Shirk Date: Sun, 1 Jan 2006 20:06:26 +0000 Subject: [PATCH] Merged in trunk updates, including meta_contacts Merged revisions 4951,4962-4969 via svnmerge from svn://svn.gajim.org/gajim/trunk ........ r4951 | nk | 2005-12-30 16:50:36 -0700 (Fri, 30 Dec 2005) | 1 line fixes in greek transl ........ r4962 | asterix | 2006-01-01 11:41:04 -0700 (Sun, 01 Jan 2006) | 2 lines merge meta_contacts branch with trunk. Meta contacts are not in gajim yet, but framework is here. We now use gajim.contacts.many_functions() to handle contacts and groupchat_contacts. ........ r4963 | asterix | 2006-01-01 11:43:24 -0700 (Sun, 01 Jan 2006) | 2 lines correct contacts file ........ r4964 | asterix | 2006-01-01 11:47:26 -0700 (Sun, 01 Jan 2006) | 2 lines dict.remove() doesn't exists, it's del dict[] ........ r4965 | asterix | 2006-01-01 11:50:15 -0700 (Sun, 01 Jan 2006) | 2 lines some missing commits from branch ........ r4966 | asterix | 2006-01-01 11:53:30 -0700 (Sun, 01 Jan 2006) | 2 lines end of gc_contact.nick -> gc_contact.name ........ r4967 | asterix | 2006-01-01 12:05:59 -0700 (Sun, 01 Jan 2006) | 2 lines new ACE option: send_sha_in_gc_presence that allow to send sha info in groupchat presences ........ r4968 | asterix | 2006-01-01 12:12:36 -0700 (Sun, 01 Jan 2006) | 2 lines 0.9.1-2 in debian that solve the group bug (commit [4924]) ........ r4969 | asterix | 2006-01-01 12:31:13 -0700 (Sun, 01 Jan 2006) | 2 lines typo ........ --- debian/changelog | 6 + debian/patches/00_debian-group_bugfix.patch | 13 + po/el/LC_MESSAGES/gajim.po | 8 +- src/chat.py | 12 +- src/common/config.py | 1 + src/common/connection.py | 6 +- src/common/contacts.py | 295 ++++++++++++++ src/common/gajim.py | 36 +- src/config.py | 30 +- src/conversation_textview.py | 4 +- src/dialogs.py | 53 ++- src/disco.py | 8 +- src/filetransfers_window.py | 7 +- src/gajim.py | 94 ++--- src/groupchat_window.py | 134 +++---- src/history_window.py | 19 +- src/notify.py | 13 +- src/remote_control.py | 149 ++++--- src/roster_window.py | 413 ++++++++++---------- src/systray.py | 8 +- src/tabbed_chat_window.py | 23 +- src/tooltips.py | 50 +-- src/vcard.py | 7 +- 23 files changed, 822 insertions(+), 567 deletions(-) create mode 100644 debian/patches/00_debian-group_bugfix.patch create mode 100644 src/common/contacts.py diff --git a/debian/changelog b/debian/changelog index 942dcd1e7..30ef72d23 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +gajim (0.9.1-2) unstable; urgency=low + + * fix group bug Closes: #345306 + + -- Yann Le Boulanger Fri, 30 Dec 2005 13:09:55 +0100 + gajim (0.9.1-1) unstable; urgency=low * new upstream release diff --git a/debian/patches/00_debian-group_bugfix.patch b/debian/patches/00_debian-group_bugfix.patch new file mode 100644 index 000000000..0a5ab2190 --- /dev/null +++ b/debian/patches/00_debian-group_bugfix.patch @@ -0,0 +1,13 @@ +Index: src/roster_window.py +=================================================================== +--- src/roster_window.py (revision 4923) ++++ src/roster_window.py (working copy) +@@ -87,6 +87,8 @@ + model = self.tree.get_model() + root = self.get_account_iter(account) + group_iter = model.iter_children(root) ++ # C_NAME column contacts the pango escaped group name ++ name = gtkgui_helpers.escape_for_pango_markup(name) + while group_iter: + group_name = model[group_iter][C_NAME].decode('utf-8') + if name == group_name: diff --git a/po/el/LC_MESSAGES/gajim.po b/po/el/LC_MESSAGES/gajim.po index e96554e97..aee20e0c1 100644 --- a/po/el/LC_MESSAGES/gajim.po +++ b/po/el/LC_MESSAGES/gajim.po @@ -548,7 +548,7 @@ msgstr "" "Συμπληρώστε την ταυτότητα της επαφής προς την οποία\n" "θέλετε να στείλετε ένα μήνυμα συζήτησης" -#. if offline or connecting +#. if or connecting #: ../src/dialogs.py:767 ../src/dialogs.py:1145 ../src/dialogs.py:1265 msgid "Connection not available" msgstr "Σύνδεση μη διαθέσιμη" @@ -750,7 +750,7 @@ msgstr "_Συμμετοχή" #: ../src/disco.py:1202 ../src/gtkgui.glade.h:330 ../src/roster_window.py:1075 msgid "_Edit" -msgstr "Επε_ξεργασία" +msgstr "Ε_πεξεργασία" #: ../src/disco.py:1241 #, python-format @@ -3530,11 +3530,11 @@ msgstr "" #: ../src/roster_window.py:2636 msgid "Change Status Message..." -msgstr "Αλλαγή Μηνύμαος Κατάστασης..." +msgstr "Αλλαγή Μηνύματος Κατάστασης..." #: ../src/systray.py:151 msgid "_Change Status Message..." -msgstr "Αλλαγή Μηνύμαος _Κατάστασης..." +msgstr "Αλλαγή Μηνύματος _Κατάστασης..." #. for chat_with #. for new_message diff --git a/src/chat.py b/src/chat.py index 40725418e..24b2af4f3 100644 --- a/src/chat.py +++ b/src/chat.py @@ -189,7 +189,7 @@ class Chat: add = _('Group Chat') elif len(self.xmls) == 1: # just one tab if self.widget_name == 'tabbed_chat_window': - c = gajim.get_first_contact_instance_from_jid(self.account, jid) + c = gajim.contacts.get_first_contact_from_jid(self.account, jid) if c is None: add = '' else: @@ -297,9 +297,9 @@ class Chat: def get_message_type(self, jid): if self.widget_name == 'groupchat_window': return 'gc' - if gajim.contacts[self.account].has_key(jid): - return 'chat' - return 'pm' + if gajim.contacts.is_pm_from_jid(self.account, jid): + return 'pm' + return 'chat' def get_nth_jid(self, page_number = None): notebook = self.notebook @@ -464,7 +464,7 @@ class Chat: if self.widget_name == 'tabbed_chat_window': jid = self.get_active_jid() - c = gajim.get_first_contact_instance_from_jid(self.account, jid) + c = gajim.contacts.get_first_contact_from_jid(self.account, jid) if _('not in the roster') in c.groups: # for add_to_roster_menuitem childs[5].show() childs[5].set_no_show_all(False) @@ -502,7 +502,7 @@ class Chat: childs[3].set_active(isactive) childs[3].set_property('sensitive', issensitive) # If we don't have resource, we can't do file transfert - c = gajim.get_first_contact_instance_from_jid(self.account, jid) + c = gajim.contacts.get_first_contact_from_jid(self.account, jid) if not c.resource: childs[2].set_sensitive(False) else: diff --git a/src/common/config.py b/src/common/config.py index 5721a3f66..565a57878 100644 --- a/src/common/config.py +++ b/src/common/config.py @@ -170,6 +170,7 @@ class Config: 'roster_window_skip_taskbar': [opt_bool, False], 'use_urgency_hint': [opt_bool, True, _('If True and installed GTK+ and PyGTK versions are at least 2.8, make the window flash (the default behaviour in most Window Managers) when holding pending events.')], 'notification_timeout': [opt_int, 5], + 'send_sha_in_gc_presence': [opt_bool, True, _('Jabberd1.4 does not like sha info when one join a password protected room. Turn this option to False to stop sending sha info in groupchat presences')], 'one_message_window': [opt_str, 'never', _('Controls the window where new messages are placed.\n\'always\' - All messages are sent to a single window.\n\'never\' - All messages get their own window.\n\'peracct\' - Messages for each account are sent to a specific window.\n\'pertype\' - Each message type (e.g., chats vs. groupchats) are sent to a specific window. Note, changing this option requires restarting Gajim before the changes will take effect')], } diff --git a/src/common/connection.py b/src/common/connection.py index 5be1089ae..2010d7a20 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -2182,7 +2182,8 @@ class Connection: show = helpers.get_xmpp_show(STATUS_LIST[self.connected]) p = common.xmpp.Presence(to = '%s@%s/%s' % (room, server, nick), show = show, status = self.status) - p = self.add_sha(p) + if gajim.config.get('send_sha_in_gc_presence'): + p = self.add_sha(p) t = p.setTag(common.xmpp.NS_MUC + ' x') if password: t.setTagData('password', password) @@ -2228,7 +2229,8 @@ class Connection: show = helpers.get_xmpp_show(show) p = common.xmpp.Presence(to = '%s/%s' % (jid, nick), typ = ptype, show = show, status = status) - p = self.add_sha(p) + if gajim.config.get('send_sha_in_gc_presence'): + p = self.add_sha(p) # send instantly so when we go offline, status is sent to gc before we # disconnect from jabber server self.connection.send(p) diff --git a/src/common/contacts.py b/src/common/contacts.py new file mode 100644 index 000000000..139b6e609 --- /dev/null +++ b/src/common/contacts.py @@ -0,0 +1,295 @@ +## common/contacts.py +## +## Contributors for this file: +## - Yann Le Boulanger +## +## Copyright (C) 2003-2004 Yann Le Boulanger +## Vincent Hanquez +## Copyright (C) 2005 Yann Le Boulanger +## Vincent Hanquez +## Nikos Kouremenos +## Dimitur Kirov +## Travis Shirk +## Norman Rasmussen +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; version 2 only. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## + +import common.gajim + +class Contact: + '''Information concerning each contact''' + def __init__(self, jid='', name='', groups=[], show='', status='', sub='', + ask='', resource='', priority=5, keyID='', our_chatstate=None, + chatstate=None): + self.jid = jid + self.name = name + self.groups = groups + self.show = show + self.status = status + self.sub = sub + self.ask = ask + self.resource = resource + self.priority = priority + self.keyID = keyID + + # please read jep-85 http://www.jabber.org/jeps/jep-0085.html + # we keep track of jep85 support by the peer by three extra states: + # None, False and 'ask' + # None if no info about peer + # False if peer does not support jep85 + # 'ask' if we sent the first 'active' chatstate and are waiting for reply + # this holds what WE SEND to contact (our current chatstate) + self.our_chatstate = our_chatstate + # this is contact's chatstate + self.chatstate = chatstate + + def get_full_jid(self): + if self.resource: + return self.jid + '/' + self.resource + return self.jid + +class GC_Contact: + '''Information concerning each groupchat contact''' + def __init__(self, room_jid='', name='', show='', status='', role='', + affiliation='', jid = ''): + self.room_jid = room_jid + self.name = name + self.show = show + self.status = status + self.role = role + self.affiliation = affiliation + self.jid = jid + + def get_full_jid(self): + return self.room_jid + '/' + self.name + +class Contacts: + '''Information concerning all contacts and groupchat contacts''' + def __init__(self): + self._contacts = {} # list of contacts {acct: {jid1: [C1, C2]}, } one Contact per resource + self._gc_contacts = {} # list of contacts that are in gc {acct: {room_jid: {nick: C}}} + self._sub_contacts = {} # {acct: {jid1: jid2}} means jid1 is sub of jid2 + + def change_account_name(self, old_name, new_name): + self._contacts[new_name] = self._contacts[old_name] + self._gc_contacts[new_name] = self._gc_contacts[old_name] + del self._contacts[old_name] + del self._gc_contacts[old_name] + + def add_account(self, account): + self._contacts[account] = {} + self._gc_contacts[account] = {} + + def get_accounts(self): + return self._contacts.keys() + + def remove_account(self, account): + del self._contacts[account] + del self._gc_contacts[account] + + def create_contact(self, jid='', name='', groups=[], show='', status='', + sub='', ask='', resource='', priority=5, keyID='', our_chatstate=None, + chatstate=None): + return Contact(jid, name, groups, show, status, sub, ask, resource, + priority, keyID, our_chatstate, chatstate) + + def copy_contact(self, contact): + return self.create_contact(jid = contact.jid, name = contact.name, + groups = contact.groups, show = contact.show, status = contact.status, + sub = contact.sub, ask = contact.ask, resource = contact.resource, + priority = contact.priority, keyID = contact.keyID, + our_chatstate = contact.our_chatstate, chatstate = contact.chatstate) + + def add_contact(self, account, contact): + # No such account before ? + if not self._contacts.has_key(account): + self._contacts[account] = {contact.jid : [contact]} + return + # No such jid before ? + if not self._contacts[account].has_key(contact.jid): + self._contacts[account][contact.jid] = [contact] + return + # If same JID with same resource already exists, use the new one + for c in self._contacts[account][contact.jid]: + if c.resource == contact.resource: + self.remove_contact(account, c) + break + self._contacts[account][contact.jid].append(contact) + + def remove_contact(self, account, contact): + if not self._contacts.has_key(account): + return + if not self._contacts[account].has_key(contact.jid): + return + if contact in self._contacts[account][contact.jid]: + self._contacts[account][contact.jid].remove(contact) + # It was the last resource of this contact ? + if not len(self._contacts[account][contact.jid]): + del self._contacts[account][contact.jid] + + def remove_jid(self, account, jid): + '''Removes all contacts for a given jid''' + if not self._contacts.has_key(account): + return + if not self._contacts[account].has_key(jid): + return + del self._contacts[account][jid] + + def get_contact(self, account, jid, resource = None): + '''Returns the list of contact instances for this jid (one per resource) + if no resource is given + returns the contact instance for the given resource if it's given + or None if there is not''' + if jid in self._contacts[account]: + contacts = self._contacts[account][jid] + if not resource: + return contacts + for c in contacts: + if c.resource == resource: + return c + return None + + def is_subcontact(self, account, contact): + if contact.jid in self._sub_contacts[account]: + return True + + def get_contacts_from_jid(self, account, jid): + ''' we may have two or more resources on that jid ''' + if jid in self._contacts[account]: + contacts_instances = self._contacts[account][jid] + return contacts_instances + return [] + + def get_highest_prio_contact_from_contacts(self, contacts): + if not contacts: + return None + prim_contact = contacts[0] + for contact in contacts[1:]: + if int(contact.priority) > int(prim_contact.priority): + prim_contact = contact + return prim_contact + + def get_contact_with_highest_priority(self, account, jid): + contacts = self.get_contacts_from_jid(account, jid) + return self.get_highest_prio_contact_from_contacts(contacts) + + def get_first_contact_from_jid(self, account, jid): + if jid in self._contacts[account]: + return self._contacts[account][jid][0] + else: # it's fake jid + room, nick = common.gajim.get_room_and_nick_from_fjid(jid) + if self._gc_contacts[account].has_key(room) and \ + nick in self._gc_contacts[account][room]: + return self._gc_contacts[account][room][nick] + return None + + def get_parent_contact(self, account, contact): + '''Returns the parent contact of contact if it's a sub-contact, + else contact''' + if is_subcontact(account, contact): + parrent_jid = self._sub_contacts[account][contact.jid] + return self.get_contact_with_highest_priority(account, + parrent_jid) + return contact + + def get_master_contact(self, account, contact): + '''Returns the master contact of contact (parent of parent...) if it's a + sub-contact, else contact''' + while is_subcontact(account, contact): + parrent_jid = self._sub_contacts[account][contact.jid] + contact = self.get_contact_with_highest_priority(account, + parrent_jid) + return contact + + def is_pm_from_jid(self, account, jid): + '''Returns True if the given jid is a private message jid''' + if jid in self._contacts[account]: + return False + return True + + def is_pm_from_contact(self, account, contact): + '''Returns True if the given contact is a private message contact''' + if isinstance(contact, Contcat): + return False + return True + + def get_jid_list(self, account): + return self._contacts[account].keys() + + def contact_from_gc_contact(self, gc_contact): + '''Create a Contact instance from a GC_Contact instance''' + return Contact(jid = gc_contact.get_full_jid(), name = gc_contact.name, + groups = ['none'], show = gc_contact.show, status = gc_contact.status, + sub = 'none') + + def create_gc_contact(self, room_jid='', name='', show='', status='', + role='', affiliation='', jid=''): + return GC_Contact(room_jid, name, show, status, role, affiliation, jid) + + def add_gc_contact(self, account, gc_contact): + # No such account before ? + if not self._gc_contacts.has_key(account): + self._contacts[account] = {gc_contact.room_jid : {gc_contact.name: \ + gc_contact}} + return + # No such room_jid before ? + if not self._gc_contacts[account].has_key(gc_contact.room_jid): + self._gc_contacts[account][gc_contact.room_jid] = {gc_contact.name: \ + gc_contact} + return + self._gc_contacts[account][gc_contact.room_jid][gc_contact.name] = \ + gc_contact + + def remove_gc_contact(self, account, gc_contact): + if not self._gc_contacts.has_key(account): + return + if not self._gc_contacts[account].has_key(gc_contact.room_jid): + return + if not self._gc_contacts[account][gc_contact.room_jid].has_key( + gc_contact.name): + return + del self._gc_contacts[account][gc_contact.room_jid][gc_contact.name] + # It was the last nick in room ? + if not len(self._gc_contacts[account][gc_contact.room_jid]): + del self._gc_contacts[account][gc_contact.room_jid] + + def remove_room(self, account, room_jid): + if not self._gc_contacts.has_key(account): + return + if not self._gc_contacts[account].has_key(room_jid): + return + del self._gc_contacts[account][room_jid] + + def get_gc_contact(self, account, room_jid, nick): + if not self._gc_contacts.has_key(account): + return + if not self._gc_contacts[account].has_key(room_jid): + return + if not self._gc_contacts[account][room_jid].has_key(nick): + return + del self._gc_contacts[account][room_jid][nick] + + def get_gc_list(self, account): + if not self._gc_contacts.has_key(account): + return [] + return self._gc_contacts[account].keys() + + def get_nick_list(self, account, room_jid): + gc_list = self.get_gc_list(account) + if not room_jid in gc_list: + return [] + return self._gc_contacts[account][room_jid].keys() + + def get_gc_contact(self, account, room_jid, nick): + nick_list = self.get_nick_list(account, room_jid) + if not nick in nick_list: + return None + return self._gc_contacts[account][room_jid][nick] diff --git a/src/common/gajim.py b/src/common/gajim.py index 3a57e3555..b72a88b7c 100644 --- a/src/common/gajim.py +++ b/src/common/gajim.py @@ -29,7 +29,7 @@ import logging import mutex import config - +from contacts import Contacts interface = None # The actual interface (the gtk one for the moment) version = '0.10' @@ -77,8 +77,7 @@ last_message_time = {} # list of time of the latest incomming message # {acct1: {jid1: time1, jid2: time2}, } encrypted_chats = {} # list of encrypted chats {acct1: [jid1, jid2], ..} -contacts = {} # list of contacts {acct: {jid1: [C1, C2]}, } one Contact per resource -gc_contacts = {} # list of contacts that are in gc {acct: {room_jid: {nick: C}}} +contacts = Contacts() gc_connected = {} # tell if we are connected to the room or not {acct: {room_jid: True}} gc_passwords = {} # list of the pass required to enter a room {room_jid: password} @@ -159,40 +158,9 @@ def get_real_jid_from_fjid(account, fjid): def get_room_from_fjid(jid): return get_room_and_nick_from_fjid(jid)[0] -def get_contact_instances_from_jid(account, jid): - ''' we may have two or more resources on that jid ''' - if jid in contacts[account]: - contacts_instances = contacts[account][jid] - return contacts_instances - -def get_first_contact_instance_from_jid(account, jid): - contact = None - if jid in contacts[account]: - contact = contacts[account][jid][0] - else: # it's fake jid - #FIXME: problem see comment in next line - room, nick = \ - get_room_and_nick_from_fjid(jid) # if we ban/kick we now real jid - if gc_contacts[account].has_key(room) and \ - nick in gc_contacts[account][room]: - contact = gc_contacts[account][room][nick] - return contact - -def get_contact_instance_with_highest_priority(account, jid): - contact_instances = contacts[account][jid] - return get_highest_prio_contact_from_contacts(contact_instances) - def get_contact_name_from_jid(account, jid): return contacts[account][jid][0].name -def get_highest_prio_contact_from_contacts(contacts): - prim_contact = None # primary contact - for contact in contacts: - if prim_contact == None or int(contact.priority) > \ - int(prim_contact.priority): - prim_contact = contact - return prim_contact - def get_jid_without_resource(jid): return jid.split('/')[0] diff --git a/src/config.py b/src/config.py index 5ff022d76..9c7770898 100644 --- a/src/config.py +++ b/src/config.py @@ -43,7 +43,6 @@ try: except: HAS_GTK_SPELL = False -from gajim import Contact from common import helpers from common import gajim from common import connection @@ -556,7 +555,7 @@ class PreferencesWindow: # open new tabbed chat windows for jid in jids: if kind == 'chats': - c = gajim.get_contact_instance_with_highest_priority(acct, jid) + c = gajim.contacts.get_contact_with_highest_priority(acct, jid) gajim.interface.roster.new_chat(c, acct) if kind == 'gc': gajim.interface.roster.new_room(jid, saved_var[jid]['nick'], acct) @@ -586,7 +585,7 @@ class PreferencesWindow: # open new tabbed chat windows for jid in jids: if kind == 'chats': - c = gajim.get_contact_instance_with_highest_priority(acct, jid) + c = gajim.contacts.get_contact_with_highest_priority(acct, jid) gajim.interface.roster.new_chat(c, acct) if kind == 'gc': gajim.interface.roster.new_room(jid, saved_var[jid]['nick'], acct) @@ -1259,8 +1258,6 @@ class AccountModificationWindow: gajim.allow_notifications[name] = \ gajim.allow_notifications[self.account] gajim.groups[name] = gajim.groups[self.account] - gajim.contacts[name] = gajim.contacts[self.account] - gajim.gc_contacts[name] = gajim.gc_contacts[self.account] gajim.gc_connected[name] = gajim.gc_connected[self.account] gajim.newly_added[name] = gajim.newly_added[self.account] gajim.to_be_removed[name] = gajim.to_be_removed[self.account] @@ -1272,6 +1269,8 @@ class AccountModificationWindow: gajim.status_before_autoaway[self.account] gajim.events_for_ui[name] = gajim.events_for_ui[self.account] + gajim.contacts.change_account_name(self.account, name) + #upgrade account variable in opened windows for kind in ('infos', 'disco', 'chats', 'gc', 'gc_config'): for j in gajim.interface.instances[name][kind]: @@ -1288,8 +1287,6 @@ class AccountModificationWindow: del gajim.nicks[self.account] del gajim.allow_notifications[self.account] del gajim.groups[self.account] - del gajim.contacts[self.account] - del gajim.gc_contacts[self.account] del gajim.gc_connected[self.account] del gajim.newly_added[self.account] del gajim.to_be_removed[self.account] @@ -1860,13 +1857,6 @@ class ServiceRegistrationWindow(DataFormWindow): entry.grab_focus() table.show_all() - def add_transport_to_roster(self): - user1 = Contact(jid = self.service, name = self.service, - groups = [_('Transports')], show = 'offline', status = 'offline', - sub = 'from') - gajim.contacts[self.account][self.service] = [user1] - gajim.interface.roster.add_contact_to_roster(self.service, self.account) - def on_ok_button_clicked(self, widget): '''When Ok button is clicked: send registration info to the core''' @@ -1877,7 +1867,8 @@ class ServiceRegistrationWindow(DataFormWindow): if self.infos.has_key('registered'): del self.infos['registered'] else: - self.add_transport_to_roster() + gajim.interface.roster.add_transport_to_roster(self.account, + self.service) gajim.connections[self.account].register_agent(self.service, self.infos) self.window.destroy() @@ -1886,7 +1877,8 @@ class ServiceRegistrationWindow(DataFormWindow): if self.infos.has_key('registered'): del self.infos['registered'] else: - self.add_transport_to_roster() + gajim.interface.roster.add_transport_to_roster(self.account, + self.service) gajim.connections[self.account].register_agent(self.service, self.infos, True) # True is for is_form self.window.destroy() @@ -2183,8 +2175,7 @@ class RemoveAccountWindow: del gajim.nicks[self.account] del gajim.allow_notifications[self.account] del gajim.groups[self.account] - del gajim.contacts[self.account] - del gajim.gc_contacts[self.account] + gajim.contacts.remove_account(self.account) del gajim.gc_connected[self.account] del gajim.to_be_removed[self.account] del gajim.newly_added[self.account] @@ -2724,8 +2715,7 @@ _('You can set advanced account options by pressing Advanced button, or later by gajim.awaiting_events[self.account] = {} gajim.connections[self.account].connected = 0 gajim.groups[self.account] = {} - gajim.contacts[self.account] = {} - gajim.gc_contacts[self.account] = {} + gajim.contacts.add_account(self.account) gajim.gc_connected[self.account] = {} gajim.newly_added[self.account] = [] gajim.to_be_removed[self.account] = [] diff --git a/src/conversation_textview.py b/src/conversation_textview.py index 35614ceed..8025558b4 100644 --- a/src/conversation_textview.py +++ b/src/conversation_textview.py @@ -371,8 +371,8 @@ class ConversationTextview(gtk.TextView): self.on_join_group_chat_menuitem_activate, text) allow_add = False - if gajim.contacts[self.account].has_key(text): - c = gajim.contacts[self.account][text][0] + c = gajim.contacts.get_first_contact_from_jid(self.account, text) + if c and not gajim.contacts.is_pm_from_contact(self.account, c): if _('not in the roster') in c.groups: allow_add = True else: # he or she's not at all in the account contacts diff --git a/src/dialogs.py b/src/dialogs.py index d279ea9d0..6e0014c25 100644 --- a/src/dialogs.py +++ b/src/dialogs.py @@ -43,7 +43,6 @@ except: from filetransfers_window import FileTransfersWindow from gajim_themes_window import GajimThemesWindow from advanced import AdvancedConfigurationWindow -from gajim import Contact from common import gajim from common import helpers from common import i18n @@ -107,11 +106,6 @@ class EditGroupsDialog: def group_toggled_cb(self, cell, path): self.changes_made = True model = self.list.get_model() - if model[path][1] and len(self.user.groups) == 1: # we try to remove - # the last group - ErrorDialog(_('Cannot remove last group'), - _('At least one contact group must be present.')).get_response() - return model[path][1] = not model[path][1] if model[path][1]: self.user.groups.append(model[path][0].decode('utf-8')) @@ -304,10 +298,10 @@ _('Please fill in the data of the contact you want to add in account %s') %accou liststore.append(['Jabber', '']) self.agents = ['Jabber'] jid_agents = [] - for j in gajim.contacts[account]: - user = gajim.contacts[account][j][0] - if _('Transports') in user.groups and user.show != 'offline' and \ - user.show != 'error': + for j in gajim.contacts.get_jid_list(account): + contact = gajim.contacts.get_first_contact_from_jid(account, j) + if _('Transports') in contact.groups and contact.show != 'offline' and\ + contact.show != 'error': jid_agents.append(j) for a in jid_agents: if a.find('aim') > -1: @@ -382,8 +376,9 @@ _('Please fill in the data of the contact you want to add in account %s') %accou return # Check if jid is already in roster - if jid in gajim.contacts[self.account] and _('not in the roster') not in \ - gajim.contacts[self.account][jid][0].groups: + if jid in gajim.contacts.get_jid_list(self.account) and \ + _('not in the roster') not in \ + gajim.contacts.get_first_contact_from_jid(self.account, jid).groups: ErrorDialog(_('Contact already in roster'), _('This contact is already listed in your roster.')).get_response() return @@ -629,7 +624,7 @@ class SubscriptionRequestWindow: '''accept the request''' gajim.connections[self.account].send_authorization(self.jid) self.window.destroy() - if not gajim.contacts[self.account].has_key(self.jid): + if self.jid not in gajim.contacts.get_jid_list(self.account): AddNewContactWindow(self.account, self.jid) def on_contact_info_button_clicked(self, widget): @@ -826,8 +821,8 @@ class PopupNotificationWindow: event_type_label.set_markup('%s' %event_type) - if self.jid in gajim.contacts[account]: - txt = gajim.contacts[account][self.jid][0].name + if self.jid in gajim.contacts.get_jid_list(account): + txt = gajim.contacts.get_first_contact_from_jid(account, self.jid).name else: txt = self.jid @@ -867,7 +862,8 @@ class PopupNotificationWindow: close_button.modify_bg(gtk.STATE_NORMAL, bg_color) eventbox.modify_bg(gtk.STATE_NORMAL, bg_color) event_description_label.set_markup('%s' % txt) - elif event_type in (_('File Transfer Completed'), _('File Transfer Stopped')): + elif event_type in (_('File Transfer Completed'), + _('File Transfer Stopped')): bg_color = gtk.gdk.color_parse('yellowgreen') close_button.modify_bg(gtk.STATE_NORMAL, bg_color) eventbox.modify_bg(gtk.STATE_NORMAL, bg_color) @@ -875,8 +871,8 @@ class PopupNotificationWindow: if file_props['type'] == 'r': # get the name of the sender, as it is in the roster sender = unicode(file_props['sender']).split('/')[0] - name = gajim.get_first_contact_instance_from_jid( - account, sender).name + name = gajim.contacts.get_first_contact_from_jid(account, + sender).name txt = _('From %s') % name else: receiver = file_props['receiver'] @@ -884,8 +880,8 @@ class PopupNotificationWindow: receiver = receiver.jid receiver = receiver.split('/')[0] # get the name of the contact, as it is in the roster - name = gajim.get_first_contact_instance_from_jid( - account, receiver).name + name = gajim.contacts.get_first_contact_from_jid(account, + receiver).name txt = _('To %s') % name else: txt = '' @@ -930,8 +926,8 @@ class PopupNotificationWindow: return # use Contact class, new_chat expects it that way # is it in the roster? - if gajim.contacts[self.account].has_key(self.jid): - contact = gajim.get_contact_instance_with_highest_priority( + if self.jid in gajim.contacts.get_jid_list(self.account): + contact = gajim.contacts.get_contact_with_highest_priority( self.account, self.jid) else: keyID = '' @@ -942,14 +938,15 @@ class PopupNotificationWindow: if self.msg_type.find('file') != 0: if self.msg_type == 'pm': room_jid, nick = self.jid.split('/', 1) - show = gajim.gc_contacts[self.account][room_jid][nick].show - contact = Contact(jid = self.jid, name = nick, groups = ['none'], - show = show, sub = 'none') + gc_contact = gajim.contacts.get_gc_contact(self.account, + room_jid, nick) + contact = gajim.contacts.contact_from_gc_contact(gc_contact) else: - contact = Contact(jid = self.jid, name = self.jid.split('@')[0], + contact = gajim.contacts.create_contact(jid = self.jid, + name = self.jid.split('@')[0], groups = [_('not in the roster')], show = 'not in the roster', - status = _('not in the roster'), sub = 'none', keyID = keyID) - gajim.contacts[self.account][self.jid] = [contact] + status = '', sub = 'none', keyID = keyID) + gajim.contacts.add_contact(self.account, contact) gajim.interface.roster.add_contact_to_roster(contact.jid, self.account) diff --git a/src/disco.py b/src/disco.py index 1acd5ddb7..81823d254 100644 --- a/src/disco.py +++ b/src/disco.py @@ -56,7 +56,6 @@ import gtk.glade import dialogs import tooltips -from gajim import Contact from common import helpers from common import gajim from common import xmpp @@ -1194,9 +1193,10 @@ class ToplevelAgentBrowser(AgentBrowser): if self.register_button and xmpp.NS_REGISTER in features: # We can register this agent registered_transports = [] - contacts = gajim.contacts[self.account] - for j in contacts: - if _('Transports') in contacts[j][0].groups: + jid_list = gajim.contacts.get_jid_list(self.account) + for j in jid_list: + contact = gajim.contacts.get_first_contact_from_jid(self.account, j) + if _('Transports') in contact.groups: registered_transports.append(j) if jid in registered_transports: self.register_button.set_label(_('_Edit')) diff --git a/src/filetransfers_window.py b/src/filetransfers_window.py index e0e3c3a22..540c0f335 100644 --- a/src/filetransfers_window.py +++ b/src/filetransfers_window.py @@ -177,7 +177,7 @@ class FileTransfersWindow: helpers.convert_bytes(file_props['size']) if file_props['type'] == 'r': jid = unicode(file_props['sender']).split('/')[0] - sender_name = gajim.get_first_contact_instance_from_jid( + sender_name = gajim.contacts.get_first_contact_from_jid( file_props['tt_account'], jid).name sender = gtkgui_helpers.escape_for_pango_markup(sender_name) else: @@ -187,7 +187,7 @@ class FileTransfersWindow: sectext += '\n\t' +_('Recipient: ') if file_props['type'] == 's': jid = unicode(file_props['receiver']).split('/')[0] - receiver_name = gajim.get_first_contact_instance_from_jid( + receiver_name = gajim.contacts.get_first_contact_from_jid( file_props['tt_account'], jid).name recipient = gtkgui_helpers.escape_for_pango_markup(receiver_name) else: @@ -289,7 +289,8 @@ _('Connection with peer cannot be established.')) if contact.find('/') == -1: return (jid, resource) = contact.split('/', 1) - contact = gajim.Contact(jid = jid, resource = resource) + contact = gajim.contacts.create_contact(jid = jid, + resource = resource) (file_dir, file_name) = os.path.split(file_path) file_props = self.get_send_file_props(account, contact, file_path, file_name) diff --git a/src/gajim.py b/src/gajim.py index 6a63c9c69..62bfdb7cd 100755 --- a/src/gajim.py +++ b/src/gajim.py @@ -138,35 +138,6 @@ if profile: parser = optparser.OptionsParser(config_filename) -class Contact: - '''Information concerning each contact''' - def __init__(self, jid='', name='', groups=[], show='', status='', sub='', - ask='', resource='', priority=5, keyID='', role='', affiliation='', - our_chatstate=None, chatstate=None): - self.jid = jid - self.name = name - self.groups = groups - self.show = show - self.status = status - self.sub = sub - self.ask = ask - self.resource = resource - self.priority = priority - self.keyID = keyID - self.role = role - self.affiliation = affiliation - - # please read jep-85 http://www.jabber.org/jeps/jep-0085.html - # we keep track of jep85 support by the peer by three extra states: - # None, False and 'ask' - # None if no info about peer - # False if peer does not support jep85 - # 'ask' if we sent the first 'active' chatstate and are waiting for reply - # this holds what WE SEND to contact (our current chatstate) - self.our_chatstate = our_chatstate - # this is contact's chatstate - self.chatstate = chatstate - import roster_window import systray import dialogs @@ -305,8 +276,10 @@ class Interface: else: ji = jid # Update contact - if gajim.contacts[account].has_key(ji): - lcontact = gajim.contacts[account][ji] + + jid_list = gajim.contacts.get_jid_list(account) + if ji in jid_list: + lcontact = gajim.contacts.get_contacts_from_jid(account, ji) contact1 = None resources = [] for c in lcontact: @@ -320,17 +293,13 @@ class Interface: if old_show == new_show and contact1.status == array[2]: #no change return else: - contact1 = gajim.contacts[account][ji][0] + contact1 = gajim.contacts.get_first_contact_from_jid(account, ji) if contact1.show in statuss: old_show = statuss.index(contact1.show) if (resources != [''] and (len(lcontact) != 1 or lcontact[0].show != 'offline')) and jid.find('@') > 0: old_show = 0 - contact1 = Contact(jid = contact1.jid, name = contact1.name, - groups = contact1.groups, show = contact1.show, - status = contact1.status, sub = contact1.sub, - ask = contact1.ask, resource = contact1.resource, - priority = contact1.priority, keyID = contact1.keyID) + contact1 = gajim.contacts.copy_contact(contact1) lcontact.append(contact1) contact1.resource = resource if contact1.jid.find('@') > 0 and len(lcontact) == 1: # It's not an agent @@ -357,13 +326,13 @@ class Interface: contact1.keyID = keyID if jid.find('@') <= 0: # It must be an agent - if gajim.contacts[account].has_key(ji): + if ji in jid_list: # Update existing iter self.roster.draw_contact(ji, account) elif jid == gajim.get_jid_from_account(account): # It's another of our resources. We don't need to see that! return - elif gajim.contacts[account].has_key(ji): + elif ji in jid_list: # It isn't an agent # reset chatstate if needed: # (when contact signs out or has errors) @@ -454,7 +423,7 @@ class Interface: return # Handle chat states - contact = gajim.get_first_contact_instance_from_jid(account, jid) + contact = gajim.contacts.get_first_contact_from_jid(account, jid) # FIXME if self.instances[account]['chats'].has_key(jid): chat_win = self.instances[account]['chats'][jid] @@ -524,8 +493,9 @@ class Interface: show = model[i][3] else: show = 'offline' - c = Contact(jid = fjid, name = nick, groups = ['none'], - show = show, ask = 'none') + gc_c = gajim.contacts.create_gc_contact(room_jid = jid, + name = nick, show = show) + c = gajim.contacts.contact_from_gc_contct(c) self.roster.new_chat(c, account) # FIXME self.instances[account]['chats'][fjid].print_conversation( @@ -559,14 +529,12 @@ class Interface: def handle_event_subscribed(self, account, array): #('SUBSCRIBED', account, (jid, resource)) jid = array[0] - if gajim.contacts[account].has_key(jid): - c = gajim.get_first_contact_instance_from_jid(account, jid) + if jid in gajim.contacts.get_jid_list(account): + c = gajim.contacts.get_first_contact_from_jid(account, jid) c.resource = array[1] self.roster.remove_contact(c, account) if _('not in the roster') in c.groups: c.groups.remove(_('not in the roster')) - if len(c.groups) == 0: - c.groups = [_('General')] self.roster.add_contact_to_roster(c.jid, account) gajim.connections[account].update_contact(c.jid, c.name, c.groups) else: @@ -577,10 +545,10 @@ class Interface: keyID = attached_keys[attached_keys.index(jid) + 1] name = jid.split('@', 1)[0] name = name.split('%', 1)[0] - contact1 = Contact(jid = jid, name = name, groups = [_('General')], - show = 'online', status = 'online', ask = 'to', - resource = array[1], keyID = keyID) - gajim.contacts[account][jid] = [contact1] + contact1 = gajim.contacts.create_contact(jid = jid, name = name, + groups = None, show = 'online', status = 'online', + ask = 'to', resource = array[1], keyID = keyID) + gajim.contacts.add_contact(account, contact1) self.roster.add_contact_to_roster(jid, account) dialogs.InformationDialog(_('Authorization accepted'), _('The contact "%s" has authorized you to see his or her status.') @@ -789,12 +757,12 @@ class Interface: def handle_event_roster_info(self, account, array): #('ROSTER_INFO', account, (jid, name, sub, ask, groups)) jid = array[0] - if not gajim.contacts[account].has_key(jid): + if not jid in gajim.contacts.get_jid_list(account): return - contacts = gajim.contacts[account][jid] + contacts = gajim.contacts.get_contacts_from_jid(account, jid) if not (array[2] or array[3]): self.roster.remove_contact(contacts[0], account) - del gajim.contacts[account][jid] + gajim.contacts.remove_jid(account, jid) #FIXME if it was the only one in its group, remove the group return for contact in contacts: @@ -901,10 +869,10 @@ class Interface: def handle_event_file_request(self, account, array): jid = array[0] - if not gajim.contacts[account].has_key(jid): + if jid not in gajim.contacts.get_jid_list(account): return file_props = array[1] - contact = gajim.contacts[account][jid][0] + contact = gajim.contacts.get_first_contact_from_jid(account, jid) if gajim.popup_window(account): self.instances['file_transfers'].show_file_request(account, contact, @@ -1286,7 +1254,8 @@ class Interface: if wins['chats'].has_key(jid): w = wins['chats'][jid] else: - self.roster.new_chat(gajim.contacts[account][jid][0], account) + contact = gajim.contacts.get_first_contact_from_jid(account, jid) + self.roster.new_chat(contact, account) w = wins['chats'][jid] elif typ == 'pm': # FIXME @@ -1294,12 +1263,14 @@ class Interface: w = wins['chats'][jid] else: room_jid, nick = jid.split('/', 1) - if gajim.gc_contacts[account][room_jid].has_key(nick): - show = gajim.gc_contacts[account][room_jid][nick].show + gc_contact = gajim.contacts.get_gc_contact(account, room_jid, nick) + if gc_contact: + show = gc_contact.show else: show = 'offline' - c = Contact(jid = jid, name = nick, groups = ['none'], - show = show, ask = 'none') + gc_contact = gajim.contacts.create_gc_contact(room_jid = room_jid, + name = nick, show = show) + c = gajim.contacts.contact_from_gc_contct(gc_contact) self.roster.new_chat(c, account) w = wins['chats'][jid] elif typ in ('normal', 'file-request', 'file-request-error', @@ -1383,9 +1354,8 @@ class Interface: for a in gajim.connections: self.instances[a] = {'infos': {}, 'disco': {}, 'chats': {}, 'gc': {}, 'gc_config': {}} - gajim.contacts[a] = {} + gajim.contacts.add_account(a) gajim.groups[a] = {} - gajim.gc_contacts[a] = {} gajim.gc_connected[a] = {} gajim.newly_added[a] = [] gajim.to_be_removed[a] = [] diff --git a/src/groupchat_window.py b/src/groupchat_window.py index 99e61f87e..5587524e2 100644 --- a/src/groupchat_window.py +++ b/src/groupchat_window.py @@ -39,7 +39,6 @@ import gtkgui_helpers import history_window import tooltips -from gajim import Contact from common import gajim from common import helpers from gettext import ngettext @@ -121,8 +120,6 @@ class GroupchatWindow(chat.Chat): 'nick': self.nicks[room_jid], 'model': self.list_treeview[room_jid].get_model(), 'subject': self.subjects[room_jid], - 'contacts': gajim.gc_contacts[self.account][room_jid], - 'connected': gajim.gc_connected[self.account][room_jid], } def load_var(self, room_jid, var): @@ -132,8 +129,6 @@ class GroupchatWindow(chat.Chat): self.list_treeview[room_jid].expand_all() self.set_subject(room_jid, var['subject']) self.subjects[room_jid] = var['subject'] - gajim.gc_contacts[self.account][room_jid] = var['contacts'] - gajim.gc_connected[self.account][room_jid] = var['connected'] if gajim.gc_connected[self.account][room_jid]: self.got_connected(room_jid) @@ -194,7 +189,7 @@ class GroupchatWindow(chat.Chat): def on_groupchat_window_destroy(self, widget): chat.Chat.on_window_destroy(self, widget, 'gc') for room_jid in self.xmls: - del gajim.gc_contacts[self.account][room_jid] + gajim.contacts.remove_room(self.account, room_jid) del gajim.gc_connected[self.account][room_jid] def on_groupchat_window_focus_in_event(self, widget, event): @@ -347,18 +342,15 @@ class GroupchatWindow(chat.Chat): fin = True return None - def get_nick_list(self, room_jid): - '''get nicks of contacts in a room''' - return gajim.gc_contacts[self.account][room_jid].keys() - def remove_contact(self, room_jid, nick): '''Remove a user from the contacts_list''' model = self.list_treeview[room_jid].get_model() iter = self.get_contact_iter(room_jid, nick) if not iter: return - if gajim.gc_contacts[self.account][room_jid].has_key(nick): - del gajim.gc_contacts[self.account][room_jid][nick] + gc_contact = gajim.contacts.get_gc_contact(self.account, room_jid, nick) + if gc_contact: + gajim.contacts.remove_gc_contact(self.account, gc_contact) parent_iter = model.iter_parent(iter) model.remove(iter) if model.iter_n_children(parent_iter) == 0: @@ -366,16 +358,12 @@ class GroupchatWindow(chat.Chat): def add_contact_to_roster(self, room_jid, nick, show, role, jid, affiliation, status): model = self.list_treeview[room_jid].get_model() - resource = '' role_name = helpers.get_uf_role(role, plural = True) if jid: - jids = jid.split('/', 1) - j = jids[0] - if len(jids) > 1: - resource = jids[1] + jid = jid.split('/', 1)[0] else: - j = '' + jid = '' name = nick @@ -385,10 +373,11 @@ class GroupchatWindow(chat.Chat): (gajim.interface.roster.jabber_state_images['16']['closed'], 'role', role, '%s' % role_name)) iter = model.append(role_iter, (None, 'contact', nick, name)) - if not gajim.gc_contacts[self.account][room_jid].has_key(nick): - gajim.gc_contacts[self.account][room_jid][nick] = \ - Contact(jid = j, name = nick, show = show, resource = resource, - role = role, affiliation = affiliation, status = status) + if not nick in gajim.contacts.get_nick_list(self.account, room_jid): + gc_contact = gajim.contacts.create_gc_contact(room_jid = room_jid, + name = nick, show = show, status = status, role = role, + affiliation = affiliation, jid = jid) + gajim.contacts.add_gc_contact(self.account, gc_contact) self.draw_contact(room_jid, nick) if nick == self.nicks[room_jid]: # we became online self.got_connected(room_jid) @@ -401,15 +390,15 @@ class GroupchatWindow(chat.Chat): if not iter: return model = self.list_treeview[room_jid].get_model() - contact = gajim.gc_contacts[self.account][room_jid][nick] + gc_contact = gajim.contacts.get_gc_contact(self.account, room_jid, nick) state_images = gajim.interface.roster.jabber_state_images['16'] if gajim.awaiting_events[self.account].has_key(room_jid + '/' + nick): image = state_images['message'] else: - image = state_images[contact.show] + image = state_images[gc_contact.show] - name = gtkgui_helpers.escape_for_pango_markup(contact.name) - status = contact.status + name = gtkgui_helpers.escape_for_pango_markup(gc_contact.name) + status = gc_contact.status # add status msg, if not empty, under contact name in the treeview if status and gajim.config.get('show_status_msgs_in_roster'): status = status.strip() @@ -428,17 +417,16 @@ class GroupchatWindow(chat.Chat): def draw_roster(self, room_jid): model = self.list_treeview[room_jid].get_model() model.clear() - for nick in gajim.gc_contacts[self.account][room_jid]: - contact = gajim.gc_contacts[self.account][room_jid][nick] - fjid = contact.jid - if contact.resource: - fjid += '/' + contact.resource - self.add_contact_to_roster(room_jid, nick, contact.show, contact.role, - fjid, contact.affiliation, contact.status) + for nick in gajim.contacts.get_nick_list(self.account, room_jid): + gc_contact = gajim.contacts.get_gc_contact(self.account, room_jid, nick) + self.add_contact_to_roster(room_jid, nick, gc_contact.show, + gc_contact.role, gc_contact.jid, gc_contact.affiliation, + gc_contact.status) def get_role(self, room_jid, nick): - if gajim.gc_contacts[self.account][room_jid].has_key(nick): - return gajim.gc_contacts[self.account][room_jid][nick].role + gc_contact = gajim.contacts.get_gc_contact(self.account, room_jid, nick) + if gc_contact: + return gc_contact.role else: return 'visitor' @@ -490,7 +478,7 @@ class GroupchatWindow(chat.Chat): room_jid + '/' + nick): self.remove_contact(room_jid, nick) else: - c = gajim.gc_contacts[self.account][room_jid][nick] + c = gajim.contacts.get_gc_contact(self.account, room_jid, nick) c.show = show c.status = status if nick == self.nicks[room_jid] and statusCode != '303': # We became offline @@ -507,7 +495,7 @@ class GroupchatWindow(chat.Chat): self.add_contact_to_roster(room_jid, nick, show, role, jid, affiliation, status) else: - c = gajim.gc_contacts[self.account][room_jid][nick] + c = gajim.contacts.get_gc_contact(self.account, room_jid, nick) if c.show == show and c.status == status and \ c.affiliation == affiliation: #no change return @@ -547,7 +535,7 @@ class GroupchatWindow(chat.Chat): # for room_jid & number of unread private msgs with each contact # that we have nb = 0 - for nick in self.get_nick_list(room_jid): + for nick in gajim.contacts.get_nick_list(self.account, room_jid): fjid = room_jid + '/' + nick if gajim.awaiting_events[self.account].has_key(fjid): # gc can only have messages as event @@ -689,7 +677,8 @@ class GroupchatWindow(chat.Chat): self.nick_hits[room_jid].pop(0) else: self.nick_hits[room_jid] = [] # clear the hit list - list_nick = self.get_nick_list(room_jid) + list_nick = gajim.contacts.get_nick_list(self.account, + room_jid) for nick in list_nick: if nick.lower().startswith(begin.lower()): # the word is the begining of a nick self.nick_hits[room_jid].append(nick) @@ -807,7 +796,7 @@ class GroupchatWindow(chat.Chat): # example: /query foo if len(message_array): nick = message_array.pop(0) - nicks = self.get_nick_list(room_jid) + nicks = gajim.contacts.get_nick_list(self.account, room_jid) if nick in nicks: self.on_send_pm(nick = nick) self.clear(message_textview) @@ -822,7 +811,8 @@ class GroupchatWindow(chat.Chat): if len(message_array): message_array = message_array[0].split() nick = message_array.pop(0) - room_nicks = self.get_nick_list(room_jid) + room_nicks = gajim.contacts.get_nick_list(self.account, + room_jid) if nick in room_nicks: privmsg = ' '.join(message_array) self.on_send_pm(nick=nick, msg=privmsg) @@ -904,7 +894,8 @@ class GroupchatWindow(chat.Chat): if len(message_array): message_array = message_array[0].split() nick = message_array.pop(0) - room_nicks = self.get_nick_list(room_jid) + room_nicks = gajim.contacts.get_nick_list(self.account, + room_jid) reason = ' '.join(message_array) if nick in room_nicks: ban_jid = gajim.construct_fjid(room_jid, nick) @@ -924,7 +915,8 @@ class GroupchatWindow(chat.Chat): if len(message_array): message_array = message_array[0].split() nick = message_array.pop(0) - room_nicks = self.get_nick_list(room_jid) + room_nicks = gajim.contacts.get_nick_list(self.account, + room_jid) reason = ' '.join(message_array) if nick in room_nicks: gajim.connections[self.account].gc_set_role(room_jid, nick, @@ -1162,7 +1154,7 @@ current room topic.') % command, room_jid) def on_info(self, widget, room_jid, nick): '''Call vcard_information_window class to display user's information''' - c = gajim.gc_contacts[self.account][room_jid][nick] + c = gajim.contacts.get_gc_contact(self.account, room_jid, nick) if c.jid and c.resource: # on GC, we know resource only if we're mod and up jid = c.jid @@ -1174,9 +1166,7 @@ current room topic.') % command, room_jid) gajim.interface.instances[self.account]['infos'][jid].window.present() else: # we copy contact because c.jid must contain the fakeJid for vcard - c2 = Contact(jid = jid, name = c.name, groups = c.groups, - show = c.show, status = c.status, sub = c.sub, - resource = c.resource, role = c.role, affiliation = c.affiliation) + c2 = gajim.contacts.contact_from_gc_contact(c) gajim.interface.instances[self.account]['infos'][jid] = \ vcard.VcardWindow(c2, self.account, False) @@ -1195,10 +1185,9 @@ current room topic.') % command, room_jid) room_jid = self.get_active_jid() fjid = gajim.construct_fjid(room_jid, nick) # 'fake' jid if not gajim.interface.instances[self.account]['chats'].has_key(fjid): - show = gajim.gc_contacts[self.account][room_jid][nick].show - u = Contact(jid = fjid, name = nick, groups = ['none'], show = show, - sub = 'none') - gajim.interface.roster.new_chat(u, self.account) + gc_c = gajim.contacts.get_gc_contact(self.account, room_jid, nick) + c = gajim.contacts.contact_from_gc_contact(gc_c) + gajim.interface.roster.new_chat(c, self.account) #make active here in case we need to send a message gajim.interface.instances[self.account]['chats'][fjid].set_active_tab(fjid) @@ -1241,15 +1230,15 @@ current room topic.') % command, room_jid) '''Make contact's popup menu''' model = self.list_treeview[room_jid].get_model() nick = model[iter][C_NICK].decode('utf-8') - c = gajim.gc_contacts[self.account][room_jid][nick] + c = gajim.contacts.get_gc_contact(self.account, room_jid, nick) jid = c.jid target_affiliation = c.affiliation target_role = c.role # looking for user's affiliation and role user_nick = self.nicks[room_jid] - user_affiliation = gajim.gc_contacts[self.account][room_jid][user_nick].\ - affiliation + user_affiliation = gajim.contacts.get_gc_contact(self.account, room_jid, + user_nick).affiliation user_role = self.get_role(room_jid, user_nick) # making menu from glade @@ -1340,8 +1329,8 @@ current room topic.') % command, room_jid) room_jid, show='offline', status=reason) del self.nicks[room_jid] # They can already be removed by the destroy function - if gajim.gc_contacts[self.account].has_key(room_jid): - del gajim.gc_contacts[self.account][room_jid] + if room_jid in gajim.contacts.get_room_list(self.account): + gajim.contacts.remove_room(self.account, room_jid) del gajim.gc_connected[self.account][room_jid] del self.list_treeview[room_jid] del self.subjects[room_jid] @@ -1357,7 +1346,11 @@ current room topic.') % command, room_jid) def got_disconnected(self, room_jid): model = self.list_treeview[room_jid].get_model() model.clear() - gajim.gc_contacts[self.account][room_jid] = {} + nick_list = gajim.contacts.get_nick_list(self.account, room_jid) + for nick in nick_list: + gc_contact = gajim.contacts.get_gc_contact(self.account, room_jid, + nick) + gajim.contacts.remove_gc_contact(self.account, gc_contact) gajim.gc_connected[self.account][room_jid] = False message_textview = self.message_textviews[room_jid] message_textview.set_sensitive(False) @@ -1525,10 +1518,8 @@ current room topic.') % command, room_jid) gajim.interface.systray.add_jid(fjid, self.account, 'pm') self.show_title() else: - show = gajim.gc_contacts[self.account][room_jid][nick].show - c = Contact(jid = fjid, name = nick, groups = ['none'], show = show, - ask = 'none') - gajim.interface.roster.new_chat(c, self.account) + gc_c = gajim.contacts.get_gc_contact(self.account, room_jid, nick) + gajim.interface.roster.new_chat(gc_c, self.account) # Scroll to line self.list_treeview[room_jid].expand_row(path[0:1], False) self.list_treeview[room_jid].scroll_to_cell(path) @@ -1562,7 +1553,8 @@ current room topic.') % command, room_jid) self.tooltip.id = row nick = model[iter][C_NICK].decode('utf-8') self.tooltip.timeout = gobject.timeout_add(500, - self.show_tooltip, gajim.gc_contacts[account][room_jid][nick]) + self.show_tooltip, gajim.contacts.get_gc_contact(account, + room_jid, nick)) def on_list_treeview_leave_notify_event(self, widget, event): model = widget.get_model() @@ -1636,10 +1628,9 @@ current room topic.') % command, room_jid) nick = model[iter][C_NICK].decode('utf-8') fjid = gajim.construct_fjid(room_jid, nick) if not gajim.interface.instances[self.account]['chats'].has_key(fjid): - show = gajim.gc_contacts[self.account][room_jid][nick].show - u = Contact(jid = fjid, name = nick, groups = ['none'], - show = show, sub = 'none') - gajim.interface.roster.new_chat(u, self.account) + gc_c = gajim.contacts.get_gc_contact(self.account, room_jid, + nick) + gajim.interface.roster.new_chat(gc_c, self.account) gajim.interface.instances[self.account]['chats'][fjid].set_active_tab(fjid) gajim.interface.instances[self.account]['chats'][fjid].window.present() return True @@ -1655,7 +1646,8 @@ current room topic.') % command, room_jid) model = widget.get_model() iter = model.get_iter(path) nick = model[iter][C_NICK].decode('utf-8') - if not nick in gajim.gc_contacts[self.account][room_jid]: #it's a group + if not nick in gajim.contacts.get_nick_list(self.account, room_jid): + #it's a group if x < 20: # first cell in 1st column (the arrow SINGLE clicked) if (widget.row_expanded(path)): widget.collapse_row(path) @@ -1680,11 +1672,9 @@ current room topic.') % command, room_jid) nick = model[iter][C_NICK].decode('utf-8') jid = gajim.construct_fjid(room_jid, nick) if not gajim.interface.instances[self.account]['chats'].has_key(jid): - show = gajim.gc_contacts[self.account][room_jid][nick].show - contact = Contact(jid = jid, name = nick, groups = ['none'], - show = show, sub = 'none') - gajim.interface.roster.new_chat(contact, self.account) - jid = contact.jid + gc_c = gajim.contacts.get_gc_contact(self.account, room_jid, nick) + gajim.interface.roster.new_chat(gc_c, self.account) + jid = gc_c.jid gajim.interface.instances[self.account]['chats'][jid].set_active_tab(jid) gajim.interface.instances[self.account]['chats'][jid].window.present() diff --git a/src/history_window.py b/src/history_window.py index 53463d8be..c7a9ef2c8 100644 --- a/src/history_window.py +++ b/src/history_window.py @@ -106,8 +106,8 @@ class HistoryWindow: col.set_attributes(renderer, text = C_MESSAGE) col.set_resizable(True) - if account and gajim.contacts[account].has_key(jid): - contact = gajim.get_first_contact_instance_from_jid(account, jid) + contact = gajim.contacts.get_first_contact_from_jid(account, jid) + if contact: title = _('Conversation History with %s') % contact.name else: title = _('Conversation History with %s') % jid @@ -237,14 +237,17 @@ class HistoryWindow: if kind == constants.KIND_GC_MSG: tag_name = 'incoming' elif kind in (constants.KIND_SINGLE_MSG_RECV, constants.KIND_CHAT_MSG_RECV): - try: - # is he in our roster? if yes use the name - contact_name = gajim.contacts[self.account][self.jid][0].name - except: + contact = gajim.contacts.get_first_contact_from_jid(self.account, + self.jid) + if contact: + # he is in our roster, use the name + contact_name = contact.name + else: room_jid, nick = gajim.get_room_and_nick_from_fjid(self.jid) # do we have him as gc_contact? - if nick and gajim.gc_contacts[self.account].has_key(room_jid) and\ - gajim.gc_contacts[self.account][room_jid].has_key(nick): + gc_contact = gajim.contacts.get_gc_contact(self.account, room_jid, + nick) + if gc_contact: # so yes, it's pm! contact_name = nick else: diff --git a/src/notify.py b/src/notify.py index 5947af905..2d9f6aa6e 100644 --- a/src/notify.py +++ b/src/notify.py @@ -105,8 +105,9 @@ class DesktopNotification: self.msg_type = msg_type self.file_props = file_props - if jid in gajim.contacts[account]: - actor = gajim.get_first_contact_instance_from_jid(account, jid).name + contact = gajim.contacts.get_first_contact_from_jid(account, jid) + if contact: + actor = contact.name else: actor = jid @@ -148,8 +149,8 @@ class DesktopNotification: if file_props['type'] == 'r': # get the name of the sender, as it is in the roster sender = unicode(file_props['sender']).split('/')[0] - name = gajim.get_first_contact_instance_from_jid( - account, sender).name + name = gajim.contacts.get_first_contact_from_jid(account, + sender).name filename = os.path.basename(file_props['file-name']) if event_type == _('File Transfer Completed'): txt = _('You successfully received %(filename)s from %(name)s.')\ @@ -165,8 +166,8 @@ class DesktopNotification: receiver = receiver.jid receiver = receiver.split('/')[0] # get the name of the contact, as it is in the roster - name = gajim.get_first_contact_instance_from_jid( - account, receiver).name + name = gajim.contacts.get_first_contact_from_jid(account, + receiver).name filename = os.path.basename(file_props['file-name']) if event_type == _('File Transfer Completed'): txt = _('You successfully sent %(filename)s to %(name)s.')\ diff --git a/src/remote_control.py b/src/remote_control.py index ac611d89e..899834001 100644 --- a/src/remote_control.py +++ b/src/remote_control.py @@ -74,7 +74,7 @@ class Remote: def raise_signal(self, signal, arg): if self.signal_object: self.signal_object.raise_signal(signal, repr(arg)) - + class SignalObject(DbusPrototype): ''' Local object definition for /org/gajim/dbus/RemoteObject. This doc must @@ -121,7 +121,6 @@ class SignalObject(DbusPrototype): else: self.emit_signal(INTERFACE, signal, arg) - # signals def VcardInfo(self, *vcard): pass @@ -131,7 +130,7 @@ class SignalObject(DbusPrototype): returns status (show to be exact) which is the global one unless account is given''' account = self._get_real_arguments(args, 1)[0] - accounts = gajim.contacts.keys() + accounts = gajim.contacts.get_accounts() if not account: # If user did not ask for account, returns the global status return helpers.get_global_show() @@ -153,40 +152,48 @@ class SignalObject(DbusPrototype): return str(status) - def send_file(self, *args): - '''send_file(file_path, jid, account=None) - send file, located at 'file_path' to 'jid', using account - (optional) 'account' ''' - file_path, jid, account = self._get_real_arguments(args, 3) - accounts = gajim.contacts.keys() - + def get_account_and_contact(self, account, jid): + ''' get the account (if not given) and contact instance from jid''' + connected_account = None + contact = None + accounts = gajim.contacts.get_accounts() # if there is only one account in roster, take it as default # if user did not ask for account if not account and len(accounts) == 1: account = accounts[0] if account: - if gajim.connections[account].connected > 1: # account is online - connected_account = gajim.connections[account] + if gajim.connections[account].connected > 1: # account is connected + connected_account = account + contact = gajim.contacts.get_contact_with_highest_priority(account, + jid) else: for account in accounts: - if gajim.contacts[account].has_key(jid) and \ - gajim.connections[account].connected > 1: # account is online - connected_account = gajim.connections[account] + contact = gajim.contacts.get_contact_with_highest_priority(account, + jid) + if contact and gajim.connections[account].connected > 1: + # account is connected + connected_account = account break - if gajim.contacts.has_key(account) and \ - gajim.contacts[account].has_key(jid): - contact = gajim.get_highest_prio_contact_from_contacts( - gajim.contacts[account][jid]) - else: + if not contact: contact = jid - + + return connected_account, contact + + def send_file(self, *args): + '''send_file(file_path, jid, account=None) + send file, located at 'file_path' to 'jid', using account + (optional) 'account' ''' + file_path, jid, account = self._get_real_arguments(args, 3) + + connected_account, contact = self.get_account_and_contact(account, jid) + if connected_account: if os.path.isfile(file_path): # is it file? - gajim.interface.instances['file_transfers'].send_file(account, - contact, file_path) + gajim.interface.instances['file_transfers'].send_file( + connected_account, contact, file_path) return True return False - + def send_message(self, *args): ''' send_message(jid, message, keyID=None, account=None) send 'message' to 'jid', using account (optional) 'account'. @@ -196,23 +203,12 @@ class SignalObject(DbusPrototype): return None # or raise error if not keyID: keyID = '' - connected_account = None - accounts = gajim.contacts.keys() - - # if there is only one account in roster, take it as default - if not account and len(accounts) == 1: - account = accounts[0] - if account: - if gajim.connections[account].connected > 1: # account is online - connected_account = gajim.connections[account] - else: - for account in accounts: - if gajim.contacts[account].has_key(jid) and \ - gajim.connections[account].connected > 1: # account is online - connected_account = gajim.connections[account] - break + + connected_account, contact = self.get_account_and_contact(account, jid) + if connected_account: - res = connected_account.send_message(jid, message, keyID) + connection = gajim.connections[connected_account] + res = connection.send_message(jid, message, keyID) return True return False @@ -236,24 +232,25 @@ class SignalObject(DbusPrototype): first_connected_acct = None for acct in accounts: if gajim.connections[acct].connected > 1: # account is online + contact = gajim.contacts.get_first_contact_from_jid(acct, jid) if gajim.interface.msg_win_mgr.has_window(jid): connected_account = acct break # jid is in roster - elif gajim.contacts[acct].has_key(jid): + elif contact: connected_account = acct break - # we send the message to jid not in roster, because account is specified, - # or there is only one account + # we send the message to jid not in roster, because account is + # specified, or there is only one account elif account: connected_account = acct elif first_connected_acct is None: first_connected_acct = acct - + # if jid is not a conntact, open-chat with first connected account if connected_account is None and first_connected_acct: connected_account = first_connected_acct - + if connected_account: gajim.interface.roster.new_chat_from_jid(connected_account, jid) # preserve the 'steal focus preservation' @@ -262,7 +259,7 @@ class SignalObject(DbusPrototype): win.window.focus() return True return False - + def change_status(self, *args, **keywords): ''' change_status(status, message, account). account is optional - if not specified status is changed for all accounts. ''' @@ -276,7 +273,7 @@ class SignalObject(DbusPrototype): status, message) else: # account not specified, so change the status of all accounts - for acc in gajim.contacts.keys(): + for acc in gajim.contacts.get_accounts(): gobject.idle_add(gajim.interface.roster.send_status, acc, status, message) return None @@ -297,10 +294,11 @@ class SignalObject(DbusPrototype): # FIXME: raise exception for missing argument (0.3+) return None - accounts = gajim.contacts.keys() - + accounts = gajim.contacts.get_accounts() + for account in accounts: - if gajim.contacts[account].__contains__(jid): + contact = gajim.contacts.get_first_contact_from_jid(account, jid) + if contact: self.vcard_account = account gajim.connections[account].request_vcard(jid) break @@ -308,13 +306,12 @@ class SignalObject(DbusPrototype): def list_accounts(self, *args): ''' list register accounts ''' - if gajim.contacts: - result = gajim.contacts.keys() - if result and len(result) > 0: - result_array = [] - for account in result: - result_array.append(account.encode('utf-8')) - return result_array + result = gajim.contacts.get_accounts() + if result and len(result) > 0: + result_array = [] + for account in result: + result_array.append(account.encode('utf-8')) + return result_array return None def list_contacts(self, *args): @@ -322,24 +319,22 @@ class SignalObject(DbusPrototype): then return the contacts for the specified account ''' [for_account] = self._get_real_arguments(args, 1) result = [] - if not gajim.contacts or len(gajim.contacts) == 0: + accounts = gajim.contacts.get_accounts() + if len(accounts) == 0: return None if for_account: - if gajim.contacts.has_key(for_account): - for jid in gajim.contacts[for_account]: - item = self._serialized_contacts( - gajim.contacts[for_account][jid]) + accounts_to_search = [for_account] + else: + accounts_to_search = accounts + for account in accounts_to_search: + if account in accounts: + for jid in gajim.contacts.get_jid_list(for_account): + item = self._serialized_contacts(gajim.contacts.get_contact( + for_account, jid)) if item: result.append(item) else: - # 'for_account: is not recognised:', - return None - else: - for account in gajim.contacts: - for jid in gajim.contacts[account]: - item = self._serialized_contacts(gajim.contacts[account][jid]) - if item: - result.append(item) + continue # dbus 0.40 does not support return result as empty list if result == []: return None @@ -407,27 +402,27 @@ class SignalObject(DbusPrototype): def add_contact(self, *args): [account] = self._get_real_arguments(args, 1) - if gajim.contacts.has_key(account): + accounts = gajim.contacts.get_accounts() + if account in accounts: AddNewContactWindow(account) return True return False def remove_contact(self, *args): [jid, account] = self._get_real_arguments(args, 2) - accounts = gajim.contacts.keys() + accounts = gajim.contacts.get_accounts() # if there is only one account in roster, take it as default if account: accounts = [account] - else: - accounts = gajim.contacts.keys() contact_exists = False for account in accounts: - if gajim.contacts[account].has_key(jid): + contacts = gajim.contacts.get_contact(account, jid) + if contacts: gajim.connections[account].unsubscribe(jid) - for contact in gajim.contacts[account][jid]: + for contact in contacts: gajim.interface.roster.remove_contact(contact, account) - del gajim.contacts[account][jid] + gajim.contacts.remove_jid(account, jid) contact_exists = True return contact_exists diff --git a/src/roster_window.py b/src/roster_window.py index 42e0809e7..b0d9bd390 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -40,7 +40,6 @@ import gtkgui_helpers import cell_renderer_image import tooltips -from gajim import Contact from common import gajim from common import helpers from common import i18n @@ -105,12 +104,12 @@ class RosterWindow: return found group_iter = model.iter_children(acct) while group_iter: - user_iter = model.iter_children(group_iter) - while user_iter: - if jid == model[user_iter][C_JID].decode('utf-8') and \ - account == model[user_iter][C_ACCOUNT].decode('utf-8'): - found.append(user_iter) - user_iter = model.iter_next(user_iter) + contact_iter = model.iter_children(group_iter) + while contact_iter: + if jid == model[contact_iter][C_JID].decode('utf-8') and \ + account == model[contact_iter][C_ACCOUNT].decode('utf-8'): + found.append(contact_iter) + contact_iter = model.iter_next(contact_iter) group_iter = model.iter_next(group_iter) return found @@ -147,36 +146,35 @@ class RosterWindow: def add_contact_to_roster(self, jid, account): '''Add a contact to the roster and add groups if they aren't in roster''' showOffline = gajim.config.get('showoffline') - if not gajim.contacts[account].has_key(jid): + contact = gajim.contacts.get_first_contact_from_jid(account, jid) + if not contact: return - users = gajim.contacts[account][jid] - user = users[0] - if user.jid.find('@') <= 0: # if not '@' or '@' starts the jid ==> agent - user.groups = [_('Transports')] - elif user.groups == []: - user.groups.append(_('General')) + if contact.jid.find('@') <= 0: + # if not '@' or '@' starts the jid ==> agent + contact.groups = [_('Transports')] hide = True - if user.sub in ('both', 'to'): + if contact.sub in ('both', 'to'): hide = False - elif user.ask == 'subscribe': + elif contact.ask == 'subscribe': hide = False - # FIXME: uncomment when we support contacts in no group -# elif user.name or len(user.groups): - elif user.name: + elif contact.name or len(contact.groups): hide = False # JEP-0162 if hide: return - if user.show in ('offline', 'error') and \ - not showOffline and (not _('Transports') in user.groups or \ + if contact.show in ('offline', 'error') and \ + not showOffline and (not _('Transports') in contact.groups or \ gajim.connections[account].connected < 2) and \ - not gajim.awaiting_events[account].has_key(user.jid): + not gajim.awaiting_events[account].has_key(jid): return model = self.tree.get_model() - for g in user.groups: + groups = contact.groups + if not groups: + groups = [_('General')] + for g in groups: iterG = self.get_group_iter(g, account) if not iterG: IterAcct = self.get_account_iter(account) @@ -198,40 +196,48 @@ class RosterWindow: typestr = 'agent' # we add some values here. see draw_contact for more - model.append(iterG, (None, user.name, - typestr, user.jid, account, False, None)) + model.append(iterG, (None, contact.name, + typestr, contact.jid, account, False, None)) if gajim.groups[account][g]['expand']: self.tree.expand_row(model.get_path(iterG), False) self.draw_contact(jid, account) self.draw_avatar(jid, account) - def really_remove_contact(self, user, account): - if user.jid in gajim.newly_added[account]: - return - if user.jid.find('@') < 1 and gajim.connections[account].connected > 1: # It's an agent - return - if user.jid in gajim.to_be_removed[account]: - gajim.to_be_removed[account].remove(user.jid) - if gajim.config.get('showoffline'): - self.draw_contact(user.jid, account) - return - self.remove_contact(user, account) + def add_transport_to_roster(self, account, transport): + c = gajim.contacts.create_contact(jid = transport, name = transport, + groups = [_('Transports')], show = 'offline', status = 'offline', + sub = 'from') + gajim.contacts.add_contact(account, c) + gajim.interface.roster.add_contact_to_roster(transport, account) - def remove_contact(self, user, account): - '''Remove a user from the roster''' - if user.jid in gajim.to_be_removed[account]: + def really_remove_contact(self, contact, account): + if contact.jid in gajim.newly_added[account]: + return + if contact.jid.find('@') < 1 and gajim.connections[account].connected > 1: # It's an agent + return + if contact.jid in gajim.to_be_removed[account]: + gajim.to_be_removed[account].remove(contact.jid) + if gajim.config.get('showoffline'): + self.draw_contact(contact.jid, account) + return + self.remove_contact(contact, account) + + def remove_contact(self, contact, account): + '''Remove a contact from the roster''' + if contact.jid in gajim.to_be_removed[account]: return model = self.tree.get_model() - for i in self.get_contact_iter(user.jid, account): + for i in self.get_contact_iter(contact.jid, account): parent_i = model.iter_parent(i) group = model.get_value(parent_i, 3).decode('utf-8') model.remove(i) if model.iter_n_children(parent_i) == 0: model.remove(parent_i) # We need to check all contacts, even offline contacts - for jid in gajim.contacts[account]: - if group in gajim.get_contact_instance_with_highest_priority(account, jid).groups: + for jid in gajim.contacts.get_jid_list(account): + if group in gajim.contacts.get_contact_with_highest_priority( + account, jid).groups: break else: if gajim.groups[account].has_key(group): @@ -252,8 +258,11 @@ class RosterWindow: iters = self.get_contact_iter(jid, account) if len(iters) == 0: return - contact_instances = gajim.get_contact_instances_from_jid(account, jid) - contact = gajim.get_highest_prio_contact_from_contacts(contact_instances) + contact_instances = gajim.contacts.get_contact(account, jid) + contact = gajim.contacts.get_highest_prio_contact_from_contacts( + contact_instances) + if not contact: + return name = gtkgui_helpers.escape_for_pango_markup(contact.name) if len(contact_instances) > 1: @@ -265,9 +274,9 @@ class RosterWindow: add_acct = False # look through all contacts of all accounts for a in gajim.connections: - for j in gajim.contacts[a]: + for j in gajim.contacts.get_jid_list(a): # [0] cause it'fster than highest_prio - c = gajim.contacts[a][j][0] + c = gajim.contacts.get_first_contact_from_jid(a, j) if c.name == contact.name and (j, a) != (jid, account): add_acct = True break @@ -631,15 +640,15 @@ class RosterWindow: self.tree.get_model().clear() for acct in gajim.connections: self.add_account_to_roster(acct) - for jid in gajim.contacts[acct].keys(): + for jid in gajim.contacts.get_jid_list(acct): self.add_contact_to_roster(jid, acct) self.make_menu() # re-make menu in case an account was removed #FIXME: maybe move thie make_menu() in where we remove the account? def fill_contacts_and_groups_dicts(self, array, account): '''fill gajim.contacts and gajim.groups''' - if not gajim.contacts.has_key(account): - gajim.contacts[account] = {} + if account not in gajim.contacts.get_accounts(): + gajim.contacts.add_account(account) if not gajim.groups.has_key(account): gajim.groups[account] = {} for jid in array.keys(): @@ -665,13 +674,14 @@ class RosterWindow: 'attached_gpg_keys').split() if jid in attached_keys: keyID = attached_keys[attached_keys.index(jid) + 1] - contact1 = Contact(jid = ji, name = name, groups = array[jid]['groups'], - show = show, status = status, sub = array[jid]['subscription'], - ask = array[jid]['ask'], resource = resource, keyID = keyID) + contact1 = gajim.contacts.create_contact(jid = ji, name = name, + groups = array[jid]['groups'], show = show, status = status, + sub = array[jid]['subscription'], ask = array[jid]['ask'], + resource = resource, keyID = keyID) + gajim.contacts.add_contact(account, contact1) # when we draw the roster, we avoid having the same contact # more than once (f.e. we avoid showing it twice when 2 resources) - gajim.contacts[account][ji] = [contact1] for g in array[jid]['groups']: if g in gajim.groups[account].keys(): continue @@ -692,18 +702,15 @@ class RosterWindow: def chg_contact_status(self, contact, show, status, account): '''When a contact changes his or her status''' showOffline = gajim.config.get('showoffline') - contact_instances = gajim.contacts[account][contact.jid] + contact_instances = gajim.contacts.get_contact(account, contact.jid) contact.show = show contact.status = status if show in ('offline', 'error') and \ not gajim.awaiting_events[account].has_key(contact.jid): - if len(contact_instances) > 1: # if multiple resources - contact_instances.remove(contact) - self.draw_contact(contact.jid, account) - elif not showOffline: - self.remove_contact(contact, account) - else: - self.draw_contact(contact.jid, account) + if len(contact_instances) > 1 or not showOffline: + # if multiple resources or we don't show offline contacts + gajim.contacts.remove_contact(account, contact) + self.draw_contact(contact.jid, account) else: if not self.get_contact_iter(contact.jid, account): self.add_contact_to_roster(contact.jid, account) @@ -721,17 +728,17 @@ class RosterWindow: uf_show = helpers.get_uf_show(show) ctl.print_conversation(_('%s is now %s (%s)') % (name, uf_show, status), 'status') - if contact == gajim.get_contact_instance_with_highest_priority(account, - contact.jid): + if contact == gajim.contacts.get_contact_with_highest_priority(account, + contact.jid): ctl.draw_banner() - def on_info(self, widget, user, account): - '''Call vcard_information_window class to display user's information''' + def on_info(self, widget, contact, account): + '''Call vcard_information_window class to display contact's information''' info = gajim.interface.instances[account]['infos'] - if info.has_key(user.jid): - info[user.jid].window.present() + if info.has_key(contact.jid): + info[contact.jid].window.present() else: - info[user.jid] = vcard.VcardWindow(user, account) + info[contact.jid] = vcard.VcardWindow(contact, account) def show_tooltip(self, contact): pointer = self.tree.get_pointer() @@ -774,8 +781,9 @@ class RosterWindow: jid = model[iter][C_JID].decode('utf-8') if self.tooltip.timeout == 0 or self.tooltip.id != props[0]: self.tooltip.id = row + contacts = gajim.contacts.get_contact(account, jid) self.tooltip.timeout = gobject.timeout_add(500, - self.show_tooltip, gajim.contacts[account][jid]) + self.show_tooltip, contacts) elif model[iter][C_TYPE] == 'account': # we're on an account entry in the roster account = model[iter][C_ACCOUNT].decode('utf-8') @@ -789,9 +797,8 @@ class RosterWindow: contacts = [] connection = gajim.connections[account] # get our current contact info - contact = Contact(jid = jid, name = account, - show = connection.get_status(), - sub = 'both', + contact = gajim.contacts.create_contact(jid = jid, name = account, + show = connection.get_status(), sub = 'both', status = connection.status, resource = gajim.config.get_per('accounts', connection.name, 'resource'), @@ -810,10 +817,11 @@ class RosterWindow: show = roster.getShow(jid+'/'+resource) if not show: show = 'online' - contact = Contact(jid=jid, name=account, - show=show, - status=roster.getStatus(jid+'/'+resource), resource=resource, - priority=roster.getPriority(jid+'/'+resource)) + contact = gajim.contacts.create_contact(jid = jid, + name = account, show = show, + status = roster.getStatus(jid+'/'+resource), + resource = resource, + priority = roster.getPriority(jid+'/'+resource)) contacts.append(contact) if self.tooltip.timeout == 0 or self.tooltip.id != props[0]: self.tooltip.id = row @@ -834,7 +842,7 @@ class RosterWindow: # We remove the server contact # remove it from treeview self.remove_contact(contact, account) - del gajim.contacts[account][contact.jid] + gajim.contacts.remove_contact(account, contact) return window = dialogs.ConfirmationDialog(_('Transport "%s" will be removed') % contact.jid, _('You will no longer be able to send and receive messages to contacts from this transport.')) @@ -844,14 +852,16 @@ class RosterWindow: # remove transport from treeview self.remove_contact(contact, account) # remove transport's contacts from treeview - for jid, contacts in gajim.contacts[account].items(): - contact = contacts[0] + jid_list = gajim.contacts.get_jid_list(account) + for jid in jid_list: if jid.endswith('@' + contact.jid): + c = gajim.contacts.get_first_contact_from_jid(account, jid) gajim.log.debug( 'Removing contact %s due to unregistered transport %s'\ - % (contact.jid, contact.name)) - self.remove_contact(contact, account) - del gajim.contacts[account][contact.jid] + % (jid, contact.jid)) + # Transport contacts can't have 2 resources + self.remove_contact(c, account) + gajim.contacts.remove_contact(account, contact) def on_rename(self, widget, iter, path): # this function is called either by F2 or by Rename menuitem @@ -868,22 +878,22 @@ class RosterWindow: account = model[iter][C_ACCOUNT].decode('utf-8') if row_type == 'contact': # it's jid - #Remove resource indicator (Name (2)) - contacts = gajim.contacts[account][jid] - name = contacts[0].name + # Remove resource indicator (Name (2)) + contact = gajim.contacts.get_first_contact_from_jid(account, jid) + name = contact.name model[iter][C_NAME] = gtkgui_helpers.escape_for_pango_markup(name) model[iter][C_EDITABLE] = True # set 'editable' to True self.tree.set_cursor(path, self.tree.get_column(0), True) - def on_assign_pgp_key(self, widget, user, account): + def on_assign_pgp_key(self, widget, contact, account): attached_keys = gajim.config.get_per('accounts', account, 'attached_gpg_keys').split() keys = {} keyID = 'None' for i in xrange(0, len(attached_keys)/2): keys[attached_keys[2*i]] = attached_keys[2*i+1] - if attached_keys[2*i] == user.jid: + if attached_keys[2*i] == contact.jid: keyID = attached_keys[2*i+1] public_keys = gajim.connections[account].ask_gpg_keys() public_keys['None'] = 'None' @@ -893,22 +903,22 @@ class RosterWindow: if keyID is None: return if keyID[0] == 'None': - if user.jid in keys: - del keys[user.jid] + if contact.jid in keys: + del keys[contact.jid] else: - keys[user.jid] = keyID[0] - for u in gajim.contacts[account][user.jid]: + keys[contact.jid] = keyID[0] + for u in gajim.contacts.get_contact(account, contact.jid): u.keyID = keyID[0] - if gajim.interface.msg_win_mgr.has_window(user.jid): - ctl = gajim.interface.msg_win_mgr.get_control(user.jid) + if gajim.interface.msg_win_mgr.has_window(contact.jid): + ctl = gajim.interface.msg_win_mgr.get_control(contact.jid) ctl.draw_widgets() keys_str = '' for jid in keys: keys_str += jid + ' ' + keys[jid] + ' ' gajim.config.set_per('accounts', account, 'attached_gpg_keys', keys_str) - def on_edit_groups(self, widget, user, account): - dlg = dialogs.EditGroupsDialog(user, account) + def on_edit_groups(self, widget, contact, account): + dlg = dialogs.EditGroupsDialog(contact, account) dlg.run() def on_history(self, widget, contact, account): @@ -936,8 +946,7 @@ class RosterWindow: jid = model[iter][C_JID].decode('utf-8') path = model.get_path(iter) account = model[iter][C_ACCOUNT].decode('utf-8') - contact = gajim.get_highest_prio_contact_from_contacts( - gajim.contacts[account][jid]) + contact = gajim.contacts.get_contact_with_highest_priority(account, jid) xml = gtk.glade.XML(GTKGUI_GLADE, 'roster_contact_context_menu', APP) @@ -1055,14 +1064,14 @@ class RosterWindow: jid = model[iter][C_JID].decode('utf-8') path = model.get_path(iter) account = model[iter][C_ACCOUNT].decode('utf-8') - user = gajim.get_contact_instance_with_highest_priority(account, jid) + contact = gajim.contacts.get_contact_with_highest_priority(account, jid) menu = gtk.Menu() item = gtk.ImageMenuItem(_('_Log on')) icon = gtk.image_new_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_MENU) item.set_image(icon) menu.append(item) - show = gajim.get_contact_instance_with_highest_priority(account, jid).show + show = contact.show if show != 'offline' and show != 'error': item.set_sensitive(False) item.connect('activate', self.on_agent_logging, jid, None, account) @@ -1083,13 +1092,13 @@ class RosterWindow: icon = gtk.image_new_from_stock(gtk.STOCK_PREFERENCES, gtk.ICON_SIZE_MENU) item.set_image(icon) menu.append(item) - item.connect('activate', self.on_edit_agent, user, account) + item.connect('activate', self.on_edit_agent, contact, account) item = gtk.ImageMenuItem(_('_Remove from Roster')) icon = gtk.image_new_from_stock(gtk.STOCK_REMOVE, gtk.ICON_SIZE_MENU) item.set_image(icon) menu.append(item) - item.connect('activate', self.on_remove_agent, user, account) + item.connect('activate', self.on_remove_agent, contact, account) event_button = self.get_possible_button_event(event) @@ -1226,41 +1235,41 @@ class RosterWindow: event.time) menu.show_all() - def on_add_to_roster(self, widget, user, account): - dialogs.AddNewContactWindow(account, user.jid) + def on_add_to_roster(self, widget, contact, account): + dialogs.AddNewContactWindow(account, contact.jid) def authorize(self, widget, jid, account): - '''Authorize a user (by re-sending auth menuitem)''' + '''Authorize a contact (by re-sending auth menuitem)''' gajim.connections[account].send_authorization(jid) dialogs.InformationDialog(_('Authorization has been sent'), _('Now "%s" will know your status.') %jid) def req_sub(self, widget, jid, txt, account, group=None, pseudo=None): - '''Request subscription to a user''' + '''Request subscription to a contact''' if not pseudo: pseudo = jid gajim.connections[account].request_subscription(jid, txt) - if not group: - group = _('General') - if not gajim.contacts[account].has_key(jid): + if group: + group = [group] + contact = gajim.contacts.get_contact_with_highest_priority(account, jid) + if not contact: keyID = '' attached_keys = gajim.config.get_per('accounts', account, 'attached_gpg_keys').split() if jid in attached_keys: keyID = attached_keys[attached_keys.index(jid) + 1] - user1 = Contact(jid = jid, name = pseudo, groups = [group], - show = 'requested', status = '', ask = 'none', + contact = gajim.contacts.create_contact(jid = jid, name = pseudo, + groups = group, show = 'requested', status = '', ask = 'none', sub = 'subscribe', keyID = keyID) - gajim.contacts[account][jid] = [user1] + gajim.contacts.add_contact(account, contact) else: - user1 = gajim.get_contact_instance_with_highest_priority(account, jid) - if not _('not in the roster') in user1.groups: + if not _('not in the roster') in contact.groups: dialogs.InformationDialog(_('Subscription request has been sent'), -_('If "%s" accepts this request you will know his or her status.') %jid) +_('If "%s" accepts this request you will know his or her status.') % jid) return - user1.groups = [group] - user1.name = pseudo - self.remove_contact(user1, account) + contact.groups = group + contact.name = pseudo + self.remove_contact(contact, account) self.add_contact_to_roster(jid, account) def revoke_auth(self, widget, jid, account): @@ -1300,11 +1309,12 @@ _('If "%s" accepts this request you will know his or her status.') %jid) type = model[iter][C_TYPE] if type in ('account', 'group'): return - user = gajim.get_contact_instance_with_highest_priority(account, jid) + contact = gajim.contacts.get_contact_with_highest_priority(account, + jid) if type == 'contact': - self.on_req_usub(widget, user, account) + self.on_req_usub(widget, contact, account) elif type == 'agent': - self.on_remove_agent(widget, user, account) + self.on_remove_agent(widget, contact, account) def show_appropriate_context_menu(self, event, iter): model = self.tree.get_model() @@ -1363,11 +1373,10 @@ _('If "%s" accepts this request you will know his or her status.') %jid) account = model[iter][C_ACCOUNT].decode('utf-8') jid = model[iter][C_JID].decode('utf-8') win = None - if gajim.interface.msg_win_mgr.has_window(jid): - win = gajim.interface.msg_win_mgr.get_window(jid) - elif gajim.contacts[account].has_key(jid): - c = gajim.get_contact_instance_with_highest_priority(account, - jid) + c = gajim.contacts.get_contact_with_highest_priority(account, jid) + if gajim.interface.msg_win_mgr.has_window(c.jid): + win = gajim.interface.msg_win_mgr.get_window(c.jid) + elif c: self.new_chat(c, account) win = gajim.interface.msg_win_mgr.get_window(jid) win.set_active_tab(jid) @@ -1411,27 +1420,28 @@ _('If "%s" accepts this request you will know his or her status.') %jid) else: self.tree.expand_row(path, False) - def on_req_usub(self, widget, user, account): + def on_req_usub(self, widget, contact, account): '''Remove a contact''' window = dialogs.ConfirmationDialogCheck( - _('Contact "%s" will be removed from your roster') % (user.name), + _('Contact "%s" will be removed from your roster') % (contact.name), _('By removing this contact you also by default remove authorization resulting in him or her always seeing you as offline.'), _('I want this contact to know my status after removal')) - # maybe use 2 optionboxes from which the user can select? (better) + # maybe use 2 optionboxes from which the contact can select? (better) if window.get_response() == gtk.RESPONSE_OK: remove_auth = True if window.is_checked(): remove_auth = False - gajim.connections[account].unsubscribe(user.jid, remove_auth) - for u in gajim.contacts[account][user.jid]: + gajim.connections[account].unsubscribe(contact.jid, remove_auth) + for u in gajim.contacts.get_contact(account, contact.jid): self.remove_contact(u, account) - del gajim.contacts[account][u.jid] - if gajim.interface.msg_win_mgr.has_window(user.jid): - user1 = Contact(jid = user.jid, name = user.name, - groups = [_('not in the roster')], show = 'not in the roster', - status = '', ask = 'none', keyID = user.keyID) - gajim.contacts[account][user.jid] = [user1] - self.add_contact_to_roster(user.jid, account) + gajim.contacts.remove_jid(account, u.jid) + if gajim.interface.msg_win_mgr.has_window(contact.jid): + c = gajim.contacts.create_contact(jid = contact.jid, + name = contact.name, groups = [_('not in the roster')], + show = 'not in the roster', status = '', ask = 'none', + keyID = contact.keyID) + gajim.contacts.add_contact(account, c) + self.add_contact_to_roster(contact.jid, account) def forget_gpg_passphrase(self, keyid): if self.gpg_passphrase.has_key(keyid): @@ -1634,7 +1644,7 @@ _('If "%s" accepts this request you will know his or her status.') %jid) def on_status_changed(self, account, status): '''the core tells us that our status has changed''' - if not gajim.contacts.has_key(account): + if account not in gajim.contacts.get_accounts(): return model = self.tree.get_model() accountIter = self.get_account_iter(account) @@ -1643,13 +1653,14 @@ _('If "%s" accepts this request you will know his or her status.') %jid) if status == 'offline': if accountIter: model[accountIter][6] = None - for jid in gajim.contacts[account]: - luser = gajim.contacts[account][jid] - luser_copy = [] - for user in luser: - luser_copy.append(user) - for user in luser_copy: - self.chg_contact_status(user, 'offline', 'Disconnected', account) + for jid in gajim.contacts.get_jid_list(account): + lcontact = gajim.contacts.get_contact(account, jid) + lcontact_copy = [] + for contact in lcontact: + lcontact_copy.append(contact) + for contact in lcontact_copy: + self.chg_contact_status(contact, 'offline', 'Disconnected', + account) self.update_status_combobox() self.make_menu() @@ -1663,18 +1674,18 @@ _('If "%s" accepts this request you will know his or her status.') %jid) mw.new_tab(chat_control) def new_chat_from_jid(self, account, jid): - if gajim.contacts[account].has_key(jid): - contact = gajim.get_contact_instance_with_highest_priority(account, jid) - else: + contact = gajim.contacts.get_contact_with_highest_priority(account, jid) + if not contact: keyID = '' attached_keys = gajim.config.get_per('accounts', account, 'attached_gpg_keys').split() if jid in attached_keys: keyID = attached_keys[attached_keys.index(jid) + 1] - contact = Contact(jid = jid, name = jid.split('@')[0], - groups = [_('not in the roster')], show = 'not in the roster', - status = '', sub = 'none', keyID = keyID) - gajim.contacts[account][jid] = [contact] + contact = gajim.contacts.create_contact(jid = jid, + name = jid.split('@')[0], groups = [_('not in the roster')], + show = 'not in the roster', status = '', sub = 'none', + keyID = keyID) + gajim.contacts.add_contact(account, contact) self.add_contact_to_roster(contact.jid, account) if not gajim.interface.msg_win_mgr.has_window(contact.jid): @@ -1696,16 +1707,18 @@ _('If "%s" accepts this request you will know his or her status.') %jid) def on_message(self, jid, msg, tim, account, encrypted = False, msg_type = '', subject = None, resource = ''): '''when we receive a message''' - if not gajim.contacts[account].has_key(jid): + contact = gajim.contacts.get_contact_with_highest_priority(account, jid) + if not contact: keyID = '' attached_keys = gajim.config.get_per('accounts', account, 'attached_gpg_keys').split() if jid in attached_keys: keyID = attached_keys[attached_keys.index(jid) + 1] - user1 = Contact(jid = jid, name = jid.split('@')[0], - groups = [_('not in the roster')], show = 'not in the roster', - status = '', ask = 'none', keyID = keyID, resource = resource) - gajim.contacts[account][jid] = [user1] + contact = gajim.contacts.create_contact(jid = jid, + name = jid.split('@')[0], groups = [_('not in the roster')], + show = 'not in the roster', status = '', ask = 'none', + keyID = keyID, resource = resource) + gajim.contacts.add_contact(account, contact) self.add_contact_to_roster(jid, account) iters = self.get_contact_iter(jid, account) @@ -1727,8 +1740,6 @@ _('If "%s" accepts this request you will know his or her status.') %jid) popup = True if msg_type == 'normal' and popup: # it's single message to be autopopuped - contact = gajim.get_contact_instance_with_highest_priority(account, - jid) dialogs.SingleMessageWindow(account, contact.jid, action = 'receive', from_whom = jid, subject = subject, message = msg, resource = resource) @@ -1755,8 +1766,7 @@ _('If "%s" accepts this request you will know his or her status.') %jid) self.nb_unread += 1 if popup: if not gajim.interface.msg_win_mgr.has_window(jid): - c = gajim.get_contact_instance_with_highest_priority(account, jid) - self.new_chat(c, account) + self.new_chat(contact, account) if path: self.tree.expand_row(path[0:1], False) self.tree.expand_row(path[0:2], False) @@ -1973,7 +1983,8 @@ _('If "%s" accepts this request you will know his or her status.') %jid) gajim.interface.remove_first_event(account, jid, typ) return True elif typ == 'file-request': - contact = gajim.get_contact_instance_with_highest_priority(account, jid) + contact = gajim.contacts.get_contact_with_highest_priority(account, + jid) gajim.interface.remove_first_event(account, jid, typ) ft.show_file_request(account, contact, data) return True @@ -2008,13 +2019,13 @@ _('If "%s" accepts this request you will know his or her status.') %jid) if first_ev: if self.open_event(account, jid, first_ev): return + c = gajim.contacts.get_contact_with_highest_priority(account, jid) # Get the window containing the chat win = gajim.interface.msg_win_mgr.get_window(jid) if win: win.set_active_tab(jid) - elif gajim.contacts[account].has_key(jid): - contact = gajim.get_contact_instance_with_highest_priority(account, jid) - self.new_chat(contact, account) + elif c: + self.new_chat(c, account) win = gajim.interface.msg_win_mgr.get_window(jid) win.set_active_tab(jid) win.window.present() @@ -2086,7 +2097,8 @@ _('If "%s" accepts this request you will know his or her status.') %jid) jid = model[iter][C_JID].decode('utf-8') type = model[iter][C_TYPE] # restore the number of resources string at the end of contact name - if type == 'contact' and len(gajim.contacts[account][jid]) > 1: + contacts = gajim.contacts.get_contact(account, jid) + if type == 'contact' and len(contacts) > 1: self.draw_contact(jid, account) # reset editable to False model[iter][C_EDITABLE] = False @@ -2112,29 +2124,31 @@ _('If "%s" accepts this request you will know his or her status.') %jid) jid = model[iter][C_JID].decode('utf-8') type = model[iter][C_TYPE] if type == 'contact': - old_text = gajim.get_contact_instance_with_highest_priority(account, jid).name + old_text = gajim.contacts.get_contact_with_highest_priority(account, + jid).name if old_text != new_text: - for u in gajim.contacts[account][jid]: + for u in gajim.contacts.get_contact(account, jid): u.name = new_text gajim.connections[account].update_contact(jid, new_text, u.groups) self.draw_contact(jid, account) elif type == 'group': # in C_JID cilumn it's not escaped old_name = model[iter][C_JID].decode('utf-8') - # Groups maynot change name from or to 'not in the roster' + # Groups maynot change name from or to 'not in the roster' if _('not in the roster') in (new_text, old_name): return - #get all users in that group - for jid in gajim.contacts[account]: - user = gajim.get_contact_instance_with_highest_priority(account, jid) - if old_name in user.groups: + # get all contacts in that group + for jid in gajim.contacts.get_jid_list(account): + contact = gajim.contacts.get_contact_with_highest_priority(account, + jid) + if old_name in contact.groups: #set them in the new one and remove it from the old - self.remove_contact(user, account) - user.groups.remove(old_name) - user.groups.append(new_text) - self.add_contact_to_roster(user.jid, account) - gajim.connections[account].update_contact(user.jid, user.name, - user.groups) + self.remove_contact(contact, account) + contact.groups.remove(old_name) + contact.groups.append(new_text) + self.add_contact_to_roster(contact.jid, account) + gajim.connections[account].update_contact(contact.jid, + contact.name, contact.groups) model.set_value(iter, 5, False) def on_service_disco_menuitem_activate(self, widget, account): @@ -2344,10 +2358,10 @@ _('If "%s" accepts this request you will know his or her status.') %jid) renderer.set_property('cell-background', None) renderer.set_property('xalign', 1) # align pixbuf to the right - def get_show(self, luser): - prio = luser[0].priority - show = luser[0].show - for u in luser: + def get_show(self, lcontact): + prio = lcontact[0].priority + show = lcontact[0].show + for u in lcontact: if u.priority > prio: prio = u.priority show = u.show @@ -2381,22 +2395,28 @@ _('If "%s" accepts this request you will know his or her status.') %jid) jid1 = model[iter1][C_JID].decode('utf-8') jid2 = model[iter2][C_JID].decode('utf-8') if type1 == 'contact': - luser1 = gajim.contacts[account1][jid1] - name1 = luser1[0].name + lcontact1 = gajim.contacts.get_contact(account1, jid1) + contact1 = gajim.contacts.get_first_contact_from_jid(account1, jid1) + if not contact1: + return 0 + name1 = contact1.name if type2 == 'contact': - luser2 = gajim.contacts[account2][jid2] - name2 = luser2[0].name + lcontact2 = gajim.contacts.get_contact(account2, jid2) + contact2 = gajim.contacts.get_first_contact_from_jid(account2, jid2) + if not contact2: + return 0 + name2 = contact2.name # We first compare by show if sort_by_show is True if type1 == 'contact' and type2 == 'contact' and \ gajim.config.get('sort_by_show'): cshow = {'online':0, 'chat': 1, 'away': 2, 'xa': 3, 'dnd': 4, 'invisible': 5, 'offline': 6, 'not in the roster': 7, 'error': 8} - s = self.get_show(luser1) + s = self.get_show(lcontact1) if s in cshow: show1 = cshow[s] else: show1 = 9 - s = self.get_show(luser2) + s = self.get_show(lcontact2) if s in cshow: show2 = cshow[s] else: @@ -2471,22 +2491,23 @@ _('If "%s" accepts this request you will know his or her status.') %jid) return # We upgrade only the first user because user2.groups is a pointer to # user1.groups - u = gajim.contacts[account][data][0] + c = gajim.contacts.get_first_contact_from_jid(account, data) if context.action != gtk.gdk.ACTION_COPY: - u.groups.remove(grp_source) + c.groups.remove(grp_source) if model.iter_n_children(iter_group_source) == 1: # this was the only child model.remove(iter_group_source) # delete the group if it is empty (need to look for offline users too) - for jid in gajim.contacts[account]: - if grp_source in gajim.get_contact_instance_with_highest_priority(account, jid).groups: + for jid in gajim.contacts.get_jid_list(account): + if grp_source in gajim.contacts.get_contact_with_highest_priority( + account, jid).groups: break else: del gajim.groups[account][grp_source] - if not grp_dest in u.groups: - u.groups.append(grp_dest) + if not grp_dest in c.groups: + c.groups.append(grp_dest) self.add_contact_to_roster(data, account) - gajim.connections[account].update_contact(u.jid, u.name, u.groups) + gajim.connections[account].update_contact(c.jid, c.name, c.groups) if context.action in (gtk.gdk.ACTION_MOVE, gtk.gdk.ACTION_COPY): context.finish(True, True, etime) return diff --git a/src/systray.py b/src/systray.py index f5c378398..06ea29dd4 100644 --- a/src/systray.py +++ b/src/systray.py @@ -33,7 +33,6 @@ import os import tooltips import gtkgui_helpers -from gajim import Contact from common import gajim from common import helpers from common import i18n @@ -101,10 +100,11 @@ class Systray: self.set_img() def start_chat(self, widget, account, jid): + contact = gajim.contacts.get_first_contact_from_jid(account, jid) if gajim.interface.msg_win_mgr.has_window(jid): gajim.interface.msg_win_mgr.get_window(jid).set_active_tab(jid) gajim.interface.msg_win_mgr.get_window(jid).present() - elif gajim.contacts[account].has_key(jid): + elif contact: gajim.interface.roster.new_chat(gajim.contacts[account][jid][0], account) gajim.interface.msg_win_mgr.get_window(jid).set_active_tab(jid) @@ -249,8 +249,8 @@ class Systray: groups_menu.append(item) contacts_menu = gtk.Menu() item.set_submenu(contacts_menu) - for contacts in gajim.contacts[account].values(): - contact = gajim.get_highest_prio_contact_from_contacts(contacts) + for jid in gajim.contacts.get_jid_list(account): + contact = gajim.get_contact_with_highest_priority(account, jid) if group in contact.groups and contact.show != 'offline' and \ contact.show != 'error': at_least_one = True diff --git a/src/tabbed_chat_window.py b/src/tabbed_chat_window.py index 4faf68aeb..6931d2b86 100644 --- a/src/tabbed_chat_window.py +++ b/src/tabbed_chat_window.py @@ -338,17 +338,16 @@ class TabbedChatWindow(chat.Chat): def set_state_image(self, jid): prio = 0 - if gajim.contacts[self.account].has_key(jid): - contacts_list = gajim.contacts[self.account][jid] - else: - contacts_list = [self.contacts[jid]] + contact_list = gajim.contacts.get_contact(self.account, jid) + if not contact_list: + contact_list = [self.contacts[jid]] - contact = contacts_list[0] + contact = contact_list[0] show = contact.show jid = contact.jid keyID = contact.keyID - for u in contacts_list: + for u in contact_list: if u.priority > prio: prio = u.priority show = u.show @@ -436,7 +435,7 @@ class TabbedChatWindow(chat.Chat): def on_send_file_menuitem_activate(self, widget): jid = self.get_active_jid() - contact = gajim.get_first_contact_instance_from_jid(self.account, jid) + contact = gajim.contacts.get_first_contact_from_jid(self.account, jid) gajim.interface.instances['file_transfers'].show_file_send_request( self.account, contact) @@ -532,7 +531,7 @@ class TabbedChatWindow(chat.Chat): in the last 5 seconds? if yes we go active for mouse, composing for kbd if no we go paused if we were previously composing ''' - contact = gajim.get_first_contact_instance_from_jid(self.account, jid) + contact = gajim.contacts.get_first_contact_from_jid(self.account, jid) if jid not in self.xmls or contact is None: # the tab with jid is no longer open or contact left # stop timer @@ -564,7 +563,7 @@ class TabbedChatWindow(chat.Chat): in the last 30 seconds? if yes we go active if no we go inactive ''' - contact = gajim.get_first_contact_instance_from_jid(self.account, jid) + contact = gajim.contacts.get_first_contact_from_jid(self.account, jid) if jid not in self.xmls or contact is None: # the tab with jid is no longer open or contact left return False # stop looping @@ -691,7 +690,7 @@ class TabbedChatWindow(chat.Chat): if jid is None: jid = self.get_active_jid() - contact = gajim.get_first_contact_instance_from_jid(self.account, jid) + contact = gajim.contacts.get_first_contact_from_jid(self.account, jid) if contact is None: # contact was from pm in MUC, and left the room so contact is None @@ -748,7 +747,7 @@ class TabbedChatWindow(chat.Chat): return jid = self.get_active_jid() - contact = gajim.get_first_contact_instance_from_jid(self.account, jid) + contact = gajim.contacts.get_first_contact_from_jid(self.account, jid) if contact is None: # contact was from pm in MUC, and left the room, or we left the room room, nick = gajim.get_room_and_nick_from_fjid(jid) @@ -877,7 +876,7 @@ class TabbedChatWindow(chat.Chat): if (contact.show == 'offline' or contact.show == 'error'): showOffline = gajim.config.get('showoffline') if not showOffline and typ == 'chat' and \ - len(gajim.contacts[self.account][jid]) == 1: + len(gajim.contacts.get_contact(self.account, jid)) == 1: gajim.interface.roster.really_remove_contact(contact, self.account) elif typ == 'pm': gcs[room_jid].remove_contact(room_jid, nick) diff --git a/src/tooltips.py b/src/tooltips.py index eec22c7ed..068c2ddcb 100644 --- a/src/tooltips.py +++ b/src/tooltips.py @@ -186,25 +186,24 @@ class NotificationAreaTooltip(BaseTooltip, StatusTable): def get_accounts_info(self): accounts = [] - if gajim.contacts: - for account in gajim.contacts.keys(): - status_idx = gajim.connections[account].connected - # uncomment the following to hide offline accounts - # if status_idx == 0: continue - status = gajim.SHOW_LIST[status_idx] - message = gajim.connections[account].status - single_line = helpers.get_uf_show(status) - if message is None: - message = '' - else: - message = message.strip() - if message != '': - single_line += ': ' + message - # the other solution is to hide offline accounts - elif status == 'offline': - message = helpers.get_uf_show(status) - accounts.append({'name': account, 'status_line': single_line, - 'show': status, 'message': message}) + for account in gajim.contacts.get_accounts(): + status_idx = gajim.connections[account].connected + # uncomment the following to hide offline accounts + # if status_idx == 0: continue + status = gajim.SHOW_LIST[status_idx] + message = gajim.connections[account].status + single_line = helpers.get_uf_show(status) + if message is None: + message = '' + else: + message = message.strip() + if message != '': + single_line += ': ' + message + # the other solution is to hide offline accounts + elif status == 'offline': + message = helpers.get_uf_show(status) + accounts.append({'name': account, 'status_line': single_line, + 'show': status, 'message': message}) return accounts def fill_table_with_accounts(self, accounts): @@ -245,10 +244,12 @@ class NotificationAreaTooltip(BaseTooltip, StatusTable): for acct in gajim.connections: # we count unread chat/pm messages for ctl in gajim.interface.msg_win_mgr.controls(): - if gajim.contacts[acct].has_key(jid): + c = gajim.contacts.get_first_contact_from_jid(acct, jid) + if c: unread_chat += ctl.nb_unread else: unread_pm += ctl.nb_unread + # FIXME # we count unread gc/pm messages gc_wins = gajim.interface.instances[acct]['gc'] @@ -341,7 +342,7 @@ class GCTooltip(BaseTooltip): # escape markup entities info += ' - ' + gtkgui_helpers.escape_for_pango_markup(status) - if contact.resource.strip() != '': + if hasattr(contact, 'resource') and contact.resource.strip() != '': info += '\n' + _('Resource: ') + \ '' + gtkgui_helpers.escape_for_pango_markup( contact.resource) @@ -377,7 +378,8 @@ class RosterTooltip(NotificationAreaTooltip): self.win.add(self.hbox) return # primary contact - prim_contact = gajim.get_highest_prio_contact_from_contacts(contacts) + prim_contact = gajim.contacts.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) @@ -483,7 +485,7 @@ class FileTransfersTooltip(BaseTooltip): if file_props['type'] == 'r': text += '\n' + _('Sender: ') + '' sender = unicode(file_props['sender']).split('/')[0] - name = gajim.get_first_contact_instance_from_jid( + name = gajim.contacts.get_first_contact_from_jid( file_props['tt_account'], sender).name else: text += '\n' + _('Recipient: ') + '' @@ -494,7 +496,7 @@ class FileTransfersTooltip(BaseTooltip): if receiver.find('@') == -1: name = receiver else: - name = gajim.get_first_contact_instance_from_jid( + name = gajim.contacts.get_first_contact_from_jid( file_props['tt_account'], receiver).name text += gtkgui_helpers.escape_for_pango_markup(name) text += '\n' + _('Size: ') + '' diff --git a/src/vcard.py b/src/vcard.py index f502ba0d9..a40ef2c94 100644 --- a/src/vcard.py +++ b/src/vcard.py @@ -78,7 +78,7 @@ class VcardWindow: '''Class for contact's information window''' def __init__(self, contact, account, vcard = False): - #the contact variable is the jid if vcard is true + # the contact variable is the jid if vcard is true self.xml = gtk.glade.XML(GTKGUI_GLADE, 'vcard_information_window', APP) self.window = self.xml.get_widget('vcard_information_window') self.xml.get_widget('photo_vbuttonbox').set_no_show_all(True) @@ -330,8 +330,9 @@ class VcardWindow: self.os_info = {0: {'resource': self.contact.resource, 'client': '', 'os': ''}} i = 1 - if gajim.contacts[self.account].has_key(self.contact.jid): - for c in gajim.contacts[self.account][self.contact.jid]: + contact_list = gajim.contacts.get_contact(self.account, self.contact.jid) + if contact_list: + for c in contact_list: if c.resource != self.contact.resource: resources += '\n%s (%s)' % (c.resource, unicode(c.priority))