emailuis/nmailui/src/nmmessagelistview.cpp
changeset 18 578830873419
child 20 ecc8def7944a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailuis/nmailui/src/nmmessagelistview.cpp	Fri Apr 16 14:51:52 2010 +0300
@@ -0,0 +1,534 @@
+/*
+* 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:
+*
+*/
+
+static const char *NMUI_MESSAGE_LIST_VIEW_XML = ":/docml/nmmessagelistview.docml";
+static const char *NMUI_MESSAGE_LIST_VIEW = "NmMessageListView";
+static const char *NMUI_MESSAGE_LIST_TREE_LIST = "MessageTreeList";
+static const char *NMUI_MESSAGE_LIST_NO_MESSAGES = "MessageListNoMessages";
+static const char *NMUI_MESSAGE_LIST_FOLDER_LABEL = "folderLabel";
+static const char *NMUI_MESSAGE_LIST_SYNC_ICON = "syncIcon";
+
+static const int nmNoMessagesDelay = 200;
+
+#include "nmuiheaders.h"
+
+/*!
+	\class NmMessageListView
+	\brief Message list view
+*/
+
+/*!
+    Constructor
+*/
+NmMessageListView::NmMessageListView(
+    NmApplication &application,
+    NmUiStartParam* startParam,
+    NmUiEngine &uiEngine,
+    NmMailboxListModel &mailboxListModel,
+    NmMessageListModel &messageListModel,
+    HbDocumentLoader *documentLoader,
+    QGraphicsItem *parent)
+: NmBaseView(startParam, parent),
+mApplication(application),
+mMessageListWidget(NULL),
+mUiEngine(uiEngine),
+mMailboxListModel(mailboxListModel),
+mMessageListModel(messageListModel),
+mDocumentLoader(documentLoader),
+mItemContextMenu(NULL),
+mLongPressedItem(NULL),
+mNoMessagesLabel(NULL)
+{
+    // Load view layout
+    loadViewLayout();
+    // Set mailbox name to title pane
+    setMailboxName();
+    // Init tree view
+    initTreeView();
+    // Refresh list
+    refreshList();
+}
+
+/*!
+    Destructor
+*/
+NmMessageListView::~NmMessageListView()
+{
+    delete mDocumentLoader;
+    mWidgetList.clear();
+    if (mItemContextMenu){
+        mItemContextMenu->clearActions();
+    }
+    delete mItemContextMenu;
+    mUiEngine.releaseMessageListModel(mStartParam->mailboxId());
+}
+
+/*!
+    View layout loading from XML
+*/
+void NmMessageListView::loadViewLayout()
+{
+    // Use document loader to load the view
+    bool ok = false;
+    setObjectName(QString(NMUI_MESSAGE_LIST_VIEW));
+    QObjectList objectList;
+    objectList.append(this);
+    // Pass the view to documentloader. Document loader uses this view
+    // when docml is parsed, instead of creating new view.
+    if (mDocumentLoader) {
+        mDocumentLoader->setObjectTree(objectList);
+        mWidgetList = mDocumentLoader->load(NMUI_MESSAGE_LIST_VIEW_XML, &ok);
+    }
+
+    if (ok == true && mWidgetList.count()) {
+        // Get message list widget
+        mMessageListWidget = qobject_cast<HbTreeView *>
+            (mDocumentLoader->findWidget(NMUI_MESSAGE_LIST_TREE_LIST));
+        if (mMessageListWidget) {
+            NMLOG("nmailui: List object loaded");
+            // Set item prototype.
+            mMessageListWidget->setItemPrototype(new NmMessageListViewItem());
+            mMessageListWidget->setItemRecycling(true);
+            mMessageListWidget->contentWidget()->setProperty("indentation", 0);
+            mMessageListWidget->setScrollDirections(Qt::Vertical);
+            mMessageListWidget->setClampingStyle(HbScrollArea::BounceBackClamping);
+            mMessageListWidget->setFrictionEnabled(true);
+        }
+        else {
+            NMLOG("nmailui: List object loading failed");
+        }
+        mNoMessagesLabel = qobject_cast<HbLabel *>
+            (mDocumentLoader->findWidget(NMUI_MESSAGE_LIST_NO_MESSAGES));
+        if (mNoMessagesLabel) {
+            mNoMessagesLabel->setAlignment(Qt::AlignCenter);
+            mNoMessagesLabel->setFontSpec(HbFontSpec(HbFontSpec::Primary));
+            mNoMessagesLabel->hide();
+            mNoMessagesLabel->setPlainText(hbTrId("txt_mail_dblist_no_messages"));
+        }
+        else{
+            NMLOG("nmailui: (no messages) object loading failed");
+        }
+        
+        mFolderLabel = qobject_cast<HbLabel *>(mDocumentLoader->findWidget(NMUI_MESSAGE_LIST_FOLDER_LABEL));
+        if (mFolderLabel) {
+            mFolderLabel->setPlainText(hbTrId("txt_mail_subhead_inbox"));
+        }
+        
+        mSyncIcon = qobject_cast<HbLabel *>(mDocumentLoader->findWidget(NMUI_MESSAGE_LIST_SYNC_ICON));
+        if (mSyncIcon) {
+            mSyncIcon->setIcon(NmIcons::getIcon(NmIcons::NmIconOffline));
+        }
+
+        // Connect options menu about to show to create options menu function
+        QObject::connect(menu(), SIGNAL(aboutToShow()),
+        		this, SLOT(createOptionsMenu()));
+        
+        QObject::connect(&mUiEngine, SIGNAL(syncStateEvent(NmSyncState, const NmId &)),
+                                this, SLOT(handleSyncStateEvent(NmSyncState, const NmId &)));
+        
+        QObject::connect(&mUiEngine, SIGNAL(connectionEvent(NmConnectState, const NmId &)),
+                                        this, SLOT(handleConnectionEvent(NmConnectState, const NmId &)));
+        
+        // Menu needs one dummy item so that aboutToShow signal is emitted.
+        NmAction *dummy = new NmAction(0);
+        menu()->addAction(dummy);
+    }
+    else {
+        NMLOG("nmailui: Resource loading failed");
+    }
+
+    //create toolbar
+    createToolBar();
+}
+
+/*!
+    initTreeView
+*/
+void NmMessageListView::initTreeView()
+{
+    // Get mailbox widget pointer and set parameters
+    if (mMessageListWidget){
+        QObject::connect(mMessageListWidget,
+                SIGNAL(activated(const QModelIndex &)), this,
+                SLOT(itemActivated(const QModelIndex &)));
+        QObject::connect(mMessageListWidget,
+                SIGNAL(longPressed(HbAbstractViewItem*, QPointF)), this,
+                SLOT(showItemContextMenu(HbAbstractViewItem*, QPointF)));
+        mMessageListWidget->setFocus();
+        mItemContextMenu = new HbMenu();
+    }
+}
+
+
+/*!
+    Reload view contents with new start parameters
+    Typically when view is already open and external view activation occurs
+    for this same view
+*/
+void NmMessageListView::reloadViewContents(NmUiStartParam* startParam)
+{
+    // Check start parameter validity, message view cannot
+    // be updated if given parameter is zero.
+    if (startParam&&startParam->viewId()==NmUiViewMessageList&&
+        startParam->folderId()!=0) {
+        // Delete existing start parameter data
+        delete mStartParam;
+        mStartParam=NULL;
+        // Store new start parameter data
+        mStartParam=startParam;
+        refreshList();
+    }
+    else {
+        NMLOG("nmailui: Invalid message list start parameter");
+        // Unused start parameter needs to be deleted
+        delete startParam;
+    }
+}
+
+
+/*!
+    Return view id
+*/
+NmUiViewId NmMessageListView::nmailViewId() const
+{
+    return NmUiViewMessageList;
+}
+
+/*!
+    Refresh list
+*/
+void NmMessageListView::refreshList()
+{
+    NmId mailboxId = mMessageListModel.currentMailboxId();
+    if (mSyncIcon && mailboxId == mMessageListModel.currentMailboxId()) {
+        if (mUiEngine.syncState(mailboxId) == Synchronizing) {
+            mSyncIcon->setIcon(NmIcons::getIcon(NmIcons::NmIconSynching));
+        }
+        else {
+            if (mUiEngine.connectionState(mailboxId) == Connected) {
+                mSyncIcon->setIcon(NmIcons::getIcon(NmIcons::NmIconOnline));
+            }
+            else {
+                mSyncIcon->setIcon(NmIcons::getIcon(NmIcons::NmIconOffline));
+            }
+        }
+    }
+    
+    if (mMessageListWidget) {
+        mMessageListWidget->setModel(static_cast<QStandardItemModel*>(&mMessageListModel));
+        QObject::connect(&mMessageListModel, SIGNAL(rowsInserted(const QModelIndex&,int,int)),
+                this, SLOT(itemsAdded(const QModelIndex&,int,int)));
+        QObject::connect(&mMessageListModel, SIGNAL(rowsRemoved(const QModelIndex&,int,int)),
+                this, SLOT(itemsRemoved()));
+        QObject::connect(&mMessageListModel, SIGNAL(setNewParam(NmUiStartParam*)),
+                this, SLOT(reloadViewContents(NmUiStartParam*)));
+        
+        if (mMessageListModel.rowCount()==0){
+            // Single shot timer to display text smoothly after layout has been constructed
+            QTimer::singleShot(nmNoMessagesDelay, this, SLOT(showNoMessagesText()));
+        }
+    }
+}
+
+void NmMessageListView::handleSyncStateEvent(NmSyncState syncState, const NmId & mailboxId)
+{
+    if (mSyncIcon && mailboxId == mMessageListModel.currentMailboxId()) {
+        if (syncState == Synchronizing) {
+            mSyncIcon->setIcon(NmIcons::getIcon(NmIcons::NmIconSynching));
+        }
+        else {
+            if (mUiEngine.connectionState(mailboxId) == Connected) {
+                mSyncIcon->setIcon(NmIcons::getIcon(NmIcons::NmIconOnline));
+            }
+            else {
+                mSyncIcon->setIcon(NmIcons::getIcon(NmIcons::NmIconOffline));
+            }
+        }
+    }
+}
+
+void NmMessageListView::handleConnectionEvent(NmConnectState connectState, const NmId &mailboxId)
+{
+    if (mSyncIcon && mailboxId == mMessageListModel.currentMailboxId() && mUiEngine.syncState(mailboxId) != Synchronizing) {
+        if (connectState == Connected) {
+            mSyncIcon->setIcon(NmIcons::getIcon(NmIcons::NmIconOnline));
+        }
+        else {
+            mSyncIcon->setIcon(NmIcons::getIcon(NmIcons::NmIconOffline));
+        }
+    }
+}
+
+/*!
+    Long keypress handling
+*/
+void NmMessageListView::showItemContextMenu(HbAbstractViewItem *listViewItem, const QPointF &coords)
+{
+    // Store long press item for later use with response
+    mLongPressedItem = mMessageListModel.data(
+            listViewItem->modelIndex(), Qt::DisplayRole).value<NmMessageListModelItem*>();
+    if (mItemContextMenu && mLongPressedItem && mLongPressedItem->itemType() ==
+        NmMessageListModelItem::NmMessageItemMessage) {
+
+        // Clear previous items from context menu
+        mItemContextMenu->clearActions();
+        NmUiExtensionManager &extMngr = mApplication.extManager();
+        QList<NmAction*> list;
+        // Fetch items from extension based on item
+        NmMessageEnvelope *envelope = mLongPressedItem->envelopePtr();
+        if (envelope){
+            NmActionRequest request(this, NmActionContextMenu, NmActionContextViewMessageList,
+                    NmActionContextDataMessage, mStartParam->mailboxId(), mStartParam->folderId(),
+                    envelope->id(),QVariant::fromValue(envelope));
+            extMngr.getActions(request, list);
+        }
+        else{
+            NmActionRequest request(this, NmActionContextMenu, NmActionContextViewMessageList,
+                    NmActionContextDataMessage, mStartParam->mailboxId(), mStartParam->folderId(),
+                    envelope->id());
+            extMngr.getActions(request, list);
+        }
+        for (int i=0;i<list.count();i++) {
+            mItemContextMenu->addAction(list[i]);
+        }
+        mItemContextMenu->exec(coords);
+    }
+}
+
+/*!
+    Item activation handling. Expand/collapse for title dividers
+    opening for mail items
+*/
+
+void NmMessageListView::itemActivated(const QModelIndex &index)
+{
+    // Do expand/collapse for title divider items
+	NmMessageListModelItem* modelItem = mMessageListModel.data(
+        		index, Qt::DisplayRole).value<NmMessageListModelItem*>();
+    if (modelItem && modelItem->itemType()==
+        NmMessageListModelItem::NmMessageItemTitleDivider) {
+        if (!mMessageListWidget->isExpanded(index)) {
+            mMessageListWidget->setExpanded(index, true);
+            modelItem->setExpanded(true);
+        }
+        else {
+            mMessageListWidget->setExpanded(index, false);
+            modelItem->setExpanded(false);
+        }
+    }
+    if (modelItem && modelItem->itemType() == NmMessageListModelItem::NmMessageItemMessage)
+    {
+        NmUiStartParam *startParam = new NmUiStartParam(NmUiViewMessageViewer,
+            mStartParam->mailboxId(), mStartParam->folderId(),
+            modelItem->envelope().id());
+        mApplication.enterNmUiView(startParam);
+    }
+}
+
+
+/*!
+    createOptionsMenu. Functions asks menu commands from extension
+    to be added to options menu.
+*/
+void NmMessageListView::createOptionsMenu()
+{
+    menu()->clearActions();
+    NmActionRequest request(this, NmActionOptionsMenu, NmActionContextViewMessageList,
+    		NmActionContextDataNone, mStartParam->mailboxId(), mStartParam->folderId() );
+    NmUiExtensionManager &extMngr = mApplication.extManager();
+    QList<NmAction*> list;
+    extMngr.getActions(request, list);
+    for (int i=0;i<list.count();i++) {
+        menu()->addAction(list[i]);
+    }
+}
+
+/*!
+    handleActionCommand. From NmMenuObserver, extension manager calls this
+    call to handle menu command in the UI.
+*/
+void NmMessageListView::handleActionCommand(NmActionResponse &actionResponse)
+{
+    // Handle context menu commands here
+    if (actionResponse.menuType() == NmActionOptionsMenu) {
+        switch (actionResponse.responseCommand()) {
+            case NmActionResponseCommandNewMail: {
+                // Check that given start response has mailbox and folder id's
+                if (actionResponse.mailboxId()!=0){
+                    NmUiStartParam *startParam = new NmUiStartParam(NmUiViewMessageEditor,
+                            actionResponse.mailboxId(), mStartParam->folderId());
+                    // startParam ownerhips transfers
+                    mApplication.enterNmUiView(startParam);
+                }
+                break;
+            }
+            case NmActionResponseCommandUpdateMailboxName: {
+                setMailboxName();
+                break;
+            }
+            case NmActionResponseCommandMailboxDeleted: {
+                mApplication.popView();
+				break;
+            }
+            default: {
+                break;
+            }
+        }
+    }
+
+    // Handle context menu commands here
+    else if (actionResponse.menuType()==NmActionContextMenu){
+        switch (actionResponse.responseCommand()){
+           case NmActionResponseCommandOpen:{
+               if (mLongPressedItem){
+                   NmUiStartParam *startParam = new NmUiStartParam(NmUiViewMessageViewer,
+                       mStartParam->mailboxId(), mStartParam->folderId(),
+                       mLongPressedItem->envelope().id());
+                   mApplication.enterNmUiView(startParam);
+                   mLongPressedItem=NULL;
+                   }
+               }
+               break;
+           //temporary solution..
+           case NmActionResponseCommandForward:{
+                if (mLongPressedItem){
+                   NmUiStartParam *startParam = new NmUiStartParam(NmUiViewMessageEditor,
+                       mStartParam->mailboxId(), mStartParam->folderId(),
+                       mLongPressedItem->envelope().id());
+                   mApplication.enterNmUiView(startParam);
+                   mLongPressedItem=NULL;
+                   }
+               }
+               break;
+           default:
+               break;
+        }
+    }
+    // Handle toolbar commands here
+    else if ( actionResponse.menuType() == NmActionToolbar ) {
+        if ( actionResponse.responseCommand() == NmActionResponseCommandNewMail ) {
+            // Check that given start response has mailbox and folder id's
+            if (actionResponse.mailboxId()!=0){
+                if (mUiEngine.isSendingMessage()) {
+                    // sending is ongoing so just show a note
+                    QString noteText = hbTrId("txt_mail_dialog_still_sending");
+                    
+                    // get message subject from the message being sent
+                    const NmMessage *message = mUiEngine.messageBeingSent();
+                    if (message) {
+                        noteText = noteText.arg(NmUtilities::truncate(message->envelope().subject(), 20));
+                    }
+                    HbMessageBox::warning(noteText);
+                }
+                else {
+                    NmUiStartParam *startParam = new NmUiStartParam(NmUiViewMessageEditor,
+                            actionResponse.mailboxId(), mStartParam->folderId());
+                    // startParam ownerhips transfers
+                    mApplication.enterNmUiView(startParam);
+                }
+            }
+        }
+    }
+
+
+}
+
+
+/*!
+    Set mailbox name to title
+*/
+void NmMessageListView::setMailboxName()
+{
+    if (mStartParam){
+        NmMailboxMetaData *meta = mUiEngine.mailboxById(mStartParam->mailboxId());
+        if (meta){
+            setTitle(meta->name());
+        }
+    }
+}
+
+/*!
+    createToolBar. Function asks menu commands from extension
+    to be added to toolbar owned by the HbView. Also toolbar
+    specific icons are added in this function.
+*/
+void NmMessageListView::createToolBar()
+{
+    HbToolBar *tb = toolBar();
+    if (!tb) {
+        return;
+    }
+    tb->clearActions();
+    NmActionRequest request(this, NmActionToolbar, NmActionContextViewMessageList,
+            NmActionContextDataNone, mStartParam->mailboxId(), mStartParam->folderId() );
+    NmUiExtensionManager &extMngr = mApplication.extManager();
+    if (!&extMngr) {
+        return;
+    }
+    QList<NmAction *> list;
+    extMngr.getActions(request, list);
+    for (int i = 0; i < list.count(); i++) {
+        tb->addAction(list[i]);
+    }
+}
+
+/*!
+    Observe items added
+*/
+void NmMessageListView::itemsAdded(const QModelIndex &parent, int start, int end)
+{
+    NMLOG("nmailui: NmMessageListView::itemsAdded");
+    Q_UNUSED(parent);
+    Q_UNUSED(end);
+    if (mNoMessagesLabel && mNoMessagesLabel->isVisible()) {
+        mNoMessagesLabel->hide();
+        mMessageListWidget->show();
+    }
+    if (0 == start && mMessageListWidget) {
+        QList<HbAbstractViewItem*> items = mMessageListWidget->visibleItems();
+        if (items.count()) {
+            QModelIndex index = items.at(0)->modelIndex();
+            if (1 == index.row()) {
+                QModelIndex previous = mMessageListWidget->previousIndex(index);
+                if (previous.isValid()) {
+                    mMessageListWidget->scrollTo(previous);
+                }
+            }
+        }
+    }
+}
+
+/*!
+    Observe items removed
+*/
+void NmMessageListView::itemsRemoved()
+{
+    if (mNoMessagesLabel && mMessageListModel.rowCount() == 0){
+        showNoMessagesText();
+    }
+}
+
+/*!
+    Show "(no messages)" text at the middle of the screen.
+*/
+void NmMessageListView::showNoMessagesText()
+{
+    if (mNoMessagesLabel) {
+        mMessageListWidget->hide();
+        mNoMessagesLabel->show();
+    }
+}