messagingapp/msgui/appengine/src/conversationsmodel.cpp
branchRCL_3
changeset 26 ebe688cedc25
equal deleted inserted replaced
25:fa1df4b99609 26:ebe688cedc25
       
     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 "conversationsmodel.h"
       
    19 #include "conversationsenginedefines.h"
       
    20 #include "conversationmsgstorehandler.h"
       
    21 #include "convergedmessage.h"
       
    22 #include <xqconversions.h>
       
    23 #include "conversationsengineutility.h"
       
    24 #include "unidatamodelloader.h"
       
    25 #include "unidatamodelplugininterface.h"
       
    26 #include "ringbc.h"
       
    27 #include "msgcontacthandler.h"
       
    28 #include "mmsconformancecheck.h"
       
    29 #include <ccsconversationentry.h>
       
    30 #include <fileprotectionresolver.h>
       
    31 
       
    32 #include "debugtraces.h"
       
    33 
       
    34 #include <QFile>
       
    35 #include <QFileInfo>
       
    36 #include <s32mem.h>
       
    37 #include <s32strm.h>
       
    38 #include <fbs.h>
       
    39 #include <ccsdefs.h>
       
    40 
       
    41 //CONSTANTS
       
    42 _LIT(KDbFileName, "c:[2002A542]conversations.db");
       
    43 
       
    44 // preview sql query
       
    45 _LIT(KSelectConvMsgsStmt, "SELECT message_id, msg_processingstate, subject, body_text, preview_path, msg_property, preview_icon FROM conversation_messages WHERE message_id=:message_id ");
       
    46 
       
    47 //selecet preview-icon query
       
    48 _LIT(KSelectPreviewIconStmt,"SELECT  message_id, preview_icon FROM conversation_messages WHERE message_id = :message_id ");
       
    49 
       
    50 //selecet vcard-path query
       
    51 _LIT(KSelectVCardStmt,"SELECT  message_id, msg_processingstate, preview_path FROM conversation_messages WHERE message_id = :message_id ");
       
    52 
       
    53 // preview-cache max cost (items)
       
    54 const int CACHE_COST =  50;
       
    55 //Preview thumbnail size
       
    56 const int KWidth = 9.5 * 6.7;
       
    57 const int KHeight = 9.5 * 6.7;
       
    58 //---------------------------------------------------------------
       
    59 // ConversationsModel::ConversationsModel
       
    60 // Constructor
       
    61 //---------------------------------------------------------------
       
    62 ConversationsModel::ConversationsModel(ConversationMsgStoreHandler* msgStoreHandler,
       
    63     QObject* parent) :
       
    64     QStandardItemModel(parent), mMsgStoreHandler(msgStoreHandler), iSqlDbOpen(EFalse)
       
    65 {
       
    66     //Open SQL DB
       
    67     if (KErrNone == iSqlDb.Open(KDbFileName))
       
    68     {
       
    69         iSqlDbOpen = ETrue;
       
    70     }
       
    71     previewIconCache.setMaxCost(CACHE_COST);
       
    72 
       
    73     int err = connect(this, SIGNAL(retrievePreviewIcon(int, QString&)), this,
       
    74         SLOT(updatePreviewIcon(int, QString&)));
       
    75     QCRITICAL_WRITE_FORMAT("Error from connect()", err)
       
    76     iDataModelPluginLoader = new UniDataModelLoader;
       
    77     iMmsDataPlugin = iDataModelPluginLoader->getDataModelPlugin(ConvergedMessage::Mms);
       
    78     iBioMsgPlugin = iDataModelPluginLoader->getDataModelPlugin(ConvergedMessage::BioMsg);
       
    79 }
       
    80 
       
    81 //---------------------------------------------------------------
       
    82 // ConversationsModel::~ConversationsModel
       
    83 // Destructor
       
    84 //---------------------------------------------------------------
       
    85 ConversationsModel::~ConversationsModel()
       
    86 {
       
    87     //Close SQL-DB
       
    88     iSqlDb.Close();
       
    89 
       
    90 	//clear preview-cache
       
    91     previewIconCache.clear();
       
    92 
       
    93     if (iDataModelPluginLoader) {
       
    94         delete iDataModelPluginLoader;
       
    95         iDataModelPluginLoader = NULL;
       
    96     }
       
    97 }
       
    98 
       
    99 //---------------------------------------------------------------
       
   100 // ConversationsModel::data
       
   101 // @see header
       
   102 //---------------------------------------------------------------
       
   103 QVariant ConversationsModel::data(const QModelIndex & index, int role) const
       
   104 {
       
   105     QVariant value;
       
   106     QStandardItem* item = itemFromIndex(index);
       
   107     switch (role) {
       
   108     case ConversationId:
       
   109     {
       
   110         value = item->data(ConversationId);
       
   111         break;
       
   112     }
       
   113     case UnReadStatus:
       
   114     {
       
   115         value = item->data(UnReadStatus);
       
   116         break;
       
   117     }
       
   118     case ContactId:
       
   119     {
       
   120         value = item->data(ContactId);
       
   121         break;
       
   122     }
       
   123     case TimeStamp:
       
   124     {
       
   125         value = item->data(TimeStamp);
       
   126         break;
       
   127     }
       
   128     case ConvergedMsgId:
       
   129     {
       
   130         value = item->data(ConvergedMsgId);
       
   131         break;
       
   132     }
       
   133     case MessageProperty:
       
   134     {
       
   135         value = item->data(MessageProperty);
       
   136         break;
       
   137     }
       
   138     case MessageType:
       
   139     {
       
   140         value = item->data(MessageType);
       
   141         break;
       
   142     }
       
   143     case MessageSubType:
       
   144     {
       
   145         value = item->data(MessageSubType);
       
   146         break;
       
   147     }
       
   148     case Subject:
       
   149     {
       
   150         value = item->data(Subject);
       
   151         break;
       
   152     }
       
   153     case BodyText:
       
   154     {
       
   155         value = item->data(BodyText);
       
   156         break;
       
   157     }
       
   158     case ConversationAddress:
       
   159     {
       
   160         value = item->data(ConversationAddress);
       
   161         break;
       
   162     }
       
   163     case Direction:
       
   164     {
       
   165         value = item->data(Direction);
       
   166         break;
       
   167     }
       
   168     case SendingState:
       
   169     {
       
   170         value = item->data(SendingState);
       
   171         break;
       
   172     }
       
   173     case PreviewIcon:
       
   174     {
       
   175         QString filepath(item->data(Attachments).toString());
       
   176         int msgId = item->data(ConvergedMsgId).toInt();
       
   177         HbIcon *icon = getPreviewIconItem(msgId, filepath);
       
   178         return *icon;
       
   179     }
       
   180     case MessagePriority:
       
   181     {
       
   182         value = item->data(MessagePriority);
       
   183         break;
       
   184     }
       
   185     case Attachments:
       
   186     {
       
   187         value = item->data(Attachments);
       
   188         break;
       
   189     }
       
   190     case MessageLocation:
       
   191     {
       
   192         value = item->data(MessageLocation);
       
   193         break;
       
   194     }
       
   195     case MessageStore:
       
   196     {
       
   197         value = item->data(MessageStore);
       
   198         break;
       
   199     }
       
   200     case ConversationAlias:
       
   201     {
       
   202         value = item->data(ConversationAlias);
       
   203         break;
       
   204     }
       
   205     case UnreadCount:
       
   206     {
       
   207         value = item->data(UnreadCount);
       
   208         break;
       
   209     }
       
   210     case DisplayName: // Fall through start
       
   211         value = item->data(DisplayName);
       
   212         break;
       
   213     case Avatar: // Fall througn end
       
   214         value = item->data(Avatar);
       
   215         break;
       
   216     case NotificationStatus:
       
   217         value = item->data(NotificationStatus);
       
   218         break;
       
   219     default:
       
   220     {
       
   221         //No matching role found, set invalid variant
       
   222         value = QVariant();
       
   223         break;
       
   224     }
       
   225     }
       
   226     return value;
       
   227 }
       
   228 
       
   229 //---------------------------------------------------------------
       
   230 // ConversationsModel::addRow
       
   231 // @see header
       
   232 //---------------------------------------------------------------
       
   233 void ConversationsModel::addRow(const CCsConversationEntry& entry, bool dynamicUpdate)
       
   234 {
       
   235     int msgId = entry.EntryId();
       
   236     //match, if found update else add item
       
   237     QModelIndexList indexList = this->match(index(0, 0), ConvergedMsgId, msgId, -1,
       
   238         Qt::MatchExactly);
       
   239 
       
   240     // if not found, add new item
       
   241     if (indexList.count() == 0) {
       
   242         QStandardItem* item = new QStandardItem();
       
   243         populateItem(*item, entry);
       
   244         if (!dynamicUpdate) {
       
   245             insertRow(0, item);
       
   246         }
       
   247         else {
       
   248             int i;
       
   249             for (i = rowCount() - 1; i >= 0; --i) {
       
   250                 QStandardItem* modelItem = this->item(i, 0);
       
   251                 if (modelItem->data(ConvergedMsgId).toInt() < item->data(ConvergedMsgId).toInt()) {
       
   252                     if (i == rowCount() - 1) {
       
   253                         appendRow(item);
       
   254                     }
       
   255                     else {
       
   256                         insertRow(i + 1, item);
       
   257                     }
       
   258                     return;
       
   259                 }
       
   260             }
       
   261             if (i == 0) {
       
   262                 insertRow(0, item);
       
   263             }
       
   264         }
       
   265     }
       
   266     else {
       
   267         // Update an existing item
       
   268         QModelIndex index = indexList[0];
       
   269         QStandardItem* item = this->item(index.row(), 0);
       
   270         populateItem(*item, entry);
       
   271     }
       
   272 }
       
   273 
       
   274 //---------------------------------------------------------------
       
   275 // ConversationsModel::deleteRow
       
   276 // @see header
       
   277 //---------------------------------------------------------------
       
   278 void ConversationsModel::deleteRow(int msgId)
       
   279 {
       
   280     //match, if found remove item
       
   281     QModelIndexList indexList =
       
   282         this->match(index(0, 0), ConvergedMsgId, msgId, 1, Qt::MatchExactly);
       
   283 
       
   284     if (indexList.count() == 1) {
       
   285         QModelIndex index = indexList[0];
       
   286         this->removeRow(index.row());
       
   287     }
       
   288 }
       
   289 
       
   290 //---------------------------------------------------------------
       
   291 // ConversationsModel::populateItem
       
   292 // @see header
       
   293 //---------------------------------------------------------------
       
   294 void ConversationsModel::populateItem(QStandardItem& item, const CCsConversationEntry& entry)
       
   295 {
       
   296     QCRITICAL_WRITE("ConversationsModel::populateItem start.");
       
   297 
       
   298     int msgId = entry.EntryId();
       
   299     // id
       
   300     item.setData(msgId, ConvergedMsgId);
       
   301 
       
   302     // description
       
   303     HBufC* description = entry.Description();
       
   304     QString subject("");
       
   305     if (description && description->Length()) {
       
   306         subject = (XQConversions::s60DescToQString(*description));     
       
   307     }
       
   308 
       
   309     // time stamp
       
   310     TTime unixEpoch(KUnixEpoch);
       
   311     TTimeIntervalSeconds seconds;
       
   312     TTime timeStamp(entry.TimeStamp());
       
   313     timeStamp.SecondsFrom(unixEpoch, seconds);
       
   314     item.setData(seconds.Int(), TimeStamp);
       
   315 
       
   316     //contact details
       
   317     HBufC* contact = entry.Contact();
       
   318     if (contact && contact->Length()) {
       
   319         item.setData(XQConversions::s60DescToQString(*contact), ConversationAddress);
       
   320     }
       
   321 
       
   322     // message type.
       
   323     int msgType = ConversationsEngineUtility::messageType(entry.GetType());
       
   324     item.setData(msgType, MessageType);
       
   325 
       
   326     //message sub-type
       
   327     item.setData(ConversationsEngineUtility::messageSubType(entry.GetType()), MessageSubType);
       
   328 
       
   329     // unread status
       
   330     if (entry.IsAttributeSet(ECsAttributeUnread)) {
       
   331         item.setData(true, UnReadStatus);
       
   332     }
       
   333     else {
       
   334         item.setData(false, UnReadStatus);
       
   335     }
       
   336 
       
   337     //sending state
       
   338     item.setData(entry.GetSendState(), SendingState);
       
   339     // direction
       
   340     item.setData(entry.ConversationDir(), Direction);
       
   341 
       
   342     //location
       
   343     if (entry.ConversationDir() == ECsDirectionIncoming) {
       
   344         item.setData(ConvergedMessage::Inbox, MessageLocation);
       
   345     }
       
   346     else if (entry.IsAttributeSet(ECsAttributeDraft)) {
       
   347         item.setData(ConvergedMessage::Draft, MessageLocation);
       
   348     }
       
   349     else if (entry.IsAttributeSet(ECsAttributeSent)) {
       
   350         item.setData(ConvergedMessage::Sent, MessageLocation);
       
   351     }
       
   352     else {
       
   353         item.setData(ConvergedMessage::Outbox, MessageLocation);
       
   354     }
       
   355 
       
   356     //message specific handling
       
   357     if (msgType == ConvergedMessage::Mms) {
       
   358         QCRITICAL_WRITE("ConversationsModel::populateItem  MMS start.")
       
   359         handleMMS(item, entry);
       
   360         QCRITICAL_WRITE("ConversationsModel::populateItem MMS end.")
       
   361     }
       
   362     else if(msgType == ConvergedMessage::MmsNotification) {
       
   363         item.setData(subject, Subject);
       
   364         handleMMSNotification(item, entry);
       
   365     }
       
   366     else if (msgType == ConvergedMessage::BT) {
       
   367         handleBlueToothMessages(item, entry);
       
   368     }
       
   369     else if (msgType == ConvergedMessage::BioMsg) {
       
   370         handleBioMessages(item, entry);
       
   371     }
       
   372     else {
       
   373         // sms bodytext
       
   374         item.setData(subject, BodyText);
       
   375     }
       
   376 
       
   377     QCRITICAL_WRITE("ConversationsModel::populateItem end.");
       
   378 }
       
   379 
       
   380 //---------------------------------------------------------------
       
   381 // ConversationsModel::validateMsgForForward
       
   382 // @see header file
       
   383 //---------------------------------------------------------------
       
   384 bool ConversationsModel::validateMsgForForward(qint32 messageId)
       
   385 {
       
   386     bool retValue = true;
       
   387     //Validate if the mms msg can be forwarded or not
       
   388     MmsConformanceCheck* mmsConformanceCheck = new MmsConformanceCheck;
       
   389     retValue = mmsConformanceCheck->validateMsgForForward(messageId);
       
   390 
       
   391     delete mmsConformanceCheck;
       
   392     return retValue;
       
   393 }
       
   394 
       
   395 
       
   396 //---------------------------------------------------------------
       
   397 // ConversationsModel::handleMMS
       
   398 // @see header
       
   399 //---------------------------------------------------------------
       
   400 void ConversationsModel::handleMMS(QStandardItem& item, const CCsConversationEntry& entry)
       
   401 {
       
   402     //msg_id
       
   403     int msgId = entry.EntryId();
       
   404 
       
   405     bool isEntryInDb = false;
       
   406     TInt err = KErrNone;
       
   407 
       
   408     //check if db is open and query db
       
   409     if (iSqlDbOpen)
       
   410     {
       
   411         RSqlStatement sqlSelectStmt;
       
   412         err = sqlSelectStmt.Prepare(iSqlDb, KSelectConvMsgsStmt);
       
   413 
       
   414         // move to fallback option
       
   415         if (KErrNone == err)
       
   416             {
       
   417             TInt msgIdIndex = sqlSelectStmt.ParameterIndex(_L(":message_id"));
       
   418             TInt msgProcessingStateIndex = sqlSelectStmt.ColumnIndex(_L("msg_processingstate"));
       
   419             TInt subjectIndex = sqlSelectStmt.ColumnIndex(_L("subject"));
       
   420             TInt bodyIndex = sqlSelectStmt.ColumnIndex(_L("body_text"));
       
   421             TInt previewPathIndex = sqlSelectStmt.ColumnIndex(
       
   422                     _L("preview_path"));
       
   423             TInt msgpropertyIndex = sqlSelectStmt.ColumnIndex(
       
   424                 _L("msg_property"));
       
   425             TInt previewIconIndex = sqlSelectStmt.ColumnIndex(
       
   426                 _L("preview_icon"));
       
   427 
       
   428             err = sqlSelectStmt.BindInt(msgIdIndex, msgId);
       
   429 
       
   430             // populate item
       
   431             if ((KErrNone == err) && (sqlSelectStmt.Next() == KSqlAtRow))
       
   432                 {
       
   433                 int msgProcessingState = 0;
       
   434                 msgProcessingState = sqlSelectStmt.ColumnInt(
       
   435                         msgProcessingStateIndex);
       
   436                 if (msgProcessingState == EPreviewMsgProcessed)
       
   437                     {
       
   438                     // use entry to populate model only when,
       
   439                     // entry is present in DB and its processing is over.
       
   440                     RBuf subjectBuffer;
       
   441                     if( subjectBuffer.Create(
       
   442                             sqlSelectStmt.ColumnSize(
       
   443                                     subjectIndex)) == KErrNone)
       
   444                     {
       
   445                         sqlSelectStmt.ColumnText(subjectIndex, subjectBuffer);
       
   446                         item.setData(
       
   447                                 XQConversions::s60DescToQString(
       
   448                                         subjectBuffer), Subject);
       
   449                         subjectBuffer.Close();
       
   450                     }
       
   451                     
       
   452                     RBuf bodyBuffer;
       
   453                     if (bodyBuffer.Create(
       
   454                             sqlSelectStmt.ColumnSize(
       
   455                                     bodyIndex)) == KErrNone)
       
   456                     {
       
   457                        sqlSelectStmt.ColumnText(bodyIndex, bodyBuffer);
       
   458                        item.setData(
       
   459                                XQConversions::s60DescToQString(
       
   460                                        bodyBuffer), BodyText);
       
   461                        bodyBuffer.Close();
       
   462                     }
       
   463 
       
   464                     RBuf previewPathBuffer;
       
   465                     QString attachmentPath;
       
   466                     if (previewPathBuffer.Create(
       
   467                             sqlSelectStmt.ColumnSize(
       
   468                                     previewPathIndex)) == KErrNone)
       
   469                     {
       
   470                         sqlSelectStmt.ColumnText(
       
   471                                 previewPathIndex,
       
   472                                 previewPathBuffer);
       
   473 
       
   474                         //Rightnow set inside attachments
       
   475                         attachmentPath = XQConversions::s60DescToQString(
       
   476                                 previewPathBuffer);
       
   477                         item.setData(attachmentPath, Attachments);
       
   478                         previewPathBuffer.Close();
       
   479                     }
       
   480                     
       
   481                     int msgProperty = 0;
       
   482                     msgProperty = sqlSelectStmt.ColumnInt(msgpropertyIndex);
       
   483                     item.setData(msgProperty, MessageProperty);
       
   484 
       
   485                     RSqlColumnReadStream stream;
       
   486                     //Get data from binary column BLOB
       
   487                     TInt err = stream.ColumnBinary(sqlSelectStmt,
       
   488                             previewIconIndex);
       
   489 
       
   490                     QCRITICAL_WRITE_FORMAT("Error from ColumnBinary()", err)
       
   491 
       
   492                     if (err == KErrNone)
       
   493                         {
       
   494                         CFbsBitmap *bitmap = new CFbsBitmap;
       
   495                         TRAPD(err,bitmap->InternalizeL(stream));
       
   496                         QCRITICAL_WRITE_FORMAT("Error from bitmap InternalizeL()", err)
       
   497 
       
   498                         //convert bitmap to pixmap
       
   499                         if (err == KErrNone)
       
   500                             {
       
   501                             TSize size = bitmap->SizeInPixels();
       
   502                             int bytesPerLine = bitmap->ScanLineLength(
       
   503                                     size.iWidth, bitmap->DisplayMode());
       
   504                             const uchar* dataPtr =
       
   505                                     (const uchar*) bitmap->DataAddress();
       
   506 
       
   507                             QPixmap pixmap = QPixmap::fromImage(QImage(
       
   508                                     dataPtr, size.iWidth, size.iHeight,
       
   509                                     bytesPerLine, QImage::Format_RGB16));
       
   510 
       
   511                             setPreviewIcon(pixmap, attachmentPath, msgId,
       
   512                                     true);
       
   513 
       
   514                             }
       
   515                         //remove bitmap
       
   516                         delete bitmap;
       
   517                         }
       
   518 
       
   519                     //set flag to disable fallback option
       
   520                     isEntryInDb = true;
       
   521                     }
       
   522                 }
       
   523             }
       
   524         sqlSelectStmt.Close();
       
   525         }
       
   526 
       
   527     //fallback option incase of db operation failure or enry not found in DB
       
   528     //populate from data plugins
       
   529     if (!isEntryInDb || err != KErrNone)
       
   530     {
       
   531         int error = iMmsDataPlugin->setMessageId(entry.EntryId());
       
   532         if(error != KErrNone)
       
   533         {
       
   534             // skip all
       
   535             return;
       
   536         }
       
   537         int msgProperty = 0;
       
   538 
       
   539         if (iMmsDataPlugin->attachmentCount() > 0)
       
   540         {
       
   541             msgProperty |= EPreviewAttachment;
       
   542         }
       
   543 
       
   544         if(validateMsgForForward(entry.EntryId()))
       
   545         {
       
   546             msgProperty |= EPreviewForward;
       
   547         }
       
   548 
       
   549         //subject
       
   550         item.setData(iMmsDataPlugin->subject(), Subject);
       
   551 
       
   552         int slideCount = iMmsDataPlugin->slideCount();
       
   553         bool isBodyTextSet = false;
       
   554         bool isAudioSet = false;
       
   555         bool isImageSet = false;
       
   556         bool isVideoSet = false;
       
   557         QString textContent;
       
   558         QString videoPath;
       
   559         QString imagePath;
       
   560 
       
   561         for (int i = 0; i < slideCount; ++i)
       
   562         {
       
   563             UniMessageInfoList objectList = iMmsDataPlugin->slideContent(i);
       
   564             for (int index = 0; index < objectList.count(); ++index)
       
   565             {
       
   566                 if (!isBodyTextSet && objectList[index]->mimetype().contains(
       
   567                     "text"))
       
   568                 {
       
   569                     QFile file(objectList[index]->path());
       
   570                     file.open(QIODevice::ReadOnly);
       
   571                     QByteArray textArray;
       
   572                     textArray = file.readAll();
       
   573                     char *data = new char[textArray.size()+1];
       
   574                     strcpy(data,textArray.data());
       
   575                     //This is needed since MMS text content 
       
   576                     //is stored in UTF8 format
       
   577                     textContent = textContent.fromUtf8(data,strlen(data));
       
   578                     delete []data;
       
   579                     item.setData(textContent, BodyText);
       
   580                     isBodyTextSet = true;
       
   581                     file.close();
       
   582                 }
       
   583                 if (!isVideoSet && !isImageSet && objectList[index]->mimetype().contains(
       
   584                     "image"))
       
   585                 {
       
   586                     isImageSet = true;
       
   587                     msgProperty |= EPreviewImage;
       
   588                     if (objectList[index]->isProtected())
       
   589                     {
       
   590                         msgProperty |= EPreviewProtectedImage;
       
   591                     }
       
   592                     if (objectList[index]->isCorrupted())
       
   593                     {
       
   594                         msgProperty |= EPreviewCorruptedImage;
       
   595                     }
       
   596                     imagePath = objectList[index]->path();
       
   597                 }
       
   598                 if (!isVideoSet && !isAudioSet && objectList[index]->mimetype().contains(
       
   599                     "audio"))
       
   600                 {
       
   601                     msgProperty |= EPreviewAudio;
       
   602                     if (objectList[index]->isProtected())
       
   603                     {
       
   604                         msgProperty |= EPreviewProtectedAudio;
       
   605                     }
       
   606                     if (objectList[index]->isCorrupted())
       
   607                     {
       
   608                         msgProperty |= EPreviewCorruptedAudio;
       
   609                     }
       
   610                     isAudioSet = true;
       
   611                 }
       
   612                 if (!( isImageSet || isAudioSet) && !isVideoSet && objectList[index]->mimetype().contains(
       
   613                     "video"))
       
   614                 {
       
   615                     isVideoSet = true;
       
   616                     msgProperty |= EPreviewVideo;
       
   617                     if (objectList[index]->isProtected())
       
   618                     {
       
   619                         msgProperty |= EPreviewProtectedVideo;
       
   620                     }
       
   621                     if (objectList[index]->isCorrupted())
       
   622                     {
       
   623                         msgProperty |= EPreviewCorruptedVideo;
       
   624                     }
       
   625                     videoPath = objectList[index]->path();
       
   626                 }
       
   627             }
       
   628             foreach(UniMessageInfo* slide,objectList)
       
   629                 {
       
   630                     delete slide;
       
   631                 }
       
   632         }
       
   633         QPixmap pixmap;
       
   634         //populate item  with the attachment list
       
   635         //TODO: This code is not required bcoz video icon is show and not preview  
       
   636         if (isVideoSet)
       
   637         {
       
   638             item.setData(videoPath, Attachments);
       
   639             // Store thumbnail only for non protected, non corrupted content.
       
   640             if (!(EPreviewProtectedVideo & msgProperty) &&
       
   641                 !(EPreviewCorruptedVideo & msgProperty))
       
   642             {
       
   643                 setPreviewIcon(pixmap, videoPath, msgId, false);
       
   644             }
       
   645         }
       
   646         else if (isImageSet)
       
   647         {
       
   648             item.setData(imagePath, Attachments);
       
   649             // Store thumbnail only for non protected, non corrupted content.
       
   650             if (!(EPreviewProtectedImage & msgProperty) &&
       
   651                 !(EPreviewCorruptedImage & msgProperty))
       
   652             {
       
   653                 setPreviewIcon(pixmap, imagePath, msgId, false);
       
   654             }
       
   655         }
       
   656         //populate msgProperty
       
   657         item.setData(msgProperty, MessageProperty);
       
   658     }
       
   659 
       
   660     // fill other attributes
       
   661     if (entry.IsAttributeSet(ECsAttributeHighPriority))
       
   662     {
       
   663         item.setData(ConvergedMessage::High, MessagePriority);
       
   664     }
       
   665     else if (entry.IsAttributeSet(ECsAttributeLowPriority))
       
   666     {
       
   667         item.setData(ConvergedMessage::Low, MessagePriority);
       
   668     }
       
   669 }
       
   670 
       
   671 //---------------------------------------------------------------
       
   672 // ConversationsModel::handleMMSNotification
       
   673 // @see header
       
   674 //---------------------------------------------------------------
       
   675 void ConversationsModel::handleMMSNotification(QStandardItem& item,
       
   676     const CCsConversationEntry& entry)
       
   677 {
       
   678     // set context to current entry
       
   679     TRAPD(err, mMsgStoreHandler->setNotificationMessageIdL(entry.EntryId()));
       
   680     if(err != KErrNone)
       
   681     {
       
   682         return;
       
   683     }
       
   684 
       
   685     // fetch relevent info to show in CV
       
   686     // notification state e.g. waiting, retrieving etc
       
   687     QString statusStr;
       
   688     int status;
       
   689     mMsgStoreHandler->NotificationStatus(status, statusStr);
       
   690 
       
   691     // create data for bodytext role
       
   692     QString dataText;
       
   693     dataText.append(mMsgStoreHandler->NotificationMsgSize());
       
   694     dataText.append(QChar::LineSeparator);
       
   695     dataText.append(mMsgStoreHandler->NotificationClass());
       
   696     dataText.append(QChar::LineSeparator);
       
   697     dataText.append(mMsgStoreHandler->NotificationExpiryDate());
       
   698     if(!statusStr.isEmpty())
       
   699     {
       
   700         dataText.append(QChar::LineSeparator);
       
   701         dataText.append(statusStr);
       
   702     }
       
   703 
       
   704     // set fetched data to roles
       
   705     item.setData(status, NotificationStatus);
       
   706     item.setData(dataText, BodyText);
       
   707 
       
   708     if (entry.IsAttributeSet(ECsAttributeHighPriority)) {
       
   709         item.setData(ConvergedMessage::High, MessagePriority);
       
   710     }
       
   711     else if (entry.IsAttributeSet(ECsAttributeLowPriority)) {
       
   712         item.setData(ConvergedMessage::Low, MessagePriority);
       
   713     }
       
   714 }
       
   715 
       
   716 //---------------------------------------------------------------
       
   717 // ConversationsModel::handleBlueToothMessages
       
   718 // @see header
       
   719 //---------------------------------------------------------------
       
   720 void ConversationsModel::handleBlueToothMessages(QStandardItem& item,
       
   721     const CCsConversationEntry& entry)
       
   722     {
       
   723     int msgSubType = ConversationsEngineUtility::messageSubType(
       
   724             entry.GetType());
       
   725     
       
   726     if (msgSubType == ConvergedMessage::VCard)
       
   727         {
       
   728         handleVCard(item, entry.EntryId());
       
   729         }
       
   730     else
       
   731         {
       
   732         QString description = XQConversions::s60DescToQString(
       
   733                 *(entry.Description()));
       
   734 
       
   735         if (msgSubType == ConvergedMessage::VCal) // "vCalendar"
       
   736             {
       
   737             //message sub-type
       
   738             item.setData(ConvergedMessage::VCal, MessageSubType);
       
   739             }
       
   740         else
       
   741             {
       
   742             //message sub-type
       
   743             item.setData(ConvergedMessage::None, MessageSubType);
       
   744             }
       
   745         //for BT messages we show filenames for all other (except vcard) messages
       
   746         //get filename and set as body
       
   747         QFileInfo fileinfo(description);
       
   748         QString filename = fileinfo.fileName();
       
   749         item.setData(filename, BodyText);
       
   750         }
       
   751     }
       
   752 
       
   753 //---------------------------------------------------------------
       
   754 // ConversationsModel::handleBioMessages
       
   755 // @see header
       
   756 //---------------------------------------------------------------
       
   757 void ConversationsModel::handleBioMessages(QStandardItem& item, const CCsConversationEntry& entry)
       
   758 {
       
   759     int msgSubType = ConversationsEngineUtility::messageSubType(entry.GetType());
       
   760     if (ConvergedMessage::VCard == msgSubType)
       
   761         {
       
   762         handleVCard(item, entry.EntryId());
       
   763         }
       
   764     else if (ConvergedMessage::VCal == msgSubType) {
       
   765         //not supported
       
   766     }
       
   767     else if (ConvergedMessage::RingingTone == msgSubType) {
       
   768         iBioMsgPlugin->setMessageId(entry.EntryId());
       
   769         if (iBioMsgPlugin->attachmentCount() > 0) {
       
   770             UniMessageInfoList attList = iBioMsgPlugin->attachmentList();
       
   771             QString attachmentPath = attList[0]->path();
       
   772 
       
   773             //get tone title, and set as bodytext
       
   774             RingBc ringBc;
       
   775             item.setData(ringBc.toneTitle(attachmentPath), BodyText);
       
   776             while (!attList.isEmpty()) {
       
   777                 delete attList.takeFirst();
       
   778             }
       
   779         }
       
   780 
       
   781     }
       
   782     else {
       
   783         // description
       
   784         HBufC* description = entry.Description();
       
   785         QString subject("");
       
   786         if (description && description->Length()) {
       
   787             subject = (XQConversions::s60DescToQString(*description));
       
   788             item.setData(subject, BodyText);
       
   789         }
       
   790     }
       
   791 }
       
   792 
       
   793 //---------------------------------------------------------------
       
   794 // ConversationsModel::getDBHandle()
       
   795 // @see header
       
   796 //---------------------------------------------------------------
       
   797 RSqlDatabase& ConversationsModel::getDBHandle(TBool& isOpen)
       
   798 {
       
   799     isOpen = iSqlDbOpen;
       
   800     return iSqlDb;
       
   801 }
       
   802 
       
   803 //---------------------------------------------------------------
       
   804 // ConversationsModel::setPreviewIcon()
       
   805 // @see header
       
   806 //---------------------------------------------------------------
       
   807 void ConversationsModel::setPreviewIcon(QPixmap& pixmap, QString& filePath,
       
   808     int msgId, bool inDb)
       
   809 {
       
   810 
       
   811     //Since the population happens in reverse this check is needed so that
       
   812     //most recent items have their icons present in cache
       
   813     if (previewIconCache.totalCost() >= previewIconCache.maxCost())
       
   814         return;
       
   815 
       
   816     // if not found in db, set from file path
       
   817     if (!inDb)
       
   818     {
       
   819         QPixmap pixmap(filePath);
       
   820         QPixmap scaledPixmap = pixmap.scaled(KWidth, KHeight, Qt::IgnoreAspectRatio);
       
   821         HbIcon *previewIcon = new HbIcon(scaledPixmap);
       
   822 
       
   823         previewIconCache.insert(msgId, previewIcon);
       
   824 
       
   825     }
       
   826     else
       
   827     {
       
   828         HbIcon *previewIcon = new HbIcon(pixmap);
       
   829         previewIconCache.insert(msgId, previewIcon);
       
   830     }
       
   831 }
       
   832 
       
   833 //---------------------------------------------------------------
       
   834 // ConversationsModel::getPreviewIconItem()
       
   835 // @see header
       
   836 //---------------------------------------------------------------
       
   837 HbIcon* ConversationsModel::getPreviewIconItem(int msgId,
       
   838     QString& filepath) const
       
   839 {
       
   840     QCRITICAL_WRITE("ConversationsModel::getPreviewIconItem start.")
       
   841 
       
   842     //Initialize icon from the Cache will be NULL if Item not present
       
   843     HbIcon* previewIcon = previewIconCache[msgId];
       
   844     if (!previewIcon)
       
   845     {
       
   846         //This is done in this way as non-const function call cant be done here
       
   847         emit retrievePreviewIcon(msgId, filepath);
       
   848 
       
   849         previewIcon = previewIconCache[msgId];
       
   850     }
       
   851 
       
   852     QCRITICAL_WRITE("ConversationsModel::getPreviewIconItem start.")
       
   853 
       
   854     return previewIcon;
       
   855 }
       
   856 
       
   857 //---------------------------------------------------------------
       
   858 // ConversationsModel::updatePreviewIcon()
       
   859 // @see header
       
   860 //---------------------------------------------------------------
       
   861 void ConversationsModel::updatePreviewIcon(int msgId, QString& filePath)
       
   862 {
       
   863     QCRITICAL_WRITE("ConversationsModel::updatePreviewIcon start.")
       
   864 
       
   865     //sql query to get preview-icon from DB
       
   866     bool imagePreviewed = false;
       
   867     QPixmap pixmap;
       
   868 
       
   869     if (iSqlDbOpen)
       
   870     {
       
   871         RSqlStatement sqlSelectPreviewIconStmt;
       
   872         TInt err = sqlSelectPreviewIconStmt.Prepare(iSqlDb,
       
   873             KSelectPreviewIconStmt);
       
   874 
       
   875         QCRITICAL_WRITE_FORMAT("Error from Prepare()", err)
       
   876 
       
   877         if (err == KErrNone)
       
   878         {
       
   879             //msg_id
       
   880             TInt msgIdIndex = sqlSelectPreviewIconStmt.ParameterIndex(
       
   881                 _L(":message_id"));
       
   882             sqlSelectPreviewIconStmt.BindInt(msgIdIndex, msgId);
       
   883 
       
   884             // get preview-icon from DB
       
   885             err = sqlSelectPreviewIconStmt.Next();
       
   886             QCRITICAL_WRITE_FORMAT("Error from Next()", err)
       
   887 
       
   888             if (err == KSqlAtRow)
       
   889             {
       
   890                 TInt previewIconIndex = sqlSelectPreviewIconStmt.ColumnIndex(
       
   891                     _L("preview_icon"));
       
   892 
       
   893                 RSqlColumnReadStream stream;
       
   894 
       
   895                 //Get data from binary column BLOB
       
   896                 err = stream.ColumnBinary(sqlSelectPreviewIconStmt,
       
   897                     previewIconIndex);
       
   898 
       
   899                 QCRITICAL_WRITE_FORMAT("Error from ColumnBinary()", err)
       
   900 
       
   901                 if (err == KErrNone)
       
   902                 {
       
   903                     CFbsBitmap *bitmap = new CFbsBitmap;
       
   904                     TRAPD(err,bitmap->InternalizeL(stream));
       
   905                     QCRITICAL_WRITE_FORMAT("Error from bitmap InternalizeL()", err)
       
   906 
       
   907                     //convert bitmap to pixmap
       
   908                     if (err == KErrNone)
       
   909                     {
       
   910                         TSize size = bitmap->SizeInPixels();
       
   911                         int bytesPerLine = bitmap->ScanLineLength(size.iWidth,
       
   912                             bitmap->DisplayMode());
       
   913                         const uchar* dataPtr =
       
   914                                 (const uchar*) bitmap->DataAddress();
       
   915 
       
   916                         pixmap = QPixmap::fromImage(QImage(dataPtr,
       
   917                             size.iWidth, size.iHeight, bytesPerLine,
       
   918                             QImage::Format_RGB16));
       
   919 
       
   920                         imagePreviewed = true;
       
   921 
       
   922                         QCRITICAL_WRITE("Bitmap Conversion completed")
       
   923                     }
       
   924                     //remove bitmap
       
   925                     delete bitmap;
       
   926                 }
       
   927                 //close stream
       
   928                 stream.Close();
       
   929             }
       
   930         }
       
   931         sqlSelectPreviewIconStmt.Close();
       
   932     }
       
   933 
       
   934     // if not found in db, set from file path
       
   935     if (!imagePreviewed)
       
   936     {
       
   937         QPixmap orgPixmap(filePath);
       
   938         pixmap = orgPixmap.scaled(63.65, 63.65, Qt::IgnoreAspectRatio);
       
   939     }
       
   940     HbIcon * previewIcon = new HbIcon(pixmap);
       
   941 
       
   942     previewIconCache.insert(msgId, previewIcon);
       
   943 
       
   944     QCRITICAL_WRITE("ConversationsModel::updatePreviewIcon end.")
       
   945 
       
   946 }
       
   947 
       
   948 //---------------------------------------------------------------
       
   949 // ConversationsModel::handleVCard()
       
   950 // @see header
       
   951 //---------------------------------------------------------------
       
   952 void ConversationsModel::handleVCard(QStandardItem& item, int msgId)
       
   953     {
       
   954     //sql query to get vcard-path from DB
       
   955     bool vCardParsed = false;
       
   956 
       
   957     if (iSqlDbOpen)
       
   958         {
       
   959         RSqlStatement sqlSelectVcardStmt;
       
   960         TInt err = sqlSelectVcardStmt.Prepare(iSqlDb, KSelectVCardStmt);
       
   961 
       
   962         QCRITICAL_WRITE_FORMAT("Error from Prepare()", err)
       
   963 
       
   964         if (err == KErrNone)
       
   965             {
       
   966             //msg_id
       
   967             TInt msgIdIndex = sqlSelectVcardStmt.ParameterIndex(
       
   968                     _L(":message_id"));
       
   969             sqlSelectVcardStmt.BindInt(msgIdIndex, msgId);
       
   970             // state
       
   971             TInt msgProcessingStateIndex = sqlSelectVcardStmt.ColumnIndex(
       
   972                     _L("msg_processingstate"));
       
   973            
       
   974             // get vacrd-path from DB
       
   975             err = sqlSelectVcardStmt.Next();
       
   976             QCRITICAL_WRITE_FORMAT("Error from Next()", err)
       
   977 
       
   978             if (err == KSqlAtRow)
       
   979                 {
       
   980                 int msgProcessingState = 0;
       
   981                 msgProcessingState = sqlSelectVcardStmt.ColumnInt(
       
   982                         msgProcessingStateIndex);
       
   983                 if (msgProcessingState == EPreviewMsgProcessed)
       
   984                     {
       
   985                     //path-index
       
   986                     TInt previewPathIndex = sqlSelectVcardStmt.ColumnIndex(
       
   987                             _L("preview_path"));
       
   988 
       
   989                     //Get vcard-path data from path-index
       
   990                     RSqlColumnReadStream stream;
       
   991                     err = stream.ColumnBinary(sqlSelectVcardStmt,
       
   992                             previewPathIndex);
       
   993 
       
   994                     QCRITICAL_WRITE_FORMAT("Error from ColumnBinary()", err)
       
   995 
       
   996                     if (err == KErrNone)
       
   997                     {
       
   998                         RBuf vCardPathBuffer;
       
   999                         if (vCardPathBuffer.Create(
       
  1000                                 sqlSelectVcardStmt.ColumnSize(
       
  1001                                 previewPathIndex)) == KErrNone)
       
  1002                         {
       
  1003                             sqlSelectVcardStmt.ColumnText(
       
  1004                                     previewPathIndex,
       
  1005                                     vCardPathBuffer);
       
  1006 
       
  1007                             //set inside attachments
       
  1008                             QString attachmentPath(
       
  1009                                     XQConversions::s60DescToQString(
       
  1010                                             vCardPathBuffer));
       
  1011                             item.setData(attachmentPath, Attachments);
       
  1012 
       
  1013                             //get display-name and set as bodytext
       
  1014                             QString displayName =
       
  1015                                     MsgContactHandler::getVCardDisplayName(
       
  1016                                             attachmentPath);
       
  1017                             item.setData(displayName, BodyText);
       
  1018 
       
  1019                             vCardPathBuffer.Close();
       
  1020                             vCardParsed = true;
       
  1021                             
       
  1022                             QCRITICAL_WRITE("vcard parsing complete.")
       
  1023                         }
       
  1024                     }
       
  1025                     //close stream
       
  1026                     stream.Close();
       
  1027                     }
       
  1028                 }
       
  1029             }
       
  1030         sqlSelectVcardStmt.Close();
       
  1031         }
       
  1032 
       
  1033     // fallback, if not parsed in DB, parse from store
       
  1034     if (!vCardParsed)
       
  1035         {
       
  1036         iBioMsgPlugin->setMessageId(msgId);
       
  1037 
       
  1038         if (iBioMsgPlugin->attachmentCount() > 0)
       
  1039             {
       
  1040             UniMessageInfoList attList = iBioMsgPlugin->attachmentList();
       
  1041             QString attachmentPath = attList[0]->path();
       
  1042 
       
  1043             //get display-name and set as bodytext
       
  1044             QString displayName = MsgContactHandler::getVCardDisplayName(
       
  1045                     attachmentPath);
       
  1046             item.setData(displayName, BodyText);
       
  1047             item.setData(attachmentPath, Attachments);
       
  1048 
       
  1049             // clear attachement list : its allocated at data model
       
  1050             while (!attList.isEmpty())
       
  1051                 {
       
  1052                 delete attList.takeFirst();
       
  1053                 }
       
  1054             }
       
  1055         }
       
  1056     }
       
  1057 
       
  1058 //---------------------------------------------------------------
       
  1059 // ConversationsModel::clearModel()
       
  1060 // @see header
       
  1061 //---------------------------------------------------------------
       
  1062 void ConversationsModel::clearModel()
       
  1063 {
       
  1064     clear();
       
  1065     previewIconCache.clear();
       
  1066 }
       
  1067 
       
  1068 //---------------------------------------------------------------
       
  1069 // ConversationsModel::emitConversationViewEmpty()
       
  1070 // @see header
       
  1071 //---------------------------------------------------------------
       
  1072 void ConversationsModel:: emitConversationViewEmpty()
       
  1073 {
       
  1074     emit conversationViewEmpty();
       
  1075 }
       
  1076 //EOF