Calendar Engine provides the data model, functionality and the needed APIs to build calendar applications following the IEETF standard iCalendar. The subsystem also provides the means to export and import this data so it can be synchronized to other ends.
The Calendar Engine has this scope:
NOT in the scope:
The concepts followed in this subsystem are defined in the iCalendar standard. These are:
Entries in the Calendar. They have date and time, and at least a title. All the other fields are optional. They can be recurrent.
Similar to the Events but they add the ToDo status. The can have recurrence.
Simple text notes. They don't take time in the calendar even if they have time. They can be also recurrent. Don't confuse these notes with the old concept of the polymorphic notes that Organiser was following before.
|Interface name||Interface type||Interface scope||Interface state||Required credentials||Description|
|libkcalcore||library||Platform API||Unstable||None||KDE's KCalCore. Provides classes to parse iCal and vCal, defines iCal data types. Recurrence handling, Time Zone information, etc.|
|libmkcal||library||Platform API||Unstable||GRP::calendar, TrackerWrite||Extension to KCalCore. Adds support to save, retrieve, load by date, etc of Calendar Data from a Sqlite DB. It also provides possibility to keep a copy in tracker to be indexed.|
|calendardb||file||Internal API||Unstable||GRP::calendar||Sqlite database used as permanent storage of the calendar data. It should NOT be used directly. Only through the libraries.|
|InvitationPlugin and ServicePlugin||virtual interface||Unstable||Platform API||none||Interfaces defined for plugins. These plugins are loaded in mKCal. They are used to handle invitations and service specifics behaviors.|
Table 1: Interfaces provided
|Domain/subsystem||Interface name||Interface scope||Description|
|System Control||libtimed||Platform||Used for: time and time zone change signals. Get current Time Zone. Setting alarms.|
|Content Framework||Tracker DBUS||Plaform||DBUS API used to save a copy of Calendar data to Tracker to be indexed. (This behavior is a runtime configurable parameter).|
|Data Management||libsqlite3||Platform||Sqlite DB used as permanent storage|
|Qt||QMF||Platform||Email API used as the default invitation handler. If no specific plugin designated if there is an invitation, the default action of sending an email with iCal attached is used.|
|Calendar Engine||libical||Platform||Libical is an internal library of this subsystem used to help in the iCalendar format parsing and writing.|
|Development Platform||libuuid||Platform||Library that generates UUIDs as specified in ISO/IEC 11578:1996|
|Startup Services||tzdata||Platform||Time Zone definition files|
|System Software||tzdata||Platform||Time Zone definitions.|
Table 2: Interfaces used
Apart of those there is of course Qt. As KCalCore is coming from the KDE world it is using some KDE specific data types. Originally they are defined in kdelibs but these ones are not included in the platform. To compile everything there are some of this classes inside /usr/include/kcalcoren/kpimutils Also as this version of KCalCore is compiled with this stubs, it is not installed in the original place but instead the package, includes, pc files are renamed to kcalcoren. So in the future KDE developers could install the KCalCore linked to the kdelibs if they want.
In the diagram the linking is done dynamic unless it says DBUS that it is run time.
Backend of the Calendar and Notes applications. Handles the storage and has the public API that can be used by other applications to modify calendar data. It comes from the open source KDE’s KCalCore. This library comes from a simplification and refactoring of the KCal library.
Library that extends kcalcore adding the persistence storage (SQLite) and also tracker integration.
It also exposes the InvitationPlugin/ServicePlugin API that is for third parties that handled invitations in a special way (some communication is needed with a server, etc) and not by attaching the iCalendar file in an email. These special behaviors can be implemented in plugins. Eg: ActiveSync. The plugins must provided the methods for changing the status of an invitation and to send new invitations. The selection of which plugin is loaded is done based on the Calendar (Notebook on API level). When creating a Notebook the name of the plugin has to be provided, if it is null, the fall back plugin will be used.
The fallback plugin to send the invitation as an attachment in an email using the default email account is provided with libmkcal package.
Library loaded as a plugin in Contactsd that checks when a contact has changed/added/deleted a birthday it adds it directly to the calendar database.
Timed is a deamon running on the system and is the one in charge of scheduling the alarms, notifying application of a time or timezone change. Libtimed is a library to interface with that daemon. Calendar Engine when setting an alarm, only sets the first occurrence of a recursive event (timed does not support complex recurrences) and when this one is trigger it arms the next one (this means that the component that shows the alarms has to be called even if the event was missed, no battery etc.)
Open source library handled in this subsystem that parses and generates iCalendar standard files.
To send invitations, if there is no InvitationPlugin associated to a calendar, the default action is to send an iCalendar (.ics) file attached to an email. QMF library is used to send it with the default email address.
Tracker is the global index in the platform, and Calenar Engine keeps updated a copy of the information it stores in its own database also in Tracker. But Calendar Engine does not listen to the changes done in Tracker, so to modify data always libmkcal API needs to be used.
Searching capabilities are also provided by Content Framework (in combination with Content Manager). This subsystem provides APIs to search in the database based on date, certain properties of the elements, but not textual search.
This subsystem does not provide any executables to the platform. There are only libraries which will run in other processes.
Note: Libmkcal creates a new thread for monitoring database changes from other processes.
There are no periodic activities done. There is no impact on boot time as they are not loaded. There are no checks of network availability as it should be done by the subsystems calling this one.
The normal usage of this subsystem is to load and unload calendar events into memory. The are two usual behaviors:
Important to note. When saving an incidence into a persistence storage it usually also requires to set an alarm (using libtimed0 and this implies a dbus call) and also to save it into tracker (if requested) that is also another dbus call.
mkcal has a plugin architecture to hide the service specifics to the applications using the library. This is based in a few keys that will be explained here.
It is important to note that the execution of the plugins is done in the same process and Event Loop that the rest of the application. So in case that the sending of the invitation is a long lasting task it should be decouple so the application is not frozen during that time. his key in the service paramater.
The only data storage of this subsystem is the sqlite database. It is stored in the users home directory. And to avoid other application users to worry about the location, there is a static method ExtendedCalendar::defaultStorage() that returns a pointer to the default storage (includes the connection to the DB).
The database is defined in mkcal package, sqlitestorage.h file.
Currently the defaultStorage() is a SqliteStore with Tracker support enabled. This means that every thing is saved into the Sqlite Database and also a copy is saved into the proper ontologies in Tracker. This copies are kept so content can be found through global search. But it is never accessed from this library. The reading is always done from Sqlite for performance reasons.
There are no differences in the usage from device or from SDK. In order to run it in the SDK of course all dependencies need to be there, and DBUS and other daemons running (tracker, timed).
There are two important base classes. Abstract class Calendar from KCalCore contain incidences (events, todos, journals) and methods for adding/deleting/querying them. It is implemented by ExtendedCalendar in mKCal.
Abstract class ExtendedStorage defines the interface to load and save calendar incidences into permanent storage. It is implemented by a few diffent storages, like SqliteStorage which is the default MeeGo storage. But more can be added implementing this interface.
Calendars can exist without storages but storages must always be linked to a calendar. The normal way to create calendar and default storage is:
ExtendedCalendar::Ptr cal = ExtendedCalendar::Ptr ( new ExtendedCalendar( QLatin1String( "UTC" ) ) ); ExtendedStorage::Ptr storage = calendar.defaultStorage( cal ); storage->open();
Initially calendar is empty unless you create new incidences into it, or use the storage to load incidences into the calendar. Original KCal provided only means for loading all incidences at once, but that may be too costly for an embedded device (loading could take tens of seconds for very large calendars). ExtendedStorage added methods for smart loading only those incidences that must be shown to the user at that time.
When you add incidences to the calendar, or modify/delete existing ones, you must call storage->save() to write incidences into persistent storage. Calendar methods always operate in memory only, you can make a series of changes in a calendar and then 'commit' them all at once by calling storage->save().