From 75502cb30b6b56c4ab65ef7f3e315c3298408937 Mon Sep 17 00:00:00 2001
From: tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>
Date: Sat, 28 Aug 2010 01:04:18 +0000
Subject: Added tasks support to CalDAV resource This nearly completes Zimbra
 integration

git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1168963 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
---
 kresources/caldav/config.cpp      |  32 ++++++++--
 kresources/caldav/config.h        |   4 ++
 kresources/caldav/job.h           |  15 +++++
 kresources/caldav/preferences.cpp |  27 ++++++++
 kresources/caldav/preferences.h   |   5 ++
 kresources/caldav/prefsskel.kcfg  |   8 +++
 kresources/caldav/reader.cpp      |  33 +++++++++-
 kresources/caldav/reader.h        |   8 +++
 kresources/caldav/resource.cpp    | 126 +++++++++++++++++++++++++++++++++++---
 kresources/caldav/resource.h      |  20 +++++-
 kresources/caldav/writer.cpp      |  27 ++++++++
 kresources/caldav/writer.h        |  64 ++++++++++++++++---
 12 files changed, 341 insertions(+), 28 deletions(-)

diff --git a/kresources/caldav/config.cpp b/kresources/caldav/config.cpp
index da9bd847..550e00c9 100644
--- a/kresources/caldav/config.cpp
+++ b/kresources/caldav/config.cpp
@@ -88,6 +88,8 @@ void ResourceCalDavConfig::loadSettings( KRES::Resource *resource ) {
         mUsername->setText(p->username());
         mRememberPassword->setChecked(p->rememberPassword());
         mPassword->setText(p->password());
+        mTasksUrl->setText(p->tasksUrl());
+        mUseSTasks->setChecked(p->useSTasks());
 
         mReloadConfig->loadSettings(res);
         mSaveConfig->loadSettings(res);
@@ -106,6 +108,8 @@ void ResourceCalDavConfig::saveSettings( KRES::Resource *resource ) {
             p->setUsername(mUsername->text());
             p->setRememberPassword(mRememberPassword->isChecked());
             p->setPassword(mPassword->text());
+            p->setTasksUrl(mTasksUrl->text());
+            p->setUseSTasks(mUseSTasks->isChecked());
         }
     }
 }
@@ -121,22 +125,36 @@ void ResourceCalDavConfig::setupUI() {
     mainLayout->addWidget( label, 1, 0 );
     mainLayout->addWidget( mUrl, 1, 1 );
 
+    // Tasks URL
+    TQLabel *tlabel = new TQLabel( i18n( "Tasks URL:" ), this );
+    mTasksUrl = new TQLineEdit( this );
+    mainLayout->addWidget( tlabel, 2, 0 );
+    mainLayout->addWidget( mTasksUrl, 2, 1 );
+
+    // Use Task URL checkbox
+    mUseSTasks = new TQCheckBox( i18n("Use separate Tasks URL"), this );
+    mainLayout->addWidget(mUseSTasks, 3, 0 );
+
     // Username
     label = new TQLabel( i18n( "Username:" ), this );
     mUsername = new TQLineEdit( this );
-    mainLayout->addWidget( label, 2, 0 );
-    mainLayout->addWidget( mUsername, 2, 1 );
+    mainLayout->addWidget( label, 4, 0 );
+    mainLayout->addWidget( mUsername, 4, 1 );
 
     // Password
     label = new TQLabel( i18n( "Password:" ), this );
     mPassword = new TQLineEdit( this );
     mPassword->setEchoMode( TQLineEdit::Password );
-    mainLayout->addWidget( label, 3, 0 );
-    mainLayout->addWidget( mPassword, 3, 1 );
+    mainLayout->addWidget( label, 5, 0 );
+    mainLayout->addWidget( mPassword, 5, 1 );
 
     // Remember password checkbox
     mRememberPassword = new TQCheckBox( i18n("Remember password"), this );
-    mainLayout->addWidget(mRememberPassword, 4, 1);
+    mainLayout->addWidget(mRememberPassword, 6, 1);
+
+    mTasksUrl->setEnabled(mUseSTasks->isChecked());
+    connect( mUseSTasks, TQT_SIGNAL( toggled( bool ) ),
+           TQT_SLOT( slotSTasksToggled( bool ) ) );
 
     // configs
     TQHBoxLayout* horizontal = new TQHBoxLayout(this);
@@ -159,4 +177,8 @@ void ResourceCalDavConfig::setupUI() {
     vertical->addLayout(horizontal);
 }
 
+void ResourceCalDavConfig::slotSTasksToggled( bool enabled ) {
+    mTasksUrl->setEnabled(enabled);
+}
+
 // EOF ========================================================================
diff --git a/kresources/caldav/config.h b/kresources/caldav/config.h
index 5e9d2e76..746c87ac 100644
--- a/kresources/caldav/config.h
+++ b/kresources/caldav/config.h
@@ -50,6 +50,8 @@ public slots:
     virtual void loadSettings(KRES::Resource *resource);
     virtual void saveSettings(KRES::Resource *resource);
 
+    void slotSTasksToggled( bool );
+
 protected:
 
     virtual void setupUI();
@@ -57,8 +59,10 @@ protected:
 private:
 
     TQLineEdit *mUrl;
+    TQLineEdit *mTasksUrl;
     TQLineEdit *mUsername;
     TQLineEdit *mPassword;
+    TQCheckBox *mUseSTasks;
     TQCheckBox *mRememberPassword;
     CalDavReloadConfig* mReloadConfig;
     CalDavSaveConfig* mSaveConfig;
diff --git a/kresources/caldav/job.h b/kresources/caldav/job.h
index 254a0a10..53d4e0e1 100644
--- a/kresources/caldav/job.h
+++ b/kresources/caldav/job.h
@@ -53,6 +53,13 @@ public:
         mUrl = s;
     }
 
+    /**
+     * Sets a new Tasks URL to load.
+     */
+    virtual void setTasksUrl(const TQString& s) {
+        mTasksUrl = s;
+    }
+
     /**
      * Sets the parent qobject.
      */
@@ -74,6 +81,13 @@ public:
         return mUrl;
     }
 
+    /**
+     * @return Tasks URL to load.
+     */
+    virtual TQString tasksUrl() const {
+        return mTasksUrl;
+    }
+
     /**
      * @return parent object
      */
@@ -147,6 +161,7 @@ protected:
 private:
 
     TQString mUrl;
+    TQString mTasksUrl;
     bool mError;
     TQString mErrorString;
     long mErrorNumber;
diff --git a/kresources/caldav/preferences.cpp b/kresources/caldav/preferences.cpp
index 8e27b9df..d70a3519 100644
--- a/kresources/caldav/preferences.cpp
+++ b/kresources/caldav/preferences.cpp
@@ -232,5 +232,32 @@ TQString CalDavPrefs::getFullUrl() {
     return safeURL;
 }
 
+TQString CalDavPrefs::getFullTasksUrl() {
+    if (useSTasks() == 0)
+      return TQString();
+
+    TQUrl t(tasksUrl());
+    TQString safeURL;
+    int firstAt;
+
+    t.setUser(username());
+    t.setPassword(password());
+
+    safeURL = t.toString();
+
+    firstAt = safeURL.find("@") + 1;
+    while (safeURL.find("@", firstAt) != -1) {
+        safeURL.replace(safeURL.find("@", firstAt), 1, "%40");
+    }
+
+    // Unencode the username, as Zimbra stupidly rejects the %40
+    safeURL.replace("%40", "@");
+
+    // Encode any spaces, as libcaldav stupidly fails otherwise
+    safeURL.replace(" ", "%20");
+
+    return safeURL;
+}
+
 // EOF ========================================================================
 
diff --git a/kresources/caldav/preferences.h b/kresources/caldav/preferences.h
index 3a9400ae..666b8ccf 100644
--- a/kresources/caldav/preferences.h
+++ b/kresources/caldav/preferences.h
@@ -87,6 +87,11 @@ public:
      */
     TQString getFullUrl();
 
+    /**
+     * @return A full URL to connect to CalDAV Tasks server (including username and password).
+     */
+    TQString getFullTasksUrl();
+
 protected:
 
     /**
diff --git a/kresources/caldav/prefsskel.kcfg b/kresources/caldav/prefsskel.kcfg
index 39b79b85..bb05a75f 100644
--- a/kresources/caldav/prefsskel.kcfg
+++ b/kresources/caldav/prefsskel.kcfg
@@ -10,6 +10,14 @@
    <label>URL</label>
   </entry>
 
+  <entry key="TasksUrl" type="String" >
+   <label>URL</label>
+  </entry>
+
+  <entry key="UseSTasks" type="Bool" >
+   <label>Use separate Tasks URL</label>
+  </entry>
+
   <entry key="Username" type="String">
    <label>User Name</label>
   </entry>
diff --git a/kresources/caldav/reader.cpp b/kresources/caldav/reader.cpp
index 7d912a7f..4a65b2ab 100644
--- a/kresources/caldav/reader.cpp
+++ b/kresources/caldav/reader.cpp
@@ -31,6 +31,7 @@ using namespace KCal;
 void CalDavReader::cleanJob() {
     CalDavJob::cleanJob();
     mData = "";
+    mTasksData = "";
 }
 
 int CalDavReader::runJob(runtime_info* RT) {
@@ -41,10 +42,10 @@ int CalDavReader::runJob(runtime_info* RT) {
 
     if (mGetAll) {
         kdDebug() << "getting all objects";
-    	res = caldav_getall_object(result, std::string(url().ascii()).c_str(), RT);
+        res = caldav_tasks_getall_object(result, std::string(url().ascii()).c_str(), RT);
     } else {
         kdDebug() << "getting object from the specified time range";
-        res = caldav_get_object(result, mTimeStart.toTime_t(), mTimeEnd.toTime_t(), std::string(url().ascii()).c_str(), RT);
+        res = caldav_tasks_get_object(result, mTimeStart.toTime_t(), mTimeEnd.toTime_t(), std::string(url().ascii()).c_str(), RT);
     }
 
     if (OK == res) {
@@ -60,6 +61,34 @@ int CalDavReader::runJob(runtime_info* RT) {
 
     caldav_free_response(&result);
 
+    if ((OK == res) && (tasksUrl() != "")) {
+      kdDebug() << "reader::run, url: " << tasksUrl();
+
+      response* result = caldav_get_response();
+      CALDAV_RESPONSE res = OK;
+
+      if (mGetAll) {
+          kdDebug() << "getting all objects";
+          res = caldav_tasks_getall_object(result, std::string(tasksUrl().ascii()).c_str(), RT);
+      } else {
+          kdDebug() << "getting object from the specified time range";
+          res = caldav_tasks_get_object(result, mTimeStart.toTime_t(), mTimeEnd.toTime_t(), std::string(tasksUrl().ascii()).c_str(), RT);
+      }
+
+      if (OK == res) {
+          kdDebug() << "success";
+          if (result->msg) {
+              mTasksData = result->msg;
+          } else {
+              kdDebug() << "empty collection";
+              // empty collection
+              mTasksData = "";
+          }
+      }
+
+      caldav_free_response(&result);
+    }
+
     return res;
 }
 
diff --git a/kresources/caldav/reader.h b/kresources/caldav/reader.h
index 191d28ba..c34f2083 100644
--- a/kresources/caldav/reader.h
+++ b/kresources/caldav/reader.h
@@ -71,6 +71,13 @@ public:
         return mData;
     }
 
+    /**
+     * @return downloaded task data in iCal format.
+     */
+    TQString tasksData() const {
+        return mTasksData;
+    }
+
 protected:
 
     virtual int runJob(runtime_info* caldavRuntime);
@@ -80,6 +87,7 @@ protected:
 private:
 
     TQString mData;
+    TQString mTasksData;
     bool mGetAll;
     TQDateTime mTimeStart;
     TQDateTime mTimeEnd;
diff --git a/kresources/caldav/resource.cpp b/kresources/caldav/resource.cpp
index 462cd629..f3835b18 100644
--- a/kresources/caldav/resource.cpp
+++ b/kresources/caldav/resource.cpp
@@ -160,7 +160,7 @@ bool ResourceCalDav::doLoad() {
     emit resourceLoaded(this);
 
     log("starting download job");
-    startLoading(mPrefs->getFullUrl());
+    startLoading(mPrefs->getFullUrl(), mPrefs->getFullTasksUrl());
 
     return true;
 }
@@ -189,7 +189,7 @@ bool ResourceCalDav::doSave() {
     }
 
     log("start writing job");
-    if (startWriting(mPrefs->getFullUrl()) == true) {
+    if (startWriting(mPrefs->getFullUrl(), mPrefs->getFullTasksUrl()) == true) {
         log("clearing changes");
         // FIXME: Calling clearChanges() here is not the ideal way since the
         // upload might fail, but there is no other place to call it...
@@ -333,6 +333,7 @@ void ResourceCalDav::loadingQueuePop() {
     LoadingTask *t = mLoadingQueue.head();
 
     mLoader->setUrl(t->url);
+    mLoader->setTasksUrl(t->tasksUrl);
     mLoader->setParent(this);
     mLoader->setType(0);
 
@@ -352,9 +353,10 @@ void ResourceCalDav::loadingQueuePop() {
     delete t;
 }
 
-void ResourceCalDav::startLoading(const TQString& url) {
+void ResourceCalDav::startLoading(const TQString& url, const TQString& tasksUrl) {
     LoadingTask *t = new LoadingTask;
     t->url = url;
+    t->tasksUrl = tasksUrl;
     loadingQueuePush(t);
 }
 
@@ -379,7 +381,7 @@ void ResourceCalDav::loadFinished() {
                 else {
                     // Set new password and try again
                     mPrefs->setPassword(TQString(newpass));
-                    startLoading(mPrefs->getFullUrl());
+                    startLoading(mPrefs->getFullUrl(), mPrefs->getFullTasksUrl());
                 }
             }
             else {
@@ -394,6 +396,7 @@ void ResourceCalDav::loadFinished() {
     } else {
         log("successful load");
         TQString data = loader->data();
+        TQString tasksData = loader->tasksData();
 
         if (!data.isNull() && !data.isEmpty()) {
             // TODO: I don't know why, but some schedules on http://caldav-test.ioda.net/ (I used it for testing)
@@ -414,6 +417,26 @@ void ResourceCalDav::loadFinished() {
                 emit resourceLoaded(this);
             }
         }
+
+        if (!tasksData.isNull() && !tasksData.isEmpty()) {
+            // TODO: I don't know why, but some schedules on http://caldav-test.ioda.net/ (I used it for testing)
+            // have some lines separated by single \r rather than \n or \r\n.
+            // ICalFormat fails to parse that.
+            tasksData.replace("\r\n", "\n"); // to avoid \r\n becomes \n\n after the next line
+            tasksData.replace('\r', '\n');
+
+            log("trying to parse...");
+            if (parseTasksData(tasksData)) {
+                // FIXME: The agenda view can crash when a change is
+                // made on a remote server and a reload is requested!
+                log("... parsing is ok");
+                log("clearing changes");
+                enableChangeNotification();
+                clearChanges();
+                emit resourceChanged(this);
+                emit resourceLoaded(this);
+            }
+        }
     }
 
     // Loading queue and mLoadingQueueReady flag are not shared resources, i.e. only one thread has an access to them.
@@ -495,6 +518,60 @@ bool ResourceCalDav::parseData(const TQString& data) {
     return ret;
 }
 
+bool ResourceCalDav::parseTasksData(const TQString& data) {
+    log("parseTasksData()");
+
+    bool ret = true;
+
+    // check if the data is OK
+    // May be it's not efficient (parsing is done twice), but it should be safe
+    if (!checkData(data)) {
+        loadError(i18n("Parsing calendar data failed."));
+        return false;
+    }
+
+    disableChangeNotification();
+
+    log("actually parsing the data");
+
+    ICalFormat ical;
+    if ( !ical.fromString( &mCalendar, data ) ) {
+        // this should never happen, but...
+        ret = false;
+    }
+
+    // debug code here -------------------------------------------------------
+#ifdef KCALDAV_DEBUG
+    const TQString fout_path = "/tmp/kcaldav_download_" + identifier() + ".tmp";
+
+    TQFile fout(fout_path);
+    if (fout.open(IO_WriteOnly | IO_Append)) {
+        TQTextStream sout(&fout);
+        sout << "---------- " << resourceName() << ": --------------------------------\n";
+        sout << data << "\n";
+        fout.close();
+    } else {
+        loadError(i18n("can't open file"));
+    }
+#endif // KCALDAV_DEBUG
+    // end of debug code ----------------------------------------------------
+
+    enableChangeNotification();
+
+    if (ret) {
+        log("parsing is ok");
+        //if ( !noReadOnlyOnLoad() && readOnly() ) {
+        if ( readOnly() ) {
+            log("ensuring read only flag honored");
+            ensureReadOnlyFlagHonored();
+        }
+        log("saving to cache");
+        saveCache();
+    }
+
+    return ret;
+}
+
 /*=========================================================================
 | WRITING METHODS
  ========================================================================*/
@@ -554,6 +631,7 @@ void ResourceCalDav::writingQueuePop() {
     log("writingQueuePop: url = " + t->url);
 
     mWriter->setUrl(t->url);
+    mWriter->setTasksUrl(t->tasksUrl);
     mWriter->setParent(this);
     mWriter->setType(1);
 
@@ -577,6 +655,10 @@ void ResourceCalDav::writingQueuePop() {
     mWriter->setChangedObjects(t->changed);
     mWriter->setDeletedObjects(t->deleted);
 
+    mWriter->setAddedTasksObjects(t->tasksAdded);
+    mWriter->setChangedTasksObjects(t->tasksChanged);
+    mWriter->setDeletedTasksObjects(t->tasksDeleted);
+
     mWritingQueueReady = false;
 
     log("starting actual write job");
@@ -607,7 +689,7 @@ void ResourceCalDav::releaseReadLockout() {
     readLockout = false;
 }
 
-bool ResourceCalDav::startWriting(const TQString& url) {
+bool ResourceCalDav::startWriting(const TQString& url, const TQString& tasksUrl) {
     log("startWriting: url = " + url);
 
     // WARNING: This will segfault if a separate read or write thread
@@ -644,9 +726,17 @@ bool ResourceCalDav::startWriting(const TQString& url) {
         currentIncidence.append(*it);
 
         t->url = url;
-        t->added = getICalString(currentIncidence);
+        t->tasksUrl = tasksUrl;
+        t->added = "";
         t->changed = "";
         t->deleted = "";
+        t->tasksAdded = "";
+        t->tasksChanged = "";
+        t->tasksDeleted = "";
+        if (getICalString(currentIncidence).contains("BEGIN:VEVENT") > 0)
+          t->added = getICalString(currentIncidence);
+        else if (getICalString(currentIncidence).contains("BEGIN:VTODO") > 0)
+          t->tasksAdded = getICalString(currentIncidence);
 
         writingQueuePush(t);
     }
@@ -658,9 +748,18 @@ bool ResourceCalDav::startWriting(const TQString& url) {
         currentIncidence.append(*it);
 
         t->url = url;
+        t->tasksUrl = tasksUrl;
         t->added = "";
-        t->changed = getICalString(currentIncidence);
+        t->changed = "";
         t->deleted = "";
+        t->tasksAdded = "";
+        t->tasksChanged = "";
+        t->tasksDeleted = "";
+
+        if (getICalString(currentIncidence).contains("BEGIN:VEVENT") > 0)
+          t->changed = getICalString(currentIncidence);
+        else if (getICalString(currentIncidence).contains("BEGIN:VTODO") > 0)
+          t->tasksChanged = getICalString(currentIncidence);
 
         writingQueuePush(t);
     }
@@ -672,9 +771,18 @@ bool ResourceCalDav::startWriting(const TQString& url) {
         currentIncidence.append(*it);
 
         t->url = url;
+        t->tasksUrl = tasksUrl;
         t->added = "";
         t->changed = "";
-        t->deleted = getICalString(currentIncidence);
+        t->deleted = "";
+        t->tasksAdded = "";
+        t->tasksChanged = "";
+        t->tasksDeleted = "";
+
+        if (getICalString(currentIncidence).contains("BEGIN:VEVENT") > 0)
+          t->deleted = getICalString(currentIncidence);
+        else if (getICalString(currentIncidence).contains("BEGIN:VTODO") > 0)
+          t->tasksDeleted = getICalString(currentIncidence);
 
         writingQueuePush(t);
     }
@@ -701,7 +809,7 @@ void ResourceCalDav::writingFinished() {
                 else {
                     // Set new password and try again
                     mPrefs->setPassword(TQString(newpass));
-                    startWriting(mPrefs->getFullUrl());
+                    startWriting(mPrefs->getFullUrl(), mPrefs->getFullTasksUrl());
                 }
             }
             else {
diff --git a/kresources/caldav/resource.h b/kresources/caldav/resource.h
index ba1f3e9a..bb69807b 100644
--- a/kresources/caldav/resource.h
+++ b/kresources/caldav/resource.h
@@ -85,13 +85,20 @@ protected:
 
     struct LoadingTask {
         TQString url;
+        TQString tasksUrl;
     };
 
     struct WritingTask {
         TQString url;
+        TQString tasksUrl;
+
         TQString added;
         TQString changed;
         TQString deleted;
+
+        TQString tasksAdded;
+        TQString tasksChanged;
+        TQString tasksDeleted;
     };
 
 
@@ -121,8 +128,9 @@ protected:
     /**
      * Initiates calendar loading process.
      * @param url URL to load calendar data from.
+     * @param tasksUrl URL to load task data from.
      */
-    void startLoading(const TQString& url);
+    void startLoading(const TQString& url, const TQString& tasksUrl);
 
     /**
      * Checks if the data is correct and can be parsed.
@@ -138,12 +146,20 @@ protected:
      */
     bool parseData(const TQString& data);
 
+    /**
+     * Parses the data and adds tasks to the calendar.
+     * Unlike @ref parseData, this function does NOT clear the cache.
+     * @param data calendar data.
+     * @return true on success, false on fail.
+     */
+    bool parseTasksData(const TQString& data);
+
     /**
      * Initiates calendar writing process.
      * @param url URL to save calendar data to.
      * @return true if write was queued successfully, false if not
      */
-    bool startWriting(const TQString& url);
+    bool startWriting(const TQString& url, const TQString& tasksUrl);
 
     /**
      * Returns a list of incidences as a valid iCalendar string.
diff --git a/kresources/caldav/writer.cpp b/kresources/caldav/writer.cpp
index 98008bcd..4580df51 100644
--- a/kresources/caldav/writer.cpp
+++ b/kresources/caldav/writer.cpp
@@ -28,6 +28,7 @@
 // It's done, because, for some reason, SOGo server returns an error
 // on caldav_modify_object. DAViCAL works fine both ways.
 #define USE_CALDAV_MODIFY
+#define USE_CALDAV_TASKS_MODIFY
 
 /*=========================================================================
 | NAMESPACE
@@ -72,6 +73,32 @@ int CalDavWriter::runJob(runtime_info* RT) {
 #endif // if USE_CALDAV_MODIFY
     }
 
+    res = OK;
+
+    kdDebug() << "pushing added tasks objects";
+    res = pushTasksObjects(mTasksAdded, caldav_add_object, OK, RT);
+    if ((OK == res) && (tasksUrl() != "")) {
+#ifdef USE_CALDAV_TASKS_MODIFY
+        kdDebug() << "pushing changed objects";
+        res = pushTasksObjects(mTasksChanged, caldav_tasks_modify_object, OK, RT);
+        if (OK == res) {
+            kdDebug() << "pushing deleted objects";
+            res = pushTasksObjects(mTasksDeleted, caldav_tasks_delete_object, OK, RT);
+        }
+#else // if USE_CALDAV_TASKS_MODIFY
+        kdDebug() << "pushing changed objects (delete)";
+        res = pushTasksObjects(mTasksChanged, caldav_tasks_delete_object, OK, RT);
+        if (OK == res) {
+            kdDebug() << "pushing changed objects (add)";
+            res = pushTasksObjects(mTasksChanged, caldav_add_object, OK, RT);
+            if (OK == res) {
+                kdDebug() << "pushing deleted objects";
+                res = pushTasksObjects(mTasksDeleted, caldav_tasks_delete_object, OK, RT);
+            }
+        }
+#endif // if USE_CALDAV_TASKS_MODIFY
+    }
+
     if (OK != res) {
         clearObjects();
     }
diff --git a/kresources/caldav/writer.h b/kresources/caldav/writer.h
index 2d1d2d7b..e9bfcd3b 100644
--- a/kresources/caldav/writer.h
+++ b/kresources/caldav/writer.h
@@ -46,32 +46,59 @@ public:
     }
 
     /**
-     * Sets the information about added incidences writer should send to server.
-     * @param s icalendar-formatted string consists of all added incidences plus necessary calendar info.
-     * May be an empty string, which means there is no added incidences to send.
+     * Sets the information about added events writer should send to server.
+     * @param s icalendar-formatted string consists of all added events plus necessary calendar info.
+     * May be an empty string, which means there are no added events to send.
      */
     void setAddedObjects(const TQString& s) {
         mAdded = s;
     }
 
     /**
-     * Sets the information about changed incidences writer should send to server.
-     * @param s icalendar-formatted string consists of all changed incidences plus necessary calendar info.
-     * May be an empty string, which means there is no changed incidences to send.
+     * Sets the information about changed events writer should send to server.
+     * @param s icalendar-formatted string consists of all changed events plus necessary calendar info.
+     * May be an empty string, which means there are no changed events to send.
      */
     void setChangedObjects(const TQString& s) {
         mChanged = s;
     }
 
     /**
-     * Sets the information about deleted incidences writer should send to server.
-     * @param s icalendar-formatted string consists of all deleted incidences plus necessary calendar info.
-     * May be an empty string, which means there is no deleted incidences to send.
+     * Sets the information about deleted events writer should send to server.
+     * @param s icalendar-formatted string consists of all deleted events plus necessary calendar info.
+     * May be an empty string, which means there are no deleted events to send.
      */
     void setDeletedObjects(const TQString& s) {
         mDeleted = s;
     }
 
+    /**
+     * Sets the information about added tasks writer should send to server.
+     * @param s icalendar-formatted string consists of all added tasks plus necessary calendar info.
+     * May be an empty string, which means there are no added tasks to send.
+     */
+    void setAddedTasksObjects(const TQString& s) {
+        mTasksAdded = s;
+    }
+
+    /**
+     * Sets the information about changed tasks writer should send to server.
+     * @param s icalendar-formatted string consists of all changed tasks plus necessary calendar info.
+     * May be an empty string, which means there are no changed tasks to send.
+     */
+    void setChangedTasksObjects(const TQString& s) {
+        mTasksChanged = s;
+    }
+
+    /**
+     * Sets the information about deleted tasks writer should send to server.
+     * @param s icalendar-formatted string consists of all deleted tasks plus necessary calendar info.
+     * May be an empty string, which means there are no deleted tasks to send.
+     */
+    void setDeletedTasksObjects(const TQString& s) {
+        mTasksDeleted = s;
+    }
+
     /**
      * Clear all the information previously set.
      */
@@ -79,6 +106,9 @@ public:
         setAddedObjects("");
         setChangedObjects("");
         setDeletedObjects("");
+        setAddedTasksObjects("");
+        setChangedTasksObjects("");
+        setDeletedTasksObjects("");
     }
 
 protected:
@@ -87,7 +117,7 @@ protected:
 
     virtual void cleanJob();
 
-    /// Just a wrapper above libcaldav functions.
+    /// Just a wrapper above libcaldav event writing functions.
     template<typename Operation>
     int pushObjects(const TQString& data, Operation op, int okCode, runtime_info* RT) {
         int r = okCode;
@@ -97,11 +127,25 @@ protected:
         return r;
     }
 
+    /// Just a wrapper above libcaldav task writing functions.
+    template<typename Operation>
+    int pushTasksObjects(const TQString& data, Operation op, int okCode, runtime_info* RT) {
+        int r = okCode;
+        if (!data.isNull() && !data.isEmpty()) {
+            r = op(std::string(data.ascii()).c_str(), std::string(tasksUrl().ascii()).c_str(), RT);
+        }
+        return r;
+    }
+
 private:
 
     TQString mAdded;
     TQString mChanged;
     TQString mDeleted;
+
+    TQString mTasksAdded;
+    TQString mTasksChanged;
+    TQString mTasksDeleted;
 };
 
 } // namespace KCal
-- 
cgit v1.2.3

