emailservices/nmailagent/src/nmmailagent.cpp
branchRCL_3
changeset 63 d189ee25cf9d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailservices/nmailagent/src/nmmailagent.cpp	Tue Aug 31 15:04:17 2010 +0300
@@ -0,0 +1,1302 @@
+/*
+ * 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: Mail agent is responsible of monitoring mail accounts. It activates
+ *              and deactivates indicator depending on received events. Mail agent is
+ *              also responsible of monitoring silence mode, playing alert tone and vibrating
+ *              phone when new mail is received.
+ *
+ */
+
+#include "emailtrace.h"
+#include "nmmailagentheaders.h"
+#include "nmmailagent.h"
+
+#include <xqaiwdeclplat.h>
+#include <xqapplicationmanager.h>
+#include <xqaiwrequest.h>
+
+#include <xqsettingsmanager.h>
+#include <xqcentralrepositoryutils.h>
+#include <xqsystemtoneservice.h>
+#include <xqsettingskey.h>
+#include <ProfileEngineInternalCRKeys.h>
+
+// CONSTANTS
+const int NmAgentIndicatorNotSet = -1;
+const int NmAgentAlertToneTimer = 60000; // 60s
+const int NmAgentDefaultVibraDuration = 1000; // 1 second
+static const quint32 NmRepositoryId = 0x2002C326;
+static const QString NmMailboxIndicatorType = "com.nokia.nmail.indicatorplugin_%1/1.0";
+static const QString NmSendIndicatorName = "com.nokia.nmail.indicatorplugin.send/1.0";
+static const QString NmUnreadIndicatorName = "com.nokia.nmail.indicatorplugin.unread/1.0";
+const XQCentralRepositorySettingsKey NmSilenceModeKey(KCRUidProfileEngine.iUid, KProEngSilenceMode);
+const int NmSilenceModeOn = 1;
+
+/*!
+    Helper method for finding out if XQSettingsKey and XQCentralRepositorySettingsKey points to
+    same key.
+
+    \param settingKey XQSettingsKey
+    \param cenrepSettingKey XQCentralRepositorySettingsKey
+    \return <code>true</code> if target, uid and key matches otherwise returns <code>false</code>
+ */
+bool keysEqual(const XQSettingsKey& settingKey, const XQCentralRepositorySettingsKey& cenrepSettingKey)
+{
+    return ((settingKey.target() == cenrepSettingKey.target()) &&
+        (settingKey.uid() == cenrepSettingKey.uid()) &&
+        (settingKey.key() == cenrepSettingKey.key()));
+}
+
+/*!
+    \class NmMailboxInfo
+
+    \brief Main class for storing mailbox data.
+ */
+NmMailboxInfo::NmMailboxInfo()
+: mId(0),
+  mIndicatorIndex(NmAgentIndicatorNotSet),
+  mInboxFolderId(0),
+  mOutboxFolderId(0),
+  mSyncState(SyncComplete),
+  mConnectState(Disconnected),
+  mInboxCreatedMessages(0),
+  mInboxChangedMessages(0),
+  mInboxDeletedMessages(0),
+  mOutboxMails(0),
+  mActive(false)
+  {
+      NM_FUNCTION;
+  }
+
+
+/*!
+    \class NmMailAgent
+
+    \brief Main class for receiving email events. Activates and deactivates
+           the indicator.
+*/
+NmMailAgent::NmMailAgent()
+: mIndicator(NULL),
+  mPluginFactory(NULL),
+  mVibra(NULL),
+  mSettingManager(NULL),
+  mUiEventsNotifier(NULL),
+  mAlertToneAllowed(true),
+  mLastOutboxCount(0),
+  mUnreadIndicatorActive(false),
+  mSilenceMode(NmSilenceModeOn)  // by default silent mode is on
+{
+    NM_FUNCTION;
+}
+
+
+/*!
+    Delayed start.
+ */
+void NmMailAgent::delayedStart()
+{
+    NM_FUNCTION;
+
+    if (!init()) {
+        // Initialisation failed. Quit the agent.
+        QCoreApplication::exit(1);
+    }
+}
+
+/*!
+    Initialise the agent.
+
+    \return true if succesfully started.
+*/
+bool NmMailAgent::init()
+{
+    NM_FUNCTION;
+
+    mPluginFactory = NmDataPluginFactory::instance();
+    if (!mPluginFactory) {
+        NM_ERROR(1,"NmMailAgent::init(): PluginFactory not created");
+        return false;
+    }
+
+    // Check status of silent mode.
+    delete mSettingManager;
+    mSettingManager = NULL;
+    mSettingManager = new XQSettingsManager();
+    QVariant silenceMode = mSettingManager->readItemValue(NmSilenceModeKey,
+        XQSettingsManager::TypeInt);
+    mSilenceMode = silenceMode.toInt();
+
+    // Start monitoring silence mode key.
+    bool monitoring(mSettingManager->startMonitoring(NmSilenceModeKey, XQSettingsManager::TypeInt));
+    monitoring &= connect(mSettingManager,
+                          SIGNAL(valueChanged(const XQSettingsKey &, const QVariant &)),
+                          this,
+                          SLOT(valueChanged(const XQSettingsKey &, const QVariant &)),
+                          Qt::UniqueConnection);
+
+    // If silence mode monitoring can't be started, then change silence mode on to be sure
+    // that no tone is played if silence mode is turned on at somepoint.
+    if (!monitoring) {
+        mSilenceMode = NmSilenceModeOn;
+    }
+
+    delete mIndicator;
+    mIndicator = NULL;
+    mIndicator = new HbIndicator();
+    connect(mIndicator,SIGNAL(userActivated(const QString &, const QVariantMap &)),
+        this, SLOT(indicatorActivated(const QString &, const QVariantMap &)));
+
+    QList<QObject*> *plugins = mPluginFactory->pluginInstances();
+
+    foreach (QObject *plugin, *plugins) {
+        if (plugin) {
+            // Start listening events
+            connect(plugin, SIGNAL(mailboxEvent(NmMailboxEvent, const QList<NmId> &)),
+                    this, SLOT(handleMailboxEvent(NmMailboxEvent, const QList<NmId> &)),
+                    Qt::UniqueConnection);
+
+            connect(plugin, SIGNAL(messageEvent(
+                        NmMessageEvent, const NmId &, const QList<NmId> &, const NmId &)),
+                    this, SLOT(handleMessageEvent(
+                        NmMessageEvent, const NmId &, const QList<NmId> &, const NmId &)),
+                    Qt::UniqueConnection);
+
+            connect(plugin, SIGNAL(syncStateEvent(NmSyncState, const NmOperationCompletionEvent &)),
+                    this, SLOT(handleSyncStateEvent(NmSyncState, const NmOperationCompletionEvent &)),
+                Qt::UniqueConnection);
+
+            connect(plugin, SIGNAL(connectionEvent(NmConnectState, const NmId, int)),
+                    this, SLOT(handleConnectionEvent(NmConnectState, const NmId, int)),
+                    Qt::UniqueConnection);
+        }
+    }
+
+    // Construct the vibra interface instance.
+    delete mVibra;
+    mVibra = NULL;
+    TRAP_IGNORE(mVibra = CHWRMVibra::NewL());
+
+    // Start monitoring the UI events.
+    delete mUiEventsNotifier;
+    mUiEventsNotifier = NULL;
+    mUiEventsNotifier = new NmUiEventsNotifier(this);
+
+    connect(mUiEventsNotifier,
+            SIGNAL(viewStateChanged(NmUiEventsNotifier::NmUiEventType,
+                                    NmUiViewId, NmId)),
+            this,
+            SLOT(handleViewStateChangedEvent(const NmUiEventsNotifier::NmUiEventType,
+                                             const NmUiViewId, const NmId)));
+
+    // load all current mailboxes
+    initMailboxStatus();
+
+    return true;
+}
+
+/*!
+    Destructor of NmMailAgent.
+*/
+NmMailAgent::~NmMailAgent()
+{
+    NM_FUNCTION;
+
+    delete mIndicator;
+    delete mVibra;
+
+    if (mSettingManager) {
+        mSettingManager->stopMonitoring(NmSilenceModeKey);
+        delete mSettingManager;
+    }
+
+    qDeleteAll(mMailboxes);
+
+    delete mUiEventsNotifier;
+    mUiEventsNotifier = NULL;
+
+    NmDataPluginFactory::releaseInstance(mPluginFactory);
+}
+
+/*!
+    Initialize the mailbox list with the current state.
+ */
+void NmMailAgent::initMailboxStatus()
+{
+    NM_FUNCTION;
+
+    QList<NmMailbox*> mailboxes;
+    QList<QObject*> *plugins = mPluginFactory->pluginInstances();
+
+    foreach(QObject* pluginObject, *plugins) {
+        NmDataPluginInterface *plugin =
+            mPluginFactory->interfaceInstance(pluginObject);
+        if (plugin) {
+            plugin->listMailboxes(mailboxes);
+        }
+
+        // Add the indicators
+        // Must be made in reverse order to show them properly in
+        // HbIndicator menu
+        QListIterator<NmMailbox *> i(mailboxes);
+        i.toBack();
+        while (i.hasPrevious()) {
+            const NmMailbox *mailbox = i.previous();
+            if (mailbox) {
+                NmMailboxInfo *mailboxInfo = createMailboxInfo(*mailbox, plugin);
+                if (mailboxInfo) {
+                    bool activate = updateUnreadCount(mailbox->id(), *mailboxInfo);
+                    NM_COMMENT(QString("Mailbox %1 initial state: newUnread=%2 total=%3").
+                        arg(mailboxInfo->mName).
+                        arg(mailboxInfo->mNewUnreadMailIdList.count()).
+                        arg(mailboxInfo->mMailIdList.count()));
+
+                    bool wasActive = isMailboxActive(mailbox->id());
+                    if (!wasActive) {
+                        // do not activate the mailbox if it was left as hidden last time
+                        activate = false;
+                        mailboxInfo->mNewUnreadMailIdList.clear();
+                    }
+
+                    mailboxInfo->mOutboxMails = getOutboxCount(mailbox->id(),
+                        mailboxInfo->mOutboxFolderId);
+                    if (mailboxInfo->mOutboxMails > 0 && wasActive) {
+                        activate = true;
+                    }
+
+                    // Create indicator for visible mailboxes
+                    updateMailboxState(mailbox->id(), activate, false);
+                }
+            }
+        }
+        qDeleteAll(mailboxes);
+    }
+    updateUnreadIndicator();
+    updateSendIndicator();
+}
+
+/*!
+    Get mailbox unread count in inbox folder.
+
+    \param mailboxId id of the mailbox
+    \param mailboxInfo contains the list of unread messages
+    \return true if new unread mails was found
+ */
+bool NmMailAgent::updateUnreadCount(const NmId &mailboxId, NmMailboxInfo &mailboxInfo)
+{
+    NM_FUNCTION;
+
+    int newUnreadMessages(0);
+    NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId);
+
+    if (plugin) {
+        NmId inboxId = mailboxInfo.mInboxFolderId.id();
+
+        // Inbox folder ID may be still unknown
+        if (inboxId == 0) {
+            mailboxInfo.mInboxFolderId = plugin->getStandardFolderId(mailboxId, NmFolderInbox);
+            inboxId = mailboxInfo.mInboxFolderId.id();
+        }
+
+        // get list of messages in inbox
+        QList<NmMessageEnvelope*> messageList;
+        plugin->listMessages(mailboxId, inboxId, messageList);
+
+        QList<NmId> newMessageIdList;
+
+        int unreadCount(0);
+        foreach (const NmMessageEnvelope* envelope, messageList) {
+            // if the message is not read, it is "unread"
+            quint64 messageId = envelope->messageId().id();
+            newMessageIdList.append(envelope->messageId());
+            bool read = envelope->isRead();
+
+            // This is a new unread mail
+            if (!read) {
+                unreadCount++;
+
+                // Iterate through all known ids. If the id can't be found the mail is new.
+                bool found(false);
+                foreach (const NmId id, mailboxInfo.mMailIdList) {
+                    if (id.id() == messageId) {
+                        found = true;
+                        break;
+                    }
+                }
+
+                // it was new unread message
+                if (!found) {
+					if (mailboxInfo.mNewUnreadMailIdList.indexOf(messageId)<0) {
+                        mailboxInfo.mNewUnreadMailIdList.append(messageId);
+                        newUnreadMessages++;
+					}
+                }
+            }
+            else {
+                // message is now 'read' - make sure it is no longer in list new unread mails
+                mailboxInfo.mNewUnreadMailIdList.removeAll(messageId);
+            }
+        }
+        qDeleteAll(messageList);
+
+        // Save updated list of unread message IDs
+        mailboxInfo.mMailIdList = newMessageIdList;
+
+        NM_COMMENT(QString("NmMailAgent::getUnreadCount(): totalCount=%1, newUnread=%2").
+            arg(mailboxInfo.mMailIdList.count()).
+            arg(newUnreadMessages));
+    }
+
+    return (newUnreadMessages > 0);
+}
+
+/*!
+    Get mailbox count in outbox folder.
+
+    \param mailboxId id of the mailbox
+    \param outboxId Outbox folder Id
+    \return number of mails in the outbox
+ */
+int NmMailAgent::getOutboxCount(const NmId &mailboxId, const NmId &outboxId)
+{
+    NM_FUNCTION;
+
+    int count(0);
+    NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId);
+
+    if (plugin) {
+        // get list of messages in outbox
+        QList<NmMessageEnvelope*> messageList;
+        plugin->listMessages(mailboxId, outboxId, messageList);
+        count = messageList.count();
+        qDeleteAll(messageList);
+    }
+    NM_COMMENT(QString("NmMailAgent::getOutboxCount(): count=%1").arg(count));
+
+    return count;
+}
+
+/*!
+    Get list of unread counts in all active mailboxes.
+
+	\returns total number of unread mails
+ */
+int NmMailAgent::getTotalUnreadCount() const
+{
+    NM_FUNCTION;
+
+    int unreads = 0;
+    foreach (const NmMailboxInfo *mailbox, mMailboxes) {
+        if (mailbox->mActive) {
+            unreads += mailbox->mNewUnreadMailIdList.count();
+        }
+    }
+    return unreads;
+}
+
+/*!
+    Update the "@" indicator state according to unread state.
+
+    \return true if the indicator was activated
+ */
+bool NmMailAgent::updateUnreadIndicator()
+{
+    NM_FUNCTION;
+
+    int unreads = getTotalUnreadCount();
+    return updateUnreadIndicator(unreads>0);
+}
+
+/*!
+    Update mailbox visibility according to current status
+*/
+bool NmMailAgent::updateMailboxState(const NmId &mailboxId) 
+{
+    NmMailboxInfo *mailboxInfo = getMailboxInfo(mailboxId);
+    bool shown = false;
+    
+    if( mailboxInfo->mActive && 
+        (mailboxInfo->mNewUnreadMailIdList.count() > 0 ||
+         mailboxInfo->mOutboxMails>0)) {
+        shown = true;
+    }
+    
+    return updateMailboxState(mailboxId,shown,false);
+}
+
+
+/*!
+    Update the mailbox visibility and status.
+
+    \param mailboxId id of the mailbox
+    \param active visibility state of the mailbox
+    \param refreshAlways true when the indicator should be always updated
+    \return true if the mailbox state was changed
+ */
+bool NmMailAgent::updateMailboxState(const NmId &mailboxId,
+    bool active, bool refreshAlways)
+{
+    NM_FUNCTION;
+
+    NmMailboxInfo *mailboxInfo = getMailboxInfo(mailboxId);
+    bool changed = false;
+    if (mailboxInfo->mActive != active ||
+        refreshAlways) {
+
+        // store the new state to permanent storage
+        storeMailboxActive(mailboxId, active);
+
+        mailboxInfo->mActive = active;
+        changed = true;
+        if (active) {
+            // Mailbox is not yet assigned to any indicator
+            if (mailboxInfo->mIndicatorIndex < 0) {
+                mailboxInfo->mIndicatorIndex = getFreeIndicatorIndex();
+            }
+
+            updateIndicator(true,*mailboxInfo);
+        }
+        else {
+            // Indicator not anymore active. Release it.
+            if (mailboxInfo->mIndicatorIndex>=0) {
+                updateIndicator(false,*mailboxInfo);
+                mailboxInfo->mIndicatorIndex = NmAgentIndicatorNotSet;
+            }
+        }
+    }
+    return changed;
+}
+
+/*!
+    Updates indicator status.
+
+    \param mailboxIndex index of the item shown in indicator menu
+    \param active indicator visibility state
+    \param mailboxInfo information of the mailbox
+    \return true if indicator was updated with no errors
+ */
+bool NmMailAgent::updateIndicator(bool active,
+    const NmMailboxInfo& mailboxInfo)
+{
+    NM_FUNCTION;
+    NM_COMMENT(QString("NmMailAgent::updateIndicator(): index=%1, active=%2").
+        arg(mailboxInfo.mIndicatorIndex).arg(active));
+
+    bool ok = false;
+    QString name = QString(NmMailboxIndicatorType).
+        arg(mailboxInfo.mIndicatorIndex);
+
+    QList<QVariant> list;
+    list.append(mailboxInfo.mId.id());
+    list.append(mailboxInfo.mName);
+    list.append(mailboxInfo.mNewUnreadMailIdList.count());
+    list.append(mailboxInfo.mSyncState);
+    list.append(mailboxInfo.mConnectState);
+    list.append(mailboxInfo.mOutboxMails);
+    list.append(mailboxInfo.mIconName);
+    list.append(mLastOutboxCount);
+
+    if (active) {
+        ok = mIndicator->activate(name,list);
+    }
+    else {
+        ok = mIndicator->deactivate(name,list);
+    }
+
+    updateUnreadIndicator();
+
+    return ok;
+}
+
+/*!
+    Update the unread indicator state.
+
+    \param active if true unread indicator is activated otherwise deactivated
+    \return true if the indicator was activated
+ */
+bool NmMailAgent::updateUnreadIndicator(bool active)
+{
+    NM_FUNCTION;
+
+    bool activated = false;
+    bool ok;
+    if (active) {
+        ok = mIndicator->activate(NmUnreadIndicatorName);
+        activated = true;
+    }
+    else {
+        ok = mIndicator->deactivate(NmUnreadIndicatorName);
+    }
+
+    // update the state only if the activation/deactivation was successful
+    if (ok) {
+        mUnreadIndicatorActive = active;
+    }
+
+    return activated;
+}
+
+/*!
+    Opens inbox view to specific mailbox.
+
+    \param mailboxId Id of mailbox
+    \return true if inbox is succesfully opened
+ */
+bool NmMailAgent::launchMailbox(quint64 mailboxId)
+{
+    NM_FUNCTION;
+
+    bool ok(false);
+    XQApplicationManager appManager;
+    XQAiwRequest *request = appManager.create(
+        XQI_EMAIL_INBOX_VIEW, XQOP_EMAIL_INBOX_VIEW, false);
+    // Instance might be NULL if the service is not available.
+    if (request) {
+        QList<QVariant> list;
+        list.append(QVariant(mailboxId));
+        request->setArguments(list);
+        ok = request->send();
+        NM_COMMENT(QString("Launch ok=%1 error=%2").arg(ok).arg(request->lastError()));
+        delete request;
+    }
+    return ok;
+}
+
+/*!
+    Handles message created event.
+
+    \param folderId Id of the folder that includes the message
+    \param messageIds Message ids that are checked
+    \param mailboxId Id of the mailbox that includes the message
+ */
+void NmMailAgent::handleMessageCreatedEvent(const NmId &folderId, const QList<NmId> &messageIds,
+    const NmId &mailboxId)
+{
+    NM_FUNCTION;
+
+    // Check the new messages to make the indicator appear earlier
+    NmMailboxInfo *mailboxInfo = getMailboxInfo(mailboxId);
+
+    // Inbox folder ID may be still unknown
+    if (mailboxInfo->mInboxFolderId.id() == 0) {
+        NmDataPluginInterface *plugin =
+            mPluginFactory->interfaceInstance(mailboxId);
+
+        if (plugin) {
+            mailboxInfo->mInboxFolderId =
+                plugin->getStandardFolderId(mailboxId, NmFolderInbox);
+        }
+    }
+
+    if (folderId == mailboxInfo->mInboxFolderId) {
+        mailboxInfo->mInboxCreatedMessages += messageIds.count();
+
+        foreach (NmId messageId, messageIds) {
+            bool messageUnread = false;
+            mailboxInfo->mMailIdList.append(messageId);
+
+            // double check that the message ID is really new
+            bool newMessage = true;
+            if (mailboxInfo->mNewUnreadMailIdList.indexOf(messageId)>=0) {
+                newMessage = false;
+            }
+
+            // If it is a new message, update the mailbox status
+            if (newMessage) {
+                if (getMessageUnreadInfo(folderId, messageId, mailboxId, messageUnread)) {
+                    if (messageUnread) {
+                        mailboxInfo->mNewUnreadMailIdList.append(messageId);
+                        NM_COMMENT(QString(" new unread messages: count=%1").
+                            arg(mailboxInfo->mNewUnreadMailIdList.count()));
+
+                        if (!mUnreadIndicatorActive) {
+                            // make the "@" appear immediatelly
+                            updateUnreadIndicator(true);
+                        }
+                        updateMailboxState(mailboxId, true, false);
+
+                        // Play the tone as well
+                        playAlertTone();
+                    }
+                }
+            }
+        }
+    }
+
+    // When created a new mail in the outbox, we are in sending state
+    if (mailboxInfo->mOutboxFolderId == folderId) {
+        // The first mail created in the outbox
+        if (mailboxInfo->mOutboxMails <= 0) {
+            NM_COMMENT("NmMailAgent: first mail in outbox");
+        }
+        mailboxInfo->mOutboxMails += messageIds.count();
+        
+        updateMailboxState(mailboxId,true,true);
+        updateSendIndicator();
+    }
+}
+
+
+/*!
+    Handles message changed event.
+    \sa updateUnreadCount
+
+    \param folderId Id of the folder that includes the message
+    \param messageIds Message ids that are checked
+    \param mailboxId Id of the mailbox that includes the message
+ */
+void NmMailAgent::handleMessageChangedEvent(const NmId &folderId,
+    const QList<NmId> &messageIds,
+    const NmId &mailboxId)
+{
+    NM_FUNCTION;
+
+    NmMailboxInfo *mailboxInfo = getMailboxInfo(mailboxId);
+
+    // we are interested only about changes in the inbox
+    if (mailboxInfo && folderId == mailboxInfo->mInboxFolderId) {
+        mailboxInfo->mInboxChangedMessages++;
+
+        if (mailboxInfo->mNewUnreadMailIdList.count()>0) {
+            bool updateMailbox = false;
+
+            // Check how many messages was in the list of new unread mails
+            foreach (NmId messageId, messageIds) {
+                if (mailboxInfo->mNewUnreadMailIdList.indexOf(messageId)>=0) {
+                    bool messageUnread(false);
+                    if (getMessageUnreadInfo(folderId, messageId, mailboxId, messageUnread)) {
+                        // Message is no longer unread
+                        if (!messageUnread) {
+                            mailboxInfo->mNewUnreadMailIdList.removeAll(messageId);
+                            updateMailbox = true;
+                        }
+                    }
+                }
+            }
+            
+            if (updateMailbox) {
+                updateMailboxState(mailboxId);
+                updateUnreadIndicator();
+            }
+        }
+    }
+}
+
+/*!
+    Handles message deleted event.
+
+    \param folderId Id of the folder that includes the message
+    \param messageIds Message ids that are checked
+    \param mailboxId Id of the mailbox that includes the message
+ */
+void NmMailAgent::handleMessageDeletedEvent(const NmId &folderId, const QList<NmId> &messageIds,
+    const NmId &mailboxId)
+{
+    NM_FUNCTION;
+    
+    NmMailboxInfo *mailboxInfo = getMailboxInfo(mailboxId);
+
+    if (mailboxInfo && folderId == mailboxInfo->mInboxFolderId) {
+        mailboxInfo->mInboxDeletedMessages++;
+
+        // Clear the IDs from 'new unread messages' list
+        foreach (NmId messageId, messageIds) {
+            mailboxInfo->mNewUnreadMailIdList.removeAll(messageId);
+        }
+
+        // All new unread messages are now deleted
+        if (mailboxInfo->mNewUnreadMailIdList.count()==0) {
+            NM_COMMENT(" No more new unread messages");
+            updateUnreadIndicator();
+            updateMailboxState(mailboxId);
+        }
+    }
+
+    // Deleted mails from the outbox
+    if (mailboxInfo->mOutboxFolderId == folderId) {
+        mailboxInfo->mOutboxMails -= messageIds.count();
+
+        // Sanity check for the outbox count
+        if (mailboxInfo->mOutboxMails < 0) {
+            mailboxInfo->mOutboxMails = 0;
+        }
+
+        // The last mail was now deleted from outbox
+        if (mailboxInfo->mOutboxMails == 0) {
+            NM_COMMENT("NmMailAgent: last mail deleted from outbox");
+            updateSendIndicator();
+        }
+        updateMailboxState(mailboxId);
+    }
+}
+
+/*!
+    Get next free indicator index, starting from 0.
+
+    \return index of the indicator that is available
+ */
+int NmMailAgent::getFreeIndicatorIndex()
+{
+    NM_FUNCTION;
+
+    int index = 0;
+    bool found(false);
+    do {
+        found = false;
+        foreach (NmMailboxInfo *mailbox, mMailboxes) {
+            if (mailbox->mIndicatorIndex == index &&
+                mailbox->mActive) {
+                found = true;
+                index++;
+            }
+        }
+    }
+    while( found );
+    return index;
+}
+
+/*!
+    Received from NmFrameworkAdapter mailboxEvent signal
+    \sa NmFrameworkAdapter
+
+    \param event Mailbox event type
+    \param mailboxIds Mailbox ids that are checked
+ */
+void NmMailAgent::handleMailboxEvent(NmMailboxEvent event, const QList<NmId> &mailboxIds)
+{
+    NM_FUNCTION;
+    NM_COMMENT(QString("NmMailAgent::handleMailboxEvent(): event=%1").arg(event));
+
+    switch(event) {
+        case NmMailboxCreated:
+            foreach (NmId mailboxId, mailboxIds) {
+                NmMailboxInfo *mailboxInfo = getMailboxInfo(mailboxId); // create a new mailbox if needed
+                if (!mailboxInfo) {
+                    // Unable to initialise the mailbox. Try again later.
+                    NM_COMMENT("Cannot initialise mailbox");
+
+                    qRegisterMetaType<NmId>("NmId");
+                    QMetaObject::invokeMethod(this, "delayedMailboxCreated",
+                        Qt::QueuedConnection, Q_ARG(NmId,mailboxId));
+                }
+
+                // make sure the mailbox activity data is reseted
+                deleteStoredMailboxActivity(mailboxId);
+            }
+            break;
+        case NmMailboxChanged:
+
+            // Mailbox name may have been changed
+            foreach (NmId mailboxId, mailboxIds) {
+                NmMailboxInfo *mailboxInfo = getMailboxInfo(mailboxId);
+                NmMailbox *mailbox(NULL);
+                NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId);
+                if (plugin) {
+                    plugin->getMailboxById(mailboxId,mailbox);
+                }
+                if (mailbox && mailboxInfo) {
+                    if(mailbox->name() != mailboxInfo->mName) {
+                        mailboxInfo->mName = mailbox->name();
+
+                        if (mailboxInfo->mActive) {
+                            // Update the status of the mailbox
+                            updateMailboxState(mailboxId, true, true);
+                        }
+                    }
+                }
+                delete mailbox;
+            }
+            break;
+        case NmMailboxDeleted:
+            foreach (NmId mailboxId, mailboxIds) {
+                // Will hide also the indicator
+                removeMailboxInfo(mailboxId);
+
+                // make sure the mailbox activity data is deleted
+                deleteStoredMailboxActivity(mailboxId);
+            }
+            updateUnreadIndicator();
+            break;
+        default:
+            break;
+    }
+}
+
+/*!
+    Called when mailbox is initialised with a delay. This may happen at least when
+    NmMailboxCreated event is received.
+
+    \param mailboxId id of the mailbox
+*/
+void NmMailAgent::delayedMailboxCreated(const NmId mailboxId)
+{
+    NM_FUNCTION;
+
+    // create and subscribe to the mailbox, if not done earlier
+    getMailboxInfo(mailboxId);
+}
+
+
+/*!
+    Handles the view state changed UI event. The event notification is received
+    via NmUiEventsNotifier.
+
+    \param eventType The type of the UI event.
+    \param viewId The ID of the view the event concerns.
+    \param mailboxId The ID of the mailbox related to the UI event.
+*/
+void NmMailAgent::handleViewStateChangedEvent(
+    const NmUiEventsNotifier::NmUiEventType eventType,
+    const NmUiViewId viewId,
+    const NmId mailboxId)
+{
+    if (eventType == NmUiEventsNotifier::NmViewShownEvent &&
+        viewId == NmUiViewMessageList) {
+        // Get the mailbox info.
+        NmMailboxInfo *info = getMailboxInfo(mailboxId);
+
+        if (info) {
+            // The message list view was shown. If the indicator of the mailbox
+            // in question is active, deactivate it.
+            updateMailboxState(info->mId, false, false);  
+            resetMailboxState(info);
+        }
+    }
+}
+
+
+/*!
+   Map the type name to mailbox info.
+
+   \param type Indicator type name
+   \return NULL if no mailbox match the type
+ */
+NmMailboxInfo *NmMailAgent::getMailboxByType(const QString &type)
+{
+    NM_FUNCTION;
+
+    NmMailboxInfo *foundMailbox = NULL;
+    foreach (NmMailboxInfo *mailbox, mMailboxes) {
+        // mailbox is shown in indicators
+        if (mailbox->mIndicatorIndex >= 0 && mailbox->mActive) {
+            QString typeName = QString(NmMailboxIndicatorType).arg(mailbox->mIndicatorIndex);
+
+            // type names match(!)
+            if (type == typeName) {
+                foundMailbox = mailbox;
+                break;
+            }
+        }
+    }
+    return foundMailbox;
+}
+
+/*!
+    Clear the mailbox state to be 'seen'
+    \param info mailbox that will be reseted
+ */
+void NmMailAgent::resetMailboxState(NmMailboxInfo *info)
+{
+    NM_FUNCTION;
+    
+    info->mActive = false; // indicator is no longer active
+    info->mNewUnreadMailIdList.clear(); // no mails are no longer 'new'
+    storeMailboxActive(info->mId, false);
+    updateUnreadIndicator();
+}
+
+/*!
+    Called when indicator is clicked from the indicator menu
+    - indicator will be hide from the menu
+    - mailbox will be launched
+
+    \param type Indicator type name
+    \param data Data sent by indicator
+ */
+void NmMailAgent::indicatorActivated(const QString &type, const QVariantMap &data)
+{
+    NM_FUNCTION;
+    Q_UNUSED(data);
+
+    // map the indicator type to mailbox
+    NmMailboxInfo *info = getMailboxByType(type);
+    if (info) {
+        resetMailboxState(info);
+
+        launchMailbox(info->mId.id());
+    }
+}
+
+/*!
+    Called when cenrep key value has been changed.
+    - only silence mode key handled
+
+    \param key changed key
+    \param value value for a key
+ */
+void NmMailAgent::valueChanged(const XQSettingsKey &key, const QVariant &value)
+{
+    NM_FUNCTION;
+
+    if(keysEqual(key, NmSilenceModeKey)) {
+        mSilenceMode = value.toInt();
+    }
+}
+
+/*!
+    Received from NmFrameworkAdapter messageEvent signal
+    \sa NmFrameworkAdapter
+
+    \param event Message event
+    \param folderId Folder Id
+    \param messageIds List of message Ids
+    \param mailboxId Id of the mailbox
+ */
+void NmMailAgent::handleMessageEvent(
+    NmMessageEvent event,
+    const NmId &folderId,
+    const QList<NmId> &messageIds,
+    const NmId &mailboxId)
+{
+    NM_FUNCTION;
+    NM_COMMENT(QString("NmMailAgent::handleMessageEvent(): event=%1, id=%2").
+        arg(event).arg(mailboxId.id()));
+
+    switch (event) {
+        case NmMessageCreated: {
+            handleMessageCreatedEvent(folderId, messageIds, mailboxId);
+            break;
+        }
+        case NmMessageChanged: {
+            handleMessageChangedEvent(folderId, messageIds, mailboxId);
+            break;
+        }
+        case NmMessageDeleted: {
+            handleMessageDeletedEvent(folderId, messageIds, mailboxId);
+            break;
+        }
+        default:
+            break;
+    }
+}
+
+/*!
+    Received from NmFrameworkAdapter syncStateEvent signal.
+    \sa NmFrameworkAdapter
+
+    \param state state of synchronization
+    \param event Information related to asynchronous operation
+
+ */
+void NmMailAgent::handleSyncStateEvent(NmSyncState state, const NmOperationCompletionEvent &event)
+{
+    NM_FUNCTION;
+    NM_COMMENT(QString("NmMailAgent::handleSyncStateEvent(): state=%1, id=%2").
+        arg(state).arg(event.mMailboxId.id()));
+
+    NmMailboxInfo *info = getMailboxInfo(event.mMailboxId);
+    if (info) {
+        info->mSyncState = state;
+    }
+}
+
+/*!
+    Received from NmFrameworkAdapter connectionState signal.
+    \sa NmFrameworkAdapter
+
+    \param state Connection state
+    \param mailboxId Id of the mailbox
+    \parma errorcode Error code
+ */
+void NmMailAgent::handleConnectionEvent(NmConnectState state, const NmId mailboxId, int errorcode)
+{
+    NM_FUNCTION;
+    NM_COMMENT(QString("NmMailAgent::handleConnectionEvent(): state=%1, id=%2").
+        arg(state).arg(mailboxId.id()));
+    Q_UNUSED(errorcode);
+
+    NmMailboxInfo *mailboxInfo = getMailboxInfo(mailboxId);
+    if (mailboxInfo) {
+        // Connecting, Connected, Disconnecting, Disconnected
+        mailboxInfo->mConnectState = state;
+    }
+}
+
+/*!
+    Remove a mailbox info entry.
+
+    \param id Id of the mailbox
+    \return true if mailbox info was found.
+ */
+bool NmMailAgent::removeMailboxInfo(const NmId &id)
+{
+    NM_FUNCTION;
+
+    bool found = false;
+    foreach (NmMailboxInfo *mailbox, mMailboxes) {
+        if (mailbox->mId == id) {
+            // Hide the indicator too
+            if(mailbox->mIndicatorIndex>=0) {
+                updateIndicator(false,*mailbox);
+            }
+
+            found = true;
+            mMailboxes.removeAll(mailbox);
+        }
+    }
+    return found;
+}
+
+/*!
+    Create a new mailbox info entry.
+
+    \param id Id of the mailbox
+    \return new mailbox info object
+ */
+NmMailboxInfo *NmMailAgent::createMailboxInfo(const NmId &id)
+{
+    NM_FUNCTION;
+
+    // get information of the mailbox
+    NmMailbox *mailbox = NULL;
+    NmMailboxInfo *info = NULL;
+    NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(id);
+    if (plugin) {
+        plugin->getMailboxById(id, mailbox);
+        if (mailbox) {
+            info = createMailboxInfo(*mailbox,plugin);
+        }
+    }
+
+    return info;
+}
+
+/*!
+    Create a new mailbox info with given parameters
+
+    \param mailbox Mailbox which mailbox info will be created
+    \param plugin Interface to access email data
+    \return new mailbox info object
+ */
+NmMailboxInfo *NmMailAgent::createMailboxInfo(const NmMailbox &mailbox, NmDataPluginInterface *plugin)
+{
+    NM_FUNCTION;
+
+    NmMailboxInfo *mailboxInfo = new NmMailboxInfo();
+    mailboxInfo->mId = mailbox.id();
+    mailboxInfo->mName = mailbox.name();
+
+    mMailboxes.append(mailboxInfo);
+
+    // Subscribe to get all mailbox events
+    plugin->subscribeMailboxEvents(mailboxInfo->mId);
+
+    // get inbox folder ID. It might be still unknown (=0).
+    mailboxInfo->mInboxFolderId = plugin->getStandardFolderId(
+        mailbox.id(), NmFolderInbox );
+
+    // get outbox folder ID
+    mailboxInfo->mOutboxFolderId = plugin->getStandardFolderId(
+        mailbox.id(), NmFolderOutbox );
+
+    // Get branded mailbox icon
+    NmMailbox mailbox2( mailbox );
+    QString domainName = mailbox2.address().address();
+    EmailMailboxInfo emailMailboxInfo;
+    mailboxInfo->mIconName =
+        emailMailboxInfo.mailboxIcon(domainName);
+
+    return mailboxInfo;
+}
+
+/*!
+    Return mailbox info class with mailbox id. If no class is found,
+    create a new instance with given id.
+
+    \param id Id of the mailbox
+    \return mailbox info object
+ */
+NmMailboxInfo *NmMailAgent::getMailboxInfo(const NmId &id)
+{
+    NM_FUNCTION;
+
+    foreach (NmMailboxInfo *mailbox, mMailboxes) {
+        if (mailbox->mId == id) {
+            return mailbox;
+        }
+    }
+
+    // Not found. Create a new mailbox info.
+    return createMailboxInfo(id);
+}
+
+/*!
+    Finds out if the message is unread.
+
+    \param folderId the id of the folder that includes the message
+    \param messageIds the message ids that are checked
+    \param mailboxId the id of the mailbox that includes the message
+    \param unreadMessage true if there was unread messages
+    \return true if info fetching was successful
+ */
+bool NmMailAgent::getMessageUnreadInfo(const NmId &folderId,
+    const NmId &messageId, const NmId &mailboxId, bool &unreadMessage)
+{
+    NM_FUNCTION;
+
+    NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId);
+    bool ok(false);
+
+    if (plugin) {
+        NmMessage *message=NULL;
+        plugin->getMessageById(mailboxId, folderId, messageId, message);
+        if (message) {
+            ok = true;
+            NmMessageEnvelope envelope = message->envelope();
+            if (!envelope.isRead()) {
+                unreadMessage = true;
+            }
+            delete message;
+        }
+    }
+    return ok;
+}
+
+/*!
+    Plays email alert tone when new messages arrive.
+
+	\returns true if the tone was played
+ */
+bool NmMailAgent::playAlertTone()
+{
+    NM_FUNCTION;
+    bool played(false);
+
+    if (mAlertToneAllowed) {
+        // Play tone only when phone is not in silence mode.
+        if (!mSilenceMode) {
+            // Must instantiate it again to make sure correct tone is played  
+            XQSystemToneService systemTone;
+            systemTone.playTone(XQSystemToneService::EmailAlertTone);
+        }
+
+        // Execute the vibra effect.
+        if (mVibra) {
+            TRAP_IGNORE(mVibra->StartVibraL(NmAgentDefaultVibraDuration));
+        }
+
+        // play alert only once per minute
+        mAlertToneAllowed = false;
+        QTimer::singleShot(NmAgentAlertToneTimer, this, SLOT(enableAlertTone()));
+        played = true;
+    }
+
+    return played;
+}
+
+/*!
+    Allows alert tune to be played again.
+ */
+void NmMailAgent::enableAlertTone()
+{
+    NM_FUNCTION;
+
+    mAlertToneAllowed = true;
+}
+
+/*!
+    Update send indicator according to outbox state.
+ */
+void NmMailAgent::updateSendIndicator()
+{
+    NM_FUNCTION;
+
+    // Get number of mails in outboxes
+    int outboxMails(0);
+    foreach (NmMailboxInfo *mailboxInfo, mMailboxes) {
+        outboxMails += mailboxInfo->mOutboxMails;
+    }
+
+    if( outboxMails == 0 ) {
+        mIndicator->deactivate(NmSendIndicatorName);
+    }
+    else if (outboxMails > mLastOutboxCount) {
+        // New mails detected in outbox
+
+        // indicator will disappear automatically after a delay
+        mIndicator->activate(NmSendIndicatorName);
+    }
+
+    mLastOutboxCount = outboxMails;
+}
+
+/*!
+    Store the mailbox active information to permanent storage.
+
+    \param mailboxId Id of the mailbox
+    \param active true if the mailbox is active
+ */
+void NmMailAgent::storeMailboxActive(const NmId &mailboxId, bool active)
+{
+    NM_FUNCTION;
+
+    if (mSettingManager) {
+        XQCentralRepositorySettingsKey key(NmRepositoryId, mailboxId.id());
+        XQCentralRepositoryUtils utils(*mSettingManager);
+
+        if (active) {
+            // when mailbox is active, key can be deleted
+            utils.deleteKey(key);
+        }
+        else {
+            utils.createKey(key,(int)active);
+        }
+    }
+}
+
+/*!
+    Get the mailbox activity state.
+
+    \param mailboxId id of the mailbox
+    \return true if the mailbox is active or no information was stored earlier
+ */
+bool NmMailAgent::isMailboxActive(const NmId &mailboxId)
+{
+    NM_FUNCTION;
+
+    bool mailboxActive(true);
+    if (mSettingManager) {
+        XQCentralRepositorySettingsKey key(NmRepositoryId, mailboxId.id());
+        QVariant value = mSettingManager->readItemValue(key, XQSettingsManager::TypeInt);
+        if (value.isValid()) {
+            NM_COMMENT(QString("NmMailAgent::isMailboxActive - value=%1").arg(value.toInt()));
+            mailboxActive = value.toInt();
+        }
+    }
+    return mailboxActive;
+}
+
+/*!
+    Delete all stored activity information for the mailbox id.
+
+    \param mailboxId id of the mailbox
+ */
+void NmMailAgent::deleteStoredMailboxActivity(const NmId &mailboxId)
+{
+    NM_FUNCTION;
+
+    // deactivation delete the key too
+    storeMailboxActive(mailboxId, false);
+}
+
+// End of file