phonebookengines/mobcntmodel/src/cntcache.cpp
changeset 37 fd64c38c277d
equal deleted inserted replaced
31:2a11b5b00470 37:fd64c38c277d
       
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: Class for asynchronously fetching and caching basic
       
    15 *              contact info (see CntContactInfo) for list views.
       
    16 *
       
    17 */
       
    18 
       
    19 #include <hbapplication.h>
       
    20 #include <qtcontacts.h>
       
    21 #include <qcontactmanager.h>
       
    22 #include "cntcache.h"
       
    23 #include "cntcache_p.h"
       
    24 #include "cntinfoprovider.h"
       
    25 
       
    26 // set the singleton instance pointer to NULL
       
    27 CntCache* CntCache::mInstance = NULL;
       
    28 
       
    29 // value for first cache order to be assigned
       
    30 static const int CacheOrderStartValue = 1;
       
    31 // for avoiding wrap around with cache orders
       
    32 static const int MaxCacheOrderValue = 10000000;
       
    33 // number of items to read ahead into cache; this number is for one direction
       
    34 static const int ItemsToCacheAhead = 24;
       
    35 // cache size for info items (name, text, icon1name, icon2name)
       
    36 static const int InfoCacheSize = 128;
       
    37 // cache size for icon items (iconName and HbIcon)
       
    38 static const int IconCacheSize = 50;
       
    39 // number of icons in a CntContactInfo object
       
    40 static const int IconsInCntContactInfo = 2;
       
    41 // default empty text info field for a contact; it cannot be empty
       
    42 // as the listview will then ignore it, causing rendering problems
       
    43 static const QString EmptyTextField = " ";
       
    44 
       
    45 /*!
       
    46     Provides a pointer to the CntCache singleton instance.
       
    47  */
       
    48 CntCache* CntCache::instance()
       
    49 {
       
    50     if (mInstance == NULL) {
       
    51         mInstance = new CntCache();
       
    52     }
       
    53 
       
    54     return mInstance;
       
    55 }
       
    56 
       
    57 /*!
       
    58     Creates the CntCache singleton instance.
       
    59  */
       
    60 CntCache::CntCache()
       
    61     : mContactManager(new QContactManager()),
       
    62       mWorker(new CntCacheThread()),
       
    63       mNextInfoCacheOrder(CacheOrderStartValue),
       
    64       mNextIconCacheOrder(CacheOrderStartValue),
       
    65       mEmittedContactId(-1)
       
    66 {
       
    67     DP_IN("CntCache::CntCache()");
       
    68 
       
    69     // listen to worker updates
       
    70     connect(mWorker, SIGNAL(infoFieldUpdated(int, const ContactInfoField&, const QString&)),
       
    71             this, SLOT(onNewInfo(int, const ContactInfoField&, const QString&)));
       
    72     connect(mWorker, SIGNAL(iconUpdated(const QString&, const HbIcon&)),
       
    73             this, SLOT(onNewIcon(const QString&, const HbIcon&)));
       
    74     connect(mWorker, SIGNAL(infoCancelled(int)), this, SLOT(onInfoCancelled(int)));
       
    75     connect(mWorker, SIGNAL(iconCancelled(const QString&)), this, SLOT(onIconCancelled(const QString&)));
       
    76     connect(mWorker, SIGNAL(allJobsDone()), this, SLOT(scheduleOneReadAheadItem()));
       
    77 
       
    78     // listen to the database for changes to contacts
       
    79     connect(mContactManager, SIGNAL(contactsChanged(const QList<QContactLocalId>&)), this, SLOT(removeContactsFromCache(const QList<QContactLocalId>&)));
       
    80     connect(mContactManager, SIGNAL(contactsRemoved(const QList<QContactLocalId>&)), this, SLOT(removeContactsFromCache(const QList<QContactLocalId>&)));
       
    81 
       
    82     // shutdown only when the whole application shuts down
       
    83     connect(HbApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(onShutdown()));
       
    84 
       
    85     DP_OUT("CntCache::CntCache()");
       
    86 }
       
    87 
       
    88 /*!
       
    89     Destructs the CntCache singleton instance.
       
    90  */
       
    91 CntCache::~CntCache()
       
    92 {
       
    93     DP_IN("CntCache::~CntCache()");
       
    94 
       
    95     delete mWorker;
       
    96     delete mContactManager;
       
    97 
       
    98     DP_OUT("CntCache::~CntCache()");
       
    99 }
       
   100 
       
   101 /*! 
       
   102     Fetches information about a contact: name, text (e.g. phone number or
       
   103     social status) and two icons (e.g. avatar, presence). Previously cached
       
   104     content - at the very least the name - will be returned immediately.
       
   105     Availability of more information will be checked asynchronously and
       
   106     sent to clients via contactInfoUpdated() signals.
       
   107       
       
   108     The function takes a row and a list rather than just a contact id because
       
   109     of read ahead caching - contacts near the requested contacts are expected
       
   110     to be needed soon and are therefore also scheduled for caching.
       
   111 
       
   112     \param row the row of the contact to fetch
       
   113     \param idList a list with all the IDs in the list
       
   114     \return a contact with some details filled in
       
   115  */
       
   116 CntContactInfo CntCache::fetchContactInfo(int row, const QList<QContactLocalId>& idList)
       
   117 {
       
   118     DP_IN("CntCache::fetchContactInfo(" << row << ", idlist[" << idList.count() << "])");
       
   119 
       
   120     Q_ASSERT(row >= 0 && row < idList.count());
       
   121 
       
   122     QString name;
       
   123     QString text = EmptyTextField;
       
   124     HbIcon icons[IconsInCntContactInfo];
       
   125 
       
   126     int contactId = idList.at(row);
       
   127 
       
   128     if (contactId != mEmittedContactId) {
       
   129         // this request comes from the UI in response to some scrolling activity =>
       
   130         // 1) postpone all jobs so the UI can use as much of the CPU as possible
       
   131         // 2) update read ahead cache to contain all IDs of all items near this item
       
   132         mWorker->postponeJobs();
       
   133         updateReadAheadCache(row, idList);
       
   134     }
       
   135 
       
   136     // fetch contact
       
   137     if (mInfoCache.contains(contactId)) {
       
   138         // the item is in the cache
       
   139         CntInfoCacheItem* infoItem = mInfoCache.value(contactId);
       
   140         for (int i = 0; i < IconsInCntContactInfo; ++i) {
       
   141             QString iconName = infoItem->icons[i];
       
   142             if (!iconName.isEmpty()) {
       
   143                 if (mIconCache.contains(iconName)) {
       
   144                     CntIconCacheItem* iconItem = mIconCache.value(iconName);
       
   145                     iconItem->cacheOrder = mNextIconCacheOrder++;
       
   146                     icons[i] = iconItem->icon;
       
   147                     if (!iconItem->isFetched) {
       
   148                         // if icon has not yet been received from backend, add
       
   149                         // this id to the list of contacts that want to be
       
   150                         // notified when the icon is received
       
   151                         iconItem->contactIds.insert(contactId);
       
   152                     }
       
   153                 }
       
   154                 else {
       
   155                     // needed icon is not in cache, so schedule it for retrieval
       
   156                     CntIconCacheItem* iconItem = createIconCacheItem(iconName);
       
   157                     iconItem->contactIds.insert(contactId);
       
   158                     mWorker->scheduleIconJob(iconName);
       
   159                 }
       
   160             }
       
   161         }
       
   162 
       
   163         // update cache order
       
   164         infoItem->cacheOrder = mNextInfoCacheOrder++;
       
   165 
       
   166         name = infoItem->name;
       
   167         text = infoItem->text;
       
   168     }
       
   169     else {
       
   170         // the item is not in cache, so fetch the name and schedule the rest
       
   171         // of the info for retrieval
       
   172         if (fetchContactName(contactId, name)) {
       
   173             // contact found, so add new entry to cache
       
   174             CntInfoCacheItem* item = createInfoCacheItem(contactId);
       
   175             item->name = name;
       
   176             item->text = text;
       
   177 
       
   178             // ask the worker thread to fetch the information asynchronously
       
   179             mWorker->scheduleInfoJob(contactId);
       
   180         }
       
   181     }
       
   182 
       
   183     // cache read-ahead -- items near this fetched item should also be in cache
       
   184     // updateReadAhead(row, idList);
       
   185 
       
   186     DP_OUT("CntCache::fetchContactInfo(" << row << ", idlist[" << idList.count() << "]) : name =" << name);
       
   187 
       
   188     return CntContactInfo(contactId, name, text, icons[0], icons[1]);
       
   189 }
       
   190 
       
   191 /*! 
       
   192     Clears the cache - both names and icons. This function can be useful
       
   193     for example if application goes to the background and memory needs to
       
   194     be freed, or if the format of contact names change.
       
   195  */
       
   196 void CntCache::clearCache()
       
   197 {
       
   198     DP_IN("CntCache::clearCache()");
       
   199 
       
   200     // clear info cache
       
   201     foreach (CntInfoCacheItem* item, mInfoCache) {
       
   202         delete item;
       
   203     }
       
   204     mInfoCache.clear();
       
   205     mNextInfoCacheOrder = CacheOrderStartValue;
       
   206 
       
   207     // clear icon cache
       
   208     foreach (CntIconCacheItem* item, mIconCache) {
       
   209         delete item;
       
   210     }
       
   211     mIconCache.clear();
       
   212     mNextIconCacheOrder = CacheOrderStartValue;
       
   213 
       
   214     DP_OUT("CntCache::clearCache()");
       
   215 }
       
   216 
       
   217 /*! 
       
   218     Processes a new info field that has arrived from the worker thread.
       
   219     If the contact is in the info cache, then the info cache is updated
       
   220     accordingly.
       
   221     
       
   222     A contactInfoUpdated() signal is usually also emitted. The exception
       
   223     is if the info is the name of an icon and that icon is not in the icon
       
   224     cache. In this case the icon is fetched before a signal is emitted.
       
   225  */
       
   226 void CntCache::onNewInfo(int contactId, const ContactInfoField& infoField, const QString& infoValue)
       
   227 {
       
   228     DP_IN("CntCache::onNewInfo(" << contactId << "," << infoField << "," << infoValue << ")");
       
   229 
       
   230     Q_ASSERT(infoField == ContactInfoTextField || infoField == ContactInfoIcon1Field || infoField == ContactInfoIcon2Field);
       
   231 
       
   232     bool hasNewInfo;
       
   233 
       
   234     if (!mInfoCache.contains(contactId)) {
       
   235         // contact is not in cache, so nothing needs to be done
       
   236         // except notify clients that this contact has (possibly)
       
   237         // been changed
       
   238         hasNewInfo = true;
       
   239     }
       
   240     else if (infoField == ContactInfoTextField) {
       
   241         // update cache with new text for contact
       
   242         if (!infoValue.isEmpty())
       
   243             mInfoCache.value(contactId)->text = infoValue;
       
   244         else
       
   245             mInfoCache.value(contactId)->text = " ";
       
   246         hasNewInfo = true;
       
   247     }
       
   248     else {
       
   249         // update cache with new icon name for contact
       
   250         int iconIndex = (infoField == ContactInfoIcon1Field ? 0 : 1);
       
   251 
       
   252         CntInfoCacheItem* item = mInfoCache.value(contactId);
       
   253         QString iconName = infoValue;
       
   254         if (item->icons[iconIndex] != iconName) {
       
   255             item->icons[iconIndex] = iconName;
       
   256             if (iconName.isEmpty()) {
       
   257                 hasNewInfo = true;
       
   258             }
       
   259             else if (mIconCache.contains(iconName)) {
       
   260                 CntIconCacheItem* iconItem = mIconCache.value(iconName);
       
   261                 if (!iconItem->isFetched) {
       
   262                     iconItem->contactIds.insert(contactId);
       
   263                     hasNewInfo = false;
       
   264                 }
       
   265                 else {
       
   266                     hasNewInfo = true;
       
   267                 }
       
   268             }
       
   269             else {
       
   270                CntIconCacheItem* iconItem = createIconCacheItem(iconName);
       
   271                iconItem->contactIds.insert(contactId);
       
   272                mWorker->scheduleIconJob(iconName);
       
   273                hasNewInfo = false;
       
   274             }
       
   275         }
       
   276         else {
       
   277             hasNewInfo = false;
       
   278         }
       
   279     }
       
   280 
       
   281     if (hasNewInfo) {
       
   282         DP("CntCache::onNewInfo() : new info => emitting contactInfoUpdated(" << contactId << ")");
       
   283         emitContactInfoUpdated(contactId);
       
   284     }
       
   285 
       
   286     DP_OUT("CntCache::onNewInfo(" << contactId << "," << infoField << "," << infoValue << ")");
       
   287 }
       
   288 
       
   289 /*! 
       
   290     Handle the case where a request for contact info is cancelled by the
       
   291     worker because of too many subsequent requests.
       
   292  */
       
   293 void CntCache::onInfoCancelled(int contactId)
       
   294 {
       
   295     DP_IN("CntCache::onInfoCancelled(" << contactId << ")");
       
   296 
       
   297     if (mInfoCache.contains(contactId)) {
       
   298         CntInfoCacheItem* item = mInfoCache.take(contactId);
       
   299         delete item;
       
   300     }
       
   301 
       
   302     DP("CntCache::onInfoCancelled() : info cancelled => emitting contactInfoUpdated(" << contactId << ")");
       
   303     emitContactInfoUpdated(contactId);
       
   304 
       
   305     DP_OUT("CntCache::onInfoCancelled(" << contactId << ")");
       
   306 }
       
   307 
       
   308 /*! 
       
   309     Processes a new icon that has arrived from the worker thread.
       
   310     The icon cache is updated and a contactInfoUpdated() signal is
       
   311     emitted for all contacts that use this icon.
       
   312  */
       
   313 void CntCache::onNewIcon(const QString& iconName, const HbIcon& icon)
       
   314 {
       
   315     DP_IN("CntCache::onNewIcon(" << iconName << ", HbIcon)");
       
   316 
       
   317     QSet<int> contactsToNotify;
       
   318 
       
   319     if (mIconCache.contains(iconName)) {
       
   320         CntIconCacheItem* item = mIconCache.value(iconName);
       
   321         item->icon = icon;
       
   322         item->isFetched = true;
       
   323         contactsToNotify = item->contactIds;
       
   324         item->contactIds.clear();
       
   325     }
       
   326 
       
   327     foreach (int contactId, contactsToNotify) {
       
   328         DP("CntCache::onNewIcon() : new icon => emitting contactInfoUpdated(" << contactId << ")");
       
   329         emitContactInfoUpdated(contactId);
       
   330     }
       
   331 
       
   332     DP_OUT("CntCache::onNewIcon(" << iconName << ", HbIcon)");
       
   333 }
       
   334 
       
   335 /*! 
       
   336     Handle the case where a request for an icon is cancelled by the worker because
       
   337     of too many subsequent requests.
       
   338  */
       
   339 void CntCache::onIconCancelled(const QString& iconName)
       
   340 {
       
   341     DP_IN("CntCache::onIconCancelled(" << iconName << ")");
       
   342 
       
   343     QSet<int> contactsToNotify;
       
   344 
       
   345     if (mIconCache.contains(iconName)) {
       
   346         CntIconCacheItem* item = mIconCache.take(iconName);
       
   347         contactsToNotify = item->contactIds;
       
   348         item->contactIds.clear();
       
   349         delete item;
       
   350     }
       
   351 
       
   352     foreach (int contactId, contactsToNotify) {
       
   353         DP("CntCache::onIconCancelled() : icon cancelled => emitting contactInfoUpdated(" << contactId << ")");
       
   354         emitContactInfoUpdated(contactId);
       
   355     }
       
   356 
       
   357     DP_OUT("CntCache::onIconCancelled(" << iconName << ")");
       
   358 }
       
   359 
       
   360 /*! 
       
   361     Removes contacts from cache.
       
   362     
       
   363     /param contactIds ids of the contact that will be removed
       
   364  */
       
   365 void CntCache::removeContactsFromCache(const QList<QContactLocalId>& contactIds)
       
   366 {
       
   367     DP_IN("CntCache::removeContactsFromCache(idList[" << contactIds.count() << "])");
       
   368 
       
   369     foreach (QContactLocalId contactId, contactIds) {
       
   370         if (mInfoCache.contains(contactId)) {
       
   371             CntInfoCacheItem* item = mInfoCache.take(contactId);
       
   372             delete item;
       
   373         }
       
   374     }
       
   375 
       
   376     foreach (QContactLocalId contactId, contactIds) {
       
   377         emitContactInfoUpdated(contactId);
       
   378     }
       
   379 
       
   380     DP_OUT("CntCache::removeContactsFromCache(idList[" << contactIds.count() << "])");
       
   381 }
       
   382 
       
   383 /*! 
       
   384     Uses an optimized function to fetch the name of a contact from
       
   385     the database.
       
   386 
       
   387     /param contactId the id of the contact to fetch
       
   388     /param contactName the name will be stored here if the function is successful
       
   389     /return true if the name was fetched successfully
       
   390  */
       
   391 bool CntCache::fetchContactName(int contactId, QString& contactName)
       
   392 {
       
   393     bool foundContact = false;
       
   394     DP_IN("CntCache::fetchContactName(" << contactId << "," << contactName << ")");
       
   395 
       
   396     QContactFetchHint nameOnlyFetchHint;
       
   397     QStringList details;
       
   398     details << QContactDisplayLabel::DefinitionName;
       
   399     nameOnlyFetchHint.setDetailDefinitionsHint(details);
       
   400     QContact contact = mContactManager->contact(contactId, nameOnlyFetchHint);
       
   401     
       
   402     if (mContactManager->error() == QContactManager::NoError) {
       
   403         contactName = contact.displayLabel();
       
   404         foundContact = true;
       
   405         // TODO: this can be removed once qt mobility is updated (~wk20/10)
       
   406         if (contactName == "Unnamed") {
       
   407             contactName = "";
       
   408         }
       
   409     }
       
   410     
       
   411     DP_OUT("CntCache::fetchContactName(" << contactId << "," << contactName << ") : " << foundContact);
       
   412     
       
   413     return foundContact;
       
   414 }
       
   415 
       
   416 /*! 
       
   417     Collects all contact IDs near the latest fetch from the UI. These will be fetched and
       
   418     precached when UI activity slows down.
       
   419 
       
   420     \param mostRecentRow the row of the contact that was most recently fetched
       
   421     \param idList a list with all the IDs in the list
       
   422  */
       
   423 void CntCache::updateReadAheadCache(int mostRecentRow, const QList<QContactLocalId>& idList)
       
   424 {
       
   425     DP_IN("CntCache::updateReadAheadCache(" << mostRecentRow << ", idList[" << idList.count() << "] )");
       
   426     int row;
       
   427 
       
   428     mReadAheadCache.clear();
       
   429     
       
   430     // step through the area near to last fetch item and make sure all
       
   431     // contacts in it are also in cache or in the read ahead list
       
   432     for (int i = 1; i <= ItemsToCacheAhead; ++i) {
       
   433         for (int j = 0; j < 2; ++j) {
       
   434             if (j == 0) {
       
   435                 row = mostRecentRow - i;
       
   436                 if (row <= 0) {
       
   437                     continue;
       
   438                 }
       
   439             }
       
   440             else {
       
   441                 row = mostRecentRow + i;
       
   442                 if (row >= idList.count()) {
       
   443                     continue;
       
   444                 }
       
   445             }
       
   446             
       
   447             int contactId = idList.at(row);
       
   448             if (!mInfoCache.contains(contactId)) {
       
   449                 // contact is not in cache, so put the id to items to read into cache
       
   450                 mReadAheadCache.append(contactId);
       
   451             }
       
   452             else {
       
   453                 // contact is in cache; update cache order as we want to keep this item in cache
       
   454                 mInfoCache.value(contactId)->cacheOrder = mNextInfoCacheOrder++;
       
   455             }
       
   456         }
       
   457     }
       
   458 
       
   459     DP_OUT("CntCache::updateReadAheadCache(" << mostRecentRow << ", idList[" << idList.count() << "] )");
       
   460 }
       
   461 
       
   462 /*! 
       
   463     Schedules one uncached item in the read-ahead list for retrieval.
       
   464  */
       
   465 void CntCache::scheduleOneReadAheadItem()
       
   466 {
       
   467     DP_IN("CntCache::scheduleOneReadAheadItem()");
       
   468 
       
   469     QString name;
       
   470     
       
   471     while (mReadAheadCache.count() > 0) {
       
   472         int contactId = mReadAheadCache.takeFirst();
       
   473         if (!mInfoCache.contains(contactId)) {
       
   474             // contact is not in cache, so schedule it for retreival
       
   475             if (fetchContactName(contactId, name)) {
       
   476                 // contact found, so add new entry to cache
       
   477                 CntInfoCacheItem* item = createInfoCacheItem(contactId);
       
   478                 item->name = name;
       
   479                 item->text = EmptyTextField;
       
   480     
       
   481                 // schedule the info for retrieval
       
   482                 mWorker->scheduleInfoJob(contactId);
       
   483                 break;
       
   484             }
       
   485         }
       
   486     }
       
   487 
       
   488     DP_OUT("CntCache::scheduleOneReadAheadItem()");
       
   489 }
       
   490 
       
   491 /*! 
       
   492     Creates a new item in the info cache. If the cache is full,
       
   493     then the least recently accessed item is removed from cache.
       
   494     
       
   495     /param contactId id of contact for which to create the new cache item
       
   496     /return the newly created cache item
       
   497  */
       
   498 CntInfoCacheItem* CntCache::createInfoCacheItem(int contactId)
       
   499 {
       
   500     DP_IN("CntCache::createInfoCacheItem(" << contactId << ")");
       
   501 
       
   502     if (mInfoCache.count() >= InfoCacheSize) {
       
   503         // cache is full, so remove the oldest contact
       
   504         int minCacheOrder = mNextInfoCacheOrder;
       
   505         CntInfoCacheItem* oldestItem = NULL;
       
   506         foreach (CntInfoCacheItem* i, mInfoCache) {
       
   507             if (i->cacheOrder < minCacheOrder) {
       
   508                 minCacheOrder = i->cacheOrder;
       
   509                 oldestItem = i;
       
   510             }
       
   511         }
       
   512         mInfoCache.remove(oldestItem->contactId);
       
   513         delete oldestItem;
       
   514         
       
   515         // cache maintenance: if the cache ids become too large,
       
   516         // reduce all of them by MaxCacheOrderValue
       
   517         if (mNextInfoCacheOrder >= MaxCacheOrderValue) {
       
   518             mNextInfoCacheOrder -=  MaxCacheOrderValue;
       
   519             foreach (CntInfoCacheItem* i, mInfoCache) {
       
   520                 i->cacheOrder -= MaxCacheOrderValue;
       
   521             }
       
   522         }
       
   523     }
       
   524     
       
   525     // create and insert the new item
       
   526     CntInfoCacheItem* item = new CntInfoCacheItem();
       
   527     item->cacheOrder = mNextInfoCacheOrder++;
       
   528     item->contactId = contactId;
       
   529     mInfoCache.insert(contactId, item);
       
   530     
       
   531     DP_OUT("CntCache::createInfoCacheItem(" << contactId << ")");
       
   532 
       
   533     return item;
       
   534 }
       
   535 
       
   536 /*! 
       
   537     Creates a new item in the icon cache. If the cache is full,
       
   538     then the least recently accessed item is removed from cache.
       
   539     
       
   540     /param iconName name of the icon for which to create the new cache item
       
   541     /return the newly created cache item
       
   542  */
       
   543 CntIconCacheItem* CntCache::createIconCacheItem(const QString& iconName)
       
   544 {
       
   545     DP_IN("CntCache::createIconCacheItem(" << iconName << ")");
       
   546 
       
   547     if (mIconCache.count() >= IconCacheSize) {
       
   548         // cache is full, so remove the oldest icon
       
   549         int minCacheOrder = mNextIconCacheOrder;
       
   550         CntIconCacheItem* oldestItem = NULL;
       
   551         foreach (CntIconCacheItem* i, mIconCache) {
       
   552             if (i->cacheOrder < minCacheOrder) {
       
   553                 minCacheOrder = i->cacheOrder;
       
   554                 oldestItem = i;
       
   555             }
       
   556         }
       
   557         mIconCache.remove(oldestItem->iconName);
       
   558         delete oldestItem;
       
   559 
       
   560         // cache maintenance: if the cache orders become too large,
       
   561         // reduce all of them by MaxCacheOrderValue
       
   562         if (mNextIconCacheOrder >= MaxCacheOrderValue) {
       
   563             mNextIconCacheOrder -=  MaxCacheOrderValue;
       
   564             foreach (CntIconCacheItem* i, mIconCache) {
       
   565                 i->cacheOrder -=  MaxCacheOrderValue;
       
   566             }
       
   567         }
       
   568     }
       
   569 
       
   570     // create and insert the new item
       
   571     CntIconCacheItem* item = new CntIconCacheItem();
       
   572     item->cacheOrder = mNextIconCacheOrder++;
       
   573     item->iconName = iconName;
       
   574     item->isFetched = false;
       
   575     mIconCache.insert(iconName, item);
       
   576 
       
   577     DP_OUT("CntCache::createIconCacheItem(" << iconName << ")");
       
   578 
       
   579     return item;
       
   580 }
       
   581 
       
   582 /*! 
       
   583     Notifies clients that a contact might have changed.
       
   584     Clients can then request the info via fetchContactInfo() 
       
   585     if they are interested.
       
   586  */
       
   587 void CntCache::emitContactInfoUpdated(int contactId)
       
   588 {
       
   589     mEmittedContactId = contactId;
       
   590     emit contactInfoUpdated(contactId);
       
   591     mEmittedContactId = -1;
       
   592 }
       
   593 
       
   594 /*! 
       
   595     Deletes the cache.
       
   596  */
       
   597 void CntCache::onShutdown()
       
   598 {
       
   599     delete this;
       
   600 }
       
   601 
       
   602 
       
   603 /*! 
       
   604     Creates an empty object.
       
   605  */
       
   606 CntContactInfo::CntContactInfo()
       
   607     : d(new CntContactInfoData())
       
   608 {
       
   609 }
       
   610 
       
   611 /*! 
       
   612     Creates an object with all info fields set.
       
   613  */
       
   614 CntContactInfo::CntContactInfo(int id, const QString& name, const QString& text, const HbIcon& icon1, const HbIcon& icon2)
       
   615     : d(new CntContactInfoData())
       
   616 {
       
   617       d->id = id;
       
   618       d->name = name;
       
   619       d->text = text;
       
   620       d->icon1 = icon1;
       
   621       d->icon2 = icon2;
       
   622 }
       
   623 
       
   624 /*! 
       
   625     Destroys the object.
       
   626  */
       
   627 CntContactInfo::~CntContactInfo()
       
   628 {
       
   629 }
       
   630 
       
   631 /*! 
       
   632     Copy constructor.
       
   633  */
       
   634 CntContactInfo::CntContactInfo(const CntContactInfo& other)
       
   635     : d(other.d)
       
   636 {
       
   637 }
       
   638 
       
   639 /*! 
       
   640     Assignment operator.
       
   641  */
       
   642 CntContactInfo& CntContactInfo::operator=(const CntContactInfo& other)
       
   643 {
       
   644     d = other.d;
       
   645     return *this;
       
   646 }
       
   647 
       
   648 /*! 
       
   649     Getter function for the id.
       
   650  */
       
   651 int CntContactInfo::id() const
       
   652 {
       
   653     return d->id;
       
   654 }
       
   655 
       
   656 /*! 
       
   657     Getter function for the name.
       
   658  */
       
   659 QString CntContactInfo::name() const
       
   660 {
       
   661     return d->name;
       
   662 }
       
   663 
       
   664 /*! 
       
   665     Getter function for the text.
       
   666  */
       
   667 QString CntContactInfo::text() const
       
   668 {
       
   669     return d->text;
       
   670 }
       
   671 
       
   672 /*! 
       
   673     Getter function for the first icon.
       
   674  */
       
   675 HbIcon CntContactInfo::icon1() const
       
   676 {
       
   677     return d->icon1;
       
   678 }
       
   679 
       
   680 /*! 
       
   681     Getter function for the second icon.
       
   682  */
       
   683 HbIcon CntContactInfo::icon2() const
       
   684 {
       
   685     return d->icon2;
       
   686 }
       
   687