Page MenuHomePhorge

No OneTemporary

Authored By
Unknown
Size
134 KB
Referenced Files
None
Subscribers
None
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0f473d3..2887796 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,178 +1,178 @@
project(Libkolab)
cmake_minimum_required(VERSION 2.6.4)
option( BUILD_TESTS "Build the tests" TRUE )
option( PYTHON_BINDINGS "Build bindings for python" FALSE )
option( PHP_BINDINGS "Build bindings for php" FALSE )
option( USE_LIBCALENDARING "Use libcalendaring" FALSE )
set(Libkolab_MODULE_DIR ${Libkolab_SOURCE_DIR}/cmake/modules)
set(CMAKE_MODULE_PATH ${Libkolab_MODULE_DIR})
# only available from cmake-2.8.0
if(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} GREATER 7)
cmake_policy(SET CMP0012 NEW)
endif()
# only available from cmake-2.8.4
if(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} GREATER 7 AND
${CMAKE_PATCH_VERSION} GREATER 3)
cmake_policy(SET CMP0017 NEW)
endif()
# Versioning
# x.y.z scheme
# Development versions are only x.y
#
# i.e.
# 0.1 (0.1 development version towards 0.1.0)
# 0.1.0 (first release)
# 0.1.1 (patch release for 0.1.0)
# 0.2 (0.2 development version towards 0.2.0)
set(Libkolab_VERSION_MAJOR 0)
set(Libkolab_VERSION_MINOR 3)
# Enable the full x.y.z version only for release versions
# set(Libkolab_VERSION_PATCH 0)
# set(Libkolab_VERSION ${Libkolab_VERSION_MAJOR}.${Libkolab_VERSION_MINOR}.${Libkolab_VERSION_PATCH} )
set(Libkolab_VERSION ${Libkolab_VERSION_MAJOR}.${Libkolab_VERSION_MINOR} )
set(Libkolab_VERSION_STRING ${CMAKE_PROJECT_NAME}-${Libkolab_VERSION})
# set up install directories.
set(LIB_INSTALL_DIR lib CACHE STRING "The directories where to install libraries to")
set(INCLUDE_INSTALL_DIR include CACHE STRING "The directory where to install headers to")
set(INCLUDE_INSTALL_DIR ${INCLUDE_INSTALL_DIR}/kolab)
set(CMAKECONFIG_INSTALL_DIR ${LIB_INSTALL_DIR}/cmake/Libkolab )
include(MacroLogFeature)
# Do the building
find_package(Libkolabxml 0.7 REQUIRED)
macro_log_feature(Libkolabxml_FOUND "Libkolabxml" "Kolab XML Format 3 serializing library" "http://git.kolab.org/libkolabxml/" TRUE "0.7" "Required for reading/writing Kolab XML Objects")
find_package(Qt4 4.6.0 REQUIRED)
if (USE_LIBCALENDARING)
find_package(Libcalendaring)
- macro_log_feature(Libcalendaring_FOUND "Libcalendaring" "KDE Calendaring-Dependencies Library" "http://git.kolab.org/libcalendaring/" TRUE "" "Required if KDE libraries are not available.")
+ macro_log_feature(LIBCALENDARING_FOUND "Libcalendaring" "KDE Calendaring-Dependencies Library" "http://git.kolab.org/libcalendaring/" TRUE "" "Required if KDE libraries are not available.")
else()
find_package(KDE4 4.8 REQUIRED)
find_package(KdepimLibs 4.8 REQUIRED)
endif()
find_package(SWIG)
#Show summary of found libraries
macro_display_feature_log()
# add_definitions(-DKDEPIMLIBS_VERSION=0x${KdepimLibs_VERSION_MAJOR}0${KdepimLibs_VERSION_MINOR}${KDEPIMLIBS_VERSION_PATCH})
# add_definitions( -DKDEPIMLIBS_VERSION=((${KdepimLibs_VERSION_MAJOR}<<16)|(${KdepimLibs_VERSION_MINOR}<<8)|(${KDEPIMLIBS_VERSION_PATCH})) )
if("${KdepimLibs_VERSION}" VERSION_GREATER "4.8.40" OR USE_LIBCALENDARING)
add_definitions(-DKDEPIMLIBS_VERSION_DEVEL)
endif()
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wformat-security -fno-exceptions -DQT_NO_EXCEPTIONS -fno-check-new -fno-common -Woverloaded-virtual -fno-threadsafe-statics -fvisibility=hidden -Werror=return-type -fvisibility-inlines-hidden -fexceptions -UQT_NO_EXCEPTIONS -fPIC -g" )
# message("${CMAKE_CXX_FLAGS}")
if (USE_LIBCALENDARING)
set( KDE_INCLUDES ${Libcalendaring_INCLUDE_DIRS} )
set( KDE_LIBRARIES ${Libcalendaring_LIBRARIES} )
message("${Libcalendaring_INCLUDE_DIRS} ${Libcalendaring_LIBRARIES}")
else()
set( KDE_INCLUDES ${KDEPIMLIBS_INCLUDE_DIRS} ${KDE4_INCLUDE_DIR})
set( KDE_LIBRARIES
${KDEPIMLIBS_KCALCORE_LIBS}
${KDEPIMLIBS_KABC_LIBS}
${KDEPIMLIBS_KMIME_LIBS}
${KDEPIMLIBS_AKONADI_LIBS}
${KDEPIMLIBS_AKONADI_NOTES_LIBS}
${KDEPIMLIBS_KCALUTILS_LIBS}
${KDEPIMLIBS_KPIMUTILS_LIBS}
${KDE4_KDECORE_LIBRARY}
${KDE4_KIO_LIBRARY}
)
endif()
include_directories(
${QT_INCLUDES}
${KDE_INCLUDES}
${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/kolabformatV2
${Libkolabxml_INCLUDES}
./
)
configure_file(libkolab-version.h.cmake "${CMAKE_BINARY_DIR}/libkolab-version.h" @ONLY)
add_subdirectory(kolabformatV2)
add_subdirectory(conversion)
add_subdirectory(calendaring)
add_subdirectory(icalendar)
add_subdirectory(freebusy)
QT4_WRAP_CPP(CALENDARING_MOC calendaring/event.h)
# QT4_WRAP_CPP(CONVERSION_MOC conversion/qtevent.h conversion/qtduration.h)
set(KOLAB_SRCS
kolabformat/kolabobject.cpp
kolabformat/formathelpers.cpp
kolabformat/errorhandler.cpp
mime/mimeutils.cpp
${CONVERSION_SRCS}
${kolabformatv2_SRCS}
${CALENDARING_SRCS}
${ICALENDAR_SRCS}
${CALENDARING_MOC}
${CONVERSION_MOC}
${FREEBUSY_SRCS}
)
set(KOLAB_LINK_LIBRARIES
${Libkolabxml_LIBRARIES}
${QT_QTCORE_LIBRARY}
${QT_QTXML_LIBRARY}
${QT_QTGUI_LIBRARY}
${KDE_LIBRARIES}
)
if(BUILD_TESTS)
#for tests only
add_library(kolab_static STATIC ${KOLAB_SRCS})
target_link_libraries(kolab_static ${KOLAB_LINK_LIBRARIES})
add_subdirectory(tests)
endif(BUILD_TESTS)
add_library(kolab SHARED ${KOLAB_SRCS})
target_link_libraries(kolab ${KOLAB_LINK_LIBRARIES})
set_target_properties(kolab PROPERTIES VERSION ${Libkolab_VERSION}
SOVERSION ${Libkolab_VERSION_MAJOR} )
install(TARGETS kolab EXPORT LibkolabExport
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
)
install(FILES
kolab_export.h
kolabformat/kolabdefinitions.h
kolabformat/formathelpers.h
kolabformat/kolabobject.h
kolabformat/errorhandler.h
conversion/kcalconversion.h
conversion/kabcconversion.h
conversion/commonconversion.h
freebusy/freebusy.h
DESTINATION ${INCLUDE_INSTALL_DIR}
)
install(EXPORT LibkolabExport DESTINATION ${CMAKECONFIG_INSTALL_DIR} FILE LibkolabTargets.cmake )
file(RELATIVE_PATH relInstallDir ${CMAKE_INSTALL_PREFIX}/${CMAKECONFIG_INSTALL_DIR} ${CMAKE_INSTALL_PREFIX} )
configure_file(${Libkolab_MODULE_DIR}/LibkolabConfig.cmake.in ${Libkolab_BINARY_DIR}/LibkolabConfig.cmake @ONLY )
configure_file(${Libkolab_MODULE_DIR}/LibkolabConfigVersion.cmake.in ${Libkolab_BINARY_DIR}/LibkolabConfigVersion.cmake @ONLY )
# Install these two files into the same directory as the generated exports-file.
install(FILES ${Libkolab_BINARY_DIR}/LibkolabConfig.cmake ${Libkolab_BINARY_DIR}/LibkolabConfigVersion.cmake
DESTINATION ${CMAKECONFIG_INSTALL_DIR} )
diff --git a/conversion/commonconversion.cpp b/conversion/commonconversion.cpp
index 60128f3..41deb9a 100644
--- a/conversion/commonconversion.cpp
+++ b/conversion/commonconversion.cpp
@@ -1,156 +1,156 @@
/*
* Copyright (C) 2012 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 "commonconversion.h"
#include <kolabformat/errorhandler.h>
#include <iostream>
-#include <KDE/KSystemTimeZones>
-#include <KDE/KDebug>
+#include <ksystemtimezone.h>
+#include <kdebug.h>
#include <QUrl>
namespace Kolab {
namespace Conversion {
KDateTime::Spec getTimeSpec(bool isUtc, const std::string& timezone)
{
if (isUtc) { //UTC
return KDateTime::Spec(KDateTime::UTC);
}
if (timezone.empty()) { //Floating
return KDateTime::Spec(KDateTime::ClockTime);
}
//Timezone
KTimeZone tz = KSystemTimeZones::zone(QString::fromStdString(timezone)); //Needs ktimezoned (timezone daemon running) http://api.kde.org/4.x-api/kdelibs-apidocs/kdecore/html/classKSystemTimeZones.html
if (!tz.isValid()) {
Error() << "timezone not found" << QString::fromStdString(timezone);
if (!KSystemTimeZones::isTimeZoneDaemonAvailable()) {
Error() << "ktimezoned is not available and required for timezone interpretation";
}
tz = KTimeZone::utc(); //Don't crash
}
return KDateTime::Spec(tz);
}
KDateTime toDate(const Kolab::cDateTime &dt)
{
KDateTime date;
if (!dt.isValid()) { //We rely on this codepath, so it's not an error
// qDebug() << "invalid datetime converted";
return KDateTime();
}
if (dt.isDateOnly()) { //Date only
date.setDateOnly(true);
date.setDate(QDate(dt.year(), dt.month(), dt.day()));
date.setTimeSpec(KDateTime::Spec(KDateTime::ClockTime));
} else {
date.setDate(QDate(dt.year(), dt.month(), dt.day()));
date.setTime(QTime(dt.hour(), dt.minute(), dt.second()));
date.setTimeSpec(getTimeSpec(dt.isUTC(), dt.timezone()));
}
Q_ASSERT(date.timeSpec().isValid());
Q_ASSERT(date.isValid());
return date;
}
cDateTime fromDate(const KDateTime &dt)
{
if (!dt.isValid()) {
// qDebug() << "invalid datetime converted";
return cDateTime();
}
cDateTime date;
if (dt.isDateOnly()) { //Date only
const QDate &d = dt.date();
date.setDate(d.year(), d.month(), d.day());
} else {
const QDate &d = dt.date();
date.setDate(d.year(), d.month(), d.day());
const QTime &t = dt.time();
date.setTime(t.hour(), t.minute(), t.second());
if (dt.timeType() == KDateTime::UTC) { //UTC
date.setUTC(true);
} else if (dt.timeType() == KDateTime::TimeZone) { //Timezone
//TODO handle local timezone?
date.setTimezone(dt.timeZone().name().toStdString()); //FIXME use system independent name according to spec
} else if (dt.timeType() != KDateTime::ClockTime) {
Error() << "invalid timespec, assuming floating time" << dt.timeType();
return date;
}
}
Q_ASSERT(date.isValid());
return date;
}
QStringList toStringList(const std::vector<std::string> &l)
{
QStringList list;
foreach(const std::string &s, l) {
list.append(QString::fromStdString(s));
}
return list;
}
std::vector<std::string> fromStringList(const QStringList &l)
{
std::vector<std::string> list;
foreach(const QString &s, l) {
list.push_back(s.toStdString());
}
return list;
}
QUrl toMailto(const std::string &email, const std::string &name)
{
std::string mailto;
if (!name.empty()) {
mailto.append(name);
}
mailto.append("<");
mailto.append(email);
mailto.append(">");
return QUrl(QString::fromStdString(std::string("mailto:")+mailto));
}
std::string fromMailto(const QUrl &mailtoUri, std::string &name)
{
const std::string &decoded = mailtoUri.toString().toStdString();
if (decoded.substr(0, 7).compare("mailto:")) {
WARNING("no mailto address");
std::cout << decoded << std::endl;
return decoded;
}
std::size_t begin = decoded.find('<',7);
if (begin == std::string::npos) {
WARNING("no mailto address");
std::cout << decoded << std::endl;
return decoded;
}
std::size_t end = decoded.find('>', begin);
if (end == std::string::npos) {
WARNING("no mailto address");
std::cout << decoded << std::endl;
return decoded;
}
name = decoded.substr(7, begin-7);
const std::string &email = decoded.substr(begin+1, end-begin-1);
return email;
}
}
}
\ No newline at end of file
diff --git a/conversion/commonconversion.h b/conversion/commonconversion.h
index 559553e..a4b7a71 100644
--- a/conversion/commonconversion.h
+++ b/conversion/commonconversion.h
@@ -1,45 +1,45 @@
/*
* Copyright (C) 2012 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/>.
*/
#ifndef KOLABCOMMONCONVERSION_H
#define KOLABCOMMONCONVERSION_H
#include "kolab_export.h"
-#include <KDE/KDateTime>
+#include <kdatetime.h>
#include <QStringList>
#include <kolabcontainers.h>
namespace Kolab {
namespace Conversion {
KOLAB_EXPORT KDateTime toDate(const Kolab::cDateTime &dt);
KOLAB_EXPORT cDateTime fromDate(const KDateTime &dt);
QStringList toStringList(const std::vector<std::string> &l);
std::vector<std::string> fromStringList(const QStringList &l);
/**
* Returns a UTC, Floating Time or Timezone
*/
KDateTime::Spec getTimeSpec(bool isUtc, const std::string &timezone);
QUrl toMailto(const std::string &email, const std::string &name = std::string());
std::string fromMailto(const QUrl &mailtoUri, std::string &name);
};
};
#endif
\ No newline at end of file
diff --git a/conversion/kabcconversion.cpp b/conversion/kabcconversion.cpp
index b7afce7..d08f264 100644
--- a/conversion/kabcconversion.cpp
+++ b/conversion/kabcconversion.cpp
@@ -1,852 +1,853 @@
/*
* 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 <kcalcore/freebusyurlstore.h>
#include <kdebug.h>
#include <qbuffer.h>
-#include <kio/netaccess.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 & KABC::Address::Dom) {
Warning() << "domestic address is not supported";
}
if (kabcType & KABC::Address::Intl) {
Warning() << "international address is not supported";
}
if (kabcType & KABC::Address::Pref) {
pref = true;
}
if (kabcType & KABC::Address::Postal) {
Warning() << "postal address is not supported";
}
if (kabcType & KABC::Address::Parcel) {
Warning() << "parcel is not supported";
}
if (kabcType & KABC::Address::Home) {
type |= Kolab::Address::Home;
}
if (kabcType & KABC::Address::Work) {
type |= Kolab::Address::Work;
}
return type;
}
KABC::Address::Type toAddressType(int types, bool pref)
{
KABC::Address::Type type = 0;
if (pref) {
type |= KABC::Address::Pref;
}
if (types & Kolab::Address::Home) {
type |= KABC::Address::Home;
}
if (types & Kolab::Address::Work) {
type |= KABC::Address::Work;
}
return type;
}
int fromPhoneType(int kabcType, bool &pref)
{
int type = 0;
if (kabcType & KABC::PhoneNumber::Home) {
type |= Kolab::Telephone::Home;
}
if (kabcType & KABC::PhoneNumber::Work) {
type |= Kolab::Telephone::Work;
}
if (kabcType & KABC::PhoneNumber::Msg) {
type |= Kolab::Telephone::Text;
}
if (kabcType & KABC::PhoneNumber::Pref) {
pref = true;
}
if (kabcType & KABC::PhoneNumber::Voice) {
type |= Kolab::Telephone::Voice;
}
if (kabcType & KABC::PhoneNumber::Fax) {
type |= Kolab::Telephone::Fax;
}
if (kabcType & KABC::PhoneNumber::Cell) {
type |= Kolab::Telephone::Cell;
}
if (kabcType & KABC::PhoneNumber::Video) {
type |= Kolab::Telephone::Video;
}
if (kabcType & KABC::PhoneNumber::Bbs) {
Warning() << "mailbox number is not supported";
}
if (kabcType & KABC::PhoneNumber::Modem) {
Warning() << "modem is not supported";
}
if (kabcType & KABC::PhoneNumber::Car) {
type |= Kolab::Telephone::Car;
}
if (kabcType & KABC::PhoneNumber::Isdn) {
Warning() << "isdn number is not supported";
}
if (kabcType & KABC::PhoneNumber::Pcs) {
type |= Kolab::Telephone::Text;
}
if (kabcType & KABC::PhoneNumber::Pager) {
type |= Kolab::Telephone::Pager;
}
return type;
}
KABC::PhoneNumber::Type toPhoneType(int types, bool pref)
{
KABC::PhoneNumber::Type type = 0;
if (types & Kolab::Telephone::Home) {
type |= KABC::PhoneNumber::Home;
}
if (types & Kolab::Telephone::Work) {
type |= KABC::PhoneNumber::Work;
}
if (types & Kolab::Telephone::Text) {
type |= KABC::PhoneNumber::Msg;
}
if (pref) {
type |= KABC::PhoneNumber::Pref;
}
if (types & Kolab::Telephone::Voice) {
type |= KABC::PhoneNumber::Voice;
}
if (types & Kolab::Telephone::Fax) {
type |= KABC::PhoneNumber::Fax;
}
if (types & Kolab::Telephone::Cell) {
type |= KABC::PhoneNumber::Cell;
}
if (types & Kolab::Telephone::Video) {
type |= KABC::PhoneNumber::Video;
}
if (types & Kolab::Telephone::Car) {
type |= KABC::PhoneNumber::Car;
}
if (types & Kolab::Telephone::Text) {
type |= KABC::PhoneNumber::Pcs;
}
if (types & Kolab::Telephone::Pager) {
type |= KABC::PhoneNumber::Pager;
}
return type;
}
std::string fromPicture(const KABC::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;
+ kWarning() << "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());
}
KABC::Picture toPicture(const std::string &data, const std::string &mimetype) {
QImage img;
if (!img.loadFromData( QByteArray::fromRawData(data.data(), data.size()) )) {
Error() << "failed to load picture";
}
KABC::Picture logo(img);
if (logo.isEmpty()) {
Error() << "failed to read picture";
}
logo.setType(QString::fromStdString(mimetype));
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();
}
KABC::Addressee toKABC(const Kolab::Contact &contact)
{
KABC::Addressee addressee;
addressee.setUid(QString::fromStdString(contact.uid()));
addressee.setCategories(toStringList(contact.categories()));
//addressee.setName(QString::fromStdString(contact.name()));//This one is only for compatiblity (and results in a non-existing name property)
addressee.setFormattedName(QString::fromStdString(contact.name())); //This on corresponds to fn
const Kolab::NameComponents &nc = contact.nameComponents();
if (!nc.surnames().empty()) {
addressee.setFamilyName(QString::fromStdString(nc.surnames().front()));
}
if (!nc.given().empty()) {
addressee.setGivenName(QString::fromStdString(nc.given().front()));
}
if (!nc.additional().empty()) {
addressee.setAdditionalName(QString::fromStdString(nc.additional().front()));
}
if (!nc.prefixes().empty()) {
addressee.setPrefix(QString::fromStdString(nc.prefixes().front()));
}
if (!nc.suffixes().empty()) {
addressee.setSuffix(QString::fromStdString(nc.suffixes().front()));
}
addressee.setNote(QString::fromStdString(contact.note()));
addressee.setSecrecy(KABC::Secrecy::Public); //We don't have any privacy setting in xCard
QString preferredEmail;
if (!contact.emailAddresses().empty()) {
addressee.setEmails(toStringList(contact.emailAddresses()));
if ((contact.emailAddressPreferredIndex() >= 0) && (contact.emailAddressPreferredIndex() < contact.emailAddresses().size())) {
preferredEmail = QString::fromStdString(contact.emailAddresses().at(contact.emailAddressPreferredIndex()));
} else {
preferredEmail = QString::fromStdString(contact.emailAddresses().at(0));
}
addressee.insertEmail(preferredEmail, true);
}
if (!contact.freeBusyUrl().empty()) {
if (preferredEmail.isEmpty()) {
Error() << "f/b url is set but no email address available, skipping";
} else {
KCalCore::FreeBusyUrlStore::self()->writeUrl( preferredEmail, QString::fromStdString(contact.freeBusyUrl()) );
KCalCore::FreeBusyUrlStore::self()->sync();
}
}
if (!contact.nickNames().empty()) {
addressee.setNickName(QString::fromStdString(contact.nickNames().at(0))); //TODO support multiple
}
if (contact.bDay().isValid()) {
addressee.setBirthday(toDate(contact.bDay()).dateTime());
}
if (!contact.titles().empty()) {
addressee.setTitle(QString::fromStdString(contact.titles().at(0))); //TODO support multiple
}
if (!contact.urls().empty()) {
addressee.setUrl(QString::fromStdString(contact.urls().at(0).url())); //TODO support multiple
foreach(const Kolab::Url &u, contact.urls()) {
if (u.type() == Kolab::Url::Blog) {
addressee.insertCustom("KADDRESSBOOK", "BlogFeed", QString::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(QString::fromStdString(aff.organisation()));
}
if (!aff.organisationalUnits().empty()) {
addressee.setDepartment(QString::fromStdString(aff.organisationalUnits().at(0))); //TODO support multiple
}
if (!aff.roles().empty()) {
addressee.setRole(QString::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"), QString::fromStdString(related.text()));
}
if (related.relationTypes() & Kolab::Related::Manager) {
addressee.insertCustom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-ManagersName"), QString::fromStdString(related.text()));
}
}
foreach(const Kolab::Address &address, aff.addresses()) {
addressee.insertCustom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-Office"), QString::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"), QString::fromStdString(prof));
}
const std::string &adrBook = getCustom("X-AddressBook", contact);
if (!adrBook.empty()) {
addressee.insertCustom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-AddressBook"), QString::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;
}
KABC::PhoneNumber number(QString::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;
}
KABC::Address adr(toAddressType(a.types(), pref));
adr.setLabel(QString::fromStdString(a.label()));
adr.setStreet(QString::fromStdString(a.street()));
adr.setLocality(QString::fromStdString(a.locality()));
adr.setRegion(QString::fromStdString(a.region()));
adr.setPostalCode(QString::fromStdString(a.code()));
adr.setCountry(QString::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"),QString::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"),QString::fromStdString(rel.text())); //TODO support multiple
} else {
Warning() << "relation not supported";
continue;
}
}
}
return addressee;
}
Kolab::Contact fromKABC(const KABC::Addressee &addressee)
{
int prefNum = -1;
int prefCounter = -1;
Kolab::Contact c;
c.setUid(addressee.uid().toStdString());
c.setCategories(fromStringList(addressee.categories()));
c.setName(addressee.formattedName().toStdString());
Kolab::NameComponents nc;
nc.setSurnames(std::vector<std::string>() << addressee.familyName().toStdString());
nc.setGiven(std::vector<std::string>() << addressee.givenName().toStdString());
nc.setAdditional(std::vector<std::string>() << addressee.additionalName().toStdString());
nc.setPrefixes(std::vector<std::string>() << addressee.prefix().toStdString());
nc.setSuffixes(std::vector<std::string>() << addressee.suffix().toStdString());
c.setNameComponents(nc);
c.setNote(addressee.note().toStdString());
if ( !addressee.preferredEmail().isEmpty() ) {
c.setFreeBusyUrl(KCalCore::FreeBusyUrlStore::self()->readUrl( addressee.preferredEmail() ).toStdString());
}
if (!addressee.title().isEmpty()) {
c.setTitles(std::vector<std::string>() << addressee.title().toStdString());
}
Kolab::Affiliation businessAff;
businessAff.setOrganisation(addressee.organization().toStdString());
if (!addressee.department().isEmpty()) {
businessAff.setOrganisationalUnits(std::vector<std::string>() << addressee.department().toStdString());
}
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>() << addressee.role().toStdString());
}
const QString &office = addressee.custom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-Office"));
if (!office.isEmpty()) {
Kolab::Address a;
a.setTypes(Kolab::Address::Work);
a.setLabel(addressee.custom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-Office")).toStdString());
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, manager.toStdString(), Kolab::Related::Manager));
}
const QString &assistant = addressee.custom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-AssistantsName"));
if (!assistant.isEmpty()) {
relateds.push_back(Kolab::Related(Kolab::Related::Text, assistant.toStdString(), Kolab::Related::Assistant));
}
if (!relateds.empty()) {
businessAff.setRelateds(relateds);
}
c.setAffiliations(std::vector<Kolab::Affiliation>() << businessAff);
std::vector<Kolab::Url> urls;
if (!addressee.url().isEmpty()) {
urls.push_back(Kolab::Url(addressee.url().url().toStdString()));
}
const QString &blogUrl = addressee.custom(QLatin1String("KADDRESSBOOK"), QLatin1String("BlogFeed"));
if (!blogUrl.isEmpty()) {
urls.push_back(Kolab::Url(blogUrl.toStdString(), Kolab::Url::Blog));
}
c.setUrls(urls);
std::vector<Kolab::Address> addresses;
prefNum = -1;
prefCounter = -1;
foreach(const KABC::Address &a, addressee.addresses()) {
Kolab::Address adr;
bool pref = false;
adr.setTypes(fromAddressType(a.type(), pref));
prefCounter++;
if (pref) {
prefNum = prefCounter;
}
adr.setLabel(a.label().toStdString());
adr.setStreet(a.street().toStdString());
adr.setLocality(a.locality().toStdString());
adr.setRegion(a.region().toStdString());
adr.setCode(a.postalCode().toStdString());
adr.setCountry(a.country().toStdString());
addresses.push_back(adr);
}
c.setAddresses(addresses, prefNum);
if (!addressee.nickName().isEmpty()) {
c.setNickNames(std::vector<std::string>() << addressee.nickName().toStdString());
}
const QString &spouse = addressee.custom(QLatin1String("KADDRESSBOOK"), QLatin1String("X-SpousesName"));
if (!spouse.isEmpty()) {
c.setRelateds(std::vector<Kolab::Related>() << Kolab::Related(Kolab::Related::Text, spouse.toStdString(), 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)));
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 KABC::PhoneNumber &n, addressee.phoneNumbers()) {
Kolab::Telephone p;
p.setNumber(n.number().toStdString());
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>() << imAddress.toStdString(), 0);
}
int prefEmail = -1;
foreach(const QString &e, addressee.emails()) {
prefEmail++;
if (e == addressee.preferredEmail()) {
break;
}
}
c.setEmailAddresses(fromStringList(addressee.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 = addressee.custom( "KADDRESSBOOK", "OPENPGPFP" ).toStdString();
if (!pgpkey.empty()) {
keys.push_back(Kolab::Key(pgpkey, Kolab::Key::PGP));
}
const std::string &smimekey = addressee.custom( "KADDRESSBOOK", "SMIMEFP" ).toStdString();
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 = addressee.custom( "KADDRESSBOOK", "X-Profession" ).toStdString();
if (!profession.empty()) {
setCustom(profession, "X-Profession", c);
}
const std::string &adrBook = addressee.custom( "KADDRESSBOOK", "X-AddressBook" ).toStdString();
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 KABC::ContactGroup &cg)
{
DistList dl;
dl.setName(cg.name().toStdString());
dl.setUid(cg.id().toStdString());
std::vector <Kolab::ContactReference > members;
for (int i = 0; i < cg.dataCount(); i++) {
const KABC::ContactGroup::Data &data = cg.data(i);
members.push_back(Kolab::ContactReference(Kolab::ContactReference::EmailReference, data.email().toStdString(), data.name().toStdString()));
}
for (int i = 0; i < cg.contactReferenceCount(); i++) {
const KABC::ContactGroup::ContactReference &ref = cg.contactReference(i);
members.push_back(Kolab::ContactReference(Kolab::ContactReference::UidReference, ref.uid().toStdString()));
}
if (cg.contactGroupReferenceCount() > 0) {
kWarning() << "Tried to save contact group references, which should have been resolved already";
}
dl.setMembers(members);
return dl;
}
KABC::ContactGroup toKABC(const DistList &dl)
{
KABC::ContactGroup cg(QString::fromStdString(dl.name()));
cg.setId(QString::fromStdString(dl.uid()));
foreach(const Kolab::ContactReference &m, dl.members()) {
KABC::ContactGroup::Data data;
switch (m.type()) {
case Kolab::ContactReference::EmailReference:
cg.append(KABC::ContactGroup::Data(QString::fromStdString(m.name()), QString::fromStdString(m.email())));
break;
case Kolab::ContactReference::UidReference:
cg.append(KABC::ContactGroup::ContactReference(QString::fromStdString(m.uid())));
break;
default:
Error() << "invalid contact reference";
}
}
return cg;
}
} //Namespace
} //Namespace
\ No newline at end of file
diff --git a/kolabformatV2/contact.cpp b/kolabformatV2/contact.cpp
index 7e0e951..9a02b6d 100644
--- a/kolabformatV2/contact.cpp
+++ b/kolabformatV2/contact.cpp
@@ -1,1214 +1,1215 @@
/*
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 <kabc/addressee.h>
#include <kcalcore/freebusyurlstore.h>
-#include <kio/netaccess.h>
#include <kdebug.h>
#include <QFile>
#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 KABC::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
kDebug() <<"Warning: Unhandled tag" << e.tagName();
} else
kDebug() <<"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
kDebug() <<"Warning: Unhandled tag" << e.tagName();
} else
kDebug() <<"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
kDebug() <<"Warning: Unhandled tag" << e.tagName();
} else
kDebug() <<"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
//kDebug() <<"Saving unhandled tag" << e.tagName();
Custom c;
c.app = s_unhandledTagAppName;
c.name = e.tagName();
c.value = e.text();
mCustomList.append( c );
}
} else
kDebug() <<"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 /*KABC::Address::Type*/ type )
{
if ( type & KABC::Address::Home )
return "home";
if ( type & KABC::Address::Work )
return "business";
return "other";
}
static int addressTypeFromString( const QString& type )
{
if ( type == "home" )
return KABC::Address::Home;
if ( type == "business" )
return KABC::Address::Work;
// well, this shows "other" in the editor, which is what we want...
return KABC::Address::Dom | KABC::Address::Intl | KABC::Address::Postal | KABC::Address::Parcel;
}
static QStringList phoneTypeToString( KABC::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 & KABC::PhoneNumber::Fax ) {
if ( type & KABC::PhoneNumber::Home )
types << "homefax";
else // assume work -- if ( type & KABC::PhoneNumber::Work )
types << "businessfax";
type = type & ~KABC::PhoneNumber::Home;
type = type & ~KABC::PhoneNumber::Work;
}
// To support both "home1" and "home2", map Home+Pref to home1
if ( ( type & KABC::PhoneNumber::Home ) && ( type & KABC::PhoneNumber::Pref ) )
{
types << "home1";
type = type & ~KABC::PhoneNumber::Home;
type = type & ~KABC::PhoneNumber::Pref;
}
// To support both "business1" and "business2", map Work+Pref to business1
if ( ( type & KABC::PhoneNumber::Work ) && ( type & KABC::PhoneNumber::Pref ) )
{
types << "business1";
type = type & ~KABC::PhoneNumber::Work;
type = type & ~KABC::PhoneNumber::Pref;
}
if ( type & KABC::PhoneNumber::Home )
types << "home2";
if ( type & KABC::PhoneNumber::Msg ) // Msg==messaging
types << "company";
if ( type & KABC::PhoneNumber::Work )
types << "business2";
if ( type & KABC::PhoneNumber::Pref )
types << "primary";
if ( type & KABC::PhoneNumber::Voice )
types << "callback"; // ##
if ( type & KABC::PhoneNumber::Cell )
types << "mobile";
if ( type & KABC::PhoneNumber::Video )
types << "radio"; // ##
if ( type & KABC::PhoneNumber::Bbs )
types << "ttytdd";
if ( type & KABC::PhoneNumber::Modem )
types << "telex"; // #
if ( type & KABC::PhoneNumber::Car )
types << "car";
if ( type & KABC::PhoneNumber::Isdn )
types << "isdn";
if ( type & KABC::PhoneNumber::Pcs )
types << "assistant"; // ## Assistant is e.g. secretary
if ( type & KABC::PhoneNumber::Pager )
types << "pager";
return types;
}
static KABC::PhoneNumber::Type phoneTypeFromString( const QString& type )
{
if ( type == "homefax" )
return KABC::PhoneNumber::Home | KABC::PhoneNumber::Fax;
if ( type == "businessfax" )
return KABC::PhoneNumber::Work | KABC::PhoneNumber::Fax;
if ( type == "business1" )
return KABC::PhoneNumber::Work | KABC::PhoneNumber::Pref;
if ( type == "business2" )
return KABC::PhoneNumber::Work;
if ( type == "home1" )
return KABC::PhoneNumber::Home | KABC::PhoneNumber::Pref;
if ( type == "home2" )
return KABC::PhoneNumber::Home;
if ( type == "company" )
return KABC::PhoneNumber::Msg;
if ( type == "primary" )
return KABC::PhoneNumber::Pref;
if ( type == "callback" )
return KABC::PhoneNumber::Voice;
if ( type == "mobile" )
return KABC::PhoneNumber::Cell;
if ( type == "radio" )
return KABC::PhoneNumber::Video;
if ( type == "ttytdd" )
return KABC::PhoneNumber::Bbs;
if ( type == "telex" )
return KABC::PhoneNumber::Modem;
if ( type == "car" )
return KABC::PhoneNumber::Car;
if ( type == "isdn" )
return KABC::PhoneNumber::Isdn;
if ( type == "assistant" )
return KABC::PhoneNumber::Pcs;
if ( type == "pager" )
return KABC::PhoneNumber::Pager;
return KABC::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 KABC::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() );
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:
// KABC::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 KABC::Address::List addresses = addressee->addresses();
for ( KABC::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 & KABC::Address::Pref ) {
preferredAddress = address.type; // home, business or other
}
}
setPreferredAddress( preferredAddress );
const KABC::PhoneNumber::List phones = addressee->phoneNumbers();
for ( KABC::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 ) {
// KABC::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 ) ) {
//kDebug() <<"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 );
}
}
QString url = KCalCore::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( KABC::Addressee* addressee )
{
// TODO: This needs the same set of TODOs as the setFields method
KolabBase::saveTo( addressee );
addressee->setGivenName( givenName() );
addressee->setAdditionalName( middleNames() );
addressee->setFamilyName( lastName() );
addressee->setFormattedName( fullName() );
addressee->setPrefix( prefix() );
addressee->setSuffix( suffix() );
addressee->setOrganization( organization() );
addressee->setUrl( webPage() );
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" );
// 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() ) {
KABC::Picture picture( mPicture );
picture.setType(mPictureFormat);
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() ) {
KABC::Picture picture( mLogo );
picture.setType(mLogoFormat);
addressee->setLogo( picture );
}
addressee->insertCustom( "KOLAB", "LogoAttachmentName", mLogoAttachmentName );
if ( !mSound.isNull() )
addressee->setSound( KABC::Sound( mSound ) );
addressee->insertCustom( "KOLAB", "SoundAttachmentName", mSoundAttachmentName );
if ( mHasGeo )
addressee->setGeo( KABC::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 ) {
KABC::Address address;
int type = (*it).kdeAddressType;
if ( type == -1 ) { // no kde-specific type available
type = addressTypeFromString( (*it).type );
if ( (*it).type == mPreferredAddress )
type |= KABC::Address::Pref;
}
address.setType( static_cast<KABC::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 ) {
KABC::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 );
}
//kDebug() << addressee->customs();
}
QImage Contact::loadPictureFromAddressee( const KABC::Picture& picture )
{
QImage img;
if ( !picture.isIntern() && !picture.url().isEmpty() ) {
QString tmpFile;
+ kWarning() << "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 KABC::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";
}
diff --git a/kolabformatV2/incidence.cpp b/kolabformatV2/incidence.cpp
index a800193..4ac7a3e 100644
--- a/kolabformatV2/incidence.cpp
+++ b/kolabformatV2/incidence.cpp
@@ -1,976 +1,975 @@
/*
This file is part of the kolab resource - the implementation of the
Kolab storage format. See www.kolab.org for documentation on this.
Copyright (c) 2004 Bo Thorsen <bo@sonofthor.dk>
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 "incidence.h"
#include "libkolab-version.h"
#include <QList>
#include <kcalcore/journal.h>
#include <kdebug.h>
#include <kurl.h>
-#include <kio/netaccess.h>
#include <QBitArray>
using namespace KolabV2;
Incidence::Incidence( const QString& tz, const KCalCore::Incidence::Ptr &incidence )
: KolabBase( tz ), mFloatingStatus( Unset ), mHasAlarm( false )
{
Q_UNUSED( incidence );
}
Incidence::~Incidence()
{
}
void Incidence::setSummary( const QString& summary )
{
mSummary = summary;
}
QString Incidence::summary() const
{
return mSummary;
}
void Incidence::setLocation( const QString& location )
{
mLocation = location;
}
QString Incidence::location() const
{
return mLocation;
}
void Incidence::setOrganizer( const Email& organizer )
{
mOrganizer = organizer;
}
KolabBase::Email Incidence::organizer() const
{
return mOrganizer;
}
void Incidence::setStartDate( const KDateTime& startDate )
{
mStartDate = startDate;
if ( mFloatingStatus == AllDay )
kDebug() <<"ERROR: Time on start date but no time on the event";
mFloatingStatus = HasTime;
}
void Incidence::setStartDate( const QDate& startDate )
{
mStartDate = KDateTime( startDate );
if ( mFloatingStatus == HasTime )
kDebug() <<"ERROR: No time on start date but time on the event";
mFloatingStatus = AllDay;
}
void Incidence::setStartDate( const QString& startDate )
{
if ( startDate.length() > 10 )
// This is a date + time
setStartDate( stringToDateTime( startDate ) );
else
// This is only a date
setStartDate( stringToDate( startDate ) );
}
KDateTime Incidence::startDate() const
{
return mStartDate;
}
void Incidence::setAlarm( float alarm )
{
mAlarm = alarm;
mHasAlarm = true;
}
float Incidence::alarm() const
{
return mAlarm;
}
Incidence::Recurrence Incidence::recurrence() const
{
return mRecurrence;
}
void Incidence::addAttendee( const Attendee& attendee )
{
mAttendees.append( attendee );
}
QList<Incidence::Attendee>& Incidence::attendees()
{
return mAttendees;
}
const QList<Incidence::Attendee>& Incidence::attendees() const
{
return mAttendees;
}
void Incidence::setInternalUID( const QString& iuid )
{
mInternalUID = iuid;
}
QString Incidence::internalUID() const
{
return mInternalUID;
}
bool Incidence::loadAttendeeAttribute( QDomElement& element,
Attendee& attendee )
{
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 == "display-name" )
attendee.displayName = e.text();
else if ( tagName == "smtp-address" )
attendee.smtpAddress = e.text();
else if ( tagName == "status" )
attendee.status = e.text();
else if ( tagName == "request-response" )
// This sets reqResp to false, if the text is "false". Otherwise it
// sets it to true. This means the default setting is true.
attendee.requestResponse = ( e.text().toLower() != "false" );
else if ( tagName == "invitation-sent" )
// Like above, only this defaults to false
attendee.invitationSent = ( e.text().toLower() != "true" );
else if ( tagName == "role" )
attendee.role = e.text();
else if ( tagName == "delegated-to" )
attendee.delegate = e.text();
else if ( tagName == "delegated-from" )
attendee.delegator = e.text();
else
// TODO: Unhandled tag - save for later storage
kDebug() <<"Warning: Unhandled tag" << e.tagName();
} else
kDebug() <<"Node is not a comment or an element???";
}
return true;
}
void Incidence::saveAttendeeAttribute( QDomElement& element,
const Attendee& attendee ) const
{
QDomElement e = element.ownerDocument().createElement( "attendee" );
element.appendChild( e );
writeString( e, "display-name", attendee.displayName );
writeString( e, "smtp-address", attendee.smtpAddress );
writeString( e, "status", attendee.status );
writeString( e, "request-response",
( attendee.requestResponse ? "true" : "false" ) );
writeString( e, "invitation-sent",
( attendee.invitationSent ? "true" : "false" ) );
writeString( e, "role", attendee.role );
writeString( e, "delegated-to", attendee.delegate );
writeString( e, "delegated-from", attendee.delegator );
}
void Incidence::saveAttendees( QDomElement& element ) const
{
foreach ( const Attendee& attendee, mAttendees )
saveAttendeeAttribute( element, attendee );
}
void Incidence::saveAttachments( QDomElement& element ) const
{
foreach ( KCalCore::Attachment::Ptr a, mAttachments ) {
if ( a->isUri() ) {
writeString( element, "link-attachment", a->uri() );
} else if ( a->isBinary() ) {
writeString( element, "inline-attachment", a->label() );
}
}
}
void Incidence::saveAlarms( QDomElement& element ) const
{
if ( mAlarms.isEmpty() ) return;
QDomElement list = element.ownerDocument().createElement( "advanced-alarms" );
element.appendChild( list );
foreach ( KCalCore::Alarm::Ptr a, mAlarms ) {
QDomElement e = list.ownerDocument().createElement( "alarm" );
list.appendChild( e );
writeString( e, "enabled", a->enabled() ? "1" : "0" );
if ( a->hasStartOffset() ) {
writeString( e, "start-offset", QString::number( a->startOffset().asSeconds()/60 ) );
}
if ( a->hasEndOffset() ) {
writeString( e, "end-offset", QString::number( a->endOffset().asSeconds()/60 ) );
}
if ( a->repeatCount() ) {
writeString( e, "repeat-count", QString::number( a->repeatCount() ) );
writeString( e, "repeat-interval", QString::number( a->snoozeTime().asSeconds() ) );
}
switch ( a->type() ) {
case KCalCore::Alarm::Invalid:
break;
case KCalCore::Alarm::Display:
e.setAttribute( "type", "display" );
writeString( e, "text", a->text() );
break;
case KCalCore::Alarm::Procedure:
e.setAttribute( "type", "procedure" );
writeString( e, "program", a->programFile() );
writeString( e, "arguments", a->programArguments() );
break;
case KCalCore::Alarm::Email:
{
e.setAttribute( "type", "email" );
QDomElement addresses = e.ownerDocument().createElement( "addresses" );
e.appendChild( addresses );
foreach ( const KCalCore::Person::Ptr &person, a->mailAddresses() ) {
writeString( addresses, "address", person->fullName() );
}
writeString( e, "subject", a->mailSubject() );
writeString( e, "mail-text", a->mailText() );
QDomElement attachments = e.ownerDocument().createElement( "attachments" );
e.appendChild( attachments );
foreach ( const QString &attachment, a->mailAttachments() ) {
writeString( attachments, "attachment", attachment );
}
break;
}
case KCalCore::Alarm::Audio:
e.setAttribute( "type", "audio" );
writeString( e, "file", a->audioFile() );
break;
default:
kWarning() << "Unhandled alarm type:" << a->type();
break;
}
}
}
void Incidence::saveRecurrence( QDomElement& element ) const
{
QDomElement e = element.ownerDocument().createElement( "recurrence" );
element.appendChild( e );
e.setAttribute( "cycle", mRecurrence.cycle );
if ( !mRecurrence.type.isEmpty() )
e.setAttribute( "type", mRecurrence.type );
writeString( e, "interval", QString::number( mRecurrence.interval ) );
foreach ( const QString& recurrence, mRecurrence.days ) {
writeString( e, "day", recurrence );
}
if ( !mRecurrence.dayNumber.isEmpty() )
writeString( e, "daynumber", mRecurrence.dayNumber );
if ( !mRecurrence.month.isEmpty() )
writeString( e, "month", mRecurrence.month );
if ( !mRecurrence.rangeType.isEmpty() ) {
QDomElement range = element.ownerDocument().createElement( "range" );
e.appendChild( range );
range.setAttribute( "type", mRecurrence.rangeType );
QDomText t = element.ownerDocument().createTextNode( mRecurrence.range );
range.appendChild( t );
}
foreach ( const QDate& date, mRecurrence.exclusions ) {
writeString( e, "exclusion", dateToString( date ) );
}
}
void Incidence::loadRecurrence( const QDomElement& element )
{
mRecurrence.interval = 0;
mRecurrence.cycle = element.attribute( "cycle" );
mRecurrence.type = element.attribute( "type" );
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 == "interval" ) {
//kolab/issue4229, sometimes the interval value can be empty
if ( e.text().isEmpty() || e.text().toInt() <= 0 ) {
mRecurrence.interval = 1;
} else {
mRecurrence.interval = e.text().toInt();
}
}
else if ( tagName == "day" ) // can be present multiple times
mRecurrence.days.append( e.text() );
else if ( tagName == "daynumber" )
mRecurrence.dayNumber = e.text();
else if ( tagName == "month" )
mRecurrence.month = e.text();
else if ( tagName == "range" ) {
mRecurrence.rangeType = e.attribute( "type" );
mRecurrence.range = e.text();
} else if ( tagName == "exclusion" ) {
mRecurrence.exclusions.append( stringToDate( e.text() ) );
} else
// TODO: Unhandled tag - save for later storage
kDebug() <<"Warning: Unhandled tag" << e.tagName();
}
}
}
static void loadAddressesHelper( const QDomElement& element, const KCalCore::Alarm::Ptr &a )
{
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 == "address" ) {
a->addMailAddress( KCalCore::Person::fromFullName( e.text() ) );
} else {
kWarning() << "Unhandled tag" << tagName;
}
}
}
}
static void loadAttachmentsHelper( const QDomElement& element, const KCalCore::Alarm::Ptr &a )
{
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 == "attachment" ) {
a->addMailAttachment( e.text() );
} else {
kWarning() << "Unhandled tag" << tagName;
}
}
}
}
static void loadAlarmHelper( const QDomElement& element, const KCalCore::Alarm::Ptr &a )
{
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 == "start-offset" ) {
a->setStartOffset( e.text().toInt()*60 );
} else if ( tagName == "end-offset" ) {
a->setEndOffset( e.text().toInt()*60 );
} else if ( tagName == "repeat-count" ) {
a->setRepeatCount( e.text().toInt() );
} else if ( tagName == "repeat-interval" ) {
a->setSnoozeTime( e.text().toInt() );
} else if ( tagName == "text" ) {
a->setText( e.text() );
} else if ( tagName == "program" ) {
a->setProgramFile( e.text() );
} else if ( tagName == "arguments" ) {
a->setProgramArguments( e.text() );
} else if ( tagName == "addresses" ) {
loadAddressesHelper( e, a );
} else if ( tagName == "subject" ) {
a->setMailSubject( e.text() );
} else if ( tagName == "mail-text" ) {
a->setMailText( e.text() );
} else if ( tagName == "attachments" ) {
loadAttachmentsHelper( e, a );
} else if ( tagName == "file" ) {
a->setAudioFile( e.text() );
} else if ( tagName == "enabled" ) {
a->setEnabled( e.text().toInt() != 0 );
} else {
kWarning() << "Unhandled tag" << tagName;
}
}
}
}
void Incidence::loadAlarms( const 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 == "alarm" ) {
KCalCore::Alarm::Ptr a = KCalCore::Alarm::Ptr( new KCalCore::Alarm( 0 ) );
a->setEnabled( true ); // default to enabled, unless some XML attribute says otherwise.
QString type = e.attribute( "type" );
if ( type == "display" ) {
a->setType( KCalCore::Alarm::Display );
} else if ( type == "procedure" ) {
a->setType( KCalCore::Alarm::Procedure );
} else if ( type == "email" ) {
a->setType( KCalCore::Alarm::Email );
} else if ( type == "audio" ) {
a->setType( KCalCore::Alarm::Audio );
} else {
kWarning() << "Unhandled alarm type:" << type;
}
loadAlarmHelper( e, a );
mAlarms << a;
} else {
kWarning() << "Unhandled tag" << tagName;
}
}
}
}
bool Incidence::loadAttribute( QDomElement& element )
{
QString tagName = element.tagName();
if ( tagName == "summary" )
setSummary( element.text() );
else if ( tagName == "location" )
setLocation( element.text() );
else if ( tagName == "organizer" ) {
Email email;
if ( loadEmailAttribute( element, email ) ) {
setOrganizer( email );
return true;
} else
return false;
} else if ( tagName == "start-date" )
setStartDate( element.text() );
else if ( tagName == "recurrence" )
loadRecurrence( element );
else if ( tagName == "attendee" ) {
Attendee attendee;
if ( loadAttendeeAttribute( element, attendee ) ) {
addAttendee( attendee );
return true;
} else
return false;
} else if ( tagName == "link-attachment" ) {
mAttachments.push_back( KCalCore::Attachment::Ptr( new KCalCore::Attachment( element.text() ) ) );
} else if ( tagName == "alarm" )
// Alarms should be minutes before. Libkcal uses event time + alarm time
setAlarm( - element.text().toInt() );
else if ( tagName == "advanced-alarms" )
loadAlarms( element );
else if ( tagName == "x-kde-internaluid" )
setInternalUID( element.text() );
else if ( tagName == "x-custom" ) {
loadCustomAttributes( element );
} else if ( tagName == "inline-attachment" ) {
// we handle that separately later on, so no need to create a KolabUnhandled entry for it
} else {
bool ok = KolabBase::loadAttribute( element );
if ( !ok ) {
// Unhandled tag - save for later storage
kDebug() <<"Saving unhandled tag" << element.tagName();
Custom c;
c.key = QByteArray( "X-KDE-KolabUnhandled-" ) + element.tagName().toLatin1();
c.value = element.text();
mCustomList.append( c );
}
}
// We handled this
return true;
}
bool Incidence::saveAttributes( QDomElement& element ) const
{
// Save the base class elements
KolabBase::saveAttributes( element );
if ( mFloatingStatus == HasTime )
writeString( element, "start-date", dateTimeToString( startDate() ) );
else
writeString( element, "start-date", dateToString( startDate().date() ) );
writeString( element, "summary", summary() );
writeString( element, "location", location() );
saveEmailAttribute( element, organizer(), "organizer" );
if ( !mRecurrence.cycle.isEmpty() )
saveRecurrence( element );
saveAttendees( element );
saveAttachments( element );
if ( mHasAlarm ) {
// Alarms should be minutes before. Libkcal uses event time + alarm time
int alarmTime = qRound( -alarm() );
writeString( element, "alarm", QString::number( alarmTime ) );
}
saveAlarms( element );
writeString( element, "x-kde-internaluid", internalUID() );
saveCustomAttributes( element );
return true;
}
void Incidence::saveCustomAttributes( QDomElement& element ) const
{
foreach ( const Custom& custom, mCustomList ) {
QString key( custom.key );
Q_ASSERT( !key.isEmpty() );
if ( key.startsWith( QLatin1String( "X-KDE-KolabUnhandled-" ) ) ) {
key = key.mid( strlen( "X-KDE-KolabUnhandled-" ) );
writeString( element, key, custom.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( "key", key );
e.setAttribute( "value", custom.value );
}
}
}
void Incidence::loadCustomAttributes( QDomElement& element )
{
Custom custom;
custom.key = element.attribute( "key" ).toLatin1();
custom.value = element.attribute( "value" );
mCustomList.append( custom );
}
static KCalCore::Attendee::PartStat attendeeStringToStatus( const QString& s )
{
if ( s == "none" )
return KCalCore::Attendee::NeedsAction;
if ( s == "tentative" )
return KCalCore::Attendee::Tentative;
if ( s == "declined" )
return KCalCore::Attendee::Declined;
if ( s == "delegated" )
return KCalCore::Attendee::Delegated;
// Default:
return KCalCore::Attendee::Accepted;
}
static QString attendeeStatusToString( KCalCore::Attendee::PartStat status )
{
switch( status ) {
case KCalCore::Attendee::NeedsAction:
return "none";
case KCalCore::Attendee::Accepted:
return "accepted";
case KCalCore::Attendee::Declined:
return "declined";
case KCalCore::Attendee::Tentative:
return "tentative";
case KCalCore::Attendee::Delegated:
return "delegated";
case KCalCore::Attendee::Completed:
case KCalCore::Attendee::InProcess:
// These don't have any meaning in the Kolab format, so just use:
return "accepted";
default:
// Default for the case that there are more added later:
return "accepted";
}
}
static KCalCore::Attendee::Role attendeeStringToRole( const QString& s )
{
if ( s == "optional" )
return KCalCore::Attendee::OptParticipant;
if ( s == "resource" )
return KCalCore::Attendee::NonParticipant;
return KCalCore::Attendee::ReqParticipant;
}
static QString attendeeRoleToString( KCalCore::Attendee::Role role )
{
switch( role ) {
case KCalCore::Attendee::ReqParticipant:
return "required";
case KCalCore::Attendee::OptParticipant:
return "optional";
case KCalCore::Attendee::Chair:
// We don't have the notion of chair, so use
return "required";
case KCalCore::Attendee::NonParticipant:
// In Kolab, a non-participant is a resource
return "resource";
}
// Default for the case that there are more added later:
return "required";
}
static const char *s_weekDayName[] =
{
"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"
};
static const char *s_monthName[] =
{
"january", "february", "march", "april", "may", "june", "july",
"august", "september", "october", "november", "december"
};
void Incidence::setRecurrence( KCalCore::Recurrence* recur )
{
mRecurrence.interval = recur->frequency();
switch ( recur->recurrenceType() ) {
case KCalCore::Recurrence::rMinutely: // Not handled by the kolab XML
mRecurrence.cycle = "minutely";
break;
case KCalCore::Recurrence::rHourly: // Not handled by the kolab XML
mRecurrence.cycle = "hourly";
break;
case KCalCore::Recurrence::rDaily:
mRecurrence.cycle = "daily";
break;
case KCalCore::Recurrence::rWeekly: // every X weeks
mRecurrence.cycle = "weekly";
{
QBitArray arr = recur->days();
for ( uint idx = 0 ; idx < 7 ; ++idx )
if ( arr.testBit( idx ) )
mRecurrence.days.append( s_weekDayName[idx] );
}
break;
case KCalCore::Recurrence::rMonthlyPos: {
mRecurrence.cycle = "monthly";
mRecurrence.type = "weekday";
QList<KCalCore::RecurrenceRule::WDayPos> monthPositions = recur->monthPositions();
if ( !monthPositions.isEmpty() ) {
KCalCore::RecurrenceRule::WDayPos monthPos = monthPositions.first();
// TODO: Handle multiple days in the same week
mRecurrence.dayNumber = QString::number( monthPos.pos() );
mRecurrence.days.append( s_weekDayName[ monthPos.day()-1 ] );
// Not (properly) handled(?): monthPos.negative (nth days before end of month)
}
break;
}
case KCalCore::Recurrence::rMonthlyDay: {
mRecurrence.cycle = "monthly";
mRecurrence.type = "daynumber";
QList<int> monthDays = recur->monthDays();
// ####### Kolab XML limitation: only the first month day is used
if ( !monthDays.isEmpty() )
mRecurrence.dayNumber = QString::number( monthDays.first() );
break;
}
case KCalCore::Recurrence::rYearlyMonth: // (day n of Month Y)
{
mRecurrence.cycle = "yearly";
mRecurrence.type = "monthday";
QList<int> rmd = recur->yearDates();
int day = !rmd.isEmpty() ? rmd.first() : recur->startDate().day();
mRecurrence.dayNumber = QString::number( day );
QList<int> months = recur->yearMonths();
if ( !months.isEmpty() )
mRecurrence.month = s_monthName[ months.first() - 1 ]; // #### Kolab XML limitation: only one month specified
break;
}
case KCalCore::Recurrence::rYearlyDay: // YearlyDay (day N of the year). Not supported by Outlook
mRecurrence.cycle = "yearly";
mRecurrence.type = "yearday";
mRecurrence.dayNumber = QString::number( recur->yearDays().first() );
break;
case KCalCore::Recurrence::rYearlyPos: // (weekday X of week N of month Y)
mRecurrence.cycle = "yearly";
mRecurrence.type = "weekday";
QList<int> months = recur->yearMonths();
if ( !months.isEmpty() )
mRecurrence.month = s_monthName[ months.first() - 1 ]; // #### Kolab XML limitation: only one month specified
QList<KCalCore::RecurrenceRule::WDayPos> monthPositions = recur->yearPositions();
if ( !monthPositions.isEmpty() ) {
KCalCore::RecurrenceRule::WDayPos monthPos = monthPositions.first();
// TODO: Handle multiple days in the same week
mRecurrence.dayNumber = QString::number( monthPos.pos() );
mRecurrence.days.append( s_weekDayName[ monthPos.day()-1 ] );
//mRecurrence.dayNumber = QString::number( *recur->yearNums().getFirst() );
// Not handled: monthPos.negative (nth days before end of month)
}
break;
}
int howMany = recur->duration();
if ( howMany > 0 ) {
mRecurrence.rangeType = "number";
mRecurrence.range = QString::number( howMany );
} else if ( howMany == 0 ) {
mRecurrence.rangeType = "date";
mRecurrence.range = dateToString( recur->endDate() );
} else {
mRecurrence.rangeType = "none";
}
}
void Incidence::setFields( const KCalCore::Incidence::Ptr &incidence )
{
KolabBase::setFields( incidence );
if ( incidence->allDay() ) {
// This is a all-day event. Don't timezone move this one
mFloatingStatus = AllDay;
setStartDate( incidence->dtStart().date() );
} else {
mFloatingStatus = HasTime;
setStartDate( localToUTC( incidence->dtStart() ) );
}
setSummary( incidence->summary() );
setLocation( incidence->location() );
// Alarm
mHasAlarm = false; // Will be set to true, if we actually have one
if ( incidence->hasEnabledAlarms() ) {
const KCalCore::Alarm::List& alarms = incidence->alarms();
if ( !alarms.isEmpty() ) {
const KCalCore::Alarm::Ptr alarm = alarms.first();
if ( alarm->hasStartOffset() ) {
int dur = alarm->startOffset().asSeconds();
setAlarm( (float)dur / 60.0 );
}
}
}
Email org( incidence->organizer()->name(), incidence->organizer()->email() );
setOrganizer( org );
// Attendees:
KCalCore::Attendee::List attendees = incidence->attendees();
foreach ( KCalCore::Attendee::Ptr kcalAttendee, attendees ) {
Attendee attendee;
attendee.displayName = kcalAttendee->name();
attendee.smtpAddress = kcalAttendee->email();
attendee.status = attendeeStatusToString( kcalAttendee->status() );
attendee.requestResponse = kcalAttendee->RSVP();
// TODO: KCalCore::Attendee::mFlag is not accessible
// attendee.invitationSent = kcalAttendee->mFlag;
// DF: Hmm? mFlag is set to true and never used at all.... Did you mean another field?
attendee.role = attendeeRoleToString( kcalAttendee->role() );
attendee.delegate = kcalAttendee->delegate();
attendee.delegator = kcalAttendee->delegator();
addAttendee( attendee );
}
mAttachments.clear();
// Attachments
KCalCore::Attachment::List attachments = incidence->attachments();
foreach ( KCalCore::Attachment::Ptr a, attachments ) {
mAttachments.push_back( a );
}
mAlarms.clear();
// Alarms
KCalCore::Alarm::List alarms = incidence->alarms();
foreach ( KCalCore::Alarm::Ptr a, alarms ) {
mAlarms.push_back( a );
}
if ( incidence->recurs() ) {
setRecurrence( incidence->recurrence() );
mRecurrence.exclusions = incidence->recurrence()->exDates();
}
// Handle the scheduling ID
if ( incidence->schedulingID() == incidence->uid() ) {
// There is no scheduling ID
setInternalUID( QString::null ); //krazy:exclude=nullstrassign for old broken gcc
} else {
// We've internally been using a different uid, so save that as the
// temporary (internal) uid and restore the original uid, the one that
// is used in the folder and the outside world
setUid( incidence->schedulingID() );
setInternalUID( incidence->uid() );
}
// Unhandled tags and other custom properties (see libkcal/customproperties.h)
const QMap<QByteArray, QString> map = incidence->customProperties();
QMap<QByteArray, QString>::ConstIterator cit = map.begin();
for ( ; cit != map.end() ; ++cit ) {
Custom c;
c.key = cit.key();
c.value = cit.value();
mCustomList.append( c );
}
}
static QBitArray daysListToBitArray( const QStringList& days )
{
QBitArray arr( 7 );
arr.fill( false );
foreach ( const QString& day, days ) {
for ( uint i = 0; i < 7 ; ++i )
if ( day == s_weekDayName[i] )
arr.setBit( i, true );
}
return arr;
}
void Incidence::saveTo( const KCalCore::Incidence::Ptr &incidence )
{
KolabBase::saveTo( incidence );
if ( mFloatingStatus == AllDay ) {
// This is an all-day event. Don't timezone move this one
incidence->setDtStart( startDate() );
incidence->setAllDay( true );
} else {
incidence->setDtStart( utcToLocal( startDate() ) );
incidence->setAllDay( false );
}
incidence->setSummary( summary() );
incidence->setLocation( location() );
if ( mHasAlarm && mAlarms.isEmpty() ) {
KCalCore::Alarm::Ptr alarm = incidence->newAlarm();
alarm->setStartOffset( qRound( mAlarm * 60.0 ) );
alarm->setEnabled( true );
alarm->setType( KCalCore::Alarm::Display );
} else if ( !mAlarms.isEmpty() ) {
foreach ( KCalCore::Alarm::Ptr a, mAlarms ) {
a->setParent( incidence.data() );
incidence->addAlarm( a );
}
}
if ( organizer().displayName.isEmpty() )
incidence->setOrganizer( organizer().smtpAddress );
else
incidence->setOrganizer( organizer().displayName + '<'
+ organizer().smtpAddress + '>' );
incidence->clearAttendees();
foreach ( const Attendee& attendee, mAttendees ) {
KCalCore::Attendee::PartStat status = attendeeStringToStatus( attendee.status );
KCalCore::Attendee::Role role = attendeeStringToRole( attendee.role );
KCalCore::Attendee::Ptr a( new KCalCore::Attendee( attendee.displayName,
attendee.smtpAddress,
attendee.requestResponse,
status, role ) );
a->setDelegate( attendee.delegate );
a->setDelegator( attendee.delegator );
incidence->addAttendee( a );
}
incidence->clearAttachments();
foreach ( KCalCore::Attachment::Ptr a, mAttachments ) {
// TODO should we copy?
incidence->addAttachment( a );
}
if ( !mRecurrence.cycle.isEmpty() ) {
KCalCore::Recurrence* recur = incidence->recurrence(); // yeah, this creates it
// done below recur->setFrequency( mRecurrence.interval );
if ( mRecurrence.cycle == "minutely" ) {
recur->setMinutely( mRecurrence.interval );
} else if ( mRecurrence.cycle == "hourly" ) {
recur->setHourly( mRecurrence.interval );
} else if ( mRecurrence.cycle == "daily" ) {
recur->setDaily( mRecurrence.interval );
} else if ( mRecurrence.cycle == "weekly" ) {
QBitArray rDays = daysListToBitArray( mRecurrence.days );
recur->setWeekly( mRecurrence.interval, rDays );
} else if ( mRecurrence.cycle == "monthly" ) {
recur->setMonthly( mRecurrence.interval );
if ( mRecurrence.type == "weekday" ) {
recur->addMonthlyPos( mRecurrence.dayNumber.toInt(), daysListToBitArray( mRecurrence.days ) );
} else if ( mRecurrence.type == "daynumber" ) {
recur->addMonthlyDate( mRecurrence.dayNumber.toInt() );
} else kWarning() <<"Unhandled monthly recurrence type" << mRecurrence.type;
} else if ( mRecurrence.cycle == "yearly" ) {
recur->setYearly( mRecurrence.interval );
if ( mRecurrence.type == "monthday" ) {
recur->addYearlyDate( mRecurrence.dayNumber.toInt() );
for ( int i = 0; i < 12; ++i )
if ( s_monthName[ i ] == mRecurrence.month )
recur->addYearlyMonth( i+1 );
} else if ( mRecurrence.type == "yearday" ) {
recur->addYearlyDay( mRecurrence.dayNumber.toInt() );
} else if ( mRecurrence.type == "weekday" ) {
for ( int i = 0; i < 12; ++i )
if ( s_monthName[ i ] == mRecurrence.month )
recur->addYearlyMonth( i+1 );
recur->addYearlyPos( mRecurrence.dayNumber.toInt(), daysListToBitArray( mRecurrence.days ) );
} else kWarning() <<"Unhandled yearly recurrence type" << mRecurrence.type;
} else kWarning() <<"Unhandled recurrence cycle" << mRecurrence.cycle;
if ( mRecurrence.rangeType == "number" ) {
recur->setDuration( mRecurrence.range.toInt() );
} else if ( mRecurrence.rangeType == "date" ) {
recur->setEndDate( stringToDate( mRecurrence.range ) );
} // "none" is default since tje set*ly methods set infinite recurrence
incidence->recurrence()->setExDates( mRecurrence.exclusions );
}
/* If we've stored a uid to be used internally instead of the real one
* (to deal with duplicates of events in different folders) before, then
* restore it, so it does not change. Keep the original uid around for
* scheduling purposes. */
if ( !internalUID().isEmpty() ) {
incidence->setUid( internalUID() );
incidence->setSchedulingID( uid() );
}
foreach ( const Custom& custom, mCustomList ) {
incidence->setNonKDECustomProperty( custom.key, custom.value );
}
}
QString Incidence::productID() const
{
return QString( "%1, Kolab resource" ).arg( LIBKOLAB_LIB_VERSION_STRING );
}
// Unhandled KCalCore::Incidence fields:
// revision, status (unused), priority (done in tasks), attendee.uid,
// mComments, mReadOnly
diff --git a/tests/kcalconversiontest.cpp b/tests/kcalconversiontest.cpp
index 0a52108..dceb24d 100644
--- a/tests/kcalconversiontest.cpp
+++ b/tests/kcalconversiontest.cpp
@@ -1,515 +1,515 @@
/*
* Copyright (C) 2012 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 "kcalconversiontest.h"
#include <contact.h>
#include <QtCore/QObject>
#include <QtTest/QtTest>
-#include <KDE/KSystemTimeZones>
+#include <ksystemtimezone.h>
#include <kolabcontact.h>
#include <kcalcore/recurrence.h>
#include <kabc/addressee.h>
#include "conversion/kcalconversion.h"
#include "conversion/kcalconversion.cpp"
#include "conversion/kabcconversion.h"
#include "testhelpers.h"
using namespace Kolab::Conversion;
template <typename T>
void comparePointerVectors(const QVector<T> &list, const QVector<T> &other)
{
QCOMPARE(list.size(), other.size());
for (int i = 0 ; i < list.size(); i++) {
QCOMPARE(*list.at(i), *other.at(i));
}
}
void compareAttendeesVectors(const KCalCore::Attendee::List &list, const KCalCore::Attendee::List &other)
{
QCOMPARE(list.size(), other.size());
for (int i = 0 ; i < list.size(); i++) {
KCalCore::Attendee::Ptr at1 = list.at(i).constCast<KCalCore::Attendee>();
at1->setUid(QString());
KCalCore::Attendee::Ptr at2 = other.at(i).constCast<KCalCore::Attendee>();
at2->setUid(QString());
QCOMPARE(*at1, *at2);
}
}
void KCalConversionTest::testDate_data()
{
QTest::addColumn<Kolab::cDateTime>( "input" );
QTest::addColumn<KDateTime>( "result" );
QTest::newRow( "datetime with tz" ) << Kolab::cDateTime("Europe/Zurich",2006,1,8,12,0,0) << KDateTime(QDate(2006, 1, 8), QTime(12, 0, 0), KSystemTimeZones::zone("Europe/Zurich"));
QTest::newRow( "floating datetime" ) << Kolab::cDateTime(2006,1,8,12,0,0, false) << KDateTime(QDate(2006, 1, 8), QTime(12, 0, 0), KDateTime::Spec(KDateTime::ClockTime));
QTest::newRow( "utc datetime" ) << Kolab::cDateTime(2006,1,8,12,0,0, true) << KDateTime(KDateTime(QDate(2006, 1, 8), QTime(12, 0, 0), KDateTime::UTC));
QTest::newRow( "date only" ) << Kolab::cDateTime(2006,1,8) << KDateTime(QDate(2006, 1, 8));
}
void KCalConversionTest::testDate()
{
QFETCH(Kolab::cDateTime, input);
QFETCH(KDateTime, result);
const KDateTime &r = Kolab::Conversion::toDate(input);
QCOMPARE(r, result);
const Kolab::cDateTime &r2 = Kolab::Conversion::fromDate(result);
QCOMPARE(r2, input);
}
void KCalConversionTest::testDuration_data()
{
QTest::addColumn<Kolab::Duration>( "input" );
QTest::addColumn<KCalCore::Duration>( "result" );
QTest::addColumn<Kolab::Duration>( "fromResult" );
QTest::newRow( "seconds" ) << Kolab::Duration(0,0,0,30,false) << KCalCore::Duration(30, KCalCore::Duration::Seconds) << Kolab::Duration(0,0,0,30,false);
QTest::newRow( "minutes" ) << Kolab::Duration(0,0,1,30,false) << KCalCore::Duration(90, KCalCore::Duration::Seconds) << Kolab::Duration(0,0,0,90,false);
QTest::newRow( "hours" ) << Kolab::Duration(0,1,1,30,false) << KCalCore::Duration(60*60+90, KCalCore::Duration::Seconds) << Kolab::Duration(0,0,0,60*60+90,false);
QTest::newRow( "days" ) << Kolab::Duration(1,1,1,30,false) << KCalCore::Duration(24*60*60+60*60+90, KCalCore::Duration::Seconds) << Kolab::Duration(0,0,0,24*60*60+60*60+90,false);
QTest::newRow( "daysonly" ) << Kolab::Duration(30,0,0,0, false) << KCalCore::Duration(30, KCalCore::Duration::Days) << Kolab::Duration(30,0,0,0,false);
QTest::newRow( "weeks" ) << Kolab::Duration(30,false) << KCalCore::Duration(30*7, KCalCore::Duration::Days) << Kolab::Duration(30*7,0,0,0,false);
}
void KCalConversionTest::testDuration()
{
QFETCH(Kolab::Duration, input);
QFETCH(KCalCore::Duration, result);
QFETCH(Kolab::Duration, fromResult);
const KCalCore::Duration &r = Kolab::Conversion::toDuration(input);
QCOMPARE(r, result);
const Kolab::Duration &r2 = Kolab::Conversion::fromDuration(result);
QCOMPARE(r2, fromResult);
}
void KCalConversionTest::testDateTZ_data()
{
QTest::addColumn<Kolab::cDateTime>( "input" );
QTest::addColumn<KDateTime>( "result" );
QTest::newRow( "berlin" ) << Kolab::cDateTime("Europe/Berlin",2006,1,8,12,0,0) << KDateTime(QDate(2006, 1, 8), QTime(12, 0, 0), KSystemTimeZones::zone("Europe/Berlin"));
}
void KCalConversionTest::testDateTZ()
{
QFETCH(Kolab::cDateTime, input);
QFETCH(KDateTime, result);
const KDateTime &r = Kolab::Conversion::toDate(input);
QCOMPARE(result.timeZone().name(), QString::fromStdString(input.timezone()));
QCOMPARE(r.timeZone().currentOffset(), result.timeZone().currentOffset());
const Kolab::cDateTime &r2 = Kolab::Conversion::fromDate(result);
QCOMPARE(QString::fromStdString(r2.timezone()), result.timeZone().name());
}
void KCalConversionTest::testConversion_data()
{
QTest::addColumn<KCalCore::Event>( "kcal" );
QTest::addColumn<Kolab::Event>( "kolab" );
Kolab::cDateTime date(2011,2,2,12,11,10,true);
Kolab::cDateTime date2(2011,2,2,12,12,10,true);
Kolab::cDateTime date3(2012,2,2,12,12,10,true);
std::vector<int> intVector;
intVector.push_back(1);
intVector.push_back(-3);
intVector.push_back(2);
std::vector<std::string> stringVector;
stringVector.push_back("cat1");
stringVector.push_back("cat2");
stringVector.push_back("parent/child");
{
KCalCore::Event kcal;
kcal.setUid("uid");
kcal.setCreated(toDate(date));
kcal.setLastModified(toDate(date));
kcal.setRevision(3);
kcal.setSecrecy(KCalCore::Incidence::SecrecyConfidential);
kcal.setCategories(toStringList(stringVector));
kcal.setDtStart(toDate(date));
kcal.setDtEnd(toDate(date2));
kcal.setTransparency(KCalCore::Event::Transparent);
kcal.setRecurrenceId(toDate(date2)); //TODO THISANDFUTURE
kcal.recurrence()->setDaily(3);
kcal.recurrence()->setDuration(5);
kcal.recurrence()->addRDateTime(toDate(date2));
kcal.recurrence()->addRDate(toDate(date2).date());
kcal.recurrence()->addExDateTime(toDate(date3));
kcal.recurrence()->addExDate(toDate(date3).date());
KCalCore::RecurrenceRule *rr = kcal.recurrence()->defaultRRule(true);
QList<int> intList = QVector<int>::fromStdVector(intVector).toList();
rr->setBySeconds(intList);
rr->setByMinutes(intList);
rr->setByHours(intList);
rr->setByDays(QList<KCalCore::RecurrenceRule::WDayPos>() << KCalCore::RecurrenceRule::WDayPos(3,1) << KCalCore::RecurrenceRule::WDayPos(5,4));
rr->setByMonthDays(intList);
rr->setByYearDays(intList);
rr->setByMonths(intList);
rr->setByWeekNumbers(intList);
kcal.setSummary("summary");
kcal.setDescription("description");
kcal.setPriority(3);
kcal.setStatus(KCalCore::Incidence::StatusConfirmed);
kcal.setLocation("location");
kcal.setOrganizer(KCalCore::Person::Ptr(new KCalCore::Person("organizer", "organizer@email")));
KCalCore::Attendee::Ptr att(new KCalCore::Attendee("attendee", "attendee@email", false, KCalCore::Attendee::NeedsAction, KCalCore::Attendee::ReqParticipant));
att->setDelegate("mailto:delegatee<delegatee@email>");
att->setDelegator("mailto:delegator<delegator@email>");
kcal.addAttendee(att);
kcal.addAttachment(KCalCore::Attachment::Ptr(new KCalCore::Attachment(QString("uri"), "mimetype/mime")));
KCalCore::Alarm::Ptr alarm = KCalCore::Alarm::Ptr(new KCalCore::Alarm(&kcal));
KCalCore::Person::List addressees;
addressees.append(KCalCore::Person::Ptr(new KCalCore::Person("name", "email@email")));
alarm->setEmailAlarm("subject", "text", addressees, QStringList()); //No support for attachments
kcal.addAlarm(alarm);
//TODO alarms
kcal.setNonKDECustomProperty("X-KOLAB-key1", "value1");
kcal.setNonKDECustomProperty("X-KOLAB-key2", "value2");
kcal.setCustomProperty("SOMEOTHERAPP", "key2", "value2");
Q_ASSERT(kcal.nonKDECustomProperty("X-KOLAB-key1") == "value1");
Kolab::Event kolab;
kolab.setUid("uid");
kolab.setCreated(date);
kolab.setLastModified(date);
kolab.setSequence(3);
kolab.setClassification(Kolab::ClassConfidential);
kolab.setCategories(stringVector);
kolab.setStart(date);
kolab.setEnd(date2);
kolab.setTransparency(true);
Kolab::RecurrenceRule rrule;
rrule.setInterval(3);
rrule.setFrequency(Kolab::RecurrenceRule::Daily);
rrule.setCount(5);
rrule.setBysecond(intVector);
rrule.setByminute(intVector);
rrule.setByhour(intVector);
rrule.setByday(std::vector<Kolab::DayPos>() << Kolab::DayPos(3, Kolab::Monday) << Kolab::DayPos(5, Kolab::Thursday));
rrule.setBymonthday(intVector);
rrule.setByyearday(intVector);
rrule.setByweekno(intVector);
rrule.setBymonth(intVector);
kolab.setRecurrenceRule(rrule);
kolab.setRecurrenceID(date2, true);
kolab.setRecurrenceDates(std::vector<Kolab::cDateTime>() << date2 << Kolab::cDateTime(date2.year(), date2.month(), date2.day()));
kolab.setExceptionDates(std::vector<Kolab::cDateTime>() << date3 << Kolab::cDateTime(date3.year(), date3.month(), date3.day()));
kolab.setSummary("summary");
kolab.setDescription("description");
kolab.setPriority(3);
kolab.setStatus(Kolab::StatusConfirmed);
kolab.setLocation("location");
kolab.setOrganizer(Kolab::ContactReference(Kolab::ContactReference::EmailReference,"organizer@email", "organizer")); //TODO uid
Kolab::Attendee a(Kolab::ContactReference(Kolab::ContactReference::EmailReference,"attendee@email", "attendee"));//TODO uid
a.setDelegatedTo(std::vector<Kolab::ContactReference>() << Kolab::ContactReference(Kolab::ContactReference::EmailReference,"delegatee@email", "delegatee"));
a.setDelegatedFrom(std::vector<Kolab::ContactReference>() << Kolab::ContactReference(Kolab::ContactReference::EmailReference,"delegator@email", "delegator"));
a.setCutype(Kolab::CutypeIndividual);
kolab.setAttendees(std::vector<Kolab::Attendee>() << a);
Kolab::Attachment attach;
attach.setUri("uri", "mimetype/mime");
kolab.setAttachments(std::vector<Kolab::Attachment>() << attach);
// std::vector<std::string> receipents;
// receipents.push_back("email@email");
// Kolab::Alarm alarm2("summary", "description", receipents);
// kolab.setAlarms(std::vector<Kolab::Alarm>() << alarm2);
//The sorting is random, just sort them here how we think they should arrive so we don't have to sort during compare (due to lazyness).
std::vector<Kolab::CustomProperty> customproperties;
customproperties.push_back(Kolab::CustomProperty("X-KDE-SOMEOTHERAPP-key2", "value2"));
customproperties.push_back(Kolab::CustomProperty("key1", "value1"));
customproperties.push_back(Kolab::CustomProperty("key2", "value2"));
kolab.setCustomProperties(customproperties);
QTest::newRow( "with endDate and recurrence duration" ) << kcal << kolab;
}
{
KCalCore::Event kcal;
kcal.setUid("uid");
kcal.setCreated(toDate(date));
kcal.setLastModified(toDate(date));
kcal.setRevision(3);
kcal.setDtStart(toDate(date));
kcal.setDuration(KCalCore::Duration(toDate(date), toDate(date2)));
kcal.recurrence()->setDaily(3);
kcal.recurrence()->setEndDateTime(toDate(date3));
Kolab::Event kolab;
kolab.setUid("uid");
kolab.setCreated(date);
kolab.setLastModified(date);
kolab.setSequence(3);
kolab.setStart(date);
kolab.setDuration(Kolab::Duration(0, 0, 1, 0));
Kolab::RecurrenceRule rrule;
rrule.setInterval(3);
rrule.setFrequency(Kolab::RecurrenceRule::Daily);
rrule.setEnd(date3);
kolab.setRecurrenceRule(rrule);
QTest::newRow("with duration and recurrence endDate") << kcal << kolab;
}
{
Kolab::cDateTime start(2011,1,1);
Kolab::cDateTime end(2011,1,3);
KCalCore::Event kcal;
kcal.setUid("uid");
kcal.setCreated(toDate(date));
kcal.setLastModified(toDate(date));
kcal.setDtStart(toDate(start));
kcal.setDtEnd(toDate(end));
kcal.recurrence()->setDaily(3);
kcal.recurrence()->setEndDateTime(toDate(end));
Kolab::Event kolab;
kolab.setUid("uid");
kolab.setCreated(date);
kolab.setLastModified(date);
kolab.setStart(start);
kolab.setEnd(end);
Kolab::RecurrenceRule rrule;
rrule.setInterval(3);
rrule.setFrequency(Kolab::RecurrenceRule::Daily);
rrule.setEnd(end);
kolab.setRecurrenceRule(rrule);
QTest::newRow("date only dates") << kcal << kolab;
}
}
void KCalConversionTest::testConversion()
{
QFETCH(KCalCore::Event, kcal);
QFETCH(Kolab::Event, kolab);
const KCalCore::Event::Ptr e = toKCalCore(kolab);
QCOMPARE(e->uid(), kcal.uid());
QCOMPARE(e->created(), kcal.created());
QCOMPARE(e->lastModified(), kcal.lastModified());
QCOMPARE(e->revision(), kcal.revision());
QCOMPARE(e->secrecy(), kcal.secrecy());
QCOMPARE(e->categories(), kcal.categories());
QCOMPARE(e->dtStart(), kcal.dtStart());
QCOMPARE(e->dtEnd(), kcal.dtEnd());
QCOMPARE(e->duration(), kcal.duration());
QCOMPARE(e->transparency(), kcal.transparency());
QCOMPARE(*e->recurrence(), *kcal.recurrence());
QCOMPARE(e->recurrenceId(), kcal.recurrenceId());
QCOMPARE(e->recurrenceType(), kcal.recurrenceType());
QCOMPARE(e->summary(), kcal.summary());
QCOMPARE(e->description(), kcal.description());
QCOMPARE(e->priority(), kcal.priority());
QCOMPARE(e->status(), kcal.status());
QCOMPARE(e->location(), kcal.location());
QCOMPARE(e->organizer()->name(), kcal.organizer()->name());
QCOMPARE(e->organizer()->email(), kcal.organizer()->email());
compareAttendeesVectors(e->attendees(), kcal.attendees());
comparePointerVectors(e->attachments(), kcal.attachments());
// QCOMPARE(e->alarms(), kcal.alarms()); //TODO
QCOMPARE(e->customProperties(), kcal.customProperties());
// QBENCHMARK {
// toKCalCore(kolab);
// }
const Kolab::Event &b = fromKCalCore(kcal);
QCOMPARE(b.uid(), kolab.uid());
QCOMPARE(b.created(), kolab.created());
QCOMPARE(b.lastModified(), kolab.lastModified());
QCOMPARE(b.sequence(), kolab.sequence());
QCOMPARE(b.classification(), kolab.classification());
QCOMPARE(b.categories(), kolab.categories());
QCOMPARE(b.start(), kolab.start());
QCOMPARE(b.end(), kolab.end());
QCOMPARE(b.duration(), kolab.duration());
QCOMPARE(b.transparency(), kolab.transparency());
QCOMPARE(b.recurrenceRule(), kolab.recurrenceRule());
QCOMPARE(b.recurrenceID(), kolab.recurrenceID());
QCOMPARE(b.recurrenceDates(), kolab.recurrenceDates());
QCOMPARE(b.exceptionDates(), kolab.exceptionDates());
QCOMPARE(b.summary(), kolab.summary());
QCOMPARE(b.description(), kolab.description());
QCOMPARE(b.status(), kolab.status());
QCOMPARE(b.location(), kolab.location());
QCOMPARE(b.organizer(), kolab.organizer());
QCOMPARE(b.attendees(), kolab.attendees());
QCOMPARE(b.attachments(), kolab.attachments());
QCOMPARE(b.customProperties(), kolab.customProperties());
}
void KCalConversionTest::testTodoConversion_data()
{
QTest::addColumn<KCalCore::Todo>( "kcal" );
QTest::addColumn<Kolab::Todo>( "kolab" );
Kolab::cDateTime date(2011,2,2,12,11,10,true);
Kolab::cDateTime date2(2011,2,2,12,12,10,true);
{
KCalCore::Todo kcal;
kcal.setUid("uid");
kcal.setDtStart(toDate(date));
kcal.setDtDue(toDate(date2));
Kolab::Todo kolab;
kolab.setUid("uid");
kolab.setStart(date);
kolab.setDue(date2);
QTest::newRow( "todo" ) << kcal << kolab;
}
}
void KCalConversionTest::testTodoConversion()
{
QFETCH(KCalCore::Todo, kcal);
QFETCH(Kolab::Todo, kolab);
const KCalCore::Todo::Ptr e = toKCalCore(kolab);
QCOMPARE(e->uid(), kcal.uid());
QCOMPARE(e->dtStart(), kcal.dtStart());
QCOMPARE(e->dtDue(), kcal.dtDue());
const Kolab::Todo &b = fromKCalCore(kcal);
QCOMPARE(b.uid(), kolab.uid());
QCOMPARE(b.start(), kolab.start());
QCOMPARE(b.due(), kolab.due());
}
void KCalConversionTest::testJournalConversion_data()
{
QTest::addColumn<KCalCore::Journal>( "kcal" );
QTest::addColumn<Kolab::Journal>( "kolab" );
Kolab::cDateTime date(2011,2,2,12,11,10,true);
Kolab::cDateTime date2(2011,2,2,12,12,10,true);
{
KCalCore::Journal kcal;
kcal.setUid("uid");
kcal.setDtStart(toDate(date));
kcal.setSummary("summary");
Kolab::Journal kolab;
kolab.setUid("uid");
kolab.setStart(date);
kolab.setSummary("summary");
QTest::newRow( "journal" ) << kcal << kolab;
}
}
void KCalConversionTest::testJournalConversion()
{
QFETCH(KCalCore::Journal, kcal);
QFETCH(Kolab::Journal, kolab);
const KCalCore::Journal::Ptr e = toKCalCore(kolab);
QCOMPARE(e->uid(), kcal.uid());
QCOMPARE(e->dtStart(), kcal.dtStart());
QCOMPARE(e->summary(), kcal.summary());
const Kolab::Journal &b = fromKCalCore(kcal);
QCOMPARE(b.uid(), kolab.uid());
QCOMPARE(b.start(), kolab.start());
QCOMPARE(b.summary(), kolab.summary());
}
void KCalConversionTest::testContactConversion_data()
{
QTest::addColumn<KABC::Addressee>( "kcal" );
QTest::addColumn<Kolab::Contact>( "kolab" );
Kolab::cDateTime date(2011,2,2,12,11,10,true);
Kolab::cDateTime date2(2011,2,2,12,12,10,true);
{
KABC::Addressee kcal;
kcal.setUid("uid");
kcal.setFormattedName("name");
Kolab::Contact kolab;
kolab.setUid("uid");
kolab.setName("name");
QTest::newRow( "contact" ) << kcal << kolab;
}
}
void KCalConversionTest::testContactConversion()
{
QFETCH(KABC::Addressee, kcal);
QFETCH(Kolab::Contact, kolab);
const KABC::Addressee &e = toKABC(kolab);
QCOMPARE(e.uid(), kcal.uid());
QCOMPARE(e.formattedName(), kcal.formattedName());
const Kolab::Contact &b = fromKABC(kcal);
QCOMPARE(b.uid(), kolab.uid());
QCOMPARE(b.name(), kolab.name());
}
// void KCalConversionTest::BenchmarkRoundtripKCAL()
// {
// const Kolab::Event &event = Kolab::readEvent("../../tests/testfiles/icalEvent.xml", true);
// std::string result = Kolab::writeEvent(event);
// QBENCHMARK {
// Kolab::Conversion::toKCalCore(Kolab::readEvent(result, false));
// }
// }
QTEST_MAIN( KCalConversionTest )
#include "kcalconversiontest.moc"

File Metadata

Mime Type
text/x-diff
Expires
Mon, Apr 6, 12:06 AM (1 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18826177
Default Alt Text
(134 KB)

Event Timeline