17 commits - calendaring/calendaring.cpp CMakeLists.txt cmake/modules conversion/kabcconversion.cpp freebusy/CMakeLists.txt freebusy/freebusy.cpp freebusy/freebusy.h icalendar/icalendar.cpp icalendar/imip.cpp kolabformat/errorhandler.cpp kolabformat/errorhandler.h kolabformat/kolabdefinitions.h kolabformat/kolabobject.cpp kolabformat/kolabobject.h kolabformatV2/contact.cpp kolabformatV2/distributionlist.cpp mime/mimeutils.cpp tests/calendaringtest.cpp tests/CMakeLists.txt tests/freebusytest.cpp tests/freebusytest.h tests/testhelpers.h tests/testutils.h
Christian Mollekopf
mollekopf at kolabsys.com
Thu Jun 28 10:07:48 CEST 2012
CMakeLists.txt | 68 ++++++--
calendaring/calendaring.cpp | 2
cmake/modules/FindLibcalendaring.cmake | 20 ++
conversion/kabcconversion.cpp | 8
freebusy/CMakeLists.txt | 3
freebusy/freebusy.cpp | 272 +++++++++++++++++++++++++++++++++
freebusy/freebusy.h | 38 ++++
icalendar/icalendar.cpp | 6
icalendar/imip.cpp | 8
kolabformat/errorhandler.cpp | 6
kolabformat/errorhandler.h | 2
kolabformat/kolabdefinitions.h | 4
kolabformat/kolabobject.cpp | 40 +++-
kolabformat/kolabobject.h | 7
kolabformatV2/contact.cpp | 24 +-
kolabformatV2/distributionlist.cpp | 55 +++---
mime/mimeutils.cpp | 2
tests/CMakeLists.txt | 18 +-
tests/calendaringtest.cpp | 10 -
tests/freebusytest.cpp | 160 +++++++++++++++++++
tests/freebusytest.h | 32 +++
tests/testhelpers.h | 43 ++++-
tests/testutils.h | 9 +
23 files changed, 734 insertions(+), 103 deletions(-)
New commits:
commit 47e5f743922eed70cf5d7913224d2bb4ecf27837
Merge: e04661b 614e083
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Thu Jun 28 10:07:37 2012 +0200
Merge branch 'libcalendaring'
Conflicts:
freebusy/freebusy.h
commit e04661bd08e03cb35ab2724daffddc15e94d504e
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Tue Jun 26 15:15:42 2012 +0200
freebusy serializing, a couple of fixes for the generateFreeBusy code
diff --git a/freebusy/freebusy.cpp b/freebusy/freebusy.cpp
index ceb5bc2..c7f853e 100644
--- a/freebusy/freebusy.cpp
+++ b/freebusy/freebusy.cpp
@@ -24,6 +24,105 @@
#include <quuid.h>
+// namespace KCalCore {
+// struct KCalFreebusy
+// {
+//
+// void init( const Event::List &eventList, const KDateTime &start, const KDateTime &end )
+// {
+// mDtStart = start.toUtc();
+// mDtEnd = end.toUtc();
+//
+// // Loops through every event in the calendar
+// Event::List::ConstIterator it;
+// for ( it = eventList.constBegin(); it != eventList.constEnd(); ++it ) {
+// Event::Ptr event = *it;
+//
+// // If this event is transparent it shouldn't be in the freebusy list.
+// if ( event->transparency() == Event::Transparent ) {
+// continue;
+// }
+//
+// if ( event->hasRecurrenceId() ) {
+// continue; //TODO apply special period exception (duration could be different)
+// }
+//
+// const KDateTime eventStart = event->dtStart().toUtc();
+// const KDateTime eventEnd = event->dtEnd().toUtc();
+//
+// if ( event->recurs() ) {
+// const KCalCore::Duration duration( eventStart, eventEnd );
+// const KCalCore::DateTimeList list = event->recurrence()->timesInInterval(start, end);
+// foreach (const KDateTime &dt, list) {
+// const KDateTime utc = dt.toUtc();
+// addLocalPeriod(utc, duration.end(utc) );
+// }
+// } else {
+// addLocalPeriod( eventStart, eventEnd );
+// }
+// }
+//
+// // q->sortList();
+// }
+//
+// bool addLocalPeriod(
+// const KDateTime &eventStart,
+// const KDateTime &eventEnd )
+// {
+// KDateTime tmpStart;
+// KDateTime tmpEnd;
+//
+// //Check to see if the start *or* end of the event is
+// //between the start and end of the freebusy dates.
+// if ( !( ( ( mDtStart.secsTo( eventStart ) >= 0 ) &&
+// ( eventStart.secsTo( mDtEnd ) >= 0 ) ) ||
+// ( ( mDtStart.secsTo( eventEnd ) >= 0 ) &&
+// ( eventEnd.secsTo( mDtEnd ) >= 0 ) ) ) ) {
+// qDebug() << "out of scope";
+// return false;
+// }
+//
+// // qDebug() << eventStart.date().toString() << eventStart.time().toString() << mDtStart.toString();
+// if ( eventStart < mDtStart ) { //eventStart is before start
+// // qDebug() << "use start";
+// tmpStart = mDtStart;
+// } else {
+// tmpStart = eventStart;
+// }
+//
+// qDebug() << eventEnd.date().toString() << eventEnd.time().toString() << mDtEnd.toString();
+// if ( eventEnd > mDtEnd ) { //event end is after dtEnd
+// // qDebug() << "use end";
+// tmpEnd = mDtEnd;
+// } else {
+// tmpEnd = eventEnd;
+// }
+//
+// // qDebug() << "########## " << tmpStart.isValid();
+// Q_ASSERT(tmpStart.isValid());
+// Q_ASSERT(tmpEnd.isValid());
+// // qDebug() << tmpStart.date().toString() << tmpStart.time().toString() << tmpStart.toString();
+//
+// FreeBusyPeriod p( tmpStart, tmpEnd );
+// mBusyPeriods.append( p );
+//
+// return true;
+// }
+//
+// KDateTime mDtStart;
+// KDateTime mDtEnd; // end datetime
+// FreeBusyPeriod::List mBusyPeriods; // list of periods
+//
+// };
+//
+// } // Namespace
+
+
+
+
+
+
+
namespace Kolab {
namespace FreebusyUtils {
@@ -57,21 +156,43 @@ Kolab::Period addLocalPeriod( const KDateTime &eventStart, const KDateTime &eve
}
Q_ASSERT(tmpStart.isValid());
Q_ASSERT(tmpEnd.isValid());
+ if (tmpStart.isDateOnly()) {
+ tmpStart.setTime(QTime(0,0,0,0));
+ }
+ if (tmpEnd.isDateOnly()) {
+ tmpEnd.setTime(QTime(23,59,59,999)); //The window is inclusive
+ }
return Kolab::Period(Kolab::Conversion::fromDate(tmpStart), Kolab::Conversion::fromDate(tmpEnd));
}
-
+Freebusy generateFreeBusy(const std::vector< Event >& events, const cDateTime& startDate, const cDateTime& endDate)
+{
+ QList<KCalCore::Event::Ptr> list;
+ foreach (const Kolab::Event &e, events) {
+ list.append(Kolab::Conversion::toKCalCore(e));
+ }
+ KCalCore::Person::Ptr person(new KCalCore::Person("dummyname", "dummyemail"));
+ return generateFreeBusy(list, Kolab::Conversion::toDate(startDate), Kolab::Conversion::toDate(endDate), person);
+}
-Freebusy generateFreeBusy(const std::vector< Event >& events, const cDateTime& startDate, const cDateTime& endDate, const Freebusy& existing)
+Freebusy generateFreeBusy(const QList<KCalCore::Event::Ptr>& events, const KDateTime& startDate, const KDateTime& endDate, const KCalCore::Person::Ptr &organizer)
{
- const KDateTime start = Kolab::Conversion::toDate(startDate).toUtc();
- const KDateTime end = Kolab::Conversion::toDate(endDate).toUtc();
+ /*
+ * TODO the conversion of date-only values to date-time is only necessary because xCal doesn't allow date only. iCalendar doesn't seem to make this restriction so it looks like a bug.
+ */
+ KDateTime start = startDate.toUtc();
+ if (start.isDateOnly()) {
+ start.setTime(QTime(0,0,0,0));
+ }
+ KDateTime end = endDate.toUtc();
+ if (end.isDateOnly()) {
+ end.addDays(1);
+ end.setTime(QTime(0,0,0,0)); //The window is inclusive
+ }
//TODO try to merge that with KCalCore::Freebusy
std::vector<Kolab::FreebusyPeriod> freebusyPeriods;
- foreach (const Kolab::Event &e, events) {
- KCalCore::Event::Ptr event = Kolab::Conversion::toKCalCore(e);
-
+ Q_FOREACH (KCalCore::Event::Ptr event, events) {
// If this event is transparent it shouldn't be in the freebusy list.
if ( event->transparency() == KCalCore::Event::Transparent ) {
continue;
@@ -88,7 +209,7 @@ Freebusy generateFreeBusy(const std::vector< Event >& events, const cDateTime& s
if ( event->recurs() ) {
const KCalCore::Duration duration( eventStart, eventEnd );
const KCalCore::DateTimeList list = event->recurrence()->timesInInterval(start, end);
- foreach (const KDateTime &dt, list) {
+ Q_FOREACH (const KDateTime &dt, list) {
const KDateTime utc = dt.toUtc();
const Kolab::Period &period = addLocalPeriod(utc, duration.end(utc), start, end);
if (period.isValid()) {
@@ -104,21 +225,21 @@ Freebusy generateFreeBusy(const std::vector< Event >& events, const cDateTime& s
if (!periods.empty()) {
Kolab::FreebusyPeriod period;
period.setPeriods(periods);
- //TODO get out of office from event
+ //TODO get busy type from event (out-of-office, tentative)
period.setType(Kolab::FreebusyPeriod::Busy);
- // period.setEvent(event->summary().toStdString(), event->uid().toStdString(), event->location().toStdString());
- //TODO event uid etc.
+ period.setEvent(event->uid().toStdString(), event->summary().toStdString(), event->location().toStdString());
freebusyPeriods.push_back(period);
}
}
Kolab::Freebusy freebusy;
- freebusy.setStart(startDate);
- freebusy.setEnd(endDate);
+
+ freebusy.setStart(Kolab::Conversion::fromDate(start));
+ freebusy.setEnd(Kolab::Conversion::fromDate(end));
freebusy.setPeriods(freebusyPeriods);
freebusy.setUid(QUuid::createUuid().toString().toStdString());
freebusy.setTimestamp(Kolab::Conversion::fromDate(KDateTime::currentUtcDateTime()));
- freebusy.setOrganizer(ContactReference(Kolab::ContactReference::EmailReference, "email", "name"));
+ freebusy.setOrganizer(ContactReference(Kolab::ContactReference::EmailReference, organizer->email().toStdString(), organizer->name().toStdString()));
return freebusy;
}
diff --git a/freebusy/freebusy.h b/freebusy/freebusy.h
index fbea05f..a61e1c4 100644
--- a/freebusy/freebusy.h
+++ b/freebusy/freebusy.h
@@ -22,12 +22,15 @@
#include "kolab_export.h"
#include <kolabevent.h>
#include <kolabfreebusy.h>
+#include <KCalCore/Event>
namespace Kolab {
namespace FreebusyUtils {
-Kolab::Freebusy generateFreeBusy(const std::vector<Kolab::Event> &events, const Kolab::cDateTime &startDate, const Kolab::cDateTime &endDate, const Kolab::Freebusy &existing = Kolab::Freebusy());
-std::string toIFB(const Kolab::Freebusy &);
+KOLAB_EXPORT Freebusy generateFreeBusy(const QList<KCalCore::Event::Ptr>& events, const KDateTime& startDate, const KDateTime& endDate, const KCalCore::Person::Ptr &organizer);
+KOLAB_EXPORT std::string toIFB(const Kolab::Freebusy &);
+
+Kolab::Freebusy generateFreeBusy(const std::vector<Kolab::Event> &events, const Kolab::cDateTime &startDate, const Kolab::cDateTime &endDate);
}
}
diff --git a/kolabformat/kolabdefinitions.h b/kolabformat/kolabdefinitions.h
index 2fdcf70..0d53c8e 100644
--- a/kolabformat/kolabdefinitions.h
+++ b/kolabformat/kolabdefinitions.h
@@ -28,7 +28,8 @@ namespace Kolab {
#define KOLAB_FOLDER_TYPE_TASK "task"
#define KOLAB_FOLDER_TYPE_JOURNAL "journal"
#define KOLAB_FOLDER_TYPE_NOTE "note"
-#define KOLAB_FOLDER_TYPE_CONFIGURATION "configuration"
+#define KOLAB_FOLDER_TYPE_CONFIGURATION "configuration"
+#define KOLAB_FOLDER_TYPE_FREEBUSY "freebusy"
#define KOLAB_FOLDER_TYPE_DEFAULT_SUFFIX ".default"
@@ -50,6 +51,7 @@ static QString distlistKolabTypeCompat() { return QString::fromLatin1("applicati
static QString noteKolabType() { return QString::fromLatin1("application/x-vnd.kolab.note"); }
static QString configurationKolabType() { return QString::fromLatin1("application/x-vnd.kolab.configuration"); }
static QString dictKolabType() { return QString::fromLatin1("application/x-vnd.kolab.configuration.dictionary"); }
+static QString freebusyKolabType() { return QString::fromLatin1("application/x-vnd.kolab.freebusy"); }
static QString xCalMimeType() { return QString::fromLatin1("application/calendar+xml"); };
static QString xCardMimeType() { return QString::fromLatin1("application/vcard+xml"); };
diff --git a/kolabformat/kolabobject.cpp b/kolabformat/kolabobject.cpp
index 0af095d..4e76444 100644
--- a/kolabformat/kolabobject.cpp
+++ b/kolabformat/kolabobject.cpp
@@ -468,6 +468,16 @@ KMime::Message::Ptr KolabObjectWriter::writeDictionary(const QStringList &entrie
return Mime::createMessage(QString::fromStdString(configuration.uid()), kolabMimeType(), dictKolabType(), QString::fromStdString(v3String).toLocal8Bit(), true, getProductId(productId));
}
+KMime::Message::Ptr KolabObjectWriter::writeFreebusy(const Freebusy &freebusy, Version v, const QString& productId)
+{
+ ErrorHandler::clearErrors();
+ if (v != KolabV3) {
+ Critical() << "only v3 implementation available";
+ }
+ const std::string &v3String = Kolab::writeFreebusy(freebusy, getProductId(productId).toStdString());
+ ErrorHandler::handleLibkolabxmlErrors();
+ return Mime::createMessage(QString::fromStdString(freebusy.uid()), xCalMimeType(), freebusyKolabType(), QString::fromStdString(v3String).toLocal8Bit(), true, getProductId(productId));
+}
diff --git a/kolabformat/kolabobject.h b/kolabformat/kolabobject.h
index ecde1f1..7cea7bb 100644
--- a/kolabformat/kolabobject.h
+++ b/kolabformat/kolabobject.h
@@ -30,6 +30,8 @@
namespace Kolab {
+class Freebusy;
+
enum Version {
KolabV2,
KolabV3
@@ -43,7 +45,8 @@ enum ObjectType {
ContactObject,
DistlistObject,
NoteObject,
- DictionaryConfigurationObject
+ DictionaryConfigurationObject,
+ FreebusyObject
};
KOLAB_EXPORT KCalCore::Event::Ptr readV2EventXML(const QByteArray &xmlData, QStringList &attachments);
@@ -109,6 +112,8 @@ public:
static KMime::Message::Ptr writeDistlist(const KABC::ContactGroup &, Version v = KolabV3, const QString &productId = QString());
static KMime::Message::Ptr writeNote(const KMime::Message::Ptr &, Version v = KolabV3, const QString &productId = QString());
static KMime::Message::Ptr writeDictionary(const QStringList &, const QString &lang, Version v = KolabV3, const QString &productId = QString());
+ static KMime::Message::Ptr writeFreebusy(const Kolab::Freebusy &, Version v = KolabV3, const QString &productId = QString());
+
};
}; //Namespace
commit 03dcd483cce6e7dfd6aafcb071bb7c5806a93522
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Tue Jun 26 15:14:47 2012 +0200
better error messages
diff --git a/kolabformat/kolabobject.cpp b/kolabformat/kolabobject.cpp
index 27f7ef7..0af095d 100644
--- a/kolabformat/kolabobject.cpp
+++ b/kolabformat/kolabobject.cpp
@@ -121,6 +121,14 @@ QByteArray getMimeType(Kolab::ObjectType type)
return QByteArray();
}
+void printMessageDebugInfo(const KMime::Message::Ptr &msg)
+{
+ //TODO replace by Debug stream for Mimemessage
+ Debug() << "MessageId: " << msg->messageID()->asUnicodeString();
+ Debug() << "Subject: " << msg->subject()->asUnicodeString();
+// Debug() << msg->encodedContent();
+}
+
ObjectType KolabObjectReader::parseMimeMessage(const KMime::Message::Ptr &msg)
{
ErrorHandler::clearErrors();
@@ -128,6 +136,7 @@ ObjectType KolabObjectReader::parseMimeMessage(const KMime::Message::Ptr &msg)
KMime::Headers::Base *xKolabHeader = msg->getHeaderByType(X_KOLAB_TYPE_HEADER);
if (!xKolabHeader) {
CRITICAL("could not find the X-Kolab-Type Header");
+ printMessageDebugInfo(msg);
return InvalidObject;
}
const QString &kolabType = xKolabHeader->asUnicodeString(); //TODO we probably shouldn't use unicodeString
@@ -141,7 +150,7 @@ ObjectType KolabObjectReader::parseMimeMessage(const KMime::Message::Ptr &msg)
d->mVersion = KolabV2;
} else {
if (xKolabVersion->asUnicodeString() != KOLAB_VERSION_V3) { //TODO version compatibility check?
- WARNING("Kolab Version Header available but not on the same version as the implementation");
+ Warning() << "Kolab Version Header available but not on the same version as the implementation: " << xKolabVersion->asUnicodeString();
}
d->mVersion = KolabV3;
}
@@ -150,7 +159,8 @@ ObjectType KolabObjectReader::parseMimeMessage(const KMime::Message::Ptr &msg)
if (d->mObjectType == DictionaryConfigurationObject) {
KMime::Content *xmlContent = Mime::findContentByType( msg, "application/xml" );
if ( !xmlContent ) {
- CRITICAL("no part found");
+ Critical() << "no application/xml part found";
+ printMessageDebugInfo(msg);
return InvalidObject;
}
const QByteArray &xmlData = xmlContent->decodedContent();
@@ -160,7 +170,8 @@ ObjectType KolabObjectReader::parseMimeMessage(const KMime::Message::Ptr &msg)
}
KMime::Content *xmlContent = Mime::findContentByType( msg, kolabType.toLocal8Bit() );
if ( !xmlContent ) {
- CRITICAL("no part found");
+ Critical() << "no part with type" << kolabType.toLocal8Bit() << " found";
+ printMessageDebugInfo(msg);
return InvalidObject;
}
const QByteArray &xmlData = xmlContent->decodedContent();
@@ -199,7 +210,8 @@ ObjectType KolabObjectReader::parseMimeMessage(const KMime::Message::Ptr &msg)
} else { //V3
KMime::Content *xmlContent = Mime::findContentByType( msg, getMimeType(d->mObjectType) );
if ( !xmlContent ) {
- CRITICAL("no part found");
+ Critical() << "no " << getMimeType(d->mObjectType) << " part found";
+ printMessageDebugInfo(msg);
return InvalidObject;
}
switch (d->mObjectType) {
@@ -244,7 +256,8 @@ ObjectType KolabObjectReader::parseMimeMessage(const KMime::Message::Ptr &msg)
}
break;
default:
- CRITICAL("no kolab object found "+kolabType);
+ Critical() << "no kolab object found " << kolabType;
+ printMessageDebugInfo(msg);
break;
}
commit 7412e6d6fd37f5a18024ae631ae3f3b4df0f3353
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Tue Jun 26 15:14:29 2012 +0200
uid in subject
diff --git a/kolabformat/kolabobject.cpp b/kolabformat/kolabobject.cpp
index 1f46d95..27f7ef7 100644
--- a/kolabformat/kolabobject.cpp
+++ b/kolabformat/kolabobject.cpp
@@ -417,7 +417,7 @@ KMime::Message::Ptr KolabObjectWriter::writeDistlist(const KABC::ContactGroup &d
const Kolab::DistList &dist = Kolab::Conversion::fromKABC(distlist);
const std::string &v3String = Kolab::writeDistlist(dist, getProductId(productId).toStdString());
ErrorHandler::handleLibkolabxmlErrors();
- return Mime::createMessage(QString(), xCardMimeType(), contactKolabType(), QString::fromStdString(v3String).toLocal8Bit(), true, getProductId(productId));
+ return Mime::createMessage(QString::fromStdString(dist.uid()), xCardMimeType(), contactKolabType(), QString::fromStdString(v3String).toLocal8Bit(), true, getProductId(productId));
}
KolabV2::DistributionList d(&distlist);
return distListToKolabFormat(d, getProductId(productId));
@@ -431,7 +431,7 @@ KMime::Message::Ptr KolabObjectWriter::writeNote(const KMime::Message::Ptr ¬e
const Kolab::Note &n = Kolab::Conversion::fromNote(note);
const std::string &v3String = Kolab::writeNote(n, getProductId(productId).toStdString());
ErrorHandler::handleLibkolabxmlErrors();
- return Mime::createMessage(QString::fromStdString(n.summary()), kolabMimeType(), noteKolabType(), QString::fromStdString(v3String).toLocal8Bit(), true, getProductId(productId));
+ return Mime::createMessage(QString::fromStdString(n.uid()), kolabMimeType(), noteKolabType(), QString::fromStdString(v3String).toLocal8Bit(), true, getProductId(productId));
}
return noteToKolab(note, getProductId(productId));
}
@@ -452,8 +452,7 @@ KMime::Message::Ptr KolabObjectWriter::writeDictionary(const QStringList &entrie
Kolab::Configuration configuration(dictionary); //TODO preserve creation/lastModified date
const std::string &v3String = Kolab::writeConfiguration(configuration, getProductId(productId).toStdString());
ErrorHandler::handleLibkolabxmlErrors();
- //TODO uid in subject?
- return Mime::createMessage(QString(), kolabMimeType(), dictKolabType(), QString::fromStdString(v3String).toLocal8Bit(), true, getProductId(productId));
+ return Mime::createMessage(QString::fromStdString(configuration.uid()), kolabMimeType(), dictKolabType(), QString::fromStdString(v3String).toLocal8Bit(), true, getProductId(productId));
}
commit 0a13780403fa30f2f4f9474239f2a18ff0d1f017
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Tue Jun 26 15:12:47 2012 +0200
make it easy to print an error.
diff --git a/kolabformat/errorhandler.cpp b/kolabformat/errorhandler.cpp
index 4fc5147..3b2f98a 100644
--- a/kolabformat/errorhandler.cpp
+++ b/kolabformat/errorhandler.cpp
@@ -40,6 +40,7 @@ void ErrorHandler::addError(ErrorHandler::Severity s, const QString& message, co
}
if (s > m_worstError) {
m_worstError = s;
+ m_worstErrorMessage = message;
}
m_errorQueue.append(Err(s, message, location));
}
@@ -49,6 +50,11 @@ ErrorHandler::Severity ErrorHandler::error() const
return m_worstError;
}
+QString ErrorHandler::errorMessage() const
+{
+ return m_worstErrorMessage;
+}
+
const QList< ErrorHandler::Err >& ErrorHandler::getErrors() const
{
return m_errorQueue;
diff --git a/kolabformat/errorhandler.h b/kolabformat/errorhandler.h
index 73047cc..254a741 100644
--- a/kolabformat/errorhandler.h
+++ b/kolabformat/errorhandler.h
@@ -66,6 +66,7 @@ public:
void addError(Severity s, const QString &message, const QString &location);
const QList <Err> &getErrors() const;
Severity error() const;
+ QString errorMessage() const;
void clear();
/**
@@ -84,6 +85,7 @@ private:
ErrorHandler & operator= (const ErrorHandler &);
Severity m_worstError;
+ QString m_worstErrorMessage;
QList <Err> m_errorQueue;
};
commit 2dc0f49a574325bdddf505983b3d4f6e15c8a023
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Thu Jun 21 17:16:10 2012 +0200
Freebusy generation from events and ical file writing
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3f3186d..30c84a0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -73,6 +73,7 @@ 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)
@@ -87,6 +88,7 @@ set(KOLAB_SRCS
${ICALENDAR_SRCS}
${CALENDARING_MOC}
${CONVERSION_MOC}
+ ${FREEBUSY_SRCS}
)
set(KOLAB_LINK_LIBRARIES
diff --git a/freebusy/CMakeLists.txt b/freebusy/CMakeLists.txt
new file mode 100644
index 0000000..f1f584e
--- /dev/null
+++ b/freebusy/CMakeLists.txt
@@ -0,0 +1,3 @@
+set (FREEBUSY_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/freebusy.cpp
+ PARENT_SCOPE)
diff --git a/freebusy/freebusy.cpp b/freebusy/freebusy.cpp
new file mode 100644
index 0000000..ceb5bc2
--- /dev/null
+++ b/freebusy/freebusy.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2012 Christian Mollekopf <mollekopf at 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 "freebusy.h"
+#include "conversion/kcalconversion.h"
+#include <kcalcore/freebusy.h>
+#include <kcalcore/icalformat.h>
+#include <kdebug.h>
+#include <quuid.h>
+
+
+namespace Kolab {
+ namespace FreebusyUtils {
+
+
+Kolab::Period addLocalPeriod( const KDateTime &eventStart, const KDateTime &eventEnd, const KDateTime &mDtStart, const KDateTime &mDtEnd)
+{
+ KDateTime tmpStart;
+ KDateTime tmpEnd;
+
+ //Check to see if the start *or* end of the event is
+ //between the start and end of the freebusy dates.
+ if ( !( ( ( mDtStart <= eventStart) &&
+ ( eventStart <= mDtEnd ) ) ||
+ ( ( mDtStart <= eventEnd ) &&
+ ( eventEnd <= mDtEnd ) ) ) ) {
+ qDebug() << "out of scope";
+ return Kolab::Period();
+ }
+
+ if ( eventStart < mDtStart ) { //eventStart is before start
+ tmpStart = mDtStart;
+ } else {
+ tmpStart = eventStart;
+ }
+
+ qDebug() << eventEnd.date().toString() << eventEnd.time().toString() << mDtEnd.toString();
+ if ( eventEnd > mDtEnd ) { //event end is after dtEnd
+ tmpEnd = mDtEnd;
+ } else {
+ tmpEnd = eventEnd;
+ }
+ Q_ASSERT(tmpStart.isValid());
+ Q_ASSERT(tmpEnd.isValid());
+ return Kolab::Period(Kolab::Conversion::fromDate(tmpStart), Kolab::Conversion::fromDate(tmpEnd));
+}
+
+
+
+Freebusy generateFreeBusy(const std::vector< Event >& events, const cDateTime& startDate, const cDateTime& endDate, const Freebusy& existing)
+{
+ const KDateTime start = Kolab::Conversion::toDate(startDate).toUtc();
+ const KDateTime end = Kolab::Conversion::toDate(endDate).toUtc();
+
+ //TODO try to merge that with KCalCore::Freebusy
+ std::vector<Kolab::FreebusyPeriod> freebusyPeriods;
+ foreach (const Kolab::Event &e, events) {
+ KCalCore::Event::Ptr event = Kolab::Conversion::toKCalCore(e);
+
+ // If this event is transparent it shouldn't be in the freebusy list.
+ if ( event->transparency() == KCalCore::Event::Transparent ) {
+ continue;
+ }
+
+ if ( event->hasRecurrenceId() ) {
+ continue; //TODO apply special period exception (duration could be different)
+ }
+
+ const KDateTime eventStart = event->dtStart().toUtc();
+ const KDateTime eventEnd = event->dtEnd().toUtc();
+
+ std::vector <Kolab::Period> periods;
+ if ( event->recurs() ) {
+ const KCalCore::Duration duration( eventStart, eventEnd );
+ const KCalCore::DateTimeList list = event->recurrence()->timesInInterval(start, end);
+ foreach (const KDateTime &dt, list) {
+ const KDateTime utc = dt.toUtc();
+ const Kolab::Period &period = addLocalPeriod(utc, duration.end(utc), start, end);
+ if (period.isValid()) {
+ periods.push_back(period);
+ }
+ }
+ } else {
+ const Kolab::Period &period = addLocalPeriod(eventStart, eventEnd, start, end);
+ if (period.isValid()) {
+ periods.push_back(period);
+ }
+ }
+ if (!periods.empty()) {
+ Kolab::FreebusyPeriod period;
+ period.setPeriods(periods);
+ //TODO get out of office from event
+ period.setType(Kolab::FreebusyPeriod::Busy);
+ // period.setEvent(event->summary().toStdString(), event->uid().toStdString(), event->location().toStdString());
+ //TODO event uid etc.
+ freebusyPeriods.push_back(period);
+ }
+ }
+
+ Kolab::Freebusy freebusy;
+ freebusy.setStart(startDate);
+ freebusy.setEnd(endDate);
+ freebusy.setPeriods(freebusyPeriods);
+ freebusy.setUid(QUuid::createUuid().toString().toStdString());
+ freebusy.setTimestamp(Kolab::Conversion::fromDate(KDateTime::currentUtcDateTime()));
+ freebusy.setOrganizer(ContactReference(Kolab::ContactReference::EmailReference, "email", "name"));
+
+ return freebusy;
+}
+
+std::string toIFB(const Kolab::Freebusy &freebusy)
+{
+ KCalCore::FreeBusy::Ptr fb(new KCalCore::FreeBusy(Kolab::Conversion::toDate(freebusy.start()), Kolab::Conversion::toDate(freebusy.end())));
+ KCalCore::FreeBusyPeriod::List list;
+ Q_FOREACH (const Kolab::FreebusyPeriod &fbPeriod, freebusy.periods()) {
+ Q_FOREACH (const Kolab::Period &p, fbPeriod.periods()) {
+ KCalCore::FreeBusyPeriod period(Kolab::Conversion::toDate(p.start), Kolab::Conversion::toDate(p.end));
+// period.setSummary("summary"); Doesn't even work. X-SUMMARY is read though (just not written out)
+ //TODO
+ list.append(period);
+
+ }
+ }
+ fb->addPeriods(list);
+
+ fb->setUid(QString::fromStdString(freebusy.uid()));
+ fb->setOrganizer(KCalCore::Person::Ptr(new KCalCore::Person(QString::fromStdString(freebusy.organizer().name()), QString::fromStdString(freebusy.organizer().email()))));
+ fb->setLastModified(Kolab::Conversion::toDate(freebusy.timestamp()));
+
+ KCalCore::ICalFormat format;
+ QString data = format.createScheduleMessage( fb, KCalCore::iTIPPublish );
+ return data.toStdString();
+}
+
+ }
+}
diff --git a/freebusy/freebusy.h b/freebusy/freebusy.h
new file mode 100644
index 0000000..fbea05f
--- /dev/null
+++ b/freebusy/freebusy.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 Christian Mollekopf <mollekopf at 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 FREEBUSY_H
+#define FREEBUSY_H
+
+#include "kolab_export.h"
+#include <kolabevent.h>
+#include <kolabfreebusy.h>
+
+namespace Kolab {
+ namespace FreebusyUtils {
+
+Kolab::Freebusy generateFreeBusy(const std::vector<Kolab::Event> &events, const Kolab::cDateTime &startDate, const Kolab::cDateTime &endDate, const Kolab::Freebusy &existing = Kolab::Freebusy());
+std::string toIFB(const Kolab::Freebusy &);
+
+ }
+}
+
+#endif // FREEBUSY_H
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 2f1f80e..a9df2b6 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -2,25 +2,29 @@
include_directories(${CMAKE_CURRENT_BINARY_DIR})
QT4_AUTOMOC(benchmark.cpp)
-add_executable(benchmarktest benchmark.cpp ${CMAKE_CURRENT_BINARY_DIR}/${BINDINGSTEST_MOC})
+add_executable(benchmarktest benchmark.cpp)
target_link_libraries(benchmarktest ${QT_QTTEST_LIBRARY} kolab_static)
QT4_AUTOMOC(formattest.cpp)
-add_executable(formattest formattest.cpp ${CMAKE_CURRENT_BINARY_DIR}/${BINDINGSTEST_MOC})
+add_executable(formattest formattest.cpp)
target_link_libraries(formattest ${QT_QTTEST_LIBRARY} kolab_static)
QT4_AUTOMOC(upgradetest.cpp)
-add_executable(upgradetest upgradetest.cpp ${CMAKE_CURRENT_BINARY_DIR}/${BINDINGSTEST_MOC})
+add_executable(upgradetest upgradetest.cpp)
target_link_libraries(upgradetest ${QT_QTTEST_LIBRARY} kolab_static)
QT4_AUTOMOC(kcalconversiontest.cpp)
-add_executable(kcalconversiontest kcalconversiontest.cpp ${CMAKE_CURRENT_BINARY_DIR}/${BINDINGSTEST_MOC})
+add_executable(kcalconversiontest kcalconversiontest.cpp)
target_link_libraries(kcalconversiontest ${QT_QTTEST_LIBRARY} kolab_static)
QT4_AUTOMOC(calendaringtest.cpp)
-add_executable(calendaringtest calendaringtest.cpp ${CMAKE_CURRENT_BINARY_DIR}/${BINDINGSTEST_MOC})
+add_executable(calendaringtest calendaringtest.cpp)
target_link_libraries(calendaringtest ${QT_QTTEST_LIBRARY} kolab_static)
QT4_AUTOMOC(icalendartest.cpp)
-add_executable(icalendartest icalendartest.cpp ${CMAKE_CURRENT_BINARY_DIR}/${BINDINGSTEST_MOC})
-target_link_libraries(icalendartest ${QT_QTTEST_LIBRARY} kolab_static)
\ No newline at end of file
+add_executable(icalendartest icalendartest.cpp)
+target_link_libraries(icalendartest ${QT_QTTEST_LIBRARY} kolab_static)
+
+QT4_AUTOMOC(freebusytest.cpp)
+add_executable(freebusytest freebusytest.cpp)
+target_link_libraries(freebusytest ${QT_QTTEST_LIBRARY} kolab_static)
\ No newline at end of file
diff --git a/tests/calendaringtest.cpp b/tests/calendaringtest.cpp
index 3671ecb..9ad29bf 100644
--- a/tests/calendaringtest.cpp
+++ b/tests/calendaringtest.cpp
@@ -26,15 +26,7 @@
#include <calendaring/event.h>
#include "testhelpers.h"
-
-
-Kolab::Event createEvent(const Kolab::cDateTime &start, const Kolab::cDateTime &end)
-{
- Kolab::Event event;
- event.setStart(start);
- event.setEnd(end);
- return event;
-}
+#include "testutils.h"
void compareEvents(const std::vector<Kolab::Event> &list1, const std::vector<Kolab::Event> &list2)
{
diff --git a/tests/freebusytest.cpp b/tests/freebusytest.cpp
new file mode 100644
index 0000000..40adf6b
--- /dev/null
+++ b/tests/freebusytest.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2012 Christian Mollekopf <mollekopf at 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 "freebusytest.h"
+#include "testutils.h"
+#include "testhelpers.h"
+
+#include <QTest>
+#include "freebusy/freebusy.h"
+#include <kolabfreebusy.h>
+
+
+void FreebusyTest::testFB_data()
+{
+ QTest::addColumn<Kolab::cDateTime>( "start" );
+ QTest::addColumn<Kolab::cDateTime>( "end" );
+ QTest::addColumn< std::vector<Kolab::Event> >( "events" );
+ QTest::addColumn< std::vector<Kolab::FreebusyPeriod> >( "output" );
+
+
+ //UTC check
+ {
+ Kolab::Period p1(Kolab::cDateTime(2011,10,6,12,1,1,true), Kolab::cDateTime(2011,10,7,12,1,1,true));
+ Kolab::Period p2(Kolab::cDateTime(2011,10,8,12,1,1,true), Kolab::cDateTime(2011,10,9,12,1,1,true));
+ Kolab::Period p3(Kolab::cDateTime(2011,10,10,12,1,1,true), Kolab::cDateTime(2011,10,11,12,1,1,true));
+
+ std::vector<Kolab::Event> events;
+ events.push_back(createEvent(p1.start, p1.end));
+ events.push_back(createEvent(p2.start, p2.end));
+ events.push_back(createEvent(p3.start, p3.end));
+
+ Kolab::FreebusyPeriod period1;
+ period1.setType(Kolab::FreebusyPeriod::Busy);
+ period1.setPeriods(std::vector<Kolab::Period>() << p1);
+
+ Kolab::FreebusyPeriod period2;
+ period2.setType(Kolab::FreebusyPeriod::Busy);
+ period2.setPeriods(std::vector<Kolab::Period>() << p2);
+
+ Kolab::FreebusyPeriod period3;
+ period3.setType(Kolab::FreebusyPeriod::Busy);
+ period3.setPeriods(std::vector<Kolab::Period>() << p3);
+
+ {
+ std::vector<Kolab::FreebusyPeriod> output;
+ output.push_back(period1);
+ output.push_back(period2);
+ output.push_back(period3);
+
+ QTest::newRow( "simple utc" ) << Kolab::cDateTime(2010, 1, 1,1,1,1,true) << Kolab::cDateTime(2012, 1, 1,1,1,1,true) << events << output;
+ }
+
+ {
+ std::vector<Kolab::FreebusyPeriod> output;
+ output.push_back(period2);
+ output.push_back(period3);
+
+ QTest::newRow( "limit utc below" ) << Kolab::cDateTime(2011,10,8,12,1,1,true) << Kolab::cDateTime(2012, 1, 1,1,1,1,true) << events << output;
+ }
+ {
+ std::vector<Kolab::FreebusyPeriod> output;
+ output.push_back(period1);
+ output.push_back(period2);
+
+ QTest::newRow( "limit utc above" ) << Kolab::cDateTime(2010, 1, 1,1,1,1,true) << Kolab::cDateTime(2011,10,9,12,1,1,true) << events << output;
+ }
+ }
+ {
+ Kolab::Event event;
+ event.setStart(Kolab::cDateTime(2011,1,1,0,0,0,true));
+ event.setEnd(Kolab::cDateTime(2011,1,1,1,0,0,true));
+ Kolab::RecurrenceRule rrule;
+ rrule.setFrequency(Kolab::RecurrenceRule::Daily);
+ rrule.setInterval(1);
+ rrule.setCount(2);
+ event.setRecurrenceRule(rrule);
+
+ std::vector<Kolab::Event> events;
+ events.push_back(event);
+
+ std::vector<Kolab::FreebusyPeriod> output;
+ Kolab::FreebusyPeriod period1;
+ period1.setType(Kolab::FreebusyPeriod::Busy);
+ period1.setPeriods(std::vector<Kolab::Period>() << Kolab::Period(Kolab::cDateTime(2011,1,1,0,0,0,true), Kolab::cDateTime(2011,1,1,1,0,0,true))
+ << Kolab::Period(Kolab::cDateTime(2011,1,2,0,0,0,true), Kolab::cDateTime(2011,1,2,1,0,0,true))
+ );
+ output.push_back(period1);
+
+ QTest::newRow( "fullday recurrence" ) << Kolab::cDateTime(2010, 1, 1,1,1,1,true) << Kolab::cDateTime(2012,10,9,12,1,1,true) << events << output;
+ }
+}
+
+
+void FreebusyTest::testFB()
+{
+ QFETCH(Kolab::cDateTime, start);
+ QFETCH(Kolab::cDateTime, end);
+ QFETCH(std::vector<Kolab::Event>, events);
+ QFETCH(std::vector<Kolab::FreebusyPeriod>, output);
+
+ Kolab::Freebusy fb = Kolab::FreebusyUtils::generateFreeBusy(events, start, end);
+
+ QCOMPARE((int)fb.periods().size(), (int)output.size());
+ for (int i = 0; i<output.size(); i++) {
+ QCOMPARE(fb.periods().at(i), output.at(i));
+ }
+
+ std::cout << Kolab::FreebusyUtils::toIFB(fb);
+}
+
+// void FreebusyTest::testHonorTimeFrame()
+// {
+//
+// Kolab::Period p1(Kolab::cDateTime(2011,10,6,12,1,1,true), Kolab::cDateTime(2011,10,8,12,1,1,true));
+// Kolab::Period p2(Kolab::cDateTime(2011,10,7,12,1,1,true), Kolab::cDateTime(2011,10,10,12,1,1,true));
+// Kolab::Period p3(Kolab::cDateTime(2011,10,9,12,1,1,true), Kolab::cDateTime(2011,10,11,12,1,1,true));
+//
+// std::vector<Kolab::Event> events;
+// events.push_back(createEvent(p1.start, p1.end));
+// events.push_back(createEvent(p2.start, p2.end));
+// events.push_back(createEvent(p3.start, p3.end));
+//
+// Kolab::FreebusyPeriod period1;
+// period1.setType(Kolab::FreebusyPeriod::Busy);
+// period1.setPeriods(std::vector<Kolab::Period>() << p1);
+//
+// Kolab::FreebusyPeriod period2;
+// period2.setType(Kolab::FreebusyPeriod::Busy);
+// period2.setPeriods(std::vector<Kolab::Period>() << p2);
+//
+// Kolab::FreebusyPeriod period3;
+// period3.setType(Kolab::FreebusyPeriod::Busy);
+// period3.setPeriods(std::vector<Kolab::Period>() << p3);
+//
+//
+// Kolab::Freebusy fb = Kolab::FreebusyUtils::generateFreeBusy(events, Kolab::cDateTime(2010, 1, 1,1,1,1,true), Kolab::cDateTime(2012, 1, 1,1,1,1,true));
+// QCOMPARE((int)fb.periods().size(), 3);
+// QCOMPARE(fb.periods().at(0), period1);
+// QCOMPARE(fb.periods().at(1), period2);
+// QCOMPARE(fb.periods().at(2), period3);
+// }
+
+QTEST_MAIN( FreebusyTest )
+
+#include "freebusytest.moc"
\ No newline at end of file
diff --git a/tests/freebusytest.h b/tests/freebusytest.h
new file mode 100644
index 0000000..a27b9b5
--- /dev/null
+++ b/tests/freebusytest.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 Christian Mollekopf <mollekopf at 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 FREEBUSYTEST_H
+#define FREEBUSYTEST_H
+#include <QObject>
+
+class FreebusyTest: public QObject
+{
+ Q_OBJECT
+private slots:
+
+ void testFB_data();
+ void testFB();
+};
+
+#endif // FREEBUSYTEST_H
diff --git a/tests/testhelpers.h b/tests/testhelpers.h
index 614ddd2..02ef659 100644
--- a/tests/testhelpers.h
+++ b/tests/testhelpers.h
@@ -38,14 +38,16 @@ Q_DECLARE_METATYPE(std::vector<Kolab::Event>);
Q_DECLARE_METATYPE(Kolab::Todo);
Q_DECLARE_METATYPE(Kolab::Journal);
Q_DECLARE_METATYPE(Kolab::Contact);
+Q_DECLARE_METATYPE(Kolab::Period);
+Q_DECLARE_METATYPE(std::vector<Kolab::FreebusyPeriod>);
+
Q_DECLARE_METATYPE(KCalCore::Event);
Q_DECLARE_METATYPE(KCalCore::Todo);
Q_DECLARE_METATYPE(KCalCore::Journal);
Q_DECLARE_METATYPE(KCalCore::Duration);
namespace QTest {
-
-
+
template<>
char *toString(const Kolab::cDateTime &dt)
{
@@ -263,13 +265,42 @@ namespace QTest {
{
QByteArray ba = "vector<Kolab::CustomProperty>(";
for (int i = 0; i < v.size(); i++) {
- ba += QByteArray(toString(v.at(i)))+ "\n";
- }
- ba += ")";
- return qstrdup(ba.data());
+ ba += QByteArray(toString(v.at(i)))+ "\n";
+ }
+ ba += ")";
+ return qstrdup(ba.data());
}
+ template<>
+ char *toString(const Kolab::Period &p)
+ {
+ QByteArray ba = "Kolab::Period(";
+ ba += QByteArray(toString(p.start))+ "\n";
+ ba += QByteArray(toString(p.end))+ "\n";
+ ba += ")";
+ return qstrdup(ba.data());
+ }
+ template<>
+ char *toString(const std::vector<Kolab::Period> &v)
+ {
+ QByteArray ba = "vector<Kolab::Period>(";
+ for (int i = 0; i < v.size(); i++) {
+ ba += QByteArray(toString(v.at(i)))+ "\n";
+ }
+ ba += ")";
+ return qstrdup(ba.data());
+ }
+
+ template<>
+ char *toString(const Kolab::FreebusyPeriod &p)
+ {
+ QByteArray ba = "Kolab::FreebusyPeriod(";
+ ba += QString::number(p.type())+ "\n";
+ ba += QByteArray(toString(p.periods()))+ "\n";
+ ba += ")";
+ return qstrdup(ba.data());
+ }
}
diff --git a/tests/testutils.h b/tests/testutils.h
index 82c4541..32842ae 100644
--- a/tests/testutils.h
+++ b/tests/testutils.h
@@ -23,6 +23,7 @@
#include <qtemporaryfile.h>
#include <qprocess.h>
#include <kdebug.h>
+#include <kolabevent.h>
#include <kmime/kmime_message.h>
#include "kolabformat/kolabobject.h"
@@ -180,3 +181,11 @@ void normalizeContact(KABC::Addressee &addressee)
addressee.removeCustom("KOLAB", "SoundAttachmentName");
}
+
+Kolab::Event createEvent(const Kolab::cDateTime &start, const Kolab::cDateTime &end)
+{
+ Kolab::Event event;
+ event.setStart(start);
+ event.setEnd(end);
+ return event;
+}
\ No newline at end of file
commit fbae47849490c8ddba0bd092a0522b1b617fd1c0
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Thu Jun 21 17:13:04 2012 +0200
resolved merge conflict (something was messed up)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f26b32d..3f3186d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -74,7 +74,21 @@ add_subdirectory(conversion)
add_subdirectory(calendaring)
add_subdirectory(icalendar)
-set(KOLAB_SRCS kolabformat/kolabobject.cpp kolabformat/errorhandler.cpp mime/mimeutils.cpp ${CONVERSION_SRCS} ${kolabformatv2_SRCS} ${CALENDARING_SRCS} ${ICALENDAR_SRCS})
+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/errorhandler.cpp
+ mime/mimeutils.cpp
+ ${CONVERSION_SRCS}
+ ${kolabformatv2_SRCS}
+ ${CALENDARING_SRCS}
+ ${ICALENDAR_SRCS}
+ ${CALENDARING_MOC}
+ ${CONVERSION_MOC}
+)
+
set(KOLAB_LINK_LIBRARIES
${Libkolabxml_LIBRARIES}
${KDEPIMLIBS_KCALCORE_LIBS}
commit 1423ad9aa65d62f5f962acc25d3fe785f2a3e7ed
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Tue Jun 19 23:38:33 2012 +0200
Use UTC timestamp in mime-message.
diff --git a/mime/mimeutils.cpp b/mime/mimeutils.cpp
index 3a7ee6c..23fd9c1 100644
--- a/mime/mimeutils.cpp
+++ b/mime/mimeutils.cpp
@@ -192,7 +192,7 @@ KMime::Content* createExplanationPart(bool v3)
KMime::Message::Ptr createMessage(const QString& xKolabType, bool v3, const QString &prodid)
{
KMime::Message::Ptr message( new KMime::Message );
- message->date()->setDateTime( KDateTime::currentLocalDateTime() );
+ message->date()->setDateTime( KDateTime::currentUtcDateTime() );
KMime::Headers::Generic *h = new KMime::Headers::Generic( X_KOLAB_TYPE_HEADER, message.get(), xKolabType, "utf-8" );
message->appendHeader( h );
if (v3) {
commit 614e083f3bf5c59fd3ab3035697d25cbf9295d7a
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Thu Jun 28 10:05:30 2012 +0200
Make libcalendaring an option
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 67ac3a5..af4d2a5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,6 +4,7 @@ cmake_minimum_required(VERSION 2.6.4)
option( BUILD_TESTS "Build the tests" TRUE )
option( PYTHON_BINDINGS "Build bindings for python" FALSE )
+option( USE_LIBCALENDARING "Use libcalendaring" FALSE )
set(Libkolab_MODULE_DIR ${Libkolab_SOURCE_DIR}/cmake/modules)
set(CMAKE_MODULE_PATH ${Libkolab_MODULE_DIR})
@@ -45,9 +46,10 @@ set(CMAKECONFIG_INSTALL_DIR ${LIB_INSTALL_DIR}/cmake/Libkolab )
find_package(Libkolabxml 0.7 REQUIRED)
find_package(Qt4 4.6.0 REQUIRED)
find_package(Libcalendaring)
-
-# find_package(KDE4 4.8 REQUIRED)
-# find_package(KdepimLibs 4.8 REQUIRED)
+if (NOT USE_LIBCALENDARING)
+ find_package(KDE4 4.8 REQUIRED)
+ find_package(KdepimLibs 4.8 REQUIRED)
+endif()
# add_definitions(-DKDEPIMLIBS_VERSION=0x${KdepimLibs_VERSION_MAJOR}0${KdepimLibs_VERSION_MINOR}${KDEPIMLIBS_VERSION_PATCH})
@@ -59,22 +61,25 @@ endif()
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS} -fPIC -g" )
-# 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}
-# )
-set( KDE_INCLUDES ${Libcalendaring_INCLUDE_DIRS} )
-set( KDE_LIBRARIES ${Libcalendaring_LIBRARIES} )
-
-message("${Libcalendaring_INCLUDE_DIRS} ${Libcalendaring_LIBRARIES}")
+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}
commit b99d69b8f85c5920989e1df1f0e40126779d0255
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Wed Jun 27 10:53:02 2012 +0200
Compile with libcalendaring
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 30c84a0..67ac3a5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -42,11 +42,13 @@ set(INCLUDE_INSTALL_DIR include/libkolab CACHE STRING "The directories where to
set(CMAKECONFIG_INSTALL_DIR ${LIB_INSTALL_DIR}/cmake/Libkolab )
# Do the building
+find_package(Libkolabxml 0.7 REQUIRED)
+find_package(Qt4 4.6.0 REQUIRED)
+find_package(Libcalendaring)
+
+# find_package(KDE4 4.8 REQUIRED)
+# find_package(KdepimLibs 4.8 REQUIRED)
-find_package(Qt4 4.7.0 REQUIRED)
-find_package(KDE4 4.8 REQUIRED)
-find_package(KdepimLibs 4.8 REQUIRED)
-find_package(Libkolabxml 0.6 REQUIRED)
# 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})) )
@@ -55,12 +57,28 @@ if("${KdepimLibs_VERSION}" VERSION_GREATER "4.8.40" )
add_definitions(-DKDEPIMLIBS_VERSION_DEVEL)
endif()
-set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS} -fPIC" )
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS} -fPIC -g" )
+
+# 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}
+# )
+set( KDE_INCLUDES ${Libcalendaring_INCLUDE_DIRS} )
+set( KDE_LIBRARIES ${Libcalendaring_LIBRARIES} )
+
+message("${Libcalendaring_INCLUDE_DIRS} ${Libcalendaring_LIBRARIES}")
include_directories(
${QT_INCLUDES}
- ${KDEPIMLIBS_INCLUDE_DIRS}
- ${KDE4_INCLUDE_DIR}
+ ${KDE_INCLUDES}
${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/kolabformatV2
${Libkolabxml_INCLUDES}
@@ -93,22 +111,14 @@ set(KOLAB_SRCS
set(KOLAB_LINK_LIBRARIES
${Libkolabxml_LIBRARIES}
- ${KDEPIMLIBS_KCALCORE_LIBS}
- ${KDEPIMLIBS_KABC_LIBS}
- ${KDEPIMLIBS_KMIME_LIBS}
- ${KDEPIMLIBS_AKONADI_LIBS}
- ${KDEPIMLIBS_AKONADI_NOTES_LIBS}
- ${KDEPIMLIBS_KCALUTILS_LIBS}
- ${KDEPIMLIBS_KPIMUTILS_LIBS}
${QT_QTCORE_LIBRARY}
${QT_QTXML_LIBRARY}
${QT_QTGUI_LIBRARY}
- ${KDE4_KDECORE_LIBRARY}
- ${KDE4_KIO_LIBRARY}
+ ${KDE_LIBRARIES}
)
if(BUILD_TESTS)
#for tests only
- kde4_add_library(kolab_static STATIC ${KOLAB_SRCS})
+ add_library(kolab_static STATIC ${KOLAB_SRCS})
target_link_libraries(kolab_static ${KOLAB_LINK_LIBRARIES})
add_subdirectory(tests)
endif(BUILD_TESTS)
@@ -131,6 +141,7 @@ install(FILES
kolabformat/errorhandler.h
conversion/kcalconversion.h
conversion/kabcconversion.h
+ freebusy/freebusy.h
DESTINATION ${INCLUDE_INSTALL_DIR}
)
diff --git a/calendaring/calendaring.cpp b/calendaring/calendaring.cpp
index 4579348..b7ad0e3 100644
--- a/calendaring/calendaring.cpp
+++ b/calendaring/calendaring.cpp
@@ -18,7 +18,7 @@
#include "calendaring.h"
#include <kcalcore/event.h>
-#include <KDE/KCalCore/Todo>
+#include <kcalcore/todo.h>
#include <Qt/qdebug.h>
#include <kolabevent.h>
diff --git a/cmake/modules/FindLibcalendaring.cmake b/cmake/modules/FindLibcalendaring.cmake
new file mode 100644
index 0000000..3c4c860
--- /dev/null
+++ b/cmake/modules/FindLibcalendaring.cmake
@@ -0,0 +1,20 @@
+find_package(PkgConfig)
+include(FindPackageHandleStandardArgs)
+
+find_library(CALENDARING_KDECORE NAMES calendaring-kdecore)
+find_library(CALENDARING_KCALCORE NAMES calendaring-kcalcore)
+find_library(CALENDARING_KMIME NAMES calendaring-kmime)
+find_library(CALENDARING_KIMAP NAMES calendaring-kimap)
+find_library(CALENDARING_KABC NAMES calendaring-kabc)
+find_library(CALENDARING_NOTES NAMES calendaring-akonadi-notes)
+find_library(CALENDARING_KCALUTILS NAMES calendaring-kcalutils)
+find_library(CALENDARING_KPIMUTILS NAMES calendaring-kpimutils)
+
+find_path(CALENDARING_INCLUDE_DIRS NAMES libcalendaring/kdatetime.h)
+
+set( Libcalendaring_INCLUDE_DIRS "${CALENDARING_INCLUDE_DIRS}/libcalendaring" )
+
+set( Libcalendaring_LIBRARIES ${CALENDARING_KDECORE} ${CALENDARING_KCALCORE} ${CALENDARING_KMIME} ${CALENDARING_KIMAP} ${CALENDARING_KABC} ${CALENDARING_NOTES} ${CALENDARING_KCALUTILS} ${CALENDARING_KPIMUTILS})
+
+find_package_handle_standard_args(Libcalendaring DEFAULT_MSG
+ CALENDARING_KDECORE CALENDARING_KCALCORE CALENDARING_KMIME CALENDARING_KIMAP CALENDARING_KABC CALENDARING_NOTES CALENDARING_KCALUTILS CALENDARING_KPIMUTILS CALENDARING_INCLUDE_DIRS)
diff --git a/conversion/kabcconversion.cpp b/conversion/kabcconversion.cpp
index b710891..a418333 100644
--- a/conversion/kabcconversion.cpp
+++ b/conversion/kabcconversion.cpp
@@ -327,10 +327,10 @@ std::string fromPicture(const KABC::Picture &pic, std::string &mimetype)
}
} else if ( !pic.url().isEmpty() ) {
QString tmpFile;
- if ( KIO::NetAccess::download( pic.url(), tmpFile, 0 /*no widget known*/ ) ) {
- img.load( tmpFile );
- KIO::NetAccess::removeTempFile( tmpFile );
- }
+// if ( KIO::NetAccess::download( pic.url(), tmpFile, 0 /*no widget known*/ ) ) {
+// img.load( tmpFile );
+// KIO::NetAccess::removeTempFile( tmpFile );
+// }
}
if (img.isNull()) {
Error() << "invalid picture";
diff --git a/freebusy/freebusy.h b/freebusy/freebusy.h
index a61e1c4..edc3f58 100644
--- a/freebusy/freebusy.h
+++ b/freebusy/freebusy.h
@@ -22,7 +22,7 @@
#include "kolab_export.h"
#include <kolabevent.h>
#include <kolabfreebusy.h>
-#include <KCalCore/Event>
+#include <kcalcore/event.h>
namespace Kolab {
namespace FreebusyUtils {
diff --git a/icalendar/icalendar.cpp b/icalendar/icalendar.cpp
index a8fdbeb..474b8e9 100644
--- a/icalendar/icalendar.cpp
+++ b/icalendar/icalendar.cpp
@@ -23,11 +23,11 @@
#include <conversion/kcalconversion.h>
#include <conversion/commonconversion.h>
#include <mime/mimeutils.h>
-#include <KCalCore/Event>
+#include <kcalcore/event.h>
#include <kcalcore/memorycalendar.h>
#include <kcalcore/icalformat.h>
#include <kmime/kmime_message.h>
-#include <klocalizedstring.h>
+// #include <klocalizedstring.h>
#include <kdebug.h>
#include <iostream>
@@ -137,7 +137,7 @@ std::string ITipHandler::toIMip(const Event &event , ITipHandler::ITipMethod m,
} else {
QString subject;
if ( e && method == KCalCore::iTIPCounter ) {
- subject = i18n( "Counter proposal: %1", e->summary() );
+ subject = QString( "Counter proposal: %1" ).arg(e->summary());
}
return QString(mailOrganizer( e, QString::fromStdString(from), bccMe, messageText, subject)).toStdString();
}
diff --git a/icalendar/imip.cpp b/icalendar/imip.cpp
index a49aafa..0098bdb 100644
--- a/icalendar/imip.cpp
+++ b/icalendar/imip.cpp
@@ -21,10 +21,10 @@
#include "imip.h"
#include <kcalutils/incidenceformatter.h>
-#include <KPIMUtils/Email>
+#include <kpimutils/email.h>
#include <kmime/kmime_message.h>
#include <QDebug>
-#include <klocalizedstring.h>
+// #include <klocalizedstring.h>
#include <ksystemtimezone.h>
#include <kdebug.h>
@@ -203,7 +203,7 @@ QByteArray mailAttendees( const KCalCore::IncidenceBase::Ptr &incidence,
KCalCore::Incidence::Ptr inc = incidence.staticCast<KCalCore::Incidence>();
subject = inc->summary();
} else {
- subject = i18n( "Free Busy Object" );
+ subject = QString( "Free Busy Object" );
}
const QString body =
@@ -228,7 +228,7 @@ QByteArray mailOrganizer( const KCalCore::IncidenceBase::Ptr &incidence,
subject = inc->summary();
}
} else {
- subject = i18n( "Free Busy Message" );
+ subject = QString( "Free Busy Message" );
}
QString body = KCalUtils::IncidenceFormatter::mailBodyStr( incidence, KSystemTimeZones::local() );
diff --git a/kolabformatV2/contact.cpp b/kolabformatV2/contact.cpp
index 21d6fec..7e0e951 100644
--- a/kolabformatV2/contact.cpp
+++ b/kolabformatV2/contact.cpp
@@ -1179,10 +1179,10 @@ QImage Contact::loadPictureFromAddressee( const KABC::Picture& picture )
QImage img;
if ( !picture.isIntern() && !picture.url().isEmpty() ) {
QString tmpFile;
- if ( KIO::NetAccess::download( picture.url(), tmpFile, 0 /*no widget known*/ ) ) {
- img.load( tmpFile );
- KIO::NetAccess::removeTempFile( tmpFile );
- }
+// if ( KIO::NetAccess::download( picture.url(), tmpFile, 0 /*no widget known*/ ) ) {
+// img.load( tmpFile );
+// KIO::NetAccess::removeTempFile( tmpFile );
+// }
} else
img = picture.data();
return img;
@@ -1193,14 +1193,14 @@ 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 );
- }
+// 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;
diff --git a/kolabformatV2/distributionlist.cpp b/kolabformatV2/distributionlist.cpp
index f011458..61605c6 100644
--- a/kolabformatV2/distributionlist.cpp
+++ b/kolabformatV2/distributionlist.cpp
@@ -31,8 +31,8 @@
#include "distributionlist.h"
-#include <akonadi/itemfetchjob.h>
-#include <akonadi/itemfetchscope.h>
+// #include <akonadi/itemfetchjob.h>
+// #include <akonadi/itemfetchscope.h>
#include <kabc/addressee.h>
#include <kabc/contactgroup.h>
#include <kdebug.h>
@@ -198,31 +198,32 @@ void DistributionList::setFields( const KABC::ContactGroup* contactGroup )
// Hopefully all resources are available during saving, so we can look up
// in the addressbook to get name+email from the UID.
// TODO proxy should at least know the addressees it created
- for ( uint index = 0; index < contactGroup->contactReferenceCount(); ++index ) {
- const KABC::ContactGroup::ContactReference& reference = contactGroup->contactReference( index );
-
- const Akonadi::Item item( reference.uid().toLongLong() );
- Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( item );
- job->fetchScope().fetchFullPayload();
- if ( !job->exec() )
- continue;
-
- const Akonadi::Item::List items = job->items();
- if ( items.count() != 1 )
- continue;
-
- const KABC::Addressee addressee = job->items().first().payload<KABC::Addressee>();
-
- if ( !addressee.isEmpty() ) {
- Member m;
- m.displayName = addressee.formattedName();
- m.email = reference.preferredEmail();
- if ( m.email.isEmpty() )
- m.email = addressee.preferredEmail();
-
- mDistrListMembers.append( m );
- }
- }
+// for ( uint index = 0; index < contactGroup->contactReferenceCount(); ++index ) {
+// const KABC::ContactGroup::ContactReference& reference = contactGroup->contactReference( index );
+//
+// //FIXME this won't work on the server (wihtout akonadi), move this part to the akonadi resource
+// const Akonadi::Item item( reference.uid().toLongLong() );
+// Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( item );
+// job->fetchScope().fetchFullPayload();
+// if ( !job->exec() )
+// continue;
+//
+// const Akonadi::Item::List items = job->items();
+// if ( items.count() != 1 )
+// continue;
+//
+// const KABC::Addressee addressee = job->items().first().payload<KABC::Addressee>();
+//
+// if ( !addressee.isEmpty() ) {
+// Member m;
+// m.displayName = addressee.formattedName();
+// m.email = reference.preferredEmail();
+// if ( m.email.isEmpty() )
+// m.email = addressee.preferredEmail();
+//
+// mDistrListMembers.append( m );
+// }
+// }
}
// The loading is: xml -> DistributionList -> contactgroup, this is the second part
commit 9b386b6506e427efc25646c5ed2b86813bbde9ab
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Tue Jun 26 15:15:42 2012 +0200
freebusy serializing, a couple of fixes for the generateFreeBusy code
diff --git a/freebusy/freebusy.cpp b/freebusy/freebusy.cpp
index ceb5bc2..c7f853e 100644
--- a/freebusy/freebusy.cpp
+++ b/freebusy/freebusy.cpp
@@ -24,6 +24,105 @@
#include <quuid.h>
+// namespace KCalCore {
+// struct KCalFreebusy
+// {
+//
+// void init( const Event::List &eventList, const KDateTime &start, const KDateTime &end )
+// {
+// mDtStart = start.toUtc();
+// mDtEnd = end.toUtc();
+//
+// // Loops through every event in the calendar
+// Event::List::ConstIterator it;
+// for ( it = eventList.constBegin(); it != eventList.constEnd(); ++it ) {
+// Event::Ptr event = *it;
+//
+// // If this event is transparent it shouldn't be in the freebusy list.
+// if ( event->transparency() == Event::Transparent ) {
+// continue;
+// }
+//
+// if ( event->hasRecurrenceId() ) {
+// continue; //TODO apply special period exception (duration could be different)
+// }
+//
+// const KDateTime eventStart = event->dtStart().toUtc();
+// const KDateTime eventEnd = event->dtEnd().toUtc();
+//
+// if ( event->recurs() ) {
+// const KCalCore::Duration duration( eventStart, eventEnd );
+// const KCalCore::DateTimeList list = event->recurrence()->timesInInterval(start, end);
+// foreach (const KDateTime &dt, list) {
+// const KDateTime utc = dt.toUtc();
+// addLocalPeriod(utc, duration.end(utc) );
+// }
+// } else {
+// addLocalPeriod( eventStart, eventEnd );
+// }
+// }
+//
+// // q->sortList();
+// }
+//
+// bool addLocalPeriod(
+// const KDateTime &eventStart,
+// const KDateTime &eventEnd )
+// {
+// KDateTime tmpStart;
+// KDateTime tmpEnd;
+//
+// //Check to see if the start *or* end of the event is
+// //between the start and end of the freebusy dates.
+// if ( !( ( ( mDtStart.secsTo( eventStart ) >= 0 ) &&
+// ( eventStart.secsTo( mDtEnd ) >= 0 ) ) ||
+// ( ( mDtStart.secsTo( eventEnd ) >= 0 ) &&
+// ( eventEnd.secsTo( mDtEnd ) >= 0 ) ) ) ) {
+// qDebug() << "out of scope";
+// return false;
+// }
+//
+// // qDebug() << eventStart.date().toString() << eventStart.time().toString() << mDtStart.toString();
+// if ( eventStart < mDtStart ) { //eventStart is before start
+// // qDebug() << "use start";
+// tmpStart = mDtStart;
+// } else {
+// tmpStart = eventStart;
+// }
+//
+// qDebug() << eventEnd.date().toString() << eventEnd.time().toString() << mDtEnd.toString();
+// if ( eventEnd > mDtEnd ) { //event end is after dtEnd
+// // qDebug() << "use end";
+// tmpEnd = mDtEnd;
+// } else {
+// tmpEnd = eventEnd;
+// }
+//
+// // qDebug() << "########## " << tmpStart.isValid();
+// Q_ASSERT(tmpStart.isValid());
+// Q_ASSERT(tmpEnd.isValid());
+// // qDebug() << tmpStart.date().toString() << tmpStart.time().toString() << tmpStart.toString();
+//
+// FreeBusyPeriod p( tmpStart, tmpEnd );
+// mBusyPeriods.append( p );
+//
+// return true;
+// }
+//
+// KDateTime mDtStart;
+// KDateTime mDtEnd; // end datetime
+// FreeBusyPeriod::List mBusyPeriods; // list of periods
+//
+// };
+//
+// } // Namespace
+
+
+
+
+
+
+
namespace Kolab {
namespace FreebusyUtils {
@@ -57,21 +156,43 @@ Kolab::Period addLocalPeriod( const KDateTime &eventStart, const KDateTime &eve
}
Q_ASSERT(tmpStart.isValid());
Q_ASSERT(tmpEnd.isValid());
+ if (tmpStart.isDateOnly()) {
+ tmpStart.setTime(QTime(0,0,0,0));
+ }
+ if (tmpEnd.isDateOnly()) {
+ tmpEnd.setTime(QTime(23,59,59,999)); //The window is inclusive
+ }
return Kolab::Period(Kolab::Conversion::fromDate(tmpStart), Kolab::Conversion::fromDate(tmpEnd));
}
-
+Freebusy generateFreeBusy(const std::vector< Event >& events, const cDateTime& startDate, const cDateTime& endDate)
+{
+ QList<KCalCore::Event::Ptr> list;
+ foreach (const Kolab::Event &e, events) {
+ list.append(Kolab::Conversion::toKCalCore(e));
+ }
+ KCalCore::Person::Ptr person(new KCalCore::Person("dummyname", "dummyemail"));
+ return generateFreeBusy(list, Kolab::Conversion::toDate(startDate), Kolab::Conversion::toDate(endDate), person);
+}
-Freebusy generateFreeBusy(const std::vector< Event >& events, const cDateTime& startDate, const cDateTime& endDate, const Freebusy& existing)
+Freebusy generateFreeBusy(const QList<KCalCore::Event::Ptr>& events, const KDateTime& startDate, const KDateTime& endDate, const KCalCore::Person::Ptr &organizer)
{
- const KDateTime start = Kolab::Conversion::toDate(startDate).toUtc();
- const KDateTime end = Kolab::Conversion::toDate(endDate).toUtc();
+ /*
+ * TODO the conversion of date-only values to date-time is only necessary because xCal doesn't allow date only. iCalendar doesn't seem to make this restriction so it looks like a bug.
+ */
+ KDateTime start = startDate.toUtc();
+ if (start.isDateOnly()) {
+ start.setTime(QTime(0,0,0,0));
+ }
+ KDateTime end = endDate.toUtc();
+ if (end.isDateOnly()) {
+ end.addDays(1);
+ end.setTime(QTime(0,0,0,0)); //The window is inclusive
+ }
//TODO try to merge that with KCalCore::Freebusy
std::vector<Kolab::FreebusyPeriod> freebusyPeriods;
- foreach (const Kolab::Event &e, events) {
- KCalCore::Event::Ptr event = Kolab::Conversion::toKCalCore(e);
-
+ Q_FOREACH (KCalCore::Event::Ptr event, events) {
// If this event is transparent it shouldn't be in the freebusy list.
if ( event->transparency() == KCalCore::Event::Transparent ) {
continue;
@@ -88,7 +209,7 @@ Freebusy generateFreeBusy(const std::vector< Event >& events, const cDateTime& s
if ( event->recurs() ) {
const KCalCore::Duration duration( eventStart, eventEnd );
const KCalCore::DateTimeList list = event->recurrence()->timesInInterval(start, end);
- foreach (const KDateTime &dt, list) {
+ Q_FOREACH (const KDateTime &dt, list) {
const KDateTime utc = dt.toUtc();
const Kolab::Period &period = addLocalPeriod(utc, duration.end(utc), start, end);
if (period.isValid()) {
@@ -104,21 +225,21 @@ Freebusy generateFreeBusy(const std::vector< Event >& events, const cDateTime& s
if (!periods.empty()) {
Kolab::FreebusyPeriod period;
period.setPeriods(periods);
- //TODO get out of office from event
+ //TODO get busy type from event (out-of-office, tentative)
period.setType(Kolab::FreebusyPeriod::Busy);
- // period.setEvent(event->summary().toStdString(), event->uid().toStdString(), event->location().toStdString());
- //TODO event uid etc.
+ period.setEvent(event->uid().toStdString(), event->summary().toStdString(), event->location().toStdString());
freebusyPeriods.push_back(period);
}
}
Kolab::Freebusy freebusy;
- freebusy.setStart(startDate);
- freebusy.setEnd(endDate);
+
+ freebusy.setStart(Kolab::Conversion::fromDate(start));
+ freebusy.setEnd(Kolab::Conversion::fromDate(end));
freebusy.setPeriods(freebusyPeriods);
freebusy.setUid(QUuid::createUuid().toString().toStdString());
freebusy.setTimestamp(Kolab::Conversion::fromDate(KDateTime::currentUtcDateTime()));
- freebusy.setOrganizer(ContactReference(Kolab::ContactReference::EmailReference, "email", "name"));
+ freebusy.setOrganizer(ContactReference(Kolab::ContactReference::EmailReference, organizer->email().toStdString(), organizer->name().toStdString()));
return freebusy;
}
diff --git a/freebusy/freebusy.h b/freebusy/freebusy.h
index fbea05f..a61e1c4 100644
--- a/freebusy/freebusy.h
+++ b/freebusy/freebusy.h
@@ -22,12 +22,15 @@
#include "kolab_export.h"
#include <kolabevent.h>
#include <kolabfreebusy.h>
+#include <KCalCore/Event>
namespace Kolab {
namespace FreebusyUtils {
-Kolab::Freebusy generateFreeBusy(const std::vector<Kolab::Event> &events, const Kolab::cDateTime &startDate, const Kolab::cDateTime &endDate, const Kolab::Freebusy &existing = Kolab::Freebusy());
-std::string toIFB(const Kolab::Freebusy &);
+KOLAB_EXPORT Freebusy generateFreeBusy(const QList<KCalCore::Event::Ptr>& events, const KDateTime& startDate, const KDateTime& endDate, const KCalCore::Person::Ptr &organizer);
+KOLAB_EXPORT std::string toIFB(const Kolab::Freebusy &);
+
+Kolab::Freebusy generateFreeBusy(const std::vector<Kolab::Event> &events, const Kolab::cDateTime &startDate, const Kolab::cDateTime &endDate);
}
}
diff --git a/kolabformat/kolabdefinitions.h b/kolabformat/kolabdefinitions.h
index 2fdcf70..0d53c8e 100644
--- a/kolabformat/kolabdefinitions.h
+++ b/kolabformat/kolabdefinitions.h
@@ -28,7 +28,8 @@ namespace Kolab {
#define KOLAB_FOLDER_TYPE_TASK "task"
#define KOLAB_FOLDER_TYPE_JOURNAL "journal"
#define KOLAB_FOLDER_TYPE_NOTE "note"
-#define KOLAB_FOLDER_TYPE_CONFIGURATION "configuration"
+#define KOLAB_FOLDER_TYPE_CONFIGURATION "configuration"
+#define KOLAB_FOLDER_TYPE_FREEBUSY "freebusy"
#define KOLAB_FOLDER_TYPE_DEFAULT_SUFFIX ".default"
@@ -50,6 +51,7 @@ static QString distlistKolabTypeCompat() { return QString::fromLatin1("applicati
static QString noteKolabType() { return QString::fromLatin1("application/x-vnd.kolab.note"); }
static QString configurationKolabType() { return QString::fromLatin1("application/x-vnd.kolab.configuration"); }
static QString dictKolabType() { return QString::fromLatin1("application/x-vnd.kolab.configuration.dictionary"); }
+static QString freebusyKolabType() { return QString::fromLatin1("application/x-vnd.kolab.freebusy"); }
static QString xCalMimeType() { return QString::fromLatin1("application/calendar+xml"); };
static QString xCardMimeType() { return QString::fromLatin1("application/vcard+xml"); };
diff --git a/kolabformat/kolabobject.cpp b/kolabformat/kolabobject.cpp
index 0af095d..4e76444 100644
--- a/kolabformat/kolabobject.cpp
+++ b/kolabformat/kolabobject.cpp
@@ -468,6 +468,16 @@ KMime::Message::Ptr KolabObjectWriter::writeDictionary(const QStringList &entrie
return Mime::createMessage(QString::fromStdString(configuration.uid()), kolabMimeType(), dictKolabType(), QString::fromStdString(v3String).toLocal8Bit(), true, getProductId(productId));
}
+KMime::Message::Ptr KolabObjectWriter::writeFreebusy(const Freebusy &freebusy, Version v, const QString& productId)
+{
+ ErrorHandler::clearErrors();
+ if (v != KolabV3) {
+ Critical() << "only v3 implementation available";
+ }
+ const std::string &v3String = Kolab::writeFreebusy(freebusy, getProductId(productId).toStdString());
+ ErrorHandler::handleLibkolabxmlErrors();
+ return Mime::createMessage(QString::fromStdString(freebusy.uid()), xCalMimeType(), freebusyKolabType(), QString::fromStdString(v3String).toLocal8Bit(), true, getProductId(productId));
+}
diff --git a/kolabformat/kolabobject.h b/kolabformat/kolabobject.h
index ecde1f1..7cea7bb 100644
--- a/kolabformat/kolabobject.h
+++ b/kolabformat/kolabobject.h
@@ -30,6 +30,8 @@
namespace Kolab {
+class Freebusy;
+
enum Version {
KolabV2,
KolabV3
@@ -43,7 +45,8 @@ enum ObjectType {
ContactObject,
DistlistObject,
NoteObject,
- DictionaryConfigurationObject
+ DictionaryConfigurationObject,
+ FreebusyObject
};
KOLAB_EXPORT KCalCore::Event::Ptr readV2EventXML(const QByteArray &xmlData, QStringList &attachments);
@@ -109,6 +112,8 @@ public:
static KMime::Message::Ptr writeDistlist(const KABC::ContactGroup &, Version v = KolabV3, const QString &productId = QString());
static KMime::Message::Ptr writeNote(const KMime::Message::Ptr &, Version v = KolabV3, const QString &productId = QString());
static KMime::Message::Ptr writeDictionary(const QStringList &, const QString &lang, Version v = KolabV3, const QString &productId = QString());
+ static KMime::Message::Ptr writeFreebusy(const Kolab::Freebusy &, Version v = KolabV3, const QString &productId = QString());
+
};
}; //Namespace
commit 1db58a28eeb95a2ade1299add76030ab23401ebb
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Tue Jun 26 15:14:47 2012 +0200
better error messages
diff --git a/kolabformat/kolabobject.cpp b/kolabformat/kolabobject.cpp
index 27f7ef7..0af095d 100644
--- a/kolabformat/kolabobject.cpp
+++ b/kolabformat/kolabobject.cpp
@@ -121,6 +121,14 @@ QByteArray getMimeType(Kolab::ObjectType type)
return QByteArray();
}
+void printMessageDebugInfo(const KMime::Message::Ptr &msg)
+{
+ //TODO replace by Debug stream for Mimemessage
+ Debug() << "MessageId: " << msg->messageID()->asUnicodeString();
+ Debug() << "Subject: " << msg->subject()->asUnicodeString();
+// Debug() << msg->encodedContent();
+}
+
ObjectType KolabObjectReader::parseMimeMessage(const KMime::Message::Ptr &msg)
{
ErrorHandler::clearErrors();
@@ -128,6 +136,7 @@ ObjectType KolabObjectReader::parseMimeMessage(const KMime::Message::Ptr &msg)
KMime::Headers::Base *xKolabHeader = msg->getHeaderByType(X_KOLAB_TYPE_HEADER);
if (!xKolabHeader) {
CRITICAL("could not find the X-Kolab-Type Header");
+ printMessageDebugInfo(msg);
return InvalidObject;
}
const QString &kolabType = xKolabHeader->asUnicodeString(); //TODO we probably shouldn't use unicodeString
@@ -141,7 +150,7 @@ ObjectType KolabObjectReader::parseMimeMessage(const KMime::Message::Ptr &msg)
d->mVersion = KolabV2;
} else {
if (xKolabVersion->asUnicodeString() != KOLAB_VERSION_V3) { //TODO version compatibility check?
- WARNING("Kolab Version Header available but not on the same version as the implementation");
+ Warning() << "Kolab Version Header available but not on the same version as the implementation: " << xKolabVersion->asUnicodeString();
}
d->mVersion = KolabV3;
}
@@ -150,7 +159,8 @@ ObjectType KolabObjectReader::parseMimeMessage(const KMime::Message::Ptr &msg)
if (d->mObjectType == DictionaryConfigurationObject) {
KMime::Content *xmlContent = Mime::findContentByType( msg, "application/xml" );
if ( !xmlContent ) {
- CRITICAL("no part found");
+ Critical() << "no application/xml part found";
+ printMessageDebugInfo(msg);
return InvalidObject;
}
const QByteArray &xmlData = xmlContent->decodedContent();
@@ -160,7 +170,8 @@ ObjectType KolabObjectReader::parseMimeMessage(const KMime::Message::Ptr &msg)
}
KMime::Content *xmlContent = Mime::findContentByType( msg, kolabType.toLocal8Bit() );
if ( !xmlContent ) {
- CRITICAL("no part found");
+ Critical() << "no part with type" << kolabType.toLocal8Bit() << " found";
+ printMessageDebugInfo(msg);
return InvalidObject;
}
const QByteArray &xmlData = xmlContent->decodedContent();
@@ -199,7 +210,8 @@ ObjectType KolabObjectReader::parseMimeMessage(const KMime::Message::Ptr &msg)
} else { //V3
KMime::Content *xmlContent = Mime::findContentByType( msg, getMimeType(d->mObjectType) );
if ( !xmlContent ) {
- CRITICAL("no part found");
+ Critical() << "no " << getMimeType(d->mObjectType) << " part found";
+ printMessageDebugInfo(msg);
return InvalidObject;
}
switch (d->mObjectType) {
@@ -244,7 +256,8 @@ ObjectType KolabObjectReader::parseMimeMessage(const KMime::Message::Ptr &msg)
}
break;
default:
- CRITICAL("no kolab object found "+kolabType);
+ Critical() << "no kolab object found " << kolabType;
+ printMessageDebugInfo(msg);
break;
}
commit 348048d35b5e41af909210fd1751bd04fe1c9405
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Tue Jun 26 15:14:29 2012 +0200
uid in subject
diff --git a/kolabformat/kolabobject.cpp b/kolabformat/kolabobject.cpp
index 1f46d95..27f7ef7 100644
--- a/kolabformat/kolabobject.cpp
+++ b/kolabformat/kolabobject.cpp
@@ -417,7 +417,7 @@ KMime::Message::Ptr KolabObjectWriter::writeDistlist(const KABC::ContactGroup &d
const Kolab::DistList &dist = Kolab::Conversion::fromKABC(distlist);
const std::string &v3String = Kolab::writeDistlist(dist, getProductId(productId).toStdString());
ErrorHandler::handleLibkolabxmlErrors();
- return Mime::createMessage(QString(), xCardMimeType(), contactKolabType(), QString::fromStdString(v3String).toLocal8Bit(), true, getProductId(productId));
+ return Mime::createMessage(QString::fromStdString(dist.uid()), xCardMimeType(), contactKolabType(), QString::fromStdString(v3String).toLocal8Bit(), true, getProductId(productId));
}
KolabV2::DistributionList d(&distlist);
return distListToKolabFormat(d, getProductId(productId));
@@ -431,7 +431,7 @@ KMime::Message::Ptr KolabObjectWriter::writeNote(const KMime::Message::Ptr ¬e
const Kolab::Note &n = Kolab::Conversion::fromNote(note);
const std::string &v3String = Kolab::writeNote(n, getProductId(productId).toStdString());
ErrorHandler::handleLibkolabxmlErrors();
- return Mime::createMessage(QString::fromStdString(n.summary()), kolabMimeType(), noteKolabType(), QString::fromStdString(v3String).toLocal8Bit(), true, getProductId(productId));
+ return Mime::createMessage(QString::fromStdString(n.uid()), kolabMimeType(), noteKolabType(), QString::fromStdString(v3String).toLocal8Bit(), true, getProductId(productId));
}
return noteToKolab(note, getProductId(productId));
}
@@ -452,8 +452,7 @@ KMime::Message::Ptr KolabObjectWriter::writeDictionary(const QStringList &entrie
Kolab::Configuration configuration(dictionary); //TODO preserve creation/lastModified date
const std::string &v3String = Kolab::writeConfiguration(configuration, getProductId(productId).toStdString());
ErrorHandler::handleLibkolabxmlErrors();
- //TODO uid in subject?
- return Mime::createMessage(QString(), kolabMimeType(), dictKolabType(), QString::fromStdString(v3String).toLocal8Bit(), true, getProductId(productId));
+ return Mime::createMessage(QString::fromStdString(configuration.uid()), kolabMimeType(), dictKolabType(), QString::fromStdString(v3String).toLocal8Bit(), true, getProductId(productId));
}
commit fbe767a15225846b362f69f73a36ddd9f712fab9
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Tue Jun 26 15:12:47 2012 +0200
make it easy to print an error.
diff --git a/kolabformat/errorhandler.cpp b/kolabformat/errorhandler.cpp
index 4fc5147..3b2f98a 100644
--- a/kolabformat/errorhandler.cpp
+++ b/kolabformat/errorhandler.cpp
@@ -40,6 +40,7 @@ void ErrorHandler::addError(ErrorHandler::Severity s, const QString& message, co
}
if (s > m_worstError) {
m_worstError = s;
+ m_worstErrorMessage = message;
}
m_errorQueue.append(Err(s, message, location));
}
@@ -49,6 +50,11 @@ ErrorHandler::Severity ErrorHandler::error() const
return m_worstError;
}
+QString ErrorHandler::errorMessage() const
+{
+ return m_worstErrorMessage;
+}
+
const QList< ErrorHandler::Err >& ErrorHandler::getErrors() const
{
return m_errorQueue;
diff --git a/kolabformat/errorhandler.h b/kolabformat/errorhandler.h
index 73047cc..254a741 100644
--- a/kolabformat/errorhandler.h
+++ b/kolabformat/errorhandler.h
@@ -66,6 +66,7 @@ public:
void addError(Severity s, const QString &message, const QString &location);
const QList <Err> &getErrors() const;
Severity error() const;
+ QString errorMessage() const;
void clear();
/**
@@ -84,6 +85,7 @@ private:
ErrorHandler & operator= (const ErrorHandler &);
Severity m_worstError;
+ QString m_worstErrorMessage;
QList <Err> m_errorQueue;
};
commit db746b474560dc4b50fdf3af480b09d9573195b6
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Thu Jun 21 17:16:10 2012 +0200
Freebusy generation from events and ical file writing
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3f3186d..30c84a0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -73,6 +73,7 @@ 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)
@@ -87,6 +88,7 @@ set(KOLAB_SRCS
${ICALENDAR_SRCS}
${CALENDARING_MOC}
${CONVERSION_MOC}
+ ${FREEBUSY_SRCS}
)
set(KOLAB_LINK_LIBRARIES
diff --git a/freebusy/CMakeLists.txt b/freebusy/CMakeLists.txt
new file mode 100644
index 0000000..f1f584e
--- /dev/null
+++ b/freebusy/CMakeLists.txt
@@ -0,0 +1,3 @@
+set (FREEBUSY_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/freebusy.cpp
+ PARENT_SCOPE)
diff --git a/freebusy/freebusy.cpp b/freebusy/freebusy.cpp
new file mode 100644
index 0000000..ceb5bc2
--- /dev/null
+++ b/freebusy/freebusy.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2012 Christian Mollekopf <mollekopf at 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 "freebusy.h"
+#include "conversion/kcalconversion.h"
+#include <kcalcore/freebusy.h>
+#include <kcalcore/icalformat.h>
+#include <kdebug.h>
+#include <quuid.h>
+
+
+namespace Kolab {
+ namespace FreebusyUtils {
+
+
+Kolab::Period addLocalPeriod( const KDateTime &eventStart, const KDateTime &eventEnd, const KDateTime &mDtStart, const KDateTime &mDtEnd)
+{
+ KDateTime tmpStart;
+ KDateTime tmpEnd;
+
+ //Check to see if the start *or* end of the event is
+ //between the start and end of the freebusy dates.
+ if ( !( ( ( mDtStart <= eventStart) &&
+ ( eventStart <= mDtEnd ) ) ||
+ ( ( mDtStart <= eventEnd ) &&
+ ( eventEnd <= mDtEnd ) ) ) ) {
+ qDebug() << "out of scope";
+ return Kolab::Period();
+ }
+
+ if ( eventStart < mDtStart ) { //eventStart is before start
+ tmpStart = mDtStart;
+ } else {
+ tmpStart = eventStart;
+ }
+
+ qDebug() << eventEnd.date().toString() << eventEnd.time().toString() << mDtEnd.toString();
+ if ( eventEnd > mDtEnd ) { //event end is after dtEnd
+ tmpEnd = mDtEnd;
+ } else {
+ tmpEnd = eventEnd;
+ }
+ Q_ASSERT(tmpStart.isValid());
+ Q_ASSERT(tmpEnd.isValid());
+ return Kolab::Period(Kolab::Conversion::fromDate(tmpStart), Kolab::Conversion::fromDate(tmpEnd));
+}
+
+
+
+Freebusy generateFreeBusy(const std::vector< Event >& events, const cDateTime& startDate, const cDateTime& endDate, const Freebusy& existing)
+{
+ const KDateTime start = Kolab::Conversion::toDate(startDate).toUtc();
+ const KDateTime end = Kolab::Conversion::toDate(endDate).toUtc();
+
+ //TODO try to merge that with KCalCore::Freebusy
+ std::vector<Kolab::FreebusyPeriod> freebusyPeriods;
+ foreach (const Kolab::Event &e, events) {
+ KCalCore::Event::Ptr event = Kolab::Conversion::toKCalCore(e);
+
+ // If this event is transparent it shouldn't be in the freebusy list.
+ if ( event->transparency() == KCalCore::Event::Transparent ) {
+ continue;
+ }
+
+ if ( event->hasRecurrenceId() ) {
+ continue; //TODO apply special period exception (duration could be different)
+ }
+
+ const KDateTime eventStart = event->dtStart().toUtc();
+ const KDateTime eventEnd = event->dtEnd().toUtc();
+
+ std::vector <Kolab::Period> periods;
+ if ( event->recurs() ) {
+ const KCalCore::Duration duration( eventStart, eventEnd );
+ const KCalCore::DateTimeList list = event->recurrence()->timesInInterval(start, end);
+ foreach (const KDateTime &dt, list) {
+ const KDateTime utc = dt.toUtc();
+ const Kolab::Period &period = addLocalPeriod(utc, duration.end(utc), start, end);
+ if (period.isValid()) {
+ periods.push_back(period);
+ }
+ }
+ } else {
+ const Kolab::Period &period = addLocalPeriod(eventStart, eventEnd, start, end);
+ if (period.isValid()) {
+ periods.push_back(period);
+ }
+ }
+ if (!periods.empty()) {
+ Kolab::FreebusyPeriod period;
+ period.setPeriods(periods);
+ //TODO get out of office from event
+ period.setType(Kolab::FreebusyPeriod::Busy);
+ // period.setEvent(event->summary().toStdString(), event->uid().toStdString(), event->location().toStdString());
+ //TODO event uid etc.
+ freebusyPeriods.push_back(period);
+ }
+ }
+
+ Kolab::Freebusy freebusy;
+ freebusy.setStart(startDate);
+ freebusy.setEnd(endDate);
+ freebusy.setPeriods(freebusyPeriods);
+ freebusy.setUid(QUuid::createUuid().toString().toStdString());
+ freebusy.setTimestamp(Kolab::Conversion::fromDate(KDateTime::currentUtcDateTime()));
+ freebusy.setOrganizer(ContactReference(Kolab::ContactReference::EmailReference, "email", "name"));
+
+ return freebusy;
+}
+
+std::string toIFB(const Kolab::Freebusy &freebusy)
+{
+ KCalCore::FreeBusy::Ptr fb(new KCalCore::FreeBusy(Kolab::Conversion::toDate(freebusy.start()), Kolab::Conversion::toDate(freebusy.end())));
+ KCalCore::FreeBusyPeriod::List list;
+ Q_FOREACH (const Kolab::FreebusyPeriod &fbPeriod, freebusy.periods()) {
+ Q_FOREACH (const Kolab::Period &p, fbPeriod.periods()) {
+ KCalCore::FreeBusyPeriod period(Kolab::Conversion::toDate(p.start), Kolab::Conversion::toDate(p.end));
+// period.setSummary("summary"); Doesn't even work. X-SUMMARY is read though (just not written out)
+ //TODO
+ list.append(period);
+
+ }
+ }
+ fb->addPeriods(list);
+
+ fb->setUid(QString::fromStdString(freebusy.uid()));
+ fb->setOrganizer(KCalCore::Person::Ptr(new KCalCore::Person(QString::fromStdString(freebusy.organizer().name()), QString::fromStdString(freebusy.organizer().email()))));
+ fb->setLastModified(Kolab::Conversion::toDate(freebusy.timestamp()));
+
+ KCalCore::ICalFormat format;
+ QString data = format.createScheduleMessage( fb, KCalCore::iTIPPublish );
+ return data.toStdString();
+}
+
+ }
+}
diff --git a/freebusy/freebusy.h b/freebusy/freebusy.h
new file mode 100644
index 0000000..fbea05f
--- /dev/null
+++ b/freebusy/freebusy.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 Christian Mollekopf <mollekopf at 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 FREEBUSY_H
+#define FREEBUSY_H
+
+#include "kolab_export.h"
+#include <kolabevent.h>
+#include <kolabfreebusy.h>
+
+namespace Kolab {
+ namespace FreebusyUtils {
+
+Kolab::Freebusy generateFreeBusy(const std::vector<Kolab::Event> &events, const Kolab::cDateTime &startDate, const Kolab::cDateTime &endDate, const Kolab::Freebusy &existing = Kolab::Freebusy());
+std::string toIFB(const Kolab::Freebusy &);
+
+ }
+}
+
+#endif // FREEBUSY_H
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 2f1f80e..a9df2b6 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -2,25 +2,29 @@
include_directories(${CMAKE_CURRENT_BINARY_DIR})
QT4_AUTOMOC(benchmark.cpp)
-add_executable(benchmarktest benchmark.cpp ${CMAKE_CURRENT_BINARY_DIR}/${BINDINGSTEST_MOC})
+add_executable(benchmarktest benchmark.cpp)
target_link_libraries(benchmarktest ${QT_QTTEST_LIBRARY} kolab_static)
QT4_AUTOMOC(formattest.cpp)
-add_executable(formattest formattest.cpp ${CMAKE_CURRENT_BINARY_DIR}/${BINDINGSTEST_MOC})
+add_executable(formattest formattest.cpp)
target_link_libraries(formattest ${QT_QTTEST_LIBRARY} kolab_static)
QT4_AUTOMOC(upgradetest.cpp)
-add_executable(upgradetest upgradetest.cpp ${CMAKE_CURRENT_BINARY_DIR}/${BINDINGSTEST_MOC})
+add_executable(upgradetest upgradetest.cpp)
target_link_libraries(upgradetest ${QT_QTTEST_LIBRARY} kolab_static)
QT4_AUTOMOC(kcalconversiontest.cpp)
-add_executable(kcalconversiontest kcalconversiontest.cpp ${CMAKE_CURRENT_BINARY_DIR}/${BINDINGSTEST_MOC})
+add_executable(kcalconversiontest kcalconversiontest.cpp)
target_link_libraries(kcalconversiontest ${QT_QTTEST_LIBRARY} kolab_static)
QT4_AUTOMOC(calendaringtest.cpp)
-add_executable(calendaringtest calendaringtest.cpp ${CMAKE_CURRENT_BINARY_DIR}/${BINDINGSTEST_MOC})
+add_executable(calendaringtest calendaringtest.cpp)
target_link_libraries(calendaringtest ${QT_QTTEST_LIBRARY} kolab_static)
QT4_AUTOMOC(icalendartest.cpp)
-add_executable(icalendartest icalendartest.cpp ${CMAKE_CURRENT_BINARY_DIR}/${BINDINGSTEST_MOC})
-target_link_libraries(icalendartest ${QT_QTTEST_LIBRARY} kolab_static)
\ No newline at end of file
+add_executable(icalendartest icalendartest.cpp)
+target_link_libraries(icalendartest ${QT_QTTEST_LIBRARY} kolab_static)
+
+QT4_AUTOMOC(freebusytest.cpp)
+add_executable(freebusytest freebusytest.cpp)
+target_link_libraries(freebusytest ${QT_QTTEST_LIBRARY} kolab_static)
\ No newline at end of file
diff --git a/tests/calendaringtest.cpp b/tests/calendaringtest.cpp
index 3671ecb..9ad29bf 100644
--- a/tests/calendaringtest.cpp
+++ b/tests/calendaringtest.cpp
@@ -26,15 +26,7 @@
#include <calendaring/event.h>
#include "testhelpers.h"
-
-
-Kolab::Event createEvent(const Kolab::cDateTime &start, const Kolab::cDateTime &end)
-{
- Kolab::Event event;
- event.setStart(start);
- event.setEnd(end);
- return event;
-}
+#include "testutils.h"
void compareEvents(const std::vector<Kolab::Event> &list1, const std::vector<Kolab::Event> &list2)
{
diff --git a/tests/freebusytest.cpp b/tests/freebusytest.cpp
new file mode 100644
index 0000000..40adf6b
--- /dev/null
+++ b/tests/freebusytest.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2012 Christian Mollekopf <mollekopf at 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 "freebusytest.h"
+#include "testutils.h"
+#include "testhelpers.h"
+
+#include <QTest>
+#include "freebusy/freebusy.h"
+#include <kolabfreebusy.h>
+
+
+void FreebusyTest::testFB_data()
+{
+ QTest::addColumn<Kolab::cDateTime>( "start" );
+ QTest::addColumn<Kolab::cDateTime>( "end" );
+ QTest::addColumn< std::vector<Kolab::Event> >( "events" );
+ QTest::addColumn< std::vector<Kolab::FreebusyPeriod> >( "output" );
+
+
+ //UTC check
+ {
+ Kolab::Period p1(Kolab::cDateTime(2011,10,6,12,1,1,true), Kolab::cDateTime(2011,10,7,12,1,1,true));
+ Kolab::Period p2(Kolab::cDateTime(2011,10,8,12,1,1,true), Kolab::cDateTime(2011,10,9,12,1,1,true));
+ Kolab::Period p3(Kolab::cDateTime(2011,10,10,12,1,1,true), Kolab::cDateTime(2011,10,11,12,1,1,true));
+
+ std::vector<Kolab::Event> events;
+ events.push_back(createEvent(p1.start, p1.end));
+ events.push_back(createEvent(p2.start, p2.end));
+ events.push_back(createEvent(p3.start, p3.end));
+
+ Kolab::FreebusyPeriod period1;
+ period1.setType(Kolab::FreebusyPeriod::Busy);
+ period1.setPeriods(std::vector<Kolab::Period>() << p1);
+
+ Kolab::FreebusyPeriod period2;
+ period2.setType(Kolab::FreebusyPeriod::Busy);
+ period2.setPeriods(std::vector<Kolab::Period>() << p2);
+
+ Kolab::FreebusyPeriod period3;
+ period3.setType(Kolab::FreebusyPeriod::Busy);
+ period3.setPeriods(std::vector<Kolab::Period>() << p3);
+
+ {
+ std::vector<Kolab::FreebusyPeriod> output;
+ output.push_back(period1);
+ output.push_back(period2);
+ output.push_back(period3);
+
+ QTest::newRow( "simple utc" ) << Kolab::cDateTime(2010, 1, 1,1,1,1,true) << Kolab::cDateTime(2012, 1, 1,1,1,1,true) << events << output;
+ }
+
+ {
+ std::vector<Kolab::FreebusyPeriod> output;
+ output.push_back(period2);
+ output.push_back(period3);
+
+ QTest::newRow( "limit utc below" ) << Kolab::cDateTime(2011,10,8,12,1,1,true) << Kolab::cDateTime(2012, 1, 1,1,1,1,true) << events << output;
+ }
+ {
+ std::vector<Kolab::FreebusyPeriod> output;
+ output.push_back(period1);
+ output.push_back(period2);
+
+ QTest::newRow( "limit utc above" ) << Kolab::cDateTime(2010, 1, 1,1,1,1,true) << Kolab::cDateTime(2011,10,9,12,1,1,true) << events << output;
+ }
+ }
+ {
+ Kolab::Event event;
+ event.setStart(Kolab::cDateTime(2011,1,1,0,0,0,true));
+ event.setEnd(Kolab::cDateTime(2011,1,1,1,0,0,true));
+ Kolab::RecurrenceRule rrule;
+ rrule.setFrequency(Kolab::RecurrenceRule::Daily);
+ rrule.setInterval(1);
+ rrule.setCount(2);
+ event.setRecurrenceRule(rrule);
+
+ std::vector<Kolab::Event> events;
+ events.push_back(event);
+
+ std::vector<Kolab::FreebusyPeriod> output;
+ Kolab::FreebusyPeriod period1;
+ period1.setType(Kolab::FreebusyPeriod::Busy);
+ period1.setPeriods(std::vector<Kolab::Period>() << Kolab::Period(Kolab::cDateTime(2011,1,1,0,0,0,true), Kolab::cDateTime(2011,1,1,1,0,0,true))
+ << Kolab::Period(Kolab::cDateTime(2011,1,2,0,0,0,true), Kolab::cDateTime(2011,1,2,1,0,0,true))
+ );
+ output.push_back(period1);
+
+ QTest::newRow( "fullday recurrence" ) << Kolab::cDateTime(2010, 1, 1,1,1,1,true) << Kolab::cDateTime(2012,10,9,12,1,1,true) << events << output;
+ }
+}
+
+
+void FreebusyTest::testFB()
+{
+ QFETCH(Kolab::cDateTime, start);
+ QFETCH(Kolab::cDateTime, end);
+ QFETCH(std::vector<Kolab::Event>, events);
+ QFETCH(std::vector<Kolab::FreebusyPeriod>, output);
+
+ Kolab::Freebusy fb = Kolab::FreebusyUtils::generateFreeBusy(events, start, end);
+
+ QCOMPARE((int)fb.periods().size(), (int)output.size());
+ for (int i = 0; i<output.size(); i++) {
+ QCOMPARE(fb.periods().at(i), output.at(i));
+ }
+
+ std::cout << Kolab::FreebusyUtils::toIFB(fb);
+}
+
+// void FreebusyTest::testHonorTimeFrame()
+// {
+//
+// Kolab::Period p1(Kolab::cDateTime(2011,10,6,12,1,1,true), Kolab::cDateTime(2011,10,8,12,1,1,true));
+// Kolab::Period p2(Kolab::cDateTime(2011,10,7,12,1,1,true), Kolab::cDateTime(2011,10,10,12,1,1,true));
+// Kolab::Period p3(Kolab::cDateTime(2011,10,9,12,1,1,true), Kolab::cDateTime(2011,10,11,12,1,1,true));
+//
+// std::vector<Kolab::Event> events;
+// events.push_back(createEvent(p1.start, p1.end));
+// events.push_back(createEvent(p2.start, p2.end));
+// events.push_back(createEvent(p3.start, p3.end));
+//
+// Kolab::FreebusyPeriod period1;
+// period1.setType(Kolab::FreebusyPeriod::Busy);
+// period1.setPeriods(std::vector<Kolab::Period>() << p1);
+//
+// Kolab::FreebusyPeriod period2;
+// period2.setType(Kolab::FreebusyPeriod::Busy);
+// period2.setPeriods(std::vector<Kolab::Period>() << p2);
+//
+// Kolab::FreebusyPeriod period3;
+// period3.setType(Kolab::FreebusyPeriod::Busy);
+// period3.setPeriods(std::vector<Kolab::Period>() << p3);
+//
+//
+// Kolab::Freebusy fb = Kolab::FreebusyUtils::generateFreeBusy(events, Kolab::cDateTime(2010, 1, 1,1,1,1,true), Kolab::cDateTime(2012, 1, 1,1,1,1,true));
+// QCOMPARE((int)fb.periods().size(), 3);
+// QCOMPARE(fb.periods().at(0), period1);
+// QCOMPARE(fb.periods().at(1), period2);
+// QCOMPARE(fb.periods().at(2), period3);
+// }
+
+QTEST_MAIN( FreebusyTest )
+
+#include "freebusytest.moc"
\ No newline at end of file
diff --git a/tests/freebusytest.h b/tests/freebusytest.h
new file mode 100644
index 0000000..a27b9b5
--- /dev/null
+++ b/tests/freebusytest.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 Christian Mollekopf <mollekopf at 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 FREEBUSYTEST_H
+#define FREEBUSYTEST_H
+#include <QObject>
+
+class FreebusyTest: public QObject
+{
+ Q_OBJECT
+private slots:
+
+ void testFB_data();
+ void testFB();
+};
+
+#endif // FREEBUSYTEST_H
diff --git a/tests/testhelpers.h b/tests/testhelpers.h
index 614ddd2..02ef659 100644
--- a/tests/testhelpers.h
+++ b/tests/testhelpers.h
@@ -38,14 +38,16 @@ Q_DECLARE_METATYPE(std::vector<Kolab::Event>);
Q_DECLARE_METATYPE(Kolab::Todo);
Q_DECLARE_METATYPE(Kolab::Journal);
Q_DECLARE_METATYPE(Kolab::Contact);
+Q_DECLARE_METATYPE(Kolab::Period);
+Q_DECLARE_METATYPE(std::vector<Kolab::FreebusyPeriod>);
+
Q_DECLARE_METATYPE(KCalCore::Event);
Q_DECLARE_METATYPE(KCalCore::Todo);
Q_DECLARE_METATYPE(KCalCore::Journal);
Q_DECLARE_METATYPE(KCalCore::Duration);
namespace QTest {
-
-
+
template<>
char *toString(const Kolab::cDateTime &dt)
{
@@ -263,13 +265,42 @@ namespace QTest {
{
QByteArray ba = "vector<Kolab::CustomProperty>(";
for (int i = 0; i < v.size(); i++) {
- ba += QByteArray(toString(v.at(i)))+ "\n";
- }
- ba += ")";
- return qstrdup(ba.data());
+ ba += QByteArray(toString(v.at(i)))+ "\n";
+ }
+ ba += ")";
+ return qstrdup(ba.data());
}
+ template<>
+ char *toString(const Kolab::Period &p)
+ {
+ QByteArray ba = "Kolab::Period(";
+ ba += QByteArray(toString(p.start))+ "\n";
+ ba += QByteArray(toString(p.end))+ "\n";
+ ba += ")";
+ return qstrdup(ba.data());
+ }
+ template<>
+ char *toString(const std::vector<Kolab::Period> &v)
+ {
+ QByteArray ba = "vector<Kolab::Period>(";
+ for (int i = 0; i < v.size(); i++) {
+ ba += QByteArray(toString(v.at(i)))+ "\n";
+ }
+ ba += ")";
+ return qstrdup(ba.data());
+ }
+
+ template<>
+ char *toString(const Kolab::FreebusyPeriod &p)
+ {
+ QByteArray ba = "Kolab::FreebusyPeriod(";
+ ba += QString::number(p.type())+ "\n";
+ ba += QByteArray(toString(p.periods()))+ "\n";
+ ba += ")";
+ return qstrdup(ba.data());
+ }
}
diff --git a/tests/testutils.h b/tests/testutils.h
index 82c4541..32842ae 100644
--- a/tests/testutils.h
+++ b/tests/testutils.h
@@ -23,6 +23,7 @@
#include <qtemporaryfile.h>
#include <qprocess.h>
#include <kdebug.h>
+#include <kolabevent.h>
#include <kmime/kmime_message.h>
#include "kolabformat/kolabobject.h"
@@ -180,3 +181,11 @@ void normalizeContact(KABC::Addressee &addressee)
addressee.removeCustom("KOLAB", "SoundAttachmentName");
}
+
+Kolab::Event createEvent(const Kolab::cDateTime &start, const Kolab::cDateTime &end)
+{
+ Kolab::Event event;
+ event.setStart(start);
+ event.setEnd(end);
+ return event;
+}
\ No newline at end of file
commit 679b0effcec31cfb09e717c7a9f840434878b8bb
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Thu Jun 21 17:13:04 2012 +0200
resolved merge conflict (something was messed up)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f26b32d..3f3186d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -74,7 +74,21 @@ add_subdirectory(conversion)
add_subdirectory(calendaring)
add_subdirectory(icalendar)
-set(KOLAB_SRCS kolabformat/kolabobject.cpp kolabformat/errorhandler.cpp mime/mimeutils.cpp ${CONVERSION_SRCS} ${kolabformatv2_SRCS} ${CALENDARING_SRCS} ${ICALENDAR_SRCS})
+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/errorhandler.cpp
+ mime/mimeutils.cpp
+ ${CONVERSION_SRCS}
+ ${kolabformatv2_SRCS}
+ ${CALENDARING_SRCS}
+ ${ICALENDAR_SRCS}
+ ${CALENDARING_MOC}
+ ${CONVERSION_MOC}
+)
+
set(KOLAB_LINK_LIBRARIES
${Libkolabxml_LIBRARIES}
${KDEPIMLIBS_KCALCORE_LIBS}
commit 4cb0873adc6bd79b8cf4266075faefcbf38681fc
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date: Tue Jun 19 23:38:33 2012 +0200
Use UTC timestamp in mime-message.
diff --git a/mime/mimeutils.cpp b/mime/mimeutils.cpp
index 3a7ee6c..23fd9c1 100644
--- a/mime/mimeutils.cpp
+++ b/mime/mimeutils.cpp
@@ -192,7 +192,7 @@ KMime::Content* createExplanationPart(bool v3)
KMime::Message::Ptr createMessage(const QString& xKolabType, bool v3, const QString &prodid)
{
KMime::Message::Ptr message( new KMime::Message );
- message->date()->setDateTime( KDateTime::currentLocalDateTime() );
+ message->date()->setDateTime( KDateTime::currentUtcDateTime() );
KMime::Headers::Generic *h = new KMime::Headers::Generic( X_KOLAB_TYPE_HEADER, message.get(), xKolabType, "utf-8" );
message->appendHeader( h );
if (v3) {
More information about the commits
mailing list