diff -r 578830873419 -r ecc8def7944a emailservices/nmailagent/src/nmmailagent.cpp --- a/emailservices/nmailagent/src/nmmailagent.cpp Fri Apr 16 14:51:52 2010 +0300 +++ b/emailservices/nmailagent/src/nmmailagent.cpp Mon May 03 12:23:15 2010 +0300 @@ -19,7 +19,8 @@ #include "nmmailagent.h" // CONSTS -const int maxUnreadCount = 1; // 1 is enough +const int NmAgentMaxUnreadCount = 1; // 1 is enough +const int NmAgentIndicatorNotSet = -1; /*! @@ -28,80 +29,88 @@ \brief Main class for receiving email events and passing them to the HbIndicator */ -/*! - Creates list of folder paths where plug-ins can be loaded from. - \return folder path list. -*/ -QStringList NmMailAgent::pluginFolders() -{ - const QString nmPluginPath("resource/plugins"); - QStringList pluginDirectories; - QFileInfoList driveList = QDir::drives(); - - foreach(const QFileInfo &driveInfo, driveList) { - QString pluginDirectory = - driveInfo.absolutePath() + nmPluginPath; - - if (QFileInfo(pluginDirectory).exists()) { - pluginDirectories.append(pluginDirectory); - } - } - - return pluginDirectories; -} - NmMailboxInfo::NmMailboxInfo() { mId = 0; + mIndicatorIndex = NmAgentIndicatorNotSet; mSyncState = SyncComplete; mConnectState = Disconnected; mUnreadMails = 0; + mOutboxMails = 0; + mInboxFolderId = 0; + mOutboxFolderId = 0; + mInboxCreatedMessages = 0; + mInboxChangedMessages = 0; + mInboxDeletedMessages = 0; mActive = false; } NmMailAgent::NmMailAgent() : - mAdapter(NULL), - mActiveIndicators(0) + mPluginFactory(NULL), + mSendingState(false) { NMLOG("NmMailAgent::NmMailAgent"); } /*! + Delayed start +*/ +void NmMailAgent::delayedStart() +{ + NMLOG("NmMailAgent::delayedStart"); + if (!init()) { + // Initialisation failed. Quit the agent. + QCoreApplication::exit(1); + } +} + +/*! Initialise the agent. \return true if succesfully started. */ bool NmMailAgent::init() { - if (!loadAdapter()) { - // Failed to load NmFrameworkAdapter + NMLOG("NmMailAgent::init"); + mPluginFactory = NmDataPluginFactory::instance(); + if (!mPluginFactory) { + NMLOG("NmMailAgent::init PluginFactory not created"); return false; } - // Start listening events - connect(mAdapter, SIGNAL(mailboxEvent(NmMailboxEvent, const QList&)), - this, SLOT(handleMailboxEvent(NmMailboxEvent, const QList &))); + QList *plugins = mPluginFactory->pluginInstances(); + + foreach (QObject *plugin, *plugins) { + if (plugin) { + // Start listening events + connect(plugin, SIGNAL(mailboxEvent(NmMailboxEvent, const QList&)), + this, SLOT(handleMailboxEvent(NmMailboxEvent, const QList &)), + Qt::UniqueConnection); - connect(mAdapter, SIGNAL(messageEvent( - NmMessageEvent, const NmId &, const QList &, const NmId&)), - this, SLOT(handleMessageEvent( - NmMessageEvent, const NmId &, const QList &, const NmId&))); + connect(plugin, SIGNAL(messageEvent( + NmMessageEvent, const NmId &, const QList &, const NmId&)), + this, SLOT(handleMessageEvent( + NmMessageEvent, const NmId &, const QList &, const NmId&)), + Qt::UniqueConnection); - connect(mAdapter, SIGNAL(syncStateEvent(NmSyncState, const NmId)), - this, SLOT(handleSyncStateEvent(NmSyncState, const NmId))); + connect(plugin, SIGNAL(syncStateEvent(NmSyncState, const NmOperationCompletionEvent&)), + this, SLOT(handleSyncStateEvent(NmSyncState, const NmOperationCompletionEvent&)), + Qt::UniqueConnection); - connect(mAdapter, SIGNAL(connectionEvent(NmConnectState, const NmId)), - this, SLOT(handleConnectionEvent(NmConnectState, const NmId))); + connect(plugin, SIGNAL(connectionEvent(NmConnectState, const NmId)), + this, SLOT(handleConnectionEvent(NmConnectState, const NmId)), + Qt::UniqueConnection); + } + } // load all current mailboxes initMailboxStatus(); - updateStatus(); return true; } NmMailAgent::~NmMailAgent() { - delete mAdapter; qDeleteAll(mMailboxes); + NmDataPluginFactory::releaseInstance(mPluginFactory); } /*! @@ -111,17 +120,37 @@ { NMLOG("NmMailAgent::initMailboxStatus"); QList mailboxes; - mAdapter->listMailboxes(mailboxes); - foreach (const NmMailbox* mailbox, mailboxes) { - if (mailbox) { - NmMailboxInfo *mailboxInfo = createMailboxInfo(*mailbox); - if (mailboxInfo) { - mailboxInfo->mUnreadMails = getUnreadCount(mailbox->id(),maxUnreadCount); - updateMailboxActivity(mailbox->id(), isMailboxActive(*mailboxInfo)); + QList *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 i(mailboxes); + i.toBack(); + while (i.hasPrevious()) { + const NmMailbox *mailbox = i.previous(); + if (mailbox) { + NmMailboxInfo *mailboxInfo = createMailboxInfo(*mailbox,plugin); + if (mailboxInfo) { + mailboxInfo->mUnreadMails = getUnreadCount(mailbox->id(),NmAgentMaxUnreadCount); + mailboxInfo->mOutboxMails = getOutboxCount(mailbox->id()); + + // Create indicator for visible mailboxes + updateMailboxState(mailbox->id(), + isMailboxActive(*mailboxInfo), + false); + } } } + qDeleteAll(mailboxes); } - qDeleteAll(mailboxes); } /*! @@ -135,109 +164,115 @@ NMLOG("NmMailAgent::getUnreadCount"); int count(0); - // get inbox folder ID - NmId inboxId = mAdapter->getStandardFolderId( - mailboxId, NmFolderInbox ); + NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); - // get list of messages in inbox - QList messageList; - mAdapter->listMessages(mailboxId, inboxId, messageList); + if (plugin) { + // get inbox folder ID + NmId inboxId = plugin->getStandardFolderId( + mailboxId, NmFolderInbox ); + + // get list of messages in inbox + QList messageList; + plugin->listMessages(mailboxId, inboxId, messageList); - foreach (const NmMessageEnvelope* envelope, messageList) { - // if the message is not read, it is "unread" - if (!envelope->isRead()) { - count++; + foreach (const NmMessageEnvelope* envelope, messageList) { + // if the message is not read, it is "unread" + if (!envelope->isRead()) { + count++; - // No more unread mails are needed - if (count >= maxCount) { - break; - } - } + // No more unread mails are needed + if (count >= maxCount) { + break; + } + } + } + qDeleteAll(messageList); } - qDeleteAll(messageList); NMLOG(QString("NmMailAgent::getUnreadCount count=%1").arg(count)); return count; } /*! - Load NmFrameworkAdapter from plugins. - \return true if adapter is loaded succesfully. + Get mailbox count in outbox folder + \param mailboxId id of the mailbox + \param maxCount max number of outbox mails that is needed + \return number of mails in the outbox */ -bool NmMailAgent::loadAdapter() +int NmMailAgent::getOutboxCount(const NmId &mailboxId) { - QStringList directories(pluginFolders()); + NMLOG("NmMailAgent::getOutboxCount"); + int count(0); + + NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); - foreach (const QString &pluginPath, directories) { - QPluginLoader *loader = - new QPluginLoader(pluginPath + "/nmframeworkadapter.qtplugin"); - if (loader) { - mAdapter = static_cast(loader->instance()); - if (mAdapter) { - return true; - } - } - } - NMLOG("NmMailAgent::loadAdapter failed"); - return false; + if (plugin) { + // get outbox folder ID + NmId outboxId = plugin->getStandardFolderId( mailboxId, NmFolderOutbox ); + + // get list of messages in outbox + QList messageList; + plugin->listMessages(mailboxId, outboxId, messageList); + count = messageList.count(); + qDeleteAll(messageList); + } + NMLOG(QString("NmMailAgent::getOutboxCount count=%1").arg(count)); + + return count; } /*! - Update the mailbox visibility + 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::updateMailboxActivity(const NmId &mailboxId, bool active) +bool NmMailAgent::updateMailboxState(const NmId &mailboxId, + bool active, bool refreshAlways) { + // Update the global sending state + mSendingState = false; + foreach (NmMailboxInfo *mailboxInfo, mMailboxes) { + if (mailboxInfo->mOutboxMails>0) { + mSendingState = true; + break; + } + } + NmMailboxInfo *mailboxInfo = getMailboxInfo(mailboxId); bool changed = false; - if (mailboxInfo->mActive != active) { + if (mailboxInfo->mActive != active || + refreshAlways) { mailboxInfo->mActive = active; changed = true; if (active) { - // Mailbox becomes active again. Move to the bottom of the list. - mMailboxes.removeAll(mailboxInfo); - mMailboxes.append(mailboxInfo); + // Mailbox is not yet assigned to any indicator + if (mailboxInfo->mIndicatorIndex < 0) { + mailboxInfo->mIndicatorIndex = getIndicatorIndex(); + } + + updateIndicator(true,*mailboxInfo); + } + else { + // Indicator not anymore active. Release it. + if (mailboxInfo->mIndicatorIndex>=0) { + updateIndicator(false,*mailboxInfo); + mailboxInfo->mIndicatorIndex = NmAgentIndicatorNotSet; + } } } return changed; } /*! - Updates status according to current information -*/ -void NmMailAgent::updateStatus() -{ - NMLOG("NmMailAgent::updateStatus"); - - int activeIndicators = 0; - - // Update the indicators - foreach (NmMailboxInfo *mailboxInfo, mMailboxes) { - // Show only active mailboxes - if (mailboxInfo->mActive) { - updateIndicator(activeIndicators,true,*mailboxInfo); - activeIndicators++; - } - } - - // Hide the indicator that are not needed anymore - for (int i=activeIndicators;i0) { + if (mailboxInfo.mUnreadMails>0 || mailboxInfo.mOutboxMails>0) { return true; } return false; @@ -250,14 +285,15 @@ \param mailboxInfo information of the mailbox \return true if indicator was updated with no errors */ -bool NmMailAgent::updateIndicator(int mailboxIndex, bool active, +bool NmMailAgent::updateIndicator(bool active, const NmMailboxInfo& mailboxInfo) { NMLOG(QString("NmMailAgent::updateIndicator index=%1 active=%2 unread=%3"). - arg(mailboxIndex).arg(active).arg(mailboxInfo.mUnreadMails)); + arg(mailboxInfo.mIndicatorIndex).arg(active).arg(mailboxInfo.mUnreadMails)); bool ok = false; - QString name = QString("com.nokia.nmail.indicatorplugin_")+mailboxIndex+"/1.0"; + QString name = QString("com.nokia.nmail.indicatorplugin_%1/1.0"). + arg(mailboxInfo.mIndicatorIndex); QList list; list.append(mailboxInfo.mId.id()); @@ -265,6 +301,8 @@ list.append(mailboxInfo.mUnreadMails); list.append(mailboxInfo.mSyncState); list.append(mailboxInfo.mConnectState); + list.append(mailboxInfo.mOutboxMails); + list.append(mSendingState); HbIndicator indicator; if (active) { @@ -277,31 +315,59 @@ } /*! + Get next free indicator index, starting from 0 + @return index of the indicator that is available + */ +int NmMailAgent::getIndicatorIndex() +{ + 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 */ void NmMailAgent::handleMailboxEvent(NmMailboxEvent event, const QList &mailboxIds) { NMLOG(QString("NmMailAgent::handleMailboxEvent %1").arg(event)); - bool updateNeeded(false); switch(event) { case NmMailboxCreated: foreach (NmId mailboxId, mailboxIds) { getMailboxInfo(mailboxId); // create a new mailbox if needed - updateNeeded = true; } break; case NmMailboxChanged: + // Mailbox name may have been changed foreach (NmId mailboxId, mailboxIds) { NmMailboxInfo *mailboxInfo = getMailboxInfo(mailboxId); NmMailbox *mailbox(NULL); - mAdapter->getMailboxById(mailboxId,mailbox); + NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(mailboxId); + if (plugin) { + plugin->getMailboxById(mailboxId,mailbox); + } if (mailbox && mailboxInfo) { if(mailbox->name() != mailboxInfo->mName) { mailboxInfo->mName = mailbox->name(); - updateNeeded = true; + + if (mailboxInfo->mActive) { + // Update the status of the mailbox + updateMailboxState(mailboxId, true, true); + } } } delete mailbox; @@ -309,23 +375,18 @@ break; case NmMailboxDeleted: foreach (NmId mailboxId, mailboxIds) { - if (removeMailboxInfo(mailboxId)) { - updateNeeded = true; - } + // Will hide also the indicator + removeMailboxInfo(mailboxId); } break; default: break; } - - if (updateNeeded) { - updateStatus(); - } } /*! Received from NmFrameworkAdapter messageEvent signal - \sa NmFrameWorkAdapter + \sa NmFrameworkAdapter */ void NmMailAgent::handleMessageEvent( NmMessageEvent event, @@ -334,56 +395,114 @@ const NmId& mailboxId) { NMLOG(QString("NmMailAgent::handleMessageEvent %1 %2").arg(event).arg(mailboxId.id())); - Q_UNUSED(folderId); - Q_UNUSED(messageIds); + bool updateNeeded = false; switch (event) { + case NmMessageCreated: { + NmMailboxInfo *mailboxInfo = getMailboxInfo(mailboxId); + + if (folderId==mailboxInfo->mInboxFolderId) { + mailboxInfo->mInboxCreatedMessages++; + } + + // 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) { + updateNeeded = true; + } + mailboxInfo->mOutboxMails += messageIds.count(); + } + break; + } case NmMessageChanged: { NmMailboxInfo *mailboxInfo = getMailboxInfo(mailboxId); + + if (folderId==mailboxInfo->mInboxFolderId) { + mailboxInfo->mInboxChangedMessages++; + } + // If not currently syncronizing the mailbox, this may mean // that a message was read/unread if (mailboxInfo && mailboxInfo->mSyncState==SyncComplete) { - // check the unread status here again - mailboxInfo->mUnreadMails = getUnreadCount(mailboxId,maxUnreadCount); - if(updateMailboxActivity(mailboxId, isMailboxActive(*mailboxInfo))) { - updateStatus(); - } + // check the unread status again + mailboxInfo->mUnreadMails = getUnreadCount(mailboxId,NmAgentMaxUnreadCount); + updateNeeded = true; } break; } + case NmMessageDeleted: { + NmMailboxInfo *mailboxInfo = getMailboxInfo(mailboxId); + + if (folderId==mailboxInfo->mInboxFolderId) { + mailboxInfo->mInboxDeletedMessages++; + } + + // 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 + if (mailboxInfo->mOutboxMails == 0) { + updateNeeded = true; + } + } + break; + } default: break; } - // Do not perform an update here, just in handleSyncState + if (updateNeeded) { + NmMailboxInfo *mailboxInfo = getMailboxInfo(mailboxId); + updateMailboxState(mailboxId, + isMailboxActive(*mailboxInfo), true /* force refresh */); + } } /*! Received from NmFrameworkAdapter syncStateEvent signal - \sa NmFrameWorkAdapter + \sa NmFrameworkAdapter */ void NmMailAgent::handleSyncStateEvent( NmSyncState state, - const NmId mailboxId) + const NmOperationCompletionEvent &event) { - NMLOG(QString("NmMailAgent::handleSyncStateEvent %1 %2").arg(state).arg(mailboxId.id())); - NmMailboxInfo *info = getMailboxInfo(mailboxId); + NMLOG(QString("NmMailAgent::handleSyncStateEvent %1 %2").arg(state).arg(event.mMailboxId.id())); + NmMailboxInfo *info = getMailboxInfo(event.mMailboxId); if (info) { info->mSyncState = state; + + if (state==Synchronizing) { + // Reset counters when sync is started + info->mInboxCreatedMessages = 0; + info->mInboxChangedMessages = 0; + info->mInboxDeletedMessages = 0; + } + else if (state==SyncComplete) { + // Check the unread status here again + info->mUnreadMails = getUnreadCount(event.mMailboxId,NmAgentMaxUnreadCount); - if (state==SyncComplete) { - // check the unread status here again - info->mUnreadMails = getUnreadCount(mailboxId,maxUnreadCount); - if(updateMailboxActivity(mailboxId, isMailboxActive(*info))) { - updateStatus(); - } + // Refresh the indicator if messages created or changed + NMLOG(QString(" created=%1, changed=%1, deleted=%1"). + arg(info->mInboxCreatedMessages). + arg(info->mInboxChangedMessages). + arg(info->mInboxDeletedMessages)); + bool refresh = (info->mInboxCreatedMessages > 0) || (info->mInboxChangedMessages > 0); + + updateMailboxState(event.mMailboxId, isMailboxActive(*info), refresh); } } } /*! Received from NmFrameworkAdapter connectionState signal - \sa NmFrameWorkAdapter + \sa NmFrameworkAdapter */ void NmMailAgent::handleConnectionEvent(NmConnectState state, const NmId mailboxId) { @@ -393,7 +512,6 @@ // Connecting, Connected, Disconnecting, Disconnected mailboxInfo->mConnectState = state; } - updateStatus(); } /*! @@ -405,6 +523,11 @@ 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); } @@ -420,18 +543,23 @@ { // get information of the mailbox NmMailbox *mailbox = NULL; - mAdapter->getMailboxById(id, mailbox); - if (mailbox) { - return createMailboxInfo(*mailbox); + NmMailboxInfo *info = NULL; + NmDataPluginInterface *plugin = mPluginFactory->interfaceInstance(id); + if (plugin) { + plugin->getMailboxById(id, mailbox); + if (mailbox) { + info = createMailboxInfo(*mailbox,plugin); + } } - return NULL; + + return info; } /*! Create a new mailbox info with given parameters \return new mailbox info object */ -NmMailboxInfo *NmMailAgent::createMailboxInfo(const NmMailbox& mailbox) +NmMailboxInfo *NmMailAgent::createMailboxInfo(const NmMailbox& mailbox,NmDataPluginInterface *plugin) { NmMailboxInfo *mailboxInfo = new NmMailboxInfo(); mailboxInfo->mId = mailbox.id(); @@ -440,7 +568,16 @@ mMailboxes.append(mailboxInfo); // Subscribe to get all mailbox events - mAdapter->subscribeMailboxEvents(mailboxInfo->mId); + plugin->subscribeMailboxEvents(mailboxInfo->mId); + + // get inbox folder ID + mailboxInfo->mInboxFolderId = plugin->getStandardFolderId( + mailbox.id(), NmFolderInbox ); + + // get outbox folder ID + mailboxInfo->mOutboxFolderId = plugin->getStandardFolderId( + mailbox.id(), NmFolderOutbox ); + return mailboxInfo; }