emailservices/nmutilities/src/nmcontacthistorymodel_p.cpp
changeset 75 47d84de1c893
child 74 6c59112cfd31
equal deleted inserted replaced
72:64e38f08e49c 75:47d84de1c893
       
     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: Private implementation of Contact History Model API
       
    15 *
       
    16 */
       
    17 
       
    18 #include "emailmru.h"
       
    19 #include "nmcontacthistorymodel_p.h"
       
    20 
       
    21 // --------------------------------------------------------------------------
       
    22 // Start of implementation (NmContactHistoryModelPrivate)
       
    23 // --------------------------------------------------------------------------
       
    24 /*!
       
    25     Constructor of NmContactHistoryModelPrivate
       
    26 
       
    27     \param type The valid values are described by
       
    28     NmContactHistoryModelPrivate::HistoryModelType enum.
       
    29 */
       
    30 NmContactHistoryModelPrivate::NmContactHistoryModelPrivate(
       
    31     const NmContactHistoryModelType modelType) :
       
    32     mType(modelType),
       
    33     mContactManager(0),
       
    34     mModelReady(false)
       
    35 {
       
    36     mContactManager = new QContactManager("symbian");
       
    37     mNameOrder = EmailMRU::nameOrder();
       
    38 }
       
    39 
       
    40 /*!
       
    41     Destructor of ContactHistoryModel
       
    42 */
       
    43 NmContactHistoryModelPrivate::~NmContactHistoryModelPrivate()
       
    44 {
       
    45     delete mContactManager;
       
    46     mPrivateItemList.clear();
       
    47     mModelItemList.clear();
       
    48 }
       
    49 
       
    50 /*!
       
    51     Searches contact & MRU  databases according to query parameters.
       
    52     Emits QueryCompleted() when ready.
       
    53 
       
    54     \param query Text to be searched
       
    55     \return none
       
    56 
       
    57     Note:: QContactManager supports max. ten characters long queries.
       
    58 */
       
    59 void NmContactHistoryModelPrivate::queryDatabases(const QString& query)
       
    60 {
       
    61     mModelReady = false;
       
    62     // Clear contacts in the list
       
    63     mPrivateItemList.clear();
       
    64     mModelItemList.clear();
       
    65     mMruList.clear();
       
    66     mMruMatches.clear();
       
    67 
       
    68     // Modify search to suit our needs
       
    69     // Space must be removed, because it is understood as logigal AND
       
    70     // with QContactManager API
       
    71     QString modifiedQuery = query;
       
    72 
       
    73     int spcPosition = query.indexOf(" ");
       
    74 
       
    75     if ( spcPosition != -1 )
       
    76         {
       
    77         modifiedQuery = query.left(spcPosition);
       
    78         }
       
    79 
       
    80     queryMruDatabase(modifiedQuery);
       
    81     populateListWithMruItems(modifiedQuery);
       
    82 
       
    83     if (mContactManager)
       
    84         {
       
    85         // Get matching IDs from Contacts DB
       
    86         QList<QContactLocalId> cnt_ids = queryContactDatabase(modifiedQuery);
       
    87 
       
    88         // Populate mPrivateItemList with contact items.
       
    89         populateListWithContactItems(cnt_ids, modifiedQuery);
       
    90         }
       
    91 
       
    92     // Currently we will always emit 0 as completion code.
       
    93 
       
    94     //TODO: Will be removed, Debug Code.
       
    95     for (int i = 0; i < mPrivateItemList.size(); i++)
       
    96         {
       
    97         QSharedPointer<NmContactHistoryModelItemData> itemData = mPrivateItemList[i];
       
    98 
       
    99         QString dbgString = itemData->mItems[0].mItemText;
       
   100         dbgString.append(" ");
       
   101         dbgString.append(itemData->mItems[1].mItemText);
       
   102 
       
   103         qDebug(dbgString.toLatin1());
       
   104 
       
   105 
       
   106         }
       
   107 
       
   108     emit queryCompleted(0);
       
   109 }
       
   110 
       
   111 /*!
       
   112     Internal helper function for queryDatabases()
       
   113     Not meant to be used alone.
       
   114 
       
   115     \param query Text to be searched
       
   116     \return list of Contact items.
       
   117     \sa queryDatabases( )
       
   118 */
       
   119 QList<QContactLocalId> NmContactHistoryModelPrivate::queryContactDatabase(
       
   120     const QString &query)
       
   121 {
       
   122     // Define filter
       
   123     QContactDetailFilter df;
       
   124 
       
   125     df.setDetailDefinitionName(QContactEmailAddress::DefinitionName,
       
   126                                QContactEmailAddress::FieldEmailAddress );
       
   127 
       
   128     df.setMatchFlags( QContactFilter::MatchKeypadCollation );
       
   129 
       
   130     // Construct pattern
       
   131     QString pattern = query + QChar(30) + QString("vqwerty");
       
   132     df.setValue( pattern );
       
   133 
       
   134     // Get matching IDs
       
   135     QList<QContactLocalId> cnt_ids = mContactManager->contactIds( df );
       
   136 
       
   137     return cnt_ids;
       
   138 }
       
   139 
       
   140 /*!
       
   141     Internal helper function for queryDatabases()
       
   142     Not meant to be used alone.
       
   143 
       
   144     \param query Text to be searched from MRU
       
   145     \return true on success.
       
   146     \sa queryDatabases( )
       
   147 */
       
   148 bool NmContactHistoryModelPrivate::queryMruDatabase(
       
   149     const QString &query)
       
   150 {
       
   151     if (mType == EmailAddressModel)
       
   152     {
       
   153         bool mruListFilled = fillMruMatchList();
       
   154 
       
   155         if (!mruListFilled)
       
   156         {
       
   157             return false;
       
   158         }
       
   159 
       
   160         QHashIterator<QString, QString> i(mMruList);
       
   161 
       
   162         while (i.hasNext())
       
   163         {
       
   164             i.next();
       
   165 
       
   166             QString address = i.key();
       
   167             QString name = i.value();
       
   168 
       
   169             if ((name.length() == 0) && (address.contains('@')))
       
   170             {
       
   171                 name = address.left(address.indexOf("@"));
       
   172             }
       
   173 
       
   174             if (address.contains(query, Qt::CaseInsensitive))
       
   175             {
       
   176                 mMruMatches.insert(name, address);
       
   177             }
       
   178             else if (name.contains(query, Qt::CaseInsensitive))
       
   179             {
       
   180                 mMruMatches.insert(name, address);
       
   181             }
       
   182         }
       
   183     }
       
   184 
       
   185     return true;
       
   186 }
       
   187 
       
   188 /*!
       
   189     Internal helper function for queryDatabases()
       
   190     Not meant to be used alone.
       
   191 
       
   192     \param cnt_ids List of contact IDs
       
   193     \param modifiedQuery Query
       
   194     \sa queryDatabases( )
       
   195 */
       
   196 void NmContactHistoryModelPrivate::populateListWithContactItems(
       
   197     const QList<QContactLocalId> cnt_ids,
       
   198     const QString &modifiedQuery)
       
   199 {
       
   200     int cntCount = cnt_ids.count();
       
   201     // Populate mPrivateItemList with contact items.
       
   202     for ( int cntIndex = 0; cntIndex < cntCount; cntIndex++)
       
   203     {
       
   204         QContactLocalId cid = cnt_ids.at( cntIndex );
       
   205         // Fetch extended contact information from DB by ID
       
   206         QContact contact = mContactManager->contact( cid );
       
   207 
       
   208         // Get number of associated emails for contact
       
   209         int numberOfEmails =  contact.details(
       
   210             QContactEmailAddress::DefinitionName).count();
       
   211 
       
   212         if (numberOfEmails == 0)
       
   213         {
       
   214             continue; // Scotty, I need warp speed.
       
   215         }
       
   216 
       
   217         // Get contact name details
       
   218         QContactName contactName = contact.detail(
       
   219             QContactName::DefinitionName);
       
   220 
       
   221         QString firstName = contactName.value(
       
   222             QContactName::FieldFirstName);
       
   223         QString lastName = contactName.value(
       
   224             QContactName::FieldLastName);
       
   225 
       
   226         for (int emailIndex = 0; emailIndex < numberOfEmails; emailIndex++)
       
   227         {
       
   228             // For Display name (ex. John Doe)
       
   229             NmContactHistoryModelSubItem itemSubItem1;
       
   230             // For Email address (ex. john.doe@company.com)
       
   231             NmContactHistoryModelSubItem itemSubItem2;
       
   232 
       
   233             int queryLength = modifiedQuery.length();
       
   234 
       
   235             // Obey the contacts setting (first name last name order)
       
   236             itemSubItem1.mItemText = obeyContactOrder(firstName, lastName);
       
   237 
       
   238             if( firstName.indexOf(modifiedQuery, 0, Qt::CaseInsensitive) == 0)
       
   239             {
       
   240                 itemSubItem1.mMatchingRanges.append(0);
       
   241                 itemSubItem1.mMatchingRanges.append(queryLength-1);
       
   242             }
       
   243 
       
   244             if( lastName.indexOf(modifiedQuery, 0, Qt::CaseInsensitive) == 0)
       
   245             {
       
   246                 int indexLN = itemSubItem1.mItemText.indexOf(lastName,
       
   247                     firstName.length(),
       
   248                     Qt::CaseInsensitive );
       
   249 
       
   250                 itemSubItem1.mMatchingRanges.append(indexLN);
       
   251                 itemSubItem1.mMatchingRanges.append(indexLN+(queryLength-1));
       
   252             }
       
   253 
       
   254             itemSubItem2.mItemText = contact.details (
       
   255                  QContactEmailAddress::DefinitionName )[emailIndex].value (
       
   256                  QContactEmailAddress::FieldEmailAddress );
       
   257 
       
   258             if (itemSubItem2.mItemText.indexOf(modifiedQuery, 0,
       
   259                 Qt::CaseInsensitive) == 0 )
       
   260             {
       
   261                 itemSubItem2.mMatchingRanges.append(0);
       
   262                 itemSubItem2.mMatchingRanges.append(queryLength-1);
       
   263             }
       
   264 
       
   265             if ((itemSubItem1.mMatchingRanges.count() != 0) ||
       
   266                 (itemSubItem2.mMatchingRanges.count() != 0) )
       
   267             {
       
   268                 QSharedPointer<NmContactHistoryModelItemData> itemData
       
   269                     (new NmContactHistoryModelItemData);
       
   270 
       
   271                 itemData->mContactId = cid;
       
   272                 itemData->mItems.append(itemSubItem1);
       
   273                 itemData->mItems.append(itemSubItem2);
       
   274 
       
   275                 mPrivateItemList.append(itemData);
       
   276             }
       
   277         }
       
   278     }
       
   279 }
       
   280 
       
   281 /*!
       
   282     Internal helper function for queryDatabases()
       
   283     Not meant to be used alone.
       
   284 
       
   285     \param modifiedQuery Query
       
   286     \sa queryDatabases( )
       
   287 */
       
   288 void NmContactHistoryModelPrivate::populateListWithMruItems(
       
   289     const QString &query)
       
   290 {
       
   291     QMapIterator<QString, QString> i(mMruMatches);
       
   292 
       
   293     while (i.hasNext())
       
   294     {
       
   295         i.next();
       
   296         // For Display name (ex. John Doe)
       
   297         NmContactHistoryModelSubItem itemSubItem1;
       
   298         // For Email address (ex. john.doe@company.com)
       
   299         NmContactHistoryModelSubItem itemSubItem2;
       
   300 
       
   301         itemSubItem1.mItemText = i.key();
       
   302         itemSubItem2.mItemText = i.value();
       
   303 
       
   304         // markup for first item.
       
   305         if( i.key().indexOf(query, 0, Qt::CaseInsensitive) == 0)
       
   306         {
       
   307             itemSubItem1.mMatchingRanges.append(0);
       
   308             itemSubItem1.mMatchingRanges.append(query.length()-1);
       
   309         }
       
   310 
       
   311         QRegExp rx("[,\\s]", Qt::CaseInsensitive);
       
   312         bool separatorExists = i.key().contains(rx);
       
   313 
       
   314         if (separatorExists)
       
   315         {
       
   316             int indexLN = i.key().indexOf(",", 0, Qt::CaseInsensitive);
       
   317 
       
   318             if (indexLN == -1)
       
   319             {
       
   320                 indexLN = i.key().indexOf(" ", 0, Qt::CaseInsensitive);
       
   321             }
       
   322 
       
   323             if (indexLN > 0)
       
   324             {
       
   325                 int matchPos = i.key().indexOf(query, indexLN, Qt::CaseInsensitive);
       
   326 
       
   327                 if (matchPos > 0)
       
   328                 {
       
   329                     itemSubItem1.mMatchingRanges.append(matchPos);
       
   330                     itemSubItem1.mMatchingRanges.append((matchPos+query.length())-1);
       
   331                 }
       
   332             }
       
   333         }
       
   334 
       
   335         // markup for second item.
       
   336         if (itemSubItem2.mItemText.indexOf(query, 0, Qt::CaseInsensitive) == 0 )
       
   337          {
       
   338              itemSubItem2.mMatchingRanges.append(0);
       
   339              itemSubItem2.mMatchingRanges.append(query.length()-1);
       
   340          }
       
   341 
       
   342         // If match, add to data list.
       
   343         if ((itemSubItem1.mMatchingRanges.count() != 0) ||
       
   344             (itemSubItem2.mMatchingRanges.count() != 0) )
       
   345         {
       
   346             QSharedPointer<NmContactHistoryModelItemData> itemData
       
   347                 (new NmContactHistoryModelItemData);
       
   348 
       
   349             itemData->mContactId = 0; // No ID available, use 0.
       
   350             itemData->mItems.append(itemSubItem1);
       
   351             itemData->mItems.append(itemSubItem2);
       
   352 
       
   353             mPrivateItemList.append(itemData);
       
   354         }
       
   355     }
       
   356 }
       
   357 
       
   358 /*!
       
   359     After queryDatabases has completed this will be called from public class()
       
   360     Not meant to be used alone. (NmContactHistoryModel is using this when needed)
       
   361 
       
   362     \sa queryDatabases( )
       
   363 */
       
   364 void NmContactHistoryModelPrivate::refreshDataModel()
       
   365 {
       
   366     mModelItemList.clear();
       
   367 
       
   368     for (int cntIndex = 0;
       
   369              cntIndex < mPrivateItemList.count();
       
   370              cntIndex++)
       
   371     {
       
   372         // Construct modelItem to be added to list.
       
   373         NmContactHistoryModelItem modelItem;
       
   374 
       
   375         QSharedPointer<NmContactHistoryModelItemData> itemData(
       
   376             mPrivateItemList[cntIndex]);
       
   377 
       
   378         int id = itemData->mContactId;
       
   379         modelItem.setContactId(itemData->mContactId);
       
   380 
       
   381         for (int itemIndex = 0;
       
   382                  itemIndex < itemData->mItems.count();
       
   383                  itemIndex++)
       
   384         {
       
   385             QString key = itemData->mItems[itemIndex].mItemText;
       
   386             modelItem.appendSubItem(itemData->mItems[itemIndex]);
       
   387         }
       
   388 
       
   389         // Append modelItem to list.
       
   390         mModelItemList.append(modelItem);
       
   391     }
       
   392 
       
   393     // Notify views that we are done updating model data.
       
   394     mModelReady = true;
       
   395 
       
   396 }
       
   397 
       
   398 /*!
       
   399     This is called by public class NmContactHistoryModel when rowcount() is requested
       
   400     Not meant to be used alone.
       
   401 
       
   402 */
       
   403 int NmContactHistoryModelPrivate::rowCount(const QModelIndex &parent) const
       
   404 {
       
   405     Q_UNUSED(parent);
       
   406     return mModelItemList.count();
       
   407 }
       
   408 
       
   409 /*!
       
   410     This is called by public class NmContactHistoryModel when data() is requested
       
   411     Not meant to be used alone.
       
   412 
       
   413 */
       
   414 QVariant NmContactHistoryModelPrivate::data(const QModelIndex &index, int role) const
       
   415 {
       
   416     if ( mModelReady )
       
   417     {
       
   418         if (!index.isValid() ||
       
   419             index.row() >= mModelItemList.count() ||
       
   420             index.row() < 0)
       
   421         {
       
   422             return QVariant();
       
   423         }
       
   424 
       
   425         if (role == Qt::DisplayRole)
       
   426         {
       
   427             QVariant v;
       
   428             NmContactHistoryModelItem i = mModelItemList.at(index.row());
       
   429             v.setValue(i);
       
   430             return v;
       
   431         }
       
   432     }
       
   433 
       
   434     return QVariant();
       
   435 }
       
   436 
       
   437 /*!
       
   438     Fills MruMatchList, called from queryMruDatabase.
       
   439     Function uses Email MRU API to fetch information from CenRep
       
   440 
       
   441     \sa queryMruDatabase( )
       
   442 */
       
   443 bool NmContactHistoryModelPrivate::fillMruMatchList()
       
   444 {
       
   445     //TODO: Possible optimization, remove extra calls EmailMRU(), We need to get list only once.
       
   446     EmailMRU *mru = new EmailMRU();
       
   447 
       
   448     if (mru)
       
   449     {
       
   450         int addressCount = mru->entryCount();
       
   451 
       
   452         for (int i = addressCount; i > 0; i--)
       
   453         {
       
   454             QString key, value; // "Email or Number" & "Display Name"
       
   455             bool success;
       
   456 
       
   457             success = mru->getEntry(i, value, key);
       
   458 
       
   459             if (success)
       
   460             {
       
   461                 mMruList.insertMulti(key, value);
       
   462             }
       
   463         }
       
   464 
       
   465         delete mru;
       
   466         return true;
       
   467     }
       
   468     else
       
   469     {
       
   470         return false;
       
   471     }
       
   472 }
       
   473 
       
   474 /*!
       
   475     This is called from populateListWithContactItems() when correct order of
       
   476     first name, last name setting is required
       
   477 
       
   478     \param firstName First name
       
   479     \param lastName Last name
       
   480 
       
   481     \sa populateListWithContactItems( )
       
   482 
       
   483     \return concennated string formatted as contact setting specifies.
       
   484 */
       
   485 QString NmContactHistoryModelPrivate::obeyContactOrder(const QString &firstName,
       
   486                                                        const QString &lastName)
       
   487 {
       
   488     QString result;
       
   489 
       
   490     switch (mNameOrder)
       
   491     {
       
   492         case LastNameFirstName:
       
   493             result = lastName + " " + firstName;
       
   494         break;
       
   495 
       
   496         case LastNameCommaFirstName:
       
   497             result = lastName + ", " + firstName;
       
   498         break;
       
   499 
       
   500         case FirstNameLastName:
       
   501             result = firstName + " " + lastName;
       
   502         break;
       
   503 
       
   504         default:
       
   505             result = firstName + " " + lastName;
       
   506         break;
       
   507     }
       
   508 
       
   509     return result;
       
   510 }
       
   511 
       
   512 // --------------------------------------------------------------------------
       
   513 // End of implementation (NmContactHistoryModelPrivate)
       
   514 // --------------------------------------------------------------------------
       
   515