phonebookengines/cntlistmodel/src/cntnamefetcher.cpp
changeset 81 640d30f4fb64
parent 77 c18f9fa7f42e
child 84 63017c97b1d6
--- 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);
-}