|
|
|
/*
|
|
|
|
This file is part of libkabc and/or kaddressbook.
|
|
|
|
Copyright (c) 2004 Klarälvdalens Datakonsult AB
|
|
|
|
<info@klaralvdalens-datakonsult.se>
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library 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
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
In addition, as a special exception, the copyright holders give
|
|
|
|
permission to link the code of this program with any edition of
|
|
|
|
the TQt library by Trolltech AS, Norway (or with modified versions
|
|
|
|
of TQt that use the same license as TQt), and distribute linked
|
|
|
|
combinations including the two. You must obey the GNU General
|
|
|
|
Public License in all respects for all of the code used other than
|
|
|
|
TQt. If you modify this file, you may extend this exception to
|
|
|
|
your version of the file, but you are not obligated to do so. If
|
|
|
|
you do not wish to do so, delete this exception statement from
|
|
|
|
your version.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "contact.h"
|
|
|
|
#include "resourcekolab.h"
|
|
|
|
|
|
|
|
#include <tdeabc/addressee.h>
|
|
|
|
#include <tdeabc/stdaddressbook.h>
|
|
|
|
#include <libkcal/freebusyurlstore.h>
|
|
|
|
#include <libtdepim/distributionlist.h>
|
|
|
|
#include <tdeio/netaccess.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <float.h>
|
|
|
|
|
|
|
|
using namespace Kolab;
|
|
|
|
|
|
|
|
static const char* s_pictureAttachmentName = "kolab-picture.png";
|
|
|
|
static const char* s_logoAttachmentName = "kolab-logo.png";
|
|
|
|
static const char* s_soundAttachmentName = "sound";
|
|
|
|
static const char* s_unhandledTagAppName = "KOLABUNHANDLED"; // no hyphens in appnames!
|
|
|
|
|
|
|
|
// saving (addressee->xml)
|
|
|
|
Contact::Contact( const TDEABC::Addressee* addr )
|
|
|
|
: mHasGeo( false )
|
|
|
|
{
|
|
|
|
setFields( addr );
|
|
|
|
}
|
|
|
|
|
|
|
|
// loading (xml->addressee)
|
|
|
|
Contact::Contact( const TQString& xml, TDEABC::ResourceKolab* resource, const TQString& subResource, TQ_UINT32 sernum )
|
|
|
|
: mHasGeo( false )
|
|
|
|
{
|
|
|
|
load( xml );
|
|
|
|
if ( !mPictureAttachmentName.isEmpty() )
|
|
|
|
mPicture = loadPictureFromKMail( mPictureAttachmentName, resource, subResource, sernum );
|
|
|
|
if ( !mLogoAttachmentName.isEmpty() )
|
|
|
|
mLogo = loadPictureFromKMail( mLogoAttachmentName, resource, subResource, sernum );
|
|
|
|
if ( !mSoundAttachmentName.isEmpty() )
|
|
|
|
mSound = loadDataFromKMail( mSound, resource, subResource, sernum );
|
|
|
|
}
|
|
|
|
|
|
|
|
Contact::~Contact()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setGivenName( const TQString& name )
|
|
|
|
{
|
|
|
|
mGivenName = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::givenName() const
|
|
|
|
{
|
|
|
|
return mGivenName;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setMiddleNames( const TQString& names )
|
|
|
|
{
|
|
|
|
mMiddleNames = names;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::middleNames() const
|
|
|
|
{
|
|
|
|
return mMiddleNames;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setLastName( const TQString& name )
|
|
|
|
{
|
|
|
|
mLastName = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::lastName() const
|
|
|
|
{
|
|
|
|
return mLastName;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setFullName( const TQString& name )
|
|
|
|
{
|
|
|
|
mFullName = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::fullName() const
|
|
|
|
{
|
|
|
|
return mFullName;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setInitials( const TQString& initials )
|
|
|
|
{
|
|
|
|
mInitials = initials;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::initials() const
|
|
|
|
{
|
|
|
|
return mInitials;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setPrefix( const TQString& prefix )
|
|
|
|
{
|
|
|
|
mPrefix = prefix;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::prefix() const
|
|
|
|
{
|
|
|
|
return mPrefix;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setSuffix( const TQString& suffix )
|
|
|
|
{
|
|
|
|
mSuffix = suffix;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::suffix() const
|
|
|
|
{
|
|
|
|
return mSuffix;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setRole( const TQString& role )
|
|
|
|
{
|
|
|
|
mRole = role;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::role() const
|
|
|
|
{
|
|
|
|
return mRole;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setFreeBusyUrl( const TQString& fbUrl )
|
|
|
|
{
|
|
|
|
mFreeBusyUrl = fbUrl;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::freeBusyUrl() const
|
|
|
|
{
|
|
|
|
return mFreeBusyUrl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setOrganization( const TQString& organization )
|
|
|
|
{
|
|
|
|
mOrganization = organization;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::organization() const
|
|
|
|
{
|
|
|
|
return mOrganization;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setWebPage( const TQString& url )
|
|
|
|
{
|
|
|
|
mWebPage = url;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::webPage() const
|
|
|
|
{
|
|
|
|
return mWebPage;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setIMAddress( const TQString& imAddress )
|
|
|
|
{
|
|
|
|
mIMAddress = imAddress;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::imAddress() const
|
|
|
|
{
|
|
|
|
return mIMAddress;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setDepartment( const TQString& department )
|
|
|
|
{
|
|
|
|
mDepartment = department;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::department() const
|
|
|
|
{
|
|
|
|
return mDepartment;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setOfficeLocation( const TQString& location )
|
|
|
|
{
|
|
|
|
mOfficeLocation = location;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::officeLocation() const
|
|
|
|
{
|
|
|
|
return mOfficeLocation;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setProfession( const TQString& profession )
|
|
|
|
{
|
|
|
|
mProfession = profession;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::profession() const
|
|
|
|
{
|
|
|
|
return mProfession;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setJobTitle( const TQString& title )
|
|
|
|
{
|
|
|
|
mJobTitle = title;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::jobTitle() const
|
|
|
|
{
|
|
|
|
return mJobTitle;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setManagerName( const TQString& name )
|
|
|
|
{
|
|
|
|
mManagerName = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::managerName() const
|
|
|
|
{
|
|
|
|
return mManagerName;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setAssistant( const TQString& name )
|
|
|
|
{
|
|
|
|
mAssistant = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::assistant() const
|
|
|
|
{
|
|
|
|
return mAssistant;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setNickName( const TQString& name )
|
|
|
|
{
|
|
|
|
mNickName = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::nickName() const
|
|
|
|
{
|
|
|
|
return mNickName;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setSpouseName( const TQString& name )
|
|
|
|
{
|
|
|
|
mSpouseName = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::spouseName() const
|
|
|
|
{
|
|
|
|
return mSpouseName;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setBirthday( const TQDate& date )
|
|
|
|
{
|
|
|
|
mBirthday = date;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDate Contact::birthday() const
|
|
|
|
{
|
|
|
|
return mBirthday;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setAnniversary( const TQDate& date )
|
|
|
|
{
|
|
|
|
mAnniversary = date;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDate Contact::anniversary() const
|
|
|
|
{
|
|
|
|
return mAnniversary;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setChildren( const TQString& children )
|
|
|
|
{
|
|
|
|
mChildren = children;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::children() const
|
|
|
|
{
|
|
|
|
return mChildren;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setGender( const TQString& gender )
|
|
|
|
{
|
|
|
|
mGender = gender;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::gender() const
|
|
|
|
{
|
|
|
|
return mGender;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setLanguage( const TQString& language )
|
|
|
|
{
|
|
|
|
mLanguage = language;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::language() const
|
|
|
|
{
|
|
|
|
return mLanguage;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::addPhoneNumber( const PhoneNumber& number )
|
|
|
|
{
|
|
|
|
mPhoneNumbers.append( number );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQValueList<Contact::PhoneNumber>& Contact::phoneNumbers()
|
|
|
|
{
|
|
|
|
return mPhoneNumbers;
|
|
|
|
}
|
|
|
|
|
|
|
|
const TQValueList<Contact::PhoneNumber>& Contact::phoneNumbers() const
|
|
|
|
{
|
|
|
|
return mPhoneNumbers;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::addEmail( const Email& email )
|
|
|
|
{
|
|
|
|
mEmails.append( email );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQValueList<Contact::Email>& Contact::emails()
|
|
|
|
{
|
|
|
|
return mEmails;
|
|
|
|
}
|
|
|
|
|
|
|
|
const TQValueList<Contact::Email>& Contact::emails() const
|
|
|
|
{
|
|
|
|
return mEmails;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::addAddress( const Contact::Address& address )
|
|
|
|
{
|
|
|
|
mAddresses.append( address );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQValueList<Contact::Address>& Contact::addresses()
|
|
|
|
{
|
|
|
|
return mAddresses;
|
|
|
|
}
|
|
|
|
|
|
|
|
const TQValueList<Contact::Address>& Contact::addresses() const
|
|
|
|
{
|
|
|
|
return mAddresses;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::setPreferredAddress( const TQString& address )
|
|
|
|
{
|
|
|
|
mPreferredAddress = address;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::preferredAddress() const
|
|
|
|
{
|
|
|
|
return mPreferredAddress;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Contact::loadNameAttribute( TQDomElement& element )
|
|
|
|
{
|
|
|
|
for ( TQDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
|
|
|
|
if ( n.isComment() )
|
|
|
|
continue;
|
|
|
|
if ( n.isElement() ) {
|
|
|
|
TQDomElement e = n.toElement();
|
|
|
|
TQString tagName = e.tagName();
|
|
|
|
|
|
|
|
if ( tagName == "given-name" )
|
|
|
|
setGivenName( e.text() );
|
|
|
|
else if ( tagName == "middle-names" )
|
|
|
|
setMiddleNames( e.text() );
|
|
|
|
else if ( tagName == "last-name" )
|
|
|
|
setLastName( e.text() );
|
|
|
|
else if ( tagName == "full-name" )
|
|
|
|
setFullName( e.text() );
|
|
|
|
else if ( tagName == "initials" )
|
|
|
|
setInitials( e.text() );
|
|
|
|
else if ( tagName == "prefix" )
|
|
|
|
setPrefix( e.text() );
|
|
|
|
else if ( tagName == "suffix" )
|
|
|
|
setSuffix( e.text() );
|
|
|
|
else
|
|
|
|
// TODO: Unhandled tag - save for later storage
|
|
|
|
kdDebug() << "Warning: Unhandled tag " << e.tagName() << endl;
|
|
|
|
} else
|
|
|
|
kdDebug() << "Node is not a comment or an element???" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::saveNameAttribute( TQDomElement& element ) const
|
|
|
|
{
|
|
|
|
TQDomElement e = element.ownerDocument().createElement( "name" );
|
|
|
|
element.appendChild( e );
|
|
|
|
|
|
|
|
writeString( e, "given-name", givenName() );
|
|
|
|
writeString( e, "middle-names", middleNames() );
|
|
|
|
writeString( e, "last-name", lastName() );
|
|
|
|
writeString( e, "full-name", fullName() );
|
|
|
|
writeString( e, "initials", initials() );
|
|
|
|
writeString( e, "prefix", prefix() );
|
|
|
|
writeString( e, "suffix", suffix() );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Contact::loadPhoneAttribute( TQDomElement& element )
|
|
|
|
{
|
|
|
|
PhoneNumber number;
|
|
|
|
for ( TQDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
|
|
|
|
if ( n.isComment() )
|
|
|
|
continue;
|
|
|
|
if ( n.isElement() ) {
|
|
|
|
TQDomElement e = n.toElement();
|
|
|
|
TQString tagName = e.tagName();
|
|
|
|
|
|
|
|
if ( tagName == "type" )
|
|
|
|
number.type = e.text();
|
|
|
|
else if ( tagName == "number" )
|
|
|
|
number.number = e.text();
|
|
|
|
else
|
|
|
|
// TODO: Unhandled tag - save for later storage
|
|
|
|
kdDebug() << "Warning: Unhandled tag " << e.tagName() << endl;
|
|
|
|
} else
|
|
|
|
kdDebug() << "Node is not a comment or an element???" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
addPhoneNumber( number );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::savePhoneAttributes( TQDomElement& element ) const
|
|
|
|
{
|
|
|
|
TQValueList<PhoneNumber>::ConstIterator it = mPhoneNumbers.begin();
|
|
|
|
for ( ; it != mPhoneNumbers.end(); ++it ) {
|
|
|
|
TQDomElement e = element.ownerDocument().createElement( "phone" );
|
|
|
|
element.appendChild( e );
|
|
|
|
const PhoneNumber& p = *it;
|
|
|
|
writeString( e, "type", p.type );
|
|
|
|
writeString( e, "number", p.number );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::saveEmailAttributes( TQDomElement& element ) const
|
|
|
|
{
|
|
|
|
TQValueList<Email>::ConstIterator it = mEmails.begin();
|
|
|
|
for ( ; it != mEmails.end(); ++it )
|
|
|
|
saveEmailAttribute( element, *it );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::loadCustomAttributes( TQDomElement& element )
|
|
|
|
{
|
|
|
|
Custom custom;
|
|
|
|
custom.app = element.attribute( "app" );
|
|
|
|
custom.name = element.attribute( "name" );
|
|
|
|
custom.value = element.attribute( "value" );
|
|
|
|
mCustomList.append( custom );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::saveCustomAttributes( TQDomElement& element ) const
|
|
|
|
{
|
|
|
|
TQValueList<Custom>::ConstIterator it = mCustomList.begin();
|
|
|
|
for ( ; it != mCustomList.end(); ++it ) {
|
|
|
|
Q_ASSERT( !(*it).name.isEmpty() );
|
|
|
|
if ( (*it).app == s_unhandledTagAppName ) {
|
|
|
|
writeString( element, (*it).name, (*it).value );
|
|
|
|
} else {
|
|
|
|
// skip writing the freebusyurl as it is a hack we need to remove eventually
|
|
|
|
if ( (*it).name == TQString::fromLatin1( "FreeBusyURL" ) ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Let's use attributes so that other tag-preserving-code doesn't need sub-elements
|
|
|
|
TQDomElement e = element.ownerDocument().createElement( "x-custom" );
|
|
|
|
element.appendChild( e );
|
|
|
|
e.setAttribute( "app", (*it).app );
|
|
|
|
e.setAttribute( "name", (*it).name );
|
|
|
|
e.setAttribute( "value", (*it).value );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Contact::loadAddressAttribute( TQDomElement& element )
|
|
|
|
{
|
|
|
|
Address address;
|
|
|
|
|
|
|
|
for ( TQDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
|
|
|
|
if ( n.isComment() )
|
|
|
|
continue;
|
|
|
|
if ( n.isElement() ) {
|
|
|
|
TQDomElement e = n.toElement();
|
|
|
|
TQString tagName = e.tagName();
|
|
|
|
|
|
|
|
if ( tagName == "type" )
|
|
|
|
address.type = e.text();
|
|
|
|
else if ( tagName == "x-kde-type" )
|
|
|
|
address.kdeAddressType = e.text().toInt();
|
|
|
|
else if ( tagName == "street" )
|
|
|
|
address.street = e.text();
|
|
|
|
else if ( tagName == "pobox" )
|
|
|
|
address.pobox = e.text();
|
|
|
|
else if ( tagName == "locality" )
|
|
|
|
address.locality = e.text();
|
|
|
|
else if ( tagName == "region" )
|
|
|
|
address.region = e.text();
|
|
|
|
else if ( tagName == "postal-code" )
|
|
|
|
address.postalCode = e.text();
|
|
|
|
else if ( tagName == "country" )
|
|
|
|
address.country = e.text();
|
|
|
|
else
|
|
|
|
// TODO: Unhandled tag - save for later storage
|
|
|
|
kdDebug() << "Warning: Unhandled tag " << e.tagName() << endl;
|
|
|
|
} else
|
|
|
|
kdDebug() << "Node is not a comment or an element???" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
addAddress( address );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::saveAddressAttributes( TQDomElement& element ) const
|
|
|
|
{
|
|
|
|
TQValueList<Address>::ConstIterator it = mAddresses.begin();
|
|
|
|
for ( ; it != mAddresses.end(); ++it ) {
|
|
|
|
TQDomElement e = element.ownerDocument().createElement( "address" );
|
|
|
|
element.appendChild( e );
|
|
|
|
const Address& a = *it;
|
|
|
|
writeString( e, "type", a.type );
|
|
|
|
writeString( e, "x-kde-type", TQString::number( a.kdeAddressType ) );
|
|
|
|
if ( !a.street.isEmpty() )
|
|
|
|
writeString( e, "street", a.street );
|
|
|
|
if ( !a.pobox.isEmpty() )
|
|
|
|
writeString( e, "pobox", a.pobox );
|
|
|
|
if ( !a.locality.isEmpty() )
|
|
|
|
writeString( e, "locality", a.locality );
|
|
|
|
if ( !a.region.isEmpty() )
|
|
|
|
writeString( e, "region", a.region );
|
|
|
|
if ( !a.postalCode.isEmpty() )
|
|
|
|
writeString( e, "postal-code", a.postalCode );
|
|
|
|
if ( !a.country.isEmpty() )
|
|
|
|
writeString( e, "country", a.country );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Kolab::Contact::loadDistrListMember( const TQDomElement& element )
|
|
|
|
{
|
|
|
|
Member member;
|
|
|
|
for ( TQDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
|
|
|
|
if ( n.isComment() )
|
|
|
|
continue;
|
|
|
|
if ( n.isElement() ) {
|
|
|
|
TQDomElement e = n.toElement();
|
|
|
|
TQString tagName = e.tagName();
|
|
|
|
if ( tagName == "display-name" )
|
|
|
|
member.displayName = e.text();
|
|
|
|
else if ( tagName == "smtp-address" )
|
|
|
|
member.email = e.text();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mDistrListMembers.append( member );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Contact::saveDistrListMembers( TQDomElement& element ) const
|
|
|
|
{
|
|
|
|
TQValueList<Member>::ConstIterator it = mDistrListMembers.begin();
|
|
|
|
for( ; it != mDistrListMembers.end(); ++it ) {
|
|
|
|
TQDomElement e = element.ownerDocument().createElement( "member" );
|
|
|
|
element.appendChild( e );
|
|
|
|
const Member& m = *it;
|
|
|
|
writeString( e, "display-name", m.displayName );
|
|
|
|
writeString( e, "smtp-address", m.email );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Contact::loadAttribute( TQDomElement& element )
|
|
|
|
{
|
|
|
|
const TQString tagName = element.tagName();
|
|
|
|
switch ( tagName[0].latin1() ) {
|
|
|
|
case 'a':
|
|
|
|
if ( tagName == "address" )
|
|
|
|
return loadAddressAttribute( element );
|
|
|
|
if ( tagName == "assistant" ) {
|
|
|
|
setAssistant( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if ( tagName == "anniversary" ) {
|
|
|
|
if ( !element.text().isEmpty() )
|
|
|
|
setAnniversary( stringToDate( element.text() ) );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
if ( tagName == "birthday" ) {
|
|
|
|
if ( !element.text().isEmpty() )
|
|
|
|
setBirthday( stringToDate( element.text() ) );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
if ( tagName == "children" ) {
|
|
|
|
setChildren( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
if ( tagName == "department" ) {
|
|
|
|
setDepartment( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if ( mIsDistributionList && tagName == "display-name" ) {
|
|
|
|
setFullName( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
if ( tagName == "email" ) {
|
|
|
|
Email email;
|
|
|
|
if ( loadEmailAttribute( element, email ) ) {
|
|
|
|
addEmail( email );
|
|
|
|
return true;
|
|
|
|
} else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
if ( tagName == "free-busy-url" ) {
|
|
|
|
setFreeBusyUrl( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'g':
|
|
|
|
if ( tagName == "gender" ) {
|
|
|
|
setGender( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
if ( tagName == "im-address" ) {
|
|
|
|
setIMAddress( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'j':
|
|
|
|
if ( tagName == "job-title" ) {
|
|
|
|
// see saveAttributes: <job-title> is mapped to the Role field
|
|
|
|
setJobTitle( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
if ( tagName == "language" ) {
|
|
|
|
setLanguage( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if ( tagName == "latitude" ) {
|
|
|
|
setLatitude( element.text().toFloat() );
|
|
|
|
mHasGeo = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if ( tagName == "longitude" ) {
|
|
|
|
setLongitude( element.text().toFloat() );
|
|
|
|
mHasGeo = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
if ( tagName == "manager-name" ) {
|
|
|
|
setManagerName( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if ( mIsDistributionList && tagName == "member" ) {
|
|
|
|
loadDistrListMember( element );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
if ( tagName == "name" )
|
|
|
|
return loadNameAttribute( element );
|
|
|
|
if ( tagName == "nick-name" ) {
|
|
|
|
setNickName( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
if ( tagName == "organization" ) {
|
|
|
|
setOrganization( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if ( tagName == "office-location" ) {
|
|
|
|
setOfficeLocation( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
if ( tagName == "profession" ) {
|
|
|
|
setProfession( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if ( tagName == "picture" ) {
|
|
|
|
mPictureAttachmentName = element.text();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if ( tagName == "phone" ) {
|
|
|
|
return loadPhoneAttribute( element );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if ( tagName == "preferred-address" ) {
|
|
|
|
setPreferredAddress( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
if ( tagName == "role" ) {
|
|
|
|
setRole( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
if ( tagName == "spouse-name" ) {
|
|
|
|
setSpouseName( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
if ( tagName == "x-logo" ) {
|
|
|
|
mLogoAttachmentName = element.text();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if ( tagName == "x-sound" ) {
|
|
|
|
mSoundAttachmentName = element.text();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if ( tagName == "x-custom" ) {
|
|
|
|
loadCustomAttributes( element );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
if ( tagName == "web-page" ) {
|
|
|
|
setWebPage( element.text() );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return KolabBase::loadAttribute( element );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Contact::saveAttributes( TQDomElement& element ) const
|
|
|
|
{
|
|
|
|
// Save the base class elements
|
|
|
|
KolabBase::saveAttributes( element );
|
|
|
|
if ( mIsDistributionList ) {
|
|
|
|
writeString( element, "display-name", fullName() );
|
|
|
|
saveDistrListMembers( element );
|
|
|
|
} else {
|
|
|
|
saveNameAttribute( element );
|
|
|
|
writeString( element, "free-busy-url", freeBusyUrl() );
|
|
|
|
writeString( element, "organization", organization() );
|
|
|
|
writeString( element, "web-page", webPage() );
|
|
|
|
writeString( element, "im-address", imAddress() );
|
|
|
|
writeString( element, "department", department() );
|
|
|
|
writeString( element, "office-location", officeLocation() );
|
|
|
|
writeString( element, "profession", profession() );
|
|
|
|
writeString( element, "role", role() );
|
|
|
|
writeString( element, "job-title", jobTitle() );
|
|
|
|
writeString( element, "manager-name", managerName() );
|
|
|
|
writeString( element, "assistant", assistant() );
|
|
|
|
writeString( element, "nick-name", nickName() );
|
|
|
|
writeString( element, "spouse-name", spouseName() );
|
|
|
|
writeString( element, "birthday", dateToString( birthday() ) );
|
|
|
|
writeString( element, "anniversary", dateToString( anniversary() ) );
|
|
|
|
if ( !picture().isNull() )
|
|
|
|
writeString( element, "picture", mPictureAttachmentName );
|
|
|
|
if ( !logo().isNull() )
|
|
|
|
writeString( element, "x-logo", mLogoAttachmentName );
|
|
|
|
if ( !sound().isNull() )
|
|
|
|
writeString( element, "x-sound", mSoundAttachmentName );
|
|
|
|
writeString( element, "children", children() );
|
|
|
|
writeString( element, "gender", gender() );
|
|
|
|
writeString( element, "language", language() );
|
|
|
|
savePhoneAttributes( element );
|
|
|
|
saveEmailAttributes( element );
|
|
|
|
saveAddressAttributes( element );
|
|
|
|
writeString( element, "preferred-address", preferredAddress() );
|
|
|
|
if ( mHasGeo ) {
|
|
|
|
writeString( element, "latitude", TQString::number( latitude(), 'g', DBL_DIG ) );
|
|
|
|
writeString( element, "longitude", TQString::number( longitude(), 'g', DBL_DIG ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
saveCustomAttributes( element );
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Contact::loadXML( const TQDomDocument& document )
|
|
|
|
{
|
|
|
|
TQDomElement top = document.documentElement();
|
|
|
|
|
|
|
|
mIsDistributionList = top.tagName() == "distribution-list";
|
|
|
|
if ( top.tagName() != "contact" && !mIsDistributionList ) {
|
|
|
|
tqWarning( "XML error: Top tag was %s instead of the expected contact or distribution-list",
|
|
|
|
top.tagName().ascii() );
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for ( TQDomNode n = top.firstChild(); !n.isNull(); n = n.nextSibling() ) {
|
|
|
|
if ( n.isComment() )
|
|
|
|
continue;
|
|
|
|
if ( n.isElement() ) {
|
|
|
|
TQDomElement e = n.toElement();
|
|
|
|
if ( !loadAttribute( e ) ) {
|
|
|
|
// Unhandled tag - save for later storage
|
|
|
|
//kdDebug() << "Saving unhandled tag " << e.tagName() << endl;
|
|
|
|
Custom c;
|
|
|
|
c.app = s_unhandledTagAppName;
|
|
|
|
c.name = e.tagName();
|
|
|
|
c.value = e.text();
|
|
|
|
mCustomList.append( c );
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
kdDebug() << "Node is not a comment or an element???" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Contact::saveXML() const
|
|
|
|
{
|
|
|
|
TQDomDocument document = domTree();
|
|
|
|
TQDomElement element = document.createElement(
|
|
|
|
mIsDistributionList ? "distribution-list" : "contact" );
|
|
|
|
element.setAttribute( "version", "1.0" );
|
|
|
|
saveAttributes( element );
|
|
|
|
document.appendChild( element );
|
|
|
|
return document.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
static TQString addressTypeToString( int /*TDEABC::Address::Type*/ type )
|
|
|
|
{
|
|
|
|
if ( type & TDEABC::Address::Home )
|
|
|
|
return "home";
|
|
|
|
if ( type & TDEABC::Address::Work )
|
|
|
|
return "business";
|
|
|
|
return "other";
|
|
|
|
}
|
|
|
|
|
|
|
|
static int addressTypeFromString( const TQString& type )
|
|
|
|
{
|
|
|
|
if ( type == "home" )
|
|
|
|
return TDEABC::Address::Home;
|
|
|
|
if ( type == "business" )
|
|
|
|
return TDEABC::Address::Work;
|
|
|
|
// well, this shows "other" in the editor, which is what we want...
|
|
|
|
return TDEABC::Address::Dom | TDEABC::Address::Intl | TDEABC::Address::Postal | TDEABC::Address::Parcel;
|
|
|
|
}
|
|
|
|
|
|
|
|
static TQStringList phoneTypeToString( int /*TDEABC::PhoneNumber::Types*/ type )
|
|
|
|
{
|
|
|
|
// KABC has a bitfield, i.e. the same phone number can be used for work and home
|
|
|
|
// and fax and cellphone etc. etc.
|
|
|
|
// So when saving we need to create as many tags as bits that were set.
|
|
|
|
TQStringList types;
|
|
|
|
if ( type & TDEABC::PhoneNumber::Fax ) {
|
|
|
|
if ( type & TDEABC::PhoneNumber::Home )
|
|
|
|
types << "homefax";
|
|
|
|
else // assume work -- if ( type & TDEABC::PhoneNumber::Work )
|
|
|
|
types << "businessfax";
|
|
|
|
type = type & ~TDEABC::PhoneNumber::Home;
|
|
|
|
type = type & ~TDEABC::PhoneNumber::Work;
|
|
|
|
}
|
|
|
|
|
|
|
|
// To support both "home1" and "home2", map Home+Pref to home2
|
|
|
|
if ( ( type & TDEABC::PhoneNumber::Home ) && ( type & TDEABC::PhoneNumber::Pref ) )
|
|
|
|
{
|
|
|
|
types << "home2";
|
|
|
|
type = type & ~TDEABC::PhoneNumber::Home;
|
|
|
|
type = type & ~TDEABC::PhoneNumber::Pref;
|
|
|
|
}
|
|
|
|
// To support both "business1" and "business2", map Work+Pref to business2
|
|
|
|
if ( ( type & TDEABC::PhoneNumber::Work ) && ( type & TDEABC::PhoneNumber::Pref ) )
|
|
|
|
{
|
|
|
|
types << "business2";
|
|
|
|
type = type & ~TDEABC::PhoneNumber::Work;
|
|
|
|
type = type & ~TDEABC::PhoneNumber::Pref;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( type & TDEABC::PhoneNumber::Home )
|
|
|
|
types << "home1";
|
|
|
|
if ( type & TDEABC::PhoneNumber::Msg ) // Msg==messaging
|
|
|
|
types << "company";
|
|
|
|
if ( type & TDEABC::PhoneNumber::Work )
|
|
|
|
types << "business1";
|
|
|
|
if ( type & TDEABC::PhoneNumber::Pref )
|
|
|
|
types << "primary";
|
|
|
|
if ( type & TDEABC::PhoneNumber::Voice )
|
|
|
|
types << "callback"; // ##
|
|
|
|
if ( type & TDEABC::PhoneNumber::Cell )
|
|
|
|
types << "mobile";
|
|
|
|
if ( type & TDEABC::PhoneNumber::Video )
|
|
|
|
types << "radio"; // ##
|
|
|
|
if ( type & TDEABC::PhoneNumber::Bbs )
|
|
|
|
types << "ttytdd";
|
|
|
|
if ( type & TDEABC::PhoneNumber::Modem )
|
|
|
|
types << "telex"; // #
|
|
|
|
if ( type & TDEABC::PhoneNumber::Car )
|
|
|
|
types << "car";
|
|
|
|
if ( type & TDEABC::PhoneNumber::Isdn )
|
|
|
|
types << "isdn";
|
|
|
|
if ( type & TDEABC::PhoneNumber::Pcs )
|
|
|
|
types << "assistant"; // ## Assistant is e.g. secretary
|
|
|
|
if ( type & TDEABC::PhoneNumber::Pager )
|
|
|
|
types << "pager";
|
|
|
|
return types;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int /*TDEABC::PhoneNumber::Types*/ phoneTypeFromString( const TQString& type )
|
|
|
|
{
|
|
|
|
if ( type == "homefax" )
|
|
|
|
return TDEABC::PhoneNumber::Home | TDEABC::PhoneNumber::Fax;
|
|
|
|
if ( type == "businessfax" )
|
|
|
|
return TDEABC::PhoneNumber::Work | TDEABC::PhoneNumber::Fax;
|
|
|
|
if ( type == "business2" )
|
|
|
|
return TDEABC::PhoneNumber::Work | TDEABC::PhoneNumber::Pref;
|
|
|
|
if ( type == "business1" )
|
|
|
|
return TDEABC::PhoneNumber::Work;
|
|
|
|
if ( type == "home2" )
|
|
|
|
return TDEABC::PhoneNumber::Home | TDEABC::PhoneNumber::Pref;
|
|
|
|
if ( type == "home1" )
|
|
|
|
return TDEABC::PhoneNumber::Home;
|
|
|
|
if ( type == "company" )
|
|
|
|
return TDEABC::PhoneNumber::Msg;
|
|
|
|
if ( type == "primary" )
|
|
|
|
return TDEABC::PhoneNumber::Pref;
|
|
|
|
if ( type == "callback" )
|
|
|
|
return TDEABC::PhoneNumber::Voice;
|
|
|
|
if ( type == "mobile" )
|
|
|
|
return TDEABC::PhoneNumber::Cell;
|
|
|
|
if ( type == "radio" )
|
|
|
|
return TDEABC::PhoneNumber::Video;
|
|
|
|
if ( type == "ttytdd" )
|
|
|
|
return TDEABC::PhoneNumber::Bbs;
|
|
|
|
if ( type == "telex" )
|
|
|
|
return TDEABC::PhoneNumber::Modem;
|
|
|
|
if ( type == "car" )
|
|
|
|
return TDEABC::PhoneNumber::Car;
|
|
|
|
if ( type == "isdn" )
|
|
|
|
return TDEABC::PhoneNumber::Isdn;
|
|
|
|
if ( type == "assistant" )
|
|
|
|
return TDEABC::PhoneNumber::Pcs;
|
|
|
|
if ( type == "pager" )
|
|
|
|
return TDEABC::PhoneNumber::Pager;
|
|
|
|
return TDEABC::PhoneNumber::Home; // whatever
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char* s_knownCustomFields[] = {
|
|
|
|
"X-IMAddress",
|
|
|
|
"X-Department",
|
|
|
|
"X-Office",
|
|
|
|
"X-Profession",
|
|
|
|
"X-ManagersName",
|
|
|
|
"X-AssistantsName",
|
|
|
|
"X-SpousesName",
|
|
|
|
"X-Anniversary",
|
|
|
|
"DistributionList",
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
// The saving is addressee -> Contact -> xml, this is the first part
|
|
|
|
void Contact::setFields( const TDEABC::Addressee* addressee )
|
|
|
|
{
|
|
|
|
KolabBase::setFields( addressee );
|
|
|
|
|
|
|
|
mIsDistributionList = KPIM::DistributionList::isDistributionList( *addressee );
|
|
|
|
if ( mIsDistributionList ) {
|
|
|
|
// Hopefully all resources are available during saving, so we can look up
|
|
|
|
// in the addressbook to get name+email from the UID.
|
|
|
|
KPIM::DistributionList distrList( *addressee );
|
|
|
|
const KPIM::DistributionList::Entry::List entries = distrList.entries( TDEABC::StdAddressBook::self() );
|
|
|
|
KPIM::DistributionList::Entry::List::ConstIterator it = entries.begin();
|
|
|
|
for ( ; it != entries.end() ; ++it ) {
|
|
|
|
Member m;
|
|
|
|
m.displayName = (*it).addressee.formattedName();
|
|
|
|
m.email = (*it).email;
|
|
|
|
if ( m.email.isEmpty() )
|
|
|
|
m.email = (*it).addressee.preferredEmail();
|
|
|
|
mDistrListMembers.append( m );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setGivenName( addressee->givenName() );
|
|
|
|
setMiddleNames( addressee->additionalName() );
|
|
|
|
setLastName( addressee->familyName() );
|
|
|
|
setFullName( addressee->formattedName() );
|
|
|
|
setPrefix( addressee->prefix() );
|
|
|
|
setSuffix( addressee->suffix() );
|
|
|
|
setOrganization( addressee->organization() );
|
|
|
|
setWebPage( addressee->url().url() );
|
|
|
|
setIMAddress( addressee->custom( "KADDRESSBOOK", "X-IMAddress" ) );
|
|
|
|
#if KDE_IS_VERSION(3,5,8)
|
|
|
|
setDepartment( addressee->department());
|
|
|
|
#else
|
|
|
|
setDepartment( addressee->custom( "KADDRESSBOOK", "X-Department" ) );
|
|
|
|
#endif
|
|
|
|
setOfficeLocation( addressee->custom( "KADDRESSBOOK", "X-Office" ) );
|
|
|
|
setProfession( addressee->custom( "KADDRESSBOOK", "X-Profession" ) );
|
|
|
|
setRole( addressee->role() );
|
|
|
|
setJobTitle( addressee->title() );
|
|
|
|
setManagerName( addressee->custom( "KADDRESSBOOK", "X-ManagersName" ) );
|
|
|
|
setAssistant( addressee->custom( "KADDRESSBOOK", "X-AssistantsName" ) );
|
|
|
|
setNickName( addressee->nickName() );
|
|
|
|
setSpouseName( addressee->custom( "KADDRESSBOOK", "X-SpousesName" ) );
|
|
|
|
if ( !addressee->birthday().isNull() )
|
|
|
|
setBirthday( addressee->birthday().date() );
|
|
|
|
const TQString& anniversary = addressee->custom( "KADDRESSBOOK", "X-Anniversary" );
|
|
|
|
if ( !anniversary.isEmpty() )
|
|
|
|
setAnniversary( stringToDate( anniversary ) );
|
|
|
|
|
|
|
|
const TQStringList emails = addressee->emails();
|
|
|
|
// Conversion problem here:
|
|
|
|
// TDEABC::Addressee has only one full name and N addresses, but the XML format
|
|
|
|
// has N times (fullname+address). So we just copy the fullname over and ignore it on loading.
|
|
|
|
for ( TQStringList::ConstIterator it = emails.begin(); it != emails.end(); ++it ) {
|
|
|
|
Email email;
|
|
|
|
email.displayName = fullName();
|
|
|
|
email.smtpAddress = *it;
|
|
|
|
addEmail( email );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now the real-world addresses
|
|
|
|
TQString preferredAddress = "home";
|
|
|
|
const TDEABC::Address::List addresses = addressee->addresses();
|
|
|
|
for ( TDEABC::Address::List::ConstIterator it = addresses.begin() ; it != addresses.end(); ++it ) {
|
|
|
|
Address address;
|
|
|
|
address.kdeAddressType = (*it).type();
|
|
|
|
address.type = addressTypeToString( address.kdeAddressType );
|
|
|
|
address.street = (*it).street();
|
|
|
|
address.pobox = (*it).postOfficeBox();
|
|
|
|
address.locality = (*it).locality();
|
|
|
|
address.region = (*it).region();
|
|
|
|
address.postalCode = (*it).postalCode();
|
|
|
|
address.country = (*it).country();
|
|
|
|
// ## TODO not in the XML format: extended address info.
|
|
|
|
// ## KDE-specific tags? Or hiding those fields? Or adding a warning?
|
|
|
|
addAddress( address );
|
|
|
|
if ( address.kdeAddressType & TDEABC::Address::Pref ) {
|
|
|
|
preferredAddress = address.type; // home, business or other
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setPreferredAddress( preferredAddress );
|
|
|
|
|
|
|
|
const TDEABC::PhoneNumber::List phones = addressee->phoneNumbers();
|
|
|
|
for ( TDEABC::PhoneNumber::List::ConstIterator it = phones.begin(); it != phones.end(); ++it ) {
|
|
|
|
// Create a tag per phone type set in the bitfield
|
|
|
|
TQStringList types = phoneTypeToString( (*it).type() );
|
|
|
|
for( TQStringList::Iterator typit = types.begin(); typit != types.end(); ++typit ) {
|
|
|
|
PhoneNumber phoneNumber;
|
|
|
|
phoneNumber.type = *typit;
|
|
|
|
phoneNumber.number = (*it).number();
|
|
|
|
addPhoneNumber( phoneNumber );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setPicture( loadPictureFromAddressee( addressee->photo() ) );
|
|
|
|
mPictureAttachmentName = addressee->custom( "KOLAB", "PictureAttachmentName" );
|
|
|
|
if ( mPictureAttachmentName.isEmpty() )
|
|
|
|
mPictureAttachmentName = s_pictureAttachmentName;
|
|
|
|
|
|
|
|
setLogo( loadPictureFromAddressee( addressee->logo() ) );
|
|
|
|
mLogoAttachmentName = addressee->custom( "KOLAB", "LogoAttachmentName" );
|
|
|
|
if ( mLogoAttachmentName.isEmpty() )
|
|
|
|
mLogoAttachmentName = s_logoAttachmentName;
|
|
|
|
|
|
|
|
setSound( loadSoundFromAddressee( addressee->sound() ) );
|
|
|
|
mSoundAttachmentName = addressee->custom( "KOLAB", "SoundAttachmentName" );
|
|
|
|
if ( mSoundAttachmentName.isEmpty() )
|
|
|
|
mSoundAttachmentName = s_soundAttachmentName;
|
|
|
|
|
|
|
|
if ( addressee->geo().isValid() ) {
|
|
|
|
setLatitude( addressee->geo().latitude() );
|
|
|
|
setLongitude( addressee->geo().longitude() );
|
|
|
|
mHasGeo = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Other KADDRESSBOOK custom fields than those already handled
|
|
|
|
// (includes e.g. crypto settings, and extra im addresses)
|
|
|
|
TQStringList knownCustoms;
|
|
|
|
for ( const char** p = s_knownCustomFields; *p; ++p )
|
|
|
|
knownCustoms << TQString::fromLatin1( *p );
|
|
|
|
TQStringList customs = addressee->customs();
|
|
|
|
for( TQStringList::Iterator it = customs.begin(); it != customs.end(); ++it ) {
|
|
|
|
// TDEABC::Addressee doesn't offer a real way to iterate over customs, other than splitting strings ourselves
|
|
|
|
// The format is "app-name:value".
|
|
|
|
int pos = (*it).find( '-' );
|
|
|
|
if ( pos == -1 ) continue;
|
|
|
|
TQString app = (*it).left( pos );
|
|
|
|
if ( app == "KOLAB" ) continue;
|
|
|
|
TQString name = (*it).mid( pos + 1 );
|
|
|
|
pos = name.find( ':' );
|
|
|
|
if ( pos == -1 ) continue;
|
|
|
|
TQString value = name.mid( pos + 1 );
|
|
|
|
name = name.left( pos );
|
|
|
|
if ( !knownCustoms.contains( name ) ) {
|
|
|
|
//kdDebug() << k_funcinfo << "app=" << app << " name=" << name << " value=" << value << endl;
|
|
|
|
Custom c;
|
|
|
|
if ( app != "KADDRESSBOOK" ) // that's the default
|
|
|
|
c.app = app;
|
|
|
|
c.name = name;
|
|
|
|
c.value = value;
|
|
|
|
mCustomList.append( c );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString url = KCal::FreeBusyUrlStore::self()->readUrl( addressee->preferredEmail() );
|
|
|
|
if ( !url.isEmpty() ) {
|
|
|
|
setFreeBusyUrl( url );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Those fields, although defined in Addressee, are not used in KDE
|
|
|
|
// (e.g. not visible in kaddressbook/addresseeeditorwidget.cpp)
|
|
|
|
// So it doesn't matter much if we don't have them in the XML.
|
|
|
|
// mailer, timezone, productId, sortString, agent, rfc2426 name()
|
|
|
|
|
|
|
|
// Things KAddressBook can't handle, so they are saved as unhandled tags:
|
|
|
|
// initials, children, gender, language
|
|
|
|
}
|
|
|
|
|
|
|
|
// The loading is: xml -> Contact -> addressee, this is the second part
|
|
|
|
void Contact::saveTo( TDEABC::Addressee* addressee )
|
|
|
|
{
|
|
|
|
// TODO: This needs the same set of TODOs as the setFields method
|
|
|
|
KolabBase::saveTo( addressee );
|
|
|
|
|
|
|
|
if ( mIsDistributionList ) {
|
|
|
|
KPIM::DistributionList distrList( *addressee );
|
|
|
|
distrList.setName( fullName() );
|
|
|
|
TQValueList<Member>::ConstIterator mit = mDistrListMembers.begin();
|
|
|
|
for ( ; mit != mDistrListMembers.end(); ++mit ) {
|
|
|
|
TQString displayName = (*mit).displayName;
|
|
|
|
// fixup the display name DistributionList::assumes neither ',' nor ';' is present
|
|
|
|
displayName.replace( ',', ' ' );
|
|
|
|
displayName.replace( ';', ' ' );
|
|
|
|
distrList.insertEntry( displayName, (*mit).email );
|
|
|
|
}
|
|
|
|
addressee->insertCustom( "KADDRESSBOOK", "DistributionList", distrList.custom( "KADDRESSBOOK", "DistributionList" ) );
|
|
|
|
Q_ASSERT( KPIM::DistributionList::isDistributionList( *addressee ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
addressee->setGivenName( givenName() );
|
|
|
|
addressee->setAdditionalName( middleNames() );
|
|
|
|
addressee->setFamilyName( lastName() );
|
|
|
|
addressee->setFormattedName( fullName() );
|
|
|
|
if ( mIsDistributionList )
|
|
|
|
addressee->setName( fullName() );
|
|
|
|
addressee->setPrefix( prefix() );
|
|
|
|
addressee->setSuffix( suffix() );
|
|
|
|
addressee->setOrganization( organization() );
|
|
|
|
addressee->setUrl( webPage() );
|
|
|
|
addressee->insertCustom( "KADDRESSBOOK", "X-IMAddress", imAddress() );
|
|
|
|
#if KDE_IS_VERSION(3,5,8)
|
|
|
|
addressee->setDepartment( department() );
|
|
|
|
#else
|
|
|
|
addressee->insertCustom( "KADDRESSBOOK", "X-Department", department() );
|
|
|
|
#endif
|
|
|
|
addressee->insertCustom( "KADDRESSBOOK", "X-Office", officeLocation() );
|
|
|
|
addressee->insertCustom( "KADDRESSBOOK", "X-Profession", profession() );
|
|
|
|
addressee->setRole( role() );
|
|
|
|
addressee->setTitle( jobTitle() );
|
|
|
|
addressee->insertCustom( "KADDRESSBOOK", "X-ManagersName", managerName() );
|
|
|
|
addressee->insertCustom( "KADDRESSBOOK", "X-AssistantsName", assistant() );
|
|
|
|
addressee->setNickName( nickName() );
|
|
|
|
addressee->insertCustom( "KADDRESSBOOK", "X-SpousesName", spouseName() );
|
|
|
|
if ( birthday().isValid() )
|
|
|
|
addressee->setBirthday( TQDateTime( birthday() ) );
|
|
|
|
|
|
|
|
if ( anniversary().isValid() )
|
|
|
|
addressee->insertCustom( "KADDRESSBOOK", "X-Anniversary",
|
|
|
|
dateToString( anniversary() ) );
|
|
|
|
else
|
|
|
|
addressee->removeCustom( "KADDRESSBOOK", "X-Anniversary" );
|
|
|
|
|
|
|
|
// We need to store both the original attachment name and the picture data into the addressee.
|
|
|
|
// This is important, otherwise we would save the image under another attachment name w/o deleting the original one!
|
|
|
|
if ( !mPicture.isNull() )
|
|
|
|
addressee->setPhoto( TDEABC::Picture( mPicture ) );
|
|
|
|
// Note that we must save the filename in all cases, so that removing the picture
|
|
|
|
// actually deletes the attachment.
|
|
|
|
addressee->insertCustom( "KOLAB", "PictureAttachmentName", mPictureAttachmentName );
|
|
|
|
if ( !mLogo.isNull() )
|
|
|
|
addressee->setLogo( TDEABC::Picture( mLogo ) );
|
|
|
|
addressee->insertCustom( "KOLAB", "LogoAttachmentName", mLogoAttachmentName );
|
|
|
|
if ( !mSound.isNull() )
|
|
|
|
addressee->setSound( TDEABC::Sound( mSound ) );
|
|
|
|
addressee->insertCustom( "KOLAB", "SoundAttachmentName", mSoundAttachmentName );
|
|
|
|
|
|
|
|
if ( mHasGeo )
|
|
|
|
addressee->setGeo( TDEABC::Geo( mLatitude, mLongitude ) );
|
|
|
|
|
|
|
|
TQStringList emailAddresses;
|
|
|
|
for ( TQValueList<Email>::ConstIterator it = mEmails.begin(); it != mEmails.end(); ++it ) {
|
|
|
|
// we can't do anything with (*it).displayName
|
|
|
|
emailAddresses.append( (*it).smtpAddress );
|
|
|
|
}
|
|
|
|
addressee->setEmails( emailAddresses );
|
|
|
|
|
|
|
|
for ( TQValueList<Address>::ConstIterator it = mAddresses.begin(); it != mAddresses.end(); ++it ) {
|
|
|
|
TDEABC::Address address;
|
|
|
|
int type = (*it).kdeAddressType;
|
|
|
|
if ( type == -1 ) { // no kde-specific type available
|
|
|
|
type = addressTypeFromString( (*it).type );
|
|
|
|
if ( (*it).type == mPreferredAddress )
|
|
|
|
type |= TDEABC::Address::Pref;
|
|
|
|
}
|
|
|
|
address.setType( type );
|
|
|
|
address.setStreet( (*it).street );
|
|
|
|
address.setPostOfficeBox( (*it).pobox );
|
|
|
|
address.setLocality( (*it).locality );
|
|
|
|
address.setRegion( (*it).region );
|
|
|
|
address.setPostalCode( (*it).postalCode );
|
|
|
|
address.setCountry( (*it).country );
|
|
|
|
addressee->insertAddress( address );
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( TQValueList<PhoneNumber>::ConstIterator it = mPhoneNumbers.begin(); it != mPhoneNumbers.end(); ++it ) {
|
|
|
|
TDEABC::PhoneNumber number;
|
|
|
|
number.setType( phoneTypeFromString( (*it).type ) );
|
|
|
|
number.setNumber( (*it).number );
|
|
|
|
addressee->insertPhoneNumber( number );
|
|
|
|
}
|
|
|
|
|
|
|
|
for( TQValueList<Custom>::ConstIterator it = mCustomList.begin(); it != mCustomList.end(); ++it ) {
|
|
|
|
TQString app = (*it).app.isEmpty() ? TQString::fromLatin1( "KADDRESSBOOK" ) : (*it).app;
|
|
|
|
addressee->insertCustom( app, (*it).name, (*it).value );
|
|
|
|
}
|
|
|
|
//kdDebug(5006) << addressee->customs() << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQImage Contact::loadPictureFromKMail( const TQString& attachmentName, TDEABC::ResourceKolab* resource, const TQString& subResource, TQ_UINT32 sernum )
|
|
|
|
{
|
|
|
|
TQImage img;
|
|
|
|
KURL url;
|
|
|
|
if ( resource->kmailGetAttachment( url, subResource, sernum, attachmentName ) && !url.isEmpty() ) {
|
|
|
|
const TQString path = url.path();
|
|
|
|
img.load( path );
|
|
|
|
TQFile::remove(path);
|
|
|
|
}
|
|
|
|
return img;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQImage Contact::loadPictureFromAddressee( const TDEABC::Picture& picture )
|
|
|
|
{
|
|
|
|
TQImage img;
|
|
|
|
if ( !picture.isIntern() && !picture.url().isEmpty() ) {
|
|
|
|
TQString tmpFile;
|
|
|
|
if ( TDEIO::NetAccess::download( picture.url(), tmpFile, 0 /*no widget known*/ ) ) {
|
|
|
|
img.load( tmpFile );
|
|
|
|
TDEIO::NetAccess::removeTempFile( tmpFile );
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
img = picture.data();
|
|
|
|
return img;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQByteArray Kolab::Contact::loadDataFromKMail( const TQString& attachmentName, TDEABC::ResourceKolab* resource, const TQString& subResource, TQ_UINT32 sernum )
|
|
|
|
{
|
|
|
|
TQByteArray data;
|
|
|
|
KURL url;
|
|
|
|
if ( resource->kmailGetAttachment( url, subResource, sernum, attachmentName ) && !url.isEmpty() ) {
|
|
|
|
TQFile f( url.path() );
|
|
|
|
if ( f.open( IO_ReadOnly ) ) {
|
|
|
|
data = f.readAll();
|
|
|
|
f.close();
|
|
|
|
}
|
|
|
|
f.remove();
|
|
|
|
}
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQByteArray Kolab::Contact::loadSoundFromAddressee( const TDEABC::Sound& sound )
|
|
|
|
{
|
|
|
|
TQByteArray data;
|
|
|
|
if ( !sound.isIntern() && !sound.url().isEmpty() ) {
|
|
|
|
TQString tmpFile;
|
|
|
|
if ( TDEIO::NetAccess::download( sound.url(), tmpFile, 0 /*no widget known*/ ) ) {
|
|
|
|
TQFile f( tmpFile );
|
|
|
|
if ( f.open( IO_ReadOnly ) ) {
|
|
|
|
data = f.readAll();
|
|
|
|
f.close();
|
|
|
|
}
|
|
|
|
TDEIO::NetAccess::removeTempFile( tmpFile );
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
data = sound.data();
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Kolab::Contact::productID() const
|
|
|
|
{
|
|
|
|
// TODO: When KAB has the version number in a header file, don't hardcode (Bo)
|
|
|
|
// Or we could use Addressee::productID? (David)
|
|
|
|
return "KAddressBook 3.3, Kolab resource";
|
|
|
|
}
|