1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtCore module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 //system includes |
|
42 #include <e32base.h> |
|
43 #include <s32mem.h> |
|
44 #include <centralrepository.h> |
|
45 |
|
46 #include <QDebug> |
|
47 |
|
48 //user includes |
|
49 #include "cntsymbianfiltersqlhelper.h" |
|
50 #include "qcontactdetailfilter.h" |
|
51 #include "cnttransformcontact.h" |
|
52 #include "cntdisplaylabel.h" |
|
53 #include "cntdisplaylabelsqlfilter.h" |
|
54 #include "cntsqlsearch.h" |
|
55 |
|
56 // Telephony Configuration API |
|
57 // Keys under this category are used in defining telephony configuration. |
|
58 const TUid KCRUidTelConfiguration = {0x102828B8}; |
|
59 // Amount of digits to be used in contact matching. |
|
60 // This allows a customer to variate the amount of digits to be matched. |
|
61 const TUint32 KTelMatchDigits = 0x00000001; |
|
62 // Default match length |
|
63 const TInt KDefaultMatchLength(7); |
|
64 //Class documentation go here: |
|
65 /*! |
|
66 \class CntSymbianFilterSqlHelper |
|
67 \brief Helper class for converting filter to sql queries |
|
68 */ |
|
69 |
|
70 Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::SingleQuote,"'") ; |
|
71 Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::PercentSign,"%") ; |
|
72 Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::Space," ") ; |
|
73 Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::EqualTo,"=") ; |
|
74 Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::SqlLike," LIKE ") ; |
|
75 Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::SqlNotNull," NOT NULL ") ; |
|
76 Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::SqlWhere," WHERE ") ; |
|
77 Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::SqlOr," OR ") ; |
|
78 Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::contactsTable," contact ") ; |
|
79 Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::commAddrTable," comm_addr ") ; |
|
80 |
|
81 |
|
82 /*! |
|
83 * The constructor |
|
84 */ |
|
85 CntSymbianFilterSqlHelper::CntSymbianFilterSqlHelper(CContactDatabase& contactDatabase) |
|
86 : m_contactDatabase(contactDatabase), |
|
87 isPhoneNumberSearchforDetailFilter(false) |
|
88 { |
|
89 m_srvConnection = new CntSymbianSrvConnection(); |
|
90 m_sqlSearch = new CntSqlSearch(); |
|
91 |
|
92 contactsTableIdColumNameMapping.insert(KUidContactFieldGivenName.iUid,"first_name" ); |
|
93 contactsTableIdColumNameMapping.insert(KUidContactFieldGivenNamePronunciation.iUid,"firstname_prn" ); |
|
94 contactsTableIdColumNameMapping.insert(KUidContactFieldFamilyName.iUid,"last_name" ); |
|
95 contactsTableIdColumNameMapping.insert(KUidContactFieldFamilyNamePronunciation.iUid,"lastname_prn" ); |
|
96 contactsTableIdColumNameMapping.insert(KUidContactFieldCompanyName.iUid,"company_name" ); |
|
97 contactsTableIdColumNameMapping.insert(KUidContactFieldCompanyNamePronunciation.iUid,"companyname_prn" ); |
|
98 |
|
99 //commAddrTableIdColumNameMapping.insert(KUidContactFieldIMPP.iUid,ESipAddress ); |
|
100 commAddrTableIdColumNameMapping.insert(KUidContactFieldSIPID.iUid,ESipAddress ); |
|
101 commAddrTableIdColumNameMapping.insert(KUidContactFieldEMail.iUid,EEmailAddress ); |
|
102 |
|
103 } |
|
104 |
|
105 /*! |
|
106 * Destructor |
|
107 */ |
|
108 CntSymbianFilterSqlHelper::~CntSymbianFilterSqlHelper() |
|
109 |
|
110 { |
|
111 delete m_srvConnection; |
|
112 delete m_sqlSearch; |
|
113 contactsTableIdColumNameMapping.clear(); |
|
114 commAddrTableIdColumNameMapping.clear(); |
|
115 } |
|
116 |
|
117 /*! |
|
118 * Fetch search results from the database. |
|
119 * |
|
120 * \a filter The simple/complex QContactFilter passed . |
|
121 * \a error On return, contains the possible error. |
|
122 * \return the list of matched contact ids |
|
123 */ |
|
124 QList<QContactLocalId> CntSymbianFilterSqlHelper::searchContacts(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, |
|
125 QContactManager::Error& error) |
|
126 { |
|
127 isPhoneNumberSearchforDetailFilter = false; |
|
128 QList<QContactLocalId> idList; |
|
129 bool isPredSearch; |
|
130 idList = HandlePredictiveSearchFilter(filter,isPredSearch, error); |
|
131 if(isPredSearch) |
|
132 return idList; |
|
133 if(filterSupportLevel(filter)){ |
|
134 |
|
135 // Create sql query from the filters |
|
136 QString sqlQuery; |
|
137 createSqlQuery(filter, sqlQuery, error); |
|
138 |
|
139 if( error != QContactManager::NoError) { |
|
140 return QList<QContactLocalId>(); |
|
141 } |
|
142 // Query the database |
|
143 // If isPhoneNumberSearchforDetailFilter flag is set, we use the existing cntmodel |
|
144 // else call searchContacts |
|
145 if(isPhoneNumberSearchforDetailFilter) |
|
146 { |
|
147 // cast the filter into detail filte |
|
148 const QContactDetailFilter detailFilter(filter); |
|
149 idList = HandlePhonenumberDetailFilter(detailFilter); |
|
150 } |
|
151 else |
|
152 { |
|
153 //append the sort order to the query |
|
154 appendSortOrderQuery(sqlQuery, sortOrders); |
|
155 |
|
156 //fetch the contacts |
|
157 idList = m_srvConnection->searchContacts(sqlQuery, error); |
|
158 } |
|
159 |
|
160 } |
|
161 else |
|
162 { |
|
163 error = QContactManager::NotSupportedError; |
|
164 } |
|
165 return idList; |
|
166 |
|
167 |
|
168 } |
|
169 |
|
170 QList<QContactLocalId> CntSymbianFilterSqlHelper::HandlePredictiveSearchFilter(const QContactFilter& filter, bool &isPredSearch, |
|
171 QContactManager::Error& error) |
|
172 { |
|
173 isPredSearch = false; |
|
174 QString sqlQuery; |
|
175 if(filter.type() == QContactFilter::ContactDetailFilter){ |
|
176 const QContactDetailFilter detailFilter(filter); |
|
177 if( detailFilter.matchFlags() == QContactFilter::MatchKeypadCollation ){ |
|
178 //convert string to numeric format |
|
179 QString pattern = detailFilter.value().toString(); |
|
180 sqlQuery = m_sqlSearch->CreatePredictiveSearch(pattern); |
|
181 isPredSearch = true; |
|
182 |
|
183 return m_srvConnection->searchContacts(sqlQuery, error); |
|
184 } |
|
185 else |
|
186 { |
|
187 return QList<QContactLocalId>(); |
|
188 } |
|
189 } |
|
190 else |
|
191 { |
|
192 return QList<QContactLocalId>(); |
|
193 } |
|
194 } |
|
195 |
|
196 /*! |
|
197 * Append the sort order to the sql query |
|
198 * |
|
199 * \a sqlQuery to add the sort order to |
|
200 * \a sortOrders to be added |
|
201 */ |
|
202 void CntSymbianFilterSqlHelper::appendSortOrderQuery(QString& sqlQuery, const QList<QContactSortOrder>& sortOrders) |
|
203 { |
|
204 QString column; |
|
205 CntDisplayLabel displayLabel; |
|
206 |
|
207 bool first(true); |
|
208 |
|
209 for(int i = 0; i < sortOrders.count(); i++) |
|
210 { |
|
211 columnName(column, sortOrders.at(i).detailDefinitionName(), sortOrders.at(i).detailFieldName()); |
|
212 |
|
213 if(!column.isEmpty()) |
|
214 { |
|
215 if(first) |
|
216 { |
|
217 sqlQuery += " ORDER BY"; |
|
218 first = false; |
|
219 } |
|
220 |
|
221 else |
|
222 { |
|
223 sqlQuery += ","; |
|
224 } |
|
225 |
|
226 //use the display label if the name is null, ignore case |
|
227 sqlQuery += " CASE WHEN " + column + " ISNULL THEN \'"+ displayLabel.unNamned().toLower() + "\' ELSE lower(" + column + ") END"; |
|
228 |
|
229 if(sortOrders.at(i).direction() == Qt::AscendingOrder) |
|
230 { |
|
231 sqlQuery += " ASC"; |
|
232 } |
|
233 |
|
234 else if(sortOrders.at(i).direction() == Qt::DescendingOrder) |
|
235 { |
|
236 sqlQuery += " DESC"; |
|
237 } |
|
238 } |
|
239 } |
|
240 } |
|
241 |
|
242 /*! |
|
243 * Retrieve a column name |
|
244 * |
|
245 * \a columnName to be saved the column name if found |
|
246 * \a detailDefinitionName of the detail to fetch column name for |
|
247 * \a detailFieldName of the detail to fetch column name for |
|
248 */ |
|
249 void CntSymbianFilterSqlHelper::columnName( QString &columnName, const QString &detailDefinitionName, const QString & detailFieldName) |
|
250 { |
|
251 columnName = ""; |
|
252 |
|
253 //Name detail |
|
254 if(detailDefinitionName == QContactName::DefinitionName) |
|
255 { |
|
256 if(detailFieldName == QContactName::FieldFirst) |
|
257 { |
|
258 columnName = "first_name"; |
|
259 } |
|
260 |
|
261 else if(detailFieldName == QContactName::FieldLast) |
|
262 { |
|
263 columnName = "last_name"; |
|
264 } |
|
265 } |
|
266 |
|
267 //Organization |
|
268 else if(detailDefinitionName == QContactOrganization::DefinitionName) |
|
269 { |
|
270 if(detailFieldName == QContactOrganization::FieldName) |
|
271 { |
|
272 columnName = "company_name"; |
|
273 } |
|
274 } |
|
275 } |
|
276 |
|
277 /*! |
|
278 * converts complex filter into simple filters |
|
279 * |
|
280 * \a filter The simple/complex QContactFilter passed . |
|
281 * \a sqlQuery The sql query that would be formed |
|
282 * \a error On return, contains the possible error. |
|
283 */ |
|
284 void CntSymbianFilterSqlHelper::createSqlQuery(const QContactFilter& filter, |
|
285 QString& sqlQuery, |
|
286 QContactManager::Error& error) |
|
287 { |
|
288 //Check if it is a single filter |
|
289 bool IsOneLevelFilter = isSingleFilter(filter); |
|
290 if(IsOneLevelFilter) { |
|
291 //Single Filter, get the sql query here |
|
292 updateSqlQueryForSingleFilter(filter,sqlQuery,error); |
|
293 } else { |
|
294 // We have multiple filters. Combine these to form correct query |
|
295 // Not supported yet |
|
296 error = QContactManager::NotSupportedError; |
|
297 } |
|
298 } |
|
299 |
|
300 /*! |
|
301 * Checks if the given filter is a single filter or combination of filters |
|
302 * |
|
303 * \a filter The QContactFilter to be used. |
|
304 * \return True if the filters is single filter |
|
305 */ |
|
306 |
|
307 bool CntSymbianFilterSqlHelper::isSingleFilter(const QContactFilter& singlefilter) const |
|
308 { |
|
309 |
|
310 bool returnValue = false; |
|
311 switch (singlefilter.type()) { |
|
312 case QContactFilter::ContactDetailFilter: |
|
313 case QContactFilter::InvalidFilter : |
|
314 case QContactFilter::ContactDetailRangeFilter: |
|
315 case QContactFilter::ChangeLogFilter: |
|
316 case QContactFilter::DefaultFilter: |
|
317 //All are single filters, return True |
|
318 returnValue = true; |
|
319 break; |
|
320 case QContactFilter::ActionFilter: |
|
321 case QContactFilter::IntersectionFilter: |
|
322 case QContactFilter::UnionFilter: |
|
323 |
|
324 //All these are multiple filters |
|
325 returnValue = false; |
|
326 break; |
|
327 default: |
|
328 returnValue = false; |
|
329 break; |
|
330 }; |
|
331 return returnValue; |
|
332 } |
|
333 |
|
334 /*! |
|
335 * Updates the input sql query for single filter |
|
336 * |
|
337 * \a filter The QContactFilter to be used. |
|
338 * \a sqlQuery The sql query that would be updated |
|
339 * \a error On return, contains the possible error |
|
340 */ |
|
341 void CntSymbianFilterSqlHelper::updateSqlQueryForSingleFilter( const QContactFilter& filter, |
|
342 QString& sqlQuery, |
|
343 QContactManager::Error& error) |
|
344 { |
|
345 switch (filter.type()) { |
|
346 case QContactFilter::InvalidFilter : |
|
347 { |
|
348 // Not supported yet |
|
349 error = QContactManager::NotSupportedError; |
|
350 break; |
|
351 } |
|
352 case QContactFilter::ContactDetailFilter: |
|
353 { |
|
354 const QContactDetailFilter detailFilter(filter); |
|
355 |
|
356 //display label |
|
357 if (detailFilter.detailDefinitionName() == QContactDisplayLabel::DefinitionName) |
|
358 { |
|
359 CntDisplayLabelSqlFilter displayLabelFilter; |
|
360 displayLabelFilter.createSqlQuery(detailFilter,sqlQuery,error); |
|
361 } |
|
362 |
|
363 //type |
|
364 else if(detailFilter.detailDefinitionName() == QContactType::DefinitionName) |
|
365 { |
|
366 if(detailFilter.value().toString() == QContactType::TypeContact) |
|
367 sqlQuery = "SELECT contact_id FROM contact WHERE (type_flags>>24)=0"; |
|
368 else if(detailFilter.value().toString() == QContactType::TypeGroup) |
|
369 sqlQuery = "SELECT contact_id FROM contact WHERE (type_flags>>24)=3"; |
|
370 } |
|
371 |
|
372 //everything else |
|
373 else |
|
374 { |
|
375 updateSqlQueryForDetailFilter(filter,sqlQuery,error); |
|
376 } |
|
377 |
|
378 break; |
|
379 } |
|
380 case QContactFilter::ContactDetailRangeFilter: |
|
381 // Not supported yet |
|
382 error = QContactManager::NotSupportedError; |
|
383 break; |
|
384 |
|
385 case QContactFilter::ChangeLogFilter: |
|
386 // Not supported yet |
|
387 error = QContactManager::NotSupportedError; |
|
388 break; |
|
389 case QContactFilter::DefaultFilter: |
|
390 sqlQuery = "SELECT DISTINCT contact_id FROM contact WHERE (type_flags>>24)=0 OR (type_flags>>24)=3"; |
|
391 error = QContactManager::NoError; |
|
392 break; |
|
393 case QContactFilter::ActionFilter: |
|
394 case QContactFilter::IntersectionFilter: |
|
395 case QContactFilter::UnionFilter: |
|
396 //All these are multiple filters |
|
397 // Not supported yet |
|
398 error = QContactManager::NotSupportedError; |
|
399 break; |
|
400 default: |
|
401 //Some Unknow filter value |
|
402 // Not supported |
|
403 error = QContactManager::NotSupportedError; |
|
404 break; |
|
405 }; |
|
406 if( error != QContactManager::NoError) |
|
407 { |
|
408 sqlQuery = ""; |
|
409 } |
|
410 } |
|
411 |
|
412 /*! |
|
413 * Updates the input sql query for detail filter |
|
414 * |
|
415 * \a filter The QContactFilter to be used. |
|
416 * \a sqlQuery The sql query that would be updated |
|
417 * \a error On return, contains the possible error |
|
418 */ |
|
419 void CntSymbianFilterSqlHelper::updateSqlQueryForDetailFilter(const QContactFilter& filter, |
|
420 QString& sqlQuery, |
|
421 QContactManager::Error& error) |
|
422 { |
|
423 |
|
424 |
|
425 // cast the filter into detail filter |
|
426 const QContactDetailFilter detailFilter(filter); |
|
427 |
|
428 QString sqlWhereClause = Space + " WHERE "; |
|
429 |
|
430 //Get the table name and the column name |
|
431 bool isSubType; |
|
432 QString columnName; |
|
433 QString tableName; |
|
434 |
|
435 //Check for phonenumber. Special handling needed |
|
436 if(detailFilter.detailDefinitionName() == QContactPhoneNumber::DefinitionName){ |
|
437 isPhoneNumberSearchforDetailFilter = true; |
|
438 error = QContactManager::NoError; |
|
439 return; |
|
440 } |
|
441 |
|
442 getSqlDbTableAndColumnNameforDetailFilter(detailFilter,isSubType,tableName,columnName); |
|
443 |
|
444 //return if tableName is empty |
|
445 if(tableName == "" ){ |
|
446 error = QContactManager::NotSupportedError; |
|
447 return; |
|
448 } |
|
449 |
|
450 //check columnName |
|
451 if(columnName == "") { |
|
452 error = QContactManager::NotSupportedError; |
|
453 return; |
|
454 } |
|
455 else if(isSubType) { |
|
456 sqlWhereClause += columnName; |
|
457 sqlWhereClause += " NOT NULL "; |
|
458 } |
|
459 else { |
|
460 |
|
461 sqlWhereClause += Space + columnName + Space ; |
|
462 QString fieldToUpdate; |
|
463 //Update the value depending on the match flag |
|
464 updateFieldForDeatilFilterMatchFlag(detailFilter,fieldToUpdate,error); |
|
465 sqlWhereClause += fieldToUpdate; |
|
466 } |
|
467 |
|
468 |
|
469 //Create the sql query |
|
470 sqlQuery += "SELECT DISTINCT contact_id FROM " + Space + tableName + Space + sqlWhereClause; |
|
471 |
|
472 |
|
473 } |
|
474 |
|
475 /*! |
|
476 * Converts filed id to column name of the database table. |
|
477 * QContactManager::contacts function. |
|
478 * |
|
479 * \a fieldId field id representing the detail field name |
|
480 * \a sqlDbTableColumnName On return,contains the column name in the database |
|
481 */ |
|
482 void CntSymbianFilterSqlHelper::updateFieldForDeatilFilterMatchFlag( |
|
483 const QContactDetailFilter& filter, |
|
484 QString& fieldToUpdate , |
|
485 QContactManager::Error& error) const |
|
486 { |
|
487 // Modify the filed depending on the query |
|
488 switch(filter.matchFlags()) |
|
489 { |
|
490 case QContactFilter::MatchExactly: |
|
491 { |
|
492 // Pattern for MatchExactly: |
|
493 // " ='xyz'" |
|
494 fieldToUpdate = Space + EqualTo + SingleQuote |
|
495 + filter.value().toString() + SingleQuote; |
|
496 error = QContactManager::NoError; |
|
497 break; |
|
498 } |
|
499 case QContactFilter::MatchContains: |
|
500 { |
|
501 // Pattern for MatchContains: |
|
502 // " LIKE '%xyz%'" |
|
503 fieldToUpdate = Space + SqlLike + Space + SingleQuote + PercentSign |
|
504 + filter.value().toString() + PercentSign + SingleQuote ; |
|
505 error = QContactManager::NoError; |
|
506 break; |
|
507 } |
|
508 case QContactFilter::MatchStartsWith: |
|
509 { |
|
510 // Pattern for MatchStartsWith: |
|
511 // " LIKE 'xyz%'" |
|
512 fieldToUpdate = Space + SqlLike + Space + SingleQuote |
|
513 + filter.value().toString() + PercentSign + SingleQuote ; |
|
514 error = QContactManager::NoError; |
|
515 break; |
|
516 } |
|
517 case QContactFilter::MatchEndsWith: |
|
518 { |
|
519 // Pattern for MatchEndsWith: |
|
520 // " LIKE '%xyz'" |
|
521 fieldToUpdate = Space + SqlLike + Space + SingleQuote + PercentSign |
|
522 + filter.value().toString() + SingleQuote ; |
|
523 error = QContactManager::NoError; |
|
524 break; |
|
525 } |
|
526 case QContactFilter::MatchFixedString: |
|
527 { |
|
528 error = QContactManager::NotSupportedError; |
|
529 break; |
|
530 } |
|
531 case QContactFilter::MatchCaseSensitive: |
|
532 { |
|
533 error = QContactManager::NotSupportedError; |
|
534 break; |
|
535 } |
|
536 default: |
|
537 { |
|
538 error = QContactManager::NotSupportedError; |
|
539 break; |
|
540 } |
|
541 } |
|
542 } |
|
543 |
|
544 /*! |
|
545 * Converts filed id to column name of the database table. |
|
546 * QContactManager::contacts function. |
|
547 * |
|
548 * \a fieldId field id representing the detail field name |
|
549 * \a sqlDbTableColumnName On return,contains the column name in the database |
|
550 */ |
|
551 void CntSymbianFilterSqlHelper::getSqlDbTableAndColumnNameforDetailFilter( |
|
552 const QContactDetailFilter& detailFilter , |
|
553 bool& isSubType, |
|
554 QString& tableName, |
|
555 QString& columnName ) |
|
556 { |
|
557 |
|
558 //Get the field id for the detail field name |
|
559 CntTransformContact transformContact; |
|
560 quint32 fieldId = transformContact.GetIdForDetailL(detailFilter, isSubType); |
|
561 |
|
562 //check contacts table |
|
563 columnName = ""; |
|
564 tableName = ""; |
|
565 |
|
566 if (contactsTableIdColumNameMapping.contains(fieldId)){ |
|
567 columnName = contactsTableIdColumNameMapping.value(fieldId); |
|
568 tableName = "contact"; |
|
569 } |
|
570 |
|
571 if( ("" == columnName) || ("" == tableName)){ |
|
572 //Search comm Addr table |
|
573 if (commAddrTableIdColumNameMapping.contains(fieldId)){ |
|
574 // communication address table has slightly differnt format, so we make the column name as |
|
575 // "type = <type> and value " |
|
576 int typeval = commAddrTableIdColumNameMapping.value(fieldId) ; |
|
577 columnName = Space + "TYPE = "; |
|
578 columnName.append('0'+ typeval) |
|
579 + typeval + Space; |
|
580 columnName += " and value " ; |
|
581 tableName = "comm_addr"; |
|
582 } |
|
583 |
|
584 } |
|
585 } |
|
586 |
|
587 QList<QContactLocalId> CntSymbianFilterSqlHelper::HandlePhonenumberDetailFilter(const QContactDetailFilter detailFilter) |
|
588 { |
|
589 QList<QContactLocalId> matches; |
|
590 |
|
591 if(detailFilter.detailDefinitionName() == QContactPhoneNumber::DefinitionName){ |
|
592 |
|
593 // Phone numbers need separate handling |
|
594 if ((filterSupportLevel(detailFilter) == CntAbstractContactFilter::Supported |
|
595 || filterSupportLevel(detailFilter) == CntAbstractContactFilter::SupportedPreFilterOnly)) |
|
596 { |
|
597 QString number((detailFilter.value()).toString()); |
|
598 TPtrC commPtr(reinterpret_cast<const TUint16*>(number.utf16())); |
|
599 |
|
600 TInt matchLength(KDefaultMatchLength); |
|
601 // no need to propagate error, we can use the default match length |
|
602 TRAP_IGNORE(getMatchLengthL(matchLength)); |
|
603 |
|
604 //cal the search |
|
605 CContactIdArray* idArray(0); |
|
606 TInt err = searchPhoneNumbers(idArray, commPtr, matchLength); |
|
607 if( idArray && (err == KErrNone)){ |
|
608 // copy the matching contact ids |
|
609 for(int i(0); i < idArray->Count(); i++) { |
|
610 matches.append(QContactLocalId((*idArray)[i])); |
|
611 } |
|
612 delete idArray; |
|
613 } |
|
614 else{ |
|
615 //CntSymbianTransformError::transformError(err, error); |
|
616 } |
|
617 } |
|
618 |
|
619 |
|
620 } |
|
621 return matches; |
|
622 |
|
623 } |
|
624 /*! |
|
625 * The contact database version implementation for |
|
626 * QContactManager::filterSupported function. The possible return values are |
|
627 * Supported, NotSupported and SupportedPreFilterOnly. Supported means that |
|
628 * the filtering is implemented directly by the underlying database. |
|
629 * NotSupported means that CntSymbianFilterDbms::contacts will return an |
|
630 * error. And SupportedPreFilterOnly means that the filter is not supported, |
|
631 * but the CntSymbianFilterDbms::contacts will act like the filter was |
|
632 * supported. This means that the client must filter the pre-filtered set of |
|
633 * contacts to see if there are false positives included. Note that in some |
|
634 * cases the pre-filtering is not very effective. |
|
635 * |
|
636 * \a filter The QContactFilter to be checked. |
|
637 * \a return Supported in case the filter is supported. NotSupported in case |
|
638 * the filter is not supported. returns |
|
639 * |
|
640 */ |
|
641 CntAbstractContactFilter::FilterSupport CntSymbianFilterSqlHelper::filterSupportLevel(const QContactFilter& filter) |
|
642 { |
|
643 CntAbstractContactFilter::FilterSupport filterSupported(CntAbstractContactFilter::NotSupported); |
|
644 switch (filter.type()) { |
|
645 case QContactFilter::DefaultFilter: //default filter == no filter |
|
646 { |
|
647 filterSupported = CntAbstractContactFilter::Supported; |
|
648 break; |
|
649 } |
|
650 case QContactFilter::ContactDetailFilter: |
|
651 { |
|
652 const QContactDetailFilter &detailFilter = static_cast<const QContactDetailFilter &>(filter); |
|
653 filterSupported = checkIfDetailFilterSupported(detailFilter); |
|
654 break; |
|
655 } |
|
656 case QContactFilter::InvalidFilter : |
|
657 case QContactFilter::ContactDetailRangeFilter: |
|
658 case QContactFilter::ChangeLogFilter: |
|
659 case QContactFilter::ActionFilter: |
|
660 case QContactFilter::IntersectionFilter: |
|
661 case QContactFilter::UnionFilter: |
|
662 case QContactFilter::RelationshipFilter: |
|
663 default: |
|
664 filterSupported = CntAbstractContactFilter::NotSupported; |
|
665 break; |
|
666 } |
|
667 return filterSupported; |
|
668 } |
|
669 CntAbstractContactFilter::FilterSupport CntSymbianFilterSqlHelper::checkIfDetailFilterSupported |
|
670 (const QContactDetailFilter& detailFilter) const |
|
671 { |
|
672 |
|
673 CntAbstractContactFilter::FilterSupport filterSupported(CntAbstractContactFilter::NotSupported); |
|
674 //Get the match flags |
|
675 QContactFilter::MatchFlags matchFlags = detailFilter.matchFlags(); |
|
676 // Phone numbers |
|
677 if (detailFilter.detailDefinitionName() == QContactPhoneNumber::DefinitionName) { |
|
678 if (matchFlags == QContactFilter::MatchEndsWith){ |
|
679 filterSupported = CntAbstractContactFilter::Supported; |
|
680 } |
|
681 else if (matchFlags == QContactFilter::MatchExactly){ |
|
682 filterSupported = CntAbstractContactFilter::SupportedPreFilterOnly; |
|
683 } |
|
684 } |
|
685 // Names , Email,Sip address |
|
686 else if ( detailFilter.detailDefinitionName() == QContactName::DefinitionName || |
|
687 detailFilter.detailDefinitionName() == QContactEmailAddress::DefinitionName || |
|
688 detailFilter.detailDefinitionName() == QContactOnlineAccount::DefinitionName || |
|
689 detailFilter.detailDefinitionName() == QContactDisplayLabel::DefinitionName || |
|
690 detailFilter.detailDefinitionName() == QContactType::DefinitionName){ |
|
691 if ( (matchFlags == QContactFilter::MatchContains)|| (matchFlags == QContactFilter::MatchStartsWith)|| |
|
692 (matchFlags == QContactFilter::MatchEndsWith)|| (matchFlags == QContactFilter::MatchExactly)){ |
|
693 filterSupported = CntAbstractContactFilter::Supported; |
|
694 } |
|
695 if(matchFlags == QContactFilter::MatchKeypadCollation) |
|
696 filterSupported = CntAbstractContactFilter::Supported; |
|
697 } |
|
698 return filterSupported; |
|
699 |
|
700 } |
|
701 /* |
|
702 * Get the match length setting. Digits to be used in matching (counted from |
|
703 * right). |
|
704 */ |
|
705 void CntSymbianFilterSqlHelper::getMatchLengthL(TInt& matchLength) |
|
706 { |
|
707 //Get number of digits used to match |
|
708 CRepository* repository = CRepository::NewL(KCRUidTelConfiguration); |
|
709 CleanupStack::PushL(repository); |
|
710 User::LeaveIfError(repository->Get(KTelMatchDigits, matchLength)); |
|
711 CleanupStack::PopAndDestroy(repository); |
|
712 } |
|
713 |
|
714 /* |
|
715 * Find contacts based on a phone number. |
|
716 * \a idArray On return contains the ids of the contacts that match the phonenumber. |
|
717 * \a phoneNumber The phone number to match |
|
718 * \a matchLength Match length; digits from right. |
|
719 */ |
|
720 TInt CntSymbianFilterSqlHelper::searchPhoneNumbers( |
|
721 CContactIdArray*& idArray, |
|
722 const TDesC& phoneNumber, |
|
723 const TInt matchLength) |
|
724 { |
|
725 CContactIdArray* idArrayTmp(0); |
|
726 TRAPD( err, idArrayTmp = m_contactDatabase.MatchPhoneNumberL(phoneNumber, matchLength)); |
|
727 if(err == KErrNone){ |
|
728 idArray = idArrayTmp; |
|
729 } |
|
730 return 0; |
|
731 } |
|