--- a/phonebookengines/cntlistmodel/src/cntcache_p.cpp Fri Oct 08 11:42:51 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,491 +0,0 @@
-/*
-* 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: Private data and helper classes used by class CntCache.
-*
-*/
-
-#include <QPluginLoader>
-#include <QDir>
-
-#include <qtcontacts.h>
-#include <qcontactmanager.h>
-#include <hbapplication.h>
-#include <thumbnailmanager_qt.h>
-#include <hbicon.h>
-#include <QTimer>
-
-#include "cntcache.h"
-#include "cntcache_p.h"
-#include <cntinfoproviderfactory.h>
-#include <cntinfoprovider.h>
-#include "cntdefaultinfoprovider.h"
-#include "cntpresenceinfoprovider.h"
-#include <cntdebug.h>
-
-// maximum amount of info and icon jobs respectively -- if there are more jobs,
-// then the oldest job is skipped and the client informed that this happened
-// in this way the client can request the job again if wanted
-static const int CntMaxInfoJobs = 20;
-static const int CntMaxIconJobs = 20;
-// the event for starting to process all outstanding jobs
-static const QEvent::Type ProcessJobsEvent = QEvent::User;
-// the id that states that no icon is currently pending from thumbnail manager
-static const int NoIconRequest = -1;
-// the id that states that there is no job with that key
-static const int NoSuchJob = -1;
-// different states of postponement
-static const int JobsNotPostponed = 0;
-static const int JobsPostponedForDuration = 1;
-static const int JobsPostponedUntilResume = 2;
-
-const char *CNT_INFO_PROVIDER_EXTENSION_PLUGIN_DIRECTORY = "/resource/qt/plugins/contacts/infoproviders/";
-
-// TODO: Provide a way (cenrep keys?) for UI to set which provider to use for
-// what info field (and what info fields are indeed even in use).
-
-/*!
- Creates a new thread for fetching contact info and icons in the background.
- */
-CntCacheThread::CntCacheThread()
- : mContactManager(new QContactManager()),
- mProcessingJobs(false),
- mJobsPostponed(JobsNotPostponed),
- mIconRequestId(NoIconRequest),
- mTimer(new QTimer())
-{
- CNT_ENTRY
-
- // create static provider plugins
- mInfoProviders.insert(new CntDefaultInfoProvider(), ContactInfoAllFields);
- mInfoProviders.insert(new CntPresenceInfoProvider(), ContactInfoIcon2Field);
-
- // load dynamic 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(onInfoFieldReady(CntInfoProvider*, int, ContactInfoField, const QString&)));
- }
-
- // create & connect the thumbnail manager
- mThumbnailManager = new ThumbnailManager(this);
- mThumbnailManager->setMode(ThumbnailManager::Default);
- mThumbnailManager->setQualityPreference(ThumbnailManager::OptimizeForPerformance);
- mThumbnailManager->setThumbnailSize(ThumbnailManager::ThumbnailSmall);
- connect(mThumbnailManager, SIGNAL(thumbnailReady(QPixmap, void *, int, int)),
- this, SLOT(onIconReady(QPixmap, void *, int, int)));
-
- mTimer->setSingleShot(true);
- connect(mTimer, SIGNAL(timeout()), this, SLOT(resumeJobs()));
-
- CNT_EXIT
-}
-
-/*!
- Cleans up and destructs the thread.
- */
-CntCacheThread::~CntCacheThread()
-{
- CNT_ENTRY
-
- delete mContactManager;
- disconnect(this);
-
- mInfoJobs.clear();
- mCancelledInfoJobs.clear();
- mIconJobs.clear();
- mCancelledIconJobs.clear();
-
- if (mIconRequestId != NoIconRequest) {
- mThumbnailManager->cancelRequest(mIconRequestId);
- mIconRequestId = NoIconRequest;
- }
-
- delete mThumbnailManager;
- mThumbnailManager = NULL;
-
- qDeleteAll(mInfoProviders.keys());
- mInfoProviders.clear();
-
- CNT_EXIT
-}
-
-/*!
- Schedules a info to be fetched for a contact. When info has been fetched
- infoFieldUpdated() signals will be emitted, once for each field.
-
- /param contactId the contact for which the info is wanted
- */
-void CntCacheThread::scheduleInfoJob(int contactId, int priority)
-{
- CNT_ENTRY_ARGS( contactId )
-
- if (contactId <= 0)
- return;
-
- int index = infoJobIndex(contactId);
- if (index != NoSuchJob) {
- // if the job already exists, update the priority
- if (priority < mInfoJobs.at(index).second) {
- mInfoJobs[index] = QPair<int,int>(contactId,priority);
- }
- return;
- }
-
- if (!mProcessingJobs) {
- // new job => start processing jobs
- mProcessingJobs = true;
- HbApplication::instance()->postEvent(this, new QEvent(ProcessJobsEvent));
- }
-
- if (mInfoJobs.count() >= CntMaxInfoJobs) {
- // the queue of jobs is full, so remove the oldest job
- mCancelledInfoJobs.append(mInfoJobs.takeFirst().first);
- CNT_LOG_ARGS( mCancelledInfoJobs.last() << "removed from joblist" )
- }
-
- mInfoJobs.append(QPair<int,int>(contactId, priority));
- CNT_LOG_ARGS( contactId << "(prio:" << priority << ") appended @" << (mInfoJobs.count() - 1) );
-
- // since this job has now been scheduled, remove it from the list of
- // cancelled jobs in case it is there
- mCancelledInfoJobs.removeOne(contactId);
-
- CNT_EXIT
-}
-
-/*!
- Schedules an icon to be fetched. An iconUpdated() signal will be emitted when the icon
- has been fetched.
-
- /param iconName the name of the icon to be fetched
- */
-void CntCacheThread::scheduleIconJob(const QString& iconName, int priority)
-{
- CNT_ENTRY_ARGS( iconName )
-
- if (iconName.isEmpty())
- return;
-
- int index = iconJobIndex(iconName);
- if (index != NoSuchJob) {
- // if the job already exists, update the priority
- if (priority < mIconJobs.at(index).second) {
- mIconJobs[index] = QPair<QString,int>(iconName,priority);
- }
- return;
- }
-
- if (!mProcessingJobs) {
- // new job, so restart job loop
- mProcessingJobs = true;
- HbApplication::instance()->postEvent(this, new QEvent(ProcessJobsEvent));
- }
-
- if (mIconJobs.count() >= CntMaxIconJobs) {
- // the queue of jobs is full, so remove the oldest job
- mCancelledIconJobs.append(mIconJobs.takeLast().first);
- CNT_LOG_ARGS( mCancelledIconJobs.last() << "removed from joblist" );
- }
-
- mIconJobs.append(QPair<QString,int>(iconName, priority));
- CNT_LOG_ARGS( iconName << "(prio:" << priority << ") appended @" << (mIconJobs.count() - 1) );
-
- // since this job has now been rescheduled, remove it from the list of
- // cancelled jobs in case it is there
- mCancelledIconJobs.removeOne(iconName);
-
- CNT_EXIT
-}
-
-/*!
- Postpones outstanding jobs until milliseconds ms has passed or resumeJobs() is called.
- This should be called if the client wants to reserve more CPU time for some urgent tasks.
-
- \param milliseconds The duration of the delay; 0, which is the default, means to delay
- until resumeJobs() is called
- */
-void CntCacheThread::postponeJobs(int milliseconds)
-{
- CNT_ENTRY_ARGS("ms =" << milliseconds << " type =" << mJobsPostponed)
-
- Q_ASSERT(milliseconds >= 0);
-
- if (milliseconds == 0) {
- mTimer->stop();
- mJobsPostponed = JobsPostponedUntilResume;
- } else if (mJobsPostponed != JobsPostponedUntilResume) {
- mTimer->stop();
- mJobsPostponed = JobsPostponedForDuration;
- mTimer->start(milliseconds);
- }
-
- CNT_EXIT
-}
-
-/*!
- Postpones outstanding jobs until resumeJobs() is called. This must always be called after
- postponeJobs.
- */
-void CntCacheThread::resumeJobs()
-{
- CNT_ENTRY
-
- mTimer->stop();
- mJobsPostponed = JobsNotPostponed;
- HbApplication::instance()->postEvent(this, new QEvent(ProcessJobsEvent));
-
- CNT_EXIT
-}
-
-/*!
- Handles a class-specific event that is sent by the scheduleOrUpdate functions
- when there are jobs.
- */
-bool CntCacheThread::event(QEvent* event)
-{
- if (event->type() == ProcessJobsEvent) {
- processJobs();
- return true;
- }
-
- return QObject::event(event);
-}
-
-/*!
- Processes all scheduled jobs. The loop runs until all jobs are done.
- It pauses for a while if new info jobs appear -- this means that the
- UI is updating and so the CPU is yielded to the UI. If there are
- again new jobs after the pause, then it pauses again, and so on.
- */
-void CntCacheThread::processJobs()
-{
- CNT_ENTRY
-
- bool hasDoneJobs = false;
-
- forever {
- int infoJobs = mInfoJobs.count();
- int iconJobs = mIconJobs.count();
- int totalJobs = infoJobs + iconJobs + mCancelledInfoJobs.count() + mCancelledIconJobs.count();
-
- if (totalJobs == 0 || totalJobs == iconJobs && mIconRequestId != NoIconRequest || mJobsPostponed != JobsNotPostponed) {
- if (mJobsPostponed == JobsNotPostponed || totalJobs == 0) {
- mProcessingJobs = false;
- }
-
- if (totalJobs == 0 && hasDoneJobs) {
- emit allJobsDone();
- }
-
- break;
- }
-
- if (infoJobs > 0) {
- // get next job
- int contactId = takeNextInfoJob();
-
- // fetch qcontact
- QContactFetchHint restrictions;
- restrictions.setOptimizationHints(QContactFetchHint::NoRelationships);
- QContact contact = mContactManager->contact(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());
- }
- }
- }
- else if (iconJobs > 0 && mIconRequestId == NoIconRequest) {
- // request icon from thumbnail manager
- QString iconName = takeNextIconJob();
- mIconRequestId = mThumbnailManager->getThumbnail(iconName, NULL, 0);
- mIconRequestName = iconName;
- }
- else {
- if (mCancelledInfoJobs.count() > 0) {
- int contactId = mCancelledInfoJobs.takeLast();
- emit infoCancelled(contactId);
- }
- else if (mCancelledIconJobs.count() > 0) {
- QString iconName = mCancelledIconJobs.takeFirst();
- emit iconCancelled(iconName);
- }
- }
-
- hasDoneJobs = true;
-
- // allow signals to be passed from providers and from the client
- HbApplication::processEvents();
- }
-
- CNT_EXIT
-}
-
-/*!
- Passes an info field from a data provider up to the client via signals. The
- client is not in the same thread, so Qt passes the signal as an event.
- */
-void CntCacheThread::onInfoFieldReady(CntInfoProvider* sender, int contactId,
- ContactInfoField field, const QString& text)
-{
- CNT_ENTRY
-
- // there can be 3rd party providers, so we cannot blindly trust them;
- // info is emitted only if:
- // 1) the sender is in the list of providers
- // 2) exactly one field bit is set in parameter 'field'
- // 3) the field bit has been assigned to this provider
- if (mInfoProviders.contains(sender)
- && ((field & (field - 1)) == 0)
- && ((field & mInfoProviders.value(sender)) != 0)) {
- emit infoFieldUpdated(contactId, field, text);
- }
-
- CNT_EXIT
-}
-
-/*!
- Passes an icon from thumbnail manager up to the client via a signal. The
- client is not in the same thread, so Qt passes the signal as an event.
- */
-void CntCacheThread::onIconReady(const QPixmap& pixmap, void *data, int id, int error)
-{
- CNT_ENTRY
-
- Q_UNUSED(id);
- Q_UNUSED(data);
-
- Q_ASSERT(id == mIconRequestId && !mIconRequestName.isEmpty());
- if (!mProcessingJobs) {
- // job loop quit while waiting for this icon, so restart it
- mProcessingJobs = true;
- HbApplication::instance()->postEvent(this, new QEvent(ProcessJobsEvent));
- }
- mIconRequestId = NoIconRequest;
-
- if (error == 0) {
- emit iconUpdated(mIconRequestName, HbIcon(pixmap));
- }
-
- CNT_EXIT
-}
-
-/*!
- Finds out the index of an info job in the job list.
-
- \return index of the contact in the job list, or NoSuchJob if no job is scheduled for the contact
- */
-int CntCacheThread::infoJobIndex(int contactId)
-{
- int jobCount = mInfoJobs.count();
- for (int i = 0; i < jobCount; ++i) {
- if (mInfoJobs.at(i).first == contactId) {
- return i;
- }
- }
-
- return NoSuchJob;
-}
-
-/*!
- Picks the next job from the info job list (the one with the highest priority).
-
- \return the id of the contact for which the info should be fetched
- */
-int CntCacheThread::takeNextInfoJob()
-{
- int selectionIndex = -1;
- int selectionPriority = -1;
-
- int jobCount = mInfoJobs.count();
- if (jobCount == 0) {
- return NoSuchJob;
- }
-
- for (int i = 0; i < jobCount; ++i) {
- int jobPriority = mInfoJobs.at(i).second;
- if (jobPriority < selectionPriority || selectionPriority == -1) {
- selectionIndex = i;
- selectionPriority = jobPriority;
- }
- }
-
- return mInfoJobs.takeAt(selectionIndex).first;
-}
-
-/*!
- Picks the next job from the icon job list (the one with the highest priority).
-
- \return the name of the icon that should be fetched
- */
-QString CntCacheThread::takeNextIconJob()
-{
- int selectionIndex = -1;
- int selectionPriority = -1;
-
- int jobCount = mIconJobs.count();
- if (jobCount == 0) {
- return QString();
- }
-
- for (int i = 0; i < jobCount; ++i) {
- int jobPriority = mIconJobs.at(i).second;
- if (jobPriority < selectionPriority || selectionPriority == -1) {
- selectionIndex = i;
- selectionPriority = jobPriority;
- }
- }
-
- return mIconJobs.takeAt(selectionIndex).first;
-}
-
-/*!
- Finds out the index of an icon job in the job list.
-
- \return index of the icon in the job list, or NoSuchJob if a job for the icon is not scheduled.
- */
-int CntCacheThread::iconJobIndex(QString iconName)
-{
- int jobCount = mIconJobs.count();
- for (int i = 0; i < jobCount; ++i) {
- if (mIconJobs.at(i).first == iconName) {
- return i;
- }
- }
-
- return NoSuchJob;
-}
-
-