Hi,

Could you please review the attached patch that implements local
calendar creation in KCal-EDS?

The apps need to call
EStorage::localStorage(KCalCore::IncidenceBase::IncidenceType type,
const QString &id, bool create)
instead of defaultStorage(KCalCore::IncidenceBase::IncidenceType type)
to get a local calendar storage.

If the "create" parameter is set to false and the local storage
identified by "id" does not exist, the method will fail and return a
NULL pointer.
The ECal uri is generated from the id provided by the caller as
follows: "local:<id>".

I have written new unit tests to check the functionality and it seems
to work for me.

TIA,
-- 
Dr. Christophe Dumez
Linux Software Engineer
Intel Finland Oy - Open Source Technology Center
From 008928417df9c42cf709eaea2e9bbdcba2945416 Mon Sep 17 00:00:00 2001
From: Christophe Dumez <[email protected]>
Date: Thu, 9 Jun 2011 15:00:05 +0300
Subject: [PATCH] eKCal::EStorage Implement local calendar creation

Add localStorage() method to eKCal::EStorage that returns a local
calendar storage. The storage is only created if the "create"
boolean parameter is set to true.

Unit tests have been written to check the functionality.
---
 src/eds-storage.cpp          |   72 +++++++++++++++++++++++++++++
 src/eds-storage.h            |   15 ++++++-
 src/ekcal/ekcal-storage.h    |   10 ++++
 test/Makefile.am             |   11 +++-
 test/ut_testlocalstorage.cpp |  104 ++++++++++++++++++++++++++++++++++++++++++
 test/ut_testlocalstorage.h   |   39 ++++++++++++++++
 6 files changed, 247 insertions(+), 4 deletions(-)
 create mode 100644 test/ut_testlocalstorage.cpp
 create mode 100644 test/ut_testlocalstorage.h

diff --git a/src/eds-storage.cpp b/src/eds-storage.cpp
index 37bfe8a..8fa4d67 100644
--- a/src/eds-storage.cpp
+++ b/src/eds-storage.cpp
@@ -24,6 +24,8 @@
 
 #include <set>
 
+const QString EDS_LOCAL_STORAGE_PREFIX = "local:";
+
 namespace eKCal {
 
     EStorage::Ptr EStorage::defaultStorage(KCalCore::IncidenceBase::IncidenceType type)
@@ -36,6 +38,17 @@ namespace eKCal {
         return res;
     }
 
+    EStorage::Ptr EStorage::localStorage(KCalCore::IncidenceBase::IncidenceType type,
+                                         const QString &id, bool create)
+    {
+      eKCalImpl::EDSStorage::Ptr res(new eKCalImpl::EDSStorage);
+      if (!res->open(type, id, create)) {
+          EKCAL_DEBUG() << "opening local storage failed";
+          res.clear();
+      }
+      return res;
+    }
+
 } // namespace eKCal
 
 namespace eKCalImpl {
@@ -138,6 +151,65 @@ namespace eKCalImpl {
         return true;
     }
 
+    bool EDSStorage::open(KCalCore::IncidenceBase::IncidenceType type,
+                          const QString &id, bool create)
+    {
+      m_type = type;
+      g_type_init();
+
+      m_calendar = KCalCore::MemoryCalendar::Ptr(new KCalCore::MemoryCalendar(KSystemTimeZones::local()));
+      if (!m_calendar) {
+        return false;
+      }
+
+      switch (type) {
+      case KCalCore::IncidenceBase::TypeEvent:
+        m_database = ECalCXX::steal(e_cal_new_from_uri((EDS_LOCAL_STORAGE_PREFIX+id).toUtf8().constData(),
+                                                       E_CAL_SOURCE_TYPE_EVENT));
+        m_calendarDeleteAll = &KCalCore::MemoryCalendar::deleteAllEvents;
+        break;
+      case KCalCore::IncidenceBase::TypeTodo:
+        m_database = ECalCXX::steal(e_cal_new_from_uri((EDS_LOCAL_STORAGE_PREFIX+id).toUtf8().constData(),
+                                                       E_CAL_SOURCE_TYPE_TODO));
+        m_calendarDeleteAll = &KCalCore::MemoryCalendar::deleteAllTodos;
+        break;
+      case KCalCore::IncidenceBase::TypeJournal:
+        m_database = ECalCXX::steal(e_cal_new_from_uri((EDS_LOCAL_STORAGE_PREFIX+id).toUtf8().constData(),
+                                                       E_CAL_SOURCE_TYPE_JOURNAL));
+        m_calendarDeleteAll = &KCalCore::MemoryCalendar::deleteAllJournals;
+        break;
+      default:
+        // should be NULL, but just in case...
+        m_database.reset();
+      }
+
+      if (!m_database) {
+        EKCAL_CRITICAL() << "no system storage for type" << type;
+        return false;
+      }
+
+      // TODO (?): define a non-blocking way of creating EStorage,
+      // use e_cal_open_async() here. Probably not that relevant
+      // for local calendars.
+      GErrorCXX gerror;
+      EKCAL_DEBUG() << "Calling e_cal_open() on database" << EDS_LOCAL_STORAGE_PREFIX+id
+                       << "with create boolean at" << create;
+      if (!e_cal_open(m_database.get(),
+                      !create,
+                      gerror)) {
+          EKCAL_CRITICAL() << "e_cal_open failed" << gerror;
+          return false;
+      }
+
+      if (!e_cal_get_static_capability(m_database.get(),
+                                       CAL_STATIC_CAPABILITY_REMOVE_ONLY_THIS)) {
+          EKCAL_CRITICAL() << "local storage does not support CAL_STATIC_CAPABILITY_REMOVE_ONLY_THIS, needed for KCal-EDS";
+          return false;
+      }
+
+      return true;
+    }
+
     void EDSStorage::registerObserver(StorageObserver *observer)
     {
         m_observers.push_back(observer);
diff --git a/src/eds-storage.h b/src/eds-storage.h
index 32b2315..984b175 100644
--- a/src/eds-storage.h
+++ b/src/eds-storage.h
@@ -56,7 +56,8 @@ namespace eKCalImpl {
         EDSStorage();
 
         /**
-         * Sets up EDSStorage instance for use.
+         * Sets up EDSStorage instance for use corresponding to the default system
+         * storage for this \a type of items.
          *
          * Must succeed before instance is ready for use via the
          * EStorage API. If it fails, the EDSStorage is unusable and
@@ -64,6 +65,18 @@ namespace eKCalImpl {
          */
         bool open(KCalCore::IncidenceBase::IncidenceType type);
 
+        /**
+         * Sets up EDSStorage instance for use corresponding to a local storage identified
+         * by \a id and for this \a type of items. \a create indicate if the local storage
+         * should be created when missing.
+         *
+         * Must succeed before instance is ready for use via the
+         * EStorage API. If it fails, the EDSStorage is unusable and
+         * should be destroyed.
+         */
+        bool open(KCalCore::IncidenceBase::IncidenceType type, const QString &id,
+                  bool create);
+
         virtual KCalCore::Calendar::Ptr calendar() { return m_calendar; }
 
         virtual void registerObserver(StorageObserver *observer);
diff --git a/src/ekcal/ekcal-storage.h b/src/ekcal/ekcal-storage.h
index 7525108..3cbb834 100644
--- a/src/ekcal/ekcal-storage.h
+++ b/src/ekcal/ekcal-storage.h
@@ -145,6 +145,16 @@ namespace eKCal {
         static Ptr defaultStorage(KCalCore::IncidenceBase::IncidenceType type);
 
         /**
+         * creates a new implementation of EStorage accessing the storage identified
+         * by \a id and for the given \a type of items. The storage must already exist
+         * or \a create should be set to true.
+         *
+         * @return NULL in case of error
+         */
+        static Ptr localStorage(KCalCore::IncidenceBase::IncidenceType type,
+                                const QString &id, bool create);
+
+        /**
          * Every storage is associated with a calendar.
          *
          * The default time zone of that calendar is the one defined
diff --git a/test/Makefile.am b/test/Makefile.am
index 6afab74..df69085 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,8 +1,8 @@
 # use Qt
 include $(top_srcdir)/m4-repo/autotroll.mk
 
-check_PROGRAMS = showall ut_testchanges
-TESTS = ut_testchanges
+check_PROGRAMS = showall ut_testchanges ut_testlocalstorage
+TESTS = ut_testchanges ut_testlocalstorage
 
 # Allow Qt to set some compile flags, but not the ones normally set via configure.
 AM_CXXFLAGS = $(filter-out -O2 -g -W -Wall, $(QT_CXXFLAGS))
@@ -18,4 +18,9 @@ ut_testchanges_CXXFLAGS = $(AM_CXXFLAGS) $(ECAL_CFLAGS)
 ut_testchanges_LDADD = $(QT_LIBS) $(ECAL_LIBS) ../src/libekcal.la
 ut_testchanges_DEP = ../src/libekcal.la
 
-BUILT_SOURCES = calendar-observer.moc.cpp signal-app.moc.cpp ut_testchanges.moc.cpp
+ut_testlocalstorage_SOURCES = ut_testlocalstorage.cpp ut_testlocalstorage.moc.cpp
+ut_testlocalstorage_CXXFLAGS = $(AM_CXXFLAGS) $(ECAL_CFLAGS)
+ut_testlocalstorage_LDADD = $(QT_LIBS) $(ECAL_LIBS) ../src/libekcal.la
+ut_testlocalstorage_DEP = ../src/libekcal.la
+
+BUILT_SOURCES = calendar-observer.moc.cpp signal-app.moc.cpp ut_testchanges.moc.cpp ut_testlocalstorage.moc.cpp
diff --git a/test/ut_testlocalstorage.cpp b/test/ut_testlocalstorage.cpp
new file mode 100644
index 0000000..841905c
--- /dev/null
+++ b/test/ut_testlocalstorage.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2011 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+
+#include <QString>
+#include <QTest>
+#include <QTime>
+#include <QDebug>
+#include "ut_testlocalstorage.h"
+
+const QString TEST_STORAGE_ID = "test_storage";
+
+bool TestLocalStorage::addSimpleEvent(const KDateTime &t, const QString &summary)
+{
+  KCalCore::Event::Ptr event;
+  KDateTime utcstart(t);
+  KDateTime utcend = utcstart;
+  utcend.addSecs(60 * 60);
+  // add a minimal event
+  qDebug() << "=== single UTC event ===";
+  event = KCalCore::Event::Ptr(new KCalCore::Event);
+  event->setSummary(summary);
+  event->setDtStart(utcstart);
+  event->setDtEnd(utcend);
+  return m_calendar->addEvent(event);
+}
+
+void TestLocalStorage::initTestCase()
+{
+  m_storage = eKCal::EStorage::localStorage(KCalCore::IncidenceBase::TypeEvent,
+                                            TEST_STORAGE_ID, true);
+  QVERIFY(m_storage);
+  m_calendar = m_storage->calendar();
+  QVERIFY(m_calendar);
+}
+
+void TestLocalStorage::basicLocalStorageTest()
+{
+  // Add a simple event
+  KDateTime t(QDate(2011, 01, 01), QTime(14, 30, 0), KDateTime::Spec::UTC());
+  const QString summary = "Test UTC event";
+  bool ok = addSimpleEvent(t, summary);
+  QVERIFY(ok);
+  QVERIFY(m_calendar->save());
+
+  // Get the event back
+  KCalCore::Event::List events = m_calendar->events(t);
+  Q_ASSERT(!events.isEmpty());
+  Q_ASSERT(events.first().summary() == summary);
+}
+
+void TestLocalStorage::persistenceTest()
+{
+  // Add a simple event
+  KDateTime t(QDate(2011, 01, 01), QTime(14, 30, 0), KDateTime::Spec::UTC());
+  const QString summary = "Test UTC event 2";
+  bool ok = addSimpleEvent(t, summary);
+  QVERIFY(ok);
+  QVERIFY(m_calendar->save());
+
+  // Close the storage
+  m_storage.clear();
+  m_calendar.clear();
+  // Reopen
+  m_storage = eKCal::EStorage::localStorage(KCalCore::IncidenceBase::TypeEvent,
+                                            TEST_STORAGE_ID, false);
+  QVERIFY(m_storage);
+  m_calendar = m_storage->calendar();
+  QVERIFY(m_calendar);
+
+  // Get the event back
+  KCalCore::Event::List events = m_calendar->events(t);
+  Q_ASSERT(!events.isEmpty());
+  Q_ASSERT(events.first().summary() == "Test UTC event");
+}
+
+void TestLocalStorage::cleanup()
+{
+  qDebug() << "=== calendar cleaning ===";
+  if (m_calendar) {
+    m_calendar->deleteAllEvents();
+    KCalCore::Event::List events = m_calendar->events();
+    QVERIFY(events.isEmpty());
+    m_calendar->deleteAllJournals();
+    m_calendar->deleteAllTodos();
+  }
+}
+
+QTEST_MAIN(TestLocalStorage);
diff --git a/test/ut_testlocalstorage.h b/test/ut_testlocalstorage.h
new file mode 100644
index 0000000..6f9b893
--- /dev/null
+++ b/test/ut_testlocalstorage.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2011 Intel Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301  USA
+ */
+
+#include <QObject>
+#include <libecal/e-cal.h>
+#include <ekcal/ekcal-storage.h>
+
+class TestLocalStorage : public QObject {
+  Q_OBJECT
+
+ private slots:
+  void initTestCase();
+  void basicLocalStorageTest();
+  void persistenceTest();
+  void cleanup();
+
+private:
+  bool addSimpleEvent(const KDateTime &time, const QString &summary);
+
+private:
+  eKCal::EStorage::Ptr m_storage;
+  KCalCore::Calendar::Ptr m_calendar;
+};
-- 
1.7.4.4

_______________________________________________
MeeGo-dev mailing list
[email protected]
http://lists.meego.com/listinfo/meego-dev
http://wiki.meego.com/Mailing_list_guidelines

Reply via email to