--- a/phonebookengines/cntlistmodel/src/cntcache.cpp Wed Jun 23 18:02:44 2010 +0300
+++ b/phonebookengines/cntlistmodel/src/cntcache.cpp Tue Jul 06 14:05:47 2010 +0300
@@ -31,6 +31,8 @@
static const int CacheOrderStartValue = 1;
// for avoiding wrap around with cache orders
static const int MaxCacheOrderValue = 10000000;
+// number of items to read quickly when a new instance is requested or cache is cleared
+static const int ItemsToReadUrgently = 12;
// number of items to read ahead into cache; this number is for one direction
static const int ItemsToCacheAhead = 24;
// cache size for info items (name, text, icon1name, icon2name)
@@ -44,18 +46,6 @@
static const QString EmptyTextField = " ";
/*!
- Provides a pointer to the CntCache singleton instance.
- */
-CntCache* CntCache::instance()
-{
- if (mInstance == NULL) {
- mInstance = new CntCache();
- }
-
- return mInstance;
-}
-
-/*!
Creates the CntCache singleton instance.
*/
CntCache::CntCache()
@@ -63,7 +53,8 @@
mWorker(new CntCacheThread()),
mNextInfoCacheOrder(CacheOrderStartValue),
mNextIconCacheOrder(CacheOrderStartValue),
- mEmittedContactId(-1)
+ mEmittedContactId(-1),
+ mUrgentContacts(0)
{
CNT_ENTRY
@@ -106,6 +97,22 @@
CNT_EXIT
}
+/*!
+ Provides a pointer to the CntCache singleton instance.
+ */
+CntCache* CntCache::instance()
+{
+ if (mInstance == NULL) {
+ mInstance = new CntCache();
+ }
+
+ // whenever a client requests an instance the client will want to get all info
+ // for the first couple of contacts (~a screenfull) as fast as possible
+ mInstance->mUrgentContacts = ItemsToReadUrgently;
+
+ return mInstance;
+}
+
/*!
Fetches information about a contact: name, text (e.g. phone number or
social status) and two icons (e.g. avatar, presence). Previously cached
@@ -134,10 +141,17 @@
int contactId = idList.at(row);
if (contactId != mEmittedContactId) {
- // this request comes from the UI in response to some scrolling activity =>
+ // this request comes from the UI when a new view is created or in response to
+ // some scrolling activity; in the former case, the client should
+ // have set urgencymode on, but in the latter case:
// 1) postpone all jobs so the UI can use as much of the CPU as possible
// 2) update read ahead cache to contain all IDs of all items near this item
- mWorker->postponeJobs();
+ if (mUrgentContacts > 0) {
+ --mUrgentContacts;
+ }
+ else {
+ mWorker->postponeJobs();
+ }
updateReadAheadCache(row, idList);
}
@@ -157,19 +171,22 @@
// this id to the list of contacts that want to be
// notified when the icon is received
iconItem->contactIds.insert(contactId);
+ // also reschedule it
+ mWorker->scheduleIconJob(iconName, row);
}
}
else {
// needed icon is not in cache, so schedule it for retrieval
CntIconCacheItem* iconItem = createIconCacheItem(iconName);
iconItem->contactIds.insert(contactId);
- mWorker->scheduleIconJob(iconName);
+ mWorker->scheduleIconJob(iconName, row);
}
}
}
// update cache order
infoItem->cacheOrder = mNextInfoCacheOrder++;
+ infoItem->latestRow = row;
name = infoItem->name;
text = infoItem->text;
@@ -182,9 +199,10 @@
CntInfoCacheItem* item = createInfoCacheItem(contactId);
item->name = name;
item->text = text;
+ item->latestRow = row;
// ask the worker thread to fetch the information asynchronously
- mWorker->scheduleInfoJob(contactId);
+ mWorker->scheduleInfoJob(contactId, row);
}
}
@@ -205,6 +223,7 @@
qDeleteAll(mInfoCache);
mInfoCache.clear();
mNextInfoCacheOrder = CacheOrderStartValue;
+ mUrgentContacts = ItemsToReadUrgently;
CNT_EXIT
}
@@ -234,10 +253,7 @@
}
else if (infoField == ContactInfoTextField) {
// update cache with new text for contact
- if (!infoValue.isEmpty())
- mInfoCache.value(contactId)->text = infoValue;
- else
- mInfoCache.value(contactId)->text = " ";
+ mInfoCache.value(contactId)->text = infoValue;
hasNewInfo = true;
}
else {
@@ -269,7 +285,13 @@
else {
CntIconCacheItem* iconItem = createIconCacheItem(iconName);
iconItem->contactIds.insert(contactId);
- mWorker->scheduleIconJob(iconName);
+ if (mInfoCache.contains(contactId)) {
+ mWorker->scheduleIconJob(iconName, mInfoCache.value(contactId)->latestRow);
+ }
+ else {
+ // less important icon, since this contact is not in cache
+ mWorker->scheduleIconJob(iconName, 100000);
+ }
hasNewInfo = false;
}
}
@@ -368,7 +390,7 @@
if (mInfoCache.contains(contactId) && fetchContactName(contactId, name)) {
CntInfoCacheItem* infoItem = mInfoCache.value(contactId);
infoItem->name = name;
- mWorker->scheduleInfoJob(contactId);
+ mWorker->scheduleInfoJob(contactId, infoItem->latestRow);
}
}
@@ -420,6 +442,7 @@
QStringList details;
details << QContactDisplayLabel::DefinitionName;
nameOnlyFetchHint.setDetailDefinitionsHint(details);
+ nameOnlyFetchHint.setOptimizationHints(QContactFetchHint::NoRelationships);
QContact contact = mContactManager->contact(contactId, nameOnlyFetchHint);
if (mContactManager->error() == QContactManager::NoError) {
@@ -467,7 +490,7 @@
int contactId = idList.at(row);
if (!mInfoCache.contains(contactId)) {
// contact is not in cache, so put the id to items to read into cache
- mReadAheadCache.append(contactId);
+ mReadAheadCache.append(QPair<int,int>(contactId,row));
}
else {
// contact is in cache; update cache order as we want to keep this item in cache
@@ -487,9 +510,11 @@
CNT_ENTRY
QString name;
-
+
+ // pick the first contact from the read ahead cache and schedule it
while (mReadAheadCache.count() > 0) {
- int contactId = mReadAheadCache.takeFirst();
+ int contactId = mReadAheadCache.first().first;
+ int contactRow = mReadAheadCache.takeFirst().second;
if (!mInfoCache.contains(contactId)) {
// contact is not in cache, so schedule it for retreival
if (fetchContactName(contactId, name)) {
@@ -497,9 +522,10 @@
CntInfoCacheItem* item = createInfoCacheItem(contactId);
item->name = name;
item->text = EmptyTextField;
+ item->latestRow = contactRow;
// schedule the info for retrieval
- mWorker->scheduleInfoJob(contactId);
+ mWorker->scheduleInfoJob(contactId, contactRow);
break;
}
}