phonebookengines/cntlistmodel/src/cntlistmodel.cpp
branchRCL_3
changeset 62 5b6f26637ad3
equal deleted inserted replaced
58:d4f567ce2e7c 62:5b6f26637ad3
       
     1 /*
       
     2 * Copyright (c) 2009 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 #include "cntlistmodel_p.h"
       
    18 #include "cntlistmodel.h"
       
    19 #include "cntcache.h"
       
    20 #include "cntdebug.h"
       
    21 
       
    22 #include <qtcontacts.h>
       
    23 #include <QSet>
       
    24 #include <QTimerEvent>
       
    25 
       
    26 #include <hbindexfeedback.h>
       
    27 #include <hbframebackground.h>
       
    28 #include <hbframedrawer.h>
       
    29 #include <xqsettingsmanager.h> // for reading cenrep keys
       
    30 #include <xqsettingskey.h>
       
    31 
       
    32 const uint dummyMyCardId = 0;
       
    33 
       
    34 /*!
       
    35  * Constuct a new contact model instance. The model will own its handle
       
    36  * to the default persisted store.
       
    37  */
       
    38 CntListModel::CntListModel(const QContactFilter& contactFilter,
       
    39                          bool showMyCard,
       
    40                          QObject *parent)
       
    41     : QAbstractListModel(parent)
       
    42 {
       
    43     CNT_ENTRY
       
    44     m_defaultIcon = HbIcon("qtg_large_avatar");
       
    45     m_defaultMyCardIcon = HbIcon("qtg_large_avatar_mycard");
       
    46 
       
    47     d = new CntListModelData(contactFilter, showMyCard);
       
    48     d->m_contactManager = new QContactManager;
       
    49     d->m_ownedContactManager = true;
       
    50     d->m_cache = CntCache::instance();
       
    51     connect(d->m_cache, SIGNAL(contactInfoUpdated(QContactLocalId)), this, SLOT(handleContactInfoUpdated(QContactLocalId)));
       
    52     d->m_myCardId = d->m_contactManager->selfContactId();
       
    53     if (doConstruct() != QContactManager::NoError) {
       
    54         throw("exception");
       
    55     }
       
    56     CNT_EXIT
       
    57 }
       
    58 
       
    59 /*!
       
    60  * Construct a new CntListModel object using manager as the QContactManager
       
    61  * instance to communicate with the contacts database.
       
    62  *
       
    63  * \param manager A QContactManager instance to be used for
       
    64  *  communications with the contacts persistant store.
       
    65  */
       
    66 CntListModel::CntListModel(QContactManager* manager,
       
    67                          const QContactFilter& contactFilter,
       
    68                          bool showMyCard,
       
    69                          QObject *parent)
       
    70     : QAbstractListModel(parent)
       
    71 {
       
    72     CNT_ENTRY
       
    73     m_defaultIcon = HbIcon("qtg_large_avatar");
       
    74     m_defaultMyCardIcon = HbIcon("qtg_large_avatar_mycard");
       
    75 
       
    76     d = new CntListModelData(contactFilter, showMyCard);
       
    77 
       
    78     d->m_contactManager = manager;
       
    79     d->m_cache = CntCache::instance();
       
    80 
       
    81     connect(d->m_cache, SIGNAL(contactInfoUpdated(QContactLocalId)), this, SLOT(handleContactInfoUpdated(QContactLocalId)));
       
    82     d->m_myCardId = d->m_contactManager->selfContactId();     
       
    83 
       
    84     if (doConstruct() != QContactManager::NoError) {
       
    85         throw("exception");
       
    86     }
       
    87     CNT_EXIT
       
    88 }
       
    89 
       
    90 CntListModel::~CntListModel()
       
    91 {
       
    92 }
       
    93 
       
    94 /*!
       
    95  * Return the data to be used by the view or delegates for a particular
       
    96  * item and role.
       
    97  *
       
    98  * \param index The index of the item to return data about.
       
    99  * \param role The data should be relevant for this particular purpose.
       
   100  * \return QVariant The data for the specified index and role.
       
   101  */
       
   102 QVariant CntListModel::data(const QModelIndex &index, int role) const
       
   103 {
       
   104     CNT_ENTRY
       
   105     int row = index.row();
       
   106 
       
   107     // check that row is ok
       
   108     if (!validRowId(row)) {
       
   109         // invalid row
       
   110         return QVariant();
       
   111     }
       
   112     
       
   113     // update current contact if needed
       
   114     if (row != d->m_currentRow ) {
       
   115         if (d->m_contactIds[row] == dummyMyCardId) {
       
   116             // row contains dummy MyCard, so create dummy CntContactInfo
       
   117             d->m_currentContact = CntContactInfo();
       
   118         }
       
   119         else {
       
   120             d->m_currentContact = d->m_cache->fetchContactInfo(row, d->m_contactIds);
       
   121         }
       
   122         d->m_currentRow = row;
       
   123     }
       
   124     
       
   125     if (role == Qt::DisplayRole) {
       
   126         return dataForRole(row, role);
       
   127     }
       
   128     else if (role == Hb::IndexFeedbackRole) {
       
   129         if (row == 0 && (d->m_myCardId == d->m_contactIds[0] || dummyMyCardId == d->m_contactIds[0])) {
       
   130             // do not include MyCard in index feedback
       
   131             return QVariant();
       
   132         }
       
   133         else {
       
   134             return dataForRole(row, role).toStringList().at(0).toUpper();
       
   135         }
       
   136     }
       
   137     else if (role == Qt::BackgroundRole) {
       
   138         if (d->m_myCardId == d->m_contactIds[row] || dummyMyCardId == d->m_contactIds[row]) {
       
   139             return HbFrameBackground("qtg_fr_list_parent_normal", HbFrameDrawer::NinePieces);
       
   140         }
       
   141     }
       
   142     else if (role == Qt::DecorationRole) {
       
   143         if (d->m_currentRowSetting == CntTwoRowsNameAndPhoneNumber) {
       
   144             //icon fits only if user selected 2 rows in each name list item
       
   145             QList<QVariant> icons;
       
   146             HbIcon avatar = d->m_currentContact.icon1();
       
   147             HbIcon statusIcon = d->m_currentContact.icon2();
       
   148         
       
   149             if (!avatar.isNull()) {
       
   150                 icons.append(avatar);
       
   151             }
       
   152             else if (d->m_myCardId == d->m_contactIds[row] || dummyMyCardId == d->m_contactIds[row]) {
       
   153                 icons.append(m_defaultMyCardIcon);
       
   154             }
       
   155             else {
       
   156                 icons.append(m_defaultIcon);
       
   157             }
       
   158     
       
   159             if (!statusIcon.isNull()) {
       
   160                 icons.append(statusIcon);
       
   161             }
       
   162     
       
   163             return icons;
       
   164         }
       
   165         else {
       
   166             return QVariant();
       
   167         }
       
   168     }
       
   169     CNT_EXIT
       
   170     return QVariant();
       
   171 }
       
   172 
       
   173 /*!
       
   174  * Get the number of rows (contacts) in this model.
       
   175  *
       
   176  * \param parent Optional parent index value.
       
   177  * \return Number of contacts in this model.
       
   178  */
       
   179 int CntListModel::rowCount(const QModelIndex& /*parent*/) const
       
   180 {
       
   181     return d->m_contactIds.count();
       
   182 }
       
   183 
       
   184 /*!
       
   185  * Read a full contact entry from the database for the given model
       
   186  * index value. Only the row part of the index information will be
       
   187  * read. This is just an overload of CntListModel::contact() that
       
   188  * supports old behaviour and calls:
       
   189  *      CntListModel::contact(int row);
       
   190  *
       
   191  * The entry at the requested row will have its full contact information
       
   192  * (all fields) read from the database and returned as a QContact instance.
       
   193  *
       
   194  * \param index Index for the sought contact entry in this model.
       
   195  * \return A newly constructed QContact instance for this entry - ownership
       
   196  *  is transferred to the caller.
       
   197  *
       
   198  */
       
   199 QContact CntListModel::contact(const QModelIndex &index) const
       
   200 {
       
   201     return contact(index.row());
       
   202 }
       
   203 
       
   204 /*!
       
   205  * Returns the id for the contact at the requested row.
       
   206  *
       
   207  * \param index Index for the sought contact entry in this model.
       
   208  * \return The id for the contact, 0 if invalid index.
       
   209  *
       
   210  */
       
   211 QContactLocalId CntListModel::contactId(const QModelIndex &index) const
       
   212 {
       
   213     CNT_ENTRY
       
   214 
       
   215     if (!validRowId(index.row())) {
       
   216         return 0;
       
   217     }
       
   218 
       
   219     CNT_EXIT
       
   220     return d->m_contactIds[index.row()];
       
   221 }
       
   222 
       
   223 /*!
       
   224  * Return an index that points to the row relating to the supplied contact.
       
   225  *  E.g. if the contact is at row 7, the index with the following properties
       
   226  *  is returned:
       
   227  *      index.row() == 7
       
   228  
       
   229  * \param contact The contact for whose row an index is required
       
   230  * \return a QModelIndex with the row set to match that of the contact.
       
   231  */
       
   232 QModelIndex CntListModel::indexOfContact(const QContact &contact) const
       
   233 {
       
   234     return createIndex(rowId(contact.localId()), 0);
       
   235 }
       
   236 
       
   237 /*!
       
   238  * Return an index that points to the row relating to the supplied contact id.
       
   239  *  E.g. if the contact with this id is at row 7, the index with the following
       
   240  *  properties is returned:
       
   241  *      index.row() == 7
       
   242  
       
   243  * \param contactId The id of the contact for whose row an index is required
       
   244  * \return a QModelIndex with the row set to match that of the contact id.
       
   245  */
       
   246 QModelIndex CntListModel::indexOfContactId(const QContactLocalId &contactId) const
       
   247 {
       
   248     return createIndex(rowId(contactId), 0);
       
   249 }
       
   250 
       
   251 /*!
       
   252  * Return the contact manager used by this model.
       
   253  *
       
   254  * \return Reference to contact manager.
       
   255  */
       
   256 QContactManager& CntListModel::contactManager() const
       
   257 {
       
   258     return *d->m_contactManager;
       
   259 }
       
   260 
       
   261 /*!
       
   262  * Set new filter and sort order for the model.
       
   263  *
       
   264  * \param contactFilter New contact filter.
       
   265  * \param contactSortOrders New sort order.
       
   266  */
       
   267 void CntListModel::setFilter(const QContactFilter& contactFilter)
       
   268 {
       
   269     CNT_ENTRY
       
   270     
       
   271     d->setFilter(contactFilter);
       
   272     
       
   273     //refresh model
       
   274     updateContactIdsArray();
       
   275 
       
   276     beginResetModel();
       
   277     reset();
       
   278     endResetModel();
       
   279     
       
   280     CNT_EXIT
       
   281 }
       
   282 
       
   283 void CntListModel::setSortOrder()
       
   284 {
       
   285     XQSettingsKey nameOrderKey(XQSettingsKey::TargetCentralRepository,
       
   286                          KCRCntSettings.iUid,
       
   287                          KCntNameOrdering);
       
   288     XQSettingsManager settingsMng;
       
   289     int order = settingsMng.readItemValue(nameOrderKey, XQSettingsManager::TypeInt).toInt();
       
   290 
       
   291     QContactSortOrder sortOrderFirstName;
       
   292     sortOrderFirstName.setDetailDefinitionName(QContactName::DefinitionName,
       
   293         QContactName::FieldFirstName);
       
   294     sortOrderFirstName.setCaseSensitivity(Qt::CaseInsensitive);
       
   295 
       
   296     QContactSortOrder sortOrderLastName;
       
   297     sortOrderLastName.setDetailDefinitionName(QContactName::DefinitionName,
       
   298         QContactName::FieldLastName);
       
   299     sortOrderLastName.setCaseSensitivity(Qt::CaseInsensitive);
       
   300 
       
   301     QList<QContactSortOrder> sortOrders;
       
   302     if (order == CntOrderLastFirst || order == CntOrderLastCommaFirst) {
       
   303         sortOrders.append(sortOrderLastName);
       
   304         sortOrders.append(sortOrderFirstName);
       
   305     } else {
       
   306         sortOrders.append(sortOrderFirstName);
       
   307         sortOrders.append(sortOrderLastName);
       
   308     }
       
   309     
       
   310     d->m_sortOrders = sortOrders;
       
   311 }
       
   312 
       
   313 void CntListModel::refreshModel()
       
   314 {
       
   315     CNT_ENTRY
       
   316     
       
   317     setSortOrder();
       
   318     d->m_cache->clearCache();
       
   319     d->m_currentRow = -1;
       
   320     
       
   321     //refresh model
       
   322     updateContactIdsArray();
       
   323 
       
   324     beginResetModel();
       
   325     reset();
       
   326     endResetModel();
       
   327     
       
   328     CNT_EXIT
       
   329 }
       
   330 
       
   331 /*!
       
   332  * Enable/disable MyCard appearance in the model.
       
   333  *
       
   334  * \param enabled Status of MyCard appearance in the model.
       
   335  */
       
   336 void CntListModel::showMyCard(bool enabled)
       
   337 {
       
   338     CNT_ENTRY
       
   339     if (d->m_showMyCard == enabled) {
       
   340         return;
       
   341     }
       
   342     
       
   343     QContactLocalId myCardId = d->m_myCardId;
       
   344     if (enabled) {
       
   345         //add MyCard to the list
       
   346         if (myCardId <= 0) {
       
   347             // create a placeholder for MyCard
       
   348             d->m_contactIds.insert(0, dummyMyCardId);
       
   349         }
       
   350         else {
       
   351             d->m_contactIds.insert(0, myCardId);
       
   352         }
       
   353     }
       
   354     else {
       
   355         // remove MyCard from the list
       
   356         if (myCardId <= 0) {
       
   357             d->m_contactIds.removeOne(dummyMyCardId);
       
   358         }
       
   359         else {
       
   360             d->m_contactIds.removeOne(myCardId);
       
   361         }
       
   362     }
       
   363     d->m_showMyCard = enabled;
       
   364     d->m_currentRow = -1;
       
   365 
       
   366     beginResetModel();
       
   367     reset();
       
   368     endResetModel();
       
   369     CNT_EXIT
       
   370 }
       
   371 
       
   372 /*!
       
   373  * Returns MyCard status: shown or not.
       
   374  *
       
   375  * \return true if MyCard is shown, false otherwise.
       
   376  */
       
   377 bool CntListModel::myCardStatus() const
       
   378 {
       
   379     return d->m_showMyCard;
       
   380 }
       
   381 
       
   382 /*!
       
   383  * Returns MyCard id.
       
   384  *
       
   385  * \return MyCard id.
       
   386  */
       
   387 QContactLocalId CntListModel::myCardId() const
       
   388 {
       
   389     return d->m_myCardId;
       
   390 }
       
   391 
       
   392 /*!
       
   393  * Initializes model data and attaches database notifications to handlers.
       
   394  * 
       
   395  * \return Error status
       
   396  */
       
   397 int CntListModel::doConstruct()
       
   398 {
       
   399     CNT_ENTRY
       
   400     
       
   401     int error = initializeData();
       
   402     
       
   403     // Attach database notifications to handlers.
       
   404     connect(d->m_contactManager, SIGNAL(contactsAdded(const QList<QContactLocalId>&)), this, SLOT(handleAdded(const QList<QContactLocalId>&)));
       
   405     connect(d->m_contactManager, SIGNAL(contactsChanged(const QList<QContactLocalId>&)), this, SLOT(handleChanged(const QList<QContactLocalId>&)));
       
   406     connect(d->m_contactManager, SIGNAL(contactsRemoved(const QList<QContactLocalId>&)), this, SLOT(handleRemoved(const QList<QContactLocalId>&)));
       
   407     connect(d->m_contactManager, SIGNAL(selfContactIdChanged(const QContactLocalId&, const QContactLocalId&)), this, SLOT(handleMyCardChanged(const QContactLocalId&, const QContactLocalId&)));
       
   408     connect(d->m_contactManager, SIGNAL(dataChanged()), this, SLOT(refreshModel()));
       
   409     connect(d->m_contactManager, SIGNAL(relationshipsAdded(const QList<QContactLocalId>&)), this, SLOT(handleAddedRelationship(const QList<QContactLocalId>&)));
       
   410     connect(d->m_contactManager, SIGNAL(relationshipsRemoved(const QList<QContactLocalId>&)), this, SLOT(handleRemovedRelationship(const QList<QContactLocalId>&)));
       
   411     
       
   412     // Get current setting how to show an item in the name list and subscribe for changes
       
   413     d->m_Settings = new XQSettingsManager;
       
   414 
       
   415     d->m_NameListRowSettingkey = new XQSettingsKey(XQSettingsKey::TargetCentralRepository,
       
   416                             KCRCntSettings.iUid,
       
   417                             KCntNameListRowSetting);
       
   418     d->m_currentRowSetting = d->m_Settings->readItemValue(*d->m_NameListRowSettingkey, XQSettingsManager::TypeInt).toInt();
       
   419     d->m_Settings->startMonitoring(*d->m_NameListRowSettingkey, XQSettingsManager::TypeInt);
       
   420     connect(d->m_Settings, SIGNAL(valueChanged(const XQSettingsKey&, const QVariant&)), this, SLOT(handleRowSettingChanged(const XQSettingsKey&, const QVariant&)));
       
   421     
       
   422     CNT_EXIT
       
   423 
       
   424     return error;
       
   425 }
       
   426 
       
   427 /*!
       
   428  * Initializes d->m_contactIds to contain contact Ids from the database.
       
   429  * 
       
   430  * \return Error status
       
   431  */
       
   432 int CntListModel::initializeData()
       
   433 {
       
   434     CNT_ENTRY
       
   435     int error(QContactManager::NoError);
       
   436     
       
   437     setSortOrder();
       
   438 
       
   439     // Get a list of all contact IDs in the database.
       
   440     updateContactIdsArray();
       
   441 
       
   442     CNT_EXIT
       
   443     return error;
       
   444 }
       
   445 
       
   446 /*!
       
   447  * Gets the filtered list of the contact Ids in a sorted order  
       
   448  * 
       
   449  * \return Error status
       
   450  */
       
   451 void CntListModel::updateContactIdsArray()
       
   452 {
       
   453     CNT_ENTRY
       
   454     d->m_contactIds = d->m_contactManager->contactIds(d->m_filter,
       
   455             d->m_sortOrders);
       
   456                       
       
   457     //find MyCard contact and move it to the first position
       
   458     QContactLocalId myCardId = d->m_myCardId;
       
   459     if (myCardId > 0) {
       
   460         // MyCard exists
       
   461         d->m_contactIds.removeOne(myCardId);
       
   462         if (d->m_showMyCard) {
       
   463             d->m_contactIds.insert(0, myCardId);
       
   464         }
       
   465     } 
       
   466     else if (d->m_showMyCard) {
       
   467         // create a placeholder for MyCard
       
   468         d->m_contactIds.insert(0, dummyMyCardId);
       
   469     }
       
   470     CNT_EXIT
       
   471 }
       
   472 
       
   473 /*!
       
   474  * Read a full contact entry from the database for the row number.
       
   475  *
       
   476  * The entry at the requested row will have its full contact information
       
   477  * (all fields) read from the database and returned as a QContact instance.
       
   478  *
       
   479  * \param row Row at which the sought contact entry is in this model.
       
   480  * \return A newly constructed QContact instance for this entry - ownership
       
   481  *  is transferred to the caller.
       
   482  *
       
   483  */
       
   484 QContact CntListModel::contact(int row) const
       
   485 {
       
   486     CNT_ENTRY
       
   487     if (!validRowId(row) || d->m_contactIds[row] == dummyMyCardId) {
       
   488         return QContact();
       
   489     }
       
   490     CNT_EXIT
       
   491     return d->m_contactManager->contact(d->m_contactIds[row]);
       
   492 }
       
   493 
       
   494 /*!
       
   495  * Verify specified row id is valid.
       
   496  *
       
   497  * \param row A row number
       
   498  * \return bool indicating validity of row id
       
   499  */
       
   500 bool CntListModel::validRowId(int row) const
       
   501 {
       
   502 	return (row >= 0 && row < rowCount());
       
   503 }
       
   504 
       
   505 /*!
       
   506  * Fetch the id of the row containing the contact of the specified id.
       
   507  *
       
   508  * \param contactId The id of the contact
       
   509  * \return the row id of the contact or -1 if no item matched.
       
   510  */
       
   511 int CntListModel::rowId(const QContactLocalId &contactId) const
       
   512 {
       
   513     return d->m_contactIds.indexOf(contactId);
       
   514 }
       
   515 
       
   516 /*!
       
   517  * Return the data to be used by the view for a display role.
       
   518  *
       
   519  * \param row The row of the item to return data about.
       
   520  * \param column The column of the item to return data about.
       
   521  * \return QVariant The data for the specified index.
       
   522  */
       
   523 QVariant CntListModel::dataForRole(int row, int role) const
       
   524 {
       
   525     CNT_ENTRY
       
   526     QStringList list;
       
   527     QString name;
       
   528     QString infoText;
       
   529     bool isSelfContact = false;
       
   530     bool isNonEmptySelfContact = false;
       
   531     
       
   532     QContactLocalId id = d->m_contactIds[row];
       
   533     if (d->m_myCardId == id || dummyMyCardId == id) {
       
   534         isSelfContact = true;
       
   535         if (d->m_currentContact.id() == -1) {
       
   536             // empty card
       
   537             name = hbTrId("txt_phob_dblist_mycard");
       
   538             infoText = hbTrId("txt_phob_dblist_mycard_val_create_my_identity");
       
   539         }
       
   540         else {
       
   541             isNonEmptySelfContact = true;
       
   542         }
       
   543     }
       
   544 
       
   545     if (!isSelfContact || isNonEmptySelfContact) {
       
   546         name = d->m_currentContact.name();
       
   547         if (name.isEmpty()) {
       
   548             name = hbTrId("txt_phob_list_unnamed");
       
   549         }
       
   550         infoText = d->m_currentContact.text();
       
   551     }
       
   552     
       
   553     if ( role == Qt::DisplayRole )
       
   554     {
       
   555         list << d->m_Format->formattedText(name, d->m_filter);
       
   556     }
       
   557     else
       
   558     {
       
   559         list << name;
       
   560     }
       
   561     
       
   562     if (!isNonEmptySelfContact) {
       
   563         if (d->m_currentRowSetting == CntTwoRowsNameAndPhoneNumber) {
       
   564             //add additional text only if user wants 2 rows in each name list item
       
   565             list << infoText;
       
   566         }
       
   567     }
       
   568     CNT_EXIT
       
   569     return list;
       
   570 }
       
   571 
       
   572 /*!
       
   573  * Handle adding of contacts. 
       
   574  *
       
   575  * \param contactIds Ids of contacts added.
       
   576  */
       
   577 void CntListModel::handleAdded(const QList<QContactLocalId>& contactIds)
       
   578 {
       
   579     CNT_ENTRY
       
   580     
       
   581     //if contacts are added already, no need to do anything
       
   582     bool newContacts = false;
       
   583     for (int k = 0; k < contactIds.count() && !newContacts; k++) { 
       
   584         if(!d->m_contactIds.contains(contactIds.at(k))) {
       
   585             newContacts = true;
       
   586         }
       
   587     }
       
   588     if (!newContacts) {
       
   589         return;
       
   590     }
       
   591 
       
   592     //invalidate cached contact
       
   593     d->m_currentRow = -1;
       
   594     
       
   595     QList<QContactLocalId> oldIdList = d->m_contactIds;
       
   596     updateContactIdsArray();
       
   597     
       
   598     //Find all new contacts (=rows)
       
   599     QList<int> newRows;
       
   600     for(int i = 0; i < d->m_contactIds.count(); i++) {
       
   601         if (!oldIdList.contains(d->m_contactIds.at(i))) {
       
   602             newRows.append(i);
       
   603         }
       
   604     }
       
   605     
       
   606     // only 1 (or no) contact is added, it can be handled by beginInsertRows()
       
   607     // and endInsertRows()
       
   608     if (newRows.count() <= 1) {
       
   609         for(int j = 0; j < newRows.count(); j++) {
       
   610             beginInsertRows(QModelIndex(), newRows.at(j), newRows.at(j));
       
   611             endInsertRows();   
       
   612         }
       
   613     }
       
   614     else {
       
   615         beginResetModel();
       
   616         reset();
       
   617         endResetModel();
       
   618     }
       
   619     CNT_EXIT
       
   620 }
       
   621 
       
   622 /*!
       
   623  * Handle changes in contacts. 
       
   624  *
       
   625  * \param contactIds Ids of contacts changed.
       
   626  */
       
   627 void CntListModel::handleChanged(const QList<QContactLocalId>& contactIds)
       
   628 {
       
   629     CNT_ENTRY
       
   630     
       
   631     if (contactIds.count() == 0) {
       
   632         return;
       
   633     }
       
   634     
       
   635     //invalidate cached contact
       
   636     d->m_currentRow = -1; 
       
   637 
       
   638     int firstChangedContactPosBefore = rowId(contactIds.at(0));  
       
   639     updateContactIdsArray();
       
   640     int firstChangedContactPosAfter = rowId(contactIds.at(0)); 
       
   641 
       
   642     // if only one contact was updated and its position didn't change,
       
   643     // refresh the corresponding row
       
   644     if (contactIds.count() == 1 &&
       
   645         firstChangedContactPosBefore == firstChangedContactPosAfter &&
       
   646         firstChangedContactPosBefore >= 0) {
       
   647         QModelIndex top = index(firstChangedContactPosBefore);
       
   648         QModelIndex bottom = index(firstChangedContactPosBefore);
       
   649         emit dataChanged(top, bottom);
       
   650     }
       
   651     else {
       
   652         beginResetModel();
       
   653         reset();
       
   654         endResetModel();
       
   655     }
       
   656     
       
   657     CNT_EXIT
       
   658 }
       
   659 
       
   660 /*!
       
   661  * Handle removing of contacts. 
       
   662  *
       
   663  * \param contactIds Ids of contacts removed.
       
   664  */
       
   665 void CntListModel::handleRemoved(const QList<QContactLocalId>& contactIds)
       
   666 {
       
   667     CNT_ENTRY
       
   668     
       
   669     bool removeContacts = false;
       
   670     QList<QContactLocalId> idList = d->m_contactIds;
       
   671     for (int k = 0; k < contactIds.count() && !removeContacts; k++) {
       
   672         if(idList.contains(contactIds.at(k))) {
       
   673             removeContacts = true;
       
   674         }
       
   675     }
       
   676     if (!removeContacts) {
       
   677         return;
       
   678     }
       
   679     
       
   680     //Find contacts to remove (=rows)
       
   681     QList<int> removeRows;
       
   682     for(int i = 0; i < contactIds.count(); i++) {
       
   683         if (idList.contains(contactIds.at(i))) {
       
   684             removeRows.append(rowId(contactIds.at(i)));
       
   685         }
       
   686     }
       
   687     
       
   688     // invalidate cached contact
       
   689     d->m_currentRow = -1;
       
   690     
       
   691     int myCardRow = -1;
       
   692     if (contactIds.contains(d->m_myCardId)) {
       
   693         myCardRow = rowId(d->m_myCardId);
       
   694         d->m_myCardId = 0;
       
   695     }
       
   696 
       
   697     // remove rows starting from the bottom
       
   698     qSort(removeRows.begin(), removeRows.end(), qGreater<int>());
       
   699     for (int j = 0; j < removeRows.count(); j++) {
       
   700         if (removeRows.at(j) != myCardRow || !d->m_showMyCard) {
       
   701             beginRemoveRows(QModelIndex(), removeRows.at(j), removeRows.at(j));
       
   702             endRemoveRows();
       
   703         }
       
   704     }
       
   705 
       
   706     foreach (QContactLocalId id, contactIds) {
       
   707         d->m_contactIds.removeOne(id);
       
   708     }
       
   709 
       
   710     if (myCardRow != -1 && d->m_showMyCard) {
       
   711         d->m_contactIds.insert(0, dummyMyCardId);
       
   712         QModelIndex index = createIndex(0, 0);
       
   713         emit dataChanged(index, index);
       
   714     }
       
   715 
       
   716     CNT_EXIT
       
   717 }
       
   718 
       
   719 /*!
       
   720  * Handle my card change. 
       
   721  *
       
   722  * \param oldId Id of the old MyCard.
       
   723  * \param newId Id of the new MyCard.
       
   724  */
       
   725 void CntListModel::handleMyCardChanged(const QContactLocalId& /*oldId*/, const QContactLocalId& newId)
       
   726 {
       
   727     CNT_ENTRY
       
   728     
       
   729     //invalidate cached contact
       
   730     d->m_currentRow = -1;
       
   731     d->m_myCardId = newId;
       
   732 
       
   733     updateContactIdsArray();
       
   734     
       
   735     beginResetModel();
       
   736     reset();
       
   737     endResetModel();
       
   738     
       
   739     CNT_EXIT
       
   740 }
       
   741 
       
   742 /*!
       
   743  * Handle added relationships. 
       
   744  *
       
   745  * \param contactIds Ids of contacts added (group id and contact ids).
       
   746  */
       
   747 void CntListModel::handleAddedRelationship(const QList<QContactLocalId>& contactIds)
       
   748 {
       
   749     CNT_ENTRY
       
   750 
       
   751     if (contactIds.contains(d->m_groupId)) {
       
   752         foreach (QContactLocalId id, contactIds) {
       
   753             if (id != d->m_groupId && !d->m_contactIds.contains(id)) {
       
   754                 // at least one new contact id has been added to this group,
       
   755                 // so update the model
       
   756                 updateRelationships();
       
   757                 break;
       
   758             }
       
   759         }
       
   760     }
       
   761 
       
   762     CNT_EXIT
       
   763 }
       
   764 
       
   765 /*!
       
   766  * Handle removed relationships. 
       
   767  *
       
   768  * \param contactIds Ids of contacts removed from a relationship (group id and contact ids).
       
   769  */
       
   770 void CntListModel::handleRemovedRelationship(const QList<QContactLocalId>& contactIds)
       
   771 {
       
   772     CNT_ENTRY
       
   773 
       
   774     if (contactIds.contains(d->m_groupId)) {
       
   775         foreach (QContactLocalId id, contactIds) {
       
   776             if (d->m_contactIds.contains(id)) {
       
   777                 // at least one new contact id has been removed from this group,
       
   778                 // so update the model
       
   779                 updateRelationships();
       
   780                 break;
       
   781             }
       
   782         }
       
   783     }
       
   784 
       
   785     CNT_EXIT
       
   786 }
       
   787 
       
   788 /*!
       
   789  * Updates the model to reflect changes in the relationships.
       
   790  */
       
   791 void CntListModel::updateRelationships()
       
   792 {
       
   793     CNT_ENTRY
       
   794 
       
   795     //invalidate cached contact
       
   796     d->m_currentRow = -1;
       
   797     
       
   798     QList<QContactLocalId> oldIdList = d->m_contactIds;
       
   799     updateContactIdsArray();
       
   800     
       
   801     // find all changed rows
       
   802     QList<int> newRows, removedRows;
       
   803     for (int i = 0; i < d->m_contactIds.count(); i++) {
       
   804         if (!oldIdList.contains(d->m_contactIds.at(i))) {
       
   805             newRows.append(i);
       
   806         }
       
   807     }
       
   808     for (int i = 0; i < oldIdList.count(); i++) {
       
   809         if (!d->m_contactIds.contains(oldIdList.at(i))) {
       
   810             removedRows.append(i);
       
   811         }
       
   812     }
       
   813 
       
   814     // currently only one-row-changes are handled with beginInsertRows/beginRemoveRows
       
   815     // if there are more than one change, the whole model is reset
       
   816     if (removedRows.count() == 1 && newRows.count() == 0) {
       
   817         beginRemoveRows(QModelIndex(), removedRows.at(0), removedRows.at(0));
       
   818         endRemoveRows();
       
   819     }
       
   820     else if (newRows.count() == 1 && removedRows.count() == 0) {
       
   821         beginInsertRows(QModelIndex(), newRows.at(0), newRows.at(0));
       
   822         endInsertRows();
       
   823     }
       
   824     else {
       
   825         beginResetModel();
       
   826         endResetModel();
       
   827     }
       
   828 
       
   829     CNT_EXIT
       
   830 }
       
   831 
       
   832 /*!
       
   833 * Notify views that info for a contact has become
       
   834 * available or has changed.
       
   835 *
       
   836 * \param contactId the id of the contact
       
   837 */
       
   838 void CntListModel::handleContactInfoUpdated(QContactLocalId contactId)
       
   839 {
       
   840     CNT_ENTRY
       
   841     
       
   842     QModelIndex index = createIndex(rowId(contactId), 0);
       
   843     if (index.row() == d->m_currentRow) {
       
   844         d->m_currentRow = -1;
       
   845     }
       
   846     emit dataChanged(index, index);
       
   847     
       
   848     CNT_EXIT
       
   849 }
       
   850 
       
   851 /*!
       
   852 * Handle a change how name list item should be represented
       
   853 *
       
   854 * \param key Central repository key
       
   855 * \param value New value in the key
       
   856 */
       
   857 void CntListModel::handleRowSettingChanged(const XQSettingsKey& /*key*/, const QVariant& value)
       
   858 {
       
   859     bool ok = false;
       
   860     int newSetting = value.toInt(&ok);
       
   861     if (ok) {
       
   862         d->m_currentRowSetting = newSetting;
       
   863         beginResetModel();
       
   864         reset();
       
   865         endResetModel();
       
   866     }
       
   867 }