--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/cntplsql/src/cqwertypredictivesearchtable.cpp Wed Jun 23 18:02:44 2010 +0300
@@ -0,0 +1,360 @@
+/*
+* 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:
+*
+*/
+
+#include "cqwertypredictivesearchtable.h"
+#include "cqwertykeymap.h"
+#include "dbsqlconstants.h"
+#include <QStringList>
+
+// This macro suppresses own logs
+//#define NO_PRED_SEARCH_LOGS
+#include "predictivesearchlog.h"
+
+
+// Max amount of tokens stored from contact
+const TInt KMaxTokens = 7;
+// Max amount of mail addresses stored from contact
+const TInt KMaxMailAddresses = 3;
+
+// How many characters are stored at most in the tokens
+// Since BIGINT is a signed 64-bit integer, store only 10 characters
+// to prevent overflow when comparing upper and lower limits.
+const TInt KMaxTokenLength = 10;
+
+// Template for table names
+const TInt KMaxTableNameLength = 4;
+_LIT(KTableNameFormat, "qm%d");
+
+// Template for create table commands
+_LIT(KPredSearchCreateQwertyMailTableFormat,
+"CREATE TABLE %S (contact_id INTEGER PRIMARY KEY,\
+ n BIGINT NULL, n2 BIGINT NULL, n3 BIGINT NULL, n4 BIGINT NULL,\
+ n5 BIGINT NULL, n6 BIGINT NULL, n7 BIGINT NULL,\
+ first_name CHAR(16) NULL, last_name CHAR(16) NULL);");
+
+// Template for index names
+// e.g. index0_n2
+_LIT(KIndexNameFormat, "index%d_%S");
+
+// Template for create index commands
+// CREATE INDEX <index name> on <table> (<column>);");
+_LIT(KPredSearchCreateQwertyMailIndexFormat, "CREATE INDEX %S on %S (%S);");
+
+const QString KMailPrefix = "mailto:";
+
+
+/**
+@param aDatabase A handle to the database.
+@param aProperties A contact properties object.
+
+@return A pointer to a new CQwertyPredictiveSearchTable object.
+*/
+CQwertyPredictiveSearchTable*
+CQwertyPredictiveSearchTable::NewL(RSqlDatabase& aDatabase)
+ {
+ PRINT(_L("CQwertyPredictiveSearchTable::NewL"));
+ CQwertyPredictiveSearchTable* self = CQwertyPredictiveSearchTable::NewLC(aDatabase);
+ CleanupStack::Pop(self);
+ PRINT(_L("CQwertyPredictiveSearchTable::NewL ends"));
+ return self;
+ }
+
+
+/**
+@param aDatabase A handle to the database.
+@param aProperties A contact properties object.
+
+@return A pointer to a new CQwertyPredictiveSearchTable object.
+*/
+CQwertyPredictiveSearchTable*
+CQwertyPredictiveSearchTable::NewLC(RSqlDatabase& aDatabase)
+ {
+ PRINT(_L("CQwertyPredictiveSearchTable::NewLC"));
+ CQwertyPredictiveSearchTable* self =
+ new (ELeave) CQwertyPredictiveSearchTable(aDatabase);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ PRINT(_L("CQwertyPredictiveSearchTable::NewLC ends"));
+ return self;
+ }
+
+
+/**
+Destructor
+*/
+CQwertyPredictiveSearchTable::~CQwertyPredictiveSearchTable()
+ {
+ PRINT(_L("CQwertyPredictiveSearchTable dtor"));
+ PRINT(_L("CQwertyPredictiveSearchTable dtor ends"));
+ }
+
+
+/**
+Create the QWERTY tables and its indexes in the database.
+*/
+void CQwertyPredictiveSearchTable::CreateTableL()
+ {
+ PRINT(_L("CQwertyPredictiveSearchTable::CreateTableL"));
+
+ // How many columns have index
+ const TInt KIndexedColumnCount = 9;
+ // Names of columns that have index
+ const TDesC* indexColumns[] = {
+ &KPredSearchQwertyMailNameAsNumber,
+ &KPredSearchQwertyMailNameAsNumber2,
+ &KPredSearchQwertyMailNameAsNumber3,
+ &KPredSearchQwertyMailNameAsNumber4,
+ &KPredSearchQwertyMailNameAsNumber5,
+ &KPredSearchQwertyMailNameAsNumber6,
+ &KPredSearchQwertyMailNameAsNumber7,
+ &KPredSearchQwertyMailFirstName,
+ &KPredSearchQwertyMailLastName};
+
+ TInt maxColumnLength(0); // Length of longest column name
+ for (TInt column = 0; column < KIndexedColumnCount; ++column)
+ {
+ TInt columnNameLength = indexColumns[column]->Length();
+ if (columnNameLength > maxColumnLength)
+ {
+ maxColumnLength = columnNameLength;
+ }
+ }
+
+ // Space needed to represent number CQwertyKeyMap::EAmountOfKeysInQwertyKeypad
+ const TInt KCharsNeededForTableNumber = 2;
+ const TInt KMaxIndexNameLength =
+ KIndexNameFormat().Length() + maxColumnLength + KCharsNeededForTableNumber;
+
+ HBufC* tableName = HBufC::NewLC(KMaxTableNameLength);
+ TPtr ptrTableName = tableName->Des();
+ HBufC* createTableCmd =
+ HBufC::NewLC(KPredSearchCreateQwertyMailTableFormat().Length() +
+ KMaxTableNameLength);
+ TPtr ptrCreateTableCmd = createTableCmd->Des();
+
+ HBufC* indexName = HBufC::NewLC(KMaxIndexNameLength);
+ TPtr ptrIndexName = indexName->Des();
+ HBufC* createIndexCmd = HBufC::NewLC(KPredSearchCreateQwertyMailIndexFormat().Length() +
+ KMaxIndexNameLength +
+ KMaxTableNameLength +
+ maxColumnLength);
+ TPtr ptrCreateIndexCmd = createIndexCmd->Des();
+
+ for (TInt table = 0; table < CQwertyKeyMap::EAmountOfKeysInQwertyKeypad; ++table)
+ {
+ ptrTableName.Format(KTableNameFormat, table);
+
+ ptrCreateTableCmd.Format(KPredSearchCreateQwertyMailTableFormat, tableName);
+ PRINT1(_L("SQL command: %S"), createTableCmd);
+ User::LeaveIfError(iDatabase.Exec(*createTableCmd));
+
+ // Create indexes for each required column of the current table
+ for (TInt column = 0; column < KIndexedColumnCount; ++column)
+ {
+ ptrIndexName.Format(KIndexNameFormat, table, indexColumns[column]);
+
+ ptrCreateIndexCmd.Format(KPredSearchCreateQwertyMailIndexFormat,
+ indexName, tableName, indexColumns[column]);
+// PRINT1(_L("SQL command: %S"), createIndexCmd);
+ User::LeaveIfError(iDatabase.Exec(*createIndexCmd));
+ }
+ }
+ CleanupStack::PopAndDestroy(createIndexCmd);
+ CleanupStack::PopAndDestroy(indexName);
+ CleanupStack::PopAndDestroy(createTableCmd);
+ CleanupStack::PopAndDestroy(tableName);
+
+ PRINT(_L("CQwertyPredictiveSearchTable::CreateTableL ends"));
+ }
+
+
+TBool CQwertyPredictiveSearchTable::IsValidChar(const QChar aChar) const
+ {
+#if defined(USE_ORBIT_KEYMAP)
+ return static_cast<CQwertyKeyMap*>(iKeyMap)->IsValidChar(aChar);
+#else
+ const QChar PAD_CHAR = '!'; // This is a hack, must have same value as in cqwertykeymap.cpp
+ return static_cast<CQwertyKeyMap*>(iKeyMap)->UseHardcodedKeyMap(aChar) != PAD_CHAR;
+#endif
+ }
+
+
+HBufC* CQwertyPredictiveSearchTable::TableNameL(const QChar aCh) const
+ {
+ TInt tableNumber = static_cast<CQwertyKeyMap*>(iKeyMap)->MapKeyNameToValue(aCh);
+ if (tableNumber == CQwertyKeyMap::KPadCharValue)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ HBufC* tableName = HBufC::NewL(KMaxTableNameLength);
+ TPtr ptrTableName = tableName->Des();
+ ptrTableName.Format(KTableNameFormat, tableNumber);
+ return tableName;
+ }
+
+
+QList<QChar> CQwertyPredictiveSearchTable::FillAllTables() const
+ {
+ QList<QChar> tables;
+
+ for (TInt key = 0; key < CQwertyKeyMap::EAmountOfKeysInQwertyKeypad; ++key)
+ {
+ tables.append(iKeyMap->ArrayIndexToMappedChar(key));
+ }
+
+ return tables;
+ }
+
+
+void CQwertyPredictiveSearchTable::FillKeyboardSpecificFieldsL(
+ RSqlStatement& aSqlStatement,
+ QStringList aTokens)
+ {
+ const TDesC* paramNames[] = {
+ &KPredSearchQwertyMailNameAsNumberParam,
+ &KPredSearchQwertyMailNameAsNumberParam2,
+ &KPredSearchQwertyMailNameAsNumberParam3,
+ &KPredSearchQwertyMailNameAsNumberParam4,
+ &KPredSearchQwertyMailNameAsNumberParam5,
+ &KPredSearchQwertyMailNameAsNumberParam6,
+ &KPredSearchQwertyMailNameAsNumberParam7};
+ for (TInt i = 0; i < aTokens.count(); ++i)
+ {
+ // TODO: It'd be better to add new fn into CQwertyKeyMap, that computes
+ // the qint64 value like CQwertyKeyMap::ComputeValue().
+ QString dummyLowerLimit;
+ QString upperLimit;
+ User::LeaveIfError(iKeyMap->GetNumericLimits(aTokens[i],
+ dummyLowerLimit,
+ upperLimit));
+ bool ok(false);
+ qint64 value(0); // qint64 is same as qlonglong
+ QT_TRYCATCH_LEAVING(value = upperLimit.toLongLong(&ok));
+ if (!ok)
+ {
+ User::Leave(KErrArgument);
+ }
+ // Decrement by one to get the correct value
+ User::LeaveIfError(aSqlStatement.BindInt64(
+ User::LeaveIfError(aSqlStatement.ParameterIndex(*paramNames[i])), --value));
+ }
+ }
+
+
+/**
+* Fetch up to 3 mail addresses
+*/
+QStringList CQwertyPredictiveSearchTable::GetTableSpecificFields(
+ const CContactItem& aItem,
+ TBool& aMandatoryFieldsPresent) const
+ {
+ PRINT(_L("CQwertyPredictiveSearchTable::GetTableSpecificFields"));
+
+ QStringList mailAddresses;
+
+ // Check that the contact item is a card, own card or ICC entry.
+ const TUid KType = aItem.Type();
+ if (KType != KUidContactCard &&
+ KType != KUidContactOwnCard &&
+ KType != KUidContactICCEntry)
+ {
+ aMandatoryFieldsPresent = EFalse;
+ return mailAddresses;
+ }
+
+ TInt storedAddressCount(0);
+ for (TInt i = aItem.CardFields().Count();
+ i > 0 && storedAddressCount < KMaxMailAddresses;
+ --i)
+ {
+ CContactItemField& field = aItem.CardFields()[i - 1];
+ if (field.ContentType().ContainsFieldType(KUidContactFieldEMail) &&
+ field.StorageType() == KStorageTypeText &&
+ field.TextStorage()->IsFull()) // IsFull() returns true if field not empty
+ {
+ TPtrC mailAddress = field.TextStorage()->Text();
+ PRINT2(_L("contact id=%d has mail='%S'"), aItem.Id(), &mailAddress);
+
+ QString wholeAddress((QChar*)mailAddress.Ptr(), mailAddress.Length());
+ QString address = wholeAddress;
+ if (wholeAddress.startsWith(KMailPrefix)) // Skip prefix
+ {
+ address = wholeAddress.mid(KMailPrefix.length());
+#if defined(WRITE_PRED_SEARCH_LOGS)
+ const TInt KLogLength = 40;
+ TBuf<KLogLength> log(address.left(KLogLength).utf16());
+ PRINT1(_L("prefix removed, mail='%S'"), &log);
+#endif
+ }
+ mailAddresses.append(iKeyMap->GetMappedString(address));
+ ++storedAddressCount;
+ }
+ }
+ PRINT1(_L("CQwertyPredictiveSearchTable::GetTableSpecificFields found %d mail addrs"),
+ mailAddresses.count());
+ aMandatoryFieldsPresent = (mailAddresses.count() > 0);
+ return mailAddresses;
+ }
+
+
+/**
+Set up the CCntSqlStatement objects held by the class.
+*/
+void CQwertyPredictiveSearchTable::ConstructL()
+ {
+ PRINT(_L("CQwertyPredictiveSearchTable::ConstructL"));
+
+ CPplPredictiveSearchTableBase::ConstructL();
+
+ // Set details of INSERT
+ iInsertStmnt->SetParamL(KPredSearchQwertyMailContactId,
+ KPredSearchQwertyMailContactIdParam);
+ iInsertStmnt->SetParamL(KPredSearchQwertyMailNameAsNumber,
+ KPredSearchQwertyMailNameAsNumberParam);
+ iInsertStmnt->SetParamL(KPredSearchQwertyMailNameAsNumber2,
+ KPredSearchQwertyMailNameAsNumberParam2);
+ iInsertStmnt->SetParamL(KPredSearchQwertyMailNameAsNumber3,
+ KPredSearchQwertyMailNameAsNumberParam3);
+ iInsertStmnt->SetParamL(KPredSearchQwertyMailNameAsNumber4,
+ KPredSearchQwertyMailNameAsNumberParam4);
+ iInsertStmnt->SetParamL(KPredSearchQwertyMailNameAsNumber5,
+ KPredSearchQwertyMailNameAsNumberParam5);
+ iInsertStmnt->SetParamL(KPredSearchQwertyMailNameAsNumber6,
+ KPredSearchQwertyMailNameAsNumberParam6);
+ iInsertStmnt->SetParamL(KPredSearchQwertyMailNameAsNumber7,
+ KPredSearchQwertyMailNameAsNumberParam7);
+
+ iInsertStmnt->SetParamL(KPredSearchQwertyMailFirstName,
+ KPredSearchQwertyMailFirstNameParam);
+ iInsertStmnt->SetParamL(KPredSearchQwertyMailLastName,
+ KPredSearchQwertyMailLastNameParam);
+
+ PRINT(_L("CQwertyPredictiveSearchTable::ConstructL create key map"));
+ iKeyMap = CQwertyKeyMap::NewL();
+
+ PRINT(_L("CQwertyPredictiveSearchTable::ConstructL ends"));
+ }
+
+
+/**
+Constructor
+*/
+CQwertyPredictiveSearchTable::CQwertyPredictiveSearchTable(RSqlDatabase& aDatabase) :
+ CPplPredictiveSearchTableBase(aDatabase, KMaxTokens, KMaxTokenLength)
+ {
+ }