Commit 29469586 authored by Shashwat Jolly's avatar Shashwat Jolly

Implement asynchronous fetching for journals and entries

Implemented JournalsFetchJob and EntriesFetchJob
parent 642aa185
......@@ -5,6 +5,9 @@ kconfig_add_kcfg_files(etesyncresource_common_SRCS
set(etesyncresource_SRCS
etesyncresource.cpp
journalsfetchjob.cpp
entriesfetchjob.cpp
etesyncadapter.cpp
${etesyncresource_common_SRCS}
)
......@@ -36,6 +39,7 @@ target_link_libraries(akonadi_etesync_resource
KF5::AkonadiAgentBase
KF5::ConfigCore
KF5::Contacts
KF5::KIOCore
KF5::I18n
)
......
/*
* Copyright (C) 2020 by Shashwat Jolly <shashwat.jolly@gmail.com>
*
* 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, see <https://www.gnu.org/licenses/>.
*/
#include "entriesfetchjob.h"
#include <kio/job.h>
#include <QTimer>
#include "settings.h"
using namespace EteSyncAPI;
EntriesFetchJob::EntriesFetchJob(const EteSync *client, const QString &journalUid, const QString &prevUid, QObject *parent)
: KJob(parent), mClient(client), mJournalUid(journalUid), mPrevUid(prevUid)
{
}
void EntriesFetchJob::start()
{
QTimer::singleShot(0, this, &EntriesFetchJob::fetchEntries);
}
void EntriesFetchJob::fetchEntries()
{
EteSyncEntryManager *entryManager = etesync_entry_manager_new(mClient, mJournalUid);
mEntries = etesync_entry_manager_list(entryManager, mPrevUid, 0);
if (!mEntries) {
setError(UserDefinedError);
setErrorText(QStringLiteral("EntriesFetchJob failed to fetch entries"));
}
emitResult();
}
/*
* Copyright (C) 2020 by Shashwat Jolly <shashwat.jolly@gmail.com>
*
* 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, see <https://www.gnu.org/licenses/>.
*/
#ifndef ETESYNCENTRIESFETCHJOB_H
#define ETESYNCENTRIESFETCHJOB_H
#include <KJob>
#include "etesyncadapter.h"
namespace EteSyncAPI {
class EntriesFetchJob : public KJob
{
Q_OBJECT
public:
EntriesFetchJob(const EteSync *client, const QString &journalUid, const QString &prevUid, QObject *parent = nullptr);
void start() override;
EteSyncEntry **entries()
{
return mEntries;
}
protected:
void fetchEntries();
private:
const EteSync *mClient = nullptr;
const QString mJournalUid;
const QString mPrevUid;
EteSyncEntry **mEntries = nullptr;
};
} // namespace EteSyncAPI
#endif
/*
* Copyright (C) 2020 by Shashwat Jolly <shashwat.jolly@gmail.com>
*
* 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, see <https://www.gnu.org/licenses/>.
*/
#include <etesyncadapter.h>
QString QStringFromCharArr(const char *str)
{
if (str == NULL) {
return QString();
}
return QLatin1String(str);
}
const char *charArrFromQString(const QString &str)
{
if (str.isNull()) return NULL;
QByteArray ba = str.toLocal8Bit();
const char *ret = qstrdup(ba.data());
return ret;
}
QString etesync_auth_get_token(const EteSync *etesync, const QString &username,
const QString &password)
{
const char *uname = charArrFromQString(username);
const char *pass = charArrFromQString(password);
char *token = etesync_auth_get_token(etesync, uname, pass);
return QStringFromCharArr(token);
}
qint32 etesync_auth_invalidate_token(const EteSync *etesync,
const QString &token)
{
const char *tok = charArrFromQString(token);
return etesync_auth_invalidate_token(etesync, tok);
}
EteSyncCollectionInfo *etesync_collection_info_new(const QString &col_type,
const QString &display_name,
const QString &description,
qint32 color)
{
const char *colType = charArrFromQString(col_type);
const char *displayName = charArrFromQString(display_name);
const char *desc = charArrFromQString(description);
return etesync_collection_info_new(colType, displayName, desc, color);
}
QString etesync_crypto_derive_key(const EteSync *_etesync, const QString &salt,
const QString &password)
{
const char *s = charArrFromQString(salt);
const char *pass = charArrFromQString(password);
char *ret = etesync_crypto_derive_key(_etesync, s, pass);
return QStringFromCharArr(ret);
}
EteSyncEntry *etesync_entry_from_sync_entry(const EteSyncCryptoManager *crypto_manager,
const EteSyncSyncEntry *sync_entry,
const QString &prev_uid)
{
const char *prevUid = charArrFromQString(prev_uid);
return etesync_entry_from_sync_entry(crypto_manager, sync_entry, prevUid);
}
EteSyncSyncEntry *etesync_entry_get_sync_entry(const EteSyncEntry *entry,
const EteSyncCryptoManager *crypto_manager,
const QString &prev_uid)
{
const char *prevUid = charArrFromQString(prev_uid);
return etesync_entry_get_sync_entry(entry, crypto_manager, prevUid);
}
qint32 etesync_entry_manager_create(const EteSyncEntryManager *entry_manager,
const EteSyncEntry *const *entries,
const QString &prev_uid)
{
const char *prevUid = charArrFromQString(prev_uid);
return etesync_entry_manager_create(entry_manager, entries, prevUid);
}
EteSyncEntry **etesync_entry_manager_list(const EteSyncEntryManager *entry_manager,
const QString &prev_uid, uintptr_t limit)
{
const char *prevUid = charArrFromQString(prev_uid);
return etesync_entry_manager_list(entry_manager, prevUid, limit);
}
EteSyncEntryManager *etesync_entry_manager_new(const EteSync *etesync,
const QString &journal_uid)
{
const char *journalUid = charArrFromQString(journal_uid);
return etesync_entry_manager_new(etesync, journalUid);
}
EteSyncCryptoManager *etesync_journal_get_crypto_manager(const EteSyncJournal *journal,
const QString &key,
const EteSyncAsymmetricKeyPair *keypair)
{
const char *k = charArrFromQString(key);
return etesync_journal_get_crypto_manager(journal, k, keypair);
}
EteSyncJournal *etesync_journal_manager_fetch(const EteSyncJournalManager *journal_manager,
const QString &journal_uid)
{
const char *journalUid = charArrFromQString(journal_uid);
return etesync_journal_manager_fetch(journal_manager, journalUid);
}
EteSyncJournal *etesync_journal_new(const QString &uid, uint8_t version)
{
const char *id = charArrFromQString(uid);
return etesync_journal_new(id, version);
}
EteSync *etesync_new(const QString &client_name, const QString &server_url)
{
const char *clientName = charArrFromQString(client_name);
const char *serverUrl = charArrFromQString(server_url);
return etesync_new(clientName, serverUrl);
}
void etesync_set_auth_token(EteSync *etesync, const QString &token)
{
const char *tok = charArrFromQString(token);
etesync_set_auth_token(etesync, tok);
}
EteSyncSyncEntry *etesync_sync_entry_new(const QString &action,
const QString &content)
{
const char *act = charArrFromQString(action);
const char *cont = charArrFromQString(content);
return etesync_sync_entry_new(act, cont);
}
EteSyncCryptoManager *etesync_user_info_get_crypto_manager(const EteSyncUserInfo *user_info,
const QString &key)
{
const char *k = charArrFromQString(key);
return etesync_user_info_get_crypto_manager(user_info, k);
}
EteSyncUserInfo *etesync_user_info_manager_fetch(const EteSyncUserInfoManager *user_info_manager,
const QString &owner)
{
const char *own = charArrFromQString(owner);
return etesync_user_info_manager_fetch(user_info_manager, own);
}
......@@ -15,143 +15,69 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef ETESYNCADAPTER_H
#define ETESYNCADAPTER_H
#include <etesync/etesync.h>
QString QStringFromCharArr(const char *str) { return QLatin1String(str); }
#include <QString>
QString QStringFromCharArr(const char *str);
const char *charArrFromQString(const QString &str)
{
QByteArray ba = str.toLocal8Bit();
const char *ret = qstrdup(ba.data());
return ret;
}
const char *charArrFromQString(const QString &str);
QString etesync_auth_get_token(const EteSync *etesync, const QString &username,
const QString &password)
{
const char *uname = charArrFromQString(username);
const char *pass = charArrFromQString(password);
char *token = etesync_auth_get_token(etesync, uname, pass);
return QStringFromCharArr(token);
}
const QString &password);
qint32 etesync_auth_invalidate_token(const EteSync *etesync,
const QString &token)
{
const char *tok = charArrFromQString(token);
return etesync_auth_invalidate_token(etesync, tok);
}
const QString &token);
EteSyncCollectionInfo *etesync_collection_info_new(const QString &col_type,
const QString &display_name,
const QString &description,
qint32 color)
{
const char *colType = charArrFromQString(col_type);
const char *displayName = charArrFromQString(display_name);
const char *desc = charArrFromQString(description);
return etesync_collection_info_new(colType, displayName, desc, color);
}
qint32 color);
QString etesync_crypto_derive_key(const EteSync *_etesync, const QString &salt,
const QString &password)
{
const char *s = charArrFromQString(salt);
const char *pass = charArrFromQString(password);
char *ret = etesync_crypto_derive_key(_etesync, s, pass);
return QStringFromCharArr(ret);
}
const QString &password);
EteSyncEntry *etesync_entry_from_sync_entry(const EteSyncCryptoManager *crypto_manager,
const EteSyncSyncEntry *sync_entry,
const QString &prev_uid)
{
const char *prevUid = charArrFromQString(prev_uid);
return etesync_entry_from_sync_entry(crypto_manager, sync_entry, prevUid);
}
const QString &prev_uid);
EteSyncSyncEntry *etesync_entry_get_sync_entry(const EteSyncEntry *entry,
const EteSyncCryptoManager *crypto_manager,
const QString &prev_uid)
{
const char *prevUid = charArrFromQString(prev_uid);
return etesync_entry_get_sync_entry(entry, crypto_manager, prevUid);
}
const QString &prev_uid);
qint32 etesync_entry_manager_create(const EteSyncEntryManager *entry_manager,
const EteSyncEntry *const *entries,
const QString &prev_uid)
{
const char *prevUid = charArrFromQString(prev_uid);
return etesync_entry_manager_create(entry_manager, entries, prevUid);
}
const QString &prev_uid);
EteSyncEntry **etesync_entry_manager_list(const EteSyncEntryManager *entry_manager,
const QString &prev_uid, uintptr_t limit)
{
const char *prevUid = charArrFromQString(prev_uid);
return etesync_entry_manager_list(entry_manager, prevUid, limit);
}
const QString &prev_uid, uintptr_t limit);
EteSyncEntryManager *etesync_entry_manager_new(const EteSync *etesync,
const QString &journal_uid)
{
const char *journalUid = charArrFromQString(journal_uid);
return etesync_entry_manager_new(etesync, journalUid);
}
const QString &journal_uid);
EteSyncCryptoManager *etesync_journal_get_crypto_manager(const EteSyncJournal *journal,
const QString &key,
const EteSyncAsymmetricKeyPair *keypair)
{
const char *k = charArrFromQString(key);
return etesync_journal_get_crypto_manager(journal, k, keypair);
}
const EteSyncAsymmetricKeyPair *keypair);
EteSyncJournal *etesync_journal_manager_fetch(const EteSyncJournalManager *journal_manager,
const QString &journal_uid)
{
const char *journalUid = charArrFromQString(journal_uid);
return etesync_journal_manager_fetch(journal_manager, journalUid);
}
EteSyncJournal *etesync_journal_new(const QString &uid, uint8_t version)
{
const char *id = charArrFromQString(uid);
return etesync_journal_new(id, version);
}
EteSync *etesync_new(const QString &client_name, const QString &server_url)
{
const char *clientName = charArrFromQString(client_name);
const char *serverUrl = charArrFromQString(server_url);
return etesync_new(clientName, serverUrl);
}
void etesync_set_auth_token(EteSync *etesync, const QString &token)
{
const char *tok = charArrFromQString(token);
etesync_set_auth_token(etesync, tok);
}
const QString &journal_uid);
EteSyncJournal *etesync_journal_new(const QString &uid, uint8_t version);
EteSync *etesync_new(const QString &client_name, const QString &server_url);
void etesync_set_auth_token(EteSync *etesync, const QString &token);
EteSyncSyncEntry *etesync_sync_entry_new(const QString &action,
const QString &content)
{
const char *act = charArrFromQString(action);
const char *cont = charArrFromQString(content);
return etesync_sync_entry_new(act, cont);
}
const QString &content);
EteSyncCryptoManager *etesync_user_info_get_crypto_manager(const EteSyncUserInfo *user_info,
const QString &key)
{
const char *k = charArrFromQString(key);
return etesync_user_info_get_crypto_manager(user_info, k);
}
const QString &key);
EteSyncUserInfo *etesync_user_info_manager_fetch(const EteSyncUserInfoManager *user_info_manager,
const QString &owner)
{
const char *own = charArrFromQString(owner);
return etesync_user_info_manager_fetch(user_info_manager, own);
}
const QString &owner);
#endif
\ No newline at end of file
......@@ -17,14 +17,18 @@
#include "etesyncresource.h"
#include <AkonadiCore/CollectionModifyJob>
#include <KLocalizedString>
#include <QDBusConnection>
#include "entriesfetchjob.h"
#include "etesync_debug.h"
#include "etesyncadapter.h"
#include "journalsfetchjob.h"
#include "settings.h"
#include "settingsadaptor.h"
using namespace EteSyncAPI;
using namespace Akonadi;
etesyncResource::etesyncResource(const QString &id)
......@@ -41,105 +45,173 @@ etesyncResource::etesyncResource(const QString &id)
setNeedsNetwork(true);
serverUrl = Settings::self()->baseUrl();
username = Settings::self()->username();
password = Settings::self()->password();
encryptionPassword = Settings::self()->encryptionPassword();
connect(this, &Akonadi::AgentBase::reloadConfiguration, this, &etesyncResource::onReloadConfiguration);
qCDebug(ETESYNC_LOG) << "Resource started";
}
etesyncResource::~etesyncResource() {}
etesyncResource::~etesyncResource()
{
etesync_destroy(etesync);
}
void etesyncResource::retrieveCollections()
{
EteSyncJournal **journals = etesync_journal_manager_list(journalManager);
auto job = new JournalsFetchJob(etesync, this);
connect(job, &JournalsFetchJob::finished, this, [this](KJob *job) {
if (job->error()) {
qCWarning(ETESYNC_LOG) << "Error in fetching journals";
return;
}
qCDebug(ETESYNC_LOG) << "Retrieving collections";
EteSyncJournal **journals = qobject_cast<JournalsFetchJob *>(job)->journals();
Collection::List list;
for (EteSyncJournal **iter = journals; *iter; iter++) {
EteSyncJournal *journal = *iter;
Collection::List list;
Collection collection;
for (EteSyncJournal **iter = journals; *iter; iter++) {
EteSyncJournal *journal = *iter;
/// TODO: Remove temporary hack to handle only addressbooks
if (setupCollection(collection, journal)) continue;
EteSyncCryptoManager *cryptoManager = etesync_journal_get_crypto_manager(journal, derived, keypair);
list << collection;
EteSyncCollectionInfo *info = etesync_journal_get_info(journal, cryptoManager);
etesync_journal_destroy(journal);
}
free(journals);
collectionsRetrieved(list);
});
job->start();
}
if (QStringFromCharArr(etesync_collection_info_get_type(info)) != QStringLiteral("ADDRESS_BOOK"))
continue;
/// TODO: Remove temporary hack, make this void
int etesyncResource::setupCollection(Collection &collection, EteSyncJournal *journal)
{
int typeNum;
EteSyncCryptoManager *cryptoManager = etesync_journal_get_crypto_manager(journal, derived, keypair);
Collection c;
c.setParentCollection(Collection::root());
c.setRemoteId(QStringFromCharArr(etesync_journal_get_uid(journal)));
c.setName(QStringFromCharArr(etesync_collection_info_get_display_name(info)));
EteSyncCollectionInfo *info = etesync_journal_get_info(journal, cryptoManager);
QStringList mimeTypes;
mimeTypes << KContacts::Addressee::mimeType();
c.setContentMimeTypes(mimeTypes);
const QString type = QStringFromCharArr(etesync_collection_info_get_type(info));
list << c;
QStringList mimeTypes;
etesync_collection_info_destroy(info);
etesync_crypto_manager_destroy(cryptoManager);
etesync_journal_destroy(journal);
if (type == QStringLiteral(ETESYNC_COLLECTION_TYPE_ADDRESS_BOOK)) {
mimeTypes << KContacts::Addressee::mimeType();
typeNum = 0;
} else if (type == QStringLiteral(ETESYNC_COLLECTION_TYPE_CALENDAR)) {
mimeTypes << KContacts::Addressee::mimeType();
typeNum = 1;
} else if (type == QStringLiteral(ETESYNC_COLLECTION_TYPE_TASKS)) {
mimeTypes << KContacts::Addressee::mimeType();
typeNum = 2;
} else {
qCWarning(ETESYNC_LOG) << "Unknown journal type. Cannot set collection mime type.";
}
free(journals);
collectionsRetrieved(list);
collection.setParentCollection(Collection::root());
collection.setRemoteId(QStringFromCharArr(etesync_journal_get_uid(journal)));
collection.setName(QStringFromCharArr(etesync_collection_info_get_display_name(info)));
collection.setContentMimeTypes(mimeTypes);
etesync_collection_info_destroy(info);
etesync_crypto_manager_destroy(cryptoManager);
return typeNum;
}
void etesyncResource::retrieveItems(const Akonadi::Collection &collection)
{
const QString journalUid = collection.remoteId();
QString journalUid = collection.remoteId();
QString prevUid = collection.remoteRevision();
EteSyncJournal *journal = etesync_journal_manager_fetch(journalManager, journalUid);
auto job = new EntriesFetchJob(etesync, journalUid, prevUid, this);
EteSyncCryptoManager *cryptoManager = etesync_journal_get_crypto_manager(journal, derived, keypair);
connect(job, &EntriesFetchJob::finished, this, [this](KJob *job) {
if (job->error()) {
qCWarning(ETESYNC_LOG) << "Error in fetching entries";
return;
}
EteSyncEntryManager *entryManager = etesync_entry_manager_new(etesync, journalUid);
Collection collection = currentCollection();
QString prevUid = collection.remoteRevision();
QString journalUid = collection.remoteId();
EteSyncEntry **entries = etesync_entry_manager_list(entryManager,