Skip to content
This repository has been archived by the owner on Sep 4, 2021. It is now read-only.

Commit

Permalink
Merge pull request #59 from matthewvogt/presence-updates
Browse files Browse the repository at this point in the history
[libcontacts] Handle presence updates independently
  • Loading branch information
matthewvogt committed Dec 10, 2013
2 parents 6d62371 + 5c43523 commit 2f52e1d
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 22 deletions.
98 changes: 77 additions & 21 deletions src/seasidecache.cpp
Expand Up @@ -33,8 +33,11 @@

#include "synchronizelists.h"

#include "qtcontacts-extensions_impl.h"
#include "qcontactstatusflags_impl.h"
#include <qtcontacts-extensions_impl.h>
#include <qcontactstatusflags_impl.h>
#include <contactmanagerengine.h>

#include <private/qcontactmanager_p.h>

#include <QCoreApplication>
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
Expand Down Expand Up @@ -96,17 +99,18 @@ QStringList getAllContactNameGroups()

QString managerName()
{
#ifdef USING_QTPIM
// Temporary override until qtpim supports QTCONTACTS_MANAGER_OVERRIDE
return QStringLiteral("org.nemomobile.contacts.sqlite");
#endif
QByteArray environmentManager = qgetenv("NEMO_CONTACT_MANAGER");
return !environmentManager.isEmpty()
? QString::fromLatin1(environmentManager, environmentManager.length())
: QString();
return QString::fromLatin1("org.nemomobile.contacts.sqlite");
}

QMap<QString, QString> managerParameters()
{
QMap<QString, QString> rv;
// Report presence changes independently from other contact changes
rv.insert(QString::fromLatin1("mergePresenceChanges"), QString::fromLatin1("false"));
return rv;
}

Q_GLOBAL_STATIC_WITH_ARGS(QContactManager, manager, (managerName()))
Q_GLOBAL_STATIC_WITH_ARGS(QContactManager, manager, (managerName(), managerParameters()))

typedef QList<DetailTypeId> DetailList;

Expand Down Expand Up @@ -169,6 +173,16 @@ QContactFetchHint basicFetchHint()
return fetchHint;
}

QContactFetchHint presenceFetchHint()
{
QContactFetchHint fetchHint(basicFetchHint());

setDetailTypesHint(fetchHint, DetailList() << detailType<QContactPresence>()
<< detailType<QContactGlobalPresence>());

return fetchHint;
}

QContactFetchHint metadataFetchHint(quint32 fetchTypes = 0)
{
QContactFetchHint fetchHint(basicFetchHint());
Expand Down Expand Up @@ -514,12 +528,19 @@ SeasideCache::SeasideCache()

QContactManager *mgr(manager());

// The contactsPresenceChanged signal is not exported by QContactManager, so we
// need to find it from the manager's engine object
typedef QtContactsSqliteExtensions::ContactManagerEngine EngineType;
EngineType *cme = dynamic_cast<EngineType *>(QContactManagerData::managerData(mgr)->m_engine);

#ifdef USING_QTPIM
connect(mgr, SIGNAL(dataChanged()), this, SLOT(updateContacts()));
connect(mgr, SIGNAL(contactsAdded(QList<QContactId>)),
this, SLOT(contactsAdded(QList<QContactId>)));
connect(mgr, SIGNAL(contactsChanged(QList<QContactId>)),
this, SLOT(contactsChanged(QList<QContactId>)));
connect(cme, SIGNAL(contactsPresenceChanged(QList<QContactId>)),
this, SLOT(contactsPresenceChanged(QList<QContactId>)));
connect(mgr, SIGNAL(contactsRemoved(QList<QContactId>)),
this, SLOT(contactsRemoved(QList<QContactId>)));
#else
Expand All @@ -528,6 +549,8 @@ SeasideCache::SeasideCache()
this, SLOT(contactsAdded(QList<QContactLocalId>)));
connect(mgr, SIGNAL(contactsChanged(QList<QContactLocalId>)),
this, SLOT(contactsChanged(QList<QContactLocalId>)));
connect(cme, SIGNAL(contactsPresenceChanged(QList<QContactLocalId>)),
this, SLOT(contactsPresenceChanged(QList<QContactLocalId>)));
connect(mgr, SIGNAL(contactsRemoved(QList<QContactLocalId>)),
this, SLOT(contactsRemoved(QList<QContactLocalId>)));
#endif
Expand Down Expand Up @@ -1485,7 +1508,27 @@ bool SeasideCache::event(QEvent *event)
// we only want to retrieve aggregate contacts that have changed
m_fetchRequest.setFilter(filter & aggregateFilter());
m_fetchRequest.setFetchHint(basicFetchHint());
m_fetchRequest.setSorting(m_sortOrder);
m_fetchRequest.start();

m_fetchProcessedCount = 0;
} else if (!m_presenceChangedContacts.isEmpty() && !m_fetchRequest.isActive()) {
const int maxRequestIds = 200;

#ifdef USING_QTPIM
QContactIdFilter filter;
#else
QContactLocalIdFilter filter;
#endif
if (m_presenceChangedContacts.count() > maxRequestIds) {
filter.setIds(m_presenceChangedContacts.mid(0, maxRequestIds));
m_presenceChangedContacts = m_presenceChangedContacts.mid(maxRequestIds);
} else {
filter.setIds(m_presenceChangedContacts);
m_presenceChangedContacts.clear();
}

m_fetchRequest.setFilter(filter & aggregateFilter());
m_fetchRequest.setFetchHint(presenceFetchHint());
m_fetchRequest.start();

m_fetchProcessedCount = 0;
Expand Down Expand Up @@ -1526,7 +1569,6 @@ bool SeasideCache::event(QEvent *event)
// as the favorites store, so we don't update any favorite with a smaller data subset
m_activeResolve = &resolve;
m_fetchRequest.setFetchHint(resolve.requireComplete ? basicFetchHint() : favoriteFetchHint(m_fetchTypes));
m_fetchRequest.setSorting(m_sortOrder);
m_fetchRequest.start();

m_fetchProcessedCount = 0;
Expand Down Expand Up @@ -1590,14 +1632,14 @@ void SeasideCache::timerEvent(QTimerEvent *event)
void SeasideCache::contactsAdded(const QList<ContactIdType> &ids)
{
if (m_keepPopulated) {
updateContacts(ids);
updateContacts(ids, &m_changedContacts);
}
}

void SeasideCache::contactsChanged(const QList<ContactIdType> &ids)
{
if (m_keepPopulated) {
updateContacts(ids);
updateContacts(ids, &m_changedContacts);
} else {
// Update these contacts if they're already in the cache
QList<ContactIdType> presentIds;
Expand All @@ -1606,7 +1648,23 @@ void SeasideCache::contactsChanged(const QList<ContactIdType> &ids)
presentIds.append(id);
}
}
updateContacts(presentIds);
updateContacts(presentIds, &m_changedContacts);
}
}

void SeasideCache::contactsPresenceChanged(const QList<ContactIdType> &ids)
{
if (m_keepPopulated) {
updateContacts(ids, &m_presenceChangedContacts);
} else {
// Update these contacts if they're already in the cache
QList<ContactIdType> presentIds;
foreach (const ContactIdType &id, ids) {
if (existingItem(id)) {
presentIds.append(id);
}
}
updateContacts(presentIds, &m_presenceChangedContacts);
}
}

Expand Down Expand Up @@ -1660,7 +1718,7 @@ void SeasideCache::updateContacts()
contactIds.append(it->apiId());
}

updateContacts(contactIds);
updateContacts(contactIds, &m_changedContacts);
}

void SeasideCache::fetchContacts()
Expand All @@ -1686,7 +1744,7 @@ void SeasideCache::fetchContacts()
}
}

void SeasideCache::updateContacts(const QList<ContactIdType> &contactIds)
void SeasideCache::updateContacts(const QList<ContactIdType> &contactIds, QList<ContactIdType> *updateList)
{
// Wait for new changes to be reported
static const int PostponementIntervalMs = 500;
Expand All @@ -1696,7 +1754,7 @@ void SeasideCache::updateContacts(const QList<ContactIdType> &contactIds)

if (!contactIds.isEmpty()) {
m_contactsUpdated = true;
m_changedContacts.append(contactIds);
updateList->append(contactIds);

if (m_fetchPostponed.isValid()) {
// We are waiting to accumulate further changes
Expand Down Expand Up @@ -1919,7 +1977,6 @@ void SeasideCache::contactsAvailable()
m_fetchProcessedCount += contacts.count();
fetchHint = m_fetchRequest.fetchHint();
}

if (contacts.isEmpty())
return;

Expand Down Expand Up @@ -2411,7 +2468,6 @@ void SeasideCache::requestStateChanged(QContactAbstractRequest::State state)
// Re-fetch the non-favorites
m_fetchRequest.setFilter(nonfavoriteFilter());
m_fetchRequest.setFetchHint(onlineFetchHint(m_fetchTypes));
m_fetchRequest.setSorting(m_sortOrder);
m_fetchRequest.start();
m_fetchProcessedCount = 0;

Expand Down
5 changes: 4 additions & 1 deletion src/seasidecache.h
Expand Up @@ -363,10 +363,12 @@ private slots:
#ifdef USING_QTPIM
void contactsAdded(const QList<QContactId> &contactIds);
void contactsChanged(const QList<QContactId> &contactIds);
void contactsPresenceChanged(const QList<QContactId> &contactIds);
void contactsRemoved(const QList<QContactId> &contactIds);
#else
void contactsAdded(const QList<QContactLocalId> &contactIds);
void contactsChanged(const QList<QContactLocalId> &contactIds);
void contactsPresenceChanged(const QList<QContactLocalId> &contactIds);
void contactsRemoved(const QList<QContactLocalId> &contactIds);
#endif
void displayLabelOrderChanged();
Expand Down Expand Up @@ -394,7 +396,7 @@ private slots:
void requestUpdate();
void appendContacts(const QList<QContact> &contacts, FilterType filterType, bool partialFetch, const QSet<DetailTypeId> &queryDetailTypes);
void fetchContacts();
void updateContacts(const QList<ContactIdType> &contactIds);
void updateContacts(const QList<ContactIdType> &contactIds, QList<ContactIdType> *updateList);
void applyPendingContactUpdates();
void applyContactUpdates(const QList<QContact> &contacts, bool partialFetch, const QSet<DetailTypeId> &queryDetailTypes);

Expand Down Expand Up @@ -441,6 +443,7 @@ private slots:
QList<QPair<QSet<DetailTypeId>, QList<QContact> > > m_contactsToUpdate;
QList<ContactIdType> m_contactsToRemove;
QList<ContactIdType> m_changedContacts;
QList<ContactIdType> m_presenceChangedContacts;
QSet<ContactIdType> m_aggregatedContacts;
QList<QContactId> m_contactsToFetchConstituents;
QList<QContactId> m_contactsToFetchCandidates;
Expand Down
13 changes: 13 additions & 0 deletions src/src.pro
Expand Up @@ -36,6 +36,19 @@ equals(QT_MAJOR_VERSION, 5) {

DEFINES += CONTACTCACHE_BUILD

# We need access to QtContacts private headers
QT += contacts-private

# We need the moc output for ContactManagerEngine from sqlite-extensions
equals(QT_MAJOR_VERSION, 4) {
extensionsIncludePath = $$system(pkg-config --cflags-only-I qtcontacts-sqlite-extensions)
}
equals(QT_MAJOR_VERSION, 5) {
extensionsIncludePath = $$system(pkg-config --cflags-only-I qtcontacts-sqlite-qt5-extensions)
}
VPATH += $$replace(extensionsIncludePath, -I, )
HEADERS += contactmanagerengine.h

SOURCES += \
$$PWD/seasidecache.cpp \
$$PWD/seasideimport.cpp \
Expand Down

0 comments on commit 2f52e1d

Please sign in to comment.