messagingapp/msgui/appengine/src/conversationsmodel.cpp
branchRCL_3
changeset 57 ebe688cedc25
--- /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