--- a/phonebookui/cnthistorymodel/src/cnthistorymodel.cpp Wed Jun 23 18:02:44 2010 +0300
+++ b/phonebookui/cnthistorymodel/src/cnthistorymodel.cpp Tue Jul 06 14:05:47 2010 +0300
@@ -15,32 +15,9 @@
*
*/
-#include <QStringList>
-#include <QtAlgorithms>
-#include <hbglobal.h>
-#include <hbicon.h>
-#include <hbframebackground.h>
-
#include "cnthistorymodel_p.h"
#include "cnthistorymodel.h"
-
-// Unnamed namespace for helper functions
-namespace
-{
- bool greaterThan(const HItemPointer& t1, const HItemPointer& t2)
- {
- return ((*t1).timeStamp > (*t2).timeStamp);
- }
-
- bool lessThan(const HItemPointer& t1, const HItemPointer& t2)
- {
- return ((*t1).timeStamp < (*t2).timeStamp);
- }
-}
-
-Q_DECLARE_METATYPE(LogsEvent *)
-
/*!
* Construct a new CntHistoryModel object to communicate
* with the conversations and logs databases.
@@ -52,16 +29,17 @@
CntHistoryModel::CntHistoryModel(QContactLocalId contactId,
QContactManager* manager,
QObject *parent)
- : QAbstractListModel(parent)
+ : QAbstractListModel(parent),
+ d_ptr(new CntHistoryModelPrivate(contactId, manager))
{
- d = new CntHistoryModelData(contactId, manager);
-
- // Create the model structure and cache history data from the databases
- initializeModel();
+ Q_D(CntHistoryModel);
+ d->q_ptr = this;
}
CntHistoryModel::~CntHistoryModel()
{
+ Q_D(CntHistoryModel);
+ delete d;
}
/*!
@@ -74,97 +52,8 @@
*/
QVariant CntHistoryModel::data(const QModelIndex& index, int role) const
{
- // Invalid index
- int row = index.row();
-
- if ( !validateRowIndex(row) )
- return QVariant();
-
- HItemPointer p = d->m_List.at(row);
- if ( p.isNull() )
- return QVariant();
-
- switch( role )
- {
- case Qt::DisplayRole:
- return displayRoleData(*p);
- case Qt::DecorationRole:
- return decorationRoleData(*p);
- case Qt::BackgroundRole:
- return backgroundRoleData(*p);
- case FlagsRole:
- return QVariant((*p).flags);
- case PhoneNumberRole:
- return QVariant((*p).number);
- default:
- return QVariant();
- }
-}
-
-/*!
- * Return the data to be used by the view for a display role.
- *
- * \param item The History item to return data about.
- * return QVariant List of strings to be displayed on the view.
- * The stings can also be NULL
- * index 0 Title of the conversation item.
- * index 1 Body text
- * index 2 Time stamp
- */
-QVariant CntHistoryModel::displayRoleData(const HistoryItem& item) const
-{
- QStringList list;
- HbExtendedLocale locale = d->m_extendedLocale;
-
- if (item.timeStamp.date() == QDateTime::currentDateTime().date())
- {
- list << item.title << item.message << locale.format(item.timeStamp.time(), r_qtn_time_usual);
- }
- else
- {
- list << item.title << item.message << locale.format(item.timeStamp.date(), r_qtn_date_usual);
- }
-
- return QVariant(list);
-}
-
-/*!
- * Return the data to be used by the view for a decoration role.
- *
- * \param item The History item to return data about.
- * return QVariant String of the icon path.
- */
-QVariant CntHistoryModel::decorationRoleData(const HistoryItem& item) const
-{
- // Messages
- if (item.flags & Message)
- return QVariant(HbIcon(MESSAGE_ICON));
-
- // Call logs
- if (item.flags & CallLog) {
- if (item.flags & MissedCall)
- return QVariant(HbIcon(MISSED_CALL_ICON));
- if (item.flags & DialledCall)
- return QVariant(HbIcon(DAILED_CALL_ICON));
- if (item.flags & ReceivedCall)
- return QVariant(HbIcon(RECEIVED_CALL_ICON));
- }
-
- return QVariant();
-}
-
-/*!
- * Return the data to be used to draw the background of list items
- *
- * \param item The History item to return data about.
- * return QVariant HbFrameBackground of the list item.
- */
-QVariant CntHistoryModel::backgroundRoleData(const HistoryItem& item) const
-{
- if (item.flags & Incoming)
- return QVariant(HbFrameBackground("qtg_fr_convlist_received_normal", HbFrameDrawer::NinePieces));
- else
- return QVariant(HbFrameBackground("qtg_fr_convlist_sent_normal", HbFrameDrawer::NinePieces));
+ Q_D(const CntHistoryModel);
+ return d->data(index, role);
}
/*!
@@ -173,9 +62,10 @@
* \param parent Optional parent index value.
* \return Number of rows in this model.
*/
-int CntHistoryModel::rowCount(const QModelIndex& /*parent*/) const
+int CntHistoryModel::rowCount(const QModelIndex& parent) const
{
- return d->m_List.size();
+ Q_D(const CntHistoryModel);
+ return d->rowCount(parent);
}
/*!
@@ -184,12 +74,10 @@
* \param column Column to be sorted. It is not used.
* \param order Order to sort the list items.
*/
-void CntHistoryModel::sort(int /*column*/, Qt::SortOrder order)
+void CntHistoryModel::sort(int column, Qt::SortOrder order)
{
- if ( order == Qt::AscendingOrder )
- qStableSort(d->m_List.begin(), d->m_List.end(), lessThan);
- else
- qStableSort(d->m_List.begin(), d->m_List.end(), greaterThan);
+ Q_D(CntHistoryModel);
+ d->sort(column, order);
}
/*!
@@ -199,26 +87,8 @@
*/
void CntHistoryModel::clearHistory()
{
- if ( d->m_List.isEmpty() )
- return;
-
- // Call logs
- if ( !d->m_isMyCard && d->m_logsFilter )
- d->m_logsFilter->clearEvents();
- else if ( d->m_logsModel )
- d->m_logsModel->clearList(LogsModel::TypeLogsClearAll);
-
- // Messages
- if (d->m_msgHistory)
- d->m_msgHistory->clearMessages( (int)d->m_contactId );
-
- // Clear all data from the history model.
- int count = rowCount();
- d->m_List.clear();
- d->m_msgMap.clear();
- d->m_logsMap.clear();
- beginRemoveRows( QModelIndex(), 0, count );
- endRemoveRows();
+ Q_D(CntHistoryModel);
+ d->clearHistory();
}
/*!
@@ -227,12 +97,8 @@
*/
void CntHistoryModel::markAllAsSeen()
{
- if ( d->m_isMarkedAsSeen )
- return;
-
- // Messages
- if (d->m_msgHistory->markRead( d->m_contactId ))
- d->m_isMarkedAsSeen = true;
+ Q_D(CntHistoryModel);
+ d->markAllAsSeen();
}
/*!
@@ -241,454 +107,33 @@
*/
void CntHistoryModel::sortAndRefresh(Qt::SortOrder order)
{
- sort(0, order);
+ Q_D(CntHistoryModel);
+ d->sort(order);
beginInsertRows(QModelIndex(), 0, rowCount());
endInsertRows();
}
-/*!
- * Create the model structure and cache history data from
- * conversations and call logs databases.
- *
- */
-void CntHistoryModel::initializeModel()
-{
- initializeLogsModel();
- initializeMsgModel();
-}
-
-void CntHistoryModel::initializeMsgModel()
+void CntHistoryModel::doBeginInsertRows(const QModelIndex &parent, int first, int last)
{
- if( d->m_isMyCard )
- return;
-
- // Contact centric
- MsgHistory* m = new MsgHistory();
-
- d->m_msgHistory = m;
-
- // Connect to signals emitted by msg model
- connect(m, SIGNAL(messagesReady(QList<MsgItem>& )), this, SLOT(messagesReady(QList<MsgItem>& )));
- connect(m, SIGNAL(messageAdded(MsgItem& )), this, SLOT(messageAdded(MsgItem& )));
- connect(m, SIGNAL(messageChanged(MsgItem& )), this, SLOT(messageChanged(MsgItem& )));
- connect(m, SIGNAL(messageDeleted(MsgItem& )), this, SLOT(messageDeleted(MsgItem& )));
-
- // Subscribe to get new messages
- // received from this contact
- m->subscribe(d->m_contactId);
-
- // Initial fetch of all messages
- m->getMessages(d->m_contactId);
+ beginInsertRows(parent, first, last);
}
-void CntHistoryModel::initializeLogsModel()
+void CntHistoryModel::doEndRemoveRows()
{
- //populate model with call events
- d->m_logsModel = new LogsModel(LogsModel::LogsFullModel);
- if (!d->m_isMyCard) {
- //do the filtering to get call events for the target contact
- d->m_logsFilter = new LogsCustomFilter;
- d->m_logsFilter->setContactId(d->m_contactId);
- d->m_logsFilter->setSourceModel(d->m_logsModel);
- d->m_AbstractLogsModel = d->m_logsFilter;
-
- connect(d->m_logsFilter, SIGNAL(clearingCompleted(int)),
- this, SLOT(clearedCallLogs(int)));
- } else {
- //get all call events
- d->m_AbstractLogsModel = d->m_logsModel;
-
- connect(d->m_logsModel, SIGNAL(clearingCompleted(int)),
- this, SLOT(clearedCallLogs(int)));
- }
-
- //read first call events if any and start listening for more
- for ( int i = 0; i < d->m_AbstractLogsModel->rowCount(); ++i ) {
- LogsEvent* event = qVariantValue<LogsEvent*>(
- d->m_AbstractLogsModel->data(d->m_AbstractLogsModel->index(i, 0), LogsModel::RoleFullEvent) );
-
- if ( event ) {
- HItemPointer item = HItemPointer(new HistoryItem());
- readLogEvent(event, *item);
- d->m_logsMap.insert(i, item);
- d->m_List.append( item );
- }
- }
-
- connect(d->m_AbstractLogsModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
- this, SLOT(logsRowsInserted(const QModelIndex &, int, int)));
- connect(d->m_AbstractLogsModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
- this, SLOT(logsRowsRemoved(const QModelIndex &, int, int)));
- connect(d->m_AbstractLogsModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
- this, SLOT(logsDataChanged(const QModelIndex &, const QModelIndex &)));
- connect(d->m_AbstractLogsModel, SIGNAL(modelReset()), this, SLOT(handleLogsReset()));
-
+ endRemoveRows();
}
-/*!
- * Read call event into a history item
- *
- * \param event Call log event
- * \param item Conversation history item
- */
-void CntHistoryModel::readLogEvent(LogsEvent* event, HistoryItem& item)
-{
- QString bodyText;
- QString title;
-
- if ( d->m_isMyCard ) {
- if ( event->remoteParty().length() > 0 ) {
- title = QString(event->remoteParty());
- }
- else {
- title = QString(event->number());
- }
- } else {
- if ( event->direction() == LogsEvent::DirIn ) {
- bodyText = hbTrId("txt_phob_list_received");
- item.flags |= ReceivedCall;
- } else if ( event->direction() == LogsEvent::DirOut ) {
- bodyText = hbTrId("txt_phob_list_dialled_call");
- item.flags |= DialledCall;
- } else if ( event->direction() == LogsEvent::DirMissed ) {
- bodyText = hbTrId("txt_phob_list_missed_call");
- item.flags |= MissedCall;
- }
- }
-
- if ( event->direction() == LogsEvent::DirOut )
- item.flags |= Outgoing;
- else
- item.flags |= Incoming;
-
- item.message = bodyText;
- item.title = title;
- item.timeStamp = event->time().toLocalTime();
- item.flags |= CallLog;
- item.number = QString(event->number());
+void CntHistoryModel::doBeginRemoveRows(const QModelIndex &parent, int first, int last)
+{
+ beginRemoveRows(parent, first, last);
}
-/*!
- * Slot used for receiving new rows from the LogsModel.
- *
- * \param parent Optional parent index value.
- * \param first The first row item to be received from the model.
- * \param last The last row item to be received from the model.
- */
-void CntHistoryModel::logsRowsInserted(const QModelIndex& /*parent*/, int first, int last)
+void CntHistoryModel::doEndInsertRows()
{
- int oldRowCount = rowCount();
- QList<HItemPointer> l;
-
- for ( int i = first; i < d->m_AbstractLogsModel->rowCount() && i <= last; ++i ) {
- LogsEvent* event = qVariantValue<LogsEvent*>(
- d->m_AbstractLogsModel->data(d->m_AbstractLogsModel->index(i, 0), LogsModel::RoleFullEvent) );
-
- if ( event ) {
- HItemPointer item(new HistoryItem());
- readLogEvent(event, *item);
- d->m_logsMap.insert(i, item);
- d->m_List.append( item );
- }
- }
-
- // Check if this is the first time to receive events
- // and sort the entire list.
- if ( !d->m_initLogs ) {
- sort();
- oldRowCount = 0;
- d->m_initLogs = true;
- }
-
- beginInsertRows(QModelIndex(), oldRowCount, rowCount());
endInsertRows();
}
-/*!
- * Slot used for receiving new rows from the LogsModel.
- *
- * \param parent Optional parent index value.
- * \param first The first row item to be received from the model.
- * \param last The last row item to be received from the model.
- */
-void CntHistoryModel::logsRowsRemoved(const QModelIndex& /*parent*/, int first, int last)
-{
- QList< int > indices;
-
- for ( int i = first; i <= last; ++i ) {
- HItemPointer item = d->m_logsMap.value( i );
- int index = d->m_List.indexOf( item );
- if ( index > -1 ) {
- d->m_logsMap.remove( i );
- indices.append( index );
- }
- }
-
- foreach(int i, indices) {
- d->m_List.removeAt( i );
- }
-
- // Remove list items in batches
- if ( !indices.isEmpty() ) {
- QList< QList<int> > batches = findIndices(indices);
- foreach( QList<int> l, batches ) {
- beginRemoveRows(QModelIndex(), l.first(), l.last());
- endRemoveRows();
- }
- }
-}
-
-/*!
- * Update events from logs model. Events are
- * received as a batch
- *
- * \param first First updated model index
- * \param last Last updated model index
- */
-void CntHistoryModel::logsDataChanged(const QModelIndex& first, const QModelIndex& last)
-{
- int f = first.row();
- int l = last.row();
- QList< int > indices;
-
- for ( int i = f; i < d->m_AbstractLogsModel->rowCount() && i <= l; ++i ) {
-
- LogsEvent* event = qVariantValue<LogsEvent*>(
- d->m_AbstractLogsModel->data(d->m_AbstractLogsModel->index(i, 0), LogsModel::RoleFullEvent) );
-
- // Fetch item from the mapped logs model items
- HItemPointer item = d->m_logsMap.value( i );
-
- // Found item in the logs map
- if ( !item.isNull() ) {
- int index = d->m_List.indexOf( item );
- readLogEvent( event, *item );
- indices.append( index );
- }
- }
-
- // Emit dataChanged signal only if there were updates
- if ( !indices.isEmpty() ) {
- QList< QList<int> > batches = findIndices( indices );
- foreach( QList<int> l, batches )
- emit dataChanged( index(l.first(), 0), index(l.last(), 0) );
- }
-}
-
-/*
- * Clear all call logs after receiving a reset model
- * signal from logs model
- */
-void CntHistoryModel::handleLogsReset()
-{
- // Remove all call logs
- QList<HItemPointer> values = d->m_logsMap.values();
- foreach(HItemPointer p, values) {
- d->m_List.removeOne( p );
- }
-
- d->m_logsMap.clear();
-
- //read first call events if any and start listening for more
- for ( int i = 0; i < d->m_AbstractLogsModel->rowCount(); ++i ) {
- LogsEvent* event = qVariantValue<LogsEvent*>(
- d->m_AbstractLogsModel->data(d->m_AbstractLogsModel->index(i, 0), LogsModel::RoleFullEvent) );
-
- if ( event ) {
- HItemPointer item = HItemPointer(new HistoryItem());
- readLogEvent(event, *item);
- d->m_logsMap.insert(i, item);
- d->m_List.append( item );
- }
- }
-
- sortAndRefresh();
-}
-
-/*!
- * Check whether an idex is out of bound of our list
- *
- * \param index Index to be validated
- */
-
-bool CntHistoryModel::validateRowIndex( const int index) const
-{
- return( index < rowCount() && index >= 0 );
-}
-
-/*!
- * Find the sequences of indices for the given indices from the private list
- *
- * \param indices List of indices
- * \return sequences of indices
- */
-QList< QList<int> > CntHistoryModel::findIndices( const QList< int >& indices )
+void CntHistoryModel::doDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
- QList< QList<int> > sequences;
- QList<int> currSequence;
- int prevIndex = indices.at(0) - 1;
-
- foreach( int currIndex, indices )
- {
- if ( currIndex >= 0 )
- {
- if ( prevIndex+1 != currIndex && !currSequence.isEmpty() )
- {
- sequences.append( currSequence );
- currSequence.clear();
- }
- currSequence.append( currIndex );
- prevIndex = currIndex;
- }
- }
-
- if ( !currSequence.isEmpty() )
- {
- // Add last sequence if such exist
- sequences.append( currSequence );
- }
-
- return sequences;
-}
-
-/*!
- * Read message event into a history item
- *
- * \param event Message event
- * \param item Conversation history item
- */
-void CntHistoryModel::readMsgEvent(MsgItem& event, HistoryItem& item)
-{
- // Msg direction
- if ( event.direction() == MsgItem::MsgDirectionIncoming ) {
- item.flags |= Incoming;
- // Read status
- if ( event.isAttributeSet(MsgItem::MsgAttributeUnread) )
- item.flags |= Unseen;
- else
- item.flags &= ~Unseen;
- } else if ( event.direction() == MsgItem::MsgDirectionOutgoing )
- item.flags |= Outgoing;
-
- // Attachment
- if (event.isAttributeSet(MsgItem::MsgAttributeAttachment))
- item.flags |= Attachment;
-
- item.flags |= Message;
- item.number = event.phoneNumber();
-
- if (event.body().isEmpty())
- {
- item.message = " ";
- }
- else
- {
- item.message = event.body();
- }
-
- item.timeStamp = event.timeStamp().toLocalTime();
+ emit dataChanged(topLeft, bottomRight);
}
-
-/*!
- * Slot to receive new messages for the first time
- * from the messages model
- *
- * \param event Message event
- * \param item Conversation history item
- */
-void CntHistoryModel::messagesReady(QList<MsgItem>& msgs)
-{
- foreach( MsgItem m, msgs ) {
- // Create a new hst item
- HItemPointer item(new HistoryItem());
-
- // Parse the MsgItem and add data into hst item
- readMsgEvent( m, *item );
-
- // Map the hist item to a MsgItem in the msgModel
- d->m_msgMap.insert( m.id(), item );
-
- // Append the hst item to our list
- d->m_List.append( item );
- }
-
- sort();
-
- beginInsertRows(QModelIndex(), 0, rowCount());
- endInsertRows();
-}
-
-/*!
- * Slot to receive new messages from the messages model
- *
- * \param event Message event
- * \param item Conversation history item
- */
-void CntHistoryModel::messageAdded(MsgItem& msg)
-{
- int oldRowCount = rowCount();
-
- // Create a new hst item
- HItemPointer item(new HistoryItem());
-
- // Parse the MsgItem and add data into hst item
- readMsgEvent( msg, *item );
-
- // Map the hist item to a MsgItem in the msgModel
- d->m_msgMap.insert( msg.id(), item );
-
- // Append the hst item to our list
- d->m_List.append( item );
-
- beginInsertRows( QModelIndex(), oldRowCount, rowCount() );
- endInsertRows();
-}
-
-/*!
- * Slot to update a message from the messages model
- *
- * \param event Message event
- * \param item Conversation history item
- */
-void CntHistoryModel::messageChanged(MsgItem& msg)
-{
- // Fetch the hst item that maps to this MsgItem
- HItemPointer p = d->m_msgMap.value( msg.id() );
-
- // No item was found.
- if ( p.isNull() )
- return;
-
- // Parse the MsgItem and add data into hst item
- readMsgEvent(msg, *p);
-
- // Get the index of the the hst item in the list
- int pIndex = d->m_List.indexOf( p );
-
- emit dataChanged(index(pIndex, 0), index(pIndex, 0));
-}
-
-/*!
- * Slot to delete a message from the messages model
- *
- * \param event Message event
- * \param item Conversation history item
- */
-void CntHistoryModel::messageDeleted(MsgItem& msg)
-{
- // Fetch the hst item that maps to this MsgItem
- HItemPointer p = d->m_msgMap.value( msg.id() );
-
- // No item was found.
- if ( p.isNull() )
- return;
-
- // Remove the item in stored containers
- d->m_msgMap.remove( msg.id() );
- int index = d->m_List.indexOf( p );
- if ( index > -1 ) {
- d->m_List.removeAt( index );
- beginRemoveRows(QModelIndex(), index, index);
- endRemoveRows();
- }
-}