phonebookengines/cntlistmodel/src/cntnamefetcher.cpp
author hgs
Tue, 21 Sep 2010 17:07:25 +0300
changeset 72 6abfb1094884
permissions -rw-r--r--
201037
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
72
hgs
parents:
diff changeset
     1
/*
hgs
parents:
diff changeset
     2
* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
hgs
parents:
diff changeset
     3
* All rights reserved.
hgs
parents:
diff changeset
     4
* This component and the accompanying materials are made available
hgs
parents:
diff changeset
     5
* under the terms of "Eclipse Public License v1.0"
hgs
parents:
diff changeset
     6
* which accompanies this distribution, and is available
hgs
parents:
diff changeset
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
hgs
parents:
diff changeset
     8
*
hgs
parents:
diff changeset
     9
* Initial Contributors:
hgs
parents:
diff changeset
    10
* Nokia Corporation - initial contribution.
hgs
parents:
diff changeset
    11
*
hgs
parents:
diff changeset
    12
* Contributors:
hgs
parents:
diff changeset
    13
*
hgs
parents:
diff changeset
    14
* Description: Private data and helper classes used by class CntCache.
hgs
parents:
diff changeset
    15
*
hgs
parents:
diff changeset
    16
*/
hgs
parents:
diff changeset
    17
hgs
parents:
diff changeset
    18
#include <e32base.h>
hgs
parents:
diff changeset
    19
#include <s32mem.h>
hgs
parents:
diff changeset
    20
#include <e32std.h>
hgs
parents:
diff changeset
    21
hgs
parents:
diff changeset
    22
#include <xqutils.h>
hgs
parents:
diff changeset
    23
#include <QEvent>
hgs
parents:
diff changeset
    24
#include <QFile>
hgs
parents:
diff changeset
    25
#include <QDir>
hgs
parents:
diff changeset
    26
#include <hbapplication.h>
hgs
parents:
diff changeset
    27
#include <hbstringutil.h>
hgs
parents:
diff changeset
    28
hgs
parents:
diff changeset
    29
#include <cntdb.h>
hgs
parents:
diff changeset
    30
#include <cntuids.h>
hgs
parents:
diff changeset
    31
#include <cntdebug.h>
hgs
parents:
diff changeset
    32
hgs
parents:
diff changeset
    33
#include "cntnamefetcher.h"
hgs
parents:
diff changeset
    34
hgs
parents:
diff changeset
    35
// constants used when fetching names from CntSrv
hgs
parents:
diff changeset
    36
#define KCntSearchResultList 99
hgs
parents:
diff changeset
    37
#define KCntOpenDataBase 100
hgs
parents:
diff changeset
    38
_LIT(KCntServerExe, "CNTSRV.EXE");
hgs
parents:
diff changeset
    39
_LIT(KCntServerName, "CNTSRV");
hgs
parents:
diff changeset
    40
const TInt KAsyncMessageSlots = 6;
hgs
parents:
diff changeset
    41
const TInt KCntServerMajorVersionNumber=1;
hgs
parents:
diff changeset
    42
const TInt KCntServerMinorVersionNumber=1;
hgs
parents:
diff changeset
    43
const TInt KCntServerBuildVersionNumber=1;
hgs
parents:
diff changeset
    44
static const QEvent::Type CntAsynchOperation = QEvent::User;
hgs
parents:
diff changeset
    45
hgs
parents:
diff changeset
    46
// constants used for file cache
hgs
parents:
diff changeset
    47
static const QString cacheFolder = "20022EF9";
hgs
parents:
diff changeset
    48
static const QString cacheFilename = "contactcache.dat";
hgs
parents:
diff changeset
    49
hgs
parents:
diff changeset
    50
/*!
hgs
parents:
diff changeset
    51
     Internal class used by CntSrvConnection to issues requests to CntSrv.
hgs
parents:
diff changeset
    52
  */
hgs
parents:
diff changeset
    53
class CntSrvSession : public RSessionBase
hgs
parents:
diff changeset
    54
{
hgs
parents:
diff changeset
    55
public:
hgs
parents:
diff changeset
    56
    CntSrvSession() { mConnected = false; }
hgs
parents:
diff changeset
    57
    ~CntSrvSession() { RHandleBase::Close(); }
hgs
parents:
diff changeset
    58
    void executeSqlQueryL(const TDesC &sqlQuery, QList<CntNameCacheItem *> &names, CntNameOrder nameFormat, int sizeHintKB);
hgs
parents:
diff changeset
    59
hgs
parents:
diff changeset
    60
private:
hgs
parents:
diff changeset
    61
    void connectCntSrvL();
hgs
parents:
diff changeset
    62
hgs
parents:
diff changeset
    63
private:
hgs
parents:
diff changeset
    64
    bool mConnected;
hgs
parents:
diff changeset
    65
};
hgs
parents:
diff changeset
    66
hgs
parents:
diff changeset
    67
CntSrvConnection::CntSrvConnection()
hgs
parents:
diff changeset
    68
    : mSession(NULL),
hgs
parents:
diff changeset
    69
      mIsAsynchronous(false)
hgs
parents:
diff changeset
    70
{
hgs
parents:
diff changeset
    71
}
hgs
parents:
diff changeset
    72
hgs
parents:
diff changeset
    73
CntSrvConnection::~CntSrvConnection()
hgs
parents:
diff changeset
    74
{
hgs
parents:
diff changeset
    75
    disconnect();
hgs
parents:
diff changeset
    76
hgs
parents:
diff changeset
    77
    if (mThread.isRunning()) {
hgs
parents:
diff changeset
    78
        mThread.quit();
hgs
parents:
diff changeset
    79
        mThread.wait();
hgs
parents:
diff changeset
    80
    }
hgs
parents:
diff changeset
    81
hgs
parents:
diff changeset
    82
    delete mSession;
hgs
parents:
diff changeset
    83
hgs
parents:
diff changeset
    84
    mNames.clear();
hgs
parents:
diff changeset
    85
}
hgs
parents:
diff changeset
    86
hgs
parents:
diff changeset
    87
void CntSrvConnection::setAsynchronous()
hgs
parents:
diff changeset
    88
{
hgs
parents:
diff changeset
    89
    mIsAsynchronous = true;
hgs
parents:
diff changeset
    90
    mThread.start();
hgs
parents:
diff changeset
    91
    moveToThread(&mThread);
hgs
parents:
diff changeset
    92
}
hgs
parents:
diff changeset
    93
hgs
parents:
diff changeset
    94
bool CntSrvConnection::executeSqlQuery(const QString &sqlQuery, CntNameOrder nameFormat, int sizeHintKB)
hgs
parents:
diff changeset
    95
{
hgs
parents:
diff changeset
    96
    CNT_ENTRY
hgs
parents:
diff changeset
    97
hgs
parents:
diff changeset
    98
    if (!mSession) {
hgs
parents:
diff changeset
    99
        mSession = new CntSrvSession();
hgs
parents:
diff changeset
   100
    }
hgs
parents:
diff changeset
   101
hgs
parents:
diff changeset
   102
    if (mIsAsynchronous) {
hgs
parents:
diff changeset
   103
        mSqlQuery = sqlQuery;
hgs
parents:
diff changeset
   104
        mNameFormat = nameFormat;
hgs
parents:
diff changeset
   105
        mSizeHintKB = sizeHintKB;
hgs
parents:
diff changeset
   106
        HbApplication::instance()->postEvent(this, new QEvent(CntAsynchOperation));
hgs
parents:
diff changeset
   107
    } else {
hgs
parents:
diff changeset
   108
        mNames.clear();
hgs
parents:
diff changeset
   109
        TPtrC queryPtr(sqlQuery.utf16(), sqlQuery.length());
hgs
parents:
diff changeset
   110
        TRAPD(err, mSession->executeSqlQueryL(queryPtr, mNames, nameFormat, sizeHintKB));
hgs
parents:
diff changeset
   111
        if (err != KErrNone) {
hgs
parents:
diff changeset
   112
            qDeleteAll(mNames);
hgs
parents:
diff changeset
   113
            mNames.clear();
hgs
parents:
diff changeset
   114
            CNT_EXIT
hgs
parents:
diff changeset
   115
            return false;
hgs
parents:
diff changeset
   116
        }
hgs
parents:
diff changeset
   117
    }
hgs
parents:
diff changeset
   118
hgs
parents:
diff changeset
   119
    CNT_EXIT
hgs
parents:
diff changeset
   120
    
hgs
parents:
diff changeset
   121
    return true;
hgs
parents:
diff changeset
   122
}
hgs
parents:
diff changeset
   123
hgs
parents:
diff changeset
   124
bool CntSrvConnection::event(QEvent *event)
hgs
parents:
diff changeset
   125
{
hgs
parents:
diff changeset
   126
    if (event->type() == CntAsynchOperation) {
hgs
parents:
diff changeset
   127
        CNT_ENTRY
hgs
parents:
diff changeset
   128
hgs
parents:
diff changeset
   129
        mNames.clear();
hgs
parents:
diff changeset
   130
        TPtrC ptr(mSqlQuery.utf16(), mSqlQuery.length());
hgs
parents:
diff changeset
   131
        TRAPD(err, mSession->executeSqlQueryL(ptr, mNames, mNameFormat, mSizeHintKB));
hgs
parents:
diff changeset
   132
        if (err != KErrNone) {
hgs
parents:
diff changeset
   133
            qDeleteAll(mNames);
hgs
parents:
diff changeset
   134
            mNames.clear();
hgs
parents:
diff changeset
   135
        }
hgs
parents:
diff changeset
   136
        emit namesRead();
hgs
parents:
diff changeset
   137
        qStableSort(mNames.begin(), mNames.end(), CntNameFetcher::compareNames);
hgs
parents:
diff changeset
   138
        delete mSession;
hgs
parents:
diff changeset
   139
        mSession = NULL;
hgs
parents:
diff changeset
   140
        emit namesSorted();
hgs
parents:
diff changeset
   141
hgs
parents:
diff changeset
   142
        CNT_EXIT
hgs
parents:
diff changeset
   143
hgs
parents:
diff changeset
   144
        return true;
hgs
parents:
diff changeset
   145
    }
hgs
parents:
diff changeset
   146
    
hgs
parents:
diff changeset
   147
    return QObject::event(event);
hgs
parents:
diff changeset
   148
}
hgs
parents:
diff changeset
   149
hgs
parents:
diff changeset
   150
/*!
hgs
parents:
diff changeset
   151
    Executes a special SQL query: the first column must be the contact id and
hgs
parents:
diff changeset
   152
    the subsequent columns must be varchar fields.
hgs
parents:
diff changeset
   153
    
hgs
parents:
diff changeset
   154
    \param sqlQuery the SQL to execute
hgs
parents:
diff changeset
   155
    \param names the list where the results will be stored
hgs
parents:
diff changeset
   156
    \param nameFormat the format the names should be stored in 
hgs
parents:
diff changeset
   157
    \param sizeHintKB the expected size of the buffer needed to fit the results; a too
hgs
parents:
diff changeset
   158
                      small value will effectively double the fetch time, since the
hgs
parents:
diff changeset
   159
                      buffer is then resized and the data refetched a second time
hgs
parents:
diff changeset
   160
 */
hgs
parents:
diff changeset
   161
void CntSrvSession::executeSqlQueryL(const TDesC& sqlQuery, QList<CntNameCacheItem*> &names, CntNameOrder nameFormat, int sizeHintKB)
hgs
parents:
diff changeset
   162
{
hgs
parents:
diff changeset
   163
    int listSize = 0;
hgs
parents:
diff changeset
   164
hgs
parents:
diff changeset
   165
    // read the ids and names from the database
hgs
parents:
diff changeset
   166
    if (!mConnected) {
hgs
parents:
diff changeset
   167
        connectCntSrvL();
hgs
parents:
diff changeset
   168
    }
hgs
parents:
diff changeset
   169
hgs
parents:
diff changeset
   170
    // allocate tmeporary buffer
hgs
parents:
diff changeset
   171
    TInt bufferSize = sizeHintKB * 1024;
hgs
parents:
diff changeset
   172
    CBufFlat* buffer = CBufFlat::NewL(256);
hgs
parents:
diff changeset
   173
    CleanupStack::PushL(buffer);
hgs
parents:
diff changeset
   174
hgs
parents:
diff changeset
   175
    // try to fetch the results, if the fetch fails with
hgs
parents:
diff changeset
   176
    // a positive value, it means the buffer was too small
hgs
parents:
diff changeset
   177
    // in this case the buffer is resized and the results
hgs
parents:
diff changeset
   178
    // are fetched again
hgs
parents:
diff changeset
   179
    for (TInt tries = 0; tries < 2 && bufferSize > 0; ++tries) {
hgs
parents:
diff changeset
   180
        buffer->ResizeL(bufferSize);
hgs
parents:
diff changeset
   181
        TPtr8 bufferPtr = buffer->Ptr(0);
hgs
parents:
diff changeset
   182
        TIpcArgs args;
hgs
parents:
diff changeset
   183
        args.Set(0, &bufferPtr);
hgs
parents:
diff changeset
   184
        args.Set(1, &sqlQuery);
hgs
parents:
diff changeset
   185
        bufferSize = SendReceive(KCntSearchResultList, args);
hgs
parents:
diff changeset
   186
        CNT_LOG_ARGS("buffer size =" << bufferSize)
hgs
parents:
diff changeset
   187
        User::LeaveIfError(bufferSize);
hgs
parents:
diff changeset
   188
    } 
hgs
parents:
diff changeset
   189
hgs
parents:
diff changeset
   190
    // store the formatted names into the list
hgs
parents:
diff changeset
   191
    RBufReadStream readStream;
hgs
parents:
diff changeset
   192
    TInt id;
hgs
parents:
diff changeset
   193
    TBuf<256> firstName;
hgs
parents:
diff changeset
   194
    TBuf<256> lastName;
hgs
parents:
diff changeset
   195
hgs
parents:
diff changeset
   196
    readStream.Open(*buffer);
hgs
parents:
diff changeset
   197
    for (int i = 0; (id = readStream.ReadInt32L()) != 0; ++i) {
hgs
parents:
diff changeset
   198
        readStream >> firstName;
hgs
parents:
diff changeset
   199
        readStream >> lastName;
hgs
parents:
diff changeset
   200
        CntNameCacheItem* item = new (ELeave) CntNameCacheItem(
hgs
parents:
diff changeset
   201
            id,
hgs
parents:
diff changeset
   202
            QString::fromUtf16(firstName.Ptr(), firstName.Length()),
hgs
parents:
diff changeset
   203
            QString::fromUtf16(lastName.Ptr(), lastName.Length()),
hgs
parents:
diff changeset
   204
            nameFormat);
hgs
parents:
diff changeset
   205
        if (i >= listSize - 1) {
hgs
parents:
diff changeset
   206
            // if the list is runnning out of space, resize it;
hgs
parents:
diff changeset
   207
            // initial size is 1000 and after that it doubles
hgs
parents:
diff changeset
   208
            // every time it runs out of space
hgs
parents:
diff changeset
   209
            if (listSize == 0) {
hgs
parents:
diff changeset
   210
                listSize = 1000;
hgs
parents:
diff changeset
   211
            } else {
hgs
parents:
diff changeset
   212
                listSize *= 2;
hgs
parents:
diff changeset
   213
            }
hgs
parents:
diff changeset
   214
            QT_TRY {
hgs
parents:
diff changeset
   215
                names.reserve(listSize);
hgs
parents:
diff changeset
   216
            } QT_CATCH (...) {
hgs
parents:
diff changeset
   217
                // clean up and return
hgs
parents:
diff changeset
   218
                CleanupStack::PopAndDestroy(buffer);
hgs
parents:
diff changeset
   219
                qDeleteAll(names);
hgs
parents:
diff changeset
   220
                names.clear();
hgs
parents:
diff changeset
   221
                return;
hgs
parents:
diff changeset
   222
            }
hgs
parents:
diff changeset
   223
        }
hgs
parents:
diff changeset
   224
        names.append(item);
hgs
parents:
diff changeset
   225
    }
hgs
parents:
diff changeset
   226
hgs
parents:
diff changeset
   227
    CleanupStack::PopAndDestroy(buffer);
hgs
parents:
diff changeset
   228
}
hgs
parents:
diff changeset
   229
hgs
parents:
diff changeset
   230
/*!
hgs
parents:
diff changeset
   231
    Connect to / create a contacts server session.
hgs
parents:
diff changeset
   232
 */
hgs
parents:
diff changeset
   233
void CntSrvSession::connectCntSrvL()
hgs
parents:
diff changeset
   234
{
hgs
parents:
diff changeset
   235
    // Assume the server is already running and attempt to create a session
hgs
parents:
diff changeset
   236
    // with a maximum of KAsyncMessageSlots message slots.
hgs
parents:
diff changeset
   237
    TInt err = CreateSession(KCntServerName,
hgs
parents:
diff changeset
   238
                             TVersion(KCntServerMajorVersionNumber, KCntServerMinorVersionNumber, KCntServerBuildVersionNumber),
hgs
parents:
diff changeset
   239
                             KAsyncMessageSlots);
hgs
parents:
diff changeset
   240
    
hgs
parents:
diff changeset
   241
    // Server is not running
hgs
parents:
diff changeset
   242
    if (err == KErrNotFound) {
hgs
parents:
diff changeset
   243
        // Use the RProcess API to start the server.
hgs
parents:
diff changeset
   244
        RProcess server;
hgs
parents:
diff changeset
   245
        User::LeaveIfError(server.Create(KCntServerExe, KNullDesC));
hgs
parents:
diff changeset
   246
        
hgs
parents:
diff changeset
   247
        // Enforce server to be at system default priority EPriorityForeground
hgs
parents:
diff changeset
   248
        server.SetPriority(EPriorityForeground);
hgs
parents:
diff changeset
   249
        
hgs
parents:
diff changeset
   250
        // Synchronize with the server.
hgs
parents:
diff changeset
   251
        TRequestStatus reqStatus;
hgs
parents:
diff changeset
   252
        server.Rendezvous(reqStatus);
hgs
parents:
diff changeset
   253
        server.Resume();
hgs
parents:
diff changeset
   254
        
hgs
parents:
diff changeset
   255
        // Server will call the reciprocal static synchronization call.
hgs
parents:
diff changeset
   256
        User::WaitForRequest(reqStatus);
hgs
parents:
diff changeset
   257
        server.Close();
hgs
parents:
diff changeset
   258
        User::LeaveIfError(reqStatus.Int());
hgs
parents:
diff changeset
   259
        
hgs
parents:
diff changeset
   260
        // Create the server session.
hgs
parents:
diff changeset
   261
        User::LeaveIfError(CreateSession(KCntServerName,
hgs
parents:
diff changeset
   262
                                         TVersion(KCntServerMajorVersionNumber, KCntServerMinorVersionNumber, KCntServerBuildVersionNumber),
hgs
parents:
diff changeset
   263
                                         KAsyncMessageSlots));
hgs
parents:
diff changeset
   264
    } else {
hgs
parents:
diff changeset
   265
        User::LeaveIfError(err);
hgs
parents:
diff changeset
   266
    }
hgs
parents:
diff changeset
   267
    
hgs
parents:
diff changeset
   268
    TIpcArgs args;
hgs
parents:
diff changeset
   269
    args.Set(0, &KNullDesC);
hgs
parents:
diff changeset
   270
    User::LeaveIfError(SendReceive(KCntOpenDataBase, args));
hgs
parents:
diff changeset
   271
hgs
parents:
diff changeset
   272
    mConnected = true;
hgs
parents:
diff changeset
   273
}
hgs
parents:
diff changeset
   274
hgs
parents:
diff changeset
   275
/*!
hgs
parents:
diff changeset
   276
    Creates a CntNameFetcher object.
hgs
parents:
diff changeset
   277
 */
hgs
parents:
diff changeset
   278
CntNameFetcher::CntNameFetcher()
hgs
parents:
diff changeset
   279
    : mDbConnection(NULL),
hgs
parents:
diff changeset
   280
      mAsynchDbConnection(NULL),
hgs
parents:
diff changeset
   281
      mSettingsManager(NULL),
hgs
parents:
diff changeset
   282
      mNameFormatSetting(NULL),
hgs
parents:
diff changeset
   283
      mBufferSizeEstimate(0)
hgs
parents:
diff changeset
   284
{
hgs
parents:
diff changeset
   285
    CNT_ENTRY
hgs
parents:
diff changeset
   286
hgs
parents:
diff changeset
   287
    // get name format setting and listen to changes
hgs
parents:
diff changeset
   288
    mSettingsManager = new XQSettingsManager();
hgs
parents:
diff changeset
   289
    mNameFormatSetting = new XQSettingsKey(XQSettingsKey::TargetCentralRepository, KCRCntSettings.iUid, KCntNameOrdering);
hgs
parents:
diff changeset
   290
    mNameFormat = static_cast<CntNameOrder>(mSettingsManager->readItemValue(*mNameFormatSetting, XQSettingsManager::TypeInt).toInt());
hgs
parents:
diff changeset
   291
    mSettingsManager->startMonitoring(*mNameFormatSetting, XQSettingsManager::TypeInt);
hgs
parents:
diff changeset
   292
    connect(mSettingsManager, SIGNAL(valueChanged(const XQSettingsKey&, const QVariant&)), this, SLOT(setNameFormat(const XQSettingsKey&, const QVariant&)));
hgs
parents:
diff changeset
   293
hgs
parents:
diff changeset
   294
    // connect to contacts server
hgs
parents:
diff changeset
   295
    mDbConnection = new CntSrvConnection();
hgs
parents:
diff changeset
   296
hgs
parents:
diff changeset
   297
    CNT_EXIT
hgs
parents:
diff changeset
   298
}
hgs
parents:
diff changeset
   299
hgs
parents:
diff changeset
   300
/*!
hgs
parents:
diff changeset
   301
    Destroys a CntNameFetcher object.
hgs
parents:
diff changeset
   302
 */
hgs
parents:
diff changeset
   303
CntNameFetcher::~CntNameFetcher()
hgs
parents:
diff changeset
   304
{
hgs
parents:
diff changeset
   305
    CNT_ENTRY
hgs
parents:
diff changeset
   306
hgs
parents:
diff changeset
   307
    delete mSettingsManager;
hgs
parents:
diff changeset
   308
    delete mNameFormatSetting;
hgs
parents:
diff changeset
   309
    delete mDbConnection;
hgs
parents:
diff changeset
   310
    delete mAsynchDbConnection;
hgs
parents:
diff changeset
   311
hgs
parents:
diff changeset
   312
    CNT_EXIT
hgs
parents:
diff changeset
   313
}
hgs
parents:
diff changeset
   314
hgs
parents:
diff changeset
   315
/*!
hgs
parents:
diff changeset
   316
    Reads names from the file cache.
hgs
parents:
diff changeset
   317
hgs
parents:
diff changeset
   318
    \return true if the names were read successfully from the cache file
hgs
parents:
diff changeset
   319
hgs
parents:
diff changeset
   320
 */
hgs
parents:
diff changeset
   321
bool CntNameFetcher::readNamesFromCache(QList<CntNameCacheItem*> &names)
hgs
parents:
diff changeset
   322
{
hgs
parents:
diff changeset
   323
    CNT_ENTRY
hgs
parents:
diff changeset
   324
hgs
parents:
diff changeset
   325
    bool success = true;
hgs
parents:
diff changeset
   326
    quint32 itemCount;
hgs
parents:
diff changeset
   327
    quint32 nameFormat;
hgs
parents:
diff changeset
   328
hgs
parents:
diff changeset
   329
    QFile cacheFile(XQUtils::phoneMemoryRootPath() + cacheFolder + "\\" + cacheFilename);
hgs
parents:
diff changeset
   330
    if (!cacheFile.open(QIODevice::ReadOnly)) {
hgs
parents:
diff changeset
   331
        return false;
hgs
parents:
diff changeset
   332
    }
hgs
parents:
diff changeset
   333
hgs
parents:
diff changeset
   334
    QDataStream in(&cacheFile);
hgs
parents:
diff changeset
   335
hgs
parents:
diff changeset
   336
    mBufferSizeEstimate = 0;
hgs
parents:
diff changeset
   337
    QT_TRY {
hgs
parents:
diff changeset
   338
        // read header: nr of items, name format
hgs
parents:
diff changeset
   339
        in >> itemCount;
hgs
parents:
diff changeset
   340
        in >> nameFormat;
hgs
parents:
diff changeset
   341
        names.reserve(itemCount);
hgs
parents:
diff changeset
   342
hgs
parents:
diff changeset
   343
        // populate list with names
hgs
parents:
diff changeset
   344
        while (itemCount-- > 0) {
hgs
parents:
diff changeset
   345
            CntNameCacheItem *item = CntNameCacheItem::internalize(in, (CntNameOrder) nameFormat);
hgs
parents:
diff changeset
   346
            names.append(item);
hgs
parents:
diff changeset
   347
            mBufferSizeEstimate += 4 + 2 * item->name().length();
hgs
parents:
diff changeset
   348
        }
hgs
parents:
diff changeset
   349
    } QT_CATCH (...) {
hgs
parents:
diff changeset
   350
        qDeleteAll(names);
hgs
parents:
diff changeset
   351
        names.clear();
hgs
parents:
diff changeset
   352
        success = false;
hgs
parents:
diff changeset
   353
    }
hgs
parents:
diff changeset
   354
    
hgs
parents:
diff changeset
   355
    cacheFile.close();
hgs
parents:
diff changeset
   356
    
hgs
parents:
diff changeset
   357
    CNT_EXIT
hgs
parents:
diff changeset
   358
    
hgs
parents:
diff changeset
   359
    return success;
hgs
parents:
diff changeset
   360
}
hgs
parents:
diff changeset
   361
hgs
parents:
diff changeset
   362
/*!
hgs
parents:
diff changeset
   363
    Write names to the file cache.
hgs
parents:
diff changeset
   364
 */
hgs
parents:
diff changeset
   365
bool CntNameFetcher::writeNamesToCache(const QList<CntNameCacheItem*> &names) const
hgs
parents:
diff changeset
   366
{
hgs
parents:
diff changeset
   367
    CNT_ENTRY
hgs
parents:
diff changeset
   368
hgs
parents:
diff changeset
   369
    bool success = true;
hgs
parents:
diff changeset
   370
hgs
parents:
diff changeset
   371
    // create folder for cache file if it does not already exist
hgs
parents:
diff changeset
   372
    QString path = XQUtils::phoneMemoryRootPath() + cacheFolder;
hgs
parents:
diff changeset
   373
    if (!QDir(path).exists()) {
hgs
parents:
diff changeset
   374
        QDir dir(XQUtils::phoneMemoryRootPath());
hgs
parents:
diff changeset
   375
        if (!dir.mkdir(cacheFolder)) {
hgs
parents:
diff changeset
   376
            CNT_EXIT_ARGS("failed to create folder: " << path)
hgs
parents:
diff changeset
   377
            return false;
hgs
parents:
diff changeset
   378
        }
hgs
parents:
diff changeset
   379
hgs
parents:
diff changeset
   380
        // have to use native Symbian code to make the dir hidden
hgs
parents:
diff changeset
   381
        RFs fs;
hgs
parents:
diff changeset
   382
        fs.Connect();
hgs
parents:
diff changeset
   383
        TPtrC pathPtr(path.utf16(), path.length());
hgs
parents:
diff changeset
   384
        if (fs.SetAtt(pathPtr, KEntryAttHidden, 0) != KErrNone) {
hgs
parents:
diff changeset
   385
            fs.Close();
hgs
parents:
diff changeset
   386
            return false;
hgs
parents:
diff changeset
   387
        }
hgs
parents:
diff changeset
   388
        fs.Close();
hgs
parents:
diff changeset
   389
    }    
hgs
parents:
diff changeset
   390
hgs
parents:
diff changeset
   391
    // open cache file for writing
hgs
parents:
diff changeset
   392
    QFile cacheFile(XQUtils::phoneMemoryRootPath() + cacheFolder + "\\" + cacheFilename);
hgs
parents:
diff changeset
   393
    if (!cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
hgs
parents:
diff changeset
   394
        CNT_EXIT_ARGS("failed to create file")
hgs
parents:
diff changeset
   395
        return false;
hgs
parents:
diff changeset
   396
    }
hgs
parents:
diff changeset
   397
    QDataStream out(&cacheFile);
hgs
parents:
diff changeset
   398
hgs
parents:
diff changeset
   399
    // write the names to the cache file
hgs
parents:
diff changeset
   400
    QT_TRY {
hgs
parents:
diff changeset
   401
        // write header
hgs
parents:
diff changeset
   402
        out << names.size();
hgs
parents:
diff changeset
   403
        out << (quint32) mNameFormat;
hgs
parents:
diff changeset
   404
hgs
parents:
diff changeset
   405
        // write list with names
hgs
parents:
diff changeset
   406
        foreach (CntNameCacheItem* name, names) {
hgs
parents:
diff changeset
   407
            name->externalize(out);
hgs
parents:
diff changeset
   408
        }
hgs
parents:
diff changeset
   409
    } QT_CATCH (...) {
hgs
parents:
diff changeset
   410
        success = false;
hgs
parents:
diff changeset
   411
    }
hgs
parents:
diff changeset
   412
hgs
parents:
diff changeset
   413
    cacheFile.close();
hgs
parents:
diff changeset
   414
hgs
parents:
diff changeset
   415
    CNT_EXIT
hgs
parents:
diff changeset
   416
hgs
parents:
diff changeset
   417
    return success;
hgs
parents:
diff changeset
   418
}
hgs
parents:
diff changeset
   419
hgs
parents:
diff changeset
   420
/*!
hgs
parents:
diff changeset
   421
    Reads the name of one contact from the contact database synchronously.
hgs
parents:
diff changeset
   422
    
hgs
parents:
diff changeset
   423
    \param contactId the id of the contact
hgs
parents:
diff changeset
   424
 */
hgs
parents:
diff changeset
   425
CntNameCacheItem* CntNameFetcher::readOneName(QContactLocalId contactId) const
hgs
parents:
diff changeset
   426
{
hgs
parents:
diff changeset
   427
    CNT_ENTRY
hgs
parents:
diff changeset
   428
hgs
parents:
diff changeset
   429
    QString sqlQuery = QString("SELECT contact_id, first_name, last_name FROM contact WHERE (type_flags>>24)<=1 AND contact_id=%1").arg(contactId);
hgs
parents:
diff changeset
   430
    mDbConnection->executeSqlQuery(sqlQuery, mNameFormat, 2);
hgs
parents:
diff changeset
   431
    
hgs
parents:
diff changeset
   432
    if (mDbConnection->names().size() == 0) {
hgs
parents:
diff changeset
   433
        return NULL;
hgs
parents:
diff changeset
   434
    }
hgs
parents:
diff changeset
   435
hgs
parents:
diff changeset
   436
    CNT_EXIT
hgs
parents:
diff changeset
   437
    
hgs
parents:
diff changeset
   438
    return mDbConnection->names().at(0);
hgs
parents:
diff changeset
   439
}
hgs
parents:
diff changeset
   440
hgs
parents:
diff changeset
   441
/*!
hgs
parents:
diff changeset
   442
    Reads the names of all contacts from the contact database asynchronously.
hgs
parents:
diff changeset
   443
 */
hgs
parents:
diff changeset
   444
void CntNameFetcher::readAllNamesAsynch()
hgs
parents:
diff changeset
   445
{
hgs
parents:
diff changeset
   446
    CNT_ENTRY
hgs
parents:
diff changeset
   447
    
hgs
parents:
diff changeset
   448
    if (mAsynchDbConnection != NULL) {
hgs
parents:
diff changeset
   449
        // an asynch fetch is already in progress, so no need to start a new one
hgs
parents:
diff changeset
   450
        return;
hgs
parents:
diff changeset
   451
    }
hgs
parents:
diff changeset
   452
    
hgs
parents:
diff changeset
   453
    if (mBufferSizeEstimate == 0) {
hgs
parents:
diff changeset
   454
        mBufferSizeEstimate = 240 * 1024;
hgs
parents:
diff changeset
   455
    }
hgs
parents:
diff changeset
   456
    
hgs
parents:
diff changeset
   457
    CNT_LOG_ARGS("buffer size =" << mBufferSizeEstimate)
hgs
parents:
diff changeset
   458
    
hgs
parents:
diff changeset
   459
    mAsynchDbConnection = new CntSrvConnection();
hgs
parents:
diff changeset
   460
    mAsynchDbConnection->setAsynchronous();
hgs
parents:
diff changeset
   461
    connect(mAsynchDbConnection, SIGNAL(namesRead()), this, SIGNAL(databaseAccessComplete()));
hgs
parents:
diff changeset
   462
    connect(mAsynchDbConnection, SIGNAL(namesSorted()), this, SLOT(sendCompletionSignal()));
hgs
parents:
diff changeset
   463
    mAsynchDbConnection->executeSqlQuery("SELECT contact_id, first_name, last_name FROM contact WHERE (type_flags>>24)<=1", mNameFormat, 16 + mBufferSizeEstimate / 1024);
hgs
parents:
diff changeset
   464
    
hgs
parents:
diff changeset
   465
    CNT_EXIT
hgs
parents:
diff changeset
   466
}
hgs
parents:
diff changeset
   467
hgs
parents:
diff changeset
   468
/*!
hgs
parents:
diff changeset
   469
    Sorts the names quickly and in a locale aware manner.
hgs
parents:
diff changeset
   470
 */
hgs
parents:
diff changeset
   471
void CntNameFetcher::sortNames(QList<CntNameCacheItem *> &names) const
hgs
parents:
diff changeset
   472
{
hgs
parents:
diff changeset
   473
    CNT_ENTRY
hgs
parents:
diff changeset
   474
hgs
parents:
diff changeset
   475
    qStableSort(names.begin(), names.end(), CntNameFetcher::compareNames);
hgs
parents:
diff changeset
   476
hgs
parents:
diff changeset
   477
    CNT_EXIT
hgs
parents:
diff changeset
   478
}
hgs
parents:
diff changeset
   479
hgs
parents:
diff changeset
   480
/*! 
hgs
parents:
diff changeset
   481
    Compares a pair of contact names and returns true if the first
hgs
parents:
diff changeset
   482
    one should be presented before the second one in a list. This
hgs
parents:
diff changeset
   483
    static function is used e.g. when sorting lists of names.
hgs
parents:
diff changeset
   484
 */
hgs
parents:
diff changeset
   485
bool CntNameFetcher::compareNames(const CntNameCacheItem* a, const CntNameCacheItem* b)
hgs
parents:
diff changeset
   486
{
hgs
parents:
diff changeset
   487
    QString aName = a->name();
hgs
parents:
diff changeset
   488
    QString bName = b->name();
hgs
parents:
diff changeset
   489
hgs
parents:
diff changeset
   490
    if (aName.isEmpty()) {
hgs
parents:
diff changeset
   491
        return false;
hgs
parents:
diff changeset
   492
    } else if (bName.isEmpty()) {
hgs
parents:
diff changeset
   493
        return true;
hgs
parents:
diff changeset
   494
    }
hgs
parents:
diff changeset
   495
hgs
parents:
diff changeset
   496
    return (HbStringUtil::compareC(aName, bName) < 0);
hgs
parents:
diff changeset
   497
}
hgs
parents:
diff changeset
   498
hgs
parents:
diff changeset
   499
/*!
hgs
parents:
diff changeset
   500
    Notifies clients that the name format has changed. This function is called by the framework
hgs
parents:
diff changeset
   501
    if the name format settings is changed, see the constructor.
hgs
parents:
diff changeset
   502
 */
hgs
parents:
diff changeset
   503
void CntNameFetcher::setNameFormat(const XQSettingsKey &/*key*/, const QVariant &value)
hgs
parents:
diff changeset
   504
{
hgs
parents:
diff changeset
   505
    CNT_ENTRY
hgs
parents:
diff changeset
   506
hgs
parents:
diff changeset
   507
    bool ok = false;
hgs
parents:
diff changeset
   508
    CntNameOrder newNameFormat = static_cast<CntNameOrder>(value.toInt(&ok));
hgs
parents:
diff changeset
   509
    if (ok && newNameFormat != mNameFormat) {
hgs
parents:
diff changeset
   510
        mNameFormat = newNameFormat;
hgs
parents:
diff changeset
   511
        emit nameFormatChanged(mNameFormat);
hgs
parents:
diff changeset
   512
    }
hgs
parents:
diff changeset
   513
hgs
parents:
diff changeset
   514
    CNT_EXIT
hgs
parents:
diff changeset
   515
}
hgs
parents:
diff changeset
   516
hgs
parents:
diff changeset
   517
/*!
hgs
parents:
diff changeset
   518
    Emits the results of a completed asynch database operation.
hgs
parents:
diff changeset
   519
 */
hgs
parents:
diff changeset
   520
void CntNameFetcher::sendCompletionSignal()
hgs
parents:
diff changeset
   521
{
hgs
parents:
diff changeset
   522
    CNT_ENTRY
hgs
parents:
diff changeset
   523
hgs
parents:
diff changeset
   524
    emit namesAvailable(mAsynchDbConnection->names());
hgs
parents:
diff changeset
   525
hgs
parents:
diff changeset
   526
    delete mAsynchDbConnection;
hgs
parents:
diff changeset
   527
    mAsynchDbConnection = NULL;
hgs
parents:
diff changeset
   528
hgs
parents:
diff changeset
   529
    CNT_EXIT
hgs
parents:
diff changeset
   530
}
hgs
parents:
diff changeset
   531
hgs
parents:
diff changeset
   532
/*!
hgs
parents:
diff changeset
   533
    Creates a CntNameCacheItem object.
hgs
parents:
diff changeset
   534
 */
hgs
parents:
diff changeset
   535
CntNameCacheItem::CntNameCacheItem(QContactLocalId id, const QString& firstName, const QString& lastName, CntNameOrder nameFormat)
hgs
parents:
diff changeset
   536
{
hgs
parents:
diff changeset
   537
    mContactId = id;
hgs
parents:
diff changeset
   538
    setFormattedName(firstName, lastName, nameFormat);
hgs
parents:
diff changeset
   539
}
hgs
parents:
diff changeset
   540
hgs
parents:
diff changeset
   541
/*!
hgs
parents:
diff changeset
   542
    Destroys a CntNameCacheItem object.
hgs
parents:
diff changeset
   543
 */
hgs
parents:
diff changeset
   544
CntNameCacheItem::~CntNameCacheItem()
hgs
parents:
diff changeset
   545
{
hgs
parents:
diff changeset
   546
}
hgs
parents:
diff changeset
   547
hgs
parents:
diff changeset
   548
/*!
hgs
parents:
diff changeset
   549
    Changes the format used to present the name.
hgs
parents:
diff changeset
   550
 */
hgs
parents:
diff changeset
   551
void CntNameCacheItem::setNameFormat(CntNameOrder newFormat)
hgs
parents:
diff changeset
   552
{
hgs
parents:
diff changeset
   553
    QString firstName = mName.mid(mFirstNamePosition&0xffff, mFirstNamePosition>>16);
hgs
parents:
diff changeset
   554
    QString lastName = mName.mid(mLastNamePosition&0xffff, mLastNamePosition>>16);
hgs
parents:
diff changeset
   555
    setFormattedName(firstName, lastName, newFormat);
hgs
parents:
diff changeset
   556
}
hgs
parents:
diff changeset
   557
hgs
parents:
diff changeset
   558
/*!
hgs
parents:
diff changeset
   559
    Copies the contents of the other cache item to this one.
hgs
parents:
diff changeset
   560
 */
hgs
parents:
diff changeset
   561
void CntNameCacheItem::operator=(const CntNameCacheItem &other)
hgs
parents:
diff changeset
   562
{
hgs
parents:
diff changeset
   563
    mContactId = other.mContactId;
hgs
parents:
diff changeset
   564
    mFirstNamePosition = other.mFirstNamePosition;
hgs
parents:
diff changeset
   565
    mLastNamePosition = other.mLastNamePosition;
hgs
parents:
diff changeset
   566
    mName = other.mName;
hgs
parents:
diff changeset
   567
}
hgs
parents:
diff changeset
   568
hgs
parents:
diff changeset
   569
/*!
hgs
parents:
diff changeset
   570
    Externalizes a CntNameCacheItem object.
hgs
parents:
diff changeset
   571
 */
hgs
parents:
diff changeset
   572
void CntNameCacheItem::externalize(QDataStream &stream)
hgs
parents:
diff changeset
   573
{
hgs
parents:
diff changeset
   574
    stream << mContactId;
hgs
parents:
diff changeset
   575
    stream << mFirstNamePosition;
hgs
parents:
diff changeset
   576
    stream << mLastNamePosition;
hgs
parents:
diff changeset
   577
    stream << mName;
hgs
parents:
diff changeset
   578
}
hgs
parents:
diff changeset
   579
hgs
parents:
diff changeset
   580
/*!
hgs
parents:
diff changeset
   581
    Internalizes a CntNameCacheItem object.
hgs
parents:
diff changeset
   582
 */
hgs
parents:
diff changeset
   583
CntNameCacheItem* CntNameCacheItem::internalize(QDataStream &stream, CntNameOrder nameFormat)
hgs
parents:
diff changeset
   584
{
hgs
parents:
diff changeset
   585
    quint32 id;
hgs
parents:
diff changeset
   586
    quint32 firstNamePosition;
hgs
parents:
diff changeset
   587
    quint32 lastNamePosition;
hgs
parents:
diff changeset
   588
    QString name;
hgs
parents:
diff changeset
   589
    
hgs
parents:
diff changeset
   590
    stream >> id;
hgs
parents:
diff changeset
   591
    stream >> firstNamePosition;
hgs
parents:
diff changeset
   592
    stream >> lastNamePosition;
hgs
parents:
diff changeset
   593
    stream >> name;
hgs
parents:
diff changeset
   594
    
hgs
parents:
diff changeset
   595
    QString firstName = name.mid(firstNamePosition&0xffff, firstNamePosition>>16);
hgs
parents:
diff changeset
   596
    QString lastName = name.mid(lastNamePosition&0xffff, lastNamePosition>>16);
hgs
parents:
diff changeset
   597
hgs
parents:
diff changeset
   598
    return new CntNameCacheItem(id, firstName, lastName, nameFormat);
hgs
parents:
diff changeset
   599
}
hgs
parents:
diff changeset
   600
hgs
parents:
diff changeset
   601
/*!
hgs
parents:
diff changeset
   602
    Sets the formatted name and positions of the first name and last name,
hgs
parents:
diff changeset
   603
    according to the name format in the parameter.
hgs
parents:
diff changeset
   604
 */
hgs
parents:
diff changeset
   605
void CntNameCacheItem::setFormattedName(const QString& firstName, const QString& lastName, CntNameOrder nameFormat)
hgs
parents:
diff changeset
   606
{
hgs
parents:
diff changeset
   607
    int firstNameLength = firstName.length();
hgs
parents:
diff changeset
   608
    int lastNameLength = lastName.length();
hgs
parents:
diff changeset
   609
hgs
parents:
diff changeset
   610
    if (lastNameLength == 0) {
hgs
parents:
diff changeset
   611
        mName = firstName;
hgs
parents:
diff changeset
   612
        mFirstNamePosition = firstNameLength << 16;
hgs
parents:
diff changeset
   613
        mLastNamePosition = 0;
hgs
parents:
diff changeset
   614
    } else if (firstNameLength == 0) {
hgs
parents:
diff changeset
   615
        mName = lastName;
hgs
parents:
diff changeset
   616
        mFirstNamePosition = 0;
hgs
parents:
diff changeset
   617
        mLastNamePosition = lastNameLength << 16;
hgs
parents:
diff changeset
   618
    } else {
hgs
parents:
diff changeset
   619
        if (nameFormat == CntOrderLastFirst) {
hgs
parents:
diff changeset
   620
            mName = lastName + " " + firstName;
hgs
parents:
diff changeset
   621
            mFirstNamePosition = (firstNameLength << 16) | (lastNameLength + 1);
hgs
parents:
diff changeset
   622
            mLastNamePosition = (lastNameLength << 16);
hgs
parents:
diff changeset
   623
        } else if (nameFormat == CntOrderLastCommaFirst) {
hgs
parents:
diff changeset
   624
            mName = lastName + ", " + firstName;
hgs
parents:
diff changeset
   625
            mFirstNamePosition = (firstNameLength << 16) | (lastNameLength + 2);
hgs
parents:
diff changeset
   626
            mLastNamePosition = (lastNameLength << 16);
hgs
parents:
diff changeset
   627
        } else {
hgs
parents:
diff changeset
   628
            mName = firstName + " " + lastName;
hgs
parents:
diff changeset
   629
            mFirstNamePosition = (firstNameLength << 16);
hgs
parents:
diff changeset
   630
            mLastNamePosition = (lastNameLength << 16) | (firstNameLength + 1);
hgs
parents:
diff changeset
   631
        }
hgs
parents:
diff changeset
   632
    }
hgs
parents:
diff changeset
   633
}
hgs
parents:
diff changeset
   634
hgs
parents:
diff changeset
   635
QString CntNameCacheItem::firstName() const
hgs
parents:
diff changeset
   636
{
hgs
parents:
diff changeset
   637
    return mName.mid(mFirstNamePosition&0xffff, mFirstNamePosition>>16);
hgs
parents:
diff changeset
   638
}
hgs
parents:
diff changeset
   639
hgs
parents:
diff changeset
   640
QString CntNameCacheItem::lastName() const
hgs
parents:
diff changeset
   641
{
hgs
parents:
diff changeset
   642
    return mName.mid(mLastNamePosition&0xffff, mLastNamePosition>>16);
hgs
parents:
diff changeset
   643
}