phonebookui/cntlistmodel/cntinfofetcher.cpp
changeset 81 640d30f4fb64
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/cntlistmodel/cntinfofetcher.cpp	Fri Oct 15 12:24:46 2010 +0300
@@ -0,0 +1,171 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Fetches visual info about contacts.
+*
+*/
+
+#include <QPluginLoader>
+#include <QDir>
+#include <qtcontacts.h>
+#include <cntinfofetcher.h>
+#include <cntinfoproviderfactory.h>
+#include <cntinfoprovider.h>
+#include <cntdefaultinfoprovider.h>
+#include <cntpresenceinfoprovider.h>
+#include <cntdebug.h>
+
+/*!
+    \class CntInfoCacheItem
+    \brief Cache item that holds some visual info about a contact.
+ */
+
+/*!
+    \class CntInfoFetcher
+    \brief CntInfoFetcher asynchronously fetches visual info about contacts.
+
+    CntInfoFetcher queues requests for contact info that is to be cached.
+    It fetches the info later, when asked by the client to do so.
+
+    There are three pieces of info that is fetched:
+      - secondary text, e.g. phone number
+      - primary icon, e.g. avatar for contact
+      - secondary icon, e.g. presence status
+
+    Internally CntInfoFetcher uses plugins (info providers) to fetch the data.
+ */
+
+// maximum amount of scheduled jobs; if there are more jobs, the least
+// important job is cancelled
+const int MaxInfoJobs = 20;
+
+// directory of info providers
+const char *CNT_INFO_PROVIDER_EXTENSION_PLUGIN_DIRECTORY = "/resource/qt/plugins/contacts/infoproviders/";
+
+/*!
+    Creates a CntIconFetcher object.
+ */
+CntInfoFetcher::CntInfoFetcher(QContactManager *contactManager)
+    : CntAbstractFetcher(MaxInfoJobs),
+      mContactManager(contactManager)
+{
+    CNT_ENTRY
+
+    // create static info provider plugins
+    mInfoProviders.insert(new CntDefaultInfoProvider(), ContactInfoAllFields);
+    mInfoProviders.insert(new CntPresenceInfoProvider(), ContactInfoIcon2Field);
+
+    // load dynamic info provider plugins
+    QDir pluginsDir(CNT_INFO_PROVIDER_EXTENSION_PLUGIN_DIRECTORY);
+    foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
+        // create plugin loader
+        QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
+        if (pluginLoader.load()) {
+            CntInfoProviderFactory *factory = qobject_cast<CntInfoProviderFactory*>(pluginLoader.instance());
+            if (factory) {
+                CntInfoProvider *provider = factory->infoProvider();
+                mInfoProviders.insert(provider, provider->supportedFields());
+            }
+        }
+    }
+
+    // connect the providers
+    QMapIterator<CntInfoProvider*, ContactInfoFields> i(mInfoProviders);
+    while (i.hasNext()) {
+        i.next();
+        connect(static_cast<CntInfoProvider*>(i.key()),
+                SIGNAL(infoFieldReady(CntInfoProvider*, int, ContactInfoField, const QString&)),
+                this,
+                SLOT(forwardInfoToClient(CntInfoProvider*, int, ContactInfoField, const QString&)));
+    }
+
+    CNT_EXIT
+}
+
+/*!
+    Cleans up and destructs the CntIconFetcher object.
+ */
+CntInfoFetcher::~CntInfoFetcher()
+{
+    CNT_ENTRY
+
+    qDeleteAll(mInfoProviders.keys());
+    mInfoProviders.clear();
+
+    CNT_EXIT
+}
+
+/*!
+    Processes the next scheduled job. This function must not be
+    called until the previous job has completed.
+ */
+void CntInfoFetcher::processNextJob()
+{
+    CNT_ENTRY
+
+    if (hasScheduledJobs()) {
+        // get the next job
+        CntInfoJob *job = static_cast<CntInfoJob *>(takeNextJob());
+
+        // fetch a QContact object
+        QContactFetchHint restrictions;
+        restrictions.setOptimizationHints(QContactFetchHint::NoRelationships);
+        QContact contact = mContactManager->contact(job->contactId, restrictions);
+        
+        // request contact info from providers
+        QMapIterator<CntInfoProvider*, ContactInfoFields> i(mInfoProviders);
+        while (i.hasNext()) {
+            i.next();
+            if (i.value() != 0) {
+                i.key()->requestInfo(contact, i.value());
+            }
+        }
+        
+        delete job;
+    } else if (hasCancelledJobs()) {
+        CntInfoJob *cancelledJob = static_cast<CntInfoJob *>(takeNextCancelledJob());
+        emit infoCancelled(cancelledJob->contactId);
+        delete cancelledJob;
+    }
+
+    CNT_EXIT
+}
+
+/*!
+    \return true if a job is currently being processed; otherwise returns false.
+ */
+bool CntInfoFetcher::isProcessingJob()
+{
+    return false;
+}
+
+/*!
+    Forward info from a provider to the client.
+ */
+void CntInfoFetcher::forwardInfoToClient(CntInfoProvider *sender,
+                                         int contactId,
+                                         ContactInfoField field,
+                                         const QString &text)
+{
+    CNT_ENTRY
+
+    // there can be 3rd party info providers, so we cannot blindly trust them;
+    // info is emitted iff:
+    if (mInfoProviders.contains(sender)
+        && ((field & (field - 1)) == 0)                         // 1) exactly one field bit is set in parameter 'field'
+        && ((field & mInfoProviders.value(sender)) != 0)) {     // 2) the field bit has been assigned to this provider
+        emit infoUpdated(contactId, field, text);
+    }
+
+    CNT_EXIT
+}