diff -r 139d4b7b2938 -r 99bcbff212ad emailuis/nmailuiengine/src/nmuiengine.cpp --- a/emailuis/nmailuiengine/src/nmuiengine.cpp Mon May 24 21:02:02 2010 +0300 +++ b/emailuis/nmailuiengine/src/nmuiengine.cpp Fri May 28 13:56:43 2010 +0300 @@ -27,15 +27,22 @@ NmUiEngine *NmUiEngine::mInstance; int NmUiEngine::mReferenceCount; +const QString syncIndicatorName = "com.nokia.hb.nmsyncindicator/1.0"; + /*! Constructor */ NmUiEngine::NmUiEngine() : mMailboxListModel(NULL), + mInboxListModel(NULL), mMessageListModel(NULL), mMessageSearchListModel(NULL), - mSendOperation(NULL) + mSendOperation(NULL), + mRemoveDraftOperation(NULL), + mSaveDraftOperation(NULL) { + NM_FUNCTION; + mPluginFactory = NmDataPluginFactory::instance(); mDataManager = new NmDataManager(); // Connect to the plugins to receive change notifications @@ -78,11 +85,16 @@ */ NmUiEngine::~NmUiEngine() { + NM_FUNCTION; + if (mMessageSearchListModel) { delete mMessageSearchListModel; mMessageSearchListModel = NULL; } - + if (mInboxListModel) { + delete mInboxListModel; + mInboxListModel = NULL; + } if (mMessageListModel) { delete mMessageListModel; mMessageListModel = NULL; @@ -107,6 +119,12 @@ if (mSendOperation && mSendOperation->isRunning()) { mSendOperation->cancelOperation(); } + if(mRemoveDraftOperation && mRemoveDraftOperation->isRunning()) { + mRemoveDraftOperation->cancelOperation(); + } + if(mSaveDraftOperation && mSaveDraftOperation->isRunning()) { + mSaveDraftOperation->cancelOperation(); + } } /*! @@ -114,6 +132,8 @@ */ NmUiEngine *NmUiEngine::instance() { + NM_FUNCTION; + if (!mInstance) { mInstance = new NmUiEngine(); } @@ -126,6 +146,8 @@ */ void NmUiEngine::releaseInstance(NmUiEngine *&instance) { + NM_FUNCTION; + //can't have passed out instances if we don't have any if (mInstance) { if(instance == mInstance) { @@ -145,6 +167,8 @@ */ NmMailboxListModel &NmUiEngine::mailboxListModel() { + NM_FUNCTION; + if (!mMailboxListModel) { refreshMailboxListModel(); // creates the model too } @@ -158,6 +182,8 @@ */ void NmUiEngine::refreshMailboxListModel() { + NM_FUNCTION; + if (!mMailboxListModel) { mMailboxListModel = new NmMailboxListModel(*mDataManager); @@ -191,40 +217,82 @@ NmMessageListModel &NmUiEngine::messageListModel(const NmId &mailboxId, const NmId &folderId) { - if (!mMessageListModel) { - mMessageListModel = new NmMessageListModel(*mDataManager); - } - else { - mMessageListModel->clear(); - } + NM_FUNCTION; QObject *plugin = mPluginFactory->pluginInstance(mailboxId); + bool isInbox(false); + if (standardFolderId(mailboxId,NmFolderInbox)==folderId){ + isInbox=true; + } + if (plugin) { + // Connect plugin message events to handler slot messageEventForListModel + QObject::connect(plugin, SIGNAL(messageEvent(NmMessageEvent, const NmId &, + const QList &, const NmId&)), + this, SLOT(messageEventForListModel(NmMessageEvent, + const NmId &, const QList &, const NmId&)), Qt::UniqueConnection ); + // Create inbox list model only once when entering to inbox for the first time + // or re-create inbox list model when mailbox has changed + if ((!mInboxListModel&&isInbox)|| + (mInboxListModel&&isInbox&&mailboxId!=mInboxListModel->currentMailboxId())){ + // Delete previous model and set to NULL. Deleting model will also + // delete all items in model. + if (mInboxListModel){ + delete mInboxListModel; + mInboxListModel=NULL; + } + // Create new inbox model + mInboxListModel = new NmMessageListModel(*mDataManager); + // Initial fill up of inbox list model, otherwise updated in the background + QList messageEnvelopeList; + mDataManager->listMessages(mailboxId, folderId, messageEnvelopeList); + mInboxListModel->refresh(mailboxId, folderId, messageEnvelopeList); - if (plugin) { - QObject::connect(plugin, - SIGNAL(messageEvent(NmMessageEvent, const NmId &, const QList &, const NmId&)), - mMessageListModel, - SLOT(handleMessageEvent(NmMessageEvent, const NmId &, const QList &)), - Qt::UniqueConnection ); + while (!messageEnvelopeList.isEmpty()) { + delete messageEnvelopeList.takeFirst(); + } + } + // Selected folder is not inbox folder for the mailbox + else if (!isInbox){ + // Recreate model for other folders when needed, previous model + // items are deleted from the memory with the old model + if (mMessageListModel){ + delete mMessageListModel; + mMessageListModel=NULL; + } + mMessageListModel = new NmMessageListModel(*mDataManager); + + // Fill up other model + QList messageEnvelopeList; + mDataManager->listMessages(mailboxId, folderId, messageEnvelopeList); + mMessageListModel->refresh(mailboxId, folderId, messageEnvelopeList); + while (!messageEnvelopeList.isEmpty()) { + delete messageEnvelopeList.takeFirst(); + } + } + } + + // Connect sync state changed + if (plugin){ QObject::connect( plugin, SIGNAL(syncStateEvent(NmSyncState, const NmOperationCompletionEvent &)), this, SLOT(handleSyncStateEvent(NmSyncState, const NmOperationCompletionEvent &)), Qt::UniqueConnection); - - // No need for mailbox event subscription here, already done in - // constructor. } - - QList messageEnvelopeList; - mDataManager->listMessages(mailboxId, folderId, messageEnvelopeList); - mMessageListModel->refresh(mailboxId, folderId, messageEnvelopeList); - - while (!messageEnvelopeList.isEmpty()) { - delete messageEnvelopeList.takeFirst(); + NmMessageListModel* ret(NULL); + if (isInbox){ + ret = mInboxListModel; + // Inbox list model is queried, other model is not + // needed anymore and memory should be freeded + if (mMessageListModel){ + delete mMessageListModel; + mMessageListModel=NULL; + } } - - return *mMessageListModel; + else { + ret = mMessageListModel; + } + return *ret; } @@ -237,6 +305,8 @@ */ NmMessageListModel &NmUiEngine::messageListModelForSearch(const NmId &mailboxId) { + NM_FUNCTION; + Q_UNUSED(mailboxId); if (!mMessageSearchListModel) { @@ -251,9 +321,9 @@ if (plugin) { QObject::connect(plugin, - SIGNAL(messageEvent(NmMessageEvent, const NmId &, const QList &, const NmId&)), + SIGNAL(messageEvent(NmMessageEvent, const NmId &, const QList &, const NmId &)), mMessageSearchListModel, - SLOT(handleMessageEvent(NmMessageEvent, const NmId &, const QList &)), + SLOT(handleMessageEvent(NmMessageEvent, const NmId &, const QList &, const NmId &)), Qt::UniqueConnection); } @@ -273,6 +343,8 @@ const NmId &mailboxId, NmFolderType folderType) { + NM_FUNCTION; + NmId value; if (folderType != NmFolderOther) { NmDataPluginInterface *plugin = @@ -293,6 +365,8 @@ const NmId &folderId, const NmId &messageId) { + NM_FUNCTION; + NmMessage *message = mDataManager->message(mailboxId, folderId, messageId); return message; } @@ -304,7 +378,8 @@ const NmId &folderId, const NmId &messageId ) { - NMLOG("NmUiEngine::fetchMessage() <---"); + NM_FUNCTION; + QPointer value(NULL); NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); @@ -323,7 +398,8 @@ const NmId &messageId, const NmId &messagePartId) { - NMLOG("NmUiEngine::fetchMessagePart() <---"); + NM_FUNCTION; + QPointer value(NULL); NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); @@ -342,7 +418,8 @@ const NmId &messageId, const QList &messagePartIds) { - NMLOG("NmUiEngine::fetchMessageParts() <---"); + NM_FUNCTION; + QPointer value(NULL); NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); @@ -361,6 +438,8 @@ const NmId &messageId, const NmId &messagePartId) { + NM_FUNCTION; + NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); if (plugin) { @@ -380,33 +459,70 @@ const NmId &messageId, NmMessagePart &messagePart) { + NM_FUNCTION; + return mDataManager->contentToMessagePart(mailboxId, folderId, messageId, messagePart); } + /*! - Deletes messages from model and routes call to plugin + Deletes messages from the model and forwards the call to plugin. + + \param mailboxId The ID of the mailbox which contains the deleted message(s). + \param folderId The ID of the folder which contains the deleted message(s). + \param messageIdList A list containing the IDs of the message to be deleted. + + \return A possible error code (returned by the plugin). */ -int NmUiEngine::deleteMessages( - const NmId &mailboxId, - const NmId &folderId, - const QList &messageIdList) +int NmUiEngine::deleteMessages(const NmId &mailboxId, + const NmId &folderId, + const QList &messageIdList) { + NM_FUNCTION; + int result(NmNotFoundError); - if (mMessageListModel) { - mMessageListModel->handleMessageEvent(NmMessageDeleted, folderId, messageIdList); + + bool isInbox(false); + if (standardFolderId(mailboxId,NmFolderInbox)==folderId){ + isInbox=true; + } + if (isInbox&&mInboxListModel){ + mInboxListModel->handleMessageEvent(NmMessageDeleted, folderId, + messageIdList, mailboxId); + } + else if (mMessageListModel) { + mMessageListModel->handleMessageEvent(NmMessageDeleted, folderId, + messageIdList, mailboxId); } + + // If the search list model exists and contains message, remove the + // message from it too. + if (mMessageSearchListModel && mMessageSearchListModel->rowCount()) { + mMessageSearchListModel->handleMessageEvent(NmMessageDeleted, folderId, + messageIdList, mailboxId); + } + NmDataPluginInterface *plugin = - mPluginFactory->interfaceInstance(mailboxId); + mPluginFactory->interfaceInstance(mailboxId); + if (plugin) { - result = plugin->deleteMessages( - mailboxId, folderId, messageIdList); + result = plugin->deleteMessages(mailboxId, folderId, messageIdList); } + return result; } + /*! - Sets envelope property given in argument. - Operation is automatically deleted after completion or cancelling. + Sets the envelope property for the given envelopes. + The operation is automatically deleted after the completion or cancelling. + + \param mailboxId The ID of the mailbox containing the envelope(s). + \param folderId The ID of the folder containing the envelope(s). + \param property The property to set. + \param envelopeList The list containing the envelopes. + + \return The constructed operation. */ QPointer NmUiEngine::setEnvelopes( const NmId &mailboxId, @@ -414,26 +530,42 @@ NmEnvelopeProperties property, const QList &envelopeList) { - NMLOG("NmUiEngine::setEnvelopes() <---"); + NM_FUNCTION; + QPointer operation(NULL); - if (mMessageListModel && envelopeList.count()) { + NmMessageListModel *theMessageListModel = mMessageListModel; + + if (!theMessageListModel) { + theMessageListModel = &messageListModel(mailboxId, folderId); + } + + if (theMessageListModel && envelopeList.count()) { QList messageIdList; for (int i(0); i < envelopeList.count(); i++){ messageIdList.append(envelopeList[i]->messageId()); } - mMessageListModel->setEnvelopeProperties( - property, messageIdList); - // Store new envelopes to plugin + + theMessageListModel->setEnvelopeProperties(property, messageIdList); + + if (mMessageSearchListModel && mMessageSearchListModel->rowCount()) { + // Update the envelopes in the search list model as well. + mMessageSearchListModel->setEnvelopeProperties(property, + messageIdList); + } + + // Store the new envelopes to plugin. NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); + if (plugin) { - operation = plugin->storeEnvelopes( - mailboxId, folderId, envelopeList); + operation = + plugin->storeEnvelopes(mailboxId, folderId, envelopeList); } + messageIdList.clear(); - } - NMLOG("NmUiEngine::setEnvelopes() --->"); + } + return operation; } @@ -467,7 +599,8 @@ */ QPointer NmUiEngine::createNewMessage(const NmId &mailboxId) { - NMLOG("NmUiEngine::createNewMessage() <---"); + NM_FUNCTION; + QPointer value(NULL); NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); @@ -485,7 +618,8 @@ const NmId &mailboxId, const NmId &originalMessageId) { - NMLOG("NmUiEngine::createForwardMessage() <---"); + NM_FUNCTION; + QPointer value(NULL); NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); @@ -504,7 +638,8 @@ const NmId &originalMessageId, bool replyAll) { - NMLOG("NmUiEngine::createReplyMessage() <---"); + NM_FUNCTION; + QPointer value(NULL); NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); @@ -519,6 +654,8 @@ */ int NmUiEngine::saveMessage(const NmMessage &message) { + NM_FUNCTION; + const NmId &mailboxId = message.envelope().mailboxId(); int ret(NmNotFoundError); NmDataPluginInterface *plugin = @@ -534,11 +671,17 @@ */ int NmUiEngine::refreshMailbox(const NmId &mailboxId ) { + NM_FUNCTION; + int ret(NmNotFoundError); NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); if (plugin) { ret = plugin->refreshMailbox(mailboxId); + if (NmNoError == ret) { + HbIndicator indicator; + indicator.activate(syncIndicatorName, QVariant()); + } } return ret; } @@ -548,6 +691,8 @@ */ int NmUiEngine::goOnline(const NmId &mailboxId ) { + NM_FUNCTION; + int ret(NmNotFoundError); NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); @@ -562,6 +707,8 @@ */ int NmUiEngine::goOffline(const NmId &mailboxId ) { + NM_FUNCTION; + int ret(NmNotFoundError); NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); @@ -580,6 +727,8 @@ const NmId &folderId, const NmId &messageId) { + NM_FUNCTION; + int result(NmNotFoundError); NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); @@ -591,10 +740,83 @@ /*! + Handles draft message deletion after editor has closed, takes ownership of message. + */ +void NmUiEngine::removeDraftMessage(NmMessage *message) +{ + NM_FUNCTION; + + if (message) { + NmDataPluginInterface *plugin = + mPluginFactory->interfaceInstance(message->envelope().mailboxId()); + + if (plugin) { + // to be on the safer side: + // we shouldn't even be here if mRemoveDraftOperation != NULL + if (mRemoveDraftOperation && mRemoveDraftOperation->isRunning()) { + mRemoveDraftOperation->cancelOperation(); + } + // ownership of message changes + mRemoveDraftOperation = plugin->removeDraftMessage(message); + + if (mRemoveDraftOperation) { + connect(mRemoveDraftOperation, + SIGNAL(operationCompleted(int)), + this, + SLOT(handleCompletedRemoveDraftOperation())); + } + } + } +} + +/*! + Handles draft message saving after editor has closed, takes ownership of message. + */ +void NmUiEngine::saveDraftMessage(NmMessage *message, + const QList &preliminaryOperations) +{ + NM_FUNCTION; + + if (message) { + NmDataPluginInterface *plugin = + mPluginFactory->interfaceInstance(message->envelope().mailboxId()); + + if (plugin) { + // to be on the safer side: + // we shouldn't even be here if mSaveDraftOperation != NULL + if (mSaveDraftOperation && mSaveDraftOperation->isRunning()) { + mSaveDraftOperation->cancelOperation(); + } + // ownership of message changes + mSaveDraftOperation = plugin->saveMessageWithSubparts(*message); + // don't put this to mOperations as we need to handle this + // operation separately + if (mSaveDraftOperation) { + for (int i(0); i < preliminaryOperations.count(); i++ ) { + QPointer op = preliminaryOperations[i]; + mSaveDraftOperation->addPreliminaryOperation(op); + } + + connect(mSaveDraftOperation, + SIGNAL(operationCompleted(int)), + this, + SLOT(handleCompletedSaveDraftOperation())); + + // message object is not needed any more, so delete it + delete message; + message = NULL; + } + } + } +} + +/*! Sends the given message. */ void NmUiEngine::sendMessage(NmMessage *message, const QList &preliminaryOperations) { + NM_FUNCTION; + //First trigger message storing if (message) { NmDataPluginInterface *plugin = @@ -630,6 +852,8 @@ */ bool NmUiEngine::isSendingMessage() const { + NM_FUNCTION; + int ret(false); if (mSendOperation && mSendOperation->isRunning()) { ret = true; @@ -642,6 +866,8 @@ */ const NmMessage *NmUiEngine::messageBeingSent() const { + NM_FUNCTION; + const NmMessage *message = NULL; if (mSendOperation != NULL) { @@ -659,7 +885,8 @@ const NmMessage &message, const QList &fileList) { - NMLOG("NmUiEngine::addAttachments() <---"); + NM_FUNCTION; + NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(message.envelope().mailboxId()); @@ -678,7 +905,8 @@ const NmMessage &message, const NmId &attachmentPartId) { - NMLOG("NmUiEngine::removeAttachments() <---"); + NM_FUNCTION; + NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(message.envelope().mailboxId()); @@ -690,26 +918,12 @@ } /*! - Operation is automatically deleted after completion or cancelling. - */ -QPointer NmUiEngine::checkOutbox(const NmId &mailboxId) -{ - NMLOG("NmUiEngine::checkOutbox() <---"); - NmDataPluginInterface *plugin = - mPluginFactory->interfaceInstance(mailboxId); - - QPointer ret(NULL); - if (plugin) { - ret = plugin->checkOutbox(mailboxId); - } - return ret; -} - -/*! Returns the current sync state of the mailbox */ NmSyncState NmUiEngine::syncState(const NmId& mailboxId) { + NM_FUNCTION; + NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); if (plugin) { @@ -725,6 +939,8 @@ */ NmConnectState NmUiEngine::connectionState(const NmId& mailboxId) { + NM_FUNCTION; + NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); if (plugin) { @@ -747,6 +963,8 @@ int NmUiEngine::search(const NmId &mailboxId, const QStringList &searchStrings) { + NM_FUNCTION; + // Get the plugin instance. QObject *pluginInstance = mPluginFactory->pluginInstance(mailboxId); @@ -789,6 +1007,8 @@ */ int NmUiEngine::cancelSearch(const NmId &mailboxId) { + NM_FUNCTION; + int retVal(NmNoError); // Get the plugin interface. @@ -806,7 +1026,9 @@ \return Folder type */ NmFolderType NmUiEngine::folderTypeById(NmId mailboxId, NmId folderId) -{ +{ + NM_FUNCTION; + NmFolderType ret(NmFolderInbox); if (mDataManager){ ret = mDataManager->folderTypeById(mailboxId,folderId); @@ -821,6 +1043,8 @@ */ void NmUiEngine::updateActiveFolder(const NmId &mailboxId, const NmId &folderId) { + NM_FUNCTION; + NmApplicationStateInterface *interface = mPluginFactory->applicationStateInterfaceInstance(mailboxId); if (interface) { @@ -833,20 +1057,43 @@ */ void NmUiEngine::handleCompletedSendOperation() { - NMLOG("NmUiEngine::handleCompletedSendOperation()"); + NM_FUNCTION; + emit sendOperationCompleted(); } /*! + Handle completed remove draft operation. +*/ +void NmUiEngine::handleCompletedRemoveDraftOperation() +{ + NM_FUNCTION; + + // draft message deletion observing not yet implemented... +} + +/*! + Handle completed save draft operation. +*/ +void NmUiEngine::handleCompletedSaveDraftOperation() +{ + NM_FUNCTION; + + // draft message saving observing not yet implemented... +} + +/*! Handles synch operation related events */ void NmUiEngine::handleSyncStateEvent(NmSyncState syncState, const NmOperationCompletionEvent &event) { - NMLOG("NmUiEngine::handleSyncStateEvent()"); - + NM_FUNCTION; + if ( syncState == SyncComplete ) { // signal for reporting about (sync) operation completion status emit operationCompleted(event); + HbIndicator indicator; + indicator.deactivate(syncIndicatorName, QVariant()); } // signal for handling sync state icons @@ -862,6 +1109,8 @@ const QList &messageIds, const NmId& mailboxId) { + NM_FUNCTION; + switch (event) { case NmMessageDeleted: { @@ -882,6 +1131,8 @@ void NmUiEngine::handleMailboxEvent(NmMailboxEvent event, const QList &mailboxIds) { + NM_FUNCTION; + switch (event) { case NmMailboxDeleted: { @@ -904,26 +1155,59 @@ */ void NmUiEngine::handleMatchFound(const NmId &messageId, const NmId &folderId) { + NM_FUNCTION; + if (!mMessageSearchListModel) { // No search list model! return; } - // Add the found message into the search model. - QList messageIdList; - messageIdList.append(messageId); + // Resolve the folder type. + NmId mailboxId = mMessageSearchListModel->currentMailboxId(); + NmFolderType folderType = folderTypeById(mailboxId, folderId); - mMessageSearchListModel->handleMessageEvent(NmMessageFound, - folderId, - messageIdList); + // Do not display matches from outbox or draft folders. + if (folderType != NmFolderOutbox && folderType != NmFolderDrafts) { + // Add the found message into the search model. + QList messageIdList; + messageIdList.append(messageId); + + mMessageSearchListModel->handleMessageEvent(NmMessageFound, folderId, + messageIdList, mailboxId); + } } +/*! + Function sens events from plugin to both models. Inbox model for + active mailbox is always alove whereas mMessageListModel can represent + other folder in the device (sent, outbox, drafts, etc.) +*/ +void NmUiEngine::messageEventForListModel(NmMessageEvent event, + const NmId &folderId, + const QList &messageIds, + const NmId& mailboxId) +{ + NM_FUNCTION; + + // Forward event to both list models. Models will take care of checking + // whether event really belongs to current mailbox & folder + if (mInboxListModel){ + mInboxListModel->handleMessageEvent(event, folderId, + messageIds, mailboxId); + } + if (mMessageListModel){ + mMessageListModel->handleMessageEvent(event, folderId, + messageIds, mailboxId); + } +} /*! receives events when going online, and offline. */ void NmUiEngine::handleConnectEvent(NmConnectState connectState, const NmId &mailboxId, const int errorCode) { + NM_FUNCTION; + // signal for connection state icon handling emit connectionEvent(connectState, mailboxId);