summaryrefslogtreecommitdiffstats
path: root/tderesources/caldav
diff options
context:
space:
mode:
Diffstat (limited to 'tderesources/caldav')
-rw-r--r--tderesources/caldav/CMakeLists.txt54
-rw-r--r--tderesources/caldav/ConfigureChecks.cmake32
-rw-r--r--tderesources/caldav/Makefile.am34
-rw-r--r--tderesources/caldav/config.cpp208
-rw-r--r--tderesources/caldav/config.h88
-rw-r--r--tderesources/caldav/configwidgets.cpp249
-rw-r--r--tderesources/caldav/configwidgets.h102
-rw-r--r--tderesources/caldav/export.h56
-rw-r--r--tderesources/caldav/job.cpp173
-rw-r--r--tderesources/caldav/job.h290
-rw-r--r--tderesources/caldav/kcal_caldav.desktop52
-rw-r--r--tderesources/caldav/plugin.cpp49
-rw-r--r--tderesources/caldav/preferences.cpp290
-rw-r--r--tderesources/caldav/preferences.h164
-rw-r--r--tderesources/caldav/prefsskel.kcfg44
-rw-r--r--tderesources/caldav/prefsskel.kcfgc7
-rw-r--r--tderesources/caldav/reader.cpp146
-rw-r--r--tderesources/caldav/reader.h112
-rw-r--r--tderesources/caldav/resource.cpp1011
-rw-r--r--tderesources/caldav/resource.h268
-rw-r--r--tderesources/caldav/uninstall.desktop2
-rw-r--r--tderesources/caldav/writer.cpp162
-rw-r--r--tderesources/caldav/writer.h202
23 files changed, 3795 insertions, 0 deletions
diff --git a/tderesources/caldav/CMakeLists.txt b/tderesources/caldav/CMakeLists.txt
new file mode 100644
index 00000000..b43b5461
--- /dev/null
+++ b/tderesources/caldav/CMakeLists.txt
@@ -0,0 +1,54 @@
+#################################################
+#
+# (C) 2010-2011 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include( ConfigureChecks.cmake )
+
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}/libtdepim
+ ${TDE_INCLUDE_DIR}
+ ${TQT_INCLUDE_DIRS}
+ ${CALDAV_INCLUDE_DIRS}
+)
+
+link_directories(
+ ${TQT_LIBRARY_DIRS}
+ ${CALDAV_LIBRARY_DIRS}
+)
+
+
+##### other data ################################
+
+install(
+ FILES kcal_caldav.desktop
+ DESTINATION ${SERVICES_INSTALL_DIR}/tderesources/kcal )
+
+
+##### kcal_caldav (module) ######################
+
+tde_add_kpart( kcal_caldav AUTOMOC
+ SOURCES plugin.cpp
+ LINK kcal_caldav-shared
+ DESTINATION ${PLUGIN_INSTALL_DIR}
+)
+
+
+##### kcal_caldav (shared) #########################
+
+tde_add_library( kcal_caldav SHARED AUTOMOC
+ SOURCES
+ resource.cpp config.cpp configwidgets.cpp preferences.cpp job.cpp
+ reader.cpp writer.cpp prefsskel.kcfgc
+ VERSION 1.0.0
+ LINK tdepim-shared ${CALDAV_LIBRARIES}
+ DESTINATION ${LIB_INSTALL_DIR}
+)
diff --git a/tderesources/caldav/ConfigureChecks.cmake b/tderesources/caldav/ConfigureChecks.cmake
new file mode 100644
index 00000000..e98ff721
--- /dev/null
+++ b/tderesources/caldav/ConfigureChecks.cmake
@@ -0,0 +1,32 @@
+#################################################
+#
+# (C) 2010-2011 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+# FIXME we need to check for patched library
+
+# libcaldav
+pkg_search_module( CALDAV libcaldav )
+if( CALDAV_FOUND )
+ execute_process(
+ COMMAND pkg-config libcaldav --variable=pkgincludedir
+ OUTPUT_VARIABLE _incdir
+ RESULT_VARIABLE _result
+ OUTPUT_STRIP_TRAILING_WHITESPACE )
+ execute_process(
+ COMMAND pkg-config libcaldav --variable=pkglibdir
+ OUTPUT_VARIABLE _libdir
+ RESULT_VARIABLE _result
+ OUTPUT_STRIP_TRAILING_WHITESPACE )
+ list( APPEND CALDAV_INCLUDE_DIRS ${_incdir} )
+ list( APPEND CALDAV_LIBRARY_DIRS ${_libdir} )
+ list( APPEND CALDAV_LIBRARIES caldav )
+else( )
+ tde_message_fatal( "libcaldav is requested, but was not found on your system" )
+endif( )
diff --git a/tderesources/caldav/Makefile.am b/tderesources/caldav/Makefile.am
new file mode 100644
index 00000000..7749b022
--- /dev/null
+++ b/tderesources/caldav/Makefile.am
@@ -0,0 +1,34 @@
+INCLUDES = -I$(top_srcdir) $(all_includes)
+
+lib_LTLIBRARIES = libkcal_caldav.la
+
+libkcal_caldav_la_SOURCES = resource.cpp \
+ config.cpp \
+ configwidgets.cpp \
+ preferences.cpp \
+ job.cpp \
+ reader.cpp \
+ writer.cpp \
+ prefsskel.kcfgc
+libkcal_caldav_la_LDFLAGS = $(KDE_RPATH) $(all_libraries) \
+ -version-info 1:0:0 -no-undefined
+libkcal_caldav_la_LIBADD = \
+ $(top_builddir)/libkcal/libkcal.la \
+ $(top_builddir)/libtdepim/libtdepim.la \
+ -lcaldav
+libkcal_caldav_la_COMPILE_FIRST = prefsskel.h
+
+kde_module_LTLIBRARIES = kcal_caldav.la
+
+kcal_caldav_la_SOURCES = plugin.cpp
+kcal_caldav_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+kcal_caldav_la_LIBADD = libkcal_caldav.la
+kcal_caldav_la_COMPILE_FIRST = prefsskel.h
+
+kcal_servicedir = $(kde_servicesdir)/tderesources/kcal
+kcal_service_DATA = kcal_caldav.desktop
+
+METASOURCES = AUTO
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/kres_caldav.pot
diff --git a/tderesources/caldav/config.cpp b/tderesources/caldav/config.cpp
new file mode 100644
index 00000000..0a07aafc
--- /dev/null
+++ b/tderesources/caldav/config.cpp
@@ -0,0 +1,208 @@
+/*=========================================================================
+| KCalDAV
+|--------------------------------------------------------------------------
+| (c) 2010 Timothy Pearson
+| (c) 2009 Kumaran Santhanam (initial KDE4 version)
+|
+| This project is released under the GNU General Public License.
+| Please see the file COPYING for more details.
+|--------------------------------------------------------------------------
+| Configuration and properties dialog
+ ========================================================================*/
+
+/*=========================================================================
+| INCLUDES
+ ========================================================================*/
+
+#include "resource.h"
+#include "config.h"
+#include "configwidgets.h"
+
+#include <kcombobox.h>
+#include <kdebug.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <klineedit.h>
+#include <klistview.h>
+#include <kurlrequester.h>
+
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqcheckbox.h>
+
+/*=========================================================================
+| NAMESPACE
+ ========================================================================*/
+
+using namespace KCal;
+
+/*=========================================================================
+| CONSTANTS
+ ========================================================================*/
+
+/*=========================================================================
+| STATIC METHODS
+ ========================================================================*/
+
+ResourceCalDav* ResourceCalDavConfig::getCalDavResource(KRES::Resource* resource) {
+ ResourceCalDav *res = dynamic_cast<ResourceCalDav *>( resource );
+ if (!res) {
+ kdDebug() << "invalid resource type" << '\n';
+ }
+
+ return res;
+}
+
+CalDavPrefs* ResourceCalDavConfig::getPrefs(ResourceCalDav* res) {
+ CalDavPrefs* p = NULL;
+
+ if (res) {
+ p = res->prefs();
+ if (!p) {
+ kdDebug() << "CalDAV: res->prefs() returned NULL" << '\n';
+ }
+ }
+
+ return p;
+}
+
+/*=========================================================================
+| CONSTRUCTOR / DESTRUCTOR
+ ========================================================================*/
+
+ResourceCalDavConfig::ResourceCalDavConfig( TQWidget *parent )
+ : KRES::ConfigWidget( parent )
+{
+ setupUI();
+}
+
+/*=========================================================================
+| METHODS
+ ========================================================================*/
+
+void ResourceCalDavConfig::loadSettings( KRES::Resource *resource ) {
+ ResourceCalDav* res = getCalDavResource(resource);
+ CalDavPrefs* p = getPrefs(res);
+ if (NULL != p) {
+ mUrl->setText(p->url());
+ mUsername->setText(p->username());
+ mRememberPassword->setChecked(p->rememberPassword());
+ mPassword->setText(p->password());
+ mTasksUrl->setText(p->tasksUrl());
+ mJournalsUrl->setText(p->journalsUrl());
+ mUseSTasks->setChecked(p->useSTasks());
+ mUseSJournals->setChecked(p->useSJournals());
+
+ mReloadConfig->loadSettings(res);
+ mSaveConfig->loadSettings(res);
+ }
+}
+
+void ResourceCalDavConfig::saveSettings( KRES::Resource *resource ) {
+ ResourceCalDav* res = getCalDavResource(resource);
+ if (NULL != res) {
+ mReloadConfig->saveSettings(res);
+ mSaveConfig->saveSettings(res);
+
+ CalDavPrefs* p = getPrefs(res);
+ if (NULL != p) {
+ p->setUrl(mUrl->text());
+ p->setUsername(mUsername->text());
+ p->setRememberPassword(mRememberPassword->isChecked());
+ p->setPassword(mPassword->text());
+ p->setTasksUrl(mTasksUrl->text());
+ p->setUseSTasks(mUseSTasks->isChecked());
+ p->setJournalsUrl(mJournalsUrl->text());
+ p->setUseSJournals(mUseSJournals->isChecked());
+ }
+ }
+}
+
+void ResourceCalDavConfig::setupUI() {
+ TQVBoxLayout *vertical = new TQVBoxLayout(this);
+
+ TQGridLayout *mainLayout = new TQGridLayout( this );
+
+ // URL
+ TQLabel *label = new TQLabel( i18n( "URL:" ), this );
+ mUrl = new TQLineEdit( this );
+ 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, 3, 0 );
+ mainLayout->addWidget( mTasksUrl, 3, 1 );
+
+ // Use Task URL checkbox
+ mUseSTasks = new TQCheckBox( i18n("Use separate Tasks URL"), this );
+ mainLayout->addWidget(mUseSTasks, 2, 0 );
+
+ // Journals URL
+ TQLabel *jlabel = new TQLabel( i18n( "Journals URL:" ), this );
+ mJournalsUrl = new TQLineEdit( this );
+ mainLayout->addWidget( jlabel, 5, 0 );
+ mainLayout->addWidget( mJournalsUrl, 5, 1 );
+
+ // Use Journal URL checkbox
+ mUseSJournals = new TQCheckBox( i18n("Use separate Journals URL"), this );
+ mainLayout->addWidget(mUseSJournals, 4, 0 );
+
+ // Username
+ label = new TQLabel( i18n( "Username:" ), this );
+ mUsername = new TQLineEdit( this );
+ mainLayout->addWidget( label, 6, 0 );
+ mainLayout->addWidget( mUsername, 6, 1 );
+
+ // Password
+ label = new TQLabel( i18n( "Password:" ), this );
+ mPassword = new TQLineEdit( this );
+ mPassword->setEchoMode( TQLineEdit::Password );
+ mainLayout->addWidget( label, 7, 0 );
+ mainLayout->addWidget( mPassword, 7, 1 );
+
+ // Remember password checkbox
+ mRememberPassword = new TQCheckBox( i18n("Remember password"), this );
+ mainLayout->addWidget(mRememberPassword, 8, 1);
+
+ mTasksUrl->setEnabled(mUseSTasks->isChecked());
+ connect( mUseSTasks, TQT_SIGNAL( toggled( bool ) ),
+ TQT_SLOT( slotSTasksToggled( bool ) ) );
+
+ mJournalsUrl->setEnabled(mUseSJournals->isChecked());
+ connect( mUseSJournals, TQT_SIGNAL( toggled( bool ) ),
+ TQT_SLOT( slotSJournalsToggled( bool ) ) );
+
+ // configs
+ TQHBoxLayout* horizontal = new TQHBoxLayout(this);
+
+ // Reload config
+ mReloadConfig = new CalDavReloadConfig(this);
+ horizontal->addWidget(mReloadConfig);
+
+ // Save config
+ mSaveConfig = new CalDavSaveConfig(this);
+ horizontal->addWidget(mSaveConfig);
+
+ // FIXME: This feature does not work; hide the UI elements for later use
+ mRememberPassword->hide();
+ label->hide();
+ mPassword->hide();
+
+ // combining layouts
+ vertical->addLayout(mainLayout);
+ vertical->addLayout(horizontal);
+}
+
+void ResourceCalDavConfig::slotSTasksToggled( bool enabled ) {
+ mTasksUrl->setEnabled(enabled);
+}
+
+void ResourceCalDavConfig::slotSJournalsToggled( bool enabled ) {
+ mJournalsUrl->setEnabled(enabled);
+}
+
+#include "config.moc"
+
+// EOF ========================================================================
diff --git a/tderesources/caldav/config.h b/tderesources/caldav/config.h
new file mode 100644
index 00000000..fe03114c
--- /dev/null
+++ b/tderesources/caldav/config.h
@@ -0,0 +1,88 @@
+/*=========================================================================
+| KCalDAV
+|--------------------------------------------------------------------------
+| (c) 2010 Timothy Pearson
+| (c) 2009 Kumaran Santhanam (initial KDE4 version)
+|
+| This project is released under the GNU General Public License.
+| Please see the file COPYING for more details.
+|--------------------------------------------------------------------------
+| Configuration and properties dialog
+ ========================================================================*/
+
+#ifndef KCAL_RESOURCECALDAVCONFIG_H
+#define KCAL_RESOURCECALDAVCONFIG_H
+
+/*=========================================================================
+| INCLUDES
+ ========================================================================*/
+
+#include "resource.h"
+
+#include <kdemacros.h>
+#include <tderesources/configwidget.h>
+
+class TQLineEdit;
+class TQCheckBox;
+
+namespace KCal {
+
+class CalDavReloadConfig;
+class CalDavSaveConfig;
+
+/*=========================================================================
+| CLASS
+ ========================================================================*/
+
+/**
+ * Configuration widget for CalDAV resource.
+ */
+class KDE_EXPORT ResourceCalDavConfig : public KRES::ConfigWidget
+{
+ Q_OBJECT
+
+
+public:
+
+ ResourceCalDavConfig(TQWidget *parent = 0);
+
+public slots:
+
+ virtual void loadSettings(KRES::Resource *resource);
+ virtual void saveSettings(KRES::Resource *resource);
+
+ void slotSTasksToggled( bool );
+ void slotSJournalsToggled( bool );
+
+protected:
+
+ virtual void setupUI();
+
+private:
+
+ TQLineEdit *mUrl;
+ TQLineEdit *mTasksUrl;
+ TQLineEdit *mJournalsUrl;
+ TQLineEdit *mUsername;
+ TQLineEdit *mPassword;
+ TQCheckBox *mUseSTasks;
+ TQCheckBox *mUseSJournals;
+ TQCheckBox *mRememberPassword;
+ CalDavReloadConfig* mReloadConfig;
+ CalDavSaveConfig* mSaveConfig;
+
+ static ResourceCalDav* getCalDavResource(KRES::Resource* res);
+
+ /**
+ * Returns preferences of the given ResourceCalDav object.
+ * @param res resource object.
+ * @return if preferences object is obtained successfully, it's returned. Otherwise, NULL is returned.
+ */
+ static CalDavPrefs* getPrefs(ResourceCalDav* res);
+};
+
+} // namespace KCal
+
+
+#endif // KCAL_RESOURCECALDAVCONFIG_H
+
diff --git a/tderesources/caldav/configwidgets.cpp b/tderesources/caldav/configwidgets.cpp
new file mode 100644
index 00000000..ab8c7905
--- /dev/null
+++ b/tderesources/caldav/configwidgets.cpp
@@ -0,0 +1,249 @@
+/*=========================================================================
+| KCalDAV
+|--------------------------------------------------------------------------
+| (c) 2010 Timothy Pearson
+| (c) 2009 Kumaran Santhanam (initial KDE4 version)
+|
+| This project is released under the GNU General Public License.
+| Please see the file COPYING for more details.
+|--------------------------------------------------------------------------
+| Automatic Reload / Automatic Save configuration widgets.
+| The code is mostly taken from resourcecachedconfig.h/cpp files from
+| the kcal library and changed to meet our requirements.
+| The original copyright is below.
+ ========================================================================*/
+/*
+ This file is part of the kcal library.
+
+ Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "configwidgets.h"
+
+#include <libkcal/resourcecached.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqcheckbox.h>
+#include <tqradiobutton.h>
+#include <tqspinbox.h>
+#include <tqbuttongroup.h>
+#include <tqgroupbox.h>
+#include <tqhbox.h>
+
+using namespace KCal;
+
+//@cond PRIVATE
+class CalDavConfigPrivate
+{
+ public:
+ CalDavConfigPrivate()
+ : mGroup( 0 ),
+ mIntervalSpin( 0 ) {}
+
+ TQButtonGroup *mGroup;
+ TQSpinBox *mIntervalSpin;
+};
+
+class CalDavReloadConfig::Private
+ : public CalDavConfigPrivate
+{
+};
+
+class CalDavSaveConfig::Private
+ : public CalDavConfigPrivate
+{
+};
+//@endcond
+
+CalDavReloadConfig::CalDavReloadConfig( TQWidget *parent )
+ : TQWidget( parent ), d( new KCal::CalDavReloadConfig::Private() )
+{
+ TQBoxLayout *topLayout = new TQVBoxLayout( this );
+
+ //TQGroupBox *groupBox = new TQGroupBox( i18nc( "@title:group", "Automatic Reload" ), this );
+ TQGroupBox *groupBox = new TQGroupBox( i18n( "Automatic Reload" ), this );
+ topLayout->addWidget( groupBox );
+
+ TQRadioButton *noAutomaticReload =
+ new TQRadioButton(
+ //i18nc( "@option:radio never reload the cache", "Never" ), groupBox );
+ i18n( "Never" ), groupBox );
+ TQRadioButton *automaticReloadOnStartup =
+ new TQRadioButton(
+ //i18nc( "@option:radio reload the cache on startup", "Only on startup" ), groupBox );
+ i18n( "Only on startup" ), groupBox );
+ TQRadioButton *intervalRadio =
+ new TQRadioButton(
+// i18nc( "@option:radio reload the cache at regular intervals",
+// "Regular interval" ), groupBox );
+ i18n( "Regular interval" ), groupBox );
+
+ d->mGroup = new TQButtonGroup( this );
+ d->mGroup->hide();
+ d->mGroup->insert( intervalRadio, 2 );
+ d->mGroup->insert( automaticReloadOnStartup, 1 );
+ d->mGroup->insert( noAutomaticReload, 0 );
+
+ connect( intervalRadio, TQT_SIGNAL( toggled( bool ) ),
+ TQT_SLOT( slotIntervalToggled( bool ) ) );
+
+ TQHBox *intervalBox = new TQHBox( groupBox );
+ //new TQLabel( i18nc( "@label:spinbox", "Interval in minutes:" ), intervalBox );
+ new TQLabel( i18n( "Interval in minutes:" ), intervalBox );
+ d->mIntervalSpin = new TQSpinBox( intervalBox );
+ d->mIntervalSpin->setRange( 1, 900 );
+ d->mIntervalSpin->setEnabled( false );
+
+ groupBox->setColumnLayout(1, Qt::Vertical);
+ TQVBoxLayout *vbox = new TQVBoxLayout(groupBox->layout());
+ vbox->addWidget(intervalRadio);
+ vbox->addWidget(intervalBox);
+ vbox->addWidget(automaticReloadOnStartup);
+ vbox->addWidget(noAutomaticReload);
+ vbox->addStretch(1);
+}
+
+CalDavReloadConfig::~CalDavReloadConfig()
+{
+ delete d;
+}
+
+void CalDavReloadConfig::loadSettings( ResourceCached *resource )
+{
+ d->mIntervalSpin->setValue( resource->reloadInterval() );
+ d->mGroup->setButton( resource->reloadPolicy() );
+}
+
+void CalDavReloadConfig::saveSettings( ResourceCached *resource )
+{
+ resource->setReloadInterval( d->mIntervalSpin->value() );
+ resource->setReloadPolicy( d->mGroup->selectedId() );
+}
+
+void CalDavReloadConfig::slotIntervalToggled( bool checked )
+{
+ if ( checked ) {
+ d->mIntervalSpin->setEnabled( true );
+ } else {
+ d->mIntervalSpin->setEnabled( false );
+ }
+}
+
+CalDavSaveConfig::CalDavSaveConfig( TQWidget *parent )
+ : TQWidget( parent ), d( new KCal::CalDavSaveConfig::Private() )
+{
+ TQBoxLayout *topLayout = new TQVBoxLayout( this );
+
+ //TQGroupBox *groupBox = new TQGroupBox( i18nc( "@title:group", "Automatic Save" ), this );
+ TQGroupBox *groupBox = new TQGroupBox( i18n( "Automatic Save" ), this );
+ d->mGroup = new TQButtonGroup( this );
+ d->mGroup->hide();
+ topLayout->addWidget( groupBox );
+
+ TQRadioButton *never =
+ new TQRadioButton(
+ //i18nc( "@option:radio never save the cache automatically", "Never" ), groupBox );
+ i18n( "Never" ), groupBox );
+ TQRadioButton *onExit =
+ new TQRadioButton(
+ //i18nc( "@option:radio save the cache on exit", "Only on exit" ), groupBox );
+ i18n( "Only on exit" ), groupBox );
+
+ TQRadioButton *intervalRadio =
+ new TQRadioButton(
+ //i18nc( "@option:radio save the cache at regular intervals", "Regular interval" ), groupBox );
+ i18n( "Regular interval" ), groupBox );
+
+ d->mGroup = new TQButtonGroup( this );
+ d->mGroup->hide();
+ d->mGroup->insert( never, 0 );
+ d->mGroup->insert( onExit, 1 );
+ d->mGroup->insert( intervalRadio, 2 );
+
+ connect( intervalRadio, TQT_SIGNAL( toggled( bool ) ),
+ TQT_SLOT( slotIntervalToggled( bool ) ) );
+
+ TQHBox *intervalBox = new TQHBox( groupBox );
+ //new TQLabel( i18nc( "@label:spinbox", "Interval in minutes:" ), intervalBox );
+ new TQLabel( i18n( "Interval in minutes:" ), intervalBox );
+ d->mIntervalSpin = new TQSpinBox( intervalBox );
+ d->mIntervalSpin->setRange( 1, 900 );
+ d->mIntervalSpin->setEnabled( false );
+
+ TQRadioButton *delay =
+ new TQRadioButton(
+// i18nc( "@option:radio save the cache after some delay",
+// "Delayed after changes" ), groupBox );
+ i18n( "Delayed after changes" ), groupBox );
+ TQRadioButton *every =
+ new TQRadioButton(
+// i18nc( "@option:radio save the cache after every modification",
+// "Immediately after changes" ), groupBox );
+ i18n( "Immediately after changes" ), groupBox );
+ d->mGroup->insert( delay, 3 );
+ d->mGroup->insert( every, 4 );
+
+ // hide unwanted widgets. They may be useful in future, so don't delete them for now.
+ intervalRadio->hide();
+ intervalBox->hide();
+
+ groupBox->setColumnLayout(1, Qt::Vertical);
+ TQVBoxLayout *vbox = new TQVBoxLayout(groupBox->layout());
+ vbox->addWidget(delay);
+ vbox->addWidget(every);
+ vbox->addWidget(intervalRadio);
+ vbox->addWidget(intervalBox);
+ vbox->addWidget(onExit);
+ vbox->addWidget(never);
+ vbox->addStretch(1);
+
+}
+
+CalDavSaveConfig::~CalDavSaveConfig()
+{
+ delete d;
+}
+
+void CalDavSaveConfig::loadSettings( ResourceCached *resource )
+{
+ d->mIntervalSpin->setValue( resource->saveInterval() );
+ d->mGroup->setButton( resource->savePolicy() );
+}
+
+void CalDavSaveConfig::saveSettings( ResourceCached *resource )
+{
+ resource->setSaveInterval( d->mIntervalSpin->value() );
+ resource->setSavePolicy( d->mGroup->selectedId() );
+}
+
+void CalDavSaveConfig::slotIntervalToggled( bool checked )
+{
+ if ( checked ) {
+ d->mIntervalSpin->setEnabled( true );
+ } else {
+ d->mIntervalSpin->setEnabled( false );
+ }
+}
+
+#include "configwidgets.moc"
+
+// EOF ========================================================================
diff --git a/tderesources/caldav/configwidgets.h b/tderesources/caldav/configwidgets.h
new file mode 100644
index 00000000..1e524844
--- /dev/null
+++ b/tderesources/caldav/configwidgets.h
@@ -0,0 +1,102 @@
+/*=========================================================================
+| KCalDAV
+|--------------------------------------------------------------------------
+| (c) 2010 Timothy Pearson
+| (c) 2009 Kumaran Santhanam (initial KDE4 version)
+|
+| This project is released under the GNU General Public License.
+| Please see the file COPYING for more details.
+|--------------------------------------------------------------------------
+| Automatic Reload / Automatic Save configuration widgets.
+| The code is mostly taken from resourcecachedconfig.h/cpp files from
+| the kcal library and changed to meet our requirements.
+| The original copyright is below.
+ ========================================================================*/
+/*
+ This file is part of the kcal library.
+
+ Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KCALDAV_AUTOWIDGETS_H
+#define KCALDAV_AUTOWIDGETS_H
+
+#include <tqwidget.h>
+#include <kdemacros.h>
+
+namespace KCal {
+
+class ResourceCached;
+
+/**
+ Configuration widget for reload policy
+
+ @see ResourceCached
+*/
+class KDE_EXPORT CalDavReloadConfig : public TQWidget
+{
+ Q_OBJECT
+
+ public:
+ explicit CalDavReloadConfig( TQWidget *parent = 0 );
+ ~CalDavReloadConfig();
+ public slots:
+ void loadSettings( ResourceCached *resource );
+ void saveSettings( ResourceCached *resource );
+
+ protected slots:
+ void slotIntervalToggled( bool );
+
+ private:
+ //@cond PRIVATE
+ //TQ_DISABLE_COPY( CalDavReloadConfig )
+ class Private;
+ Private *const d;
+ //@endcond
+};
+
+/**
+ Configuration widget for save policy
+
+ @see ResourceCached
+*/
+class KDE_EXPORT CalDavSaveConfig : public TQWidget
+{
+ Q_OBJECT
+
+ public:
+ explicit CalDavSaveConfig( TQWidget *parent = 0 );
+ ~CalDavSaveConfig();
+
+ public slots:
+ void loadSettings( ResourceCached *resource );
+ void saveSettings( ResourceCached *resource );
+
+ protected slots:
+ void slotIntervalToggled( bool );
+
+ private:
+ //@cond PRIVATE
+ //TQ_DISABLE_COPY( CalDavSaveConfig )
+ class Private;
+ Private *const d;
+ //@endcond
+};
+
+}
+
+#endif // KCALDAV_AUTOWIDGETS_H
diff --git a/tderesources/caldav/export.h b/tderesources/caldav/export.h
new file mode 100644
index 00000000..c439f53f
--- /dev/null
+++ b/tderesources/caldav/export.h
@@ -0,0 +1,56 @@
+/*=========================================================================
+| KCalDAV
+|--------------------------------------------------------------------------
+| (c) 2010 Timothy Pearson
+| (c) 2009 Kumaran Santhanam (initial KDE4 version)
+|
+| This project is released under the GNU General Public License.
+| Please see the file COPYING for more details.
+|--------------------------------------------------------------------------
+| Some support macros.
+| The code is mostly taken from KDE source files.
+| The original copyright is below.
+ ========================================================================*/
+/* This file is part of the KDE project
+ Copyright (C) 2008 Jarosław Staniek <staniek@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KRESOURCES_TDEPIM_EXPORT_H
+#define KRESOURCES_TDEPIM_EXPORT_H
+
+/** Exports a function returning tderesources plugin factory, for resource class @a resourceclass,
+ * @a resourceconfigclass config class and @a catalog catalog.
+ */
+#define EXPORT_KRESOURCES_PLUGIN( resourceclass, resourceconfigclass, catalog ) \
+ typedef KRES::PluginFactory< resourceclass, resourceconfigclass > FactoryBase; \
+ class Factory : public FactoryBase { \
+ public: Factory() { TDEGlobal::locale()->insertCatalogue(catalog); } \
+ }; \
+ K_EXPORT_PLUGIN( Factory )
+
+/** Like EXPORT_KRESOURCES_PLUGIN but allows to specify two catalogs.
+ */
+#define EXPORT_KRESOURCES_PLUGIN2( resourceclass, resourceconfigclass, catalog1, catalog2 ) \
+ typedef KRES::PluginFactory< resourceclass, resourceconfigclass > FactoryBase; \
+ class Factory : public FactoryBase { \
+ public: Factory() { TDEGlobal::locale()->insertCatalogue(catalog1); \
+ TDEGlobal::locale()->insertCatalogue(catalog2); } \
+ }; \
+ K_EXPORT_PLUGIN( Factory )
+
+#endif
diff --git a/tderesources/caldav/job.cpp b/tderesources/caldav/job.cpp
new file mode 100644
index 00000000..93f91cd5
--- /dev/null
+++ b/tderesources/caldav/job.cpp
@@ -0,0 +1,173 @@
+/*=========================================================================
+| KCalDAV
+|--------------------------------------------------------------------------
+| (c) 2010 Timothy Pearson
+| (c) 2009 Kumaran Santhanam (initial KDE4 version)
+|
+| This project is released under the GNU General Public License.
+| Please see the file COPYING for more details.
+|--------------------------------------------------------------------------
+| Job class for accessing remote calendars.
+ ========================================================================*/
+
+/*=========================================================================
+| INCLUDES
+ ========================================================================*/
+
+#include "job.h"
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <tqmutex.h>
+
+#define log(s) kdDebug() << s << '\n';
+
+/*=========================================================================
+| NAMESPACE
+ ========================================================================*/
+
+using namespace KCal;
+
+/*=========================================================================
+| STATIC
+ ========================================================================*/
+
+/*=========================================================================
+| CONSTRUCTOR AND DESTRUCTOR
+ ========================================================================*/
+
+CalDavJob::CalDavJob(const TQString& url) {
+ cleanJob();
+ setUrl(url);
+}
+
+CalDavJob::~CalDavJob() {
+}
+
+
+/*=========================================================================
+| METHODS
+ ========================================================================*/
+
+void CalDavJob::enableCaldavDebug(runtime_info* rt) {
+ if (rt && rt->options) {
+ rt->options->debug = 0; // if debug = 1, it causes major CPU overhead
+ rt->options->verify_ssl_certificate = FALSE;
+ }
+}
+
+void CalDavJob::setErrorString(const TQString& err, const long number) {
+ mError = true;
+ mErrorString = err;
+ mErrorNumber = number;
+}
+
+void CalDavJob::setTasksErrorString(const TQString& err, const long number) {
+ mTasksError = true;
+ mTasksErrorString = err;
+ mTasksErrorNumber = number;
+}
+
+void CalDavJob::setJournalsErrorString(const TQString& err, const long number) {
+ mJournalsError = true;
+ mJournalsErrorString = err;
+ mJournalsErrorNumber = number;
+}
+
+void CalDavJob::processError(const caldav_error* err) {
+ TQString error_string;
+
+ long code = err->code;
+
+ if (-401 == code) { // unauthorized
+ error_string = i18n("Unauthorized. Username or password incorrect.");
+ } else if (-599 <= code && code <= -300) {
+ error_string = i18n("HTTP error %1. Please ensure that the URL is a valid CalDAV resource.").arg(-code);
+ } else {
+ error_string = err->str;
+ }
+
+ setErrorString(error_string, code);
+}
+
+void CalDavJob::processTasksError(const caldav_error* err) {
+ TQString error_string;
+
+ long code = err->code;
+
+ if (-401 == code) { // unauthorized
+ error_string = i18n("Unauthorized. Username or password incorrect.");
+ } else if (-599 <= code && code <= -300) {
+ error_string = i18n("HTTP error %1. Please ensure that the URL is a valid CalDAV resource.").arg(-code);
+ } else {
+ error_string = err->str;
+ }
+
+ setTasksErrorString(error_string, code);
+}
+
+void CalDavJob::processJournalsError(const caldav_error* err) {
+ TQString error_string;
+
+ long code = err->code;
+
+ if (-401 == code) { // unauthorized
+ error_string = i18n("Unauthorized. Username or password incorrect.");
+ } else if (-599 <= code && code <= -300) {
+ error_string = i18n("HTTP error %1. Please ensure that the URL is a valid CalDAV resource.").arg(-code);
+ } else {
+ error_string = err->str;
+ }
+
+ setJournalsErrorString(error_string, code);
+}
+
+
+void CalDavJob::run() {
+ log("cleaning job");
+ cleanJob();
+
+ int res = OK;
+ int tasksres = OK;
+ int journalsres = OK;
+
+ runtime_info* caldav_runtime = caldav_get_runtime_info();
+
+#ifdef KCALDAV_DEBUG
+ log("setting debug caldav options");
+ enableCaldavDebug(caldav_runtime);
+#endif // KCALDAV_DEBUG
+
+ log("running event job");
+ res = runJob(caldav_runtime);
+
+ if (OK != res) {
+ log("event job failed");
+ processError(caldav_runtime->error);
+ }
+
+ log("running tasks job");
+ tasksres = runTasksJob(caldav_runtime);
+
+ if (OK != tasksres) {
+ log("tasks job failed");
+ processTasksError(caldav_runtime->error);
+ }
+
+ log("running journals job");
+ journalsres = runJournalsJob(caldav_runtime);
+
+ if (OK != journalsres) {
+ log("journals job failed");
+ processJournalsError(caldav_runtime->error);
+ }
+
+ caldav_free_runtime_info(&caldav_runtime);
+
+ // Signal done
+ // 1000 is read, 1001 is write
+ if (type() == 0) TQApplication::postEvent ( parent(), new TQEvent( static_cast<TQEvent::Type>(1000) ) );
+ if (type() == 1) TQApplication::postEvent ( parent(), new TQEvent( static_cast<TQEvent::Type>(1001) ) );
+}
+
+// EOF ========================================================================
diff --git a/tderesources/caldav/job.h b/tderesources/caldav/job.h
new file mode 100644
index 00000000..7d312d90
--- /dev/null
+++ b/tderesources/caldav/job.h
@@ -0,0 +1,290 @@
+/*=========================================================================
+| KCalDAV
+|--------------------------------------------------------------------------
+| (c) 2010 Timothy Pearson
+| (c) 2009 Kumaran Santhanam (initial KDE4 version)
+|
+| This project is released under the GNU General Public License.
+| Please see the file COPYING for more details.
+|--------------------------------------------------------------------------
+| Job class for accessing remote calendars.
+ ========================================================================*/
+
+/*=========================================================================
+| INCLUDES
+ ========================================================================*/
+
+#ifndef KCALDAV_JOB_H
+#define KCALDAV_JOB_H
+
+#include <tqthread.h>
+#include <tqstring.h>
+#include <tqdatetime.h>
+#include <tqapplication.h>
+
+extern "C" {
+ #include <caldav.h>
+}
+
+namespace KCal {
+
+/*=========================================================================
+| CLASS
+ ========================================================================*/
+
+/**
+ * Calendar job.
+ */
+class CalDavJob : public TQThread {
+
+public:
+
+ /**
+ * @param url URL to load.
+ */
+ CalDavJob(const TQString& url = TQString());
+
+ virtual ~CalDavJob();
+
+ /**
+ * Sets a new URL to load.
+ */
+ virtual void setUrl(const TQString& s) {
+ mUrl = s;
+ }
+
+ /**
+ * Sets a new Tasks URL to load.
+ */
+ virtual void setTasksUrl(const TQString& s) {
+ mTasksUrl = s;
+ }
+
+ /**
+ * Sets a new Journals URL to load.
+ */
+ virtual void setJournalsUrl(const TQString& s) {
+ mJournalsUrl = s;
+ }
+
+ /**
+ * Sets the parent qobject.
+ */
+ virtual void setParent(TQObject *s) {
+ mParent = s;
+ }
+
+ /**
+ * Sets the type (0==read, 1==write)
+ */
+ virtual void setType(int s) {
+ mType = s;
+ }
+
+ /**
+ * @return URL to load.
+ */
+ virtual TQString url() const {
+ return mUrl;
+ }
+
+ /**
+ * @return Tasks URL to load.
+ */
+ virtual TQString tasksUrl() const {
+ return mTasksUrl;
+ }
+
+ /**
+ * @return Journals URL to load.
+ */
+ virtual TQString journalsUrl() const {
+ return mJournalsUrl;
+ }
+
+ /**
+ * @return parent object
+ */
+ virtual TQObject *parent() {
+ return mParent;
+ }
+
+ /**
+ * @return type
+ */
+ virtual int type() {
+ return mType;
+ }
+
+ /**
+ * @return true if events downloading process failed.
+ */
+ virtual bool error() const {
+ return mError;
+ }
+
+ /**
+ * @return true if tasks downloading process failed.
+ */
+ virtual bool tasksError() const {
+ return mTasksError;
+ }
+
+ /**
+ * @return true if journals downloading process failed.
+ */
+ virtual bool journalsError() const {
+ return mJournalsError;
+ }
+
+ /**
+ * @return an event error string.
+ */
+ virtual TQString errorString() const {
+ return mErrorString;
+ }
+
+ /**
+ * @return a task error string.
+ */
+ virtual TQString tasksErrorString() const {
+ return mTasksErrorString;
+ }
+
+ /**
+ * @return a journal error string.
+ */
+ virtual TQString journalsErrorString() const {
+ return mJournalsErrorString;
+ }
+
+ /**
+ * @return an event error number.
+ */
+ virtual long errorNumber() const {
+ return mErrorNumber;
+ }
+
+ /**
+ * @return a task error number.
+ */
+ virtual long tasksErrorNumber() const {
+ return mTasksErrorNumber;
+ }
+
+ /**
+ * @return a journal error number.
+ */
+ virtual long journalsErrorNumber() const {
+ return mJournalsErrorNumber;
+ }
+
+protected:
+
+ virtual void run();
+
+ /**
+ * Main run method for event jobs. Jobs should not override run() method.
+ * Instead of this they should override this one.
+ * @param caldavRuntime specific libcaldav runtime information. This pointer should not be saved for the usage
+ * outside of runJob.
+ * @return libcaldav response code (see CALDAV_RESPONSE)
+ */
+ virtual int runJob(runtime_info* caldavRuntime) = 0;
+
+ /**
+ * Main run method for task jobs. Jobs should not override run() method.
+ * Instead of this they should override this one.
+ * @param caldavRuntime specific libcaldav runtime information. This pointer should not be saved for the usage
+ * outside of runJob.
+ * @return libcaldav response code (see CALDAV_RESPONSE)
+ */
+ virtual int runTasksJob(runtime_info* caldavRuntime) = 0;
+
+ /**
+ * Main run method for journal jobs. Jobs should not override run() method.
+ * Instead of this they should override this one.
+ * @param caldavRuntime specific libcaldav runtime information. This pointer should not be saved for the usage
+ * outside of runJob.
+ * @return libcaldav response code (see CALDAV_RESPONSE)
+ */
+ virtual int runJournalsJob(runtime_info* caldavRuntime) = 0;
+
+ /**
+ * Some cleaning. Jobs may (and usually should) override this method.
+ */
+ virtual void cleanJob() {
+ mError = false;
+ mErrorString = "";
+ mErrorNumber = 0;
+ mTasksError = false;
+ mTasksErrorString = "";
+ mTasksErrorNumber = 0;
+ mJournalsError = false;
+ mJournalsErrorString = "";
+ mJournalsErrorNumber = 0;
+ }
+
+ /**
+ * Sets an event error string to @p err. Also sets an error flag.
+ */
+ void setErrorString(const TQString& str, const long number);
+
+ /**
+ * Sets a task error string to @p err. Also sets an error flag.
+ */
+ void setTasksErrorString(const TQString& str, const long number);
+
+ /**
+ * Sets a journal error string to @p err. Also sets an error flag.
+ */
+ void setJournalsErrorString(const TQString& str, const long number);
+
+ /**
+ * Process an event error.
+ * Subclasses can overwrite this method, if some special error message handling
+ * should be done. Call setErrorString() to set the error after processing is done.
+ * @param err error structure.
+ */
+ virtual void processError(const caldav_error* err);
+
+ /**
+ * Process a task error.
+ * Subclasses can overwrite this method, if some special error message handling
+ * should be done. Call setErrorString() to set the error after processing is done.
+ * @param err error structure.
+ */
+ virtual void processTasksError(const caldav_error* err);
+
+ /**
+ * Process a journal error.
+ * Subclasses can overwrite this method, if some special error message handling
+ * should be done. Call setErrorString() to set the error after processing is done.
+ * @param err error structure.
+ */
+ virtual void processJournalsError(const caldav_error* err);
+
+private:
+
+ TQString mUrl;
+ TQString mTasksUrl;
+ TQString mJournalsUrl;
+ bool mError;
+ bool mTasksError;
+ bool mJournalsError;
+ TQString mErrorString;
+ TQString mTasksErrorString;
+ TQString mJournalsErrorString;
+ long mErrorNumber;
+ long mTasksErrorNumber;
+ long mJournalsErrorNumber;
+ TQObject *mParent;
+ int mType;
+
+ void enableCaldavDebug(runtime_info*);
+};
+
+} // namespace KCal
+
+#endif // KCALDAV_JOB_H
+
diff --git a/tderesources/caldav/kcal_caldav.desktop b/tderesources/caldav/kcal_caldav.desktop
new file mode 100644
index 00000000..b237c04b
--- /dev/null
+++ b/tderesources/caldav/kcal_caldav.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Name=CalDAV Server (e.g. Google Calendar)
+Name[af]=CalDAV bediener (bv. Google Calendar)
+Name[bg]=Сървър CalDAV (e.g. Google Calendar)
+Name[br]=Servijer CalDAV (e.g. Google Calendar)
+Name[ca]=Servidor CalDAV (p.ex. Google Calendar)
+Name[cs]=CalDAV server (např. Google Calendar)
+Name[da]=CalDAV-server (f.eks. Google Calendar)
+Name[de]=CalDAV-Server (z. B. Google Calendar)
+Name[el]=Εξυπηρετητής CalDAV (π.χ. Google Calendar)
+Name[es]=Servidor CalDAV (por ejemplo, Google Calendar)
+Name[et]=CalDAV server (nt. Google Calendar)
+Name[eu]=CalDAV zerbitzaria (adib. Google Calendar)
+Name[fa]=کارساز CalDAV (مثلاً Google Calendar)
+Name[fi]=CalDAV-palvelin (esim. Google Calendar)
+Name[fr]=CalDAV Serveur (ex. Google Calendar)
+Name[fy]=CalDAV-tsjinner (Google Calendar)
+Name[ga]=Freastalaí CalDAV (m.sh. Google Calendar)
+Name[gl]=Servidor CalDAV (e.g. Google Calendar)
+Name[hu]=CalDAV-kiszolgáló (pl. Google Calendar)
+Name[is]=CalDAV þjónn (t.d. Google Calendar)
+Name[it]=Server CalDAV (per es. Google Calendar)
+Name[ja]=CalDAV サーバ (例 Google Calendar)
+Name[ka]=სერვერი CalDAV (მაგ., Google Calendar)
+Name[kk]=CalDAV сервері (мысалы Google Calendar)
+Name[km]=ម៉ាស៊ីន​បម្រើ CalDAV (ឧ. Google Calendar)
+Name[lt]=CalDAV serveris (pvz.: Google Calendar)
+Name[ms]=Pelayan CalDAV (misalnya Google Calendar)
+Name[nb]=CalDAV-tjener (f.eks. Google Calendar)
+Name[nds]=CalDAV-Server (t.B. Google Calendar)
+Name[ne]=समूह DAV सर्भर (जस्तै: खुला ग्रुपवेयर)
+Name[nl]=CalDAV-server (Google Calendar)
+Name[nn]=CalDAV-tenar (t.d. Google Calendar)
+Name[pl]=Serwer CalDAV (np. Google Calendar)
+Name[pt]=Servidor CalDAV (por exemplo Google Calendar)
+Name[pt_BR]=Servidor GroupDav (p. ex. Google Calendar)
+Name[ru]=Сервер CalDAV (например, Google Calendar)
+Name[sk]=CalDAV Server (napr. Google Calendar)
+Name[sl]=Strežnik CalDAV (npr. Google Calendar)
+Name[sr]=CalDAV сервер (нпр. Google Calendar)
+Name[sr@Latn]=CalDAV server (npr. Google Calendar)
+Name[sv]=CalDAV-server (t.ex. Google Calendar)
+Name[ta]=CalDAV சேவகன் (e.g. Google Calendar)
+Name[tr]=CalDAV Sunucusu (ör. Google Calendar)
+Name[uk]=Сервер CalDAV (напр., Google Calendar)
+Name[zh_CN]=CalDAV 服务器(如 Google Calendar)
+Name[zh_TW]=CalDAV 伺服器 (如: Google Calendar)
+X-TDE-Library=kcal_caldav
+Type=Service
+ServiceTypes=KResources/Plugin
+X-TDE-ResourceFamily=calendar
+X-TDE-ResourceType=caldav
diff --git a/tderesources/caldav/plugin.cpp b/tderesources/caldav/plugin.cpp
new file mode 100644
index 00000000..9ce6d60f
--- /dev/null
+++ b/tderesources/caldav/plugin.cpp
@@ -0,0 +1,49 @@
+/*=========================================================================
+| KCalDAV
+|--------------------------------------------------------------------------
+| (c) 2010 Timothy Pearson
+| (c) 2009 Kumaran Santhanam (initial KDE4 version)
+|
+| This project is released under the GNU General Public License.
+| Please see the file COPYING for more details.
+|--------------------------------------------------------------------------
+| CalDAV resource factory.
+ ========================================================================*/
+
+/*=========================================================================
+| INCLUDES
+ ========================================================================*/
+
+#include "resource.h"
+#include "config.h"
+#include "export.h"
+
+#include <kglobal.h>
+#include <klocale.h>
+
+/*=========================================================================
+| NAMESPACE
+ ========================================================================*/
+
+using namespace KCal;
+
+/*=========================================================================
+| CLASS
+ ========================================================================*/
+
+// Creates the resource factory.
+//EXPORT_KRESOURCES_PLUGIN2( ResourceCalDav, ResourceCalDavConfig, "libkcal", "kres_caldav" )
+
+typedef KRES::PluginFactory<ResourceCalDav, ResourceCalDavConfig> CalDavFactory;
+
+extern "C"
+{
+ void *init_kcal_caldav()
+ {
+ TDEGlobal::locale()->insertCatalogue( "libkcal" );
+ TDEGlobal::locale()->insertCatalogue( "kres_caldav" );
+ return new CalDavFactory;
+ }
+}
+
+// EOF ========================================================================
diff --git a/tderesources/caldav/preferences.cpp b/tderesources/caldav/preferences.cpp
new file mode 100644
index 00000000..5286d022
--- /dev/null
+++ b/tderesources/caldav/preferences.cpp
@@ -0,0 +1,290 @@
+/*=========================================================================
+| KCalDAV
+|--------------------------------------------------------------------------
+| (c) 2010 Timothy Pearson
+| (c) 2009 Kumaran Santhanam (initial KDE4 version)
+|
+| This project is released under the GNU General Public License.
+| Please see the file COPYING for more details.
+|--------------------------------------------------------------------------
+| CalDAV resource preferences class.
+ ========================================================================*/
+
+/*=========================================================================
+| INCLUDES
+ ========================================================================*/
+
+#include "preferences.h"
+
+#include <tdewallet.h>
+#include <tqstring.h>
+#include <tqurl.h>
+#include <kdebug.h>
+
+/*=========================================================================
+| NAMESPACES
+ ========================================================================*/
+
+using namespace KCal;
+using namespace KWallet;
+
+/*=========================================================================
+| CONSTANTS
+ ========================================================================*/
+
+const TQString CalDavPrefs::NO_PASSWORD = "";
+const TQString CalDavPrefs::WALLET_FOLDER = "CalDAV resource";
+const TQString CalDavPrefs::WALLET_PWD_SUFFIX = ":caldav_password";
+
+/*=========================================================================
+| METHODS
+ ========================================================================*/
+
+bool CalDavPrefs::setWalletFolder(const TQString& folder) {
+ bool ret = true;
+
+ if (!mNoWallet && NULL != mWallet) {
+ if (!mWallet->hasFolder(folder)) {
+ if (!mWallet->createFolder(folder)) {
+ ret = false;
+ kdWarning() << "can't create the wallet folder for CalDAV passwords";
+ }
+ }
+ if (!mWallet->setFolder(folder)) {
+ ret = false;
+ kdWarning() << "can't set the wallet folder for CalDAV passwords";
+ }
+ } else {
+ // the wallet is inaccessible or not configured
+ ret = false;
+ }
+
+ return ret;
+}
+
+Wallet* CalDavPrefs::getWallet() {
+ Wallet* ret = NULL;
+
+ if (!mNoWallet) {
+ // the wallet is not marked as inaccessible
+
+ if (NULL == mWallet) {
+ kdDebug() << "creating wallet for " + mPrefix << '\n';
+
+ mWallet = Wallet::openWallet(Wallet::NetworkWallet(), 0);
+ if (NULL == mWallet) {
+ mNoWallet = true; // can't open the wallet, mark it inaccessible
+ kdWarning() << "can't create a wallet for CalDAV passwords";
+ } else {
+ if (setWalletFolder(WALLET_FOLDER)) {
+ // reserved
+ } else {
+ // can't set the wallet folder, remove the wallet and mark it inaccessible
+ kdWarning() << "can't set the walet folder for CalDAV passwords";
+ removeWallet(true);
+ }
+ }
+ }
+
+ ret = mWallet;
+ }
+
+ return ret;
+}
+
+void CalDavPrefs::removeWallet(bool noWallet) {
+ delete mWallet;
+ mWallet = NULL;
+ mNoWallet = noWallet;
+}
+
+void CalDavPrefs::addPrefix(const TQString& prefix) {
+ TDEConfigSkeletonItem::List itemList = items();
+ TDEConfigSkeletonItem::List::Iterator it;
+
+ for ( it = itemList.begin(); it != itemList.end(); ++it ) {
+ (*it)->setGroup( prefix + ':' + (*it)->group() );
+ }
+}
+
+bool CalDavPrefs::writePasswordToWallet(const TQString& password) {
+
+ Wallet* w = getWallet();
+
+ bool ret = false;
+ if (NULL != w) {
+ int rc = w->writePassword(mPrefix + WALLET_PWD_SUFFIX, password);
+ if (0 != rc) {
+ kdWarning() << "CalDAV: can't write password to the wallet";
+ } else {
+ ret = true;
+ }
+ }
+
+ return ret;
+}
+
+bool CalDavPrefs::readPasswordFromWallet(TQString& password) {
+ Wallet* w = getWallet();
+
+ bool ret = false;
+ if (NULL != w) {
+ TQString p;
+ int rc = w->readPassword(mPrefix + WALLET_PWD_SUFFIX, p);
+ if (0 == rc) {
+ //CalDavPrefsSkel::setPassword(p);
+ password = p;
+ ret = true;
+ } else {
+ kdWarning() << "CalDAV: can't read password from the wallet";
+ password = NO_PASSWORD;
+ }
+ }
+
+ return ret;
+}
+
+bool CalDavPrefs::removePasswordFromWallet() {
+
+ Wallet* w = getWallet();
+
+ bool ret = false;
+ if (NULL != w) {
+ int rc = w->removeEntry(mPrefix + WALLET_PWD_SUFFIX);
+ if (0 == rc) {
+ ret = true;
+ } else {
+ kdWarning() << "CalDAV: can't remove password from the wallet";
+ }
+ }
+
+ return ret;
+}
+
+void CalDavPrefs::setPassword(const TQString& p) {
+
+ mPassword = p;
+
+ if (rememberPassword()) {
+ writePasswordToWallet(p);
+ }
+}
+
+TQString CalDavPrefs::password() {
+ if (NO_PASSWORD == mPassword) {
+ readPasswordFromWallet(mPassword);
+ }
+ return mPassword;
+}
+
+TQString CalDavPrefs::getusername() {
+ return username();
+}
+
+void CalDavPrefs::setRememberPassword(bool v) {
+ kdDebug() << "remember: " << v << '\n';
+
+ CalDavPrefsSkel::setRememberPassword(v);
+
+ if (!v) {
+ // we should not remember password. If there is one already stored, it must be removed.
+ kdDebug() << "removing password from wallet" << '\n';
+ removePasswordFromWallet();
+ }
+}
+
+void CalDavPrefs::writeConfig() {
+ CalDavPrefsSkel::writeConfig();
+}
+
+void CalDavPrefs::readConfig() {
+
+ CalDavPrefsSkel::readConfig();
+
+ // the password is not in config file, try to restore it from the wallet.
+ /*if (rememberPassword()) {
+ readPasswordFromWallet();
+ }*/
+}
+
+TQString CalDavPrefs::getFullUrl() {
+
+ TQUrl t(url());
+ 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;
+}
+
+TQString CalDavPrefs::getFullTasksUrl() {
+ if (useSTasks() == 0)
+ return getFullUrl();
+
+ 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;
+}
+
+TQString CalDavPrefs::getFullJournalsUrl() {
+ if (useSJournals() == 0)
+ return getFullUrl();
+
+ TQUrl t(journalsUrl());
+ 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/tderesources/caldav/preferences.h b/tderesources/caldav/preferences.h
new file mode 100644
index 00000000..0c4532cf
--- /dev/null
+++ b/tderesources/caldav/preferences.h
@@ -0,0 +1,164 @@
+/*=========================================================================
+| KCalDAV
+|--------------------------------------------------------------------------
+| (c) 2010 Timothy Pearson
+| (c) 2009 Kumaran Santhanam (initial KDE4 version)
+|
+| This project is released under the GNU General Public License.
+| Please see the file COPYING for more details.
+|--------------------------------------------------------------------------
+| CalDAV resource preferences class.
+ ========================================================================*/
+
+/*=========================================================================
+| INCLUDES
+ ========================================================================*/
+
+#ifndef KCAL_CALDAVPREFS_H
+#define KCAL_CALDAVPREFS_H
+
+#include "prefsskel.h"
+
+#include <tdewallet.h>
+#include <kdebug.h>
+
+class TQString;
+
+namespace KCal {
+
+/*=========================================================================
+| CLASS
+ ========================================================================*/
+
+/**
+ * This class provides access to ResourceCalDav preferences.
+ * It inherits auto-generated CalDavPrefsSkel class to add password-handling code.
+ * KWallet is used for storing passwords.
+ * It also adds code to allow multiple CalDAV resources to store settings in the same
+ * config file.
+ */
+class CalDavPrefs : public CalDavPrefsSkel {
+
+public:
+
+ /**
+ * @param prefix Unique prefix of the resource instance (use identifier() method).
+ */
+ CalDavPrefs(const TQString& prefix)
+ : mWallet(NULL)
+ , mNoWallet(false)
+ , mPrefix(prefix)
+ , mPassword(NO_PASSWORD)
+ {
+ addPrefix(prefix);
+ }
+
+ virtual ~CalDavPrefs() {
+ kdDebug() << "removing wallet" << '\n';
+ removeWallet();
+ }
+
+ virtual void writeConfig();
+ virtual void readConfig();
+
+ /**
+ * Sets a new password. Also, if remember password flag is true,
+ * remembers the password in the wallet. So, if you want the password
+ * to be properly saved, call this method after ensuring the remember flag
+ * is set.
+ */
+ void setPassword(const TQString& p);
+
+ /**
+ * Returns password. The password is taken from the wallet.
+ * May return an empty string, if there is no password available.
+ */
+ TQString password();
+
+ /**
+ * Returns the username.
+ */
+ TQString getusername();
+
+ void setRememberPassword(bool v);
+
+ /**
+ * @return A full URL to connect to CalDAV server (including username and password).
+ */
+ TQString getFullUrl();
+
+ /**
+ * @return A full URL to connect to CalDAV Tasks server (including username and password).
+ */
+ TQString getFullTasksUrl();
+
+ /**
+ * @return A full URL to connect to CalDAV Journals server (including username and password).
+ */
+ TQString getFullJournalsUrl();
+
+protected:
+
+ /**
+ * Add an unique prefix to TDEConfigGroup, so that different instances of the resource
+ * can use the same config file.
+ * @param prefix Unique prefix of the resource instance.
+ */
+ void addPrefix(const TQString& prefix);
+
+ /**
+ * Returns the wallet or NULL, if the wallet can't be obtained.
+ */
+ KWallet::Wallet* getWallet();
+
+ /**
+ * Tries to set a working folder for the wallet. If the wallet is not configured yet, does nothing.
+ * @param folder the wallet working folder
+ * @return true, if the folder has been set, and false otherwise.
+ */
+ bool setWalletFolder(const TQString& folder);
+
+ /**
+ * Removes the wallet. If @p noWallet is set, the wallet has been marked inaccessible, so that subsequent
+ * getWallet calls will not try to recreate it.
+ */
+ void removeWallet(bool noWallet = false);
+
+ /**
+ * Wrire password to the wallet.
+ * @param password password to write
+ * @return true on success, false on failure
+ */
+ bool writePasswordToWallet(const TQString& password);
+
+ /**
+ * Extracts password from the wallet.
+ * @param password a variable to save read password to.
+ * @return true on success, false on failure
+ */
+ bool readPasswordFromWallet(TQString& password);
+
+ /**
+ * Clears password in the wallet.
+ * @return true on success, false on failure
+ */
+ bool removePasswordFromWallet();
+
+private:
+
+ static const TQString NO_PASSWORD;
+ static const TQString WALLET_FOLDER;
+ static const TQString WALLET_PWD_SUFFIX;
+
+ KWallet::Wallet* mWallet;
+ bool mNoWallet;
+
+ TQString mPrefix;
+ TQString mPassword;
+};
+
+} // namespace KCal
+
+#endif // KCAL_CALDAVPREFS_H
+
+
diff --git a/tderesources/caldav/prefsskel.kcfg b/tderesources/caldav/prefsskel.kcfg
new file mode 100644
index 00000000..5f4cdc16
--- /dev/null
+++ b/tderesources/caldav/prefsskel.kcfg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="tderesources_caldavrc" />
+ <group name="General" >
+
+ <entry key="Url" type="String" >
+ <label>URL</label>
+ </entry>
+
+ <entry key="TasksUrl" type="String" >
+ <label>URL</label>
+ </entry>
+
+ <entry key="JournalsUrl" type="String" >
+ <label>URL</label>
+ </entry>
+
+ <entry key="UseSTasks" type="Bool" >
+ <label>Use separate Tasks URL</label>
+ <default>false</default>
+ </entry>
+
+ <entry key="UseSJournals" type="Bool" >
+ <label>Use separate Journals URL</label>
+ <default>false</default>
+ </entry>
+
+ <entry key="Username" type="String">
+ <label>User Name</label>
+ </entry>
+
+<!-- <entry key="Password" type="String" >
+ <label>Password</label>
+ </entry>-->
+
+ <entry key="RememberPassword" type="Bool" >
+ <label>Remember password</label>
+ </entry>
+
+ </group>
+</kcfg>
diff --git a/tderesources/caldav/prefsskel.kcfgc b/tderesources/caldav/prefsskel.kcfgc
new file mode 100644
index 00000000..b6b3aae0
--- /dev/null
+++ b/tderesources/caldav/prefsskel.kcfgc
@@ -0,0 +1,7 @@
+# Code generation options for kconfig_compiler
+File=prefsskel.kcfg
+ClassName=CalDavPrefsSkel
+NameSpace=KCal
+Singleton=false
+Mutators=true
+GlobalEnums=true
diff --git a/tderesources/caldav/reader.cpp b/tderesources/caldav/reader.cpp
new file mode 100644
index 00000000..92501e4f
--- /dev/null
+++ b/tderesources/caldav/reader.cpp
@@ -0,0 +1,146 @@
+/*=========================================================================
+| KCalDAV
+|--------------------------------------------------------------------------
+| (c) 2010 Timothy Pearson
+| (c) 2009 Kumaran Santhanam (initial KDE4 version)
+|
+| This project is released under the GNU General Public License.
+| Please see the file COPYING for more details.
+|--------------------------------------------------------------------------
+| Remote calendar loading.
+ ========================================================================*/
+
+/*=========================================================================
+| INCLUDES
+ ========================================================================*/
+
+#include "reader.h"
+#include <kdebug.h>
+#include <string>
+
+/*=========================================================================
+| NAMESPACE
+ ========================================================================*/
+
+using namespace KCal;
+
+/*=========================================================================
+| METHODS
+ ========================================================================*/
+
+void CalDavReader::cleanJob() {
+ CalDavJob::cleanJob();
+ mData = "";
+}
+
+void CalDavReader::cleanTasksJob() {
+ CalDavJob::cleanJob();
+ mTasksData = "";
+}
+
+void CalDavReader::cleanJournalsJob() {
+ CalDavJob::cleanJob();
+ mJournalsData = "";
+}
+
+int CalDavReader::runJob(runtime_info* RT) {
+ kdDebug() << "reader::run, url: " << url() << '\n';
+
+ response* result = caldav_get_response();
+ CALDAV_RESPONSE res = OK;
+
+ if ((OK == res) && (url() != "")) {
+ if (mGetAll) {
+ kdDebug() << "getting all objects" << '\n';
+ res = caldav_getall_object(result, std::string(url().ascii()).c_str(), RT);
+ } else {
+ kdDebug() << "getting object from the specified time range" << '\n';
+ res = caldav_get_object(result, mTimeStart.toTime_t(), mTimeEnd.toTime_t(), std::string(url().ascii()).c_str(), RT);
+ }
+
+ if (OK == res) {
+ kdDebug() << "success" << '\n';
+ if (result->msg) {
+ mData = result->msg;
+ } else {
+ kdDebug() << "empty collection" << '\n';
+ // empty collection
+ mData = "";
+ }
+ }
+ }
+
+ caldav_free_response(&result);
+
+ return res;
+}
+
+int CalDavReader::runTasksJob(runtime_info* RT) {
+ kdDebug() << "reader::run, tasksUrl: " << tasksUrl() << '\n';
+
+ response* result = caldav_get_response();
+ CALDAV_RESPONSE tasksres = OK;
+
+ if ((OK == tasksres) && (tasksUrl() != "")) {
+ kdDebug() << "reader::run, url: " << tasksUrl() << '\n';
+
+ if (mGetAll) {
+ kdDebug() << "getting all objects" << '\n';
+ tasksres = caldav_tasks_getall_object(result, std::string(tasksUrl().ascii()).c_str(), RT);
+ } else {
+ kdDebug() << "getting object from the specified time range" << '\n';
+ tasksres = caldav_tasks_get_object(result, mTimeStart.toTime_t(), mTimeEnd.toTime_t(), std::string(tasksUrl().ascii()).c_str(), RT);
+ }
+
+ if (OK == tasksres) {
+ kdDebug() << "success" << '\n';
+ if (result->msg) {
+ mTasksData = result->msg;
+ } else {
+ kdDebug() << "empty collection" << '\n';
+ // empty collection
+ mTasksData = "";
+ }
+ }
+
+ caldav_free_response(&result);
+ }
+
+ return tasksres;
+}
+
+int CalDavReader::runJournalsJob(runtime_info* RT) {
+ kdDebug() << "reader::run, journalsUrl: " << journalsUrl() << '\n';
+
+ response* result = caldav_get_response();
+ CALDAV_RESPONSE journalsres = OK;
+
+ if ((OK == journalsres) && (journalsUrl() != "")) {
+ kdDebug() << "reader::run, url: " << journalsUrl() << '\n';
+
+ if (mGetAll) {
+ kdDebug() << "getting all objects" << '\n';
+ journalsres = caldav_tasks_getall_object(result, std::string(journalsUrl().ascii()).c_str(), RT);
+ } else {
+ kdDebug() << "getting object from the specified time range" << '\n';
+ journalsres = caldav_tasks_get_object(result, mTimeStart.toTime_t(), mTimeEnd.toTime_t(), std::string(journalsUrl().ascii()).c_str(), RT);
+ }
+
+ if (OK == journalsres) {
+ kdDebug() << "success" << '\n';
+ if (result->msg) {
+ mJournalsData = result->msg;
+ } else {
+ kdDebug() << "empty collection" << '\n';
+ // empty collection
+ mJournalsData = "";
+ }
+ }
+
+ caldav_free_response(&result);
+ }
+
+ return journalsres;
+}
+
+// EOF ========================================================================
diff --git a/tderesources/caldav/reader.h b/tderesources/caldav/reader.h
new file mode 100644
index 00000000..9bcc8c87
--- /dev/null
+++ b/tderesources/caldav/reader.h
@@ -0,0 +1,112 @@
+/*=========================================================================
+| KCalDAV
+|--------------------------------------------------------------------------
+| (c) 2010 Timothy Pearson
+| (c) 2009 Kumaran Santhanam (initial KDE4 version)
+|
+| This project is released under the GNU General Public License.
+| Please see the file COPYING for more details.
+|--------------------------------------------------------------------------
+| Remote calendar loading class.
+ ========================================================================*/
+
+/*=========================================================================
+| INCLUDES
+ ========================================================================*/
+
+#ifndef KCALDAV_LOADER_H
+#define KCALDAV_LOADER_H
+
+#include "job.h"
+
+#include <tqstring.h>
+#include <tqdatetime.h>
+
+namespace KCal {
+
+/*=========================================================================
+| CLASS
+ ========================================================================*/
+
+/**
+ * Calendar Reader.
+ */
+class CalDavReader : public CalDavJob {
+
+public:
+
+ /**
+ * @param url URL to load.
+ */
+ CalDavReader(const TQString& url = TQString()) :
+ CalDavJob(url)
+ , mGetAll(true)
+ {
+ }
+
+ /**
+ * Sets a time range. Only event between @p start and @p end will be loaded.
+ * This method call disables the effect of setGetAll() call.
+ * setGetAll() call disables the effect of this method.
+ */
+ void setRange(const TQDateTime& start, const TQDateTime& end) {
+ mGetAll = false;
+ mTimeStart = start;
+ mTimeEnd = end;
+ }
+
+ /**
+ * Sets the flag to load all events from the remote calendar.
+ * This method call disables the effect of setRange() call.
+ * setGetAll() call disables the effect of this method.
+ */
+ void setGetAll() {
+ mGetAll = true;
+ }
+
+ /**
+ * @return downloaded calendar data in iCal format.
+ */
+ TQString data() const {
+ return mData;
+ }
+
+ /**
+ * @return downloaded task data in iCal format.
+ */
+ TQString tasksData() const {
+ return mTasksData;
+ }
+
+ /**
+ * @return downloaded journal data in iCal format.
+ */
+ TQString journalsData() const {
+ return mJournalsData;
+ }
+
+protected:
+
+ virtual int runJob(runtime_info* caldavRuntime);
+ virtual int runTasksJob(runtime_info* caldavRuntime);
+ virtual int runJournalsJob(runtime_info* caldavRuntime);
+
+ virtual void cleanJob();
+ virtual void cleanTasksJob();
+ virtual void cleanJournalsJob();
+
+private:
+
+ TQString mData;
+ TQString mTasksData;
+ TQString mJournalsData;
+ bool mGetAll;
+ TQDateTime mTimeStart;
+ TQDateTime mTimeEnd;
+
+};
+
+} // namespace KCal
+
+#endif // KCALDAV_LOADER_H
+
diff --git a/tderesources/caldav/resource.cpp b/tderesources/caldav/resource.cpp
new file mode 100644
index 00000000..b9285e61
--- /dev/null
+++ b/tderesources/caldav/resource.cpp
@@ -0,0 +1,1011 @@
+/*=========================================================================
+| KCalDAV
+|--------------------------------------------------------------------------
+| (c) 2010 Timothy Pearson
+| (c) 2009 Kumaran Santhanam (initial KDE4 version)
+|
+| This project is released under the GNU General Public License.
+| Please see the file COPYING for more details.
+|--------------------------------------------------------------------------
+| Main interface to the KResource system.
+ ========================================================================*/
+
+/*=========================================================================
+| INCLUDES
+ ========================================================================*/
+
+#include <string.h>
+#include <unistd.h>
+
+#include <tqurl.h>
+#include <tqmessagebox.h>
+#include <tqapplication.h>
+#include <tqeventloop.h>
+
+#include <libkcal/calendarlocal.h>
+#include <libkcal/icalformat.h>
+
+#include <klocale.h>
+#include <kpassdlg.h>
+
+#include <tqdatetime.h>
+#include <tqmutex.h>
+#include <tqthread.h>
+
+#ifdef KCALDAV_DEBUG
+ #include <tqfile.h>
+#endif
+
+#include "resource.h"
+#include "reader.h"
+#include "writer.h"
+
+/*=========================================================================
+| NAMESPACE
+ ========================================================================*/
+
+using namespace KCal;
+
+/*=========================================================================
+| CONSTANTS
+ ========================================================================*/
+
+const unsigned long ResourceCalDav::TERMINATION_WAITING_TIME = 3 * 1000; // 3 seconds
+const int ResourceCalDav::CACHE_DAYS = 90;
+
+const int ResourceCalDav::DEFAULT_RELOAD_INTERVAL = 10;
+const int ResourceCalDav::DEFAULT_SAVE_INTERVAL = 10;
+const int ResourceCalDav::DEFAULT_RELOAD_POLICY = ResourceCached::ReloadInterval;
+const int ResourceCalDav::DEFAULT_SAVE_POLICY = ResourceCached::SaveDelayed;
+
+/*=========================================================================
+| UTILITY
+ ========================================================================*/
+
+#define log(s) kdDebug() << identifier() << ": " << (s) << '\n';
+
+/*=========================================================================
+| CONSTRUCTOR / DESTRUCTOR
+ ========================================================================*/
+
+ResourceCalDav::ResourceCalDav( const TDEConfig *config ) :
+ ResourceCached(config)
+ , readLockout(false)
+ , mAllWritesComplete(false)
+ , mLock(true)
+ , mPrefs(NULL)
+ , mLoader(NULL)
+ , mWriter(NULL)
+ , mProgress(NULL)
+ , mLoadingQueueReady(true)
+ , mWritingQueueReady(true)
+ , mWriteRetryTimer(NULL)
+{
+ log("ResourceCalDav(config)");
+ init();
+
+ if ( config ) {
+ readConfig( config );
+ }
+}
+
+ResourceCalDav::~ResourceCalDav() {
+ log("jobs termination");
+
+ if (mWriteRetryTimer != NULL) {
+ mWriteRetryTimer->stop(); // Unfortunately we cannot do anything at this point; if this timer is still running something is seriously wrong
+ }
+
+ if (mLoader) {
+ readLockout = true;
+ mLoader->terminate();
+ mLoader->wait(TERMINATION_WAITING_TIME);
+ mLoadingQueueReady = true;
+ }
+
+ while ((mWriter->running() == true) || (mWritingQueue.isEmpty() == false) || !mWritingQueueReady) {
+ readLockout = true;
+ sleep(1);
+ tqApp->processEvents(TQEventLoop::ExcludeUserInput);
+ }
+
+ if (mWriter) {
+ mWriter->terminate();
+ }
+
+ log("waiting for jobs terminated");
+
+ if (mLoader) {
+ mLoader->wait(TERMINATION_WAITING_TIME);
+ }
+ if (mWriter) {
+ mWriter->wait(TERMINATION_WAITING_TIME);
+ }
+
+ log("deleting jobs");
+
+ delete mLoader;
+ delete mWriter;
+
+ log("deleting preferences");
+
+ delete mPrefs;
+}
+
+bool ResourceCalDav::isSaving() {
+ doSave();
+ return (((mWriteRetryTimer != NULL) ? 1 : 0) || (mWriter->running() == true) || (mWritingQueue.isEmpty() == false) || !mWritingQueueReady || readLockout);
+}
+
+/*=========================================================================
+| GENERAL METHODS
+ ========================================================================*/
+
+bool ResourceCalDav::doLoad() {
+ bool syncCache = true;
+
+ if ((mLoadingQueueReady == false) || (mLoadingQueue.isEmpty() == false) || (mLoader->running() == true) || (isSaving() == true)) {
+ return true; // Silently fail; the user has obviously not responded to a dialog and we don't need to pop up more of them!
+ }
+
+ log(TQString("doLoad(%1)").arg(syncCache));
+
+ clearCache();
+
+ log("loading from cache");
+ disableChangeNotification();
+ loadCache();
+ enableChangeNotification();
+ clearChanges(); // TODO: Determine if this really needs to be here, as it might clear out the calendar prematurely causing user confusion while the download process is running
+ emit resourceChanged(this);
+ emit resourceLoaded(this);
+
+ log("starting download job");
+ startLoading(mPrefs->getFullUrl(), mPrefs->getFullTasksUrl(), mPrefs->getFullJournalsUrl());
+
+ return true;
+}
+
+bool ResourceCalDav::doSave() {
+ bool syncCache = true;
+
+ log(TQString("doSave(%1)").arg(syncCache));
+
+ if (!hasChanges()) {
+ log("no changes");
+ return true;
+ }
+
+ log("saving cache");
+ saveCache();
+
+ // Delete any queued read jobs
+ mLoadingQueue.clear();
+
+ // See if there is a running read thread and terminate it
+ if (mLoader->running() == true) {
+ mLoader->terminate();
+ mLoader->wait(TERMINATION_WAITING_TIME);
+ mLoadingQueueReady = true;
+ }
+
+ log("start writing job");
+ if (startWriting(mPrefs->getFullUrl(), mPrefs->getFullTasksUrl(), mPrefs->getFullJournalsUrl()) == 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...
+ clearChanges();
+ if (mWriteRetryTimer != NULL) {
+ if (mWriteRetryTimer->isActive() == false) {
+ disconnect( mWriteRetryTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(doSave()) );
+ delete mWriteRetryTimer;
+ mWriteRetryTimer = NULL;
+ }
+ }
+ return true;
+ }
+ else return true; // We do not need to alert the user to this transient failure; a timer has been started to retry the save
+}
+
+
+KABC::Lock* ResourceCalDav::lock() {
+ log("lock()");
+ return &mLock;
+}
+
+void ResourceCalDav::readConfig( const TDEConfig *config ) {
+ log("readConfig");
+ mPrefs->readConfig();
+ ResourceCached::readConfig(config);
+}
+
+void ResourceCalDav::writeConfig( TDEConfig *config ) {
+ log("writeConfig()");
+ ResourceCalendar::writeConfig(config);
+ mPrefs->writeConfig();
+ ResourceCached::writeConfig(config);
+}
+
+CalDavPrefs* ResourceCalDav::createPrefs() const {
+ log("createPrefs()");
+ CalDavPrefs* p = new CalDavPrefs(identifier());
+ return p;
+}
+
+void ResourceCalDav::init() {
+ // default settings
+ setReloadInterval(DEFAULT_RELOAD_INTERVAL);
+ setReloadPolicy(DEFAULT_RELOAD_POLICY);
+ setSaveInterval(DEFAULT_SAVE_INTERVAL);
+ setSavePolicy(DEFAULT_SAVE_POLICY);
+
+ // creating preferences
+ mPrefs = createPrefs();
+
+ // creating reader/writer instances
+ mLoader = new CalDavReader;
+ mWriter = new CalDavWriter;
+
+ // creating jobs
+ // TQt4 handles this quite differently, as shown below,
+ // whereas TQt3 needs events (see ::event())
+// connect(mLoader, TQT_SIGNAL(finished()), this, TQT_SLOT(loadFinished()));
+// connect(mWriter, TQT_SIGNAL(finished()), this, TQT_SLOT(writingFinished()));
+
+ setType("ResourceCalDav");
+}
+
+void ResourceCalDav::setIncidencesReadOnly(Incidence::List& inc, bool readOnly) {
+ Incidence::List::Iterator it;
+ for ( it = inc.begin(); it != inc.end(); ++it ) {
+ (*it)->setReadOnly( readOnly );
+ }
+}
+
+void ResourceCalDav::ensureReadOnlyFlagHonored() {
+ //disableChangeNotification();
+
+ Incidence::List inc( rawIncidences() );
+ setIncidencesReadOnly(inc, readOnly());
+
+ //enableChangeNotification();
+
+ emit resourceChanged(this);
+}
+
+void ResourceCalDav::setReadOnly(bool v) {
+ KRES::Resource::setReadOnly(v);
+ log("ensuring read only flag honored");
+ ensureReadOnlyFlagHonored();
+}
+
+void ResourceCalDav::updateProgressBar(int direction) {
+ int current_queued_events;
+ static int original_queued_events;
+
+ // See if anything is in the queues
+ current_queued_events = mWritingQueue.count() + mLoadingQueue.count();
+ if ((direction == 0) && (mLoader->running() == true)) current_queued_events++;
+ if ((direction == 1) && (mWriter->running() == true)) current_queued_events++;
+ if (current_queued_events > original_queued_events) {
+ original_queued_events = current_queued_events;
+ }
+
+ if (current_queued_events == 0) {
+ if ( mProgress != NULL) {
+ mProgress->setComplete();
+ mProgress = NULL;
+ original_queued_events = 0;
+ }
+ }
+ else {
+ if (mProgress == NULL) {
+ if (direction == 0) mProgress = KPIM::ProgressManager::createProgressItem(KPIM::ProgressManager::getUniqueID(), i18n("Downloading Calendar") );
+ if (direction == 1) mProgress = KPIM::ProgressManager::createProgressItem(KPIM::ProgressManager::getUniqueID(), i18n("Uploading Calendar") );
+ }
+ mProgress->setProgress( ((((float)original_queued_events-(float)current_queued_events)*100)/(float)original_queued_events) );
+ }
+}
+
+/*=========================================================================
+| READING METHODS
+ ========================================================================*/
+
+void ResourceCalDav::loadingQueuePush(const LoadingTask *task) {
+ if ((mLoadingQueue.isEmpty() == true) && (mLoader->running() == false)) {
+ mLoadingQueue.enqueue(task);
+ updateProgressBar(0);
+ loadingQueuePop();
+ }
+}
+
+void ResourceCalDav::loadingQueuePop() {
+ if (!mLoadingQueueReady || mLoadingQueue.isEmpty() || (isSaving() == true)) {
+ return;
+ }
+
+ if (!mLoader) {
+ log("loader == NULL");
+ return;
+ }
+
+ // Loading queue and mLoadingQueueReady flag are not shared resources, i.e. only one thread has an access to them.
+ // That's why no mutexes are required.
+ LoadingTask *t = mLoadingQueue.head();
+
+ mLoader->setUrl(t->url);
+ mLoader->setTasksUrl(t->tasksUrl);
+ mLoader->setJournalsUrl(t->journalsUrl);
+ mLoader->setParent(this);
+ mLoader->setType(0);
+
+ TQDateTime dt(TQDate::currentDate());
+ mLoader->setRange(dt.addDays(-CACHE_DAYS), dt.addDays(CACHE_DAYS));
+ //mLoader->setGetAll();
+
+ mLoadingQueueReady = false;
+
+ log("starting actual download job");
+ mLoader->start(TQThread::LowestPriority);
+
+ // if all ok, removing the task from the queue
+ mLoadingQueue.dequeue();
+ updateProgressBar(0);
+
+ delete t;
+}
+
+void ResourceCalDav::startLoading(const TQString& url, const TQString& tasksUrl, const TQString& journalsUrl) {
+ LoadingTask *t = new LoadingTask;
+ t->url = url;
+ t->tasksUrl = tasksUrl;
+ t->journalsUrl = journalsUrl;
+ loadingQueuePush(t);
+}
+
+void ResourceCalDav::loadFinished() {
+ CalDavReader* loader = mLoader;
+
+ log("load finished");
+
+ if (!loader) {
+ log("loader is NULL");
+ return;
+ }
+
+ if (loader->error()) {
+ if (loader->errorNumber() == -401) {
+ if (NULL != mPrefs) {
+ TQCString newpass;
+ if (KPasswordDialog::getPassword (newpass, TQString("<b>") + i18n("Remote authorization required") + TQString("</b><p>") + i18n("Please input the password for") + TQString(" ") + mPrefs->getusername(), NULL) != 1) {
+ log("load error: " + loader->errorString() );
+ loadError(TQString("[%1] ").arg(abs(loader->errorNumber())) + loader->errorString());
+ }
+ else {
+ // Set new password and try again
+ mPrefs->setPassword(TQString(newpass));
+ startLoading(mPrefs->getFullUrl(), mPrefs->getFullTasksUrl(), mPrefs->getFullJournalsUrl());
+ }
+ }
+ else {
+ log("load error: " + loader->errorString() );
+ loadError(TQString("[%1] ").arg(abs(loader->errorNumber())) + loader->errorString());
+ }
+ }
+ else {
+ log("load error: " + loader->errorString() );
+ loadError(TQString("[%1] ").arg(abs(loader->errorNumber())) + loader->errorString());
+ }
+ } else {
+ log("successful event load");
+ TQString data = loader->data();
+
+ 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)
+ // have some lines separated by single \r rather than \n or \r\n.
+ // ICalFormat fails to parse that.
+ data.replace("\r\n", "\n"); // to avoid \r\n becomes \n\n after the next line
+ data.replace('\r', '\n');
+
+ log("trying to parse...");
+ if (parseData(data)) {
+ // 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);
+ }
+ }
+ }
+
+ if (loader->tasksError()) {
+ if (loader->tasksErrorNumber() == -401) {
+ if (NULL != mPrefs) {
+// TQCString newpass;
+// if (KPasswordDialog::getPassword (newpass, TQString("<b>") + i18n("Remote authorization required") + TQString("</b><p>") + i18n("Please input the password for") + TQString(" ") + mPrefs->getusername(), NULL) != 1) {
+// log("load error: " + loader->tasksErrorString() );
+// loadError(TQString("[%1] ").arg(abs(loader->tasksErrorNumber())) + loader->tasksErrorString());
+// }
+// else {
+// // Set new password and try again
+// mPrefs->setPassword(TQString(newpass));
+// startLoading(mPrefs->getFullUrl(), mPrefs->getFullTasksUrl(), mPrefs->getFullJournalsUrl());
+// }
+ }
+ else {
+ log("load error: " + loader->tasksErrorString() );
+ loadError(TQString("[%1] ").arg(abs(loader->tasksErrorNumber())) + loader->tasksErrorString());
+ }
+ }
+ else {
+ log("load error: " + loader->tasksErrorString() );
+ loadError(TQString("[%1] ").arg(abs(loader->tasksErrorNumber())) + loader->tasksErrorString());
+ }
+ } else {
+ log("successful tasks load");
+ TQString tasksData = loader->tasksData();
+
+ 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);
+ }
+ }
+ }
+
+ if (loader->journalsError()) {
+ if (loader->journalsErrorNumber() == -401) {
+ if (NULL != mPrefs) {
+// TQCString newpass;
+// if (KPasswordDialog::getPassword (newpass, TQString("<b>") + i18n("Remote authorization required") + TQString("</b><p>") + i18n("Please input the password for") + TQString(" ") + mPrefs->getusername(), NULL) != 1) {
+// log("load error: " + loader->journalsErrorString() );
+// loadError(TQString("[%1] ").arg(abs(loader->journalsErrorNumber())) + loader->journalsErrorString());
+// }
+// else {
+// // Set new password and try again
+// mPrefs->setPassword(TQString(newpass));
+// startLoading(mPrefs->getFullUrl(), mPrefs->getFullTasksUrl(), mPrefs->getFullJournalsUrl());
+// }
+ }
+ else {
+ log("load error: " + loader->journalsErrorString() );
+ loadError(TQString("[%1] ").arg(abs(loader->journalsErrorNumber())) + loader->journalsErrorString());
+ }
+ }
+ else {
+ log("load error: " + loader->journalsErrorString() );
+ loadError(TQString("[%1] ").arg(abs(loader->journalsErrorNumber())) + loader->journalsErrorString());
+ }
+ } else {
+ log("successful journals load");
+ TQString journalsData = loader->journalsData();
+
+ if (!journalsData.isNull() && !journalsData.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.
+ journalsData.replace("\r\n", "\n"); // to avoid \r\n becomes \n\n after the next line
+ journalsData.replace('\r', '\n');
+
+ log("trying to parse...");
+ if (parseJournalsData(journalsData)) {
+ // 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.
+ // That's why no mutexes are required.
+ mLoader->terminate();
+ mLoader->wait(TERMINATION_WAITING_TIME);
+ mLoadingQueueReady = true;
+ updateProgressBar(0);
+ loadingQueuePop();
+}
+
+bool ResourceCalDav::checkData(const TQString& data) {
+ log("checking the data");
+
+ ICalFormat ical;
+ bool ret = true;
+ if (!ical.fromString(&mCalendar, data)) {
+ log("invalid ical string");
+ ret = false;
+ }
+
+ return ret;
+}
+
+bool ResourceCalDav::parseData(const TQString& data) {
+ log("parseData()");
+
+ 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;
+ }
+
+ log("clearing cache");
+ clearEventsCache();
+
+ 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;
+}
+
+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;
+ }
+
+ log("clearing cache");
+ clearTodosCache();
+
+ 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;
+}
+
+bool ResourceCalDav::parseJournalsData(const TQString& data) {
+ log("parseJournalsData()");
+
+ 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;
+ }
+
+ log("clearing cache");
+ clearJournalsCache();
+
+ 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
+ ========================================================================*/
+
+TQString ResourceCalDav::getICalString(const Incidence::List& inc) {
+ if (inc.isEmpty()) {
+ return "";
+ }
+
+ CalendarLocal loc(timeZoneId());
+ TQString data = "";
+ TQString header = "";
+ TQString footer = "";
+ ICalFormat ical;
+
+ // Get the iCal header and footer
+ header = ical.toString(&loc);
+ int location = header.find("END:VCALENDAR", 0, true);
+ footer = header.mid(location, 0xffffffff);
+ header.remove("END:VCALENDAR");
+
+ data = data + header;
+ // NOTE: This is very susceptible to invalid entries in added/changed/deletedIncidences
+ // Be very careful with clearChange/clearChanges, and be sure to clear after load and save...
+ for(Incidence::List::ConstIterator it = inc.constBegin(); it != inc.constEnd(); ++it) {
+ Incidence *i = (*it)->clone();
+ data = data + ical.toString(i, &mCalendar);
+ }
+ data = data + footer;
+
+ // Remove any line feeds/carriage returns/white spaces from the UID field as they WILL break libcaldav
+ int uidPos = data.find("UID:", 0) + 4;
+ int nextPos = data.findRev("\n", data.find(":", uidPos));
+ TQString uidField = data.mid(uidPos, nextPos-uidPos);
+ data.remove(uidPos, nextPos-uidPos);
+ uidField.replace("\n", "");
+ uidField.replace("\r", "");
+ uidField.replace(" ", "");
+ data.insert(uidPos, uidField);
+ return data;
+}
+
+void ResourceCalDav::writingQueuePush(const WritingTask *task) {
+// printf("task->added: %s\n\r", task->added.ascii());
+// printf("task->deleted: %s\n\r", task->deleted.ascii());
+// printf("task->changed: %s\n\r", task->changed.ascii());
+ mWritingQueue.enqueue(task);
+ updateProgressBar(1);
+ writingQueuePop();
+}
+
+void ResourceCalDav::writingQueuePop() {
+ if (!mWritingQueueReady || mWritingQueue.isEmpty()) {
+ return;
+ }
+
+ if (!mWriter) {
+ log("writer == NULL");
+ return;
+ }
+
+ // Writing queue and mWritingQueueReady flag are not shared resources, i.e. only one thread has an access to them.
+ // That's why no mutexes are required.
+ WritingTask *t = mWritingQueue.head();
+
+ log("writingQueuePop: url = " + t->url);
+
+ mWriter->setUrl(t->url);
+ mWriter->setTasksUrl(t->tasksUrl);
+ mWriter->setJournalsUrl(t->journalsUrl);
+ mWriter->setParent(this);
+ mWriter->setType(1);
+
+#ifdef KCALDAV_DEBUG
+ const TQString fout_path = "/tmp/kcaldav_upload_" + identifier() + ".tmp";
+
+ TQFile fout(fout_path);
+ if (fout.open(IO_WriteOnly | IO_Append)) {
+ TQTextStream sout(&fout);
+ sout << "---------- " << resourceName() << ": --------------------------------\n";
+ sout << "================== Added:\n" << t->added << "\n";
+ sout << "================== Changed:\n" << t->changed << "\n";
+ sout << "================== Deleted:\n" << t->deleted << "\n";
+ fout.close();
+ } else {
+ loadError(i18n("can't open file"));
+ }
+#endif // debug
+
+ mWriter->setAddedObjects(t->added);
+ mWriter->setChangedObjects(t->changed);
+ mWriter->setDeletedObjects(t->deleted);
+
+ mWriter->setAddedTasksObjects(t->tasksAdded);
+ mWriter->setChangedTasksObjects(t->tasksChanged);
+ mWriter->setDeletedTasksObjects(t->tasksDeleted);
+
+ mWriter->setAddedJournalsObjects(t->journalsAdded);
+ mWriter->setChangedJournalsObjects(t->journalsChanged);
+ mWriter->setDeletedJournalsObjects(t->journalsDeleted);
+
+ mWritingQueueReady = false;
+
+ log("starting actual write job");
+ mWriter->start(TQThread::LowestPriority);
+
+ // if all ok, remove the task from the queue
+ mWritingQueue.dequeue();
+ updateProgressBar(1);
+
+ delete t;
+}
+
+bool ResourceCalDav::event ( TQEvent * e ) {
+ if (e->type() == 1000) {
+ // Read done
+ loadFinished();
+ return TRUE;
+ }
+ else if (e->type() == 1001) {
+ // Write done
+ writingFinished();
+ return TRUE;
+ }
+ else return FALSE;
+}
+
+void ResourceCalDav::releaseReadLockout() {
+ readLockout = false;
+}
+
+bool ResourceCalDav::startWriting(const TQString& url, const TQString& tasksUrl, const TQString& journalsUrl) {
+ log("startWriting: url = " + url);
+
+ // WARNING: This will segfault if a separate read or write thread
+ // modifies the calendar with clearChanges() or similar
+ // Before these calls are made any existing read (and maybe write) threads should be finished
+ if ((mLoader->running() == true) || (mLoadingQueue.isEmpty() == false) || (mWriter->running() == true) || (mWritingQueue.isEmpty() == false)) {
+ if (mWriteRetryTimer == NULL) {
+ mWriteRetryTimer = new TQTimer(this);
+ connect( mWriteRetryTimer, TQT_SIGNAL(timeout()), TQT_SLOT(doSave()) );
+ }
+ mWriteRetryTimer->start(1000, TRUE);
+ return false;
+ }
+
+ // If we don't lock the read out for a few seconds, it would be possible for the old calendar to be
+ // downloaded before our changes are committed, presenting a very bad image to the user as his/her appointments
+ // revert to the state they were in before the write (albiet temporarily)
+ readLockout = true;
+
+ // This needs to send each event separately; i.e. if two events were added they need
+ // to be extracted and pushed on the stack independently (using two calls to writingQueuePush())
+
+ Incidence::List added = addedIncidences();
+ Incidence::List changed = changedIncidences();
+ Incidence::List deleted = deletedIncidences();
+
+ Incidence::List::ConstIterator it;
+ Incidence::List currentIncidence;
+
+ for( it = added.begin(); it != added.end(); ++it ) {
+ WritingTask *t = new WritingTask;
+
+ currentIncidence.clear();
+ currentIncidence.append(*it);
+
+ t->url = url;
+ t->tasksUrl = tasksUrl;
+ t->journalsUrl = journalsUrl;
+ t->added = "";
+ t->changed = "";
+ t->deleted = "";
+ t->tasksAdded = "";
+ t->tasksChanged = "";
+ t->tasksDeleted = "";
+ t->journalsAdded = "";
+ t->journalsChanged = "";
+ t->journalsDeleted = "";
+ if (getICalString(currentIncidence).contains("BEGIN:VEVENT") > 0)
+ t->added = getICalString(currentIncidence);
+ else if (getICalString(currentIncidence).contains("BEGIN:VTODO") > 0)
+ t->tasksAdded = getICalString(currentIncidence);
+ else if (getICalString(currentIncidence).contains("BEGIN:VJOURNAL") > 0)
+ t->journalsAdded = getICalString(currentIncidence);
+
+ writingQueuePush(t);
+ }
+
+ for( it = changed.begin(); it != changed.end(); ++it ) {
+ WritingTask *t = new WritingTask;
+
+ currentIncidence.clear();
+ currentIncidence.append(*it);
+
+ t->url = url;
+ t->tasksUrl = tasksUrl;
+ t->added = "";
+ t->changed = "";
+ t->deleted = "";
+ t->tasksAdded = "";
+ t->tasksChanged = "";
+ t->tasksDeleted = "";
+ t->journalsAdded = "";
+ t->journalsChanged = "";
+ t->journalsDeleted = "";
+
+ if (getICalString(currentIncidence).contains("BEGIN:VEVENT") > 0)
+ t->changed = getICalString(currentIncidence);
+ else if (getICalString(currentIncidence).contains("BEGIN:VTODO") > 0)
+ t->tasksChanged = getICalString(currentIncidence);
+ else if (getICalString(currentIncidence).contains("BEGIN:VJOURNAL") > 0)
+ t->journalsChanged = getICalString(currentIncidence);
+
+ writingQueuePush(t);
+ }
+
+ for( it = deleted.begin(); it != deleted.end(); ++it ) {
+ WritingTask *t = new WritingTask;
+
+ currentIncidence.clear();
+ currentIncidence.append(*it);
+
+ t->url = url;
+ t->tasksUrl = tasksUrl;
+ t->added = "";
+ t->changed = "";
+ t->deleted = "";
+ t->tasksAdded = "";
+ t->tasksChanged = "";
+ t->tasksDeleted = "";
+ t->journalsAdded = "";
+ t->journalsChanged = "";
+ t->journalsDeleted = "";
+
+ if (getICalString(currentIncidence).contains("BEGIN:VEVENT") > 0)
+ t->deleted = getICalString(currentIncidence);
+ else if (getICalString(currentIncidence).contains("BEGIN:VTODO") > 0)
+ t->tasksDeleted = getICalString(currentIncidence);
+ else if (getICalString(currentIncidence).contains("BEGIN:VJOURNALS") > 0)
+ t->journalsDeleted = getICalString(currentIncidence);
+
+ writingQueuePush(t);
+ }
+
+ return true;
+}
+
+void ResourceCalDav::writingFinished() {
+ log("writing finished");
+
+ if (!mWriter) {
+ log("mWriter is NULL");
+ return;
+ }
+
+ if (mWriter->error() && (abs(mWriter->errorNumber()) != 207)) {
+ if (mWriter->errorNumber() == -401) {
+ if (NULL != mPrefs) {
+ TQCString newpass;
+ if (KPasswordDialog::getPassword (newpass, TQString("<b>") + i18n("Remote authorization required") + TQString("</b><p>") + i18n("Please input the password for") + TQString(" ") + mPrefs->getusername(), NULL) != 1) {
+ log("write error: " + mWriter->errorString());
+ saveError(TQString("[%1] ").arg(abs(mWriter->errorNumber())) + mWriter->errorString());
+ }
+ else {
+ // Set new password and try again
+ mPrefs->setPassword(TQString(newpass));
+ startWriting(mPrefs->getFullUrl(), mPrefs->getFullTasksUrl(), mPrefs->getFullJournalsUrl());
+ }
+ }
+ else {
+ log("write error: " + mWriter->errorString());
+ saveError(TQString("[%1] ").arg(abs(mWriter->errorNumber())) + mWriter->errorString());
+ }
+ }
+ else {
+ log("write error: " + mWriter->errorString());
+ saveError(TQString("[%1] ").arg(abs(mWriter->errorNumber())) + mWriter->errorString());
+ }
+ } else {
+ log("success");
+ // is there something to do here?
+ }
+
+ // Give the remote system a few seconds to process the data before we allow any read operations
+ TQTimer::singleShot( 3000, this, TQT_SLOT(releaseReadLockout()) );
+
+ // Writing queue and mWritingQueueReady flag are not shared resources, i.e. only one thread has an access to them.
+ // That's why no mutexes are required.
+ mWriter->terminate();
+ mWriter->wait(TERMINATION_WAITING_TIME);
+ mWritingQueueReady = true;
+ updateProgressBar(1);
+ writingQueuePop();
+}
+
+#include "resource.moc"
+
+// EOF ========================================================================
diff --git a/tderesources/caldav/resource.h b/tderesources/caldav/resource.h
new file mode 100644
index 00000000..ea04ef48
--- /dev/null
+++ b/tderesources/caldav/resource.h
@@ -0,0 +1,268 @@
+/*=========================================================================
+| KCalDAV
+|--------------------------------------------------------------------------
+| (c) 2010 Timothy Pearson
+| (c) 2009 Kumaran Santhanam (initial KDE4 version)
+|
+| This project is released under the GNU General Public License.
+| Please see the file COPYING for more details.
+|--------------------------------------------------------------------------
+| Main interface to the KResource system.
+ ========================================================================*/
+
+/*=========================================================================
+| INCLUDES
+ ========================================================================*/
+
+#ifndef KCAL_RESOURCECALDAV_H
+#define KCAL_RESOURCECALDAV_H
+
+#include "preferences.h"
+#include <tqthread.h>
+#include <tqptrqueue.h>
+
+#include <libkcal/resourcecached.h>
+#include <libtdepim/progressmanager.h>
+
+#include <kabc/locknull.h>
+
+#include <tdepimmacros.h>
+#include <kconfig.h>
+
+namespace KCal {
+
+class CalDavReader;
+class CalDavWriter;
+
+/*=========================================================================
+| CLASS
+ ========================================================================*/
+
+/**
+ * This class provides a resource for accessing calendars via CalDAV protocol.
+ */
+class KDE_EXPORT ResourceCalDav : public ResourceCached
+{
+ Q_OBJECT
+
+
+public:
+
+ explicit ResourceCalDav( const TDEConfig *config );
+ virtual ~ResourceCalDav();
+
+ void readConfig( const TDEConfig *config );
+ void writeConfig( TDEConfig *config );
+
+ /**
+ * @return This resource preferences.
+ */
+ CalDavPrefs* prefs() {
+ return mPrefs;
+ }
+
+ /**
+ * @return This resource preferences.
+ */
+ const CalDavPrefs* prefs() const {
+ return mPrefs;
+ }
+
+ virtual void setReadOnly(bool v);
+
+ bool isSaving();
+
+protected slots:
+
+ void loadFinished();
+
+ virtual bool doSave();
+
+ void writingFinished();
+
+ void releaseReadLockout();
+
+protected:
+
+ struct LoadingTask {
+ TQString url;
+ TQString tasksUrl;
+ TQString journalsUrl;
+ };
+
+ struct WritingTask {
+ TQString url;
+ TQString tasksUrl;
+ TQString journalsUrl;
+
+ TQString added;
+ TQString changed;
+ TQString deleted;
+
+ TQString tasksAdded;
+ TQString tasksChanged;
+ TQString tasksDeleted;
+
+ TQString journalsAdded;
+ TQString journalsChanged;
+ TQString journalsDeleted;
+ };
+
+
+ virtual bool doLoad();
+// virtual bool doSave();
+
+ virtual KABC::Lock* lock();
+
+ /**
+ * Creates prefs and configures them.
+ * @return a newly created preferences object. It should be removed by the caller.
+ */
+ CalDavPrefs* createPrefs() const;
+
+ /**
+ * Initializes internal state.
+ * Particulary, sets save and reload policies to default values,
+ * creates writing and reading jobs and preferences objects.
+ */
+ void init();
+
+ /**
+ * Updates the progress bar
+ */
+ void updateProgressBar(int direction);
+
+ /**
+ * Initiates calendar loading process.
+ * @param url URL to load calendar data from.
+ * @param tasksUrl URL to load task data from.
+ * @param journalsUrl URL to load journal data from.
+ */
+ void startLoading(const TQString& url, const TQString& tasksUrl, const TQString& journalsUrl);
+
+ /**
+ * Checks if the data is correct and can be parsed.
+ * @param data ical string to check.
+ * @return true if the data is correct, false otherwise.
+ */
+ bool checkData(const TQString& data);
+
+ /**
+ * Parses the data and adds events to the calendar.
+ * @param data calendar data.
+ * @return true on success, false on fail.
+ */
+ bool parseData(const TQString& data);
+
+ /**
+ * Parses the data and adds tasks to the calendar.
+ * @param data calendar data.
+ * @return true on success, false on fail.
+ */
+ bool parseTasksData(const TQString& data);
+
+ /**
+ * Parses the data and adds journals to the calendar.
+ * @param data calendar data.
+ * @return true on success, false on fail.
+ */
+ bool parseJournalsData(const TQString& data);
+
+ /**
+ * Initiates calendar writing process.
+ * @param url URL to save event data to.
+ * @param tasksUrl URL to save task data to.
+ * @param journalsUrl URL to save journal data to.
+ * @return true if write was queued successfully, false if not
+ */
+ bool startWriting(const TQString& url, const TQString& tasksUrl, const TQString& journalsUrl);
+
+ /**
+ * Returns a list of incidences as a valid iCalendar string.
+ * @param inc list of incidences.
+ * @return a string in iCalendar format which describes the given incidences.
+ */
+ TQString getICalString(const Incidence::List& inc);
+
+ /**
+ * Changes read-only status of incidences from a given list.
+ * @param inc list of incidences.
+ * @param readOnly read-only status that all the incidences should have after the method finishes.
+ */
+ static void setIncidencesReadOnly(Incidence::List& inc, bool readOnly);
+
+ /**
+ * Ensures incidences' read-only states are the same as the calendar's read-only state.
+ */
+ void ensureReadOnlyFlagHonored();
+
+ /**
+ * If the loading queue is empty or the loader is not ready, does nothing.
+ * Otherwise, pops a head element and starts a loading process for it.
+ */
+ void loadingQueuePop();
+
+ /**
+ * Pushes the given loading task to the loading queue.
+ * Then calls loadingQueuePop.
+ */
+ void loadingQueuePush(const LoadingTask *task);
+
+ /**
+ * If the writing queue is empty or the writer is not ready, does nothing.
+ * Otherwise, pops a head element and starts a writing process for it.
+ */
+ void writingQueuePop();
+
+ /**
+ * Pushes the given writing task to the writing queue.
+ * Then calls writingQueuePop.
+ */
+ void writingQueuePush(const WritingTask *task);
+
+ virtual bool event ( TQEvent * e );
+
+private:
+
+ // constants: =============================================================
+
+ /// Termination waiting time in milliseconds. Used to terminate job threads.
+ static const unsigned long TERMINATION_WAITING_TIME;
+
+ /**
+ * Resource caches only events which are from the interval [-CACHE_DAYS, CACHE_DAYS].
+ */
+ static const int CACHE_DAYS;
+
+ static const int DEFAULT_RELOAD_INTERVAL;
+ static const int DEFAULT_SAVE_INTERVAL;
+ static const int DEFAULT_RELOAD_POLICY;
+ static const int DEFAULT_SAVE_POLICY;
+
+ bool readLockout;
+ bool mAllWritesComplete;
+
+ // members: ===============================================================
+
+ KABC::LockNull mLock;
+ CalDavPrefs* mPrefs;
+ CalDavReader* mLoader;
+ CalDavWriter* mWriter;
+ KPIM::ProgressItem *mProgress;
+
+ bool mLoadingQueueReady;
+ TQPtrQueue<LoadingTask> mLoadingQueue;
+
+ bool mWritingQueueReady;
+ TQPtrQueue<WritingTask> mWritingQueue;
+
+ TQTimer *mWriteRetryTimer;
+
+};
+
+
+
+} // namespace KCal
+
+#endif // KCAL_RESOURCECALDAV_H
+
diff --git a/tderesources/caldav/uninstall.desktop b/tderesources/caldav/uninstall.desktop
new file mode 100644
index 00000000..e1e3e173
--- /dev/null
+++ b/tderesources/caldav/uninstall.desktop
@@ -0,0 +1,2 @@
+[Desktop Entry]
+Hidden=true
diff --git a/tderesources/caldav/writer.cpp b/tderesources/caldav/writer.cpp
new file mode 100644
index 00000000..d9a6b2f0
--- /dev/null
+++ b/tderesources/caldav/writer.cpp
@@ -0,0 +1,162 @@
+/*=========================================================================
+| KCalDAV
+|--------------------------------------------------------------------------
+| (c) 2010 Timothy Pearson
+| (c) 2009 Kumaran Santhanam (initial KDE4 version)
+|
+| This project is released under the GNU General Public License.
+| Please see the file COPYING for more details.
+|--------------------------------------------------------------------------
+| Remote calendar writing class.
+ ========================================================================*/
+
+/*=========================================================================
+| INCLUDES
+ ========================================================================*/
+
+#include "writer.h"
+#include <kdebug.h>
+#include <string>
+
+/*=========================================================================
+| DEFINES
+ ========================================================================*/
+
+// Use caldav_modify_object() function.
+// If it's not set, a pair of caldav_delete_object/caldav_add_object
+// is used for modifying objects.
+// 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
+ ========================================================================*/
+
+using namespace KCal;
+
+/*=========================================================================
+| METHODS
+ ========================================================================*/
+
+void CalDavWriter::cleanJob() {
+ CalDavJob::cleanJob();
+}
+
+int CalDavWriter::runJob(runtime_info* RT) {
+ kdDebug() << "writer::run, url: " << url() << "\n";
+
+ int res = OK;
+
+ if ((OK == res) && (url() != "")) {
+ kdDebug() << "pushing added objects" << '\n';
+ res = pushObjects(mAdded, caldav_add_object, OK, RT);
+ if (OK == res) {
+#ifdef USE_CALDAV_MODIFY
+ kdDebug() << "pushing changed objects" << '\n';
+ res = pushObjects(mChanged, caldav_modify_object, OK, RT);
+ if (OK == res) {
+ kdDebug() << "pushing deleted objects" << '\n';
+ res = pushObjects(mDeleted, caldav_delete_object, OK, RT);
+ }
+#else // if USE_CALDAV_MODIFY
+ kdDebug() << "pushing changed objects (delete)" << '\n';
+ res = pushObjects(mChanged, caldav_delete_object, OK, RT);
+ if (OK == res) {
+ kdDebug() << "pushing changed objects (add)" << '\n';
+ res = pushObjects(mChanged, caldav_add_object, OK, RT);
+ if (OK == res) {
+ kdDebug() << "pushing deleted objects" << '\n';
+ res = pushObjects(mDeleted, caldav_delete_object, OK, RT);
+ }
+ }
+#endif // if USE_CALDAV_MODIFY
+ }
+ }
+
+ int tasksres = OK;
+
+ if ((OK == tasksres) && (tasksUrl() != "")) {
+ kdDebug() << "pushing added tasks objects" << '\n';
+ tasksres = pushTasksObjects(mTasksAdded, caldav_add_object, OK, RT);
+ if (OK == tasksres) {
+#ifdef USE_CALDAV_TASKS_MODIFY
+ kdDebug() << "pushing changed objects" << '\n';
+ tasksres = pushTasksObjects(mTasksChanged, caldav_tasks_modify_object, OK, RT);
+ if (OK == tasksres) {
+ kdDebug() << "pushing deleted objects" << '\n';
+ tasksres = pushTasksObjects(mTasksDeleted, caldav_tasks_delete_object, OK, RT);
+ }
+#else // if USE_CALDAV_TASKS_MODIFY
+ kdDebug() << "pushing changed objects (delete)" << '\n';
+ tasksres = pushTasksObjects(mTasksChanged, caldav_tasks_delete_object, OK, RT);
+ if (OK == tasksres) {
+ kdDebug() << "pushing changed objects (add)" << '\n';
+ tasksres = pushTasksObjects(mTasksChanged, caldav_add_object, OK, RT);
+ if (OK == tasksres) {
+ kdDebug() << "pushing deleted objects" << '\n';
+ tasksres = pushTasksObjects(mTasksDeleted, caldav_tasks_delete_object, OK, RT);
+ }
+ }
+#endif // if USE_CALDAV_TASKS_MODIFY
+ }
+ }
+
+ int journalsres = OK;
+
+ if ((OK == journalsres) && (tasksUrl() != "")) {
+ kdDebug() << "pushing added tasks objects" << '\n';
+ journalsres = pushJournalsObjects(mJournalsAdded, caldav_add_object, OK, RT);
+ if (OK == journalsres) {
+#ifdef USE_CALDAV_TASKS_MODIFY
+ kdDebug() << "pushing changed objects" << '\n';
+ journalsres = pushJournalsObjects(mJournalsChanged, caldav_tasks_modify_object, OK, RT);
+ if (OK == journalsres) {
+ kdDebug() << "pushing deleted objects" << '\n';
+ journalsres = pushJournalsObjects(mJournalsDeleted, caldav_tasks_delete_object, OK, RT);
+ }
+#else // if USE_CALDAV_TASKS_MODIFY
+ kdDebug() << "pushing changed objects (delete)" << '\n';
+ journalsres = pushJournalsObjects(mJournalsChanged, caldav_tasks_delete_object, OK, RT);
+ if (OK == journalsres) {
+ kdDebug() << "pushing changed objects (add)" << '\n';
+ journalsres = pushJournalsObjects(mJournalsChanged, caldav_add_object, OK, RT);
+ if (OK == journalsres) {
+ kdDebug() << "pushing deleted objects" << '\n';
+ journalsres = pushJournalsObjects(mJournalsDeleted, caldav_tasks_delete_object, OK, RT);
+ }
+ }
+#endif // if USE_CALDAV_TASKS_MODIFY
+ }
+ }
+
+ if ((OK != res) || (OK != tasksres)) {
+ clearObjects();
+ }
+
+ if (tasksres == OK)
+ return res;
+ else
+ return tasksres;
+}
+
+int CalDavWriter::runTasksJob(runtime_info* RT) {
+ // Stub function as there is no reason to split the writing jobs like the reading jobs
+ return OK;
+}
+
+void CalDavWriter::cleanTasksJob() {
+ // Stub function as there is no reason to split the writing jobs like the reading jobs
+}
+
+int CalDavWriter::runJournalsJob(runtime_info* RT) {
+ // Stub function as there is no reason to split the writing jobs like the reading jobs
+ return OK;
+}
+
+void CalDavWriter::cleanJournalsJob() {
+ // Stub function as there is no reason to split the writing jobs like the reading jobs
+}
+
+// EOF ========================================================================
diff --git a/tderesources/caldav/writer.h b/tderesources/caldav/writer.h
new file mode 100644
index 00000000..437eeed0
--- /dev/null
+++ b/tderesources/caldav/writer.h
@@ -0,0 +1,202 @@
+/*=========================================================================
+| KCalDAV
+|--------------------------------------------------------------------------
+| (c) 2010 Timothy Pearson
+| (c) 2009 Kumaran Santhanam (initial KDE4 version)
+|
+| This project is released under the GNU General Public License.
+| Please see the file COPYING for more details.
+|--------------------------------------------------------------------------
+| Remote calendar writing class.
+ ========================================================================*/
+
+/*=========================================================================
+| INCLUDES
+ ========================================================================*/
+
+#ifndef KCALDAV_WRITER_H
+#define KCALDAV_WRITER_H
+
+#include "job.h"
+
+#include <string>
+#include <tqstring.h>
+#include <tqdatetime.h>
+
+namespace KCal {
+
+/*=========================================================================
+| CLASS
+ ========================================================================*/
+
+/**
+ * Calendar writer.
+ */
+class CalDavWriter : public CalDavJob {
+
+public:
+
+ /**
+ * @param url URL to load.
+ */
+ CalDavWriter(const TQString& url = TQString()) :
+ CalDavJob(url)
+ {
+ clearObjects();
+ }
+
+ /**
+ * 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 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 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 added journals writer should send to server.
+ * @param s icalendar-formatted string consists of all added journals plus necessary calendar info.
+ * May be an empty string, which means there are no added journals to send.
+ */
+ void setAddedJournalsObjects(const TQString& s) {
+ mJournalsAdded = 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 changed journals writer should send to server.
+ * @param s icalendar-formatted string consists of all changed journals plus necessary calendar info.
+ * May be an empty string, which means there are no changed journals to send.
+ */
+ void setChangedJournalsObjects(const TQString& s) {
+ mJournalsChanged = 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;
+ }
+
+ /**
+ * Sets the information about deleted journals writer should send to server.
+ * @param s icalendar-formatted string consists of all deleted journals plus necessary calendar info.
+ * May be an empty string, which means there are no deleted journals to send.
+ */
+ void setDeletedJournalsObjects(const TQString& s) {
+ mJournalsDeleted = s;
+ }
+
+ /**
+ * Clear all the information previously set.
+ */
+ void clearObjects() {
+ setAddedObjects("");
+ setChangedObjects("");
+ setDeletedObjects("");
+ setAddedTasksObjects("");
+ setChangedTasksObjects("");
+ setDeletedTasksObjects("");
+ setAddedJournalsObjects("");
+ setChangedJournalsObjects("");
+ setDeletedJournalsObjects("");
+ }
+
+protected:
+
+ virtual int runJob(runtime_info* caldavRuntime);
+ virtual int runTasksJob(runtime_info* caldavRuntime);
+ virtual int runJournalsJob(runtime_info* caldavRuntime);
+
+ virtual void cleanJob();
+ virtual void cleanTasksJob();
+ virtual void cleanJournalsJob();
+
+ /// 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;
+ if (!data.isNull() && !data.isEmpty()) {
+ r = op(std::string(data.ascii()).c_str(), std::string(url().ascii()).c_str(), RT);
+ }
+ 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;
+ }
+
+ /// Just a wrapper above libcaldav journal writing functions.
+ template<typename Operation>
+ int pushJournalsObjects(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(journalsUrl().ascii()).c_str(), RT);
+// }
+ return r;
+ }
+
+private:
+
+ TQString mAdded;
+ TQString mChanged;
+ TQString mDeleted;
+
+ TQString mTasksAdded;
+ TQString mTasksChanged;
+ TQString mTasksDeleted;
+
+ TQString mJournalsAdded;
+ TQString mJournalsChanged;
+ TQString mJournalsDeleted;
+};
+
+} // namespace KCal
+
+#endif // KCALDAV_WRITER_H
+