--- a/phonebookengines/cntlistmodel/src/cntnamefetcher.cpp Fri Oct 08 11:42:51 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,643 +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 <e32base.h>
-#include <s32mem.h>
-#include <e32std.h>
-
-#include <xqutils.h>
-#include <QEvent>
-#include <QFile>
-#include <QDir>
-#include <hbapplication.h>
-#include <hbstringutil.h>
-
-#include <cntdb.h>
-#include <cntuids.h>
-#include <cntdebug.h>
-
-#include "cntnamefetcher.h"
-
-// constants used when fetching names from CntSrv
-#define KCntSearchResultList 99
-#define KCntOpenDataBase 100
-_LIT(KCntServerExe, "CNTSRV.EXE");
-_LIT(KCntServerName, "CNTSRV");
-const TInt KAsyncMessageSlots = 6;
-const TInt KCntServerMajorVersionNumber=1;
-const TInt KCntServerMinorVersionNumber=1;
-const TInt KCntServerBuildVersionNumber=1;
-static const QEvent::Type CntAsynchOperation = QEvent::User;
-
-// constants used for file cache
-static const QString cacheFolder = "20022EF9";
-static const QString cacheFilename = "contactcache.dat";
-
-/*!
- Internal class used by CntSrvConnection to issues requests to CntSrv.
- */
-class CntSrvSession : public RSessionBase
-{
-public:
- CntSrvSession() { mConnected = false; }
- ~CntSrvSession() { RHandleBase::Close(); }
- void executeSqlQueryL(const TDesC &sqlQuery, QList<CntNameCacheItem *> &names, CntNameOrder nameFormat, int sizeHintKB);
-
-private:
- void connectCntSrvL();
-
-private:
- bool mConnected;
-};
-
-CntSrvConnection::CntSrvConnection()
- : mSession(NULL),
- mIsAsynchronous(false)
-{
-}
-
-CntSrvConnection::~CntSrvConnection()
-{
- disconnect();
-
- if (mThread.isRunning()) {
- mThread.quit();
- mThread.wait();
- }
-
- delete mSession;
-
- mNames.clear();
-}
-
-void CntSrvConnection::setAsynchronous()
-{
- mIsAsynchronous = true;
- mThread.start();
- moveToThread(&mThread);
-}
-
-bool CntSrvConnection::executeSqlQuery(const QString &sqlQuery, CntNameOrder nameFormat, int sizeHintKB)
-{
- CNT_ENTRY
-
- if (!mSession) {
- mSession = new CntSrvSession();
- }
-
- if (mIsAsynchronous) {
- mSqlQuery = sqlQuery;
- mNameFormat = nameFormat;
- mSizeHintKB = sizeHintKB;
- HbApplication::instance()->postEvent(this, new QEvent(CntAsynchOperation));
- } else {
- mNames.clear();
- TPtrC queryPtr(sqlQuery.utf16(), sqlQuery.length());
- TRAPD(err, mSession->executeSqlQueryL(queryPtr, mNames, nameFormat, sizeHintKB));
- if (err != KErrNone) {
- qDeleteAll(mNames);
- mNames.clear();
- CNT_EXIT
- return false;
- }
- }
-
- CNT_EXIT
-
- return true;
-}
-
-bool CntSrvConnection::event(QEvent *event)
-{
- if (event->type() == CntAsynchOperation) {
- CNT_ENTRY
-
- mNames.clear();
- TPtrC ptr(mSqlQuery.utf16(), mSqlQuery.length());
- TRAPD(err, mSession->executeSqlQueryL(ptr, mNames, mNameFormat, mSizeHintKB));
- if (err != KErrNone) {
- qDeleteAll(mNames);
- mNames.clear();
- }
- emit namesRead();
- qStableSort(mNames.begin(), mNames.end(), CntNameFetcher::compareNames);
- delete mSession;
- mSession = NULL;
- emit namesSorted();
-
- CNT_EXIT
-
- return true;
- }
-
- return QObject::event(event);
-}
-
-/*!
- Executes a special SQL query: the first column must be the contact id and
- the subsequent columns must be varchar fields.
-
- \param sqlQuery the SQL to execute
- \param names the list where the results will be stored
- \param nameFormat the format the names should be stored in
- \param sizeHintKB the expected size of the buffer needed to fit the results; a too
- small value will effectively double the fetch time, since the
- buffer is then resized and the data refetched a second time
- */
-void CntSrvSession::executeSqlQueryL(const TDesC& sqlQuery, QList<CntNameCacheItem*> &names, CntNameOrder nameFormat, int sizeHintKB)
-{
- int listSize = 0;
-
- // read the ids and names from the database
- if (!mConnected) {
- connectCntSrvL();
- }
-
- // allocate tmeporary buffer
- TInt bufferSize = sizeHintKB * 1024;
- CBufFlat* buffer = CBufFlat::NewL(256);
- CleanupStack::PushL(buffer);
-
- // try to fetch the results, if the fetch fails with
- // a positive value, it means the buffer was too small
- // in this case the buffer is resized and the results
- // are fetched again
- for (TInt tries = 0; tries < 2 && bufferSize > 0; ++tries) {
- buffer->ResizeL(bufferSize);
- TPtr8 bufferPtr = buffer->Ptr(0);
- TIpcArgs args;
- args.Set(0, &bufferPtr);
- args.Set(1, &sqlQuery);
- bufferSize = SendReceive(KCntSearchResultList, args);
- CNT_LOG_ARGS("buffer size =" << bufferSize)
- User::LeaveIfError(bufferSize);
- }
-
- // store the formatted names into the list
- RBufReadStream readStream;
- TInt id;
- TBuf<256> firstName;
- TBuf<256> lastName;
-
- readStream.Open(*buffer);
- for (int i = 0; (id = readStream.ReadInt32L()) != 0; ++i) {
- readStream >> firstName;
- readStream >> lastName;
- CntNameCacheItem* item = new (ELeave) CntNameCacheItem(
- id,
- QString::fromUtf16(firstName.Ptr(), firstName.Length()),
- QString::fromUtf16(lastName.Ptr(), lastName.Length()),
- nameFormat);
- if (i >= listSize - 1) {
- // if the list is runnning out of space, resize it;
- // initial size is 1000 and after that it doubles
- // every time it runs out of space
- if (listSize == 0) {
- listSize = 1000;
- } else {
- listSize *= 2;
- }
- QT_TRY {
- names.reserve(listSize);
- } QT_CATCH (...) {
- // clean up and return
- CleanupStack::PopAndDestroy(buffer);
- qDeleteAll(names);
- names.clear();
- return;
- }
- }
- names.append(item);
- }
-
- CleanupStack::PopAndDestroy(buffer);
-}
-
-/*!
- Connect to / create a contacts server session.
- */
-void CntSrvSession::connectCntSrvL()
-{
- // Assume the server is already running and attempt to create a session
- // with a maximum of KAsyncMessageSlots message slots.
- TInt err = CreateSession(KCntServerName,
- TVersion(KCntServerMajorVersionNumber, KCntServerMinorVersionNumber, KCntServerBuildVersionNumber),
- KAsyncMessageSlots);
-
- // Server is not running
- if (err == KErrNotFound) {
- // Use the RProcess API to start the server.
- RProcess server;
- User::LeaveIfError(server.Create(KCntServerExe, KNullDesC));
-
- // Enforce server to be at system default priority EPriorityForeground
- server.SetPriority(EPriorityForeground);
-
- // Synchronize with the server.
- TRequestStatus reqStatus;
- server.Rendezvous(reqStatus);
- server.Resume();
-
- // Server will call the reciprocal static synchronization call.
- User::WaitForRequest(reqStatus);
- server.Close();
- User::LeaveIfError(reqStatus.Int());
-
- // Create the server session.
- User::LeaveIfError(CreateSession(KCntServerName,
- TVersion(KCntServerMajorVersionNumber, KCntServerMinorVersionNumber, KCntServerBuildVersionNumber),
- KAsyncMessageSlots));
- } else {
- User::LeaveIfError(err);
- }
-
- TIpcArgs args;
- args.Set(0, &KNullDesC);
- User::LeaveIfError(SendReceive(KCntOpenDataBase, args));
-
- mConnected = true;
-}
-
-/*!
- Creates a CntNameFetcher object.
- */
-CntNameFetcher::CntNameFetcher()
- : mDbConnection(NULL),
- mAsynchDbConnection(NULL),
- mSettingsManager(NULL),
- mNameFormatSetting(NULL),
- mBufferSizeEstimate(0)
-{
- CNT_ENTRY
-
- // get name format setting and listen to changes
- mSettingsManager = new XQSettingsManager();
- mNameFormatSetting = new XQSettingsKey(XQSettingsKey::TargetCentralRepository, KCRCntSettings.iUid, KCntNameOrdering);
- mNameFormat = static_cast<CntNameOrder>(mSettingsManager->readItemValue(*mNameFormatSetting, XQSettingsManager::TypeInt).toInt());
- mSettingsManager->startMonitoring(*mNameFormatSetting, XQSettingsManager::TypeInt);
- connect(mSettingsManager, SIGNAL(valueChanged(const XQSettingsKey&, const QVariant&)), this, SLOT(setNameFormat(const XQSettingsKey&, const QVariant&)));
-
- // connect to contacts server
- mDbConnection = new CntSrvConnection();
-
- CNT_EXIT
-}
-
-/*!
- Destroys a CntNameFetcher object.
- */
-CntNameFetcher::~CntNameFetcher()
-{
- CNT_ENTRY
-
- delete mSettingsManager;
- delete mNameFormatSetting;
- delete mDbConnection;
- delete mAsynchDbConnection;
-
- CNT_EXIT
-}
-
-/*!
- Reads names from the file cache.
-
- \return true if the names were read successfully from the cache file
-
- */
-bool CntNameFetcher::readNamesFromCache(QList<CntNameCacheItem*> &names)
-{
- CNT_ENTRY
-
- bool success = true;
- quint32 itemCount;
- quint32 nameFormat;
-
- QFile cacheFile(XQUtils::phoneMemoryRootPath() + cacheFolder + "\\" + cacheFilename);
- if (!cacheFile.open(QIODevice::ReadOnly)) {
- return false;
- }
-
- QDataStream in(&cacheFile);
-
- mBufferSizeEstimate = 0;
- QT_TRY {
- // read header: nr of items, name format
- in >> itemCount;
- in >> nameFormat;
- names.reserve(itemCount);
-
- // populate list with names
- while (itemCount-- > 0) {
- CntNameCacheItem *item = CntNameCacheItem::internalize(in, (CntNameOrder) nameFormat);
- names.append(item);
- mBufferSizeEstimate += 4 + 2 * item->name().length();
- }
- } QT_CATCH (...) {
- qDeleteAll(names);
- names.clear();
- success = false;
- }
-
- cacheFile.close();
-
- CNT_EXIT
-
- return success;
-}
-
-/*!
- Write names to the file cache.
- */
-bool CntNameFetcher::writeNamesToCache(const QList<CntNameCacheItem*> &names) const
-{
- CNT_ENTRY
-
- bool success = true;
-
- // create folder for cache file if it does not already exist
- QString path = XQUtils::phoneMemoryRootPath() + cacheFolder;
- if (!QDir(path).exists()) {
- QDir dir(XQUtils::phoneMemoryRootPath());
- if (!dir.mkdir(cacheFolder)) {
- CNT_EXIT_ARGS("failed to create folder: " << path)
- return false;
- }
-
- // have to use native Symbian code to make the dir hidden
- RFs fs;
- fs.Connect();
- TPtrC pathPtr(path.utf16(), path.length());
- if (fs.SetAtt(pathPtr, KEntryAttHidden, 0) != KErrNone) {
- fs.Close();
- return false;
- }
- fs.Close();
- }
-
- // open cache file for writing
- QFile cacheFile(XQUtils::phoneMemoryRootPath() + cacheFolder + "\\" + cacheFilename);
- if (!cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
- CNT_EXIT_ARGS("failed to create file")
- return false;
- }
- QDataStream out(&cacheFile);
-
- // write the names to the cache file
- QT_TRY {
- // write header
- out << names.size();
- out << (quint32) mNameFormat;
-
- // write list with names
- foreach (CntNameCacheItem* name, names) {
- name->externalize(out);
- }
- } QT_CATCH (...) {
- success = false;
- }
-
- cacheFile.close();
-
- CNT_EXIT
-
- return success;
-}
-
-/*!
- Reads the name of one contact from the contact database synchronously.
-
- \param contactId the id of the contact
- */
-CntNameCacheItem* CntNameFetcher::readOneName(QContactLocalId contactId) const
-{
- CNT_ENTRY
-
- QString sqlQuery = QString("SELECT contact_id, first_name, last_name FROM contact WHERE (type_flags>>24)<=1 AND contact_id=%1").arg(contactId);
- mDbConnection->executeSqlQuery(sqlQuery, mNameFormat, 2);
-
- if (mDbConnection->names().size() == 0) {
- return NULL;
- }
-
- CNT_EXIT
-
- return mDbConnection->names().at(0);
-}
-
-/*!
- Reads the names of all contacts from the contact database asynchronously.
- */
-void CntNameFetcher::readAllNamesAsynch()
-{
- CNT_ENTRY
-
- if (mAsynchDbConnection != NULL) {
- // an asynch fetch is already in progress, so no need to start a new one
- return;
- }
-
- if (mBufferSizeEstimate == 0) {
- mBufferSizeEstimate = 240 * 1024;
- }
-
- CNT_LOG_ARGS("buffer size =" << mBufferSizeEstimate)
-
- mAsynchDbConnection = new CntSrvConnection();
- mAsynchDbConnection->setAsynchronous();
- connect(mAsynchDbConnection, SIGNAL(namesRead()), this, SIGNAL(databaseAccessComplete()));
- connect(mAsynchDbConnection, SIGNAL(namesSorted()), this, SLOT(sendCompletionSignal()));
- mAsynchDbConnection->executeSqlQuery("SELECT contact_id, first_name, last_name FROM contact WHERE (type_flags>>24)<=1", mNameFormat, 16 + mBufferSizeEstimate / 1024);
-
- CNT_EXIT
-}
-
-/*!
- Sorts the names quickly and in a locale aware manner.
- */
-void CntNameFetcher::sortNames(QList<CntNameCacheItem *> &names) const
-{
- CNT_ENTRY
-
- qStableSort(names.begin(), names.end(), CntNameFetcher::compareNames);
-
- CNT_EXIT
-}
-
-/*!
- Compares a pair of contact names and returns true if the first
- one should be presented before the second one in a list. This
- static function is used e.g. when sorting lists of names.
- */
-bool CntNameFetcher::compareNames(const CntNameCacheItem* a, const CntNameCacheItem* b)
-{
- QString aName = a->name();
- QString bName = b->name();
-
- if (aName.isEmpty()) {
- return false;
- } else if (bName.isEmpty()) {
- return true;
- }
-
- return (HbStringUtil::compareC(aName, bName) < 0);
-}
-
-/*!
- Notifies clients that the name format has changed. This function is called by the framework
- if the name format settings is changed, see the constructor.
- */
-void CntNameFetcher::setNameFormat(const XQSettingsKey &/*key*/, const QVariant &value)
-{
- CNT_ENTRY
-
- bool ok = false;
- CntNameOrder newNameFormat = static_cast<CntNameOrder>(value.toInt(&ok));
- if (ok && newNameFormat != mNameFormat) {
- mNameFormat = newNameFormat;
- emit nameFormatChanged(mNameFormat);
- }
-
- CNT_EXIT
-}
-
-/*!
- Emits the results of a completed asynch database operation.
- */
-void CntNameFetcher::sendCompletionSignal()
-{
- CNT_ENTRY
-
- emit namesAvailable(mAsynchDbConnection->names());
-
- delete mAsynchDbConnection;
- mAsynchDbConnection = NULL;
-
- CNT_EXIT
-}
-
-/*!
- Creates a CntNameCacheItem object.
- */
-CntNameCacheItem::CntNameCacheItem(QContactLocalId id, const QString& firstName, const QString& lastName, CntNameOrder nameFormat)
-{
- mContactId = id;
- setFormattedName(firstName, lastName, nameFormat);
-}
-
-/*!
- Destroys a CntNameCacheItem object.
- */
-CntNameCacheItem::~CntNameCacheItem()
-{
-}
-
-/*!
- Changes the format used to present the name.
- */
-void CntNameCacheItem::setNameFormat(CntNameOrder newFormat)
-{
- QString firstName = mName.mid(mFirstNamePosition&0xffff, mFirstNamePosition>>16);
- QString lastName = mName.mid(mLastNamePosition&0xffff, mLastNamePosition>>16);
- setFormattedName(firstName, lastName, newFormat);
-}
-
-/*!
- Copies the contents of the other cache item to this one.
- */
-void CntNameCacheItem::operator=(const CntNameCacheItem &other)
-{
- mContactId = other.mContactId;
- mFirstNamePosition = other.mFirstNamePosition;
- mLastNamePosition = other.mLastNamePosition;
- mName = other.mName;
-}
-
-/*!
- Externalizes a CntNameCacheItem object.
- */
-void CntNameCacheItem::externalize(QDataStream &stream)
-{
- stream << mContactId;
- stream << mFirstNamePosition;
- stream << mLastNamePosition;
- stream << mName;
-}
-
-/*!
- Internalizes a CntNameCacheItem object.
- */
-CntNameCacheItem* CntNameCacheItem::internalize(QDataStream &stream, CntNameOrder nameFormat)
-{
- quint32 id;
- quint32 firstNamePosition;
- quint32 lastNamePosition;
- QString name;
-
- stream >> id;
- stream >> firstNamePosition;
- stream >> lastNamePosition;
- stream >> name;
-
- QString firstName = name.mid(firstNamePosition&0xffff, firstNamePosition>>16);
- QString lastName = name.mid(lastNamePosition&0xffff, lastNamePosition>>16);
-
- return new CntNameCacheItem(id, firstName, lastName, nameFormat);
-}
-
-/*!
- Sets the formatted name and positions of the first name and last name,
- according to the name format in the parameter.
- */
-void CntNameCacheItem::setFormattedName(const QString& firstName, const QString& lastName, CntNameOrder nameFormat)
-{
- int firstNameLength = firstName.length();
- int lastNameLength = lastName.length();
-
- if (lastNameLength == 0) {
- mName = firstName;
- mFirstNamePosition = firstNameLength << 16;
- mLastNamePosition = 0;
- } else if (firstNameLength == 0) {
- mName = lastName;
- mFirstNamePosition = 0;
- mLastNamePosition = lastNameLength << 16;
- } else {
- if (nameFormat == CntOrderLastFirst) {
- mName = lastName + " " + firstName;
- mFirstNamePosition = (firstNameLength << 16) | (lastNameLength + 1);
- mLastNamePosition = (lastNameLength << 16);
- } else if (nameFormat == CntOrderLastCommaFirst) {
- mName = lastName + ", " + firstName;
- mFirstNamePosition = (firstNameLength << 16) | (lastNameLength + 2);
- mLastNamePosition = (lastNameLength << 16);
- } else {
- mName = firstName + " " + lastName;
- mFirstNamePosition = (firstNameLength << 16);
- mLastNamePosition = (lastNameLength << 16) | (firstNameLength + 1);
- }
- }
-}
-
-QString CntNameCacheItem::firstName() const
-{
- return mName.mid(mFirstNamePosition&0xffff, mFirstNamePosition>>16);
-}
-
-QString CntNameCacheItem::lastName() const
-{
- return mName.mid(mLastNamePosition&0xffff, mLastNamePosition>>16);
-}