mirror of
https://gitdl.cn/https://github.com/chakralinux/desktop.git
synced 2025-02-03 22:47:16 +08:00
2129 lines
69 KiB
Diff
2129 lines
69 KiB
Diff
|
diff --git a/conversion/kabcconversion.cpp b/conversion/kabcconversion.cpp
|
||
|
index b7d7235..6a51e47 100644
|
||
|
--- a/conversion/kabcconversion.cpp
|
||
|
+++ b/conversion/kabcconversion.cpp
|
||
|
@@ -1,893 +1,895 @@
|
||
|
/*
|
||
|
* Copyright (C) 2011 Christian Mollekopf <mollekopf@kolabsys.com>
|
||
|
*
|
||
|
* This program is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||
|
* the Free Software Foundation, either version 3 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* 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 Lesser General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Lesser General Public License
|
||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#include "kabcconversion.h"
|
||
|
|
||
|
#include "commonconversion.h"
|
||
|
#include <qbuffer.h>
|
||
|
#include <qimagereader.h>
|
||
|
#include "kolabformat/errorhandler.h"
|
||
|
|
||
|
|
||
|
|
||
|
namespace Kolab {
|
||
|
namespace Conversion {
|
||
|
|
||
|
//The following was copied from kdepim/libkleo/kleo/enum.h,.cpp
|
||
|
enum CryptoMessageFormat {
|
||
|
InlineOpenPGPFormat = 1,
|
||
|
OpenPGPMIMEFormat = 2,
|
||
|
SMIMEFormat = 4,
|
||
|
SMIMEOpaqueFormat = 8,
|
||
|
AnyOpenPGP = InlineOpenPGPFormat|OpenPGPMIMEFormat,
|
||
|
AnySMIME = SMIMEOpaqueFormat|SMIMEFormat,
|
||
|
AutoFormat = AnyOpenPGP|AnySMIME
|
||
|
};
|
||
|
|
||
|
enum EncryptionPreference {
|
||
|
UnknownPreference = 0,
|
||
|
NeverEncrypt = 1,
|
||
|
AlwaysEncrypt = 2,
|
||
|
AlwaysEncryptIfPossible = 3,
|
||
|
AlwaysAskForEncryption = 4,
|
||
|
AskWheneverPossible = 5,
|
||
|
MaxEncryptionPreference = AskWheneverPossible
|
||
|
};
|
||
|
|
||
|
enum SigningPreference {
|
||
|
UnknownSigningPreference = 0,
|
||
|
NeverSign = 1,
|
||
|
AlwaysSign = 2,
|
||
|
AlwaysSignIfPossible = 3,
|
||
|
AlwaysAskForSigning = 4,
|
||
|
AskSigningWheneverPossible = 5,
|
||
|
MaxSigningPreference = AskSigningWheneverPossible
|
||
|
};
|
||
|
|
||
|
static const struct {
|
||
|
CryptoMessageFormat format;
|
||
|
const char * displayName;
|
||
|
const char * configName;
|
||
|
} cryptoMessageFormats[] = {
|
||
|
{ InlineOpenPGPFormat,
|
||
|
("Inline OpenPGP (deprecated)"),
|
||
|
"inline openpgp" },
|
||
|
{ OpenPGPMIMEFormat,
|
||
|
("OpenPGP/MIME"),
|
||
|
"openpgp/mime" },
|
||
|
{ SMIMEFormat,
|
||
|
("S/MIME"),
|
||
|
"s/mime" },
|
||
|
{ SMIMEOpaqueFormat,
|
||
|
("S/MIME Opaque"),
|
||
|
"s/mime opaque" },
|
||
|
};
|
||
|
static const unsigned int numCryptoMessageFormats
|
||
|
= sizeof cryptoMessageFormats / sizeof *cryptoMessageFormats ;
|
||
|
|
||
|
const char * cryptoMessageFormatToString( CryptoMessageFormat f ) {
|
||
|
if ( f == AutoFormat )
|
||
|
return "auto";
|
||
|
for ( unsigned int i = 0 ; i < numCryptoMessageFormats ; ++i )
|
||
|
if ( f == cryptoMessageFormats[i].format )
|
||
|
return cryptoMessageFormats[i].configName;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
QStringList cryptoMessageFormatsToStringList( unsigned int f ) {
|
||
|
QStringList result;
|
||
|
for ( unsigned int i = 0 ; i < numCryptoMessageFormats ; ++i )
|
||
|
if ( f & cryptoMessageFormats[i].format )
|
||
|
result.push_back( cryptoMessageFormats[i].configName );
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
CryptoMessageFormat stringToCryptoMessageFormat( const QString & s ) {
|
||
|
const QString t = s.toLower();
|
||
|
for ( unsigned int i = 0 ; i < numCryptoMessageFormats ; ++i )
|
||
|
if ( t == cryptoMessageFormats[i].configName )
|
||
|
return cryptoMessageFormats[i].format;
|
||
|
return AutoFormat;
|
||
|
}
|
||
|
|
||
|
unsigned int stringListToCryptoMessageFormats( const QStringList & sl ) {
|
||
|
unsigned int result = 0;
|
||
|
for ( QStringList::const_iterator it = sl.begin() ; it != sl.end() ; ++it )
|
||
|
result |= stringToCryptoMessageFormat( *it );
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
// For the config values used below, see also kaddressbook/editors/cryptowidget.cpp
|
||
|
|
||
|
const char* encryptionPreferenceToString( EncryptionPreference pref )
|
||
|
{
|
||
|
switch( pref ) {
|
||
|
case UnknownPreference:
|
||
|
return 0;
|
||
|
case NeverEncrypt:
|
||
|
return "never";
|
||
|
case AlwaysEncrypt:
|
||
|
return "always";
|
||
|
case AlwaysEncryptIfPossible:
|
||
|
return "alwaysIfPossible";
|
||
|
case AlwaysAskForEncryption:
|
||
|
return "askAlways";
|
||
|
case AskWheneverPossible:
|
||
|
return "askWhenPossible";
|
||
|
}
|
||
|
return 0; // keep the compiler happy
|
||
|
}
|
||
|
|
||
|
EncryptionPreference stringToEncryptionPreference( const QString& str )
|
||
|
{
|
||
|
if ( str == "never" )
|
||
|
return NeverEncrypt;
|
||
|
if ( str == "always" )
|
||
|
return AlwaysEncrypt;
|
||
|
if ( str == "alwaysIfPossible" )
|
||
|
return AlwaysEncryptIfPossible;
|
||
|
if ( str == "askAlways" )
|
||
|
return AlwaysAskForEncryption;
|
||
|
if ( str == "askWhenPossible" )
|
||
|
return AskWheneverPossible;
|
||
|
return UnknownPreference;
|
||
|
}
|
||
|
|
||
|
const char* signingPreferenceToString( SigningPreference pref )
|
||
|
{
|
||
|
switch( pref ) {
|
||
|
case UnknownSigningPreference:
|
||
|
return 0;
|
||
|
case NeverSign:
|
||
|
return "never";
|
||
|
case AlwaysSign:
|
||
|
return "always";
|
||
|
case AlwaysSignIfPossible:
|
||
|
return "alwaysIfPossible";
|
||
|
case AlwaysAskForSigning:
|
||
|
return "askAlways";
|
||
|
case AskSigningWheneverPossible:
|
||
|
return "askWhenPossible";
|
||
|
}
|
||
|
return 0; // keep the compiler happy
|
||
|
}
|
||
|
|
||
|
SigningPreference stringToSigningPreference( const QString& str )
|
||
|
{
|
||
|
if ( str == "never" )
|
||
|
return NeverSign;
|
||
|
if ( str == "always" )
|
||
|
return AlwaysSign;
|
||
|
if ( str == "alwaysIfPossible" )
|
||
|
return AlwaysSignIfPossible;
|
||
|
if ( str == "askAlways" )
|
||
|
return AlwaysAskForSigning;
|
||
|
if ( str == "askWhenPossible" )
|
||
|
return AskSigningWheneverPossible;
|
||
|
return UnknownSigningPreference;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
int fromAddressType(int kabcType, bool &pref)
|
||
|
{
|
||
|
int type = 0;
|
||
|
if (kabcType & KContacts::Address::Dom) {
|
||
|
Warning() << "domestic address is not supported";
|
||
|
}
|
||
|
if (kabcType & KContacts::Address::Intl) {
|
||
|
Warning() << "international address is not supported";
|
||
|
}
|
||
|
if (kabcType & KContacts::Address::Pref) {
|
||
|
pref = true;
|
||
|
}
|
||
|
if (kabcType & KContacts::Address::Postal) {
|
||
|
Warning() << "postal address is not supported";
|
||
|
}
|
||
|
if (kabcType & KContacts::Address::Parcel) {
|
||
|
Warning() << "parcel is not supported";
|
||
|
}
|
||
|
if (kabcType & KContacts::Address::Home) {
|
||
|
type |= Kolab::Address::Home;
|
||
|
}
|
||
|
if (kabcType & KContacts::Address::Work) {
|
||
|
type |= Kolab::Address::Work;
|
||
|
}
|
||
|
return type;
|
||
|
}
|
||
|
|
||
|
KContacts::Address::Type toAddressType(int types, bool pref)
|
||
|
{
|
||
|
KContacts::Address::Type type = 0;
|
||
|
if (pref) {
|
||
|
type |= KContacts::Address::Pref;
|
||
|
}
|
||
|
if (types & Kolab::Address::Home) {
|
||
|
type |= KContacts::Address::Home;
|
||
|
}
|
||
|
if (types & Kolab::Address::Work) {
|
||
|
type |= KContacts::Address::Work;
|
||
|
}
|
||
|
return type;
|
||
|
}
|
||
|
|
||
|
int fromPhoneType(int kabcType, bool &pref)
|
||
|
{
|
||
|
int type = 0;
|
||
|
if (kabcType & KContacts::PhoneNumber::Home) {
|
||
|
type |= Kolab::Telephone::Home;
|
||
|
}
|
||
|
if (kabcType & KContacts::PhoneNumber::Work) {
|
||
|
type |= Kolab::Telephone::Work;
|
||
|
}
|
||
|
if (kabcType & KContacts::PhoneNumber::Msg) {
|
||
|
type |= Kolab::Telephone::Text;
|
||
|
}
|
||
|
if (kabcType & KContacts::PhoneNumber::Pref) {
|
||
|
pref = true;
|
||
|
}
|
||
|
if (kabcType & KContacts::PhoneNumber::Voice) {
|
||
|
type |= Kolab::Telephone::Voice;
|
||
|
}
|
||
|
if (kabcType & KContacts::PhoneNumber::Fax) {
|
||
|
type |= Kolab::Telephone::Fax;
|
||
|
}
|
||
|
if (kabcType & KContacts::PhoneNumber::Cell) {
|
||
|
type |= Kolab::Telephone::Cell;
|
||
|
}
|
||
|
if (kabcType & KContacts::PhoneNumber::Video) {
|
||
|
type |= Kolab::Telephone::Video;
|
||
|
}
|
||
|
if (kabcType & KContacts::PhoneNumber::Bbs) {
|
||
|
Warning() << "mailbox number is not supported";
|
||
|
}
|
||
|
if (kabcType & KContacts::PhoneNumber::Modem) {
|
||
|
Warning() << "modem is not supported";
|
||
|
}
|
||
|
if (kabcType & KContacts::PhoneNumber::Car) {
|
||
|
type |= Kolab::Telephone::Car;
|
||
|
}
|
||
|
if (kabcType & KContacts::PhoneNumber::Isdn) {
|
||
|
Warning() << "isdn number is not supported";
|
||
|
}
|
||
|
if (kabcType & KContacts::PhoneNumber::Pcs) {
|
||
|
type |= Kolab::Telephone::Text;
|
||
|
}
|
||
|
if (kabcType & KContacts::PhoneNumber::Pager) {
|
||
|
type |= Kolab::Telephone::Pager;
|
||
|
}
|
||
|
return type;
|
||
|
}
|
||
|
|
||
|
KContacts::PhoneNumber::Type toPhoneType(int types, bool pref)
|
||
|
{
|
||
|
KContacts::PhoneNumber::Type type = 0;
|
||
|
if (types & Kolab::Telephone::Home) {
|
||
|
type |= KContacts::PhoneNumber::Home;
|
||
|
}
|
||
|
if (types & Kolab::Telephone::Work) {
|
||
|
type |= KContacts::PhoneNumber::Work;
|
||
|
}
|
||
|
if (types & Kolab::Telephone::Text) {
|
||
|
type |= KContacts::PhoneNumber::Msg;
|
||
|
}
|
||
|
if (pref) {
|
||
|
type |= KContacts::PhoneNumber::Pref;
|
||
|
}
|
||
|
if (types & Kolab::Telephone::Voice) {
|
||
|
type |= KContacts::PhoneNumber::Voice;
|
||
|
}
|
||
|
if (types & Kolab::Telephone::Fax) {
|
||
|
type |= KContacts::PhoneNumber::Fax;
|
||
|
}
|
||
|
if (types & Kolab::Telephone::Cell) {
|
||
|
type |= KContacts::PhoneNumber::Cell;
|
||
|
}
|
||
|
if (types & Kolab::Telephone::Video) {
|
||
|
type |= KContacts::PhoneNumber::Video;
|
||
|
}
|
||
|
if (types & Kolab::Telephone::Car) {
|
||
|
type |= KContacts::PhoneNumber::Car;
|
||
|
}
|
||
|
if (types & Kolab::Telephone::Text) {
|
||
|
type |= KContacts::PhoneNumber::Pcs;
|
||
|
}
|
||
|
if (types & Kolab::Telephone::Pager) {
|
||
|
type |= KContacts::PhoneNumber::Pager;
|
||
|
}
|
||
|
return type;
|
||
|
}
|
||
|
|
||
|
std::string fromPicture(const KContacts::Picture &pic, std::string &mimetype)
|
||
|
{
|
||
|
QByteArray input;
|
||
|
QBuffer buffer( &input );
|
||
|
buffer.open( QIODevice::WriteOnly );
|
||
|
QImage img;
|
||
|
|
||
|
|
||
|
if ( pic.isIntern() ) {
|
||
|
if ( !pic.data().isNull() ) {
|
||
|
img = pic.data();
|
||
|
}
|
||
|
} else if ( !pic.url().isEmpty() ) {
|
||
|
QString tmpFile;
|
||
|
qWarning() << "external pictures are currently not supported";
|
||
|
//FIXME add kio support to libcalendaring or use libcurl
|
||
|
// if ( KIO::NetAccess::download( pic.url(), tmpFile, 0 /*no widget known*/ ) ) {
|
||
|
// img.load( tmpFile );
|
||
|
// KIO::NetAccess::removeTempFile( tmpFile );
|
||
|
// }
|
||
|
}
|
||
|
if (img.isNull()) {
|
||
|
Error() << "invalid picture";
|
||
|
return std::string();
|
||
|
}
|
||
|
if ( !img.hasAlphaChannel() ) {
|
||
|
if (!img.save( &buffer, "JPEG" )) {
|
||
|
Error() << "error on jpeg save";
|
||
|
return std::string();
|
||
|
}
|
||
|
mimetype = "image/jpeg";
|
||
|
} else {
|
||
|
if (!img.save( &buffer, "PNG" )) {
|
||
|
Error() << "error on png save";
|
||
|
return std::string();
|
||
|
}
|
||
|
mimetype = "image/png";
|
||
|
}
|
||
|
return std::string(input.data(), input.size());
|
||
|
}
|
||
|
|
||
|
KContacts::Picture toPicture(const std::string &data, const std::string &mimetype) {
|
||
|
QImage img;
|
||
|
bool ret = false;
|
||
|
QByteArray type(mimetype.data(), mimetype.size());
|
||
|
type = type.split('/').last(); // extract "jpeg" from "image/jpeg"
|
||
|
if (QImageReader::supportedImageFormats().contains(type)) {
|
||
|
ret = img.loadFromData(QByteArray::fromRawData(data.data(), data.size()), type.constData());
|
||
|
} else {
|
||
|
ret = img.loadFromData(QByteArray::fromRawData(data.data(), data.size()));
|
||
|
}
|
||
|
if (!ret) {
|
||
|
Warning() << "failed to load picture";
|
||
|
return KContacts::Picture();
|
||
|
}
|
||
|
|
||
|
KContacts::Picture logo(img);
|
||
|
if (logo.isEmpty()) {
|
||
|
Warning() << "failed to read picture";
|
||
|
return KContacts::Picture();
|
||
|
}
|
||
|
return logo;
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
void setCustom(const std::string &value, const std::string &id, T &object)
|
||
|
{
|
||
|
std::vector <Kolab::CustomProperty > properties = object.customProperties();
|
||
|
properties.push_back(CustomProperty(id, value));
|
||
|
object.setCustomProperties(properties);
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
std::string getCustom(const std::string &id, T &object)
|
||
|
{
|
||
|
const std::vector <Kolab::CustomProperty > &properties = object.customProperties();
|
||
|
foreach(const Kolab::CustomProperty &prop, properties) {
|
||
|
if (prop.identifier == id) {
|
||
|
return prop.value;
|
||
|
}
|
||
|
}
|
||
|
return std::string();
|
||
|
}
|
||
|
|
||
|
static QString emailTypesToStringList(int emailTypes) {
|
||
|
QStringList types;
|
||
|
if (emailTypes & Kolab::Email::Home) {
|
||
|
types << "home";
|
||
|
}
|
||
|
if (emailTypes & Kolab::Email::Work) {
|
||
|
types << "work";
|
||
|
}
|
||
|
return types.join(",");
|
||
|
}
|
||
|
|
||
|
static int emailTypesFromStringlist(const QString &types) {
|
||
|
int emailTypes = Kolab::Email::NoType;
|
||
|
if (types.contains("home")) {
|
||
|
emailTypes |= Kolab::Email::Home;
|
||
|
}
|
||
|
if (types.contains("work")) {
|
||
|
emailTypes |= Kolab::Email::Work;
|
||
|
}
|
||
|
return emailTypes;
|
||
|
}
|
||
|
|
||
|
KContacts::Addressee toKABC(const Kolab::Contact &contact)
|
||
|
{
|
||
|
KContacts::Addressee addressee;
|
||
|
addressee.setUid(fromStdString(contact.uid()));
|
||
|
addressee.setCategories(toStringList(contact.categories()));
|
||
|
//addressee.setName(fromStdString(contact.name()));//This one is only for compatiblity (and results in a non-existing name property)
|
||
|
addressee.setFormattedName(fromStdString(contact.name())); //This on corresponds to fn
|
||
|
|
||
|
const Kolab::NameComponents &nc = contact.nameComponents();
|
||
|
if (!nc.surnames().empty()) {
|
||
|
addressee.setFamilyName(fromStdString(nc.surnames().front()));
|
||
|
}
|
||
|
if (!nc.given().empty()) {
|
||
|
addressee.setGivenName(fromStdString(nc.given().front()));
|
||
|
}
|
||
|
if (!nc.additional().empty()) {
|
||
|
addressee.setAdditionalName(fromStdString(nc.additional().front()));
|
||
|
}
|
||
|
if (!nc.prefixes().empty()) {
|
||
|
addressee.setPrefix(fromStdString(nc.prefixes().front()));
|
||
|
}
|
||
|
if (!nc.suffixes().empty()) {
|
||
|
addressee.setSuffix(fromStdString(nc.suffixes().front()));
|
||
|
}
|
||
|
|
||
|
addressee.setNote(fromStdString(contact.note()));
|
||
|
|
||
|
addressee.setSecrecy(KContacts::Secrecy::Public); //We don't have any privacy setting in xCard
|
||
|
|
||
|
|
||
|
QString preferredEmail;
|
||
|
|
||
|
if (!contact.emailAddresses().empty()) {
|
||
|
QStringList emails;
|
||
|
foreach( const Kolab::Email &email, contact.emailAddresses()) {
|
||
|
emails << fromStdString(email.address());
|
||
|
const QString types = emailTypesToStringList(email.types());
|
||
|
if (!types.isEmpty()) {
|
||
|
addressee.insertCustom(QLatin1String("KOLAB"), QString::fromLatin1("EmailTypes%1").arg(fromStdString(email.address())), types);
|
||
|
}
|
||
|
}
|
||
|
addressee.setEmails(emails);
|
||
|
if ((contact.emailAddressPreferredIndex() >= 0) && (contact.emailAddressPreferredIndex() < static_cast<int>(contact.emailAddresses().size()))) {
|
||
|
preferredEmail = fromStdString(contact.emailAddresses().at(contact.emailAddressPreferredIndex()).address());
|
||
|
} else {
|
||
|
preferredEmail = fromStdString(contact.emailAddresses().at(0).address());
|
||
|
}
|
||
|
addressee.insertEmail(preferredEmail, true);
|
||
|
}
|
||
|
|
||
|
if (!contact.freeBusyUrl().empty()) {
|
||
|
if (preferredEmail.isEmpty()) {
|
||
|
Error() << "f/b url is set but no email address available, skipping";
|
||
|
} else {
|
||
|
addressee.insertCustom("KOLAB", "FreebusyUrl", fromStdString(contact.freeBusyUrl()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!contact.nickNames().empty()) {
|
||
|
addressee.setNickName(fromStdString(contact.nickNames().at(0))); //TODO support multiple
|
||
|
}
|
||
|
|
||
|
if (contact.bDay().isValid()) {
|
||
|
addressee.setBirthday(toDate(contact.bDay()).dateTime());
|
||
|
}
|
||
|
if (!contact.titles().empty()) {
|
||
|
addressee.setTitle(fromStdString(contact.titles().at(0))); //TODO support multiple
|
||
|
}
|
||
|
if (!contact.urls().empty()) {
|
||
|
- addressee.setUrl(QUrl(fromStdString(contact.urls().at(0).url()))); //TODO support multiple
|
||
|
+ KContacts::ResourceLocatorUrl url;
|
||
|
+ url.setUrl(QUrl(fromStdString(contact.urls().at(0).url()))); //TODO support multiple
|
||
|
+ addressee.setUrl(url);
|
||
|
foreach(const Kolab::Url &u, contact.urls()) {
|
||
|
if (u.type() == Kolab::Url::Blog) {
|
||
|
addressee.insertCustom("KADDRESSBOOK", "BlogFeed", fromStdString(u.url()));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
if (!contact.affiliations().empty()) {
|
||
|
//Storing only a const reference leads to segfaults. No idea why.
|
||
|
const Kolab::Affiliation aff = contact.affiliations().at(0); //TODO support multiple
|
||
|
if (!aff.organisation().empty()) {
|
||
|
addressee.setOrganization(fromStdString(aff.organisation()));
|
||
|
}
|
||
|
if (!aff.organisationalUnits().empty()) {
|
||
|
addressee.setDepartment(fromStdString(aff.organisationalUnits().at(0))); //TODO support multiple
|
||
|
}
|
||
|
if (!aff.roles().empty()) {
|
||
|
addressee.setRole(fromStdString(aff.roles().at(0))); //TODO support multiple
|
||
|
}
|
||
|
if (!aff.logo().empty()) {
|
||
|
addressee.setLogo(toPicture(aff.logo(), aff.logoMimetype()));
|
||
|
}
|
||
|
foreach(const Kolab::Related &related, aff.relateds()) {
|
||
|
if (related.type() != Kolab::Related::Text) {
|
||
|
Error() << "invalid relation type";
|
||
|
continue;
|
||
|
}
|
||
|
if (related.relationTypes() & Kolab::Related::Assistant) {
|
||
|
addressee.insertCustom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-AssistantsName"), fromStdString(related.text()));
|
||
|
}
|
||
|
if (related.relationTypes() & Kolab::Related::Manager) {
|
||
|
addressee.insertCustom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-ManagersName"), fromStdString(related.text()));
|
||
|
}
|
||
|
}
|
||
|
foreach(const Kolab::Address &address, aff.addresses()) {
|
||
|
addressee.insertCustom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-Office"), fromStdString(address.label())); //TODO support proper addresses
|
||
|
}
|
||
|
}
|
||
|
const std::string &prof = getCustom("X-Profession", contact);
|
||
|
if (!prof.empty()) {
|
||
|
addressee.insertCustom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-Profession"), fromStdString(prof));
|
||
|
}
|
||
|
|
||
|
const std::string &adrBook = getCustom("X-AddressBook", contact);
|
||
|
if (!adrBook.empty()) {
|
||
|
addressee.insertCustom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-AddressBook"), fromStdString(prof));
|
||
|
}
|
||
|
|
||
|
if (!contact.photo().empty()) {
|
||
|
addressee.setPhoto(toPicture(contact.photo(), contact.photoMimetype()));
|
||
|
}
|
||
|
|
||
|
if (!contact.telephones().empty()) {
|
||
|
int index = 0;
|
||
|
foreach(const Kolab::Telephone &tel, contact.telephones()) {
|
||
|
bool pref = false;
|
||
|
if (index == contact.telephonesPreferredIndex()) {
|
||
|
pref = true;
|
||
|
}
|
||
|
KContacts::PhoneNumber number(fromStdString(tel.number()), toPhoneType(tel.types(), pref));
|
||
|
index++;
|
||
|
addressee.insertPhoneNumber(number);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!contact.addresses().empty()) {
|
||
|
int index = 0;
|
||
|
foreach(const Kolab::Address &a, contact.addresses()) {
|
||
|
bool pref = false;
|
||
|
if (index == contact.addressPreferredIndex()) {
|
||
|
pref = true;
|
||
|
}
|
||
|
KContacts::Address adr(toAddressType(a.types(), pref));
|
||
|
adr.setLabel(fromStdString(a.label()));
|
||
|
adr.setStreet(fromStdString(a.street()));
|
||
|
adr.setLocality(fromStdString(a.locality()));
|
||
|
adr.setRegion(fromStdString(a.region()));
|
||
|
adr.setPostalCode(fromStdString(a.code()));
|
||
|
adr.setCountry(fromStdString(a.country()));
|
||
|
|
||
|
index++;
|
||
|
addressee.insertAddress(adr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (contact.anniversary().isValid()) {
|
||
|
addressee.insertCustom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-Anniversary"), toDate(contact.anniversary()).toString(KDateTime::ISODate));
|
||
|
}
|
||
|
|
||
|
if (!contact.imAddresses().empty()) {
|
||
|
addressee.insertCustom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-IMAddress"),fromStdString(contact.imAddresses()[0])); //TODO support multiple
|
||
|
}
|
||
|
|
||
|
if (!contact.relateds().empty()) {
|
||
|
foreach(const Kolab::Related &rel, contact.relateds()) {
|
||
|
if (rel.type() != Kolab::Related::Text) {
|
||
|
Error() << "relation type not supported";
|
||
|
continue;
|
||
|
}
|
||
|
if (rel.relationTypes() & Kolab::Related::Spouse) {
|
||
|
addressee.insertCustom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-SpousesName"),fromStdString(rel.text())); //TODO support multiple
|
||
|
} else {
|
||
|
Warning() << "relation not supported";
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return addressee;
|
||
|
}
|
||
|
|
||
|
Kolab::Contact fromKABC(const KContacts::Addressee &addressee)
|
||
|
{
|
||
|
int prefNum = -1;
|
||
|
int prefCounter = -1;
|
||
|
Kolab::Contact c;
|
||
|
c.setUid(toStdString(addressee.uid()));
|
||
|
c.setCategories(fromStringList(addressee.categories()));
|
||
|
c.setName(toStdString(addressee.formattedName()));
|
||
|
Kolab::NameComponents nc;
|
||
|
nc.setSurnames(std::vector<std::string>() << toStdString(addressee.familyName()));
|
||
|
nc.setGiven(std::vector<std::string>() << toStdString(addressee.givenName()));
|
||
|
nc.setAdditional(std::vector<std::string>() << toStdString(addressee.additionalName()));
|
||
|
nc.setPrefixes(std::vector<std::string>() << toStdString(addressee.prefix()));
|
||
|
nc.setSuffixes(std::vector<std::string>() << toStdString(addressee.suffix()));
|
||
|
c.setNameComponents(nc);
|
||
|
|
||
|
c.setNote(toStdString(addressee.note()));
|
||
|
c.setFreeBusyUrl(toStdString(addressee.custom("KOLAB", QString("FreebusyUrl"))));
|
||
|
|
||
|
if (!addressee.title().isEmpty()) {
|
||
|
c.setTitles(std::vector<std::string>() << toStdString(addressee.title()));
|
||
|
}
|
||
|
|
||
|
Kolab::Affiliation businessAff;
|
||
|
businessAff.setOrganisation(toStdString(addressee.organization()));
|
||
|
if (!addressee.department().isEmpty()) {
|
||
|
Debug() << addressee.department() << addressee.department().toLatin1() << addressee.department().toUtf8();
|
||
|
businessAff.setOrganisationalUnits(std::vector<std::string>() << toStdString(addressee.department()));
|
||
|
}
|
||
|
|
||
|
if (!addressee.logo().isEmpty()) {
|
||
|
std::string logoMimetype;
|
||
|
const std::string &logo = fromPicture(addressee.logo(), logoMimetype);
|
||
|
businessAff.setLogo(logo, logoMimetype);
|
||
|
}
|
||
|
if (!addressee.role().isEmpty()) {
|
||
|
businessAff.setRoles(std::vector<std::string>() << toStdString(addressee.role()));
|
||
|
}
|
||
|
const QString &office = addressee.custom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-Office"));
|
||
|
if (!office.isEmpty()) {
|
||
|
Kolab::Address a;
|
||
|
a.setTypes(Kolab::Address::Work);
|
||
|
a.setLabel(toStdString(addressee.custom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-Office"))));
|
||
|
businessAff.setAddresses(std::vector<Kolab::Address>() << a);
|
||
|
}
|
||
|
|
||
|
std::vector<Kolab::Related> relateds;
|
||
|
const QString &manager = addressee.custom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-ManagersName"));
|
||
|
if (!manager.isEmpty()) {
|
||
|
relateds.push_back(Kolab::Related(Kolab::Related::Text, toStdString(manager), Kolab::Related::Manager));
|
||
|
}
|
||
|
const QString &assistant = addressee.custom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-AssistantsName"));
|
||
|
if (!assistant.isEmpty()) {
|
||
|
relateds.push_back(Kolab::Related(Kolab::Related::Text, toStdString(assistant), Kolab::Related::Assistant));
|
||
|
}
|
||
|
if (!relateds.empty()) {
|
||
|
businessAff.setRelateds(relateds);
|
||
|
}
|
||
|
if (!(businessAff == Kolab::Affiliation())) {
|
||
|
c.setAffiliations(std::vector<Kolab::Affiliation>() << businessAff);
|
||
|
}
|
||
|
|
||
|
std::vector<Kolab::Url> urls;
|
||
|
- if (!addressee.url().isEmpty()) {
|
||
|
- urls.push_back(Kolab::Url(toStdString(addressee.url().url())));
|
||
|
+ if (!addressee.url().url().isEmpty()) {
|
||
|
+ urls.push_back(Kolab::Url(toStdString(addressee.url().url().url())));
|
||
|
}
|
||
|
const QString &blogUrl = addressee.custom(QLatin1String("KADDRESSBOOK"), QLatin1String("BlogFeed"));
|
||
|
if (!blogUrl.isEmpty()) {
|
||
|
urls.push_back(Kolab::Url(toStdString(blogUrl), Kolab::Url::Blog));
|
||
|
}
|
||
|
c.setUrls(urls);
|
||
|
|
||
|
std::vector<Kolab::Address> addresses;
|
||
|
prefNum = -1;
|
||
|
prefCounter = -1;
|
||
|
foreach(const KContacts::Address &a, addressee.addresses()) {
|
||
|
Kolab::Address adr;
|
||
|
bool pref = false;
|
||
|
adr.setTypes(fromAddressType(a.type(), pref));
|
||
|
prefCounter++;
|
||
|
if (pref) {
|
||
|
prefNum = prefCounter;
|
||
|
}
|
||
|
adr.setLabel(toStdString(a.label()));
|
||
|
adr.setStreet(toStdString(a.street()));
|
||
|
adr.setLocality(toStdString(a.locality()));
|
||
|
adr.setRegion(toStdString(a.region()));
|
||
|
adr.setCode(toStdString(a.postalCode()));
|
||
|
adr.setCountry(toStdString(a.country()));
|
||
|
addresses.push_back(adr);
|
||
|
}
|
||
|
c.setAddresses(addresses, prefNum);
|
||
|
|
||
|
if (!addressee.nickName().isEmpty()) {
|
||
|
c.setNickNames(std::vector<std::string>() << toStdString(addressee.nickName()));
|
||
|
}
|
||
|
|
||
|
const QString &spouse = addressee.custom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-SpousesName"));
|
||
|
if (!spouse.isEmpty()) {
|
||
|
c.setRelateds(std::vector<Kolab::Related>() << Kolab::Related(Kolab::Related::Text, toStdString(spouse), Kolab::Related::Spouse));
|
||
|
}
|
||
|
c.setBDay(fromDate(KDateTime(addressee.birthday(), KDateTime::ClockTime)));
|
||
|
- c.setAnniversary(fromDate(KDateTime(QDate::fromString( addressee.custom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-Anniversary")), Qt::ISODate ), KDateTime::ClockTime)));
|
||
|
+ c.setAnniversary(fromDate(KDateTime(QDate::fromString( addressee.custom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-Anniversary")), Qt::ISODate ), KDateTime::Spec(KDateTime::ClockTime))));
|
||
|
if (!addressee.photo().isEmpty()) {
|
||
|
std::string mimetype;
|
||
|
const std::string &photo = fromPicture(addressee.photo(), mimetype);
|
||
|
c.setPhoto(photo, mimetype);
|
||
|
}
|
||
|
//TODO
|
||
|
// c.setGender();
|
||
|
// c.setLanguages();
|
||
|
|
||
|
std::vector <Kolab::Telephone> phones;
|
||
|
prefNum = -1;
|
||
|
prefCounter = -1;
|
||
|
foreach (const KContacts::PhoneNumber &n, addressee.phoneNumbers()) {
|
||
|
Kolab::Telephone p;
|
||
|
p.setNumber(toStdString(n.number()));
|
||
|
bool pref = false;
|
||
|
p.setTypes(fromPhoneType(n.type(), pref));
|
||
|
prefCounter++;
|
||
|
if (pref) {
|
||
|
prefNum = prefCounter;
|
||
|
}
|
||
|
phones.push_back(p);
|
||
|
}
|
||
|
c.setTelephones(phones, prefNum);
|
||
|
|
||
|
const QString &imAddress = addressee.custom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-IMAddress"));
|
||
|
if (!imAddress.isEmpty()) {
|
||
|
c.setIMaddresses(std::vector<std::string>() << toStdString(imAddress), 0);
|
||
|
}
|
||
|
|
||
|
int prefEmail = -1;
|
||
|
int count = 0;
|
||
|
std::vector<Kolab::Email> emails;
|
||
|
foreach(const QString &e, addressee.emails()) {
|
||
|
if ((prefEmail == -1) && (e == addressee.preferredEmail())) {
|
||
|
prefEmail = count;
|
||
|
}
|
||
|
count++;
|
||
|
emails.push_back(Kolab::Email(toStdString(e), emailTypesFromStringlist(addressee.custom(QLatin1String("KOLAB"), QString::fromLatin1("EmailTypes%1").arg(e)))));
|
||
|
}
|
||
|
c.setEmailAddresses(emails, prefEmail);
|
||
|
if (addressee.geo().isValid()) {
|
||
|
c.setGPSpos(std::vector<Kolab::Geo>() << Kolab::Geo(addressee.geo().latitude(), addressee.geo().longitude()));
|
||
|
}
|
||
|
|
||
|
Kolab::Crypto crypto;
|
||
|
|
||
|
const QStringList protocolPrefs = addressee.custom( "KADDRESSBOOK", "CRYPTOPROTOPREF" ).split( ',', QString::SkipEmptyParts );
|
||
|
const uint cryptoFormats = stringListToCryptoMessageFormats( protocolPrefs );
|
||
|
int formats = 0;
|
||
|
if (cryptoFormats & InlineOpenPGPFormat) {
|
||
|
formats |= Kolab::Crypto::PGPinline;
|
||
|
}
|
||
|
if (cryptoFormats & OpenPGPMIMEFormat) {
|
||
|
formats |= Kolab::Crypto::PGPmime;
|
||
|
}
|
||
|
if (cryptoFormats & SMIMEFormat) {
|
||
|
formats |= Kolab::Crypto::SMIME;
|
||
|
}
|
||
|
if (cryptoFormats & SMIMEOpaqueFormat) {
|
||
|
formats |= Kolab::Crypto::SMIMEopaque;
|
||
|
}
|
||
|
crypto.setAllowed(formats);
|
||
|
|
||
|
Kolab::Crypto::CryptoPref signPref = Kolab::Crypto::Ask;
|
||
|
switch (stringToSigningPreference(addressee.custom( "KADDRESSBOOK", "CRYPTOSIGNPREF" ) )) {
|
||
|
case NeverSign:
|
||
|
signPref = Kolab::Crypto::Never;
|
||
|
break;
|
||
|
case AlwaysSign:
|
||
|
signPref = Kolab::Crypto::Always;
|
||
|
break;
|
||
|
case AlwaysSignIfPossible:
|
||
|
signPref = Kolab::Crypto::IfPossible;
|
||
|
break;
|
||
|
case AlwaysAskForSigning:
|
||
|
case AskSigningWheneverPossible:
|
||
|
signPref = Kolab::Crypto::Ask;
|
||
|
break;
|
||
|
default:
|
||
|
signPref = Kolab::Crypto::Ask;
|
||
|
}
|
||
|
crypto.setSignPref(signPref);
|
||
|
|
||
|
Kolab::Crypto::CryptoPref encryptPref = Kolab::Crypto::Ask;
|
||
|
switch (stringToSigningPreference(addressee.custom( "KADDRESSBOOK", "CRYPTOENCRYPTPREF" ) )) {
|
||
|
case NeverEncrypt:
|
||
|
encryptPref = Kolab::Crypto::Never;
|
||
|
break;
|
||
|
case AlwaysEncrypt:
|
||
|
encryptPref = Kolab::Crypto::Always;
|
||
|
break;
|
||
|
case AlwaysEncryptIfPossible:
|
||
|
encryptPref = Kolab::Crypto::IfPossible;
|
||
|
break;
|
||
|
case AlwaysAskForEncryption:
|
||
|
case AskWheneverPossible:
|
||
|
encryptPref = Kolab::Crypto::Ask;
|
||
|
break;
|
||
|
default:
|
||
|
encryptPref = Kolab::Crypto::Ask;
|
||
|
}
|
||
|
crypto.setEncryptPref(encryptPref);
|
||
|
|
||
|
c.setCrypto(crypto);
|
||
|
|
||
|
|
||
|
//FIXME the keys are most certainly worng, look at cryptopageplugin.cpp
|
||
|
std::vector<Kolab::Key> keys;
|
||
|
const std::string &pgpkey = toStdString(addressee.custom( "KADDRESSBOOK", "OPENPGPFP" ));
|
||
|
if (!pgpkey.empty()) {
|
||
|
keys.push_back(Kolab::Key(pgpkey, Kolab::Key::PGP));
|
||
|
}
|
||
|
const std::string &smimekey = toStdString(addressee.custom( "KADDRESSBOOK", "SMIMEFP" ));
|
||
|
if (!smimekey.empty()) {
|
||
|
keys.push_back(Kolab::Key(smimekey, Kolab::Key::PKCS7_MIME));
|
||
|
}
|
||
|
c.setKeys(keys);
|
||
|
|
||
|
|
||
|
if (!addressee.sound().isEmpty()) {
|
||
|
Warning() << "sound is not supported";
|
||
|
}
|
||
|
|
||
|
const std::string &profession = toStdString(addressee.custom( "KADDRESSBOOK", "X-Profession" ));
|
||
|
if (!profession.empty()) {
|
||
|
setCustom(profession, "X-Profession", c);
|
||
|
}
|
||
|
|
||
|
const std::string &adrBook = toStdString(addressee.custom( "KADDRESSBOOK", "X-AddressBook" ));
|
||
|
if (!adrBook.empty()) {
|
||
|
setCustom(adrBook, "X-AddressBook", c);
|
||
|
}
|
||
|
|
||
|
//TODO preserve all custom properties (also such which are unknown to us)
|
||
|
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
DistList fromKABC(const KContacts::ContactGroup &cg)
|
||
|
{
|
||
|
DistList dl;
|
||
|
dl.setName(toStdString(cg.name()));
|
||
|
dl.setUid(toStdString(cg.id()));
|
||
|
|
||
|
std::vector <Kolab::ContactReference > members;
|
||
|
for (unsigned int i = 0; i < cg.dataCount(); i++) {
|
||
|
const KContacts::ContactGroup::Data &data = cg.data(i);
|
||
|
members.push_back(Kolab::ContactReference(Kolab::ContactReference::EmailReference, toStdString(data.email()), toStdString(data.name())));
|
||
|
}
|
||
|
for (unsigned int i = 0; i < cg.contactReferenceCount(); i++) {
|
||
|
const KContacts::ContactGroup::ContactReference &ref = cg.contactReference(i);
|
||
|
members.push_back(Kolab::ContactReference(Kolab::ContactReference::UidReference, toStdString(ref.uid())));
|
||
|
}
|
||
|
|
||
|
if (cg.contactGroupReferenceCount() > 0) {
|
||
|
qWarning() << "Tried to save contact group references, which should have been resolved already";
|
||
|
}
|
||
|
|
||
|
dl.setMembers(members);
|
||
|
|
||
|
return dl;
|
||
|
}
|
||
|
|
||
|
KContacts::ContactGroup toKABC(const DistList &dl)
|
||
|
{
|
||
|
KContacts::ContactGroup cg(fromStdString(dl.name()));
|
||
|
cg.setId(fromStdString(dl.uid()));
|
||
|
foreach(const Kolab::ContactReference &m, dl.members()) {
|
||
|
switch (m.type()) {
|
||
|
case Kolab::ContactReference::EmailReference:
|
||
|
cg.append(KContacts::ContactGroup::Data(fromStdString(m.name()), fromStdString(m.email())));
|
||
|
break;
|
||
|
case Kolab::ContactReference::UidReference:
|
||
|
cg.append(KContacts::ContactGroup::ContactReference(fromStdString(m.uid())));
|
||
|
break;
|
||
|
default:
|
||
|
Error() << "invalid contact reference";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return cg;
|
||
|
}
|
||
|
|
||
|
|
||
|
} //Namespace
|
||
|
} //Namespace
|
||
|
diff --git a/kolabformatV2/contact.cpp b/kolabformatV2/contact.cpp
|
||
|
index d125bd1..af95cff 100644
|
||
|
--- a/kolabformatV2/contact.cpp
|
||
|
+++ b/kolabformatV2/contact.cpp
|
||
|
@@ -1,1214 +1,1217 @@
|
||
|
/*
|
||
|
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 Qt library by Trolltech AS, Norway (or with modified versions
|
||
|
of Qt that use the same license as Qt), 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
|
||
|
Qt. 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 <kcontacts/addressee.h>
|
||
|
#include <QFile>
|
||
|
#include <QDebug>
|
||
|
#include <float.h>
|
||
|
|
||
|
using namespace KolabV2;
|
||
|
|
||
|
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 KContacts::Addressee* addr )
|
||
|
: mHasGeo( false )
|
||
|
{
|
||
|
setFields( addr );
|
||
|
}
|
||
|
|
||
|
// loading (xml->addressee)
|
||
|
Contact::Contact( const QString& xml )
|
||
|
: mHasGeo( false )
|
||
|
{
|
||
|
load( xml );
|
||
|
}
|
||
|
|
||
|
Contact::~Contact()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void Contact::setGivenName( const QString& name )
|
||
|
{
|
||
|
mGivenName = name;
|
||
|
}
|
||
|
|
||
|
QString Contact::givenName() const
|
||
|
{
|
||
|
return mGivenName;
|
||
|
}
|
||
|
|
||
|
void Contact::setMiddleNames( const QString& names )
|
||
|
{
|
||
|
mMiddleNames = names;
|
||
|
}
|
||
|
|
||
|
QString Contact::middleNames() const
|
||
|
{
|
||
|
return mMiddleNames;
|
||
|
}
|
||
|
|
||
|
void Contact::setLastName( const QString& name )
|
||
|
{
|
||
|
mLastName = name;
|
||
|
}
|
||
|
|
||
|
QString Contact::lastName() const
|
||
|
{
|
||
|
return mLastName;
|
||
|
}
|
||
|
|
||
|
void Contact::setFullName( const QString& name )
|
||
|
{
|
||
|
mFullName = name;
|
||
|
}
|
||
|
|
||
|
QString Contact::fullName() const
|
||
|
{
|
||
|
return mFullName;
|
||
|
}
|
||
|
|
||
|
void Contact::setInitials( const QString& initials )
|
||
|
{
|
||
|
mInitials = initials;
|
||
|
}
|
||
|
|
||
|
QString Contact::initials() const
|
||
|
{
|
||
|
return mInitials;
|
||
|
}
|
||
|
|
||
|
void Contact::setPrefix( const QString& prefix )
|
||
|
{
|
||
|
mPrefix = prefix;
|
||
|
}
|
||
|
|
||
|
QString Contact::prefix() const
|
||
|
{
|
||
|
return mPrefix;
|
||
|
}
|
||
|
|
||
|
void Contact::setSuffix( const QString& suffix )
|
||
|
{
|
||
|
mSuffix = suffix;
|
||
|
}
|
||
|
|
||
|
QString Contact::suffix() const
|
||
|
{
|
||
|
return mSuffix;
|
||
|
}
|
||
|
|
||
|
void Contact::setRole( const QString& role )
|
||
|
{
|
||
|
mRole = role;
|
||
|
}
|
||
|
|
||
|
QString Contact::role() const
|
||
|
{
|
||
|
return mRole;
|
||
|
}
|
||
|
|
||
|
void Contact::setFreeBusyUrl( const QString& fbUrl )
|
||
|
{
|
||
|
mFreeBusyUrl = fbUrl;
|
||
|
}
|
||
|
|
||
|
QString Contact::freeBusyUrl() const
|
||
|
{
|
||
|
return mFreeBusyUrl;
|
||
|
}
|
||
|
|
||
|
void Contact::setOrganization( const QString& organization )
|
||
|
{
|
||
|
mOrganization = organization;
|
||
|
}
|
||
|
|
||
|
QString Contact::organization() const
|
||
|
{
|
||
|
return mOrganization;
|
||
|
}
|
||
|
|
||
|
void Contact::setWebPage( const QString& url )
|
||
|
{
|
||
|
mWebPage = url;
|
||
|
}
|
||
|
|
||
|
QString Contact::webPage() const
|
||
|
{
|
||
|
return mWebPage;
|
||
|
}
|
||
|
|
||
|
void Contact::setIMAddress( const QString& imAddress )
|
||
|
{
|
||
|
mIMAddress = imAddress;
|
||
|
}
|
||
|
|
||
|
QString Contact::imAddress() const
|
||
|
{
|
||
|
return mIMAddress;
|
||
|
}
|
||
|
|
||
|
void Contact::setDepartment( const QString& department )
|
||
|
{
|
||
|
mDepartment = department;
|
||
|
}
|
||
|
|
||
|
QString Contact::department() const
|
||
|
{
|
||
|
return mDepartment;
|
||
|
}
|
||
|
|
||
|
void Contact::setOfficeLocation( const QString& location )
|
||
|
{
|
||
|
mOfficeLocation = location;
|
||
|
}
|
||
|
|
||
|
QString Contact::officeLocation() const
|
||
|
{
|
||
|
return mOfficeLocation;
|
||
|
}
|
||
|
|
||
|
void Contact::setProfession( const QString& profession )
|
||
|
{
|
||
|
mProfession = profession;
|
||
|
}
|
||
|
|
||
|
QString Contact::profession() const
|
||
|
{
|
||
|
return mProfession;
|
||
|
}
|
||
|
|
||
|
void Contact::setTitle( const QString& title )
|
||
|
{
|
||
|
mTitle = title;
|
||
|
}
|
||
|
|
||
|
QString Contact::title() const
|
||
|
{
|
||
|
return mTitle;
|
||
|
}
|
||
|
|
||
|
void Contact::setManagerName( const QString& name )
|
||
|
{
|
||
|
mManagerName = name;
|
||
|
}
|
||
|
|
||
|
QString Contact::managerName() const
|
||
|
{
|
||
|
return mManagerName;
|
||
|
}
|
||
|
|
||
|
void Contact::setAssistant( const QString& name )
|
||
|
{
|
||
|
mAssistant = name;
|
||
|
}
|
||
|
|
||
|
QString Contact::assistant() const
|
||
|
{
|
||
|
return mAssistant;
|
||
|
}
|
||
|
|
||
|
void Contact::setNickName( const QString& name )
|
||
|
{
|
||
|
mNickName = name;
|
||
|
}
|
||
|
|
||
|
QString Contact::nickName() const
|
||
|
{
|
||
|
return mNickName;
|
||
|
}
|
||
|
|
||
|
void Contact::setSpouseName( const QString& name )
|
||
|
{
|
||
|
mSpouseName = name;
|
||
|
}
|
||
|
|
||
|
QString Contact::spouseName() const
|
||
|
{
|
||
|
return mSpouseName;
|
||
|
}
|
||
|
|
||
|
void Contact::setBirthday( const QDate& date )
|
||
|
{
|
||
|
mBirthday = date;
|
||
|
}
|
||
|
|
||
|
QDate Contact::birthday() const
|
||
|
{
|
||
|
return mBirthday;
|
||
|
}
|
||
|
|
||
|
void Contact::setAnniversary( const QDate& date )
|
||
|
{
|
||
|
mAnniversary = date;
|
||
|
}
|
||
|
|
||
|
QDate Contact::anniversary() const
|
||
|
{
|
||
|
return mAnniversary;
|
||
|
}
|
||
|
|
||
|
void Contact::setChildren( const QString& children )
|
||
|
{
|
||
|
mChildren = children;
|
||
|
}
|
||
|
|
||
|
QString Contact::children() const
|
||
|
{
|
||
|
return mChildren;
|
||
|
}
|
||
|
|
||
|
void Contact::setGender( const QString& gender )
|
||
|
{
|
||
|
mGender = gender;
|
||
|
}
|
||
|
|
||
|
QString Contact::gender() const
|
||
|
{
|
||
|
return mGender;
|
||
|
}
|
||
|
|
||
|
void Contact::setLanguage( const QString& language )
|
||
|
{
|
||
|
mLanguage = language;
|
||
|
}
|
||
|
|
||
|
QString Contact::language() const
|
||
|
{
|
||
|
return mLanguage;
|
||
|
}
|
||
|
|
||
|
void Contact::addPhoneNumber( const PhoneNumber& number )
|
||
|
{
|
||
|
mPhoneNumbers.append( number );
|
||
|
}
|
||
|
|
||
|
QList<Contact::PhoneNumber>& Contact::phoneNumbers()
|
||
|
{
|
||
|
return mPhoneNumbers;
|
||
|
}
|
||
|
|
||
|
const QList<Contact::PhoneNumber>& Contact::phoneNumbers() const
|
||
|
{
|
||
|
return mPhoneNumbers;
|
||
|
}
|
||
|
|
||
|
void Contact::addEmail( const Email& email )
|
||
|
{
|
||
|
mEmails.append( email );
|
||
|
}
|
||
|
|
||
|
QList<Contact::Email>& Contact::emails()
|
||
|
{
|
||
|
return mEmails;
|
||
|
}
|
||
|
|
||
|
QString Contact::fullEmail() const
|
||
|
{
|
||
|
return mFullEmail;
|
||
|
}
|
||
|
|
||
|
const QList<Contact::Email>& Contact::emails() const
|
||
|
{
|
||
|
return mEmails;
|
||
|
}
|
||
|
|
||
|
void Contact::addAddress( const Contact::Address& address )
|
||
|
{
|
||
|
mAddresses.append( address );
|
||
|
}
|
||
|
|
||
|
QList<Contact::Address>& Contact::addresses()
|
||
|
{
|
||
|
return mAddresses;
|
||
|
}
|
||
|
|
||
|
const QList<Contact::Address>& Contact::addresses() const
|
||
|
{
|
||
|
return mAddresses;
|
||
|
}
|
||
|
|
||
|
void Contact::setPreferredAddress( const QString& address )
|
||
|
{
|
||
|
mPreferredAddress = address;
|
||
|
}
|
||
|
|
||
|
QString Contact::preferredAddress() const
|
||
|
{
|
||
|
return mPreferredAddress;
|
||
|
}
|
||
|
|
||
|
bool Contact::loadNameAttribute( QDomElement& element )
|
||
|
{
|
||
|
for ( QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
|
||
|
if ( n.isComment() )
|
||
|
continue;
|
||
|
if ( n.isElement() ) {
|
||
|
QDomElement e = n.toElement();
|
||
|
QString 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
|
||
|
qDebug() <<"Warning: Unhandled tag" << e.tagName();
|
||
|
} else
|
||
|
qDebug() <<"Node is not a comment or an element???";
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void Contact::saveNameAttribute( QDomElement& element ) const
|
||
|
{
|
||
|
QDomElement 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( QDomElement& element )
|
||
|
{
|
||
|
PhoneNumber number;
|
||
|
for ( QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
|
||
|
if ( n.isComment() )
|
||
|
continue;
|
||
|
if ( n.isElement() ) {
|
||
|
QDomElement e = n.toElement();
|
||
|
QString 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
|
||
|
qDebug() <<"Warning: Unhandled tag" << e.tagName();
|
||
|
} else
|
||
|
qDebug() <<"Node is not a comment or an element???";
|
||
|
}
|
||
|
|
||
|
addPhoneNumber( number );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void Contact::savePhoneAttributes( QDomElement& element ) const
|
||
|
{
|
||
|
QList<PhoneNumber>::ConstIterator it = mPhoneNumbers.constBegin();
|
||
|
for ( ; it != mPhoneNumbers.constEnd(); ++it ) {
|
||
|
QDomElement 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( QDomElement& element ) const
|
||
|
{
|
||
|
QList<Email>::ConstIterator it = mEmails.constBegin();
|
||
|
for ( ; it != mEmails.constEnd(); ++it )
|
||
|
saveEmailAttribute( element, *it );
|
||
|
}
|
||
|
|
||
|
void Contact::loadCustomAttributes( QDomElement& element )
|
||
|
{
|
||
|
Custom custom;
|
||
|
custom.app = element.attribute( "app" );
|
||
|
custom.name = element.attribute( "name" );
|
||
|
custom.value = element.attribute( "value" );
|
||
|
mCustomList.append( custom );
|
||
|
}
|
||
|
|
||
|
void Contact::saveCustomAttributes( QDomElement& element ) const
|
||
|
{
|
||
|
QList<Custom>::ConstIterator it = mCustomList.constBegin();
|
||
|
for ( ; it != mCustomList.constEnd(); ++it ) {
|
||
|
Q_ASSERT( !(*it).name.isEmpty() );
|
||
|
if ( (*it).app == s_unhandledTagAppName ) {
|
||
|
writeString( element, (*it).name, (*it).value );
|
||
|
} else {
|
||
|
// Let's use attributes so that other tag-preserving-code doesn't need sub-elements
|
||
|
QDomElement 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( QDomElement& element )
|
||
|
{
|
||
|
Address address;
|
||
|
|
||
|
for ( QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
|
||
|
if ( n.isComment() )
|
||
|
continue;
|
||
|
if ( n.isElement() ) {
|
||
|
QDomElement e = n.toElement();
|
||
|
QString 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
|
||
|
qDebug() <<"Warning: Unhandled tag" << e.tagName();
|
||
|
} else
|
||
|
qDebug() <<"Node is not a comment or an element???";
|
||
|
}
|
||
|
|
||
|
addAddress( address );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void Contact::saveAddressAttributes( QDomElement& element ) const
|
||
|
{
|
||
|
QList<Address>::ConstIterator it = mAddresses.constBegin();
|
||
|
for ( ; it != mAddresses.constEnd(); ++it ) {
|
||
|
QDomElement e = element.ownerDocument().createElement( "address" );
|
||
|
element.appendChild( e );
|
||
|
const Address& a = *it;
|
||
|
writeString( e, "type", a.type );
|
||
|
writeString( e, "x-kde-type", QString::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 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool Contact::loadAttribute( QDomElement& element )
|
||
|
{
|
||
|
const QString tagName = element.tagName();
|
||
|
switch ( tagName[0].toLatin1() ) {
|
||
|
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;
|
||
|
}
|
||
|
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
|
||
|
setTitle( 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;
|
||
|
}
|
||
|
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;
|
||
|
}
|
||
|
if ( tagName == "x-title" ) {
|
||
|
setTitle( element.text() );
|
||
|
return true;
|
||
|
}
|
||
|
break;
|
||
|
case 'w':
|
||
|
if ( tagName == "web-page" ) {
|
||
|
setWebPage( element.text() );
|
||
|
return true;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
return KolabBase::loadAttribute( element );
|
||
|
}
|
||
|
|
||
|
bool Contact::saveAttributes( QDomElement& element ) const
|
||
|
{
|
||
|
// Save the base class elements
|
||
|
KolabBase::saveAttributes( element );
|
||
|
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", title() );
|
||
|
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", QString::number( latitude(), 'g', DBL_DIG ) );
|
||
|
writeString( element, "longitude", QString::number( longitude(), 'g', DBL_DIG ) );
|
||
|
}
|
||
|
saveCustomAttributes( element );
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool Contact::loadXML( const QDomDocument& document )
|
||
|
{
|
||
|
QDomElement top = document.documentElement();
|
||
|
|
||
|
if ( top.tagName() != "contact" ) {
|
||
|
qWarning( "XML error: Top tag was %s instead of the expected contact",
|
||
|
top.tagName().toAscii().data() );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
for ( QDomNode n = top.firstChild(); !n.isNull(); n = n.nextSibling() ) {
|
||
|
if ( n.isComment() )
|
||
|
continue;
|
||
|
if ( n.isElement() ) {
|
||
|
QDomElement e = n.toElement();
|
||
|
if ( !loadAttribute( e ) ) {
|
||
|
// Unhandled tag - save for later storage
|
||
|
//qDebug() <<"Saving unhandled tag" << e.tagName();
|
||
|
Custom c;
|
||
|
c.app = s_unhandledTagAppName;
|
||
|
c.name = e.tagName();
|
||
|
c.value = e.text();
|
||
|
mCustomList.append( c );
|
||
|
}
|
||
|
} else
|
||
|
qDebug() <<"Node is not a comment or an element???";
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
QString Contact::saveXML() const
|
||
|
{
|
||
|
QDomDocument document = domTree();
|
||
|
QDomElement element = document.createElement("contact" );
|
||
|
element.setAttribute( "version", "1.0" );
|
||
|
saveAttributes( element );
|
||
|
document.appendChild( element );
|
||
|
return document.toString();
|
||
|
}
|
||
|
|
||
|
static QString addressTypeToString( int /*KContacts::Address::Type*/ type )
|
||
|
{
|
||
|
if ( type & KContacts::Address::Home )
|
||
|
return "home";
|
||
|
if ( type & KContacts::Address::Work )
|
||
|
return "business";
|
||
|
return "other";
|
||
|
}
|
||
|
|
||
|
static int addressTypeFromString( const QString& type )
|
||
|
{
|
||
|
if ( type == "home" )
|
||
|
return KContacts::Address::Home;
|
||
|
if ( type == "business" )
|
||
|
return KContacts::Address::Work;
|
||
|
// well, this shows "other" in the editor, which is what we want...
|
||
|
return KContacts::Address::Dom | KContacts::Address::Intl | KContacts::Address::Postal | KContacts::Address::Parcel;
|
||
|
}
|
||
|
|
||
|
static QStringList phoneTypeToString( KContacts::PhoneNumber::Type 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.
|
||
|
QStringList types;
|
||
|
if ( type & KContacts::PhoneNumber::Fax ) {
|
||
|
if ( type & KContacts::PhoneNumber::Home )
|
||
|
types << "homefax";
|
||
|
else // assume work -- if ( type & KContacts::PhoneNumber::Work )
|
||
|
types << "businessfax";
|
||
|
type = type & ~KContacts::PhoneNumber::Home;
|
||
|
type = type & ~KContacts::PhoneNumber::Work;
|
||
|
}
|
||
|
|
||
|
// To support both "home1" and "home2", map Home+Pref to home1
|
||
|
if ( ( type & KContacts::PhoneNumber::Home ) && ( type & KContacts::PhoneNumber::Pref ) )
|
||
|
{
|
||
|
types << "home1";
|
||
|
type = type & ~KContacts::PhoneNumber::Home;
|
||
|
type = type & ~KContacts::PhoneNumber::Pref;
|
||
|
}
|
||
|
// To support both "business1" and "business2", map Work+Pref to business1
|
||
|
if ( ( type & KContacts::PhoneNumber::Work ) && ( type & KContacts::PhoneNumber::Pref ) )
|
||
|
{
|
||
|
types << "business1";
|
||
|
type = type & ~KContacts::PhoneNumber::Work;
|
||
|
type = type & ~KContacts::PhoneNumber::Pref;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( type & KContacts::PhoneNumber::Home )
|
||
|
types << "home2";
|
||
|
if ( type & KContacts::PhoneNumber::Msg ) // Msg==messaging
|
||
|
types << "company";
|
||
|
if ( type & KContacts::PhoneNumber::Work )
|
||
|
types << "business2";
|
||
|
if ( type & KContacts::PhoneNumber::Pref )
|
||
|
types << "primary";
|
||
|
if ( type & KContacts::PhoneNumber::Voice )
|
||
|
types << "callback"; // ##
|
||
|
if ( type & KContacts::PhoneNumber::Cell )
|
||
|
types << "mobile";
|
||
|
if ( type & KContacts::PhoneNumber::Video )
|
||
|
types << "radio"; // ##
|
||
|
if ( type & KContacts::PhoneNumber::Bbs )
|
||
|
types << "ttytdd";
|
||
|
if ( type & KContacts::PhoneNumber::Modem )
|
||
|
types << "telex"; // #
|
||
|
if ( type & KContacts::PhoneNumber::Car )
|
||
|
types << "car";
|
||
|
if ( type & KContacts::PhoneNumber::Isdn )
|
||
|
types << "isdn";
|
||
|
if ( type & KContacts::PhoneNumber::Pcs )
|
||
|
types << "assistant"; // ## Assistant is e.g. secretary
|
||
|
if ( type & KContacts::PhoneNumber::Pager )
|
||
|
types << "pager";
|
||
|
return types;
|
||
|
}
|
||
|
|
||
|
static KContacts::PhoneNumber::Type phoneTypeFromString( const QString& type )
|
||
|
{
|
||
|
if ( type == "homefax" )
|
||
|
return KContacts::PhoneNumber::Home | KContacts::PhoneNumber::Fax;
|
||
|
if ( type == "businessfax" )
|
||
|
return KContacts::PhoneNumber::Work | KContacts::PhoneNumber::Fax;
|
||
|
if ( type == "business1" )
|
||
|
return KContacts::PhoneNumber::Work | KContacts::PhoneNumber::Pref;
|
||
|
if ( type == "business2" )
|
||
|
return KContacts::PhoneNumber::Work;
|
||
|
if ( type == "home1" )
|
||
|
return KContacts::PhoneNumber::Home | KContacts::PhoneNumber::Pref;
|
||
|
if ( type == "home2" )
|
||
|
return KContacts::PhoneNumber::Home;
|
||
|
if ( type == "company" )
|
||
|
return KContacts::PhoneNumber::Msg;
|
||
|
if ( type == "primary" )
|
||
|
return KContacts::PhoneNumber::Pref;
|
||
|
if ( type == "callback" )
|
||
|
return KContacts::PhoneNumber::Voice;
|
||
|
if ( type == "mobile" )
|
||
|
return KContacts::PhoneNumber::Cell;
|
||
|
if ( type == "radio" )
|
||
|
return KContacts::PhoneNumber::Video;
|
||
|
if ( type == "ttytdd" )
|
||
|
return KContacts::PhoneNumber::Bbs;
|
||
|
if ( type == "telex" )
|
||
|
return KContacts::PhoneNumber::Modem;
|
||
|
if ( type == "car" )
|
||
|
return KContacts::PhoneNumber::Car;
|
||
|
if ( type == "isdn" )
|
||
|
return KContacts::PhoneNumber::Isdn;
|
||
|
if ( type == "assistant" )
|
||
|
return KContacts::PhoneNumber::Pcs;
|
||
|
if ( type == "pager" )
|
||
|
return KContacts::PhoneNumber::Pager;
|
||
|
return KContacts::PhoneNumber::Home; // whatever
|
||
|
}
|
||
|
|
||
|
static const char* s_knownCustomFields[] = {
|
||
|
"X-IMAddress",
|
||
|
"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 KContacts::Addressee* addressee )
|
||
|
{
|
||
|
KolabBase::setFields( addressee );
|
||
|
|
||
|
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() );
|
||
|
+ setWebPage( addressee->url().url().url() );
|
||
|
setIMAddress( addressee->custom( "KADDRESSBOOK", "X-IMAddress" ) );
|
||
|
setDepartment( addressee->department());
|
||
|
setOfficeLocation( addressee->custom( "KADDRESSBOOK", "X-Office" ) );
|
||
|
setProfession( addressee->custom( "KADDRESSBOOK", "X-Profession" ) );
|
||
|
setRole( addressee->role() );
|
||
|
setTitle( 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 QString& anniversary = addressee->custom( "KADDRESSBOOK", "X-Anniversary" );
|
||
|
if ( !anniversary.isEmpty() )
|
||
|
setAnniversary( stringToDate( anniversary ) );
|
||
|
|
||
|
const QStringList emails = addressee->emails();
|
||
|
// Conversion problem here:
|
||
|
// KContacts::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 ( QStringList::ConstIterator it = emails.constBegin(); it != emails.constEnd(); ++it ) {
|
||
|
Email email;
|
||
|
email.displayName = fullName();
|
||
|
email.smtpAddress = *it;
|
||
|
addEmail( email );
|
||
|
}
|
||
|
|
||
|
// save formatted full email for later usage
|
||
|
mFullEmail = addressee->fullEmail();
|
||
|
|
||
|
// Now the real-world addresses
|
||
|
QString preferredAddress = "home";
|
||
|
const KContacts::Address::List addresses = addressee->addresses();
|
||
|
for ( KContacts::Address::List::ConstIterator it = addresses.constBegin() ; it != addresses.constEnd(); ++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 & KContacts::Address::Pref ) {
|
||
|
preferredAddress = address.type; // home, business or other
|
||
|
}
|
||
|
}
|
||
|
setPreferredAddress( preferredAddress );
|
||
|
|
||
|
const KContacts::PhoneNumber::List phones = addressee->phoneNumbers();
|
||
|
for ( KContacts::PhoneNumber::List::ConstIterator it = phones.constBegin(); it != phones.constEnd(); ++it ) {
|
||
|
// Create a tag per phone type set in the bitfield
|
||
|
QStringList types = phoneTypeToString( (*it).type() );
|
||
|
for( QStringList::ConstIterator typit = types.constBegin(); typit != types.constEnd(); ++typit ) {
|
||
|
PhoneNumber phoneNumber;
|
||
|
phoneNumber.type = *typit;
|
||
|
phoneNumber.number = (*it).number();
|
||
|
addPhoneNumber( phoneNumber );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
setPicture( loadPictureFromAddressee( addressee->photo() ), addressee->photo().type() );
|
||
|
mPictureAttachmentName = addressee->custom( "KOLAB", "PictureAttachmentName" );
|
||
|
if ( mPictureAttachmentName.isEmpty() )
|
||
|
mPictureAttachmentName = s_pictureAttachmentName;
|
||
|
|
||
|
setLogo( loadPictureFromAddressee( addressee->logo() ), addressee->logo().type() );
|
||
|
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)
|
||
|
QStringList knownCustoms;
|
||
|
for ( const char** p = s_knownCustomFields; *p; ++p )
|
||
|
knownCustoms << QString::fromLatin1( *p );
|
||
|
QStringList customs = addressee->customs();
|
||
|
for( QStringList::ConstIterator it = customs.constBegin(); it != customs.constEnd(); ++it ) {
|
||
|
// KContacts::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).indexOf( '-' );
|
||
|
if ( pos == -1 ) continue;
|
||
|
QString app = (*it).left( pos );
|
||
|
if ( app == "KOLAB" ) continue;
|
||
|
QString name = (*it).mid( pos + 1 );
|
||
|
pos = name.indexOf( ':' );
|
||
|
if ( pos == -1 ) continue;
|
||
|
QString value = name.mid( pos + 1 );
|
||
|
name = name.left( pos );
|
||
|
if ( !knownCustoms.contains( name ) ) {
|
||
|
//qDebug() <<"app=" << app <<" name=" << name <<" value=" << value;
|
||
|
Custom c;
|
||
|
if ( app != "KADDRESSBOOK" ) // that's the default
|
||
|
c.app = app;
|
||
|
c.name = name;
|
||
|
c.value = value;
|
||
|
mCustomList.append( c );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const QString url = addressee->custom("KOLAB", "FreebusyUrl");
|
||
|
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( KContacts::Addressee* addressee )
|
||
|
{
|
||
|
// TODO: This needs the same set of TODOs as the setFields method
|
||
|
KolabBase::saveTo( addressee );
|
||
|
+ KContacts::ResourceLocatorUrl url;
|
||
|
+
|
||
|
+ url.setUrl(QUrl(webPage()));
|
||
|
|
||
|
addressee->setGivenName( givenName() );
|
||
|
addressee->setAdditionalName( middleNames() );
|
||
|
addressee->setFamilyName( lastName() );
|
||
|
addressee->setFormattedName( fullName() );
|
||
|
addressee->setPrefix( prefix() );
|
||
|
addressee->setSuffix( suffix() );
|
||
|
addressee->setOrganization( organization() );
|
||
|
- addressee->setUrl( QUrl(webPage()) );
|
||
|
+ addressee->setUrl(url);
|
||
|
addressee->insertCustom( "KADDRESSBOOK", "X-IMAddress", imAddress() );
|
||
|
addressee->setDepartment( department() );
|
||
|
addressee->insertCustom( "KADDRESSBOOK", "X-Office", officeLocation() );
|
||
|
addressee->insertCustom( "KADDRESSBOOK", "X-Profession", profession() );
|
||
|
addressee->setRole( role() );
|
||
|
addressee->setTitle( title() );
|
||
|
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( QDateTime( birthday() ) );
|
||
|
|
||
|
if ( anniversary().isValid() )
|
||
|
addressee->insertCustom( "KADDRESSBOOK", "X-Anniversary",
|
||
|
dateToString( anniversary() ) );
|
||
|
else
|
||
|
addressee->removeCustom( "KADDRESSBOOK", "X-Anniversary" );
|
||
|
|
||
|
addressee->insertCustom( "KOLAB", "FreebusyUrl", freeBusyUrl() );
|
||
|
|
||
|
// 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() ) {
|
||
|
KContacts::Picture picture( mPicture );
|
||
|
addressee->setPhoto( picture );
|
||
|
}
|
||
|
// 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() ) {
|
||
|
KContacts::Picture picture( mLogo );
|
||
|
addressee->setLogo( picture );
|
||
|
}
|
||
|
addressee->insertCustom( "KOLAB", "LogoAttachmentName", mLogoAttachmentName );
|
||
|
if ( !mSound.isNull() )
|
||
|
addressee->setSound( KContacts::Sound( mSound ) );
|
||
|
addressee->insertCustom( "KOLAB", "SoundAttachmentName", mSoundAttachmentName );
|
||
|
|
||
|
if ( mHasGeo )
|
||
|
addressee->setGeo( KContacts::Geo( mLatitude, mLongitude ) );
|
||
|
|
||
|
QStringList emailAddresses;
|
||
|
for ( QList<Email>::ConstIterator it = mEmails.constBegin(); it != mEmails.constEnd(); ++it ) {
|
||
|
// we can't do anything with (*it).displayName
|
||
|
emailAddresses.append( (*it).smtpAddress );
|
||
|
}
|
||
|
addressee->setEmails( emailAddresses );
|
||
|
|
||
|
for ( QList<Address>::ConstIterator it = mAddresses.constBegin(); it != mAddresses.constEnd(); ++it ) {
|
||
|
KContacts::Address address;
|
||
|
int type = (*it).kdeAddressType;
|
||
|
if ( type == -1 ) { // no kde-specific type available
|
||
|
type = addressTypeFromString( (*it).type );
|
||
|
if ( (*it).type == mPreferredAddress )
|
||
|
type |= KContacts::Address::Pref;
|
||
|
}
|
||
|
address.setType( static_cast<KContacts::Address::Type>(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 ( QList<PhoneNumber>::ConstIterator it = mPhoneNumbers.constBegin(); it != mPhoneNumbers.constEnd(); ++it ) {
|
||
|
KContacts::PhoneNumber number;
|
||
|
number.setType( phoneTypeFromString( (*it).type ) );
|
||
|
number.setNumber( (*it).number );
|
||
|
addressee->insertPhoneNumber( number );
|
||
|
}
|
||
|
|
||
|
for( QList<Custom>::ConstIterator it = mCustomList.constBegin(); it != mCustomList.constEnd(); ++it ) {
|
||
|
QString app = (*it).app.isEmpty() ? QString::fromLatin1( "KADDRESSBOOK" ) : (*it).app;
|
||
|
addressee->insertCustom( app, (*it).name, (*it).value );
|
||
|
}
|
||
|
//qDebug() << addressee->customs();
|
||
|
}
|
||
|
|
||
|
QImage Contact::loadPictureFromAddressee( const KContacts::Picture& picture )
|
||
|
{
|
||
|
QImage img;
|
||
|
if ( !picture.isIntern() && !picture.url().isEmpty() ) {
|
||
|
QString tmpFile;
|
||
|
qWarning() << "external pictures are currently not supported";
|
||
|
//FIXME add kio support to libcalendaring or use libcurl
|
||
|
// if ( KIO::NetAccess::download( picture.url(), tmpFile, 0 /*no widget known*/ ) ) {
|
||
|
// img.load( tmpFile );
|
||
|
// KIO::NetAccess::removeTempFile( tmpFile );
|
||
|
// }
|
||
|
} else
|
||
|
img = picture.data();
|
||
|
return img;
|
||
|
}
|
||
|
|
||
|
QByteArray KolabV2::Contact::loadSoundFromAddressee( const KContacts::Sound& sound )
|
||
|
{
|
||
|
QByteArray data;
|
||
|
if ( !sound.isIntern() && !sound.url().isEmpty() ) {
|
||
|
QString tmpFile;
|
||
|
// if ( KIO::NetAccess::download( sound.url(), tmpFile, 0 /*no widget known*/ ) ) {
|
||
|
// QFile f( tmpFile );
|
||
|
// if ( f.open( QIODevice::ReadOnly ) ) {
|
||
|
// data = f.readAll();
|
||
|
// f.close();
|
||
|
// }
|
||
|
// KIO::NetAccess::removeTempFile( tmpFile );
|
||
|
// }
|
||
|
} else
|
||
|
data = sound.data();
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
QString KolabV2::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";
|
||
|
}
|