emailuis/nmailuiengine/src/nmuiengine.cpp
changeset 18 578830873419
child 20 ecc8def7944a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailuis/nmailuiengine/src/nmuiengine.cpp	Fri Apr 16 14:51:52 2010 +0300
@@ -0,0 +1,699 @@
+/*
+* 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 "nmuiengineheaders.h"
+
+/*!
+    \class NmUiEngine
+    \brief NmUiEngine provides a controller-type services for the email UI.
+
+*/
+
+NmUiEngine *NmUiEngine::mInstance;
+int NmUiEngine::mReferenceCount;
+
+/*!
+    Constructor
+*/
+NmUiEngine::NmUiEngine() 
+:mMailboxListModel(NULL),
+mMessageListModel(NULL),
+mSendOperation(NULL),
+mSaveOperation(NULL),
+mMessageToBeSent(false),
+mMessage(NULL)
+{
+    mPluginFactory = NmDataPluginFactory::instance();
+    mDataManager = new NmDataManager();
+}
+
+
+/*!
+    Destructor
+*/
+NmUiEngine::~NmUiEngine()
+{
+    if (mMessageListModel) {
+        delete mMessageListModel;
+        mMessageListModel = NULL;
+    }
+    if (mMailboxListModel) {
+        delete mMailboxListModel;
+        mMailboxListModel = NULL;
+    }
+    NmDataPluginFactory::releaseInstance(mPluginFactory);
+    delete mDataManager;
+    
+    while (!mOperations.isEmpty()) {
+        delete mOperations.takeLast();
+    }
+    
+    delete mSendOperation;
+    delete mSaveOperation;
+}
+
+/*!
+
+*/
+NmUiEngine *NmUiEngine::instance()
+{
+    if (!mInstance) {
+    	mInstance = new NmUiEngine();
+    }
+    mReferenceCount++;
+    return mInstance;
+}
+
+/*!
+
+*/
+void NmUiEngine::releaseInstance(NmUiEngine *&instance)
+{
+    //can't have passed out instances if we don't have any
+    if (mInstance) {
+        if(instance == mInstance) {
+            instance = NULL;
+            mReferenceCount--;
+        }
+        if (0 >= mReferenceCount) {
+            delete mInstance;
+            mInstance = NULL;
+        }
+    }
+}
+
+/*!
+    Returns a list model populated with the mailbox and top level folder objects. The model is
+    updated dynamically. The ownership of the model object is not moved to the caller.
+*/
+NmMailboxListModel &NmUiEngine::mailboxListModel()
+{
+    if (!mMailboxListModel) {
+        refreshMailboxListModel(); // creates the model too
+    }
+    
+    return *mMailboxListModel;
+}
+        
+/*!
+    Populate the list model with the mailbox and top level folder objects. The model is
+    updated dynamically. Creates the model if needed.
+*/
+void NmUiEngine::refreshMailboxListModel()
+{
+    if (!mMailboxListModel) {
+        mMailboxListModel = new NmMailboxListModel(*mDataManager);
+        
+        // Connect the model to the plugins to receive change notifications
+        QList<QObject*> *dataPlugins = mPluginFactory->pluginInstances();
+        for (int i = 0; i < dataPlugins->count(); i++) {
+            QObject *plugin = (*dataPlugins)[i];
+            if (plugin) {
+                connect(plugin, SIGNAL(mailboxEvent(NmMailboxEvent, const QList<NmId> &)),
+                    mMailboxListModel, SLOT(handleMailboxEvent(NmMailboxEvent, const QList<NmId> &)));
+            }
+        }
+    } else {
+        mMailboxListModel->clear();
+    }
+    
+    QList<NmMailbox*> mailboxList;
+    mDataManager->listMailboxes(mailboxList);
+    mMailboxListModel->refresh(mailboxList);
+    while (!mailboxList.isEmpty()) {
+        delete mailboxList.takeFirst();
+    }
+}
+
+/*!
+    Returns a message list model for a folder identified by \a mailboxId and \a folderId.
+    The model is updated dynamically. The ownership of the model object is not moved to the caller.
+*/
+NmMessageListModel &NmUiEngine::messageListModel(const NmId &mailboxId, const NmId &folderId)
+{
+    if (!mMessageListModel){
+        mMessageListModel = new NmMessageListModel(*mDataManager);
+    }
+    else{
+        mMessageListModel->clear();
+    }
+    QObject *plugin =
+        mPluginFactory->pluginInstance(mailboxId);
+    if (plugin) {
+        QObject::connect(plugin,
+            SIGNAL(messageEvent(NmMessageEvent, const NmId &, const QList<NmId> &, const NmId&)),
+        mMessageListModel,
+            SLOT(handleMessageEvent(NmMessageEvent, const NmId &, const QList<NmId> &)),
+            Qt::UniqueConnection );
+        
+        QObject::connect(plugin,
+            SIGNAL(syncStateEvent(NmSyncState, const NmId &)),
+            this,
+            SIGNAL(syncStateEvent(NmSyncState, const NmId &)),
+            Qt::UniqueConnection);
+        
+        QObject::connect(plugin,
+            SIGNAL(connectionEvent(NmConnectState, const NmId &)),
+            this,
+            SIGNAL(connectionEvent(NmConnectState, const NmId &)),
+            Qt::UniqueConnection);
+        
+        // Start to listen mailbox events
+        NmDataPluginInterface *pluginInterface = mPluginFactory->interfaceInstance(plugin);
+        if (pluginInterface) {
+            pluginInterface->subscribeMailboxEvents(mailboxId);
+        }
+    }
+    QList<NmMessageEnvelope*> messageEnvelopeList;
+    mDataManager->listMessages(mailboxId, folderId, messageEnvelopeList);
+    mMessageListModel->refresh(mailboxId, folderId, messageEnvelopeList);
+    while (!messageEnvelopeList.isEmpty()) {
+        delete messageEnvelopeList.takeFirst();
+    }
+    return *mMessageListModel;
+}
+
+/*!
+    
+*/
+void NmUiEngine::releaseMessageListModel(const NmId &mailboxId)
+{
+    // Stop listening mailbox events
+    NmDataPluginInterface *pluginInterface = mPluginFactory->interfaceInstance(mailboxId);
+    if (pluginInterface) {
+        pluginInterface->unsubscribeMailboxEvents(mailboxId);
+    }
+}
+
+/*!
+    Get the identifier of the standard folder of a type \a folderType 
+    from the mailbox \a mailboxId.
+*/
+NmId NmUiEngine::standardFolderId(
+    const NmId &mailboxId,
+    NmFolderType folderType)
+{
+    NmId value;
+    if (folderType != NmFolderOther) {
+        NmDataPluginInterface *plugin =
+            mPluginFactory->interfaceInstance(mailboxId);
+        if(plugin) {
+            value = plugin->getStandardFolderId(mailboxId, folderType);
+        }
+    }
+    return value;
+}
+
+/*!
+    Returns a message identified by \a mailboxId,  \a folderId and \amessageId.
+    The ownership of the  object is moved to the caller.
+    Returns null pointer if the message is not found.
+*/
+NmMessage *NmUiEngine::message(const NmId &mailboxId,
+                      const NmId &folderId,
+                      const NmId &messageId)
+{
+    NmMessage *message = mDataManager->message(mailboxId, folderId, messageId);
+    return message;
+}
+
+/*!
+
+*/
+NmOperation *NmUiEngine::fetchMessage( const NmId &mailboxId,
+    const NmId &folderId,
+    const NmId &messageId )
+{
+    NmOperation *value(NULL);
+    NmDataPluginInterface *plugin =
+        mPluginFactory->interfaceInstance(mailboxId);
+    if (plugin) {
+        value = plugin->fetchMessage(mailboxId, folderId, messageId);
+    }
+    return value;
+}
+
+/*!
+
+*/
+NmOperation *NmUiEngine::fetchMessagePart(
+    const NmId &mailboxId,
+    const NmId &folderId,
+    const NmId &messageId,
+    const NmId& messagePartId)
+{
+    NmOperation *value(NULL);
+    NmDataPluginInterface *plugin =
+        mPluginFactory->interfaceInstance(mailboxId);
+    if (plugin) {
+        value = plugin->fetchMessagePart(mailboxId, folderId, messageId, messagePartId);
+    }
+    return value;
+}
+
+/*!
+    Get content to message part
+*/
+int NmUiEngine::contentToMessagePart(
+    const NmId &mailboxId,
+    const NmId &folderId,
+    const NmId &messageId,
+    NmMessagePart &messagePart)
+{
+    return mDataManager->contentToMessagePart(mailboxId, folderId, messageId, messagePart);
+}
+
+/*!
+    Deletes messages from model and routes call to plugin
+*/
+int NmUiEngine::deleteMessages(
+	const NmId &mailboxId,
+	const NmId &folderId,
+	const QList<NmId> &messageIdList)
+{
+    int result(NmNotFoundError);
+	if (mMessageListModel) {
+	    mMessageListModel->handleMessageEvent(NmMessageDeleted, folderId, messageIdList);
+	}
+    NmDataPluginInterface *plugin =
+            mPluginFactory->interfaceInstance(mailboxId);
+    if (plugin) {
+          result = plugin->deleteMessages(
+	            mailboxId, folderId, messageIdList);
+    }
+	return result;
+}
+
+/*!
+    Sets envelope property given in argument.
+    Ownership of operation object is transferred to the caller.
+*/
+
+NmStoreEnvelopesOperation *NmUiEngine::setEnvelopes(
+        const NmId &mailboxId,
+        const NmId &folderId,
+        NmEnvelopeProperties property,
+        const QList<const NmMessageEnvelope*> &envelopeList)
+{
+    NMLOG("NmUiEngine::setEnvelopes() <---");
+    NmStoreEnvelopesOperation *operation(NULL);
+    if (mMessageListModel && envelopeList.count()) {
+        QList<NmId> messageIdList;
+        
+        for (int i(0); i < envelopeList.count(); i++){
+            messageIdList.append(envelopeList[i]->id());
+        }
+        mMessageListModel->setEnvelopeProperties(
+                           property, messageIdList);
+        // Store new envelopes to plugin
+        NmDataPluginInterface *plugin =
+            mPluginFactory->interfaceInstance(mailboxId);
+        if (plugin) {
+            operation = plugin->storeEnvelopes(
+                    mailboxId, folderId, envelopeList);
+        }
+        messageIdList.clear();
+    }
+    
+    NMLOG("NmUiEngine::setEnvelopes() --->");
+    return operation;
+}
+
+
+/*!
+    Returns a mailbox meta data object from model with the ID \a mailboxId.
+    Ownership of the return value is not moved to the caller.
+    Returns NULL if the mailbox is not found.
+*/
+NmMailboxMetaData *NmUiEngine::mailboxById(const NmId &mailboxId)
+{
+    NmMailboxMetaData *meta(NULL);
+    if (mMailboxListModel) {
+	    for (int i(0); i < mMailboxListModel->rowCount(); i++) {
+	        QModelIndex index = mMailboxListModel->index(i,0);
+	        NmMailboxMetaData *mailbox =
+	            mMailboxListModel->data(index, Qt::DisplayRole).value<NmMailboxMetaData*>();
+	        if (mailbox && mailbox->id() == mailboxId) {
+	            meta = mailbox;
+	            break;
+	        }
+	    }
+    }
+    return meta;
+}
+
+
+/*!
+    Creates a new message (into Drafts-folder).
+    Ownership of operation object is transferred to the caller.
+*/
+NmMessageCreationOperation *NmUiEngine::createNewMessage(const NmId &mailboxId)
+{
+    NmMessageCreationOperation *value(NULL);
+    NmDataPluginInterface *plugin =
+        mPluginFactory->interfaceInstance(mailboxId);
+    if (plugin) {
+        value = plugin->createNewMessage(mailboxId);
+    }
+    return value;
+}
+
+/*!
+    Creates a new forward message (into Drafts-folder).
+    Ownership of operation object is transferred to the caller.
+*/
+NmMessageCreationOperation *NmUiEngine::createForwardMessage(
+        const NmId &mailboxId,
+        const NmId &originalMessageId)
+{
+    NmMessageCreationOperation *value(NULL);
+    NmDataPluginInterface *plugin =
+        mPluginFactory->interfaceInstance(mailboxId);
+    if (plugin) {
+        value = plugin->createForwardMessage(mailboxId, originalMessageId);
+    }
+    return value;
+}
+
+/*!
+    Creates a new reply message (into Drafts-folder).
+    Ownership of operation object is transferred to the caller.
+*/
+NmMessageCreationOperation *NmUiEngine::createReplyMessage(
+        const NmId &mailboxId,
+        const NmId &originalMessageId,
+        bool replyAll)
+{
+    NmMessageCreationOperation *value(NULL);
+    NmDataPluginInterface *plugin =
+        mPluginFactory->interfaceInstance(mailboxId);
+    if (plugin) {
+        value = plugin->createReplyMessage(mailboxId, originalMessageId, replyAll);
+    }
+    return value;
+}
+
+/*!
+    Saves a message (into message store).
+*/
+int NmUiEngine::saveMessage(const NmMessage &message)
+{
+    const NmId &mailboxId = message.mailboxId();
+    int ret(NmNotFoundError);
+    NmDataPluginInterface *plugin =
+        mPluginFactory->interfaceInstance(mailboxId);
+    if (plugin) {
+        ret = plugin->saveMessage(message);
+    }
+    return ret;
+}
+
+/*!
+    Saves a message with its subparts (into message store).
+    Ownership of operation object is transferred to the caller.
+*/
+NmOperation *NmUiEngine::saveMessageWithSubparts(const NmMessage &message)
+{
+    NmOperation *value(NULL);
+    const NmId &mailboxId = message.mailboxId();
+    
+    NmDataPluginInterface *plugin =
+        mPluginFactory->interfaceInstance(mailboxId);
+
+    if (plugin) {
+        value = plugin->saveMessageWithSubparts(message);
+    }
+    return value;
+}
+
+/*!
+    Refreshes mailbox.
+*/
+int NmUiEngine::refreshMailbox(const NmId &mailboxId )
+{
+    int ret(NmNotFoundError);
+    NmDataPluginInterface *plugin =
+        mPluginFactory->interfaceInstance(mailboxId);
+    if (plugin) {
+        ret = plugin->refreshMailbox(mailboxId);
+    }
+    return ret;
+}
+
+/*!
+    Removes message from given mailbox and folder
+    - routes call to plugin
+*/
+int NmUiEngine::removeMessage(
+    const NmId &mailboxId,
+    const NmId &folderId,
+    const NmId &messageId)
+{
+    int result(NmNotFoundError);
+    NmDataPluginInterface *plugin =
+            mPluginFactory->interfaceInstance(mailboxId);
+    if (plugin) {
+          result = plugin->removeMessage(mailboxId, folderId, messageId);
+    }
+    return result;
+}
+
+/*!
+    Takes ownership of an operation and connects to 
+    it's completion signal
+ */
+void NmUiEngine::storeOperation(NmOperation *op)
+{
+    mOperations.append(op);
+    connect(
+            op, 
+            SIGNAL(operationCompleted(int)), 
+            this, 
+            SLOT(handleCompletedOperation()));
+}
+
+/*!
+    Sends the given message.
+ */
+void NmUiEngine::sendMessage(NmMessage *message)
+{
+    //First trigger message storing
+    if (message) {
+
+        if (mMessage) {
+            delete mMessage;
+            mMessage = NULL;
+        }
+        mMessage = message;
+
+        if (mSaveOperation) {
+            delete mSaveOperation;
+            mSaveOperation = NULL;
+        }
+        mSaveOperation = this->saveMessageWithSubparts(*message);
+
+        if (mSaveOperation) {
+            connect(mSaveOperation, SIGNAL(operationCompleted(int)), this,
+                SLOT(handleCompletedSaveOperation(int)));
+        }
+        mMessageToBeSent = true;
+    }
+}
+
+/*!
+    Is sending operation in progress.
+ */
+bool NmUiEngine::isSendingMessage() const
+{
+    int ret(false);
+    if (mSendOperation) {
+        ret = true;
+    }
+    return ret;
+}
+
+/*!
+   Returns a pointer to the message that is being sent. Returns NULL if not sending.
+ */
+const NmMessage *NmUiEngine::messageBeingSent()
+{
+    const NmMessage *message = NULL;
+    
+    if (mSendOperation != NULL) {
+        message = mSendOperation->getMessage();
+    }
+    
+    return message;
+}
+
+/*!
+    Add file attachment into given message. Return the operation object for
+    observing/cancelling. Ownership of operation object is transferred to the caller.
+ */
+NmAddAttachmentsOperation *NmUiEngine::addAttachments(
+    const NmMessage &message,
+    const QList<QString> &fileList)
+{
+    NmDataPluginInterface *plugin =
+        mPluginFactory->interfaceInstance(message.mailboxId());
+    
+    NmAddAttachmentsOperation *ret(NULL);
+    
+    if (plugin) {
+        ret = plugin->addAttachments(message, fileList);
+    }
+
+    return ret;
+}
+
+/*!
+    Remove attached file from given message. Return the operation object for
+    observing/cancelling. Ownership of operation object is transferred to the caller.
+ */
+NmOperation *NmUiEngine::removeAttachment(
+    const NmMessage &message,
+    const NmId &attachmentPartId)
+{
+    NmDataPluginInterface *plugin =
+        mPluginFactory->interfaceInstance(message.mailboxId());
+    
+    NmOperation *ret(NULL);
+    
+    if (plugin) {
+        ret = plugin->removeAttachment(message, attachmentPartId);
+    }
+
+    return ret;
+}
+
+/*!
+    Ownership of operation object is transferred to the caller.
+ */
+NmCheckOutboxOperation *NmUiEngine::checkOutbox(const NmId &mailboxId)
+{
+    NmDataPluginInterface *plugin =
+        mPluginFactory->interfaceInstance(mailboxId);
+
+    NmCheckOutboxOperation *ret(NULL);
+    
+    if (plugin) {
+        ret = plugin->checkOutbox(mailboxId);
+    }
+    
+    return ret;
+}
+
+/*!
+    Returns the current sync state of the mailbox
+ */
+NmSyncState NmUiEngine::syncState(const NmId& mailboxId)
+{
+    NmDataPluginInterface *plugin =
+                mPluginFactory->interfaceInstance(mailboxId);
+    if (plugin) {
+        return plugin->syncState(mailboxId);
+    }
+    else {
+        return SyncComplete;
+    }
+}
+
+/*!
+    Returns the current connection state of the mailbox
+ */
+NmConnectState NmUiEngine::connectionState(const NmId& mailboxId)
+{
+    NmDataPluginInterface *plugin =
+                mPluginFactory->interfaceInstance(mailboxId);
+    if (plugin) {
+        return plugin->connectionState(mailboxId);
+    }
+    else {
+        return Disconnected;
+    }
+}
+
+/*!
+ * deletes completed operations
+ * 
+ */
+void NmUiEngine::handleCompletedOperation()
+{
+    NMLOG("NmUiEngine::handleCompletedOperation() <---");
+    int count = mOperations.count();
+    
+    QObject *sender = this->sender();
+    
+    for(int i(0); i < count; i++){
+        if (mOperations[i] == sender){
+            delete mOperations.takeAt(i);
+            }
+        }
+    NMLOG("NmUiEngine::handleCompletedOperation() --->");
+}
+    
+/*!
+    Handle completed send operation
+ */
+void NmUiEngine::handleCompletedSendOperation()
+{ // let the callback method finish until cleaning the operation
+    QTimer::singleShot(1, this, SLOT(cleanupSendOperation()));
+}
+
+/*!
+    Cleanup the send operation
+ */
+void NmUiEngine::cleanupSendOperation()
+{
+    delete mSendOperation;
+    mSendOperation = NULL;
+    // delete the sent messages from the store if necessary
+    // ...
+}
+ 
+/*!
+    Handle completed store message operation
+ */
+void NmUiEngine::handleCompletedSaveOperation(int error)
+{
+	if (mMessage && mMessageToBeSent && error == NmNoError)
+	{
+	    mMessageToBeSent = false;
+	    
+	    NmDataPluginInterface *plugin =
+            mPluginFactory->interfaceInstance(mMessage->mailboxId());
+        
+        if (plugin) {
+            // to be on the safer side:
+            // we shouldn't even be here if mSendOperation != NULL
+			delete mSendOperation;
+            mSendOperation = NULL;
+            // ownership of mMessage changes
+            mSendOperation = plugin->sendMessage(mMessage);
+            mMessage = NULL;
+            // don't put this to mOperations as we need to handle this
+            // operation separately
+			if (mSendOperation) {
+			    connect(mSendOperation, 
+			            SIGNAL(operationCompleted(int)), 
+			            this, 
+			            SLOT(handleCompletedSendOperation()));
+			}
+        }
+	}
+}