diff -r dcf0eedfc1a3 -r d189ee25cf9d emailuis/nmhswidget/src/nmhswidgetemailengine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emailuis/nmhswidget/src/nmhswidgetemailengine.cpp Tue Aug 31 15:04:17 2010 +0300 @@ -0,0 +1,514 @@ +/* + * Copyright (c) 2010 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 +#include +#include +#include +#include +#include "nmcommon.h" +#include "nmmessageenvelope.h" +#include "nmhswidgetemailengine.h" +#include "nmdataplugininterface.h" +#include "nmmailbox.h" +#include "nmfolder.h" +#include "nmdatapluginfactory.h" +#include "nmhswidgetconsts.h" +#include "emailtrace.h" + +/*! + Constructor + */ +NmHsWidgetEmailEngine::NmHsWidgetEmailEngine(const NmId& monitoredMailboxId) : + mMailboxId(monitoredMailboxId), + mFolderId(0), + mAccountName(), + mUnreadCount(-1), + mEmailInterface(0), + mFactory(0), + mAccountEventReceivedWhenSuspended(false), + mMessageEventReceivedWhenSuspended(false), + mSuspended(false), + mUpdateTimer(0), + mAiwRequest(0) +{ + NM_FUNCTION; +} + +/*! + initilaize - Initializes the engine + Works as a second phase constructor. Must be called before any other operations. + Client should connect to exceptionOccured signal before calling this method. + /return true if initialize succeedes otherwise false. If false the object is unusable. + */ +bool NmHsWidgetEmailEngine::initialize() +{ + NM_FUNCTION; + + if (!constructNmPlugin()) { + //if plugin connection fails, there's no reason to proceed + return false; + } + updateData(); + updateAccount(); + + mUpdateTimer = new QTimer(this); + mUpdateTimer->setInterval(NmHsWidgetEmailEngineUpdateTimerValue); + connect(mUpdateTimer, SIGNAL(timeout()), this, SLOT(handleUpdateTimeout()) ); + + return true; +} + +/*! + constructNmPlugin + /post Constructs a connection to an instance of NmDataPluginInterface + /return true if construction succeeded, otherwise false. + */ +bool NmHsWidgetEmailEngine::constructNmPlugin() +{ + NM_FUNCTION; + + QObject* pluginInstance(0); + //Get data plugin factory instance + mFactory = NmDataPluginFactory::instance(); + if (!mFactory) { + NM_ERROR(1,"NmHsWidgetEmailEngine::constructNmPlugin() -- mFactory FAILED"); + return false; + } + + //Get plugin instance + pluginInstance = mFactory->pluginInstance(mMailboxId); + if (!pluginInstance) { + NM_ERROR(1,"NmHsWidgetEmailEngine::constructNmPlugin() -- pluginInstance FAILED"); + return false; + } + + //get interface instance + mEmailInterface = mFactory->interfaceInstance(pluginInstance); + + if (!mEmailInterface) { + NM_ERROR(1,"NmHsWidgetEmailEngine::constructNmPlugin() -- mEmailInterface FAILED"); + return false; + } + //Verify that the mailbox we are interested actually exists. + //Otherwise emit account deleted event (instead of just returning) + QList ids; + mEmailInterface->listMailboxIds(ids); + if(!ids.contains(mMailboxId)){ + NM_ERROR(1,"NmHsWidgetEmailEngine::constructNmPlugin() -- !ids.contains(mMailboxId) FAILED"); + emit exceptionOccured(NmEngineExcAccountDeleted); + return false; + } + + //retrieve folderID for this mailbox's inbox + //If NmId equals zero, we don't have the Initial sync done for the account + //This is valid at least for IMAP accounts. + //Folder ID is then retrieved later when first message event is received + mFolderId = mEmailInterface->getStandardFolderId(mMailboxId, NmFolderInbox); + + //Subscription is needed - otherwise the signals will not be received + mEmailInterface->subscribeMailboxEvents(mMailboxId); + + //Connect to events + connect(pluginInstance, SIGNAL( messageEvent(NmMessageEvent, const NmId&, + const QList&, const NmId&) ), this, + SLOT( handleMessageEvent(NmMessageEvent, const NmId&, + const QList&, const NmId&) )); + + connect(pluginInstance, SIGNAL( mailboxEvent(NmMailboxEvent, const QList& ) ), this, + SLOT( handleMailboxEvent(NmMailboxEvent, const QList&) )); + + return true; +} + +/*! + Reset envelope list + \post mEnvelopeList.isEmpty() == true && all contained objects are deleted + */ +void NmHsWidgetEmailEngine::resetEnvelopeList() +{ + NM_FUNCTION; + + while (!mEnvelopeList.isEmpty()) { + delete mEnvelopeList.takeFirst(); + } +} + +/*! + Destructor + */ +NmHsWidgetEmailEngine::~NmHsWidgetEmailEngine() +{ + NM_FUNCTION; + + resetEnvelopeList(); + if (mFactory) { + NmDataPluginFactory::releaseInstance(mFactory); + } + + if (mUpdateTimer){ + mUpdateTimer->stop(); + delete mUpdateTimer; + } +} + +/*! + getEnvelopes() provides message envelopes as a list of stack objects + Amount of message envelopes in the list parameter is the smallest of the following factors: + 'KMaxNumberOfEnvelopesProvided', 'maxEnvelopeAmount', 'amount of available envelopes'. + + \param list list to be filled with message envelopes + \param maxEnvelopeAmount Client side limit for amount of message envelope count. + \return count of envelopes added to list + */ +int NmHsWidgetEmailEngine::getEnvelopes(QList &list, int maxEnvelopeAmount) +{ + NM_FUNCTION; + list.clear(); //Reset the parameter list to avoid side effects + int i = 0; + for (; i < mEnvelopeList.count() && i < maxEnvelopeAmount; i++) { + NmMessageEnvelope env(*mEnvelopeList.at(i)); + list.append(env); + } + return i; +} + +/*! + UnreadCount + + \return count of unread mails, or -1 if there are no mails at all in the mailbox. + */ +int NmHsWidgetEmailEngine::unreadCount() +{ + NM_FUNCTION; + return mUnreadCount; +} + +/*! + accountName + + \return name of the monitored account + */ +QString NmHsWidgetEmailEngine::accountName() +{ + NM_FUNCTION; + return mAccountName; +} + +/*! + Refresh email data. + \post mEnvelopeList is refreshed with valid content so that it has + valid data with maximum of KMaxNumberOfEnvelopesProvided envelopes. + + - emits exceptionOccured(NmEngineExcFailure) if fatal error occurs. + - emits mailDataChanged() if new mail data is set into mEnvelopeList + - emits unreadCountChanged(mUnreadCount), if mUnreadCount is updated + + \return true if everything succeeded, otherwise false + */ +bool NmHsWidgetEmailEngine::updateData() +{ + NM_FUNCTION; + if (!mEmailInterface) { + NM_ERROR(1,"NmHsWidgetEmailEngine::updateData() -- Interface missing"); + emit exceptionOccured(NmEngineExcFailure); //fatal error + return false; //if interface is missing there's nothing to do + } + + //reset envelope list before retrieving new items + resetEnvelopeList(); + + //get messages from inbox + int msgErr = mEmailInterface->listMessages(mMailboxId, mFolderId, mEnvelopeList, + KMaxNumberOfEnvelopesProvided); + if (msgErr) { + //retrieval of messages failed. + return false; + } + //emit signal about new message data right away + emit mailDataChanged(); + //retrieve new unread count to mUnreadCount + NmFolder* folder = NULL; + int folderErr = mEmailInterface->getFolderById(mMailboxId, mFolderId, folder); + if (folderErr) { + //retrieval of valid folder failed. + return false; + } + if (folder) { + //If messageCount in the folder is zero we must indicate unread count to be -1 + if (mEnvelopeList.count() == 0) { + mUnreadCount = -1; + } + else { + mUnreadCount = folder->unreadMessageCount(); + } + delete folder; + folder = NULL; + //limit the unread count to KMaxUnreadCount + if (mUnreadCount > KMaxUnreadCount) { + mUnreadCount = KMaxUnreadCount; + } + //emit signal about changed unread count + emit unreadCountChanged(mUnreadCount); + }else{ + return false; + } + return true; +} + +/*! + handleMessageEvent slot. + */ +void NmHsWidgetEmailEngine::handleMessageEvent( + NmMessageEvent event, + const NmId &folderId, + const QList &messageIds, + const NmId& mailboxId) +{ + NM_FUNCTION; + Q_UNUSED(event); + Q_UNUSED(messageIds); + + if (!mEmailInterface) { + NM_ERROR(1,"NmHsWidgetEmailEngine::handleMessageEvent() -- Interface missing"); + emit exceptionOccured(NmEngineExcFailure); //fatal error + return; //if interface is missing there's nothing to do + } + + if (mFolderId == NmId(0)) { + // inbox was not created in construction phase, so let's + // get id now as received first mail event + mFolderId = mEmailInterface->getStandardFolderId(mMailboxId, NmFolderInbox); + } + if ((folderId == mFolderId) && (mailboxId == mMailboxId)) { + //Data is updated only if the engine is not suspended + if (mSuspended) { + mMessageEventReceivedWhenSuspended = true; + } + else { + //start or restart the timer. Update is started when timer expires + mUpdateTimer->start(); + } + } +} + +/*! + handleMailboxEvent slot. + */ +void NmHsWidgetEmailEngine::handleMailboxEvent(NmMailboxEvent event, const QList &mailboxIds) +{ + NM_FUNCTION; + if (mailboxIds.contains(mMailboxId)) { + switch (event) { + case (NmMailboxChanged): { + if (mSuspended) { + mAccountEventReceivedWhenSuspended = true; + } + else { + updateAccount(); + } + break; + } + case (NmMailboxDeleted): { + emit exceptionOccured(NmEngineExcAccountDeleted); + break; + } + default: + //ignored + break; + } + } +} + +/*! + * handleUpdateTimeout slot + */ +void NmHsWidgetEmailEngine::handleUpdateTimeout() +{ + NM_FUNCTION; + if (mUpdateTimer){ + mUpdateTimer->stop(); + } + updateData(); +} + +/*! + Update Account data + \post if mEmailInterface exists, the mAccountName is refreshed from adapter + and accountNameChanged signal is emitted. + */ +bool NmHsWidgetEmailEngine::updateAccount() +{ + NM_FUNCTION; + + NmMailbox* box = NULL; + if (mEmailInterface) { + int err = mEmailInterface->getMailboxById(mMailboxId, box); + if (err) { + //By specification return and wait another event + return false; + } + } + if (box) { + mAccountName = box->name(); + delete box; + box = NULL; + emit accountNameChanged(mAccountName); + } + return true; +} + +/*! + suspend slot. + \post engine will not emit signals or refresh its data during suspension. + */ +void NmHsWidgetEmailEngine::suspend() +{ + NM_FUNCTION; + mSuspended = true; +} + +/*! + activate slot. + \post Engine will immediately refresh all the data that has been announced to + have changed during the suspension. Events are enabled. + */ +void NmHsWidgetEmailEngine::activate() +{ + NM_FUNCTION; + mSuspended = false; + if (mAccountEventReceivedWhenSuspended) { + mAccountEventReceivedWhenSuspended = false; + updateAccount(); + } + if (mMessageEventReceivedWhenSuspended) { + mMessageEventReceivedWhenSuspended = false; + updateData(); + } +} + +/*! + launchMailAppInboxView slot. + \post Mail application is launched to inbox view corresponding widget's mailbox id + */ +void NmHsWidgetEmailEngine::launchMailAppInboxView() +{ + NM_FUNCTION; + + QT_TRY{ + if (!mAiwRequest) { + XQApplicationManager appManager; + mAiwRequest = appManager.create( + XQI_EMAIL_INBOX_VIEW, XQOP_EMAIL_INBOX_VIEW, + false); + + if (mAiwRequest) { + connect(mAiwRequest, SIGNAL( requestError(int, const QString&) ), + this, SLOT( aiwRequestError(int, const QString&) )); + connect(mAiwRequest, SIGNAL( requestOk(const QVariant&) ), + this, SLOT( aiwRequestOk(const QVariant&) )); + QList list; + list.append(QVariant(mMailboxId.id())); + + mAiwRequest->setSynchronous(false); + mAiwRequest->setArguments(list); + mAiwRequest->send(); + } + } + } + QT_CATCH(...){ + // no actions taken. + // try-catch mechanism added to avoid crashing widget, in case XQAiwRequest + // creation raise exception. + } +} + +/*! + launchMailAppMailViewer slot. + \param messageId Defines the message opened to viewer + \post Mail application is launched and viewing mail specified by + */ +void NmHsWidgetEmailEngine::launchMailAppMailViewer(const NmId &messageId) +{ + NM_FUNCTION; + + QT_TRY{ + if (!mAiwRequest) { + XQApplicationManager appManager; + mAiwRequest = appManager.create( + XQI_EMAIL_MESSAGE_VIEW, XQOP_EMAIL_MESSAGE_VIEW, + false); + + if (mAiwRequest) { + connect(mAiwRequest, SIGNAL( requestError(int, const QString&) ), + this, SLOT( aiwRequestError(int, const QString&) )); + connect(mAiwRequest, SIGNAL( requestOk(const QVariant&) ), + this, SLOT( aiwRequestOk(const QVariant&) )); + QList list; + list.append(QVariant(mMailboxId.id())); + list.append(QVariant(mFolderId.id())); + list.append(QVariant(messageId.id())); + + mAiwRequest->setSynchronous(false); + mAiwRequest->setArguments(list); + mAiwRequest->send(); + } + } + } + QT_CATCH(...){ + // no actions taken. + // try-catch mechanism added to avoid crashing widget, in case XQAiwRequest + // creation raise exception. + } +} + +/*! + aiwRequestOk slot. + */ +void NmHsWidgetEmailEngine::aiwRequestOk(const QVariant& result) +{ + NM_FUNCTION; + + Q_UNUSED(result); + + deleteAiwRequest(); +} + +/*! + aiwRequestError slot. + */ +void NmHsWidgetEmailEngine::aiwRequestError(int errorCode, const QString& errorMessage) +{ + NM_FUNCTION; + + Q_UNUSED(errorCode); + Q_UNUSED(errorMessage); + + deleteAiwRequest(); +} + +/*! + deleteAiwRequest function. + */ +void NmHsWidgetEmailEngine::deleteAiwRequest() +{ + NM_FUNCTION; + + delete mAiwRequest; + mAiwRequest = NULL; +} +