phonebookui/cnthistorymodel/cnthistorymodel_p.cpp
changeset 81 640d30f4fb64
equal deleted inserted replaced
77:c18f9fa7f42e 81:640d30f4fb64
       
     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 
       
    18 #include <QStringList>
       
    19 #include <QtAlgorithms>
       
    20 #include <hbglobal.h>
       
    21 #include <hbicon.h>
       
    22 #include <hbframebackground.h>
       
    23 
       
    24 #include "cnthistorymodel_p.h"
       
    25 #include "cntdebug.h"
       
    26 
       
    27 
       
    28 // Unnamed namespace for helper functions
       
    29 namespace
       
    30 {
       
    31     bool greaterThan(const HItemPointer& t1, const HItemPointer& t2)
       
    32     {
       
    33         return ((*t1).timeStamp > (*t2).timeStamp);
       
    34     }
       
    35     
       
    36     bool lessThan(const HItemPointer& t1, const HItemPointer& t2)
       
    37     {
       
    38         return ((*t1).timeStamp < (*t2).timeStamp);
       
    39     }
       
    40     
       
    41 #ifdef TRACES
       
    42 #define LOG_ITEM(i) logItem(i)    
       
    43     void logItem(const HistoryItem& item)
       
    44     {
       
    45         QStringList l;
       
    46         
       
    47         l << item.message << item.number << item.timeStamp.toString() << item.title;
       
    48         l << (item.flags & CntIncoming ? "incoming" : "outgoing");
       
    49         l << (item.flags & CntUnseen ? "unseen" : "seen");
       
    50         l << (item.flags & CntAttachment ? "attachment" : "");
       
    51         l << (item.flags & CntCallLog ? "call" : "message");
       
    52         if (item.flags & CntReceivedCall)
       
    53             l << "recieved";
       
    54         else if (item.flags & CntMissedCall)
       
    55             l << "missed";
       
    56         else if (item.flags & CntDialledCall)
       
    57             l << "dialled";
       
    58         
       
    59         l.removeAll("");
       
    60         
       
    61         qDebug() << l;
       
    62     }
       
    63 #else
       
    64 #define LOG_ITEM(i)
       
    65 #endif
       
    66 }
       
    67 
       
    68 Q_DECLARE_METATYPE(LogsEvent *)
       
    69 
       
    70 /*!
       
    71  * Construct a new CntHistoryModelPrivatePrivate object to communicate 
       
    72  * with the conversations and logs databases.
       
    73  *
       
    74  * \param contactId History specific to this contact is cached. 
       
    75  * If no contact is specified all the call logs and conversation 
       
    76  * history from all contacts will be cached.
       
    77  */
       
    78 CntHistoryModelPrivate::CntHistoryModelPrivate(QContactLocalId contactId, QContactManager* manager)
       
    79     : QObject(),
       
    80       m_logsModel(NULL),
       
    81       m_logsFilter(NULL),
       
    82       m_AbstractLogsModel(NULL),
       
    83       m_msgHistory(NULL),
       
    84       m_contactId(contactId),
       
    85       m_contactManager(manager),
       
    86       m_isMyCard(false),
       
    87       m_isMarkedAsSeen(false),
       
    88       m_initLogs(false),
       
    89       m_extendedLocale(HbExtendedLocale::system())
       
    90 {
       
    91     CNT_ENTRY
       
    92     
       
    93     // Create the model structure and cache history data from the databases
       
    94     initializeModel();
       
    95     
       
    96     CNT_EXIT
       
    97 }
       
    98 
       
    99 CntHistoryModelPrivate::~CntHistoryModelPrivate()
       
   100 {
       
   101     CNT_ENTRY
       
   102     
       
   103     delete m_logsModel;
       
   104     delete m_logsFilter;
       
   105     delete m_msgHistory;
       
   106     
       
   107     CNT_EXIT
       
   108 }
       
   109 
       
   110 /*!
       
   111  * Return the data to be used by the view or delegates for a particular
       
   112  * item and role.
       
   113  *
       
   114  * \param index The index of the item to return data about.
       
   115  * \param role The data should be relevant to this particular purpose.
       
   116  * \return QVariant The data for the specified index and role.
       
   117  */
       
   118 QVariant CntHistoryModelPrivate::data(const QModelIndex& index, int role) const
       
   119 {
       
   120     CNT_ENTRY_ARGS(index << role)
       
   121     // Invalid index
       
   122     int row = index.row();
       
   123     
       
   124     if ( !validateRowIndex(row) )
       
   125         return QVariant();
       
   126     
       
   127     HItemPointer p = m_List.at(row);
       
   128     if ( p.isNull() )
       
   129         return QVariant();
       
   130         
       
   131     switch( role )
       
   132     {       
       
   133         case Qt::DisplayRole:
       
   134             return displayRoleData(*p);
       
   135         case Qt::DecorationRole:
       
   136             return decorationRoleData(*p);
       
   137         case Qt::BackgroundRole:
       
   138             return backgroundRoleData(*p);
       
   139         case CntFlagsRole:
       
   140             return QVariant((*p).flags);
       
   141         case CntPhoneNumberRole:
       
   142             return QVariant((*p).number);
       
   143         case CntConverstaionIdRole:
       
   144             return conversationIdRoleData(row);
       
   145         default:
       
   146             return QVariant();
       
   147     }
       
   148 }
       
   149 
       
   150 /*!
       
   151  * Return the data to be used by the view for a display role.
       
   152  *
       
   153  * \param item The History item to return data about.
       
   154  *  return QVariant List of strings to be displayed on the view.
       
   155  *  The stings can also be NULL
       
   156  *  index 0 Title of the conversation item.
       
   157  *  index 1 Body text
       
   158  *  index 2 Time stamp
       
   159  */
       
   160 QVariant CntHistoryModelPrivate::displayRoleData(const HistoryItem& item) const
       
   161 {
       
   162     CNT_ENTRY
       
   163     
       
   164     QStringList list;
       
   165     HbExtendedLocale locale = m_extendedLocale;
       
   166     
       
   167     if (item.timeStamp.date() == QDateTime::currentDateTime().date())
       
   168     {
       
   169         list << item.title << item.message << locale.format(item.timeStamp.time(), r_qtn_time_usual);
       
   170     }
       
   171     else
       
   172     {
       
   173         list << item.title << item.message << locale.format(item.timeStamp.date(), r_qtn_date_usual);
       
   174     }
       
   175     
       
   176     CNT_EXIT_ARGS(list)
       
   177     
       
   178     return QVariant(list);
       
   179 }
       
   180 
       
   181 /*!
       
   182  * Return the data to be used by the view for a decoration role.
       
   183  *
       
   184  * \param item The History item to return data about.
       
   185  *  return QVariant String of the icon path.
       
   186  */
       
   187 QVariant CntHistoryModelPrivate::decorationRoleData(const HistoryItem& item) const
       
   188 {
       
   189     CNT_ENTRY
       
   190     
       
   191     // Messages
       
   192     if (item.flags & CntMessage)
       
   193         return QVariant(HbIcon(MESSAGE_ICON));
       
   194     
       
   195     // Call logs
       
   196     if (item.flags & CntCallLog) {
       
   197         if (item.flags & CntMissedCall)
       
   198             return QVariant(HbIcon(MISSED_CALL_ICON));
       
   199         if (item.flags & CntDialledCall)
       
   200             return QVariant(HbIcon(DAILED_CALL_ICON));
       
   201         if (item.flags & CntReceivedCall)
       
   202             return QVariant(HbIcon(RECEIVED_CALL_ICON));
       
   203     }
       
   204     
       
   205     return QVariant();
       
   206 }
       
   207 
       
   208 /*!
       
   209  * Return the data to be used to draw the background of list items
       
   210  *
       
   211  * \param item The History item to return data about.
       
   212  *  return QVariant HbFrameBackground of the list item.
       
   213  */
       
   214 QVariant CntHistoryModelPrivate::backgroundRoleData(const HistoryItem& item) const
       
   215 {
       
   216     if (item.flags & CntIncoming)
       
   217         return QVariant(HbFrameBackground("qtg_fr_convlist_received_normal", HbFrameDrawer::NinePieces));
       
   218     else
       
   219         return QVariant(HbFrameBackground("qtg_fr_convlist_sent_normal", HbFrameDrawer::NinePieces));
       
   220 }
       
   221 
       
   222 /*!
       
   223  * Return the conversation id of this row if it is a message
       
   224  *
       
   225  * \param item The History item to return data about.
       
   226  *  return QVariant HbFrameBackground of the list item.
       
   227  */
       
   228 QVariant CntHistoryModelPrivate::conversationIdRoleData(const int row) const
       
   229 {
       
   230     HItemPointer p = m_List.at(row);
       
   231     
       
   232     int id(-1);
       
   233     if ( p.data()->flags & CntMessage )
       
   234         id = m_msgMap.key(p, -1);
       
   235 
       
   236     if (id != -1)
       
   237         return QVariant(id);
       
   238     else
       
   239         return QVariant();
       
   240 }
       
   241 
       
   242 /*!
       
   243  * Get the number of rows (conversations) in this model.
       
   244  *
       
   245  * \param parent Optional parent index value.
       
   246  * \return Number of rows in this model.
       
   247  */
       
   248 int CntHistoryModelPrivate::rowCount(const QModelIndex& /*parent*/) const
       
   249 {
       
   250     return m_List.size();
       
   251 }
       
   252 
       
   253 /*!
       
   254  * Sort list items on the model.
       
   255  *
       
   256  * \param column Column to be sorted. It is not used.
       
   257  * \param order Order to sort the list items.
       
   258  */
       
   259 void CntHistoryModelPrivate::sort(int /*column*/, Qt::SortOrder order)
       
   260 {
       
   261     CNT_ENTRY_ARGS(order)
       
   262     
       
   263     if ( order == Qt::AscendingOrder )
       
   264         qStableSort(m_List.begin(), m_List.end(), lessThan);
       
   265     else
       
   266         qStableSort(m_List.begin(), m_List.end(), greaterThan);
       
   267     
       
   268     CNT_EXIT
       
   269 }
       
   270 
       
   271 /*!
       
   272  * Clear history from the database. If the history cached
       
   273  * is specific to one contact, only that history is cleared.
       
   274  * 
       
   275  */
       
   276 void CntHistoryModelPrivate::clearHistory()
       
   277 {
       
   278     CNT_ENTRY
       
   279     
       
   280     Q_Q(CntHistoryModel);
       
   281     
       
   282     if ( m_List.isEmpty() )
       
   283         return;
       
   284     
       
   285     // Clear all data from the history model.
       
   286     int count = rowCount();
       
   287     
       
   288     q->doBeginRemoveRows( QModelIndex(), 0, count );
       
   289     
       
   290     // Call logs
       
   291     if ( !m_isMyCard && m_logsFilter )
       
   292         m_logsFilter->clearEvents();
       
   293     else if ( m_logsModel )
       
   294         m_logsModel->clearList(LogsModel::TypeLogsClearAll);
       
   295     
       
   296     // Messages
       
   297     if (m_msgHistory)
       
   298         m_msgHistory->clearMessages( (int)m_contactId );
       
   299     
       
   300     m_List.clear();
       
   301     m_msgMap.clear();
       
   302     m_logsMap.clear();
       
   303     
       
   304     
       
   305     q->doEndRemoveRows();
       
   306     
       
   307     CNT_EXIT
       
   308 }
       
   309 
       
   310 /*!
       
   311  * Mark all the conversations in the view as seen.
       
   312  * 
       
   313  */
       
   314 void CntHistoryModelPrivate::markAllAsSeen()
       
   315 {
       
   316     CNT_ENTRY
       
   317     
       
   318     if ( m_isMarkedAsSeen )
       
   319         return;
       
   320     
       
   321     // Messages
       
   322     if (m_msgHistory->markRead( m_contactId ))
       
   323         m_isMarkedAsSeen = true;
       
   324     
       
   325     CNT_EXIT
       
   326 }
       
   327 
       
   328 /*!
       
   329  * Create the model structure and cache history data from
       
   330  * conversations and call logs databases.
       
   331  *
       
   332  */
       
   333 void CntHistoryModelPrivate::initializeModel()
       
   334 {
       
   335     CNT_ENTRY
       
   336     
       
   337     initializeLogsModel();
       
   338     initializeMsgModel();
       
   339     
       
   340     CNT_EXIT
       
   341 }
       
   342 
       
   343 void CntHistoryModelPrivate::initializeMsgModel()
       
   344 {
       
   345     CNT_ENTRY
       
   346     
       
   347     if( m_isMyCard )
       
   348         return;
       
   349     
       
   350     // Contact centric
       
   351     MsgHistory* m = new MsgHistory();
       
   352     
       
   353     m_msgHistory = m;
       
   354     
       
   355     // Connect to signals emitted by msg model
       
   356     connect(m, SIGNAL(messagesReady(QList<MsgItem>& )), this, SLOT(messagesReady(QList<MsgItem>& )));
       
   357     connect(m, SIGNAL(messageAdded(MsgItem& )), this, SLOT(messageAdded(MsgItem& )));
       
   358     connect(m, SIGNAL(messageChanged(MsgItem& )), this, SLOT(messageChanged(MsgItem& )));
       
   359     connect(m, SIGNAL(messageDeleted(MsgItem& )), this, SLOT(messageDeleted(MsgItem& )));
       
   360     
       
   361     // Subscribe to get new messages
       
   362     // received from this contact
       
   363     m->subscribe(m_contactId);
       
   364     
       
   365     // Initial fetch of all messages
       
   366     m->getMessages(m_contactId);
       
   367     
       
   368     CNT_EXIT
       
   369 }
       
   370 
       
   371 void CntHistoryModelPrivate::initializeLogsModel()
       
   372 {
       
   373     CNT_ENTRY
       
   374     
       
   375     //populate model with call events
       
   376     m_logsModel = new LogsModel(LogsModel::LogsFullModel);
       
   377     if (!m_isMyCard) {
       
   378         //do the filtering to get call events for the target contact
       
   379         m_logsFilter = new LogsCustomFilter;
       
   380         m_logsFilter->setContactId(m_contactId);
       
   381         m_logsFilter->setSourceModel(m_logsModel);
       
   382         m_AbstractLogsModel = m_logsFilter;
       
   383     } else {
       
   384         //get all call events
       
   385         m_AbstractLogsModel = m_logsModel;
       
   386     }
       
   387     
       
   388     //read first call events if any and start listening for more 
       
   389     for ( int i = 0; i < m_AbstractLogsModel->rowCount(); ++i ) {
       
   390         LogsEvent* event = qVariantValue<LogsEvent*>(
       
   391                 m_AbstractLogsModel->data(m_AbstractLogsModel->index(i, 0), LogsModel::RoleFullEvent) );
       
   392         
       
   393         if ( event ) {
       
   394             HItemPointer item = HItemPointer(new HistoryItem());
       
   395             readLogEvent(event, *item);
       
   396             m_logsMap.insert(i, item);
       
   397             m_List.append( item );
       
   398         }
       
   399     }
       
   400     
       
   401     connect(m_AbstractLogsModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), 
       
   402             this, SLOT(logsRowsInserted(const QModelIndex &, int, int)));
       
   403     connect(m_AbstractLogsModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), 
       
   404             this, SLOT(logsRowsRemoved(const QModelIndex &, int, int)));
       
   405     connect(m_AbstractLogsModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), 
       
   406                 this, SLOT(logsDataChanged(const QModelIndex &, const QModelIndex &)));
       
   407     connect(m_AbstractLogsModel, SIGNAL(modelReset()), this, SLOT(handleLogsReset()));
       
   408 
       
   409     CNT_EXIT
       
   410 }
       
   411 
       
   412 /*!
       
   413  * Read call event into a history item
       
   414  *
       
   415  * \param event Call log event
       
   416  * \param item Conversation history item
       
   417  */
       
   418 void CntHistoryModelPrivate::readLogEvent(LogsEvent* event, HistoryItem& item)
       
   419 {
       
   420     QString bodyText;
       
   421     QString title;
       
   422     
       
   423     if ( m_isMyCard ) {
       
   424         if ( event->remoteParty().length() > 0 ) {
       
   425             title = QString(event->remoteParty());
       
   426         }
       
   427         else {
       
   428             title = QString(event->number());
       
   429         }
       
   430     } else {
       
   431         if ( event->direction() == LogsEvent::DirIn ) {
       
   432             bodyText = hbTrId("txt_phob_list_received");
       
   433             item.flags |= CntReceivedCall;
       
   434         } else if ( event->direction() == LogsEvent::DirOut ) {
       
   435             bodyText = hbTrId("txt_phob_list_dialled_call");
       
   436             item.flags |= CntDialledCall;
       
   437         } else if ( event->direction() == LogsEvent::DirMissed ) {
       
   438             bodyText = hbTrId("txt_phob_list_missed_call");
       
   439             item.flags |= CntMissedCall;
       
   440         }
       
   441     }
       
   442 
       
   443     if ( event->direction() == LogsEvent::DirOut ) {
       
   444         item.flags &= ~CntIncoming;
       
   445     } else {
       
   446         item.flags |= CntIncoming;
       
   447     }
       
   448     
       
   449     item.message = bodyText;
       
   450     item.title = title;
       
   451     item.timeStamp = event->time().toLocalTime();
       
   452     item.flags |= CntCallLog;
       
   453     item.number = QString(event->number());
       
   454     
       
   455     LOG_ITEM(item);
       
   456 }
       
   457 
       
   458 /*!
       
   459  * Slot used for receiving new rows from the LogsModel.
       
   460  *
       
   461  * \param parent Optional parent index value.
       
   462  * \param first The first row item to be received from the model.
       
   463  * \param last The last row item to be received from the model.
       
   464  */
       
   465 void CntHistoryModelPrivate::logsRowsInserted(const QModelIndex& /*parent*/, int first, int last)
       
   466 {
       
   467     CNT_ENTRY_ARGS(first << last)
       
   468     
       
   469     Q_Q(CntHistoryModel);
       
   470     
       
   471     // Check if this is the first time to receive events
       
   472     if ( !m_initLogs ) {
       
   473         q->doBeginResetModel();
       
   474     }
       
   475     else {
       
   476         q->doBeginInsertRows( QModelIndex(), rowCount(), rowCount() + (last - first) );
       
   477     }
       
   478     
       
   479     QList<HItemPointer> l;
       
   480     
       
   481     for ( int i = first; i < m_AbstractLogsModel->rowCount() && i <= last; ++i ) {
       
   482         LogsEvent* event = qVariantValue<LogsEvent*>(
       
   483                 m_AbstractLogsModel->data(m_AbstractLogsModel->index(i, 0), LogsModel::RoleFullEvent) );
       
   484         
       
   485         if ( event ) {
       
   486             HItemPointer item(new HistoryItem());
       
   487             readLogEvent(event, *item);
       
   488             m_logsMap.insert(i, item);
       
   489             m_List.append( item );
       
   490         }
       
   491     }
       
   492     
       
   493     // Check if this is the first time to receive events
       
   494     // and sort the entire list.
       
   495     if ( !m_initLogs ) {
       
   496         sort();
       
   497         m_initLogs = true;
       
   498         q->doEndResetModel();
       
   499     }
       
   500     else {
       
   501         q->doEndInsertRows();
       
   502     }
       
   503     
       
   504     CNT_EXIT
       
   505 }
       
   506 
       
   507 /*!
       
   508  * Slot used for receiving new rows from the LogsModel.
       
   509  *
       
   510  * \param parent Optional parent index value.
       
   511  * \param first The first row item to be received from the model.
       
   512  * \param last The last row item to be received from the model.
       
   513  */
       
   514 void CntHistoryModelPrivate::logsRowsRemoved(const QModelIndex& /*parent*/, int first, int last)
       
   515 {
       
   516     CNT_ENTRY_ARGS(first << last)
       
   517     
       
   518     Q_Q(CntHistoryModel);
       
   519     
       
   520     QList< int > indices;
       
   521     
       
   522     for ( int i = first; i <= last; ++i ) {
       
   523         HItemPointer item = m_logsMap.value( i );
       
   524         int index = m_List.indexOf( item );
       
   525         if ( index > -1 ) {
       
   526             m_logsMap.remove( i );        
       
   527             indices.append( index );
       
   528         }
       
   529     }
       
   530     
       
   531     foreach(int i, indices) {
       
   532         m_List.removeAt( i );
       
   533     }
       
   534     
       
   535     // Remove list items in batches
       
   536     if ( !indices.isEmpty() ) {
       
   537         QList< QList<int> > batches = findIndices(indices);
       
   538         foreach( QList<int> l, batches ) {
       
   539             q->doBeginRemoveRows(QModelIndex(), l.first(), l.last());
       
   540             q->doEndRemoveRows();
       
   541         }
       
   542     }
       
   543     
       
   544     CNT_EXIT
       
   545 }
       
   546 
       
   547 /*!
       
   548  * Update events from logs model. Events are
       
   549  * received as a batch
       
   550  *
       
   551  * \param first First updated model index
       
   552  * \param last Last updated model index
       
   553  */
       
   554 void CntHistoryModelPrivate::logsDataChanged(const QModelIndex& first, const QModelIndex& last)
       
   555 {
       
   556     CNT_ENTRY_ARGS(first << last)
       
   557     
       
   558     Q_Q(CntHistoryModel);
       
   559     
       
   560     int f = first.row();
       
   561     int l = last.row();
       
   562     QList< int > indices;
       
   563     
       
   564     for ( int i = f; i < m_AbstractLogsModel->rowCount() && i <= l; ++i ) {
       
   565         
       
   566         LogsEvent* event = qVariantValue<LogsEvent*>(
       
   567                 m_AbstractLogsModel->data(m_AbstractLogsModel->index(i, 0), LogsModel::RoleFullEvent) );
       
   568         
       
   569         // Fetch item from the mapped logs model items
       
   570         HItemPointer item = m_logsMap.value( i );
       
   571         
       
   572         // Found item in the logs map
       
   573         if ( !item.isNull() && event ) {
       
   574             int index = m_List.indexOf( item );
       
   575             readLogEvent( event, *item );
       
   576             indices.append( index );
       
   577         }
       
   578     }
       
   579     
       
   580     // Emit dataChanged signal only if there were updates
       
   581     if ( !indices.isEmpty() ) {
       
   582         QList< QList<int> > batches = findIndices( indices );
       
   583         foreach( QList<int> l, batches )
       
   584             q->doDataChanged( q->index(l.first(), 0), q->index(l.last(), 0) );
       
   585     }
       
   586     
       
   587     CNT_EXIT
       
   588 }
       
   589 
       
   590 /*
       
   591  * Clear all call logs and refetches new call events after 
       
   592  * receiving a reset model signal from logs model
       
   593  */
       
   594 void CntHistoryModelPrivate::handleLogsReset()
       
   595 {
       
   596     CNT_ENTRY
       
   597     
       
   598     Q_Q(CntHistoryModel);
       
   599     
       
   600     q->doBeginResetModel();
       
   601     
       
   602     // Remove all call logs
       
   603     QList<HItemPointer> values = m_logsMap.values();
       
   604     foreach(HItemPointer p, values) {
       
   605         m_List.removeOne( p );
       
   606     }
       
   607     
       
   608     m_logsMap.clear();
       
   609     
       
   610     //read first call events if any and start listening for more 
       
   611     for ( int i = 0; i < m_AbstractLogsModel->rowCount(); ++i ) {
       
   612         LogsEvent* event = qVariantValue<LogsEvent*>(
       
   613                 m_AbstractLogsModel->data(m_AbstractLogsModel->index(i, 0), LogsModel::RoleFullEvent) );
       
   614         
       
   615         if ( event ) {
       
   616             HItemPointer item = HItemPointer(new HistoryItem());
       
   617             readLogEvent(event, *item);
       
   618             m_logsMap.insert(i, item);
       
   619             m_List.append( item );
       
   620         }
       
   621     }
       
   622     
       
   623     sort();
       
   624 
       
   625     q->doEndResetModel();
       
   626     
       
   627     CNT_EXIT
       
   628 }
       
   629 
       
   630 /*!
       
   631  * Check whether an idex is out of bound of our list
       
   632  *
       
   633  * \param index Index to be validated
       
   634  */
       
   635 
       
   636 bool CntHistoryModelPrivate::validateRowIndex( const int index) const
       
   637 {
       
   638     return( index < rowCount() && index >= 0 );
       
   639 }
       
   640 
       
   641 /*!
       
   642  * Find the sequences of indices for the given indices from the private list
       
   643  * 
       
   644  * \param indices List of indices
       
   645  * \return sequences of indices
       
   646  */
       
   647 QList< QList<int> > CntHistoryModelPrivate::findIndices( const QList< int >& indices )
       
   648 {
       
   649     CNT_ENTRY_ARGS(indices)
       
   650     
       
   651     QList< QList<int> > sequences;
       
   652     QList<int> currSequence;
       
   653     int prevIndex = indices.at(0) - 1;
       
   654     
       
   655     foreach( int currIndex, indices )
       
   656     {
       
   657         if ( currIndex >= 0 )
       
   658         {
       
   659             if ( prevIndex+1 != currIndex && !currSequence.isEmpty() )
       
   660             {
       
   661                 sequences.append( currSequence );
       
   662                 currSequence.clear();
       
   663             } 
       
   664             currSequence.append( currIndex );
       
   665             prevIndex = currIndex;
       
   666         }
       
   667     }
       
   668     
       
   669     if ( !currSequence.isEmpty() )
       
   670     {
       
   671         // Add last sequence if such exist
       
   672         sequences.append( currSequence );
       
   673     }
       
   674     
       
   675     CNT_EXIT_ARGS(sequences)
       
   676     
       
   677     return sequences;
       
   678 }
       
   679 
       
   680 /*!
       
   681  * Read message event into a history item
       
   682  *
       
   683  * \param event Message event
       
   684  * \param item Conversation history item
       
   685  */
       
   686 void CntHistoryModelPrivate::readMsgEvent(MsgItem& event, HistoryItem& item)
       
   687 {
       
   688     CNT_ENTRY
       
   689     
       
   690     // Msg direction
       
   691     if ( event.direction() == MsgItem::MsgDirectionIncoming ) {
       
   692         item.flags |= CntIncoming;
       
   693         // Read status
       
   694         if ( event.isAttributeSet(MsgItem::MsgAttributeUnread) )
       
   695             item.flags |= CntUnseen;
       
   696         else
       
   697             item.flags &= ~CntUnseen;
       
   698     } else if ( event.direction() == MsgItem::MsgDirectionOutgoing )
       
   699         item.flags &= ~CntIncoming;
       
   700     
       
   701     // Attachment
       
   702     if (event.isAttributeSet(MsgItem::MsgAttributeAttachment))
       
   703         item.flags |= CntAttachment;
       
   704     
       
   705     item.flags |= CntMessage;
       
   706     item.number = event.phoneNumber();
       
   707     
       
   708     if (event.body().isEmpty())
       
   709     {
       
   710         item.message = " ";
       
   711     }
       
   712     else
       
   713     {
       
   714         item.message = event.body();
       
   715     }
       
   716     
       
   717     item.timeStamp = event.timeStamp().toLocalTime();
       
   718     
       
   719     LOG_ITEM(item);
       
   720     
       
   721     CNT_EXIT
       
   722 }
       
   723 
       
   724 /*!
       
   725  * Slot to receive new messages for the first time
       
   726  * from the messages model
       
   727  *
       
   728  * \param event Message event
       
   729  * \param item Conversation history item
       
   730  */
       
   731 void CntHistoryModelPrivate::messagesReady(QList<MsgItem>& msgs)
       
   732 {
       
   733     CNT_ENTRY
       
   734     
       
   735     Q_Q(CntHistoryModel);
       
   736     
       
   737     q->doBeginResetModel();
       
   738     
       
   739     foreach( MsgItem m, msgs ) {
       
   740         // Create a new hst item
       
   741         HItemPointer item(new HistoryItem());
       
   742         
       
   743         // Parse the MsgItem and add data into hst item
       
   744         readMsgEvent( m, *item );
       
   745         
       
   746         // Map the hist item to a MsgItem in the msgModel
       
   747         m_msgMap.insert( m.id(), item );
       
   748         
       
   749         // Append the hst item to our list
       
   750         m_List.append( item );
       
   751     }
       
   752     
       
   753     sort();
       
   754     
       
   755     q->doEndResetModel();
       
   756     
       
   757     CNT_EXIT
       
   758 }
       
   759 
       
   760 /*!
       
   761  * Slot to receive new messages from the messages model
       
   762  *
       
   763  * \param event Message event
       
   764  * \param item Conversation history item
       
   765  */
       
   766 void CntHistoryModelPrivate::messageAdded(MsgItem& msg)
       
   767 {
       
   768     CNT_ENTRY
       
   769     
       
   770     Q_Q(CntHistoryModel);
       
   771     
       
   772     q->doBeginInsertRows( QModelIndex(), rowCount(), rowCount() );
       
   773     
       
   774     // Create a new hst item
       
   775     HItemPointer item(new HistoryItem());
       
   776     
       
   777     // Parse the MsgItem and add data into hst item
       
   778     readMsgEvent( msg, *item );
       
   779     
       
   780     // Map the hist item to a MsgItem in the msgModel
       
   781     m_msgMap.insert( msg.id(), item );
       
   782     
       
   783     // Append the hst item to our list
       
   784     m_List.append( item );
       
   785     
       
   786     q->doEndInsertRows();
       
   787     
       
   788     CNT_EXIT
       
   789 }
       
   790 
       
   791 /*!
       
   792  * Slot to update a message from the messages model
       
   793  *
       
   794  * \param event Message event
       
   795  * \param item Conversation history item
       
   796  */
       
   797 void CntHistoryModelPrivate::messageChanged(MsgItem& msg)
       
   798 {
       
   799     CNT_ENTRY
       
   800     
       
   801     Q_Q(CntHistoryModel);
       
   802     
       
   803     // Fetch the hst item that maps to this MsgItem
       
   804     HItemPointer p = m_msgMap.value( msg.id() );
       
   805     
       
   806     // No item was found.
       
   807     if ( p.isNull() )
       
   808         return;
       
   809 
       
   810     // Parse the MsgItem and add data into hst item
       
   811     readMsgEvent(msg, *p);
       
   812     
       
   813     // Get the index of the the hst item in the list
       
   814     int pIndex = m_List.indexOf( p );
       
   815     
       
   816     q->doDataChanged(q->index(pIndex, 0), q->index(pIndex, 0));
       
   817     
       
   818     CNT_EXIT
       
   819 }
       
   820 
       
   821 /*!
       
   822  * Slot to delete a message from the messages model
       
   823  *
       
   824  * \param event Message event
       
   825  * \param item Conversation history item
       
   826  */
       
   827 void CntHistoryModelPrivate::messageDeleted(MsgItem& msg)
       
   828 {
       
   829     CNT_ENTRY
       
   830     
       
   831     Q_Q(CntHistoryModel);
       
   832     
       
   833     // Fetch the hst item that maps to this MsgItem
       
   834     HItemPointer p = m_msgMap.value( msg.id() );
       
   835     
       
   836     // No item was found.
       
   837     if ( p.isNull() )
       
   838         return;
       
   839     
       
   840     // Remove the item in stored containers
       
   841     m_msgMap.remove( msg.id() );
       
   842     int index = m_List.indexOf( p );
       
   843     if ( index > -1 ) {
       
   844         q->doBeginRemoveRows(QModelIndex(), index, index);
       
   845         m_List.removeAt( index );
       
   846         q->doEndRemoveRows();
       
   847     }
       
   848     
       
   849     CNT_EXIT
       
   850 }