From 9f6e0fbfd8cf23104eba5a78f89a69fab1a417f5 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Mon, 9 Nov 2015 16:04:46 +0100 Subject: Added a folder type --- examples/dummyresource/domainadaptor.cpp | 6 ++++++ examples/dummyresource/domainadaptor.h | 12 ++++++++++-- examples/dummyresource/facade.cpp | 22 +++++----------------- examples/dummyresource/facade.h | 6 +----- examples/dummyresource/resourcefactory.cpp | 2 ++ 5 files changed, 24 insertions(+), 24 deletions(-) (limited to 'examples') diff --git a/examples/dummyresource/domainadaptor.cpp b/examples/dummyresource/domainadaptor.cpp index d08a783..74b170d 100644 --- a/examples/dummyresource/domainadaptor.cpp +++ b/examples/dummyresource/domainadaptor.cpp @@ -51,3 +51,9 @@ DummyMailAdaptorFactory::DummyMailAdaptorFactory() } +DummyFolderAdaptorFactory::DummyFolderAdaptorFactory() + : DomainTypeAdaptorFactory() +{ + +} + diff --git a/examples/dummyresource/domainadaptor.h b/examples/dummyresource/domainadaptor.h index add3e8e..e5856f8 100644 --- a/examples/dummyresource/domainadaptor.h +++ b/examples/dummyresource/domainadaptor.h @@ -21,6 +21,8 @@ #include "common/domainadaptor.h" #include "event_generated.h" #include "mail_generated.h" +#include "folder_generated.h" +#include "dummy_generated.h" #include "dummycalendar_generated.h" #include "entity_generated.h" @@ -31,10 +33,16 @@ public: virtual ~DummyEventAdaptorFactory() {}; }; -//TODO replace the resource specific event class by a mail class or a dummy class if no resource type is required. -class DummyMailAdaptorFactory : public DomainTypeAdaptorFactory +class DummyMailAdaptorFactory : public DomainTypeAdaptorFactory { public: DummyMailAdaptorFactory(); virtual ~DummyMailAdaptorFactory() {}; }; + +class DummyFolderAdaptorFactory : public DomainTypeAdaptorFactory +{ +public: + DummyFolderAdaptorFactory(); + virtual ~DummyFolderAdaptorFactory() {}; +}; diff --git a/examples/dummyresource/facade.cpp b/examples/dummyresource/facade.cpp index 5a9d722..f337bdc 100644 --- a/examples/dummyresource/facade.cpp +++ b/examples/dummyresource/facade.cpp @@ -30,6 +30,7 @@ DummyResourceFacade::~DummyResourceFacade() { } + DummyResourceMailFacade::DummyResourceMailFacade(const QByteArray &instanceIdentifier) : Akonadi2::GenericFacade(instanceIdentifier, QSharedPointer::create()) { @@ -39,25 +40,12 @@ DummyResourceMailFacade::~DummyResourceMailFacade() { } -static void addFolder(const QSharedPointer > &resultProvider, QByteArray uid, QString name, QString icon) + +DummyResourceFolderFacade::DummyResourceFolderFacade(const QByteArray &instanceIdentifier) + : Akonadi2::GenericFacade(instanceIdentifier, QSharedPointer::create()) { - auto folder = Akonadi2::ApplicationDomain::Folder::Ptr::create(); - folder->setProperty("name", name); - folder->setProperty("uid", uid); - resultProvider->add(folder); } -KAsync::Job load(const Akonadi2::Query &query, const QSharedPointer > &resultProvider) +DummyResourceFolderFacade::~DummyResourceFolderFacade() { - //Dummy implementation for a fixed set of folders - addFolder(resultProvider, "inbox", "INBOX", "mail-folder-inbox"); - addFolder(resultProvider, "sent", "Sent", "mail-folder-sent"); - addFolder(resultProvider, "trash", "Trash", "user-trash"); - addFolder(resultProvider, "drafts", "Drafts", "document-edit"); - addFolder(resultProvider, "1", "dragons", "folder"); - addFolder(resultProvider, "1", "super mega long tailed dragons", "folder"); - resultProvider->initialResultSetComplete(); - resultProvider->complete(); - return KAsync::null(); } - diff --git a/examples/dummyresource/facade.h b/examples/dummyresource/facade.h index 948116b..b00e1d7 100644 --- a/examples/dummyresource/facade.h +++ b/examples/dummyresource/facade.h @@ -36,13 +36,9 @@ public: virtual ~DummyResourceMailFacade(); }; -class DummyResourceFolderFacade : public Akonadi2::StoreFacade +class DummyResourceFolderFacade : public Akonadi2::GenericFacade { public: DummyResourceFolderFacade(const QByteArray &instanceIdentifier); virtual ~DummyResourceFolderFacade(); - virtual KAsync::Job create(const Akonadi2::ApplicationDomain::Folder &domainObject) { return KAsync::null(); }; - virtual KAsync::Job modify(const Akonadi2::ApplicationDomain::Folder &domainObject) { return KAsync::null(); }; - virtual KAsync::Job remove(const Akonadi2::ApplicationDomain::Folder &domainObject) { return KAsync::null(); }; - virtual KAsync::Job load(const Akonadi2::Query &query, const QSharedPointer > &resultProvider); }; diff --git a/examples/dummyresource/resourcefactory.cpp b/examples/dummyresource/resourcefactory.cpp index 397ca5f..edb3b42 100644 --- a/examples/dummyresource/resourcefactory.cpp +++ b/examples/dummyresource/resourcefactory.cpp @@ -40,6 +40,7 @@ //This is the resources entity type, and not the domain type #define ENTITY_TYPE_EVENT "event" #define ENTITY_TYPE_MAIL "mail" +#define ENTITY_TYPE_FOLDER "folder" /** * Index types: @@ -228,5 +229,6 @@ void DummyResourceFactory::registerFacades(Akonadi2::FacadeFactory &factory) { factory.registerFacade(PLUGIN_NAME); factory.registerFacade(PLUGIN_NAME); + factory.registerFacade(PLUGIN_NAME); } -- cgit v1.2.3 From 09aafbd1373b5d1152ac7a453a140a7f76c2e90e Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Fri, 13 Nov 2015 19:34:47 +0100 Subject: It's starting to work --- examples/dummyresource/resourcefacade.cpp | 2 +- examples/dummyresource/resourcefacade.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/dummyresource/resourcefacade.cpp b/examples/dummyresource/resourcefacade.cpp index df805e4..1090757 100644 --- a/examples/dummyresource/resourcefacade.cpp +++ b/examples/dummyresource/resourcefacade.cpp @@ -65,7 +65,7 @@ KAsync::Job DummyResourceConfigFacade::remove(const Akonadi2::ApplicationD return KAsync::null(); } -KAsync::Job DummyResourceConfigFacade::load(const Akonadi2::Query &query, const QSharedPointer > &resultProvider) +KAsync::Job DummyResourceConfigFacade::load(const Akonadi2::Query &query, const QSharedPointer > &resultProvider) { //Read configuration and list all available instances. //This includes runtime information about runing instances etc. diff --git a/examples/dummyresource/resourcefacade.h b/examples/dummyresource/resourcefacade.h index 5a5f46b..aa2ab05 100644 --- a/examples/dummyresource/resourcefacade.h +++ b/examples/dummyresource/resourcefacade.h @@ -42,7 +42,7 @@ public: //Remove instance KAsync::Job remove(const Akonadi2::ApplicationDomain::AkonadiResource &domainObject) Q_DECL_OVERRIDE; //Read configuration and available instances - KAsync::Job load(const Akonadi2::Query &query, const QSharedPointer > &resultProvider) Q_DECL_OVERRIDE; + KAsync::Job load(const Akonadi2::Query &query, const QSharedPointer > &resultProvider) Q_DECL_OVERRIDE; private: QSharedPointer getSettings(); -- cgit v1.2.3 From d4b10a3de396eebc6c815093e9e1725ece270e9e Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Sun, 15 Nov 2015 11:09:31 +0100 Subject: Working folder tree query --- examples/dummyresource/resourcefactory.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'examples') diff --git a/examples/dummyresource/resourcefactory.cpp b/examples/dummyresource/resourcefactory.cpp index edb3b42..bed1d71 100644 --- a/examples/dummyresource/resourcefactory.cpp +++ b/examples/dummyresource/resourcefactory.cpp @@ -114,6 +114,12 @@ DummyResource::DummyResource(const QByteArray &instanceIdentifier, const QShared mPipeline->setPreprocessors(ENTITY_TYPE_MAIL, QVector() << mailIndexer); mPipeline->setAdaptorFactory(ENTITY_TYPE_MAIL, mailFactory); } + { + auto folderFactory = QSharedPointer::create(); + auto folderIndexer = new IndexUpdater("folder.index.rid", ENTITY_TYPE_FOLDER); + mPipeline->setPreprocessors(ENTITY_TYPE_FOLDER, QVector() << folderIndexer); + mPipeline->setAdaptorFactory(ENTITY_TYPE_FOLDER, folderFactory); + } } void DummyResource::createEvent(const QByteArray &ridBuffer, const QMap &data, flatbuffers::FlatBufferBuilder &entityFbb) -- cgit v1.2.3 From 0f24357d01bd8a278f03793db863d3f71ac37ef2 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Wed, 18 Nov 2015 00:51:55 +0100 Subject: Don't use a smart pointer for the result provider We're not doing any lifetime management anyways. --- examples/dummyresource/resourcefacade.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'examples') diff --git a/examples/dummyresource/resourcefacade.cpp b/examples/dummyresource/resourcefacade.cpp index 1090757..af0ebe6 100644 --- a/examples/dummyresource/resourcefacade.cpp +++ b/examples/dummyresource/resourcefacade.cpp @@ -65,20 +65,20 @@ KAsync::Job DummyResourceConfigFacade::remove(const Akonadi2::ApplicationD return KAsync::null(); } -KAsync::Job DummyResourceConfigFacade::load(const Akonadi2::Query &query, const QSharedPointer > &resultProvider) +KAsync::Job DummyResourceConfigFacade::load(const Akonadi2::Query &query, Akonadi2::ResultProviderInterface &resultProvider) { //Read configuration and list all available instances. //This includes runtime information about runing instances etc. //Part of this is generic, and part is accessing the resource specific configuration. //FIXME this currently does not support live queries (because we're not inheriting from GenericFacade) //FIXME only read what was requested in the query? - return KAsync::start([resultProvider, this]() { + return KAsync::start([&resultProvider, this]() { auto settings = getSettings(); auto memoryAdaptor = QSharedPointer::create(); //TODO copy settings to adaptor // //TODO use correct instance identifier //TODO key == instance identifier ? - resultProvider->add(QSharedPointer::create("org.kde.dummy.instance1", "org.kde.dummy.config", 0, memoryAdaptor)); + resultProvider.add(QSharedPointer::create("org.kde.dummy.instance1", "org.kde.dummy.config", 0, memoryAdaptor)); }); } -- cgit v1.2.3 From b42047ad90470ecab329375fdacff03564c80074 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Wed, 18 Nov 2015 23:15:25 +0100 Subject: fixup --- examples/dummyresource/resourcefacade.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/dummyresource/resourcefacade.h b/examples/dummyresource/resourcefacade.h index aa2ab05..82e54fd 100644 --- a/examples/dummyresource/resourcefacade.h +++ b/examples/dummyresource/resourcefacade.h @@ -42,7 +42,7 @@ public: //Remove instance KAsync::Job remove(const Akonadi2::ApplicationDomain::AkonadiResource &domainObject) Q_DECL_OVERRIDE; //Read configuration and available instances - KAsync::Job load(const Akonadi2::Query &query, const QSharedPointer > &resultProvider) Q_DECL_OVERRIDE; + KAsync::Job load(const Akonadi2::Query &query, Akonadi2::ResultProviderInterface &resultProvider) Q_DECL_OVERRIDE; private: QSharedPointer getSettings(); -- cgit v1.2.3 From ef205affdb73bfdbef5830996e6336e583660fbc Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Thu, 19 Nov 2015 09:37:42 +0100 Subject: Use the new modelresult in the dummyclient --- examples/client/main.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'examples') diff --git a/examples/client/main.cpp b/examples/client/main.cpp index 0a1a725..75fcf18 100644 --- a/examples/client/main.cpp +++ b/examples/client/main.cpp @@ -23,14 +23,13 @@ #include "common/clientapi.h" #include "common/resource.h" -#include "common/listmodelresult.h" #include "common/storage.h" #include "common/domain/event.h" #include "common/resourceconfig.h" #include "console.h" #include -#include +#include #include #include #include @@ -43,8 +42,8 @@ public: View(QAbstractItemModel *model) : QWidget() { - auto listView = new QListView(this); - listView->setModel(model); + auto modelView = new QTreeView(this); + modelView->setModel(model); resize(1000, 1500); auto topLayout = new QVBoxLayout(this); @@ -61,21 +60,23 @@ public: QObject::connect(syncButton, &QPushButton::pressed, []() { Akonadi2::Query query; query.resources << "org.kde.dummy.instance1"; - Akonadi2::Store::synchronize(query); + query.syncOnDemand = true; + Akonadi2::Store::synchronize(query).exec(); }); auto removeButton = new QPushButton(this); removeButton->setText("Remove"); - QObject::connect(removeButton, &QPushButton::pressed, [listView]() { - for (auto index :listView->selectionModel()->selectedIndexes()) { - auto object = index.data(DomainObjectRole).value(); + QObject::connect(removeButton, &QPushButton::pressed, [modelView]() { + for (auto index :modelView->selectionModel()->selectedIndexes()) { + auto object = index.data(Akonadi2::Store::DomainObjectRole).value(); Akonadi2::Store::remove(*object).exec(); } }); topLayout->addWidget(titleLabel); topLayout->addWidget(syncButton); - topLayout->addWidget(listView, 10); + topLayout->addWidget(modelView, 10); + model->fetchMore(QModelIndex()); show(); } @@ -123,8 +124,9 @@ int main(int argc, char *argv[]) query.syncOnDemand = false; query.processAll = false; query.liveQuery = true; + query.requestedProperties << "summary" << "uid"; - auto model = QSharedPointer >::create(Akonadi2::Store::load(query), QList() << "summary" << "uid"); + auto model = Akonadi2::Store::loadModel(query); auto view = QSharedPointer >::create(model.data()); return app.exec(); -- cgit v1.2.3 From 8d5684292ef92f32487ba32df716a00c4a0841b5 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Thu, 19 Nov 2015 17:37:39 +0100 Subject: Loading data with the new model for the test client --- examples/client/main.cpp | 7 ++++--- examples/dummyresource/dummystore.h | 2 +- examples/dummyresource/resourcefactory.cpp | 24 ++++++++++++++++++++++++ examples/dummyresource/resourcefactory.h | 1 + 4 files changed, 30 insertions(+), 4 deletions(-) (limited to 'examples') diff --git a/examples/client/main.cpp b/examples/client/main.cpp index 75fcf18..794fc58 100644 --- a/examples/client/main.cpp +++ b/examples/client/main.cpp @@ -25,6 +25,7 @@ #include "common/resource.h" #include "common/storage.h" #include "common/domain/event.h" +#include "common/domain/folder.h" #include "common/resourceconfig.h" #include "console.h" @@ -124,10 +125,10 @@ int main(int argc, char *argv[]) query.syncOnDemand = false; query.processAll = false; query.liveQuery = true; - query.requestedProperties << "summary" << "uid"; + query.requestedProperties << "name"; - auto model = Akonadi2::Store::loadModel(query); - auto view = QSharedPointer >::create(model.data()); + auto model = Akonadi2::Store::loadModel(query); + auto view = QSharedPointer >::create(model.data()); return app.exec(); } diff --git a/examples/dummyresource/dummystore.h b/examples/dummyresource/dummystore.h index 4ecd5ea..c730118 100644 --- a/examples/dummyresource/dummystore.h +++ b/examples/dummyresource/dummystore.h @@ -23,7 +23,6 @@ class DummyStore { public: - //TODO proper singleton static DummyStore &instance() { static DummyStore instance; @@ -32,4 +31,5 @@ public: QMap > events() const; QMap > mails() const; + QMap > folders() const; }; diff --git a/examples/dummyresource/resourcefactory.cpp b/examples/dummyresource/resourcefactory.cpp index bed1d71..2a5a3e8 100644 --- a/examples/dummyresource/resourcefactory.cpp +++ b/examples/dummyresource/resourcefactory.cpp @@ -163,6 +163,27 @@ void DummyResource::createMail(const QByteArray &ridBuffer, const QMap &data, flatbuffers::FlatBufferBuilder &entityFbb) +{ + //Map the source format to the buffer format (which happens to be an exact copy here) + auto name = m_fbb.CreateString(data.value("name").toString().toStdString()); + flatbuffers::Offset parent; + bool hasParent = false; + if (!data.value("parent").toString().isEmpty()) { + hasParent = true; + parent = m_fbb.CreateString(data.value("parent").toString().toStdString()); + } + + auto builder = Akonadi2::ApplicationDomain::Buffer::FolderBuilder(m_fbb); + builder.add_name(name); + if (hasParent) { + builder.add_parent(parent); + } + auto buffer = builder.Finish(); + Akonadi2::ApplicationDomain::Buffer::FinishFolderBuffer(m_fbb, buffer); + Akonadi2::EntityBuffer::assembleEntityBuffer(entityFbb, 0, 0, 0, 0, m_fbb.GetBufferPointer(), m_fbb.GetSize()); +} + void DummyResource::synchronize(const QString &bufferType, const QMap > &data, Akonadi2::Storage::Transaction &transaction, std::function &data, flatbuffers::FlatBufferBuilder &entityFbb)> createEntity) { Index uidIndex("index.uid", transaction); @@ -209,6 +230,9 @@ KAsync::Job DummyResource::synchronizeWithSource() synchronize(ENTITY_TYPE_MAIL, DummyStore::instance().mails(), transaction, [this](const QByteArray &ridBuffer, const QMap &data, flatbuffers::FlatBufferBuilder &entityFbb) { createMail(ridBuffer, data, entityFbb); }); + synchronize(ENTITY_TYPE_FOLDER, DummyStore::instance().folders(), transaction, [this](const QByteArray &ridBuffer, const QMap &data, flatbuffers::FlatBufferBuilder &entityFbb) { + createFolder(ridBuffer, data, entityFbb); + }); f.setFinished(); }); diff --git a/examples/dummyresource/resourcefactory.h b/examples/dummyresource/resourcefactory.h index 196d29a..67681ae 100644 --- a/examples/dummyresource/resourcefactory.h +++ b/examples/dummyresource/resourcefactory.h @@ -38,6 +38,7 @@ public: private: void createEvent(const QByteArray &rid, const QMap &data, flatbuffers::FlatBufferBuilder &entityFbb); void createMail(const QByteArray &rid, const QMap &data, flatbuffers::FlatBufferBuilder &entityFbb); + void createFolder(const QByteArray &rid, const QMap &data, flatbuffers::FlatBufferBuilder &entityFbb); void synchronize(const QString &bufferType, const QMap > &data, Akonadi2::Storage::Transaction &transaction, std::function &data, flatbuffers::FlatBufferBuilder &entityFbb)> createEntity); }; -- cgit v1.2.3 From 94a2cd6ec21bf0466a9a50d6e4a0a956ed47bc82 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Thu, 19 Nov 2015 23:23:56 +0100 Subject: Move implementations to the cpp file. I finally figured out how to do that with cpp files. It requires instantiating the code with all expected classes, but that's not a big problem since we know all types. This will hopefully greatly reduce the compiletimes... --- examples/dummyresource/dummystore.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'examples') diff --git a/examples/dummyresource/dummystore.cpp b/examples/dummyresource/dummystore.cpp index 0356ec0..39ecfe4 100644 --- a/examples/dummyresource/dummystore.cpp +++ b/examples/dummyresource/dummystore.cpp @@ -36,6 +36,13 @@ static QMap createMail(int i) return mail; } +static QMap createFolder(int i) +{ + QMap folder; + folder.insert("name", QString("folder%1").arg(i)); + return folder; +} + QMap > populateEvents() { QMap> content; @@ -54,8 +61,18 @@ QMap > populateMails() return content; } +QMap > populateFolders() +{ + QMap> content; + for (int i = 0; i < 5000; i++) { + content.insert(QString("key%1").arg(i), createFolder(i)); + } + return content; +} + static QMap > s_eventSource = populateEvents(); static QMap > s_mailSource = populateMails(); +static QMap > s_folderSource = populateFolders(); QMap > DummyStore::events() const { @@ -66,3 +83,8 @@ QMap > DummyStore::mails() const { return s_mailSource; } + +QMap > DummyStore::folders() const +{ + return s_folderSource; +} -- cgit v1.2.3 From 60b4be31c40e7c4681f5ce462af84dd92872ec5f Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Wed, 25 Nov 2015 15:42:21 +0100 Subject: Separate the default index updater from other generic indexers --- examples/dummyresource/resourcefactory.cpp | 53 ++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 17 deletions(-) (limited to 'examples') diff --git a/examples/dummyresource/resourcefactory.cpp b/examples/dummyresource/resourcefactory.cpp index 2a5a3e8..e524c3f 100644 --- a/examples/dummyresource/resourcefactory.cpp +++ b/examples/dummyresource/resourcefactory.cpp @@ -52,7 +52,6 @@ * * range indexes like what date range an event affects. * * group indexes like tree hierarchies as nested sets */ -template class IndexUpdater : public Akonadi2::Preprocessor { public: IndexUpdater(const QByteArray &index, const QByteArray &type) @@ -64,21 +63,17 @@ public: void newEntity(const QByteArray &uid, qint64 revision, const Akonadi2::ApplicationDomain::BufferAdaptor &newEntity, Akonadi2::Storage::Transaction &transaction) Q_DECL_OVERRIDE { - Akonadi2::ApplicationDomain::TypeImplementation::index(uid, newEntity, transaction); add(newEntity.getProperty("remoteId"), uid, transaction); } void modifiedEntity(const QByteArray &uid, qint64 revision, const Akonadi2::ApplicationDomain::BufferAdaptor &oldEntity, const Akonadi2::ApplicationDomain::BufferAdaptor &newEntity, Akonadi2::Storage::Transaction &transaction) Q_DECL_OVERRIDE { - Akonadi2::ApplicationDomain::TypeImplementation::removeIndex(uid, oldEntity, transaction); - Akonadi2::ApplicationDomain::TypeImplementation::index(uid, newEntity, transaction); remove(oldEntity.getProperty("remoteId"), uid, transaction); add(newEntity.getProperty("remoteId"), uid, transaction); } void deletedEntity(const QByteArray &uid, qint64 revision, const Akonadi2::ApplicationDomain::BufferAdaptor &oldEntity, Akonadi2::Storage::Transaction &transaction) Q_DECL_OVERRIDE { - Akonadi2::ApplicationDomain::TypeImplementation::removeIndex(uid, oldEntity, transaction); remove(oldEntity.getProperty("remoteId"), uid, transaction); } @@ -92,6 +87,7 @@ private: void remove(const QVariant &value, const QByteArray &uid, Akonadi2::Storage::Transaction &transaction) { + //TODO hide notfound error Index(mIndexIdentifier, transaction).remove(value.toByteArray(), uid); } @@ -99,26 +95,49 @@ private: QByteArray mBufferType; }; +template +class DefaultIndexUpdater : public Akonadi2::Preprocessor { +public: + void newEntity(const QByteArray &uid, qint64 revision, const Akonadi2::ApplicationDomain::BufferAdaptor &newEntity, Akonadi2::Storage::Transaction &transaction) Q_DECL_OVERRIDE + { + Akonadi2::ApplicationDomain::TypeImplementation::index(uid, newEntity, transaction); + } + + void modifiedEntity(const QByteArray &uid, qint64 revision, const Akonadi2::ApplicationDomain::BufferAdaptor &oldEntity, const Akonadi2::ApplicationDomain::BufferAdaptor &newEntity, Akonadi2::Storage::Transaction &transaction) Q_DECL_OVERRIDE + { + Akonadi2::ApplicationDomain::TypeImplementation::removeIndex(uid, oldEntity, transaction); + Akonadi2::ApplicationDomain::TypeImplementation::index(uid, newEntity, transaction); + } + + void deletedEntity(const QByteArray &uid, qint64 revision, const Akonadi2::ApplicationDomain::BufferAdaptor &oldEntity, Akonadi2::Storage::Transaction &transaction) Q_DECL_OVERRIDE + { + Akonadi2::ApplicationDomain::TypeImplementation::removeIndex(uid, oldEntity, transaction); + } +}; + DummyResource::DummyResource(const QByteArray &instanceIdentifier, const QSharedPointer &pipeline) : Akonadi2::GenericResource(instanceIdentifier, pipeline) { { - auto eventFactory = QSharedPointer::create(); - auto eventIndexer = new IndexUpdater("event.index.rid", ENTITY_TYPE_EVENT); - mPipeline->setPreprocessors(ENTITY_TYPE_EVENT, QVector() << eventIndexer); - mPipeline->setAdaptorFactory(ENTITY_TYPE_EVENT, eventFactory); + QVector eventPreprocessors; + eventPreprocessors << new DefaultIndexUpdater; + eventPreprocessors << new IndexUpdater("event.index.rid", ENTITY_TYPE_EVENT); + mPipeline->setPreprocessors(ENTITY_TYPE_EVENT, eventPreprocessors); + mPipeline->setAdaptorFactory(ENTITY_TYPE_EVENT, QSharedPointer::create()); } { - auto mailFactory = QSharedPointer::create(); - auto mailIndexer = new IndexUpdater("mail.index.rid", ENTITY_TYPE_MAIL); - mPipeline->setPreprocessors(ENTITY_TYPE_MAIL, QVector() << mailIndexer); - mPipeline->setAdaptorFactory(ENTITY_TYPE_MAIL, mailFactory); + QVector mailPreprocessors; + mailPreprocessors << new DefaultIndexUpdater; + mailPreprocessors << new IndexUpdater("mail.index.rid", ENTITY_TYPE_MAIL); + mPipeline->setPreprocessors(ENTITY_TYPE_MAIL, mailPreprocessors); + mPipeline->setAdaptorFactory(ENTITY_TYPE_MAIL, QSharedPointer::create()); } { - auto folderFactory = QSharedPointer::create(); - auto folderIndexer = new IndexUpdater("folder.index.rid", ENTITY_TYPE_FOLDER); - mPipeline->setPreprocessors(ENTITY_TYPE_FOLDER, QVector() << folderIndexer); - mPipeline->setAdaptorFactory(ENTITY_TYPE_FOLDER, folderFactory); + QVector folderPreprocessors; + folderPreprocessors << new DefaultIndexUpdater; + folderPreprocessors << new IndexUpdater("folder.index.rid", ENTITY_TYPE_FOLDER); + mPipeline->setPreprocessors(ENTITY_TYPE_FOLDER, folderPreprocessors); + mPipeline->setAdaptorFactory(ENTITY_TYPE_FOLDER, QSharedPointer::create()); } } -- cgit v1.2.3 From 5b41b26a349967acf2197f9f9228526193fd826e Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Fri, 27 Nov 2015 17:30:04 +0100 Subject: Introduced a QueryRunner object The QueryRunner object lives for the duration of the query (so just for the initial query for non-live queries, and for the lifetime of the result model for live queries). It's supposed to handle all the threading internally and decouple the lifetime of the facade. --- examples/dummyresource/CMakeLists.txt | 2 +- examples/dummyresource/resourcefacade.cpp | 84 ------------------------------- examples/dummyresource/resourcefacade.h | 49 ------------------ 3 files changed, 1 insertion(+), 134 deletions(-) delete mode 100644 examples/dummyresource/resourcefacade.cpp delete mode 100644 examples/dummyresource/resourcefacade.h (limited to 'examples') diff --git a/examples/dummyresource/CMakeLists.txt b/examples/dummyresource/CMakeLists.txt index e4b51dd..1e80f81 100644 --- a/examples/dummyresource/CMakeLists.txt +++ b/examples/dummyresource/CMakeLists.txt @@ -4,7 +4,7 @@ add_definitions(-DQT_PLUGIN) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) -add_library(${PROJECT_NAME} SHARED facade.cpp resourcefactory.cpp domainadaptor.cpp resourcefacade.cpp dummystore.cpp) +add_library(${PROJECT_NAME} SHARED facade.cpp resourcefactory.cpp domainadaptor.cpp dummystore.cpp) generate_flatbuffers(${PROJECT_NAME} dummycalendar) qt5_use_modules(${PROJECT_NAME} Core Network) target_link_libraries(${PROJECT_NAME} akonadi2common) diff --git a/examples/dummyresource/resourcefacade.cpp b/examples/dummyresource/resourcefacade.cpp deleted file mode 100644 index af0ebe6..0000000 --- a/examples/dummyresource/resourcefacade.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2014 Christian Mollekopf - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "resourcefacade.h" - -#include -#include - -DummyResourceConfigFacade::DummyResourceConfigFacade() - : Akonadi2::StoreFacade() -{ - -} - -DummyResourceConfigFacade::~DummyResourceConfigFacade() -{ - -} - -QSharedPointer DummyResourceConfigFacade::getSettings() -{ - //FIXME deal with resource instances - const QString instanceIdentifier = "dummyresource.instance1"; - //FIXME Use config location - return QSharedPointer::create(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/akonadi2/" + "org.kde." + instanceIdentifier + "/settings.ini", QSettings::IniFormat); -} - -KAsync::Job DummyResourceConfigFacade::create(const Akonadi2::ApplicationDomain::AkonadiResource &domainObject) -{ - //TODO create resource instance - //This can be generalized in a base implementation - return KAsync::null(); -} - -KAsync::Job DummyResourceConfigFacade::modify(const Akonadi2::ApplicationDomain::AkonadiResource &domainObject) -{ - //modify configuration - //This part is likely resource specific, but could be partially generalized - return KAsync::start([domainObject, this]() { - auto settings = getSettings(); - //TODO Write properties to file - }); -} - -KAsync::Job DummyResourceConfigFacade::remove(const Akonadi2::ApplicationDomain::AkonadiResource &domainObject) -{ - //TODO remove resource instance - //This can be generalized in a base implementation - return KAsync::null(); -} - -KAsync::Job DummyResourceConfigFacade::load(const Akonadi2::Query &query, Akonadi2::ResultProviderInterface &resultProvider) -{ - //Read configuration and list all available instances. - //This includes runtime information about runing instances etc. - //Part of this is generic, and part is accessing the resource specific configuration. - //FIXME this currently does not support live queries (because we're not inheriting from GenericFacade) - //FIXME only read what was requested in the query? - return KAsync::start([&resultProvider, this]() { - auto settings = getSettings(); - auto memoryAdaptor = QSharedPointer::create(); - //TODO copy settings to adaptor - // - //TODO use correct instance identifier - //TODO key == instance identifier ? - resultProvider.add(QSharedPointer::create("org.kde.dummy.instance1", "org.kde.dummy.config", 0, memoryAdaptor)); - }); -} diff --git a/examples/dummyresource/resourcefacade.h b/examples/dummyresource/resourcefacade.h deleted file mode 100644 index 82e54fd..0000000 --- a/examples/dummyresource/resourcefacade.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2014 Christian Mollekopf - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#pragma once - -#include -#include -#include -#include - -namespace Akonadi2 { - class Query; -} - -class QSettings; - -class DummyResourceConfigFacade : public Akonadi2::StoreFacade -{ -public: - DummyResourceConfigFacade(); - ~DummyResourceConfigFacade(); - //Create an instance - KAsync::Job create(const Akonadi2::ApplicationDomain::AkonadiResource &domainObject) Q_DECL_OVERRIDE; - //Modify configuration - KAsync::Job modify(const Akonadi2::ApplicationDomain::AkonadiResource &domainObject) Q_DECL_OVERRIDE; - //Remove instance - KAsync::Job remove(const Akonadi2::ApplicationDomain::AkonadiResource &domainObject) Q_DECL_OVERRIDE; - //Read configuration and available instances - KAsync::Job load(const Akonadi2::Query &query, Akonadi2::ResultProviderInterface &resultProvider) Q_DECL_OVERRIDE; - -private: - QSharedPointer getSettings(); -}; -- cgit v1.2.3 From 0118cd09f9a2cc956ae0a07b3ba8ad3c95314cab Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Fri, 27 Nov 2015 17:44:21 +0100 Subject: list and count options for non-gui operations --- examples/client/main.cpp | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'examples') diff --git a/examples/client/main.cpp b/examples/client/main.cpp index 794fc58..c75b3ce 100644 --- a/examples/client/main.cpp +++ b/examples/client/main.cpp @@ -68,7 +68,7 @@ public: auto removeButton = new QPushButton(this); removeButton->setText("Remove"); QObject::connect(removeButton, &QPushButton::pressed, [modelView]() { - for (auto index :modelView->selectionModel()->selectedIndexes()) { + for (auto index : modelView->selectionModel()->selectedIndexes()) { auto object = index.data(Akonadi2::Store::DomainObjectRole).value(); Akonadi2::Store::remove(*object).exec(); } @@ -93,6 +93,8 @@ int main(int argc, char *argv[]) QObject::tr("A resource to connect to")); cliOptions.addOption(QCommandLineOption("clear")); cliOptions.addOption(QCommandLineOption("debuglevel")); + cliOptions.addOption(QCommandLineOption("list")); + cliOptions.addOption(QCommandLineOption("count")); cliOptions.addHelpOption(); cliOptions.process(app); QStringList resources = cliOptions.positionalArguments(); @@ -124,11 +126,27 @@ int main(int argc, char *argv[]) } query.syncOnDemand = false; query.processAll = false; - query.liveQuery = true; query.requestedProperties << "name"; auto model = Akonadi2::Store::loadModel(query); - auto view = QSharedPointer >::create(model.data()); - - return app.exec(); + if (cliOptions.isSet("list")) { + query.liveQuery = false; + qDebug() << "Listing"; + QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, [model](const QModelIndex &index, int start, int end) { + for (int i = start; i <= end; i++) { + qDebug() << model->data(model->index(i, 0, index)).toString(); + } + }); + model->fetchMore(QModelIndex()); + return app.exec(); + } else if (cliOptions.isSet("count")) { + query.liveQuery = false; + model->fetchMore(QModelIndex()); + qDebug() << "Counted results " << model->rowCount(QModelIndex()); + } else { + query.liveQuery = true; + auto view = QSharedPointer >::create(model.data()); + return app.exec(); + } + return 0; } -- cgit v1.2.3 From 4926e7f613ea3e03a2865eec66c6a8c1ec0b6516 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Sat, 28 Nov 2015 16:07:15 +0100 Subject: Cleanup --- examples/client/main.cpp | 4 +--- examples/dummyresource/dummystore.cpp | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'examples') diff --git a/examples/client/main.cpp b/examples/client/main.cpp index c75b3ce..3fa5a4e 100644 --- a/examples/client/main.cpp +++ b/examples/client/main.cpp @@ -77,7 +77,6 @@ public: topLayout->addWidget(titleLabel); topLayout->addWidget(syncButton); topLayout->addWidget(modelView, 10); - model->fetchMore(QModelIndex()); show(); } @@ -127,6 +126,7 @@ int main(int argc, char *argv[]) query.syncOnDemand = false; query.processAll = false; query.requestedProperties << "name"; + query.liveQuery = true; auto model = Akonadi2::Store::loadModel(query); if (cliOptions.isSet("list")) { @@ -137,11 +137,9 @@ int main(int argc, char *argv[]) qDebug() << model->data(model->index(i, 0, index)).toString(); } }); - model->fetchMore(QModelIndex()); return app.exec(); } else if (cliOptions.isSet("count")) { query.liveQuery = false; - model->fetchMore(QModelIndex()); qDebug() << "Counted results " << model->rowCount(QModelIndex()); } else { query.liveQuery = true; diff --git a/examples/dummyresource/dummystore.cpp b/examples/dummyresource/dummystore.cpp index 39ecfe4..458695f 100644 --- a/examples/dummyresource/dummystore.cpp +++ b/examples/dummyresource/dummystore.cpp @@ -64,7 +64,7 @@ QMap > populateMails() QMap > populateFolders() { QMap> content; - for (int i = 0; i < 5000; i++) { + for (int i = 0; i < 5; i++) { content.insert(QString("key%1").arg(i), createFolder(i)); } return content; -- cgit v1.2.3 From 887abffb3f712acaa23eae174d5890f337fe43cb Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Sat, 28 Nov 2015 16:20:38 +0100 Subject: Cleanup --- examples/client/main.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'examples') diff --git a/examples/client/main.cpp b/examples/client/main.cpp index 3fa5a4e..7e69c0a 100644 --- a/examples/client/main.cpp +++ b/examples/client/main.cpp @@ -27,6 +27,7 @@ #include "common/domain/event.h" #include "common/domain/folder.h" #include "common/resourceconfig.h" +#include "common/log.h" #include "console.h" #include -- cgit v1.2.3 From 6ad307dd846d07f1b55a1679a8d2eb47525af57d Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Mon, 30 Nov 2015 18:46:50 +0100 Subject: example client: slot performance measurements, async commands --- examples/client/main.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) (limited to 'examples') diff --git a/examples/client/main.cpp b/examples/client/main.cpp index 7e69c0a..2aeb328 100644 --- a/examples/client/main.cpp +++ b/examples/client/main.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "common/clientapi.h" #include "common/resource.h" @@ -36,6 +37,7 @@ #include #include #include +#include template class View : public QWidget @@ -84,9 +86,29 @@ public: }; + +class MyApplication : public QApplication +{ + QElapsedTimer t; +public: + MyApplication(int& argc, char ** argv) : QApplication(argc, argv) { } + virtual ~MyApplication() { } + + virtual bool notify(QObject* receiver, QEvent* event) + { + t.start(); + bool ret = QApplication::notify(receiver, event); + if(t.elapsed() > 3) + qDebug("processing event type %d for object %s took %dms", + (int)event->type(), receiver->objectName().toLocal8Bit().data(), + (int)t.elapsed()); + return ret; + } +}; + int main(int argc, char *argv[]) { - QApplication app(argc, argv); + MyApplication app(argc, argv); QCommandLineParser cliOptions; cliOptions.addPositionalArgument(QObject::tr("[resource]"), @@ -129,19 +151,36 @@ int main(int argc, char *argv[]) query.requestedProperties << "name"; query.liveQuery = true; + QTime time; + time.start(); auto model = Akonadi2::Store::loadModel(query); + qDebug() << "Loaded model in " << time.elapsed() << " ms"; + if (cliOptions.isSet("list")) { query.liveQuery = false; qDebug() << "Listing"; QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, [model](const QModelIndex &index, int start, int end) { for (int i = start; i <= end; i++) { - qDebug() << model->data(model->index(i, 0, index)).toString(); + std::cout << "\tRow " << model->rowCount() << ": " << model->data(model->index(i, 0, index)).toString().toStdString() << std::endl; } }); - return app.exec(); + QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [model, &app](const QModelIndex &, const QModelIndex &, const QVector &roles) { + if (roles.contains(Akonadi2::Store::ChildrenFetchedRole)) { + app.quit(); + } + }); + if (!model->data(QModelIndex(), Akonadi2::Store::ChildrenFetchedRole).toBool()) { + return app.exec(); + } } else if (cliOptions.isSet("count")) { query.liveQuery = false; - qDebug() << "Counted results " << model->rowCount(QModelIndex()); + QObject::connect(model.data(), &QAbstractItemModel::dataChanged, [model, &app](const QModelIndex &, const QModelIndex &, const QVector &roles) { + if (roles.contains(Akonadi2::Store::ChildrenFetchedRole)) { + std::cout << "\tCounted results " << model->rowCount(QModelIndex()); + app.quit(); + } + }); + return app.exec(); } else { query.liveQuery = true; auto view = QSharedPointer >::create(model.data()); -- cgit v1.2.3