qtmobility/plugins/contacts/symbian/src/filtering/cntsymbianfilterdbms.cpp
changeset 4 90517678cc4f
parent 1 2b40d63a9c3d
child 8 71781823f776
equal deleted inserted replaced
1:2b40d63a9c3d 4:90517678cc4f
    88  * All the other filtering flags fallback to the generic filtering done
    88  * All the other filtering flags fallback to the generic filtering done
    89  * in QContactManagerEngine (expected to be done by to the caller). Contacts
    89  * in QContactManagerEngine (expected to be done by to the caller). Contacts
    90  * are sorted only if the sort order is supported by contacts database. See
    90  * are sorted only if the sort order is supported by contacts database. See
    91  * CntSymbianSorterDbms::filterSupportLevel for the list of supported sort
    91  * CntSymbianSorterDbms::filterSupportLevel for the list of supported sort
    92  * orders.
    92  * orders.
       
    93  * 
       
    94  * Using detail filter with match flag MatchPhoneNumber is implemented by the
       
    95  * contact model "phone number match" that filters by comparing the search
       
    96  * string characters (digits) starting from the rightmost digit. The detail
       
    97  * filter value must be at least 7 digits, otherwise an error code
       
    98  * NotSupportedError is given. The actual digit count that is used is 7 to 15
       
    99  * digits, depending on the configuration of the device.
    93  *
   100  *
    94  * \a filter The QContactFilter to be used.
   101  * \a filter The QContactFilter to be used.
    95  * \a sortOrders The sort orders to be used. If the sort orders are not
   102  * \a sortOrders The sort orders to be used. If the sort orders are not
    96  * supported by contacts database this parameter is ignored and sorting needs
   103  * supported by contacts database this parameter is ignored and sorting needs
    97  * to be done by the caller.
   104  * to be done by the caller.
    99  */
   106  */
   100 QList<QContactLocalId> CntSymbianFilter::contacts(
   107 QList<QContactLocalId> CntSymbianFilter::contacts(
   101     const QContactFilter &filter,
   108     const QContactFilter &filter,
   102     const QList<QContactSortOrder> &sortOrders,
   109     const QList<QContactSortOrder> &sortOrders,
   103     bool &filterSupportedFlag,
   110     bool &filterSupportedFlag,
   104     QContactManager::Error &error)
   111     QContactManager::Error* error)
   105 {
   112 {
   106     QList<QContactLocalId> result;
   113     QList<QContactLocalId> result;
   107 
   114 
   108     // No need to proceed if some of the filters in the chain is not supported
   115     // No need to proceed if some of the filters in the chain is not supported
   109     if(!filterSupportedFlag) return result;
   116     if(!filterSupportedFlag) return result;
   132     // an intersection filter
   139     // an intersection filter
   133     } else if (filter.type() == QContactFilter::ContactDetailFilter
   140     } else if (filter.type() == QContactFilter::ContactDetailFilter
   134             && (static_cast<const QContactDetailFilter &>(filter)).value().type() == QVariant::StringList) {
   141             && (static_cast<const QContactDetailFilter &>(filter)).value().type() == QVariant::StringList) {
   135         QStringList values = (static_cast<const QContactDetailFilter &>(filter)).value().toStringList();
   142         QStringList values = (static_cast<const QContactDetailFilter &>(filter)).value().toStringList();
   136         QContactIntersectionFilter intersectionFilter;
   143         QContactIntersectionFilter intersectionFilter;
   137         foreach(QString value, values) {
   144         foreach(const QString& value, values) {
   138             QContactDetailFilter detailFilter = filter;
   145             QContactDetailFilter detailFilter = filter;
   139             detailFilter.setValue(value);
   146             detailFilter.setValue(value);
   140             intersectionFilter.append(detailFilter);
   147             intersectionFilter.append(detailFilter);
   141         }
   148         }
   142         // The resulting filter is handled with a recursive function call
   149         // The resulting filter is handled with a recursive function call
   143         result = contacts(intersectionFilter, sortOrders, filterSupportedFlag, error);
   150         result = contacts(intersectionFilter, sortOrders, filterSupportedFlag, error);
   144     } else {
   151     } else {
   145         if (filterSupportLevel(filter) == Supported) {
   152         FilterSupport filterSupport = filterSupportLevel(filter);
       
   153         if (filterSupport == Supported) {
   146             filterSupportedFlag = true;
   154             filterSupportedFlag = true;
   147             // Filter supported, use as the result directly
   155             // Filter supported, use as the result directly
   148             result = filterContacts(filter, error);
   156             result = filterContacts(filter, error);
   149         } else if (filterSupportLevel(filter) == SupportedPreFilterOnly) {
   157         } else if (filterSupport == SupportedPreFilterOnly) {
   150             // Filter only does pre-filtering, the caller is responsible of
   158             // Filter only does pre-filtering, the caller is responsible of
   151             // removing possible false positives after filtering
   159             // removing possible false positives after filtering
   152             filterSupportedFlag = false;
   160             filterSupportedFlag = false;
   153             result = filterContacts(filter, error);
   161             result = filterContacts(filter, error);
       
   162         } else if (filterSupport == IllegalFilter) {
       
   163             // Don't do filtering; fail with an error
       
   164             filterSupportedFlag = false;
       
   165             *error = QContactManager::NotSupportedError;
   154         } else {
   166         } else {
   155             // Don't do filtering here, return all contact ids and tell the
   167             // Don't do filtering here, return all contact ids and tell the
   156             // caller to do slow filtering
   168             // caller to do slow filtering
   157             filterSupportedFlag = false;
   169             filterSupportedFlag = false;
   158             result = filterContacts(QContactInvalidFilter(), error);
   170             result = filterContacts(QContactInvalidFilter(), error);
   223 
   235 
   224         // Phone numbers
   236         // Phone numbers
   225         if (defName == QContactPhoneNumber::DefinitionName) {
   237         if (defName == QContactPhoneNumber::DefinitionName) {
   226             
   238             
   227             if (matchFlags == QContactFilter::MatchPhoneNumber) {
   239             if (matchFlags == QContactFilter::MatchPhoneNumber) {
   228                 return Supported;
   240                 if (detailFilter.value().canConvert(QVariant::String)) {
   229             }
   241                     if (detailFilter.value().toString().length() >= 7) {
   230             
   242                         return Supported;
   231             if (matchFlags == QContactFilter::MatchExactly ||
   243                     } else {
   232                 matchFlags == QContactFilter::MatchEndsWith ||
   244                         // It is a feature of Symbian contact model that phone
   233                 matchFlags == QContactFilter::MatchFixedString) {
   245                         // number match requires at least 7 digits. In case of
   234                 return SupportedPreFilterOnly;
   246                         // phone number match it is best to give an error as a
       
   247                         // result because the phone number match logic would
       
   248                         // not be much of use with less than 7 digit matching.
       
   249                         // It would give false positives too often.
       
   250                         return IllegalFilter;
       
   251                     }
       
   252                 }
       
   253             } else if (matchFlags == QContactFilter::MatchExactly
       
   254                 || matchFlags == QContactFilter::MatchEndsWith
       
   255                 || matchFlags == QContactFilter::MatchFixedString) {
       
   256                 if (detailFilter.value().canConvert(QVariant::String)) {
       
   257                     // It is a feature of Symbian contact model that phone
       
   258                     // number match requires at least 7 digits
       
   259                     if (detailFilter.value().toString().length() >= 7) {
       
   260                         return SupportedPreFilterOnly;
       
   261                     }
       
   262                 }
   235             }
   263             }
   236         // Names
   264         // Names
   237         } else if (defName == QContactName::DefinitionName
   265         } else if (defName == QContactName::DefinitionName
   238                 || defName == QContactNickname::DefinitionName
   266                 || defName == QContactNickname::DefinitionName
   239                 || defName == QContactEmailAddress::DefinitionName) {
   267                 || defName == QContactEmailAddress::DefinitionName) {
   274     return NotSupported;
   302     return NotSupported;
   275 }
   303 }
   276 
   304 
   277 QList<QContactLocalId> CntSymbianFilter::filterContacts(
   305 QList<QContactLocalId> CntSymbianFilter::filterContacts(
   278     const QContactFilter& filter,
   306     const QContactFilter& filter,
   279     QContactManager::Error& error)
   307     QContactManager::Error* error)
   280 {
   308 {
   281     QList<QContactLocalId> matches;
   309     QList<QContactLocalId> matches;
   282     CContactIdArray* idArray(0);
   310     CContactIdArray* idArray(0);
   283 
   311 
   284     if (filter.type() == QContactFilter::InvalidFilter ){
   312     if (filter.type() == QContactFilter::InvalidFilter) {
   285         TTime epoch(0);
   313         TTime epoch(0);
   286         idArray = m_contactDatabase.ContactsChangedSinceL(epoch); // return all contacts
   314         idArray = m_contactDatabase.ContactsChangedSinceL(epoch); // return all contacts
   287     } else if(filterSupportLevel(filter) == NotSupported) {
   315     } else if(filterSupportLevel(filter) == NotSupported) {
   288         error = QContactManager::NotSupportedError;
   316         *error = QContactManager::NotSupportedError;
   289     } else if (filter.type() == QContactFilter::ContactDetailFilter) {
   317     } else if (filter.type() == QContactFilter::ContactDetailFilter) {
   290         const QContactDetailFilter &detailFilter = static_cast<const QContactDetailFilter &>(filter);
   318         const QContactDetailFilter &detailFilter = static_cast<const QContactDetailFilter &>(filter);
   291 
   319 
   292         // Phone numbers
   320         // Phone numbers
   293         if (detailFilter.detailDefinitionName() == QContactPhoneNumber::DefinitionName) {
   321         if (detailFilter.detailDefinitionName() == QContactPhoneNumber::DefinitionName) {
   325                 // for filtering with display label
   353                 // for filtering with display label
   326                 if (detailFilter.detailDefinitionName() == QContactDisplayLabel::DefinitionName
   354                 if (detailFilter.detailDefinitionName() == QContactDisplayLabel::DefinitionName
   327                     && detailFilter.matchFlags() == QContactFilter::MatchStartsWith) {
   355                     && detailFilter.matchFlags() == QContactFilter::MatchStartsWith) {
   328 
   356 
   329                     // Remove false positives
   357                     // Remove false positives
   330                     for(TInt i(0); i < idArray->Count(); i++) {
   358                     for(TInt i(0); i < idArray->Count(); ++i) {
   331                         CContactItem* contactItem = m_contactDatabase.ReadContactLC((*idArray)[i]);
   359                         CContactItem* contactItem = m_contactDatabase.ReadContactLC((*idArray)[i]);
   332                         const CContactItemFieldSet& fieldSet(contactItem->CardFields());
   360                         const CContactItemFieldSet& fieldSet(contactItem->CardFields());
   333                         if(isFalsePositive(fieldSet, KUidContactFieldGivenName, namePtr)
   361                         if(isFalsePositive(fieldSet, KUidContactFieldGivenName, namePtr)
   334                            && isFalsePositive(fieldSet, KUidContactFieldFamilyName, namePtr)
   362                            && isFalsePositive(fieldSet, KUidContactFieldFamilyName, namePtr)
   335                            && isFalsePositive(fieldSet, KUidContactFieldCompanyName, namePtr)
   363                            && isFalsePositive(fieldSet, KUidContactFieldCompanyName, namePtr)
   343             }
   371             }
   344             delete fieldDef;
   372             delete fieldDef;
   345         }
   373         }
   346     }
   374     }
   347 
   375 
   348     if(idArray && (error == QContactManager::NoError)) {
   376     if(idArray && (*error == QContactManager::NoError)) {
   349         // copy the matching contact ids
   377         // copy the matching contact ids
   350         for(int i(0); i < idArray->Count(); i++) {
   378         for(int i(0); i < idArray->Count(); i++) {
   351             matches.append(QContactLocalId((*idArray)[i]));
   379             matches.append(QContactLocalId((*idArray)[i]));
   352         }
   380         }
   353     }
   381     }
   375         TPtrC text = storage->Text();
   403         TPtrC text = storage->Text();
   376         index = text.FindC(searchString);
   404         index = text.FindC(searchString);
   377         // Check if this is the first word beginning with search string
   405         // Check if this is the first word beginning with search string
   378         if(index == 0)
   406         if(index == 0)
   379             value = false;
   407             value = false;
   380         // Check if this is in the beginning of a word (the preceeding
   408         // Check if this is in the beginning of a word (the preceding
   381         // character is a space)
   409         // character is a space)
   382         else if(index > 0 && TChar(text[index-1]) == TChar(0x20))
   410         else if(index > 0 && TChar(text[index-1]) == TChar(0x20))
   383             value = false;
   411             value = false;
   384     }
   412     }
   385     return value;
   413     return value;
   403     // TODO: Refactor to use the transform classes
   431     // TODO: Refactor to use the transform classes
   404     // Names
   432     // Names
   405     if(detailFilter.detailDefinitionName() == QContactName::DefinitionName) {
   433     if(detailFilter.detailDefinitionName() == QContactName::DefinitionName) {
   406         if(detailFilter.detailFieldName() == QContactName::FieldPrefix) {
   434         if(detailFilter.detailFieldName() == QContactName::FieldPrefix) {
   407             tempFieldDef->AppendL(KUidContactFieldPrefixName);
   435             tempFieldDef->AppendL(KUidContactFieldPrefixName);
   408         } else if(detailFilter.detailFieldName() == QContactName::FieldFirst) {
   436         } else if(detailFilter.detailFieldName() == QContactName::FieldFirstName) {
   409             tempFieldDef->AppendL(KUidContactFieldGivenName);
   437             tempFieldDef->AppendL(KUidContactFieldGivenName);
   410         } else if(detailFilter.detailFieldName() == QContactName::FieldMiddle) {
   438         } else if(detailFilter.detailFieldName() == QContactName::FieldMiddleName) {
   411             tempFieldDef->AppendL(KUidContactFieldAdditionalName);
   439             tempFieldDef->AppendL(KUidContactFieldAdditionalName);
   412         } else if(detailFilter.detailFieldName() == QContactName::FieldLast) {
   440         } else if(detailFilter.detailFieldName() == QContactName::FieldLastName) {
   413             tempFieldDef->AppendL(KUidContactFieldFamilyName);
   441             tempFieldDef->AppendL(KUidContactFieldFamilyName);
   414         } else if(detailFilter.detailFieldName() == QContactName::FieldSuffix) {
   442         } else if(detailFilter.detailFieldName() == QContactName::FieldSuffix) {
   415             tempFieldDef->AppendL(KUidContactFieldSuffixName);
   443             tempFieldDef->AppendL(KUidContactFieldSuffixName);
   416         } else {
   444         } else {
   417             // default to all name fields
   445             // default to all name fields