From bcb704366cb5e333a626c18c308c7e0448a8e69f Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdenetwork@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kopete/protocols/jabber/jabbercontactpool.cpp | 355 ++++++++++++++++++++++++++ 1 file changed, 355 insertions(+) create mode 100644 kopete/protocols/jabber/jabbercontactpool.cpp (limited to 'kopete/protocols/jabber/jabbercontactpool.cpp') diff --git a/kopete/protocols/jabber/jabbercontactpool.cpp b/kopete/protocols/jabber/jabbercontactpool.cpp new file mode 100644 index 00000000..736c6045 --- /dev/null +++ b/kopete/protocols/jabber/jabbercontactpool.cpp @@ -0,0 +1,355 @@ + /* + * jabbercontactpool.cpp + * + * Copyright (c) 2004 by Till Gerken + * Copyright (c) 2006 by Olivier Goffart + * + * Kopete (c) by the Kopete developers + * + * ************************************************************************* + * * * + * * 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; either version 2 of the License, or * + * * (at your option) any later version. * + * * * + * ************************************************************************* + */ + +#include "jabbercontactpool.h" + +#include +#include +#include +#include +#include +#include "kopeteuiglobal.h" +#include "jabberprotocol.h" +#include "jabberbasecontact.h" +#include "jabbercontact.h" +#include "jabbergroupcontact.h" +#include "jabbergroupmembercontact.h" +#include "jabberresourcepool.h" +#include "jabberaccount.h" +#include "jabbertransport.h" + +JabberContactPool::JabberContactPool ( JabberAccount *account ) +{ + + // automatically delete all contacts in the pool upon removal + mPool.setAutoDelete (true); + + mAccount = account; + +} + +JabberContactPool::~JabberContactPool () +{ +} + +JabberContactPoolItem *JabberContactPool::findPoolItem ( const XMPP::RosterItem &contact ) +{ + + // see if the contact already exists + for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ()) + { + if ( mContactItem->contact()->rosterItem().jid().full().lower() == contact.jid().full().lower() ) + { + return mContactItem; + } + } + + return 0; + +} + +JabberContact *JabberContactPool::addContact ( const XMPP::RosterItem &contact, Kopete::MetaContact *metaContact, bool dirty ) +{ + // see if the contact already exists + JabberContactPoolItem *mContactItem = findPoolItem ( contact ); + if ( mContactItem) + { + kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Updating existing contact " << contact.jid().full() << " - " << mContactItem->contact() << endl; + + // It exists, update it. + mContactItem->contact()->updateContact ( contact ); + mContactItem->setDirty ( dirty ); + + JabberContact *retval = dynamic_cast(mContactItem->contact ()); + + if ( !retval ) + { + KMessageBox::error ( Kopete::UI::Global::mainWidget (), + "Fatal error in the Jabber contact pool. Please restart Kopete and submit a debug log " + "of your session to http://bugs.kde.org.", + "Fatal Jabber Error" ); + } + + return retval; + } + + kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Adding new contact " << contact.jid().full() << endl; + + JabberTransport *transport=0l; + QString legacyId; + //find if the contact should be added to a transport. + if(mAccount->transports().contains(contact.jid().domain())) + { + transport=mAccount->transports()[contact.jid().domain()]; + legacyId=transport->legacyId( contact.jid() ); + } + + // create new contact instance and add it to the dictionary + JabberContact *newContact = new JabberContact ( contact, transport ? (Kopete::Account*)transport : (Kopete::Account*)mAccount, metaContact , legacyId ); + JabberContactPoolItem *newContactItem = new JabberContactPoolItem ( newContact ); + connect ( newContact, SIGNAL ( contactDestroyed ( Kopete::Contact * ) ), this, SLOT ( slotContactDestroyed ( Kopete::Contact * ) ) ); + newContactItem->setDirty ( dirty ); + mPool.append ( newContactItem ); + + return newContact; + +} + +JabberBaseContact *JabberContactPool::addGroupContact ( const XMPP::RosterItem &contact, bool roomContact, Kopete::MetaContact *metaContact, bool dirty ) +{ + + XMPP::RosterItem mContact ( roomContact ? contact.jid().userHost () : contact.jid().full() ); + + // see if the contact already exists + JabberContactPoolItem *mContactItem = findPoolItem ( mContact ); + if ( mContactItem) + { + if(mContactItem->contact()->inherits(roomContact ? + (const char*)("JabberGroupContact") : (const char*)("JabberGroupMemberContact") ) ) + { + + kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Updating existing contact " << mContact.jid().full() << endl; + + // It exists, update it. + mContactItem->contact()->updateContact ( mContact ); + mContactItem->setDirty ( dirty ); + + //we must tell to the originating function that no new contact has been added + return 0L;//mContactItem->contact (); + } + else + { + //this happen if we receive a MUC invitaiton: when the invitaiton is received, it's from the muc itself + //and then kopete will create a temporary contact for it. but it will not be a good contact. + kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Bad contact will be removed and re-added " << mContact.jid().full() << endl; + Kopete::MetaContact *old_mc=mContactItem->contact()->metaContact(); + delete mContactItem->contact(); + mContactItem = 0L; + if(old_mc->contacts().isEmpty() && old_mc!=metaContact) + { + Kopete::ContactList::self()->removeMetaContact( old_mc ); + } + + } + + } + + kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Adding new contact " << mContact.jid().full() << endl; + + // create new contact instance and add it to the dictionary + JabberBaseContact *newContact; + + if ( roomContact ) + newContact = new JabberGroupContact ( contact, mAccount, metaContact ); + else + newContact = new JabberGroupMemberContact ( contact, mAccount, metaContact ); + + JabberContactPoolItem *newContactItem = new JabberContactPoolItem ( newContact ); + + connect ( newContact, SIGNAL ( contactDestroyed ( Kopete::Contact * ) ), this, SLOT ( slotContactDestroyed ( Kopete::Contact * ) ) ); + + newContactItem->setDirty ( dirty ); + mPool.append ( newContactItem ); + + return newContact; + +} + +void JabberContactPool::removeContact ( const XMPP::Jid &jid ) +{ + kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Removing contact " << jid.full() << endl; + + for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ()) + { + if ( mContactItem->contact()->rosterItem().jid().full().lower() == jid.full().lower() ) + { + /* + * The following deletion will cause slotContactDestroyed() + * to be called, which will clean the up the list. + */ + if(mContactItem->contact()) + { + Kopete::MetaContact *mc=mContactItem->contact()->metaContact(); + delete mContactItem->contact (); + if(mc && mc->contacts().isEmpty()) + { + Kopete::ContactList::self()->removeMetaContact(mc) ; + } + } + return; + } + } + + kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "WARNING: No match found!" << endl; + +} + +void JabberContactPool::slotContactDestroyed ( Kopete::Contact *contact ) +{ + kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Contact deleted, collecting the pieces..." << endl; + + JabberBaseContact *jabberContact = static_cast( contact ); + //WARNING this ptr is not usable, we are in the Kopete::Contact destructor + + // remove contact from the pool + for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ()) + { + if ( mContactItem->contact() == jabberContact ) + { + mPool.remove (); + break; + } + } + + // delete all resources for it + if(contact->account()==(Kopete::Account*)(mAccount)) + mAccount->resourcePool()->removeAllResources ( XMPP::Jid ( contact->contactId() ) ); + else + { + //this is a legacy contact. we have no way to get the real Jid at this point, we can only guess it. + QString contactId= contact->contactId().replace('@','%') + "@" + contact->account()->myself()->contactId(); + mAccount->resourcePool()->removeAllResources ( XMPP::Jid ( contactId ) ) ; + } + +} + +void JabberContactPool::clear () +{ + kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Clearing the contact pool." << endl; + + for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ()) + { + /* + * The following deletion will cause slotContactDestroyed() + * to be called, which will clean the up the list. + * NOTE: this is a very inefficient way to clear the list + */ + delete mContactItem->contact (); + } + +} + +void JabberContactPool::setDirty ( const XMPP::Jid &jid, bool dirty ) +{ + kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Setting flag for " << jid.full() << " to " << dirty << endl; + + for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ()) + { + if ( mContactItem->contact()->rosterItem().jid().full().lower() == jid.full().lower() ) + { + mContactItem->setDirty ( dirty ); + return; + } + } + + kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "WARNING: No match found!" << endl; + +} + +void JabberContactPool::cleanUp () +{ + kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Cleaning dirty items from contact pool." << endl; + + for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ()) + { + if ( mContactItem->dirty () ) + { + kdDebug(JABBER_DEBUG_GLOBAL) << k_funcinfo << "Removing dirty contact " << mContactItem->contact()->contactId () << endl; + + /* + * The following deletion will cause slotContactDestroyed() + * to be called, which will clean the up the list. + */ + delete mContactItem->contact (); + } + } + +} + +JabberBaseContact *JabberContactPool::findExactMatch ( const XMPP::Jid &jid ) +{ + + for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ()) + { + if ( mContactItem->contact()->rosterItem().jid().full().lower () == jid.full().lower () ) + { + return mContactItem->contact (); + } + } + + return 0L; + +} + +JabberBaseContact *JabberContactPool::findRelevantRecipient ( const XMPP::Jid &jid ) +{ + + for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ()) + { + if ( mContactItem->contact()->rosterItem().jid().full().lower () == jid.userHost().lower () ) + { + return mContactItem->contact (); + } + } + + return 0L; + +} + +QPtrList JabberContactPool::findRelevantSources ( const XMPP::Jid &jid ) +{ + QPtrList list; + + for(JabberContactPoolItem *mContactItem = mPool.first (); mContactItem; mContactItem = mPool.next ()) + { + if ( mContactItem->contact()->rosterItem().jid().userHost().lower () == jid.userHost().lower () ) + { + list.append ( mContactItem->contact () ); + } + } + + return list; + +} + +JabberContactPoolItem::JabberContactPoolItem ( JabberBaseContact *contact ) +{ + mDirty = true; + mContact = contact; +} + +JabberContactPoolItem::~JabberContactPoolItem () +{ +} + +void JabberContactPoolItem::setDirty ( bool dirty ) +{ + mDirty = dirty; +} + +bool JabberContactPoolItem::dirty () +{ + return mDirty; +} + +JabberBaseContact *JabberContactPoolItem::contact () +{ + return mContact; +} + +#include "jabbercontactpool.moc" -- cgit v1.2.1