Skip to content

Commit

Permalink
[qtcontacts-sqlite] Add Request classes to provide asynchronous synch…
Browse files Browse the repository at this point in the history
…ronisation API. Contributes to JB#50551
  • Loading branch information
Chris Adams committed Sep 16, 2020
1 parent e44f1ab commit 393e561
Show file tree
Hide file tree
Showing 24 changed files with 2,986 additions and 959 deletions.
312 changes: 312 additions & 0 deletions src/engine/contactsengine.cpp
Expand Up @@ -41,6 +41,10 @@
#include "qtcontacts-extensions.h"
#include "qtcontacts-extensions_impl.h"
#include "qcontactdetailfetchrequest_p.h"
#include "qcontactcollectionchangesfetchrequest_p.h"
#include "qcontactchangesfetchrequest_p.h"
#include "qcontactchangessaverequest_p.h"
#include "qcontactclearchangeflagsrequest_p.h"
#include "displaylabelgroupgenerator.h"

#include <QCoreApplication>
Expand All @@ -51,6 +55,8 @@
#include <QUuid>
#include <QDataStream>

#include <QContactCollection>
#include <QContact>
#include <QContactAbstractRequest>
#include <QContactFetchRequest>
#include <QContactCollectionFetchRequest>
Expand Down Expand Up @@ -681,7 +687,273 @@ class DetailFetchJob : public TemplateJob<QContactDetailFetchRequest>
const QList<int> m_fields;
QList<QContactDetail> m_details;
const QContactDetail::DetailType m_type;
};

class CollectionChangesFetchJob : public TemplateJob<QContactCollectionChangesFetchRequest>
{
public:
CollectionChangesFetchJob(QContactCollectionChangesFetchRequest *request, QContactCollectionChangesFetchRequestPrivate *d)
: TemplateJob(request)
, m_accountId(d->accountId)
, m_applicationName(d->applicationName)
, m_addedCollections(d->addedCollections)
, m_modifiedCollections(d->modifiedCollections)
, m_removedCollections(d->removedCollections)
, m_unmodifiedCollections(d->unmodifiedCollections)
{
}

void execute(ContactReader *, WriterProxy &writer) override
{
m_error = writer->fetchCollectionChanges(
m_accountId,
m_applicationName,
&m_addedCollections,
&m_modifiedCollections,
&m_removedCollections,
&m_unmodifiedCollections);
}

void updateState(QContactAbstractRequest::State state) override
{
if (m_request) {
QContactCollectionChangesFetchRequestPrivate * const d = QContactCollectionChangesFetchRequestPrivate::get(m_request);

d->error = m_error;
d->state = state;

if (state == QContactAbstractRequest::FinishedState) {
d->addedCollections = m_addedCollections;
d->modifiedCollections = m_modifiedCollections;
d->removedCollections = m_removedCollections;
d->unmodifiedCollections = m_unmodifiedCollections;
emit (m_request->*(d->resultsAvailable))();
}
emit (m_request->*(d->stateChanged))(state);
}
}

QString description() const override
{
QString s(QLatin1String("Collection Changes Fetch"));
return s;
}

private:
const int m_accountId;
const QString m_applicationName;
QList<QContactCollection> m_addedCollections;
QList<QContactCollection> m_modifiedCollections;
QList<QContactCollection> m_removedCollections;
QList<QContactCollection> m_unmodifiedCollections;
};

class ContactChangesFetchJob : public TemplateJob<QContactChangesFetchRequest>
{
public:
ContactChangesFetchJob(QContactChangesFetchRequest *request, QContactChangesFetchRequestPrivate *d)
: TemplateJob(request)
, m_collectionId(d->collectionId)
, m_addedContacts(d->addedContacts)
, m_modifiedContacts(d->modifiedContacts)
, m_removedContacts(d->removedContacts)
, m_unmodifiedContacts(d->unmodifiedContacts)
{
}

void execute(ContactReader *, WriterProxy &writer) override
{
m_error = writer->fetchContactChanges(
m_collectionId,
&m_addedContacts,
&m_modifiedContacts,
&m_removedContacts,
&m_unmodifiedContacts);
}

void updateState(QContactAbstractRequest::State state) override
{
if (m_request) {
QContactChangesFetchRequestPrivate * const d = QContactChangesFetchRequestPrivate::get(m_request);

d->error = m_error;
d->state = state;

if (state == QContactAbstractRequest::FinishedState) {
d->addedContacts = m_addedContacts;
d->modifiedContacts = m_modifiedContacts;
d->removedContacts = m_removedContacts;
d->unmodifiedContacts = m_unmodifiedContacts;
emit (m_request->*(d->resultsAvailable))();
}
emit (m_request->*(d->stateChanged))(state);
}
}

QString description() const override
{
QString s(QLatin1String("Collection Changes Fetch"));
return s;
}

private:
const QContactCollectionId m_collectionId;
QList<QContact> m_addedContacts;
QList<QContact> m_modifiedContacts;
QList<QContact> m_removedContacts;
QList<QContact> m_unmodifiedContacts;
};

class ContactChangesSaveJob : public TemplateJob<QContactChangesSaveRequest>
{
public:
ContactChangesSaveJob(QContactChangesSaveRequest *request, QContactChangesSaveRequestPrivate *d)
: TemplateJob(request)
, m_addedCollections(d->addedCollections)
, m_modifiedCollections(d->modifiedCollections)
, m_removedCollections(d->removedCollections)
, m_policy(d->policy == QContactChangesSaveRequest::PreserveLocalChanges
? QtContactsSqliteExtensions::ContactManagerEngine::PreserveLocalChanges
: QtContactsSqliteExtensions::ContactManagerEngine::PreserveRemoteChanges)
, m_clearChangeFlags(d->clearChangeFlags)
{
}

void execute(ContactReader *, WriterProxy &writer) override
{
QList<QContactCollection> collections;
QList<QList<QContact> > contacts;
QHash<QContactCollection*, QList<QContact>* > addedCollections_ptrs;
QHash<QContactCollection*, QList<QContact>* > modifiedCollections_ptrs;

// the storeSyncChanges method parameters are in+out parameters.
// construct the appropriate data structures.
QHash<int, int> addedCollectionsIndexes;
QHash<int, int> modifiedCollectionsIndexes;
QHash<QContactCollection, QList<QContact> >::iterator ait, aend, mit, mend;
ait = m_addedCollections.begin(), aend = m_addedCollections.end();
for ( ; ait != aend; ++ait) {
addedCollectionsIndexes.insert(collections.size(), contacts.size());
collections.append(ait.key());
contacts.append(ait.value());
}
mit = m_modifiedCollections.begin(), mend = m_modifiedCollections.end();
for ( ; mit != mend; ++mit) {
modifiedCollectionsIndexes.insert(collections.size(), contacts.size());
collections.append(mit.key());
contacts.append(mit.value());
}

// do this as a second phase to avoid non-const operations causing potential detach
// and thus invalidating our references.
QHash<int, int>::const_iterator iit, iend;
iit = addedCollectionsIndexes.constBegin(), iend = addedCollectionsIndexes.constEnd();
for ( ; iit != iend; ++iit) {
addedCollections_ptrs.insert(&collections[iit.key()], &contacts[iit.value()]);
}
iit = modifiedCollectionsIndexes.constBegin(), iend = modifiedCollectionsIndexes.constEnd();
for ( ; iit != iend; ++iit) {
modifiedCollections_ptrs.insert(&collections[iit.key()], &contacts[iit.value()]);
}

m_error = writer->storeChanges(
&addedCollections_ptrs,
&modifiedCollections_ptrs,
m_removedCollections,
m_policy,
m_clearChangeFlags);

if (m_error == QContactManager::NoError) {
m_addedCollections.clear();
QHash<QContactCollection*, QList<QContact>* >::iterator ait, aend, mit, mend;
ait = addedCollections_ptrs.begin(), aend = addedCollections_ptrs.end();
for ( ; ait != aend; ++ait) {
m_addedCollections.insert(*ait.key(), *ait.value());
}
m_modifiedCollections.clear();
mit = modifiedCollections_ptrs.begin(), mend = modifiedCollections_ptrs.end();
for ( ; mit != mend; ++mit) {
m_modifiedCollections.insert(*mit.key(), *mit.value());
}
}
}

void updateState(QContactAbstractRequest::State state) override
{
if (m_request) {
QContactChangesSaveRequestPrivate * const d = QContactChangesSaveRequestPrivate::get(m_request);

d->error = m_error;
d->state = state;

if (state == QContactAbstractRequest::FinishedState) {
d->addedCollections = m_addedCollections;
d->modifiedCollections = m_modifiedCollections;
emit (m_request->*(d->resultsAvailable))();
}
emit (m_request->*(d->stateChanged))(state);
}
}

QString description() const override
{
QString s(QLatin1String("Changes Save"));
return s;
}

private:
QHash<QContactCollection, QList<QContact> > m_addedCollections;
QHash<QContactCollection, QList<QContact> > m_modifiedCollections;
QList<QContactCollectionId> m_removedCollections;
const QtContactsSqliteExtensions::ContactManagerEngine::ConflictResolutionPolicy m_policy;
const bool m_clearChangeFlags;
};

class ClearChangeFlagsJob : public TemplateJob<QContactClearChangeFlagsRequest>
{
public:
ClearChangeFlagsJob(QContactClearChangeFlagsRequest *request, QContactClearChangeFlagsRequestPrivate *d)
: TemplateJob(request)
, m_collectionId(d->collectionId)
, m_contactIds(d->contactIds)
{
}

void execute(ContactReader *, WriterProxy &writer) override
{
m_error = m_collectionId.isNull()
? writer->clearChangeFlags(
m_contactIds,
false)
: writer->clearChangeFlags(
m_collectionId,
false);
}

void updateState(QContactAbstractRequest::State state) override
{
if (m_request) {
QContactClearChangeFlagsRequestPrivate * const d = QContactClearChangeFlagsRequestPrivate::get(m_request);

d->error = m_error;
d->state = state;

if (state == QContactAbstractRequest::FinishedState) {
emit (m_request->*(d->resultsAvailable))();
}
emit (m_request->*(d->stateChanged))(state);
}
}

QString description() const override
{
QString s(QLatin1String("Clear Change Flags"));
return s;
}

private:
const QContactCollectionId m_collectionId;
const QList<QContactId> m_contactIds;
};

class JobThread : public QThread
Expand Down Expand Up @@ -1497,6 +1769,46 @@ bool ContactsEngine::startRequest(QContactDetailFetchRequest* request)
return true;
}

bool ContactsEngine::startRequest(QContactCollectionChangesFetchRequest* request)
{
Job *job = new CollectionChangesFetchJob(request, QContactCollectionChangesFetchRequestPrivate::get(request));

job->updateState(QContactAbstractRequest::ActiveState);
m_jobThread->enqueue(job);

return true;
}

bool ContactsEngine::startRequest(QContactChangesFetchRequest* request)
{
Job *job = new ContactChangesFetchJob(request, QContactChangesFetchRequestPrivate::get(request));

job->updateState(QContactAbstractRequest::ActiveState);
m_jobThread->enqueue(job);

return true;
}

bool ContactsEngine::startRequest(QContactChangesSaveRequest* request)
{
Job *job = new ContactChangesSaveJob(request, QContactChangesSaveRequestPrivate::get(request));

job->updateState(QContactAbstractRequest::ActiveState);
m_jobThread->enqueue(job);

return true;
}

bool ContactsEngine::startRequest(QContactClearChangeFlagsRequest* request)
{
Job *job = new ClearChangeFlagsJob(request, QContactClearChangeFlagsRequestPrivate::get(request));

job->updateState(QContactAbstractRequest::ActiveState);
m_jobThread->enqueue(job);

return true;
}

bool ContactsEngine::cancelRequest(QContactAbstractRequest* req)
{
return cancelRequest(static_cast<QObject *>(req));
Expand Down
4 changes: 4 additions & 0 deletions src/engine/contactsengine.h
Expand Up @@ -141,6 +141,10 @@ class ContactsEngine : public QtContactsSqliteExtensions::ContactManagerEngine
void requestDestroyed(QObject* request) override;
bool startRequest(QContactAbstractRequest* req) override;
bool startRequest(QContactDetailFetchRequest* request) override;
bool startRequest(QContactCollectionChangesFetchRequest* request) override;
bool startRequest(QContactChangesFetchRequest* request) override;
bool startRequest(QContactChangesSaveRequest* request) override;
bool startRequest(QContactClearChangeFlagsRequest* request) override;
bool cancelRequest(QContactAbstractRequest* req) override;
bool cancelRequest(QObject* request) override;
bool waitForRequestFinished(QContactAbstractRequest* req, int msecs) override;
Expand Down
1 change: 1 addition & 0 deletions src/extensions/QContactChangesFetchRequest
@@ -0,0 +1 @@
#include "./qcontactchangesfetchrequest.h"
1 change: 1 addition & 0 deletions src/extensions/QContactChangesSaveRequest
@@ -0,0 +1 @@
#include "./qcontactchangessaverequest.h"
1 change: 1 addition & 0 deletions src/extensions/QContactClearChangeFlagsRequest
@@ -0,0 +1 @@
#include "./qcontactclearchangeflagsrequest.h"
1 change: 1 addition & 0 deletions src/extensions/QContactCollectionChangesFetchRequest
@@ -0,0 +1 @@
#include "./qcontactcollectionchangesfetchrequest.h"
8 changes: 8 additions & 0 deletions src/extensions/contactmanagerengine.h
Expand Up @@ -37,6 +37,10 @@

QT_BEGIN_NAMESPACE_CONTACTS
class QContactDetailFetchRequest;
class QContactChangesFetchRequest;
class QContactCollectionChangesFetchRequest;
class QContactChangesSaveRequest;
class QContactClearChangeFlagsRequest;
QT_END_NAMESPACE_CONTACTS

QTCONTACTS_USE_NAMESPACE
Expand Down Expand Up @@ -119,6 +123,10 @@ class Q_DECL_EXPORT ContactManagerEngine

virtual void requestDestroyed(QObject* request) = 0;
virtual bool startRequest(QContactDetailFetchRequest* request) = 0;
virtual bool startRequest(QContactCollectionChangesFetchRequest* request) = 0;
virtual bool startRequest(QContactChangesFetchRequest* request) = 0;
virtual bool startRequest(QContactChangesSaveRequest* request) = 0;
virtual bool startRequest(QContactClearChangeFlagsRequest* request) = 0;
virtual bool cancelRequest(QObject* request) = 0;
virtual bool waitForRequestFinished(QObject* req, int msecs) = 0;

Expand Down

0 comments on commit 393e561

Please sign in to comment.