|
1 /* |
|
2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 #include "cqwertypredictivesearchtable.h" |
|
19 #include "cqwertykeymap.h" |
|
20 #include "dbsqlconstants.h" |
|
21 #include <QStringList> |
|
22 |
|
23 // This macro suppresses own logs |
|
24 //#define NO_PRED_SEARCH_LOGS |
|
25 #include "predictivesearchlog.h" |
|
26 |
|
27 |
|
28 // Max amount of tokens stored from contact |
|
29 const TInt KMaxTokens = 7; |
|
30 // Max amount of mail addresses stored from contact |
|
31 const TInt KMaxMailAddresses = 3; |
|
32 |
|
33 // How many characters are stored at most in the tokens |
|
34 // Since BIGINT is a signed 64-bit integer, store only 10 characters |
|
35 // to prevent overflow when comparing upper and lower limits. |
|
36 const TInt KMaxTokenLength = 10; |
|
37 |
|
38 // Template for table names |
|
39 const TInt KMaxTableNameLength = 4; |
|
40 _LIT(KTableNameFormat, "qm%d"); |
|
41 |
|
42 // Template for create table commands |
|
43 _LIT(KPredSearchCreateQwertyMailTableFormat, |
|
44 "CREATE TABLE %S (contact_id INTEGER PRIMARY KEY,\ |
|
45 n BIGINT NULL, n2 BIGINT NULL, n3 BIGINT NULL, n4 BIGINT NULL,\ |
|
46 n5 BIGINT NULL, n6 BIGINT NULL, n7 BIGINT NULL,\ |
|
47 first_name CHAR(16) NULL, last_name CHAR(16) NULL);"); |
|
48 |
|
49 // Template for index names |
|
50 // e.g. index0_n2 |
|
51 _LIT(KIndexNameFormat, "index%d_%S"); |
|
52 |
|
53 // Template for create index commands |
|
54 // CREATE INDEX <index name> on <table> (<column>);"); |
|
55 _LIT(KPredSearchCreateQwertyMailIndexFormat, "CREATE INDEX %S on %S (%S);"); |
|
56 |
|
57 const QString KMailPrefix = "mailto:"; |
|
58 |
|
59 |
|
60 /** |
|
61 @param aDatabase A handle to the database. |
|
62 @param aProperties A contact properties object. |
|
63 |
|
64 @return A pointer to a new CQwertyPredictiveSearchTable object. |
|
65 */ |
|
66 CQwertyPredictiveSearchTable* |
|
67 CQwertyPredictiveSearchTable::NewL(RSqlDatabase& aDatabase) |
|
68 { |
|
69 PRINT(_L("CQwertyPredictiveSearchTable::NewL")); |
|
70 CQwertyPredictiveSearchTable* self = CQwertyPredictiveSearchTable::NewLC(aDatabase); |
|
71 CleanupStack::Pop(self); |
|
72 PRINT(_L("CQwertyPredictiveSearchTable::NewL ends")); |
|
73 return self; |
|
74 } |
|
75 |
|
76 |
|
77 /** |
|
78 @param aDatabase A handle to the database. |
|
79 @param aProperties A contact properties object. |
|
80 |
|
81 @return A pointer to a new CQwertyPredictiveSearchTable object. |
|
82 */ |
|
83 CQwertyPredictiveSearchTable* |
|
84 CQwertyPredictiveSearchTable::NewLC(RSqlDatabase& aDatabase) |
|
85 { |
|
86 PRINT(_L("CQwertyPredictiveSearchTable::NewLC")); |
|
87 CQwertyPredictiveSearchTable* self = |
|
88 new (ELeave) CQwertyPredictiveSearchTable(aDatabase); |
|
89 CleanupStack::PushL(self); |
|
90 self->ConstructL(); |
|
91 PRINT(_L("CQwertyPredictiveSearchTable::NewLC ends")); |
|
92 return self; |
|
93 } |
|
94 |
|
95 |
|
96 /** |
|
97 Destructor |
|
98 */ |
|
99 CQwertyPredictiveSearchTable::~CQwertyPredictiveSearchTable() |
|
100 { |
|
101 PRINT(_L("CQwertyPredictiveSearchTable dtor")); |
|
102 PRINT(_L("CQwertyPredictiveSearchTable dtor ends")); |
|
103 } |
|
104 |
|
105 |
|
106 /** |
|
107 Create the QWERTY tables and its indexes in the database. |
|
108 */ |
|
109 void CQwertyPredictiveSearchTable::CreateTableL() |
|
110 { |
|
111 PRINT(_L("CQwertyPredictiveSearchTable::CreateTableL")); |
|
112 |
|
113 // How many columns have index |
|
114 const TInt KIndexedColumnCount = 9; |
|
115 // Names of columns that have index |
|
116 const TDesC* indexColumns[] = { |
|
117 &KPredSearchQwertyMailNameAsNumber, |
|
118 &KPredSearchQwertyMailNameAsNumber2, |
|
119 &KPredSearchQwertyMailNameAsNumber3, |
|
120 &KPredSearchQwertyMailNameAsNumber4, |
|
121 &KPredSearchQwertyMailNameAsNumber5, |
|
122 &KPredSearchQwertyMailNameAsNumber6, |
|
123 &KPredSearchQwertyMailNameAsNumber7, |
|
124 &KPredSearchQwertyMailFirstName, |
|
125 &KPredSearchQwertyMailLastName}; |
|
126 |
|
127 TInt maxColumnLength(0); // Length of longest column name |
|
128 for (TInt column = 0; column < KIndexedColumnCount; ++column) |
|
129 { |
|
130 TInt columnNameLength = indexColumns[column]->Length(); |
|
131 if (columnNameLength > maxColumnLength) |
|
132 { |
|
133 maxColumnLength = columnNameLength; |
|
134 } |
|
135 } |
|
136 |
|
137 // Space needed to represent number CQwertyKeyMap::EAmountOfKeysInQwertyKeypad |
|
138 const TInt KCharsNeededForTableNumber = 2; |
|
139 const TInt KMaxIndexNameLength = |
|
140 KIndexNameFormat().Length() + maxColumnLength + KCharsNeededForTableNumber; |
|
141 |
|
142 HBufC* tableName = HBufC::NewLC(KMaxTableNameLength); |
|
143 TPtr ptrTableName = tableName->Des(); |
|
144 HBufC* createTableCmd = |
|
145 HBufC::NewLC(KPredSearchCreateQwertyMailTableFormat().Length() + |
|
146 KMaxTableNameLength); |
|
147 TPtr ptrCreateTableCmd = createTableCmd->Des(); |
|
148 |
|
149 HBufC* indexName = HBufC::NewLC(KMaxIndexNameLength); |
|
150 TPtr ptrIndexName = indexName->Des(); |
|
151 HBufC* createIndexCmd = HBufC::NewLC(KPredSearchCreateQwertyMailIndexFormat().Length() + |
|
152 KMaxIndexNameLength + |
|
153 KMaxTableNameLength + |
|
154 maxColumnLength); |
|
155 TPtr ptrCreateIndexCmd = createIndexCmd->Des(); |
|
156 |
|
157 for (TInt table = 0; table < CQwertyKeyMap::EAmountOfKeysInQwertyKeypad; ++table) |
|
158 { |
|
159 ptrTableName.Format(KTableNameFormat, table); |
|
160 |
|
161 ptrCreateTableCmd.Format(KPredSearchCreateQwertyMailTableFormat, tableName); |
|
162 PRINT1(_L("SQL command: %S"), createTableCmd); |
|
163 User::LeaveIfError(iDatabase.Exec(*createTableCmd)); |
|
164 |
|
165 // Create indexes for each required column of the current table |
|
166 for (TInt column = 0; column < KIndexedColumnCount; ++column) |
|
167 { |
|
168 ptrIndexName.Format(KIndexNameFormat, table, indexColumns[column]); |
|
169 |
|
170 ptrCreateIndexCmd.Format(KPredSearchCreateQwertyMailIndexFormat, |
|
171 indexName, tableName, indexColumns[column]); |
|
172 // PRINT1(_L("SQL command: %S"), createIndexCmd); |
|
173 User::LeaveIfError(iDatabase.Exec(*createIndexCmd)); |
|
174 } |
|
175 } |
|
176 CleanupStack::PopAndDestroy(createIndexCmd); |
|
177 CleanupStack::PopAndDestroy(indexName); |
|
178 CleanupStack::PopAndDestroy(createTableCmd); |
|
179 CleanupStack::PopAndDestroy(tableName); |
|
180 |
|
181 PRINT(_L("CQwertyPredictiveSearchTable::CreateTableL ends")); |
|
182 } |
|
183 |
|
184 |
|
185 TBool CQwertyPredictiveSearchTable::IsValidChar(const QChar aChar) const |
|
186 { |
|
187 #if defined(USE_ORBIT_KEYMAP) |
|
188 return static_cast<CQwertyKeyMap*>(iKeyMap)->IsValidChar(aChar); |
|
189 #else |
|
190 const QChar PAD_CHAR = '!'; // This is a hack, must have same value as in cqwertykeymap.cpp |
|
191 return static_cast<CQwertyKeyMap*>(iKeyMap)->UseHardcodedKeyMap(aChar) != PAD_CHAR; |
|
192 #endif |
|
193 } |
|
194 |
|
195 |
|
196 HBufC* CQwertyPredictiveSearchTable::TableNameL(const QChar aCh) const |
|
197 { |
|
198 TInt tableNumber = static_cast<CQwertyKeyMap*>(iKeyMap)->MapKeyNameToValue(aCh); |
|
199 if (tableNumber == CQwertyKeyMap::KPadCharValue) |
|
200 { |
|
201 User::Leave(KErrArgument); |
|
202 } |
|
203 |
|
204 HBufC* tableName = HBufC::NewL(KMaxTableNameLength); |
|
205 TPtr ptrTableName = tableName->Des(); |
|
206 ptrTableName.Format(KTableNameFormat, tableNumber); |
|
207 return tableName; |
|
208 } |
|
209 |
|
210 |
|
211 QList<QChar> CQwertyPredictiveSearchTable::FillAllTables() const |
|
212 { |
|
213 QList<QChar> tables; |
|
214 |
|
215 for (TInt key = 0; key < CQwertyKeyMap::EAmountOfKeysInQwertyKeypad; ++key) |
|
216 { |
|
217 tables.append(iKeyMap->ArrayIndexToMappedChar(key)); |
|
218 } |
|
219 |
|
220 return tables; |
|
221 } |
|
222 |
|
223 |
|
224 void CQwertyPredictiveSearchTable::FillKeyboardSpecificFieldsL( |
|
225 RSqlStatement& aSqlStatement, |
|
226 QStringList aTokens) |
|
227 { |
|
228 const TDesC* paramNames[] = { |
|
229 &KPredSearchQwertyMailNameAsNumberParam, |
|
230 &KPredSearchQwertyMailNameAsNumberParam2, |
|
231 &KPredSearchQwertyMailNameAsNumberParam3, |
|
232 &KPredSearchQwertyMailNameAsNumberParam4, |
|
233 &KPredSearchQwertyMailNameAsNumberParam5, |
|
234 &KPredSearchQwertyMailNameAsNumberParam6, |
|
235 &KPredSearchQwertyMailNameAsNumberParam7}; |
|
236 for (TInt i = 0; i < aTokens.count(); ++i) |
|
237 { |
|
238 // TODO: It'd be better to add new fn into CQwertyKeyMap, that computes |
|
239 // the qint64 value like CQwertyKeyMap::ComputeValue(). |
|
240 QString dummyLowerLimit; |
|
241 QString upperLimit; |
|
242 User::LeaveIfError(iKeyMap->GetNumericLimits(aTokens[i], |
|
243 dummyLowerLimit, |
|
244 upperLimit)); |
|
245 bool ok(false); |
|
246 qint64 value(0); // qint64 is same as qlonglong |
|
247 QT_TRYCATCH_LEAVING(value = upperLimit.toLongLong(&ok)); |
|
248 if (!ok) |
|
249 { |
|
250 User::Leave(KErrArgument); |
|
251 } |
|
252 // Decrement by one to get the correct value |
|
253 User::LeaveIfError(aSqlStatement.BindInt64( |
|
254 User::LeaveIfError(aSqlStatement.ParameterIndex(*paramNames[i])), --value)); |
|
255 } |
|
256 } |
|
257 |
|
258 |
|
259 /** |
|
260 * Fetch up to 3 mail addresses |
|
261 */ |
|
262 QStringList CQwertyPredictiveSearchTable::GetTableSpecificFields( |
|
263 const CContactItem& aItem, |
|
264 TBool& aMandatoryFieldsPresent) const |
|
265 { |
|
266 PRINT(_L("CQwertyPredictiveSearchTable::GetTableSpecificFields")); |
|
267 |
|
268 QStringList mailAddresses; |
|
269 |
|
270 // Check that the contact item is a card, own card or ICC entry. |
|
271 const TUid KType = aItem.Type(); |
|
272 if (KType != KUidContactCard && |
|
273 KType != KUidContactOwnCard && |
|
274 KType != KUidContactICCEntry) |
|
275 { |
|
276 aMandatoryFieldsPresent = EFalse; |
|
277 return mailAddresses; |
|
278 } |
|
279 |
|
280 TInt storedAddressCount(0); |
|
281 for (TInt i = aItem.CardFields().Count(); |
|
282 i > 0 && storedAddressCount < KMaxMailAddresses; |
|
283 --i) |
|
284 { |
|
285 CContactItemField& field = aItem.CardFields()[i - 1]; |
|
286 if (field.ContentType().ContainsFieldType(KUidContactFieldEMail) && |
|
287 field.StorageType() == KStorageTypeText && |
|
288 field.TextStorage()->IsFull()) // IsFull() returns true if field not empty |
|
289 { |
|
290 TPtrC mailAddress = field.TextStorage()->Text(); |
|
291 PRINT2(_L("contact id=%d has mail='%S'"), aItem.Id(), &mailAddress); |
|
292 |
|
293 QString wholeAddress((QChar*)mailAddress.Ptr(), mailAddress.Length()); |
|
294 QString address = wholeAddress; |
|
295 if (wholeAddress.startsWith(KMailPrefix)) // Skip prefix |
|
296 { |
|
297 address = wholeAddress.mid(KMailPrefix.length()); |
|
298 #if defined(WRITE_PRED_SEARCH_LOGS) |
|
299 const TInt KLogLength = 40; |
|
300 TBuf<KLogLength> log(address.left(KLogLength).utf16()); |
|
301 PRINT1(_L("prefix removed, mail='%S'"), &log); |
|
302 #endif |
|
303 } |
|
304 mailAddresses.append(iKeyMap->GetMappedString(address)); |
|
305 ++storedAddressCount; |
|
306 } |
|
307 } |
|
308 PRINT1(_L("CQwertyPredictiveSearchTable::GetTableSpecificFields found %d mail addrs"), |
|
309 mailAddresses.count()); |
|
310 aMandatoryFieldsPresent = (mailAddresses.count() > 0); |
|
311 return mailAddresses; |
|
312 } |
|
313 |
|
314 |
|
315 /** |
|
316 Set up the CCntSqlStatement objects held by the class. |
|
317 */ |
|
318 void CQwertyPredictiveSearchTable::ConstructL() |
|
319 { |
|
320 PRINT(_L("CQwertyPredictiveSearchTable::ConstructL")); |
|
321 |
|
322 CPplPredictiveSearchTableBase::ConstructL(); |
|
323 |
|
324 // Set details of INSERT |
|
325 iInsertStmnt->SetParamL(KPredSearchQwertyMailContactId, |
|
326 KPredSearchQwertyMailContactIdParam); |
|
327 iInsertStmnt->SetParamL(KPredSearchQwertyMailNameAsNumber, |
|
328 KPredSearchQwertyMailNameAsNumberParam); |
|
329 iInsertStmnt->SetParamL(KPredSearchQwertyMailNameAsNumber2, |
|
330 KPredSearchQwertyMailNameAsNumberParam2); |
|
331 iInsertStmnt->SetParamL(KPredSearchQwertyMailNameAsNumber3, |
|
332 KPredSearchQwertyMailNameAsNumberParam3); |
|
333 iInsertStmnt->SetParamL(KPredSearchQwertyMailNameAsNumber4, |
|
334 KPredSearchQwertyMailNameAsNumberParam4); |
|
335 iInsertStmnt->SetParamL(KPredSearchQwertyMailNameAsNumber5, |
|
336 KPredSearchQwertyMailNameAsNumberParam5); |
|
337 iInsertStmnt->SetParamL(KPredSearchQwertyMailNameAsNumber6, |
|
338 KPredSearchQwertyMailNameAsNumberParam6); |
|
339 iInsertStmnt->SetParamL(KPredSearchQwertyMailNameAsNumber7, |
|
340 KPredSearchQwertyMailNameAsNumberParam7); |
|
341 |
|
342 iInsertStmnt->SetParamL(KPredSearchQwertyMailFirstName, |
|
343 KPredSearchQwertyMailFirstNameParam); |
|
344 iInsertStmnt->SetParamL(KPredSearchQwertyMailLastName, |
|
345 KPredSearchQwertyMailLastNameParam); |
|
346 |
|
347 PRINT(_L("CQwertyPredictiveSearchTable::ConstructL create key map")); |
|
348 iKeyMap = CQwertyKeyMap::NewL(); |
|
349 |
|
350 PRINT(_L("CQwertyPredictiveSearchTable::ConstructL ends")); |
|
351 } |
|
352 |
|
353 |
|
354 /** |
|
355 Constructor |
|
356 */ |
|
357 CQwertyPredictiveSearchTable::CQwertyPredictiveSearchTable(RSqlDatabase& aDatabase) : |
|
358 CPplPredictiveSearchTableBase(aDatabase, KMaxTokens, KMaxTokenLength) |
|
359 { |
|
360 } |