--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingapp/msgui/appengine/src/conversationsmodel.cpp Tue Aug 31 15:11:31 2010 +0300
@@ -0,0 +1,1076 @@
+/*
+ * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of "Eclipse Public License v1.0"
+ * which accompanies this distribution, and is available
+ * at the URL "http://www.eclipse.org/legal/epl-v10.html".
+ *
+ * Initial Contributors:
+ * Nokia Corporation - initial contribution.
+ *
+ * Contributors:
+ *
+ * Description:
+ *
+ */
+
+#include "conversationsmodel.h"
+#include "conversationsenginedefines.h"
+#include "conversationmsgstorehandler.h"
+#include "convergedmessage.h"
+#include <xqconversions.h>
+#include "conversationsengineutility.h"
+#include "unidatamodelloader.h"
+#include "unidatamodelplugininterface.h"
+#include "ringbc.h"
+#include "msgcontacthandler.h"
+#include "mmsconformancecheck.h"
+#include <ccsconversationentry.h>
+#include <fileprotectionresolver.h>
+
+#include "debugtraces.h"
+
+#include <QFile>
+#include <QFileInfo>
+#include <s32mem.h>
+#include <s32strm.h>
+#include <fbs.h>
+#include <ccsdefs.h>
+
+//CONSTANTS
+_LIT(KDbFileName, "c:[2002A542]conversations.db");
+
+// preview sql query
+_LIT(KSelectConvMsgsStmt, "SELECT message_id, msg_processingstate, subject, body_text, preview_path, msg_property, preview_icon FROM conversation_messages WHERE message_id=:message_id ");
+
+//selecet preview-icon query
+_LIT(KSelectPreviewIconStmt,"SELECT message_id, preview_icon FROM conversation_messages WHERE message_id = :message_id ");
+
+//selecet vcard-path query
+_LIT(KSelectVCardStmt,"SELECT message_id, msg_processingstate, preview_path FROM conversation_messages WHERE message_id = :message_id ");
+
+// preview-cache max cost (items)
+const int CACHE_COST = 50;
+//Preview thumbnail size
+const int KWidth = 9.5 * 6.7;
+const int KHeight = 9.5 * 6.7;
+//---------------------------------------------------------------
+// ConversationsModel::ConversationsModel
+// Constructor
+//---------------------------------------------------------------
+ConversationsModel::ConversationsModel(ConversationMsgStoreHandler* msgStoreHandler,
+ QObject* parent) :
+ QStandardItemModel(parent), mMsgStoreHandler(msgStoreHandler), iSqlDbOpen(EFalse)
+{
+ //Open SQL DB
+ if (KErrNone == iSqlDb.Open(KDbFileName))
+ {
+ iSqlDbOpen = ETrue;
+ }
+ previewIconCache.setMaxCost(CACHE_COST);
+
+ int err = connect(this, SIGNAL(retrievePreviewIcon(int, QString&)), this,
+ SLOT(updatePreviewIcon(int, QString&)));
+ QCRITICAL_WRITE_FORMAT("Error from connect()", err)
+ iDataModelPluginLoader = new UniDataModelLoader;
+ iMmsDataPlugin = iDataModelPluginLoader->getDataModelPlugin(ConvergedMessage::Mms);
+ iBioMsgPlugin = iDataModelPluginLoader->getDataModelPlugin(ConvergedMessage::BioMsg);
+}
+
+//---------------------------------------------------------------
+// ConversationsModel::~ConversationsModel
+// Destructor
+//---------------------------------------------------------------
+ConversationsModel::~ConversationsModel()
+{
+ //Close SQL-DB
+ iSqlDb.Close();
+
+ //clear preview-cache
+ previewIconCache.clear();
+
+ if (iDataModelPluginLoader) {
+ delete iDataModelPluginLoader;
+ iDataModelPluginLoader = NULL;
+ }
+}
+
+//---------------------------------------------------------------
+// ConversationsModel::data
+// @see header
+//---------------------------------------------------------------
+QVariant ConversationsModel::data(const QModelIndex & index, int role) const
+{
+ QVariant value;
+ QStandardItem* item = itemFromIndex(index);
+ switch (role) {
+ case ConversationId:
+ {
+ value = item->data(ConversationId);
+ break;
+ }
+ case UnReadStatus:
+ {
+ value = item->data(UnReadStatus);
+ break;
+ }
+ case ContactId:
+ {
+ value = item->data(ContactId);
+ break;
+ }
+ case TimeStamp:
+ {
+ value = item->data(TimeStamp);
+ break;
+ }
+ case ConvergedMsgId:
+ {
+ value = item->data(ConvergedMsgId);
+ break;
+ }
+ case MessageProperty:
+ {
+ value = item->data(MessageProperty);
+ break;
+ }
+ case MessageType:
+ {
+ value = item->data(MessageType);
+ break;
+ }
+ case MessageSubType:
+ {
+ value = item->data(MessageSubType);
+ break;
+ }
+ case Subject:
+ {
+ value = item->data(Subject);
+ break;
+ }
+ case BodyText:
+ {
+ value = item->data(BodyText);
+ break;
+ }
+ case ConversationAddress:
+ {
+ value = item->data(ConversationAddress);
+ break;
+ }
+ case Direction:
+ {
+ value = item->data(Direction);
+ break;
+ }
+ case SendingState:
+ {
+ value = item->data(SendingState);
+ break;
+ }
+ case PreviewIcon:
+ {
+ QString filepath(item->data(Attachments).toString());
+ int msgId = item->data(ConvergedMsgId).toInt();
+ HbIcon *icon = getPreviewIconItem(msgId, filepath);
+ return *icon;
+ }
+ case MessagePriority:
+ {
+ value = item->data(MessagePriority);
+ break;
+ }
+ case Attachments:
+ {
+ value = item->data(Attachments);
+ break;
+ }
+ case MessageLocation:
+ {
+ value = item->data(MessageLocation);
+ break;
+ }
+ case MessageStore:
+ {
+ value = item->data(MessageStore);
+ break;
+ }
+ case ConversationAlias:
+ {
+ value = item->data(ConversationAlias);
+ break;
+ }
+ case UnreadCount:
+ {
+ value = item->data(UnreadCount);
+ break;
+ }
+ case DisplayName: // Fall through start
+ value = item->data(DisplayName);
+ break;
+ case Avatar: // Fall througn end
+ value = item->data(Avatar);
+ break;
+ case NotificationStatus:
+ value = item->data(NotificationStatus);
+ break;
+ default:
+ {
+ //No matching role found, set invalid variant
+ value = QVariant();
+ break;
+ }
+ }
+ return value;
+}
+
+//---------------------------------------------------------------
+// ConversationsModel::addRow
+// @see header
+//---------------------------------------------------------------
+void ConversationsModel::addRow(const CCsConversationEntry& entry, bool dynamicUpdate)
+{
+ int msgId = entry.EntryId();
+ //match, if found update else add item
+ QModelIndexList indexList = this->match(index(0, 0), ConvergedMsgId, msgId, -1,
+ Qt::MatchExactly);
+
+ // if not found, add new item
+ if (indexList.count() == 0) {
+ QStandardItem* item = new QStandardItem();
+ populateItem(*item, entry);
+ if (!dynamicUpdate) {
+ insertRow(0, item);
+ }
+ else {
+ int i;
+ for (i = rowCount() - 1; i >= 0; --i) {
+ QStandardItem* modelItem = this->item(i, 0);
+ if (modelItem->data(ConvergedMsgId).toInt() < item->data(ConvergedMsgId).toInt()) {
+ if (i == rowCount() - 1) {
+ appendRow(item);
+ }
+ else {
+ insertRow(i + 1, item);
+ }
+ return;
+ }
+ }
+ if (i == 0) {
+ insertRow(0, item);
+ }
+ }
+ }
+ else {
+ // Update an existing item
+ QModelIndex index = indexList[0];
+ QStandardItem* item = this->item(index.row(), 0);
+ populateItem(*item, entry);
+ }
+}
+
+//---------------------------------------------------------------
+// ConversationsModel::deleteRow
+// @see header
+//---------------------------------------------------------------
+void ConversationsModel::deleteRow(int msgId)
+{
+ //match, if found remove item
+ QModelIndexList indexList =
+ this->match(index(0, 0), ConvergedMsgId, msgId, 1, Qt::MatchExactly);
+
+ if (indexList.count() == 1) {
+ QModelIndex index = indexList[0];
+ this->removeRow(index.row());
+ }
+}
+
+//---------------------------------------------------------------
+// ConversationsModel::populateItem
+// @see header
+//---------------------------------------------------------------
+void ConversationsModel::populateItem(QStandardItem& item, const CCsConversationEntry& entry)
+{
+ QCRITICAL_WRITE("ConversationsModel::populateItem start.");
+
+ int msgId = entry.EntryId();
+ // id
+ item.setData(msgId, ConvergedMsgId);
+
+ // description
+ HBufC* description = entry.Description();
+ QString subject("");
+ if (description && description->Length()) {
+ subject = (XQConversions::s60DescToQString(*description));
+ }
+
+ // time stamp
+ TTime unixEpoch(KUnixEpoch);
+ TTimeIntervalSeconds seconds;
+ TTime timeStamp(entry.TimeStamp());
+ timeStamp.SecondsFrom(unixEpoch, seconds);
+ item.setData(seconds.Int(), TimeStamp);
+
+ //contact details
+ HBufC* contact = entry.Contact();
+ if (contact && contact->Length()) {
+ item.setData(XQConversions::s60DescToQString(*contact), ConversationAddress);
+ }
+
+ // message type.
+ int msgType = ConversationsEngineUtility::messageType(entry.GetType());
+ item.setData(msgType, MessageType);
+
+ //message sub-type
+ item.setData(ConversationsEngineUtility::messageSubType(entry.GetType()), MessageSubType);
+
+ // unread status
+ if (entry.IsAttributeSet(ECsAttributeUnread)) {
+ item.setData(true, UnReadStatus);
+ }
+ else {
+ item.setData(false, UnReadStatus);
+ }
+
+ //sending state
+ item.setData(entry.GetSendState(), SendingState);
+ // direction
+ item.setData(entry.ConversationDir(), Direction);
+
+ //location
+ if (entry.ConversationDir() == ECsDirectionIncoming) {
+ item.setData(ConvergedMessage::Inbox, MessageLocation);
+ }
+ else if (entry.IsAttributeSet(ECsAttributeDraft)) {
+ item.setData(ConvergedMessage::Draft, MessageLocation);
+ }
+ else if (entry.IsAttributeSet(ECsAttributeSent)) {
+ item.setData(ConvergedMessage::Sent, MessageLocation);
+ }
+ else {
+ item.setData(ConvergedMessage::Outbox, MessageLocation);
+ }
+
+ //message specific handling
+ if (msgType == ConvergedMessage::Mms) {
+ QCRITICAL_WRITE("ConversationsModel::populateItem MMS start.")
+ handleMMS(item, entry);
+ QCRITICAL_WRITE("ConversationsModel::populateItem MMS end.")
+ }
+ else if(msgType == ConvergedMessage::MmsNotification) {
+ item.setData(subject, Subject);
+ handleMMSNotification(item, entry);
+ }
+ else if (msgType == ConvergedMessage::BT) {
+ handleBlueToothMessages(item, entry);
+ }
+ else if (msgType == ConvergedMessage::BioMsg) {
+ handleBioMessages(item, entry);
+ }
+ else {
+ // sms bodytext
+ item.setData(subject, BodyText);
+ }
+
+ QCRITICAL_WRITE("ConversationsModel::populateItem end.");
+}
+
+//---------------------------------------------------------------
+// ConversationsModel::validateMsgForForward
+// @see header file
+//---------------------------------------------------------------
+bool ConversationsModel::validateMsgForForward(qint32 messageId)
+{
+ bool retValue = true;
+ //Validate if the mms msg can be forwarded or not
+ MmsConformanceCheck* mmsConformanceCheck = new MmsConformanceCheck;
+ retValue = mmsConformanceCheck->validateMsgForForward(messageId);
+
+ delete mmsConformanceCheck;
+ return retValue;
+}
+
+
+//---------------------------------------------------------------
+// ConversationsModel::handleMMS
+// @see header
+//---------------------------------------------------------------
+void ConversationsModel::handleMMS(QStandardItem& item, const CCsConversationEntry& entry)
+{
+ //msg_id
+ int msgId = entry.EntryId();
+
+ bool isEntryInDb = false;
+ TInt err = KErrNone;
+
+ //check if db is open and query db
+ if (iSqlDbOpen)
+ {
+ RSqlStatement sqlSelectStmt;
+ err = sqlSelectStmt.Prepare(iSqlDb, KSelectConvMsgsStmt);
+
+ // move to fallback option
+ if (KErrNone == err)
+ {
+ TInt msgIdIndex = sqlSelectStmt.ParameterIndex(_L(":message_id"));
+ TInt msgProcessingStateIndex = sqlSelectStmt.ColumnIndex(_L("msg_processingstate"));
+ TInt subjectIndex = sqlSelectStmt.ColumnIndex(_L("subject"));
+ TInt bodyIndex = sqlSelectStmt.ColumnIndex(_L("body_text"));
+ TInt previewPathIndex = sqlSelectStmt.ColumnIndex(
+ _L("preview_path"));
+ TInt msgpropertyIndex = sqlSelectStmt.ColumnIndex(
+ _L("msg_property"));
+ TInt previewIconIndex = sqlSelectStmt.ColumnIndex(
+ _L("preview_icon"));
+
+ err = sqlSelectStmt.BindInt(msgIdIndex, msgId);
+
+ // populate item
+ if ((KErrNone == err) && (sqlSelectStmt.Next() == KSqlAtRow))
+ {
+ int msgProcessingState = 0;
+ msgProcessingState = sqlSelectStmt.ColumnInt(
+ msgProcessingStateIndex);
+ if (msgProcessingState == EPreviewMsgProcessed)
+ {
+ // use entry to populate model only when,
+ // entry is present in DB and its processing is over.
+ RBuf subjectBuffer;
+ if( subjectBuffer.Create(
+ sqlSelectStmt.ColumnSize(
+ subjectIndex)) == KErrNone)
+ {
+ sqlSelectStmt.ColumnText(subjectIndex, subjectBuffer);
+ item.setData(
+ XQConversions::s60DescToQString(
+ subjectBuffer), Subject);
+ subjectBuffer.Close();
+ }
+
+ RBuf bodyBuffer;
+ if (bodyBuffer.Create(
+ sqlSelectStmt.ColumnSize(
+ bodyIndex)) == KErrNone)
+ {
+ sqlSelectStmt.ColumnText(bodyIndex, bodyBuffer);
+ item.setData(
+ XQConversions::s60DescToQString(
+ bodyBuffer), BodyText);
+ bodyBuffer.Close();
+ }
+
+ RBuf previewPathBuffer;
+ QString attachmentPath;
+ if (previewPathBuffer.Create(
+ sqlSelectStmt.ColumnSize(
+ previewPathIndex)) == KErrNone)
+ {
+ sqlSelectStmt.ColumnText(
+ previewPathIndex,
+ previewPathBuffer);
+
+ //Rightnow set inside attachments
+ attachmentPath = XQConversions::s60DescToQString(
+ previewPathBuffer);
+ item.setData(attachmentPath, Attachments);
+ previewPathBuffer.Close();
+ }
+
+ int msgProperty = 0;
+ msgProperty = sqlSelectStmt.ColumnInt(msgpropertyIndex);
+ item.setData(msgProperty, MessageProperty);
+
+ RSqlColumnReadStream stream;
+ //Get data from binary column BLOB
+ TInt err = stream.ColumnBinary(sqlSelectStmt,
+ previewIconIndex);
+
+ QCRITICAL_WRITE_FORMAT("Error from ColumnBinary()", err)
+
+ if (err == KErrNone)
+ {
+ CFbsBitmap *bitmap = new CFbsBitmap;
+ TRAPD(err,bitmap->InternalizeL(stream));
+ QCRITICAL_WRITE_FORMAT("Error from bitmap InternalizeL()", err)
+
+ //convert bitmap to pixmap
+ if (err == KErrNone)
+ {
+ TSize size = bitmap->SizeInPixels();
+ int bytesPerLine = bitmap->ScanLineLength(
+ size.iWidth, bitmap->DisplayMode());
+ const uchar* dataPtr =
+ (const uchar*) bitmap->DataAddress();
+
+ QPixmap pixmap = QPixmap::fromImage(QImage(
+ dataPtr, size.iWidth, size.iHeight,
+ bytesPerLine, QImage::Format_RGB16));
+
+ setPreviewIcon(pixmap, attachmentPath, msgId,
+ true);
+
+ }
+ //remove bitmap
+ delete bitmap;
+ }
+
+ //set flag to disable fallback option
+ isEntryInDb = true;
+ }
+ }
+ }
+ sqlSelectStmt.Close();
+ }
+
+ //fallback option incase of db operation failure or enry not found in DB
+ //populate from data plugins
+ if (!isEntryInDb || err != KErrNone)
+ {
+ int error = iMmsDataPlugin->setMessageId(entry.EntryId());
+ if(error != KErrNone)
+ {
+ // skip all
+ return;
+ }
+ int msgProperty = 0;
+
+ if (iMmsDataPlugin->attachmentCount() > 0)
+ {
+ msgProperty |= EPreviewAttachment;
+ }
+
+ if(validateMsgForForward(entry.EntryId()))
+ {
+ msgProperty |= EPreviewForward;
+ }
+
+ //subject
+ item.setData(iMmsDataPlugin->subject(), Subject);
+
+ int slideCount = iMmsDataPlugin->slideCount();
+ bool isBodyTextSet = false;
+ bool isAudioSet = false;
+ bool isImageSet = false;
+ bool isVideoSet = false;
+ QString textContent;
+ QString videoPath;
+ QString imagePath;
+
+ for (int i = 0; i < slideCount; ++i)
+ {
+ UniMessageInfoList objectList = iMmsDataPlugin->slideContent(i);
+ for (int index = 0; index < objectList.count(); ++index)
+ {
+ if (!isBodyTextSet && objectList[index]->mimetype().contains(
+ "text"))
+ {
+ QFile file(objectList[index]->path());
+ file.open(QIODevice::ReadOnly);
+ QByteArray textArray;
+ textArray = file.readAll();
+ char *data = new char[textArray.size()+1];
+ strcpy(data,textArray.data());
+ //This is needed since MMS text content
+ //is stored in UTF8 format
+ textContent = textContent.fromUtf8(data,strlen(data));
+ delete []data;
+ item.setData(textContent, BodyText);
+ isBodyTextSet = true;
+ file.close();
+ }
+ if (!isVideoSet && !isImageSet && objectList[index]->mimetype().contains(
+ "image"))
+ {
+ isImageSet = true;
+ msgProperty |= EPreviewImage;
+ if (objectList[index]->isProtected())
+ {
+ msgProperty |= EPreviewProtectedImage;
+ }
+ if (objectList[index]->isCorrupted())
+ {
+ msgProperty |= EPreviewCorruptedImage;
+ }
+ imagePath = objectList[index]->path();
+ }
+ if (!isVideoSet && !isAudioSet && objectList[index]->mimetype().contains(
+ "audio"))
+ {
+ msgProperty |= EPreviewAudio;
+ if (objectList[index]->isProtected())
+ {
+ msgProperty |= EPreviewProtectedAudio;
+ }
+ if (objectList[index]->isCorrupted())
+ {
+ msgProperty |= EPreviewCorruptedAudio;
+ }
+ isAudioSet = true;
+ }
+ if (!( isImageSet || isAudioSet) && !isVideoSet && objectList[index]->mimetype().contains(
+ "video"))
+ {
+ isVideoSet = true;
+ msgProperty |= EPreviewVideo;
+ if (objectList[index]->isProtected())
+ {
+ msgProperty |= EPreviewProtectedVideo;
+ }
+ if (objectList[index]->isCorrupted())
+ {
+ msgProperty |= EPreviewCorruptedVideo;
+ }
+ videoPath = objectList[index]->path();
+ }
+ }
+ foreach(UniMessageInfo* slide,objectList)
+ {
+ delete slide;
+ }
+ }
+ QPixmap pixmap;
+ //populate item with the attachment list
+ //TODO: This code is not required bcoz video icon is show and not preview
+ if (isVideoSet)
+ {
+ item.setData(videoPath, Attachments);
+ // Store thumbnail only for non protected, non corrupted content.
+ if (!(EPreviewProtectedVideo & msgProperty) &&
+ !(EPreviewCorruptedVideo & msgProperty))
+ {
+ setPreviewIcon(pixmap, videoPath, msgId, false);
+ }
+ }
+ else if (isImageSet)
+ {
+ item.setData(imagePath, Attachments);
+ // Store thumbnail only for non protected, non corrupted content.
+ if (!(EPreviewProtectedImage & msgProperty) &&
+ !(EPreviewCorruptedImage & msgProperty))
+ {
+ setPreviewIcon(pixmap, imagePath, msgId, false);
+ }
+ }
+ //populate msgProperty
+ item.setData(msgProperty, MessageProperty);
+ }
+
+ // fill other attributes
+ if (entry.IsAttributeSet(ECsAttributeHighPriority))
+ {
+ item.setData(ConvergedMessage::High, MessagePriority);
+ }
+ else if (entry.IsAttributeSet(ECsAttributeLowPriority))
+ {
+ item.setData(ConvergedMessage::Low, MessagePriority);
+ }
+}
+
+//---------------------------------------------------------------
+// ConversationsModel::handleMMSNotification
+// @see header
+//---------------------------------------------------------------
+void ConversationsModel::handleMMSNotification(QStandardItem& item,
+ const CCsConversationEntry& entry)
+{
+ // set context to current entry
+ TRAPD(err, mMsgStoreHandler->setNotificationMessageIdL(entry.EntryId()));
+ if(err != KErrNone)
+ {
+ return;
+ }
+
+ // fetch relevent info to show in CV
+ // notification state e.g. waiting, retrieving etc
+ QString statusStr;
+ int status;
+ mMsgStoreHandler->NotificationStatus(status, statusStr);
+
+ // create data for bodytext role
+ QString dataText;
+ dataText.append(mMsgStoreHandler->NotificationMsgSize());
+ dataText.append(QChar::LineSeparator);
+ dataText.append(mMsgStoreHandler->NotificationClass());
+ dataText.append(QChar::LineSeparator);
+ dataText.append(mMsgStoreHandler->NotificationExpiryDate());
+ if(!statusStr.isEmpty())
+ {
+ dataText.append(QChar::LineSeparator);
+ dataText.append(statusStr);
+ }
+
+ // set fetched data to roles
+ item.setData(status, NotificationStatus);
+ item.setData(dataText, BodyText);
+
+ if (entry.IsAttributeSet(ECsAttributeHighPriority)) {
+ item.setData(ConvergedMessage::High, MessagePriority);
+ }
+ else if (entry.IsAttributeSet(ECsAttributeLowPriority)) {
+ item.setData(ConvergedMessage::Low, MessagePriority);
+ }
+}
+
+//---------------------------------------------------------------
+// ConversationsModel::handleBlueToothMessages
+// @see header
+//---------------------------------------------------------------
+void ConversationsModel::handleBlueToothMessages(QStandardItem& item,
+ const CCsConversationEntry& entry)
+ {
+ int msgSubType = ConversationsEngineUtility::messageSubType(
+ entry.GetType());
+
+ if (msgSubType == ConvergedMessage::VCard)
+ {
+ handleVCard(item, entry.EntryId());
+ }
+ else
+ {
+ QString description = XQConversions::s60DescToQString(
+ *(entry.Description()));
+
+ if (msgSubType == ConvergedMessage::VCal) // "vCalendar"
+ {
+ //message sub-type
+ item.setData(ConvergedMessage::VCal, MessageSubType);
+ }
+ else
+ {
+ //message sub-type
+ item.setData(ConvergedMessage::None, MessageSubType);
+ }
+ //for BT messages we show filenames for all other (except vcard) messages
+ //get filename and set as body
+ QFileInfo fileinfo(description);
+ QString filename = fileinfo.fileName();
+ item.setData(filename, BodyText);
+ }
+ }
+
+//---------------------------------------------------------------
+// ConversationsModel::handleBioMessages
+// @see header
+//---------------------------------------------------------------
+void ConversationsModel::handleBioMessages(QStandardItem& item, const CCsConversationEntry& entry)
+{
+ int msgSubType = ConversationsEngineUtility::messageSubType(entry.GetType());
+ if (ConvergedMessage::VCard == msgSubType)
+ {
+ handleVCard(item, entry.EntryId());
+ }
+ else if (ConvergedMessage::VCal == msgSubType) {
+ //not supported
+ }
+ else if (ConvergedMessage::RingingTone == msgSubType) {
+ iBioMsgPlugin->setMessageId(entry.EntryId());
+ if (iBioMsgPlugin->attachmentCount() > 0) {
+ UniMessageInfoList attList = iBioMsgPlugin->attachmentList();
+ QString attachmentPath = attList[0]->path();
+
+ //get tone title, and set as bodytext
+ RingBc ringBc;
+ item.setData(ringBc.toneTitle(attachmentPath), BodyText);
+ while (!attList.isEmpty()) {
+ delete attList.takeFirst();
+ }
+ }
+
+ }
+ else {
+ // description
+ HBufC* description = entry.Description();
+ QString subject("");
+ if (description && description->Length()) {
+ subject = (XQConversions::s60DescToQString(*description));
+ item.setData(subject, BodyText);
+ }
+ }
+}
+
+//---------------------------------------------------------------
+// ConversationsModel::getDBHandle()
+// @see header
+//---------------------------------------------------------------
+RSqlDatabase& ConversationsModel::getDBHandle(TBool& isOpen)
+{
+ isOpen = iSqlDbOpen;
+ return iSqlDb;
+}
+
+//---------------------------------------------------------------
+// ConversationsModel::setPreviewIcon()
+// @see header
+//---------------------------------------------------------------
+void ConversationsModel::setPreviewIcon(QPixmap& pixmap, QString& filePath,
+ int msgId, bool inDb)
+{
+
+ //Since the population happens in reverse this check is needed so that
+ //most recent items have their icons present in cache
+ if (previewIconCache.totalCost() >= previewIconCache.maxCost())
+ return;
+
+ // if not found in db, set from file path
+ if (!inDb)
+ {
+ QPixmap pixmap(filePath);
+ QPixmap scaledPixmap = pixmap.scaled(KWidth, KHeight, Qt::IgnoreAspectRatio);
+ HbIcon *previewIcon = new HbIcon(scaledPixmap);
+
+ previewIconCache.insert(msgId, previewIcon);
+
+ }
+ else
+ {
+ HbIcon *previewIcon = new HbIcon(pixmap);
+ previewIconCache.insert(msgId, previewIcon);
+ }
+}
+
+//---------------------------------------------------------------
+// ConversationsModel::getPreviewIconItem()
+// @see header
+//---------------------------------------------------------------
+HbIcon* ConversationsModel::getPreviewIconItem(int msgId,
+ QString& filepath) const
+{
+ QCRITICAL_WRITE("ConversationsModel::getPreviewIconItem start.")
+
+ //Initialize icon from the Cache will be NULL if Item not present
+ HbIcon* previewIcon = previewIconCache[msgId];
+ if (!previewIcon)
+ {
+ //This is done in this way as non-const function call cant be done here
+ emit retrievePreviewIcon(msgId, filepath);
+
+ previewIcon = previewIconCache[msgId];
+ }
+
+ QCRITICAL_WRITE("ConversationsModel::getPreviewIconItem start.")
+
+ return previewIcon;
+}
+
+//---------------------------------------------------------------
+// ConversationsModel::updatePreviewIcon()
+// @see header
+//---------------------------------------------------------------
+void ConversationsModel::updatePreviewIcon(int msgId, QString& filePath)
+{
+ QCRITICAL_WRITE("ConversationsModel::updatePreviewIcon start.")
+
+ //sql query to get preview-icon from DB
+ bool imagePreviewed = false;
+ QPixmap pixmap;
+
+ if (iSqlDbOpen)
+ {
+ RSqlStatement sqlSelectPreviewIconStmt;
+ TInt err = sqlSelectPreviewIconStmt.Prepare(iSqlDb,
+ KSelectPreviewIconStmt);
+
+ QCRITICAL_WRITE_FORMAT("Error from Prepare()", err)
+
+ if (err == KErrNone)
+ {
+ //msg_id
+ TInt msgIdIndex = sqlSelectPreviewIconStmt.ParameterIndex(
+ _L(":message_id"));
+ sqlSelectPreviewIconStmt.BindInt(msgIdIndex, msgId);
+
+ // get preview-icon from DB
+ err = sqlSelectPreviewIconStmt.Next();
+ QCRITICAL_WRITE_FORMAT("Error from Next()", err)
+
+ if (err == KSqlAtRow)
+ {
+ TInt previewIconIndex = sqlSelectPreviewIconStmt.ColumnIndex(
+ _L("preview_icon"));
+
+ RSqlColumnReadStream stream;
+
+ //Get data from binary column BLOB
+ err = stream.ColumnBinary(sqlSelectPreviewIconStmt,
+ previewIconIndex);
+
+ QCRITICAL_WRITE_FORMAT("Error from ColumnBinary()", err)
+
+ if (err == KErrNone)
+ {
+ CFbsBitmap *bitmap = new CFbsBitmap;
+ TRAPD(err,bitmap->InternalizeL(stream));
+ QCRITICAL_WRITE_FORMAT("Error from bitmap InternalizeL()", err)
+
+ //convert bitmap to pixmap
+ if (err == KErrNone)
+ {
+ TSize size = bitmap->SizeInPixels();
+ int bytesPerLine = bitmap->ScanLineLength(size.iWidth,
+ bitmap->DisplayMode());
+ const uchar* dataPtr =
+ (const uchar*) bitmap->DataAddress();
+
+ pixmap = QPixmap::fromImage(QImage(dataPtr,
+ size.iWidth, size.iHeight, bytesPerLine,
+ QImage::Format_RGB16));
+
+ imagePreviewed = true;
+
+ QCRITICAL_WRITE("Bitmap Conversion completed")
+ }
+ //remove bitmap
+ delete bitmap;
+ }
+ //close stream
+ stream.Close();
+ }
+ }
+ sqlSelectPreviewIconStmt.Close();
+ }
+
+ // if not found in db, set from file path
+ if (!imagePreviewed)
+ {
+ QPixmap orgPixmap(filePath);
+ pixmap = orgPixmap.scaled(63.65, 63.65, Qt::IgnoreAspectRatio);
+ }
+ HbIcon * previewIcon = new HbIcon(pixmap);
+
+ previewIconCache.insert(msgId, previewIcon);
+
+ QCRITICAL_WRITE("ConversationsModel::updatePreviewIcon end.")
+
+}
+
+//---------------------------------------------------------------
+// ConversationsModel::handleVCard()
+// @see header
+//---------------------------------------------------------------
+void ConversationsModel::handleVCard(QStandardItem& item, int msgId)
+ {
+ //sql query to get vcard-path from DB
+ bool vCardParsed = false;
+
+ if (iSqlDbOpen)
+ {
+ RSqlStatement sqlSelectVcardStmt;
+ TInt err = sqlSelectVcardStmt.Prepare(iSqlDb, KSelectVCardStmt);
+
+ QCRITICAL_WRITE_FORMAT("Error from Prepare()", err)
+
+ if (err == KErrNone)
+ {
+ //msg_id
+ TInt msgIdIndex = sqlSelectVcardStmt.ParameterIndex(
+ _L(":message_id"));
+ sqlSelectVcardStmt.BindInt(msgIdIndex, msgId);
+ // state
+ TInt msgProcessingStateIndex = sqlSelectVcardStmt.ColumnIndex(
+ _L("msg_processingstate"));
+
+ // get vacrd-path from DB
+ err = sqlSelectVcardStmt.Next();
+ QCRITICAL_WRITE_FORMAT("Error from Next()", err)
+
+ if (err == KSqlAtRow)
+ {
+ int msgProcessingState = 0;
+ msgProcessingState = sqlSelectVcardStmt.ColumnInt(
+ msgProcessingStateIndex);
+ if (msgProcessingState == EPreviewMsgProcessed)
+ {
+ //path-index
+ TInt previewPathIndex = sqlSelectVcardStmt.ColumnIndex(
+ _L("preview_path"));
+
+ //Get vcard-path data from path-index
+ RSqlColumnReadStream stream;
+ err = stream.ColumnBinary(sqlSelectVcardStmt,
+ previewPathIndex);
+
+ QCRITICAL_WRITE_FORMAT("Error from ColumnBinary()", err)
+
+ if (err == KErrNone)
+ {
+ RBuf vCardPathBuffer;
+ if (vCardPathBuffer.Create(
+ sqlSelectVcardStmt.ColumnSize(
+ previewPathIndex)) == KErrNone)
+ {
+ sqlSelectVcardStmt.ColumnText(
+ previewPathIndex,
+ vCardPathBuffer);
+
+ //set inside attachments
+ QString attachmentPath(
+ XQConversions::s60DescToQString(
+ vCardPathBuffer));
+ item.setData(attachmentPath, Attachments);
+
+ //get display-name and set as bodytext
+ QString displayName =
+ MsgContactHandler::getVCardDisplayName(
+ attachmentPath);
+ item.setData(displayName, BodyText);
+
+ vCardPathBuffer.Close();
+ vCardParsed = true;
+
+ QCRITICAL_WRITE("vcard parsing complete.")
+ }
+ }
+ //close stream
+ stream.Close();
+ }
+ }
+ }
+ sqlSelectVcardStmt.Close();
+ }
+
+ // fallback, if not parsed in DB, parse from store
+ if (!vCardParsed)
+ {
+ iBioMsgPlugin->setMessageId(msgId);
+
+ if (iBioMsgPlugin->attachmentCount() > 0)
+ {
+ UniMessageInfoList attList = iBioMsgPlugin->attachmentList();
+ QString attachmentPath = attList[0]->path();
+
+ //get display-name and set as bodytext
+ QString displayName = MsgContactHandler::getVCardDisplayName(
+ attachmentPath);
+ item.setData(displayName, BodyText);
+ item.setData(attachmentPath, Attachments);
+
+ // clear attachement list : its allocated at data model
+ while (!attList.isEmpty())
+ {
+ delete attList.takeFirst();
+ }
+ }
+ }
+ }
+
+//---------------------------------------------------------------
+// ConversationsModel::clearModel()
+// @see header
+//---------------------------------------------------------------
+void ConversationsModel::clearModel()
+{
+ clear();
+ previewIconCache.clear();
+}
+
+//---------------------------------------------------------------
+// ConversationsModel::emitConversationViewEmpty()
+// @see header
+//---------------------------------------------------------------
+void ConversationsModel:: emitConversationViewEmpty()
+{
+ emit conversationViewEmpty();
+}
+//EOF