You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
677 lines
21 KiB
677 lines
21 KiB
15 years ago
|
/*
|
||
|
* jabbercontact.cpp - Base class for the Kopete Jabber protocol contact
|
||
|
*
|
||
|
* Copyright (c) 2002-2004 by Till Gerken <till@tantalo.net>
|
||
|
* Copyright (c) 2006 by Olivier Goffart <ogoffart at kde.org>
|
||
|
*
|
||
|
* Kopete (c) by the Kopete developers <kopete-devel@kde.org>
|
||
|
*
|
||
|
* *************************************************************************
|
||
|
* * *
|
||
|
* * 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 <kdebug.h>
|
||
|
#include <klocale.h>
|
||
|
#include <kiconloader.h>
|
||
|
#include <kstandarddirs.h>
|
||
|
#include <qtimer.h>
|
||
|
#include <qimage.h>
|
||
|
#include <qregexp.h>
|
||
|
#include <kmessagebox.h>
|
||
|
#include <kio/netaccess.h>
|
||
|
|
||
|
|
||
|
#include <kopetegroup.h>
|
||
|
#include <kopetecontactlist.h>
|
||
|
|
||
|
#include "jabberbasecontact.h"
|
||
|
|
||
|
#include "xmpp_tasks.h"
|
||
|
|
||
|
#include "jabberprotocol.h"
|
||
|
#include "jabberaccount.h"
|
||
|
#include "jabberresource.h"
|
||
|
#include "jabberresourcepool.h"
|
||
|
#include "kopetemetacontact.h"
|
||
|
#include "kopetemessage.h"
|
||
|
#include "kopeteuiglobal.h"
|
||
|
#include "jabbertransport.h"
|
||
|
#include "dlgjabbervcard.h"
|
||
|
|
||
|
|
||
|
/**
|
||
|
* JabberBaseContact constructor
|
||
|
*/
|
||
|
JabberBaseContact::JabberBaseContact (const XMPP::RosterItem &rosterItem, Kopete::Account *account, Kopete::MetaContact * mc, const QString &legacyId)
|
||
|
: Kopete::Contact (account, legacyId.isEmpty() ? rosterItem.jid().full() : legacyId , mc )
|
||
|
{
|
||
|
setDontSync ( false );
|
||
|
|
||
|
JabberTransport *t=transport();
|
||
|
m_account= t ? t->account() : static_cast<JabberAccount *>(Kopete::Contact::account());
|
||
|
|
||
|
|
||
|
// take roster item and update display name
|
||
|
updateContact ( rosterItem );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
JabberProtocol *JabberBaseContact::protocol ()
|
||
|
{
|
||
|
|
||
|
return static_cast<JabberProtocol *>(Kopete::Contact::protocol ());
|
||
|
}
|
||
|
|
||
|
|
||
|
JabberTransport * JabberBaseContact::transport( )
|
||
|
{
|
||
|
return dynamic_cast<JabberTransport*>(Kopete::Contact::account());
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Return if we are reachable (defaults to true because
|
||
|
we can send on- and offline, only return false if the
|
||
|
account itself is offline, too) */
|
||
|
bool JabberBaseContact::isReachable ()
|
||
|
{
|
||
|
if (account()->isConnected())
|
||
|
return true;
|
||
|
|
||
|
return false;
|
||
|
|
||
|
}
|
||
|
|
||
|
void JabberBaseContact::updateContact ( const XMPP::RosterItem & item )
|
||
|
{
|
||
|
kdDebug ( JABBER_DEBUG_GLOBAL ) << k_funcinfo << "Synchronizing local copy of " << contactId() << " with information received from server. (name='" << item.name() << "' groups='" << item.groups() << "')"<< endl;
|
||
|
|
||
|
mRosterItem = item;
|
||
|
|
||
|
// if we don't have a meta contact yet, stop processing here
|
||
|
if ( !metaContact () )
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
* We received the information from the server, as such,
|
||
|
* don't attempt to synch while we update our local copy.
|
||
|
*/
|
||
|
setDontSync ( true );
|
||
|
|
||
|
// The myself contact is not in the roster on server, ignore this code
|
||
|
// because the myself MetaContact displayname become the latest
|
||
|
// Jabber acccount jid.
|
||
|
if( metaContact() != Kopete::ContactList::self()->myself() )
|
||
|
{
|
||
|
// only update the alias if its not empty
|
||
|
if ( !item.name().isEmpty () && item.name() != item.jid().bare() )
|
||
|
{
|
||
|
QString newName = item.name ();
|
||
|
QString oldName = metaContact()->displayName();
|
||
|
Kopete::Contact *source=metaContact()->displayNameSourceContact();
|
||
|
// kdDebug ( JABBER_DEBUG_GLOBAL ) << k_funcinfo << "setting display name of " << contactId () << " to " << newName << endl;
|
||
|
metaContact()->setDisplayName ( newName );
|
||
|
//automatically set to custom source if the source is to this contact.
|
||
|
if( metaContact()->displayNameSource()==Kopete::MetaContact::SourceContact && newName != oldName && ( source == this || source == 0L ) )
|
||
|
metaContact()->setDisplayNameSource( Kopete::MetaContact::SourceCustom );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Set the contact's subscription status
|
||
|
*/
|
||
|
switch ( item.subscription().type () )
|
||
|
{
|
||
|
case XMPP::Subscription::None:
|
||
|
setProperty ( protocol()->propSubscriptionStatus,
|
||
|
i18n ( "You cannot see each others' status." ) );
|
||
|
break;
|
||
|
case XMPP::Subscription::To:
|
||
|
setProperty ( protocol()->propSubscriptionStatus,
|
||
|
i18n ( "You can see this contact's status but they cannot see your status." ) );
|
||
|
break;
|
||
|
case XMPP::Subscription::From:
|
||
|
setProperty ( protocol()->propSubscriptionStatus,
|
||
|
i18n ( "This contact can see your status but you cannot see their status." ) );
|
||
|
break;
|
||
|
case XMPP::Subscription::Both:
|
||
|
setProperty ( protocol()->propSubscriptionStatus,
|
||
|
i18n ( "You can see each others' status." ) );
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if( !metaContact()->isTemporary() )
|
||
|
{
|
||
|
/*
|
||
|
* In this method, as opposed to KC::syncGroups(),
|
||
|
* the group list from the server is authoritative.
|
||
|
* As such, we need to find a list of all groups
|
||
|
* that the meta contact resides in but does not
|
||
|
* reside in on the server anymore, as well as all
|
||
|
* groups that the meta contact does not reside in,
|
||
|
* but resides in on the server.
|
||
|
* Then, we'll have to synchronize the KMC using
|
||
|
* that information.
|
||
|
*/
|
||
|
Kopete::GroupList groupsToRemoveFrom, groupsToAddTo;
|
||
|
|
||
|
// find all groups our contact is in but that are not in the server side roster
|
||
|
for ( unsigned i = 0; i < metaContact()->groups().count (); i++ )
|
||
|
{
|
||
|
if ( item.groups().find ( metaContact()->groups().at(i)->displayName () ) == item.groups().end () )
|
||
|
groupsToRemoveFrom.append ( metaContact()->groups().at ( i ) );
|
||
|
}
|
||
|
|
||
|
// now find all groups that are in the server side roster but not in the local group
|
||
|
for ( unsigned i = 0; i < item.groups().count (); i++ )
|
||
|
{
|
||
|
bool found = false;
|
||
|
for ( unsigned j = 0; j < metaContact()->groups().count (); j++)
|
||
|
{
|
||
|
if ( metaContact()->groups().at(j)->displayName () == *item.groups().at(i) )
|
||
|
{
|
||
|
found = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( !found )
|
||
|
{
|
||
|
groupsToAddTo.append ( Kopete::ContactList::self()->findGroup ( *item.groups().at(i) ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Special case: if we don't add the contact to any group and the
|
||
|
* list of groups to remove from contains the top level group, we
|
||
|
* risk removing the contact from the visible contact list. In this
|
||
|
* case, we need to make sure at least the top level group stays.
|
||
|
*/
|
||
|
if ( ( groupsToAddTo.count () == 0 ) && ( groupsToRemoveFrom.contains ( Kopete::Group::topLevel () ) ) )
|
||
|
{
|
||
|
groupsToRemoveFrom.remove ( Kopete::Group::topLevel () );
|
||
|
}
|
||
|
|
||
|
for ( Kopete::Group *group = groupsToRemoveFrom.first (); group; group = groupsToRemoveFrom.next () )
|
||
|
{
|
||
|
kdDebug ( JABBER_DEBUG_GLOBAL ) << k_funcinfo << "Removing " << contactId() << " from group " << group->displayName () << endl;
|
||
|
metaContact()->removeFromGroup ( group );
|
||
|
}
|
||
|
|
||
|
for ( Kopete::Group *group = groupsToAddTo.first (); group; group = groupsToAddTo.next () )
|
||
|
{
|
||
|
kdDebug ( JABBER_DEBUG_GLOBAL ) << k_funcinfo << "Adding " << contactId() << " to group " << group->displayName () << endl;
|
||
|
metaContact()->addToGroup ( group );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Enable updates for the server again.
|
||
|
*/
|
||
|
setDontSync ( false );
|
||
|
|
||
|
//can't do it now because it's called from contructor at a point some virtual function are not available
|
||
|
QTimer::singleShot(0, this, SLOT(reevaluateStatus()));
|
||
|
|
||
|
}
|
||
|
|
||
|
void JabberBaseContact::updateResourceList ()
|
||
|
{
|
||
|
/*
|
||
|
* Set available resources.
|
||
|
* This is a bit more complicated: We need to generate
|
||
|
* all images dynamically from the KOS icons and store
|
||
|
* them into the mime factory, then plug them into
|
||
|
* the richtext.
|
||
|
*/
|
||
|
JabberResourcePool::ResourceList resourceList;
|
||
|
account()->resourcePool()->findResources ( rosterItem().jid() , resourceList );
|
||
|
|
||
|
if ( resourceList.isEmpty () )
|
||
|
{
|
||
|
removeProperty ( protocol()->propAvailableResources );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
QString resourceListStr = "<table cellspacing=\"0\">";
|
||
|
|
||
|
for ( JabberResourcePool::ResourceList::iterator it = resourceList.begin (); it != resourceList.end (); ++it )
|
||
|
{
|
||
|
// icon, resource name and priority
|
||
|
resourceListStr += QString ( "<tr><td><img src=\"kopete-onlinestatus-icon:%1\" /> <b>%2</b> (Priority: %3)</td></tr>" ).
|
||
|
arg ( protocol()->resourceToKOS((*it)->resource()).mimeSourceFor ( account () ),
|
||
|
(*it)->resource().name (), QString::number ( (*it)->resource().priority () ) );
|
||
|
|
||
|
// client name, version, OS
|
||
|
if ( !(*it)->clientName().isEmpty () )
|
||
|
{
|
||
|
resourceListStr += QString ( "<tr><td>%1: %2 (%3)</td></tr>" ).
|
||
|
arg ( i18n ( "Client" ), (*it)->clientName (), (*it)->clientSystem () );
|
||
|
}
|
||
|
|
||
|
// Supported features
|
||
|
#if 0 //disabled because it's just an ugly and long list of incomprehensible namespaces to the user
|
||
|
QStringList supportedFeatures = (*it)->features().list();
|
||
|
QStringList::ConstIterator featuresIt, featuresItEnd = supportedFeatures.constEnd();
|
||
|
if( !supportedFeatures.empty() )
|
||
|
resourceListStr += QString( "<tr><td>Supported Features:" );
|
||
|
for( featuresIt = supportedFeatures.constBegin(); featuresIt != featuresItEnd; ++featuresIt )
|
||
|
{
|
||
|
XMPP::Features tempFeature(*featuresIt);
|
||
|
resourceListStr += QString("\n<br>");
|
||
|
if ( tempFeature.id() > XMPP::Features::FID_None )
|
||
|
resourceListStr += tempFeature.name() + QString(" (");
|
||
|
resourceListStr += *featuresIt;
|
||
|
if ( tempFeature.id() > Features::FID_None )
|
||
|
resourceListStr += QString(")");
|
||
|
}
|
||
|
if( !supportedFeatures.empty() )
|
||
|
resourceListStr += QString( "</td></tr>" );
|
||
|
#endif
|
||
|
|
||
|
// resource timestamp
|
||
|
resourceListStr += QString ( "<tr><td>%1: %2</td></tr>" ).
|
||
|
arg ( i18n ( "Timestamp" ), KGlobal::locale()->formatDateTime ( (*it)->resource().status().timeStamp(), true, true ) );
|
||
|
|
||
|
// message, if any
|
||
|
if ( !(*it)->resource().status().status().stripWhiteSpace().isEmpty () )
|
||
|
{
|
||
|
resourceListStr += QString ( "<tr><td>%1: %2</td></tr>" ).
|
||
|
arg (
|
||
|
i18n ( "Message" ),
|
||
|
Kopete::Message::escape( (*it)->resource().status().status () )
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
resourceListStr += "</table>";
|
||
|
|
||
|
setProperty ( protocol()->propAvailableResources, resourceListStr );
|
||
|
}
|
||
|
|
||
|
void JabberBaseContact::reevaluateStatus ()
|
||
|
{
|
||
|
kdDebug (JABBER_DEBUG_GLOBAL) << k_funcinfo << "Determining new status for " << contactId () << endl;
|
||
|
|
||
|
Kopete::OnlineStatus status;
|
||
|
XMPP::Resource resource = account()->resourcePool()->bestResource ( mRosterItem.jid () );
|
||
|
|
||
|
status = protocol()->resourceToKOS ( resource );
|
||
|
|
||
|
|
||
|
/* Add some icon to show the subscription */
|
||
|
if( ( mRosterItem.subscription().type() == XMPP::Subscription::None || mRosterItem.subscription().type() == XMPP::Subscription::From)
|
||
|
&& inherits ( "JabberContact" ) && metaContact() != Kopete::ContactList::self()->myself() && account()->isConnected() )
|
||
|
{
|
||
|
status = Kopete::OnlineStatus(status.status() ,
|
||
|
status.weight() ,
|
||
|
protocol() ,
|
||
|
status.internalStatus() | 0x0100,
|
||
|
status.overlayIcons() + QStringList("status_unknown_overlay") , //FIXME: find better icon
|
||
|
status.description() );
|
||
|
}
|
||
|
|
||
|
|
||
|
updateResourceList ();
|
||
|
|
||
|
kdDebug (JABBER_DEBUG_GLOBAL) << k_funcinfo << "New status for " << contactId () << " is " << status.description () << endl;
|
||
|
setOnlineStatus ( status );
|
||
|
|
||
|
/*
|
||
|
* Set away message property.
|
||
|
* We just need to read it from the current resource.
|
||
|
*/
|
||
|
if ( !resource.status ().status ().isEmpty () )
|
||
|
{
|
||
|
setProperty ( protocol()->propAwayMessage, resource.status().status () );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
removeProperty ( protocol()->propAwayMessage );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
QString JabberBaseContact::fullAddress ()
|
||
|
{
|
||
|
|
||
|
XMPP::Jid jid = rosterItem().jid();
|
||
|
|
||
|
if ( jid.resource().isEmpty () )
|
||
|
{
|
||
|
jid.setResource ( account()->resourcePool()->bestResource ( jid ).name () );
|
||
|
}
|
||
|
|
||
|
return jid.full ();
|
||
|
|
||
|
}
|
||
|
|
||
|
XMPP::Jid JabberBaseContact::bestAddress ()
|
||
|
{
|
||
|
|
||
|
// see if we are subscribed with a preselected resource
|
||
|
if ( !mRosterItem.jid().resource().isEmpty () )
|
||
|
{
|
||
|
// we have a preselected resource, so return our default full address
|
||
|
return mRosterItem.jid ();
|
||
|
}
|
||
|
|
||
|
// construct address out of user@host and current best resource
|
||
|
XMPP::Jid jid = mRosterItem.jid ();
|
||
|
jid.setResource ( account()->resourcePool()->bestResource( mRosterItem.jid() ).name () );
|
||
|
|
||
|
return jid;
|
||
|
|
||
|
}
|
||
|
|
||
|
void JabberBaseContact::setDontSync ( bool flag )
|
||
|
{
|
||
|
|
||
|
mDontSync = flag;
|
||
|
|
||
|
}
|
||
|
|
||
|
bool JabberBaseContact::dontSync ()
|
||
|
{
|
||
|
|
||
|
return mDontSync;
|
||
|
|
||
|
}
|
||
|
|
||
|
void JabberBaseContact::serialize (QMap < QString, QString > &serializedData, QMap < QString, QString > & /* addressBookData */ )
|
||
|
{
|
||
|
|
||
|
// Contact id and display name are already set for us, only add the rest
|
||
|
serializedData["JID"] = mRosterItem.jid().full();
|
||
|
|
||
|
serializedData["groups"] = mRosterItem.groups ().join (QString::fromLatin1 (","));
|
||
|
}
|
||
|
|
||
|
void JabberBaseContact::slotUserInfo( )
|
||
|
{
|
||
|
if ( !account()->isConnected () )
|
||
|
{
|
||
|
account()->errorConnectFirst ();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Update the vCard
|
||
|
//slotGetTimedVCard();
|
||
|
|
||
|
new dlgJabberVCard ( account(), this, Kopete::UI::Global::mainWidget () );
|
||
|
}
|
||
|
|
||
|
void JabberBaseContact::setPropertiesFromVCard ( const XMPP::VCard &vCard )
|
||
|
{
|
||
|
kdDebug ( JABBER_DEBUG_GLOBAL ) << k_funcinfo << "Updating vCard for " << contactId () << endl;
|
||
|
|
||
|
// update vCard cache timestamp if this is not a temporary contact
|
||
|
if ( metaContact() && !metaContact()->isTemporary () )
|
||
|
{
|
||
|
setProperty ( protocol()->propVCardCacheTimeStamp, QDateTime::currentDateTime().toString ( Qt::ISODate ) );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Set the nickname property.
|
||
|
* but ignore it if we are in a groupchat, or it will clash with the normal nickname
|
||
|
*/
|
||
|
if(inherits ( "JabberContact" ))
|
||
|
{
|
||
|
if ( !vCard.nickName().isEmpty () )
|
||
|
{
|
||
|
setProperty ( protocol()->propNickName, vCard.nickName () );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
removeProperty ( protocol()->propNickName );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Kopete does not allow a modification of the "full name"
|
||
|
* property. However, some vCards specify only the full name,
|
||
|
* some specify only first and last name.
|
||
|
* Due to these inconsistencies, if first and last name don't
|
||
|
* exist, it is attempted to parse the full name.
|
||
|
*/
|
||
|
|
||
|
// remove all properties first
|
||
|
removeProperty ( protocol()->propFirstName );
|
||
|
removeProperty ( protocol()->propLastName );
|
||
|
removeProperty ( protocol()->propFullName );
|
||
|
|
||
|
if ( !vCard.fullName().isEmpty () && vCard.givenName().isEmpty () && vCard.familyName().isEmpty () )
|
||
|
{
|
||
|
QString lastName = vCard.fullName().section ( ' ', 0, -1 );
|
||
|
QString firstName = vCard.fullName().left(vCard.fullName().length () - lastName.length ()).stripWhiteSpace ();
|
||
|
|
||
|
setProperty ( protocol()->propFirstName, firstName );
|
||
|
setProperty ( protocol()->propLastName, lastName );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( !vCard.givenName().isEmpty () )
|
||
|
setProperty ( protocol()->propFirstName, vCard.givenName () );
|
||
|
|
||
|
if ( !vCard.familyName().isEmpty () )
|
||
|
setProperty ( protocol()->propLastName, vCard.familyName () );
|
||
|
}
|
||
|
if( !vCard.fullName().isEmpty() )
|
||
|
setProperty ( protocol()->propFullName, vCard.fullName() );
|
||
|
|
||
|
/*
|
||
|
* Set the general information
|
||
|
*/
|
||
|
removeProperty( protocol()->propJid );
|
||
|
removeProperty( protocol()->propBirthday );
|
||
|
removeProperty( protocol()->propTimezone );
|
||
|
removeProperty( protocol()->propHomepage );
|
||
|
|
||
|
setProperty( protocol()->propJid, vCard.jid() );
|
||
|
|
||
|
if( !vCard.bdayStr().isEmpty () )
|
||
|
setProperty( protocol()->propBirthday, vCard.bdayStr() );
|
||
|
if( !vCard.timezone().isEmpty () )
|
||
|
setProperty( protocol()->propTimezone, vCard.timezone() );
|
||
|
if( !vCard.url().isEmpty () )
|
||
|
setProperty( protocol()->propHomepage, vCard.url() );
|
||
|
|
||
|
/*
|
||
|
* Set the work information.
|
||
|
*/
|
||
|
removeProperty( protocol()->propCompanyName );
|
||
|
removeProperty( protocol()->propCompanyDepartement );
|
||
|
removeProperty( protocol()->propCompanyPosition );
|
||
|
removeProperty( protocol()->propCompanyRole );
|
||
|
|
||
|
if( !vCard.org().name.isEmpty() )
|
||
|
setProperty( protocol()->propCompanyName, vCard.org().name );
|
||
|
if( !vCard.org().unit.join(",").isEmpty() )
|
||
|
setProperty( protocol()->propCompanyDepartement, vCard.org().unit.join(",")) ;
|
||
|
if( !vCard.title().isEmpty() )
|
||
|
setProperty( protocol()->propCompanyPosition, vCard.title() );
|
||
|
if( !vCard.role().isEmpty() )
|
||
|
setProperty( protocol()->propCompanyRole, vCard.role() );
|
||
|
|
||
|
/*
|
||
|
* Set the about information
|
||
|
*/
|
||
|
removeProperty( protocol()->propAbout );
|
||
|
|
||
|
if( !vCard.desc().isEmpty() )
|
||
|
setProperty( protocol()->propAbout, vCard.desc() );
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Set the work and home addresses information
|
||
|
*/
|
||
|
removeProperty( protocol()->propWorkStreet );
|
||
|
removeProperty( protocol()->propWorkExtAddr );
|
||
|
removeProperty( protocol()->propWorkPOBox );
|
||
|
removeProperty( protocol()->propWorkCity );
|
||
|
removeProperty( protocol()->propWorkPostalCode );
|
||
|
removeProperty( protocol()->propWorkCountry );
|
||
|
|
||
|
removeProperty( protocol()->propHomeStreet );
|
||
|
removeProperty( protocol()->propHomeExtAddr );
|
||
|
removeProperty( protocol()->propHomePOBox );
|
||
|
removeProperty( protocol()->propHomeCity );
|
||
|
removeProperty( protocol()->propHomePostalCode );
|
||
|
removeProperty( protocol()->propHomeCountry );
|
||
|
|
||
|
for(XMPP::VCard::AddressList::const_iterator it = vCard.addressList().begin(); it != vCard.addressList().end(); it++)
|
||
|
{
|
||
|
XMPP::VCard::Address address = (*it);
|
||
|
|
||
|
if(address.work)
|
||
|
{
|
||
|
setProperty( protocol()->propWorkStreet, address.street );
|
||
|
setProperty( protocol()->propWorkExtAddr, address.extaddr );
|
||
|
setProperty( protocol()->propWorkPOBox, address.pobox );
|
||
|
setProperty( protocol()->propWorkCity, address.locality );
|
||
|
setProperty( protocol()->propWorkPostalCode, address.pcode );
|
||
|
setProperty( protocol()->propWorkCountry, address.country );
|
||
|
}
|
||
|
else
|
||
|
if(address.home)
|
||
|
{
|
||
|
setProperty( protocol()->propHomeStreet, address.street );
|
||
|
setProperty( protocol()->propHomeExtAddr, address.extaddr );
|
||
|
setProperty( protocol()->propHomePOBox, address.pobox );
|
||
|
setProperty( protocol()->propHomeCity, address.locality );
|
||
|
setProperty( protocol()->propHomePostalCode, address.pcode );
|
||
|
setProperty( protocol()->propHomeCountry, address.country );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Delete emails first, they might not be present
|
||
|
* in the vCard at all anymore.
|
||
|
*/
|
||
|
removeProperty ( protocol()->propEmailAddress );
|
||
|
removeProperty ( protocol()->propWorkEmailAddress );
|
||
|
|
||
|
/*
|
||
|
* Set the home and work email information.
|
||
|
*/
|
||
|
XMPP::VCard::EmailList::const_iterator emailEnd = vCard.emailList().end ();
|
||
|
for(XMPP::VCard::EmailList::const_iterator it = vCard.emailList().begin(); it != emailEnd; ++it)
|
||
|
{
|
||
|
XMPP::VCard::Email email = (*it);
|
||
|
|
||
|
if(email.work)
|
||
|
{
|
||
|
if( !email.userid.isEmpty() )
|
||
|
setProperty ( protocol()->propWorkEmailAddress, email.userid );
|
||
|
}
|
||
|
else
|
||
|
if(email.home)
|
||
|
{
|
||
|
if( !email.userid.isEmpty() )
|
||
|
setProperty ( protocol()->propEmailAddress, email.userid );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Delete phone number properties first as they might have
|
||
|
* been unset during an update and are not present in
|
||
|
* the vCard at all anymore.
|
||
|
*/
|
||
|
removeProperty ( protocol()->propPrivatePhone );
|
||
|
removeProperty ( protocol()->propPrivateMobilePhone );
|
||
|
removeProperty ( protocol()->propWorkPhone );
|
||
|
removeProperty ( protocol()->propWorkMobilePhone );
|
||
|
|
||
|
/*
|
||
|
* Set phone numbers. Note that if a mobile phone number
|
||
|
* is specified, it's assigned to the private mobile
|
||
|
* phone number property. This might not be the desired
|
||
|
* behavior for all users.
|
||
|
*/
|
||
|
XMPP::VCard::PhoneList::const_iterator phoneEnd = vCard.phoneList().end ();
|
||
|
for(XMPP::VCard::PhoneList::const_iterator it = vCard.phoneList().begin(); it != phoneEnd; ++it)
|
||
|
{
|
||
|
XMPP::VCard::Phone phone = (*it);
|
||
|
|
||
|
if(phone.work)
|
||
|
{
|
||
|
setProperty ( protocol()->propWorkPhone, phone.number );
|
||
|
}
|
||
|
else
|
||
|
if(phone.fax)
|
||
|
{
|
||
|
setProperty ( protocol()->propPhoneFax, phone.number);
|
||
|
}
|
||
|
else
|
||
|
if(phone.cell)
|
||
|
{
|
||
|
setProperty ( protocol()->propPrivateMobilePhone, phone.number );
|
||
|
}
|
||
|
else
|
||
|
if(phone.home)
|
||
|
{
|
||
|
setProperty ( protocol()->propPrivatePhone, phone.number );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Set photo/avatar property.
|
||
|
*/
|
||
|
removeProperty( protocol()->propPhoto );
|
||
|
|
||
|
QImage contactPhoto;
|
||
|
QString fullJid = mRosterItem.jid().full();
|
||
|
QString finalPhotoPath = locateLocal("appdata", "jabberphotos/" + fullJid.replace(QRegExp("[./~]"),"-") +".png");
|
||
|
|
||
|
// photo() is a QByteArray
|
||
|
if ( !vCard.photo().isEmpty() )
|
||
|
{
|
||
|
kdDebug( JABBER_DEBUG_GLOBAL ) << k_funcinfo << "Contact has a photo embedded into his vCard." << endl;
|
||
|
|
||
|
// QImage is used to save to disk in PNG later.
|
||
|
contactPhoto = QImage( vCard.photo() );
|
||
|
}
|
||
|
// Contact photo is a URI.
|
||
|
else if( !vCard.photoURI().isEmpty() )
|
||
|
{
|
||
|
QString tempPhotoPath = 0;
|
||
|
|
||
|
// Downalod photo from URI.
|
||
|
if( !KIO::NetAccess::download( vCard.photoURI(), tempPhotoPath, 0) )
|
||
|
{
|
||
|
KMessageBox::queuedMessageBox( Kopete::UI::Global::mainWidget (), KMessageBox::Sorry, i18n( "Downloading of Jabber contact photo failed!" ) );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
kdDebug( JABBER_DEBUG_GLOBAL ) << k_funcinfo << "Contact photo is a URI." << endl;
|
||
|
|
||
|
contactPhoto = QImage( tempPhotoPath );
|
||
|
|
||
|
KIO::NetAccess::removeTempFile( tempPhotoPath );
|
||
|
}
|
||
|
|
||
|
// Save the image to the disk, then set the property.
|
||
|
if( !contactPhoto.isNull() && contactPhoto.save(finalPhotoPath, "PNG") )
|
||
|
{
|
||
|
kdDebug( JABBER_DEBUG_GLOBAL ) << k_funcinfo << "Setting photo for contact: " << fullJid << endl;
|
||
|
setProperty( protocol()->propPhoto, finalPhotoPath );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#include "jabberbasecontact.moc"
|
||
|
|
||
|
// vim: set noet ts=4 sts=4 sw=4:
|