Akonadi: first functional version

TODOs resolved, adapted to backend API changes.
This commit is contained in:
Dinesh 2010-08-14 17:00:46 +05:30 committed by Patrick Ohly
parent 2ec870e3e5
commit c9458d29bd
6 changed files with 140 additions and 71 deletions

View File

@ -22,14 +22,17 @@
#include <boost/algorithm/string.hpp>
#include <syncevo/declarations.h>
SE_BEGIN_CXX
static SyncSource *createSource(const SyncSourceParams &params)
{
SourceType sourceType = SyncSource::getSourceType(params.m_nodes);
bool isMe;
bool isMe;
isMe = sourceType.m_backend == "KDE Address Book";
if (isMe || sourceType.m_backend == "addressbook") {
if (sourceType.m_format == "" || sourceType.m_format == "text/vcard"
@ -116,7 +119,7 @@ static RegisterSyncSource registerMe("KDE Contact/Calendar/Task List/Memos",
" iCalendar 2.0 (default) = text/calendar\n"
" vCalendar 1.0 = text/x-calendar\n"
"KDE Memos = memo = memos = kde-memos\n"
" plain text in UTF-8 (default) = text/plain\n",
" plain text in UTF-8 (default) = text/plain\n",
Values() +
(Aliases("KDE Address Book") + "KDE Contacts" + "kde-contacts") +
(Aliases("KDE Calendar") + "kde-calendar") +

View File

@ -16,7 +16,8 @@ Configuring without Evolution and with Akonadi:
--disable-shared --enable-static \
--enable-libcurl \
--enable-unit-tests --enable-integration-tests \
--disable-ecal --disable-ebook --disable-libsoup
--disable-ecal --disable-ebook --disable-libsoup \
--enable-akonadi --enable-kwallet
This creates src/syncevolution and src/client-test which can be run under
a debugger directly.

View File

@ -26,19 +26,28 @@
#include <Akonadi/ItemFetchJob>
#include <Akonadi/ItemFetchScope>
#include <Akonadi/ItemModifyJob>
#include <Akonadi/CollectionFetchJob>
#include <Akonadi/CollectionFetchScope>
#include <Akonadi/CollectionStatistics>
#include <Akonadi/CollectionStatisticsJob>
#include <Akonadi/Control>
#include <kurl.h>
#include <QtCore/QCoreApplication>
#include <QtCore/QStringList>
#include <QtCore/QDebug>
SE_BEGIN_CXX
using namespace Akonadi;
AkonadiSyncSource::AkonadiSyncSource(const char *submime,
const SyncSourceParams &params) :
TrackingSyncSource(params),
m_subMime(submime)
const SyncSourceParams &params)
: TrackingSyncSource(params)
, m_subMime(submime)
{
}
@ -46,14 +55,54 @@ AkonadiSyncSource::~AkonadiSyncSource()
{
}
bool AkonadiSyncSource::isEmpty(){return false;}
bool AkonadiSyncSource::isEmpty()
{
//To Check if the respective collection is Empty, without actually loading the collections
CollectionStatisticsJob *statisticsJob = new CollectionStatisticsJob(m_collection);
if (!statisticsJob->exec()) {
throwError("Error fetching the collection stats");
}
return statisticsJob->statistics().count() == 0;
}
void AkonadiSyncSource::start()
{
int argc = 1;
static const char *prog = "syncevolution";
static char *argv[] = { (char *)&prog, NULL };
if (!qApp) {
new QCoreApplication(argc, argv);
KAboutData aboutData(// The program name used internally.
"syncevolution",
// The message catalog name
// If null, program name is used instead.
0,
// A displayable program name string.
ki18n("Syncevolution"),
// The program version string.
"1.0",
// Short description of what the app does.
ki18n("Lets Akonadi synchronize with a SyncML Peer"),
// The license this code is released under
KAboutData::License_GPL,
// Copyright Statement
ki18n("(c) 2010"),
// Optional text shown in the About box.
// Can contain any information desired.
ki18n(""),
// The program homepage string.
"http://www.syncevolution.org/",
// The bug report email address
"syncevolution@syncevolution.org");
KCmdLineArgs::init(argc, argv, &aboutData);
if (!kapp) {
new KApplication;
}
// Start The Akonadi Server if not already Running.
if (!Akonadi::ServerManager::isRunning()) {
qDebug() << "Akonadi Server isn't running, and hence starting it.";
if (!Akonadi::Control::start()) {
qDebug() << "Couldn't Start Akonadi Server: hence the akonadi backend of syncevolution wont work ..";
}
}
}
@ -62,33 +111,32 @@ SyncSource::Databases AkonadiSyncSource::getDatabases()
start();
Databases res;
// TODO: insert databases which match the "type"
// of the source, including a user-visible description
// and a database IDs. Exactly one of the databases
// should be marked as the default one used by the
// source.
QStringList mimeTypes;
mimeTypes << m_subMime.c_str();
// Insert databases which match the "type" of the source, including a user-visible
// description and a database IDs. Exactly one of the databases should be marked
// as the default one used by the source.
// res.push_back("Contacts", "some-KDE-specific-ID", isDefault);
CollectionFetchJob *fetchJob = new CollectionFetchJob(Collection::root(),
CollectionFetchJob::Recursive);
// fetchJob->setMimeTypeFilter(m_subMime.c_str());
fetchJob->fetchScope().setContentMimeTypes(mimeTypes);
if (!fetchJob->exec()) {
throwError("cannot list collections");
}
// the first collection of the right type is the default
// TODO: is there a better way to choose the default?
// Currently, the first collection of the right type is the default
// This decision should go to the GUI: which deals with sync profiles.
bool isFirst = true;
Collection::List collections = fetchJob->collections();
foreach(const Collection &collection, collections) {
// TODO: filter out collections which contain no items
// of the type we sync (m_subMime)
if (true) {
res.push_back(Database(collection.name().toUtf8().constData(),
collection.url().url().toUtf8().constData(),
isFirst));
isFirst = false;
}
foreach (const Collection &collection, collections) {
res.push_back(Database(collection.name().toUtf8().constData(),
collection.url().url().toUtf8().constData(),
isFirst));
isFirst = false;
}
return res;
}
@ -101,9 +149,9 @@ void AkonadiSyncSource::open()
// otherwise the collection URL or a name
string id = getDatabaseID();
// TODO: support selection by name and empty ID for default
// TODO: check for invalid URL?!
// support selection by name and empty ID for default by using
// evolutionsource = akonadi:?collection=<number>
// invalid url=>invalid collection Error at runtime.
m_collection = Collection::fromUrl(KUrl(id.c_str()));
}
@ -111,15 +159,17 @@ void AkonadiSyncSource::listAllItems(SyncSourceRevisions::RevisionMap_t &revisio
{
// copy all local IDs and the corresponding revision
ItemFetchJob *fetchJob = new ItemFetchJob(m_collection);
if (!fetchJob->exec()) {
throwError("listing items");
}
BOOST_FOREACH(const Item &item, fetchJob->items()) {
// TODO: filter out items which don't have the right type
// (for example, VTODO when syncing events)
// if (... == m_subMime)
revisions[QByteArray::number(item.id()).constData()] =
QByteArray::number(item.revision()).constData();
BOOST_FOREACH (const Item &item, fetchJob->items()) {
// Filter out items which don't have the right type (for example, VTODO when
// syncing events)
if (item.mimeType() == m_subMime.c_str()) {
revisions[QByteArray::number(item.id()).constData()] =
QByteArray::number(item.revision()).constData();
}
}
}
@ -128,8 +178,7 @@ void AkonadiSyncSource::close()
// TODO: close collection!?
}
TrackingSyncSource::InsertItemResult
AkonadiSyncSource::insertItem(const std::string &luid, const std::string &data, bool raw)
TrackingSyncSource::InsertItemResult AkonadiSyncSource::insertItem(const std::string &luid, const std::string &data, bool raw)
{
Item item;
@ -139,6 +188,7 @@ AkonadiSyncSource::insertItem(const std::string &luid, const std::string &data,
ItemCreateJob *createJob = new ItemCreateJob(item, m_collection);
if (!createJob->exec()) {
throwError(string("storing new item ") + luid);
return InsertItemResult("", "", false);
}
item = createJob->item();
} else {
@ -146,18 +196,23 @@ AkonadiSyncSource::insertItem(const std::string &luid, const std::string &data,
ItemFetchJob *fetchJob = new ItemFetchJob(Item(syncItemId));
if (!fetchJob->exec()) {
throwError(string("checking item ") + luid);
}
}
item = fetchJob->items().first();
item.setPayloadFromData(QByteArray(data.c_str()));
ItemModifyJob *modifyJob = new ItemModifyJob(item);
// TODO: SyncEvolution must pass the known revision that
// we are updating.
// TODO: check that the item has not been updated in the meantime
if (!modifyJob->exec()) {
throwError(string("updating item ") + luid);
return InsertItemResult("", "", false);
}
item = modifyJob->item();
}
// TODO: Read-only datastores may not have actually added something here!
// Read-only datastores may not have actually added something here!
// The Jobs themselves throw errors, and hence the return statements
// above will take care of this
return InsertItemResult(QByteArray::number(item.id()).constData(),
QByteArray::number(item.revision()).constData(),
false);

View File

@ -28,6 +28,7 @@
#include <Akonadi/Item>
#include <QtCore/QDateTime>
#include <QtCore/QStringList>
#include <syncevo/TrackingSyncSource.h>
@ -42,7 +43,6 @@ class TimeTrackingObserver;
* and "engine" formats).
*
* Change tracking is done via the item uid/revision attributes.
*
*
* Databases (collections in Akonadi terminology) are selected via
* their int64 ID number.
@ -69,21 +69,26 @@ public:
virtual void close();
virtual bool isEmpty();
private:
void start();
Akonadi::Collection m_collection;
const std::string m_subMime;
void start();
};
class AkonadiContactSource : public AkonadiSyncSource
{
public:
AkonadiContactSource(const SyncSourceParams &params) :
AkonadiSyncSource("text/vcard", params)
{}
public:
AkonadiContactSource(const SyncSourceParams &params)
: AkonadiSyncSource("text/directory", params)
{
}
virtual const char *getMimeType() const { return "text/vcard"; }
virtual const char *getMimeVersion() const { return "3.0"; }
virtual std::string getMimeType() const {
return "text/vcard";
}
virtual std::string getMimeVersion() const {
return "3.0";
}
void getSynthesisInfo(SynthesisInfo &info,
XMLConfigFragments &fragments)
@ -106,41 +111,46 @@ class AkonadiContactSource : public AkonadiSyncSource
class AkonadiCalendarSource : public AkonadiSyncSource
{
public:
AkonadiCalendarSource(const SyncSourceParams &params) :
AkonadiSyncSource("application/x-vnd.akonadi.calendar.event", params)
{}
public:
AkonadiCalendarSource(const SyncSourceParams &params)
: AkonadiSyncSource("application/x-vnd.akonadi.calendar.event", params)
{
}
// TODO: the items are expected to be complete VCALENDAR with
// all necessary VTIMEZONEs and one VEVENT (here) resp. VTODO
// (AkonadiTodoSource). Not sure what we get from Akonadi.
virtual const char *getMimeType() const { return "text/calendar"; }
virtual const char *getMimeVersion() const { return "2.0"; }
virtual std::string getMimeType() const { return "text/calendar"; }
virtual std::string getMimeVersion() const { return "2.0"; }
};
class AkonadiTaskSource : public AkonadiSyncSource
{
public:
AkonadiTaskSource(const SyncSourceParams &params) :
AkonadiSyncSource("text/x-vnd.akonadi.calendar.todo", params)
{}
public:
AkonadiTaskSource(const SyncSourceParams &params)
: AkonadiSyncSource("text/calendar", params)
{
}
virtual const char *getMimeType() const { return "text/calendar"; }
virtual const char *getMimeVersion() const { return "2.0"; }
virtual std::string getMimeType() const { return "text/calendar"; }
virtual std::string getMimeVersion() const { return "2.0"; }
};
class AkonadiMemoSource : public AkonadiSyncSource
{
public:
AkonadiMemoSource(const SyncSourceParams &params) :
AkonadiSyncSource("text/x-vnd.akonadi.calendar.journal", params)
{}
public:
AkonadiMemoSource(const SyncSourceParams &params)
: AkonadiSyncSource("text/x-vnd.akonadi.calendar.journal", params)
{
}
// TODO: the AkonadiMemoSource is expected to import/export
// plain text with the summary in the first line; currently
// the AkonadiSyncSource will use VJOURNAL
virtual const char *getMimeType() const { return "text/plain"; }
virtual const char *getMimeVersion() const { return "1.0"; }
// Also Currently there is no application which uses akonadi backend
// to display notes: probably work for knote??
virtual std::string getMimeType() const { return "text/plain"; }
virtual std::string getMimeVersion() const { return "1.0"; }
};
SE_END_CXX

View File

@ -6,10 +6,10 @@ dnl Invoke autogen.sh to produce a configure script.
# kdepimlibs5-dev >= 4.3 provides the necessary files.
AKONADIFOUND=yes
if ! test "$KDEPIM_CFLAGS"; then
KDEPIM_CFLAGS="-I/usr/include/KDE -I/usr/include/qt4"
KDEPIM_CFLAGS="-I`kde4-config --path include` -I`kde4-config --path include`/KDE -I`qmake -query QT_INSTALL_HEADERS`"
fi
if ! test "$KDEPIM_LIBS"; then
KDEPIM_LIBS="-lakonadi-kde"
KDEPIM_LIBS="-L`kde4-config --prefix`/lib`kde4-config --libsuffix` -lakonadi-kde"
fi
AC_LANG_PUSH(C++)
old_CPPFLAGS="$CPPFLAGS"

View File

@ -35,8 +35,8 @@ public:
Settings::self()->contactsRemoteDatabaseName().toLatin1())
{
setName(Settings::self()->contactsCollectionName().toLatin1());
setType("text/x-vcard");
setSupportedTypes("text/x-vcard:,text/vcard");
setType("text/vcard");
setSupportedTypes("text/x-vcard,text/vcard");
}
};