emailuis/nmhswidget/src/nmhswidget.cpp
branchRCL_3
changeset 63 d189ee25cf9d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailuis/nmhswidget/src/nmhswidget.cpp	Tue Aug 31 15:04:17 2010 +0300
@@ -0,0 +1,596 @@
+/*
+ * 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 <QtGui>
+#include <QGraphicsLinearLayout>
+#include <hbcolorscheme.h>
+#include <hbdocumentloader.h>
+#include <QTranslator>
+#include <hbframedrawer.h>
+#include <hbframeitem.h>
+#include <hblabel.h>
+#include "nmcommon.h"
+#include "nmhswidget.h"
+#include "nmhswidgetemailengine.h"
+#include "nmmessageenvelope.h"
+#include "nmhswidgettitlerow.h"
+#include "nmhswidgetemailrow.h"
+#include "nmhswidgetconsts.h"
+#include "nmhswidgetdatetimeobserver.h"
+#include "emailtrace.h"
+
+NmHsWidget::NmHsWidget(QGraphicsItem *parent, Qt::WindowFlags flags)
+    : HbWidget(parent, flags), 
+      mMainContainer(0),
+      mEmptySpaceContainer(0),
+      mWidgetContainer(0),
+      mTitleRow(0),
+      mContentContainer(0),
+      mNoMailsLabel(0),
+      mContentLayout(0),              
+      mBackgroundFrameDrawer(0),
+      mTranslator(0),
+      mEngine(0),      
+      mAccountId(0),
+      mAccountIconName(),
+      mDateObserver(0),
+      mIsExpanded(false)
+{
+    NM_FUNCTION;
+}
+
+/*!
+ Destructor
+ */
+NmHsWidget::~NmHsWidget()
+{
+    NM_FUNCTION;
+
+    delete mTranslator;
+    mTranslator = NULL;
+
+    delete mEngine;
+    mEngine = NULL;
+
+    delete mBackgroundFrameDrawer;
+    mBackgroundFrameDrawer = NULL;
+
+    delete mDateObserver;
+    mDateObserver = NULL;
+}
+
+/*!
+ \fn QPainterPath NmHsWidget::shape()
+
+ Called by home screen fw to check widget boundaries, needed to draw
+ outside widget boundingRect.
+ /return QPainterPath path describing actual boundaries of widget 
+  including child items
+ */
+QPainterPath NmHsWidget::shape() const
+{
+    NM_FUNCTION;
+    
+    QPainterPath path;
+    path.setFillRule(Qt::WindingFill);
+    if (mWidgetContainer){
+        //add mWidgetContainer using geometry to get
+        //correct point for top-left-corner
+        QRectF widgetRect = mWidgetContainer->geometry();
+        path.addRect(widgetRect); 
+        
+        //then fetch shape from title row 
+        QPainterPath titlepath;
+        titlepath.addPath(mTitleRow->shape());
+        //translate it's location to be inside mWidgetContainer
+        titlepath.translate(widgetRect.topLeft());
+        //and finally add it to path
+        path.addPath(titlepath);    
+    }
+    //simplified path, i.e. only outlines
+    return path.simplified();
+}
+
+/*!
+ \fn void NmHsWidget::onShow()
+
+ called by home screen fw when widget gets visible
+ */
+void NmHsWidget::onShow()
+{
+    NM_FUNCTION;
+    if (mEngine) {
+        mEngine->activate();
+    }
+}
+
+/*!
+ \fn void NmHsWidget::onHide()
+
+ called by home screen fw when widget gets hidden
+ */
+void NmHsWidget::onHide()
+{
+    NM_FUNCTION;
+    if (mEngine) {
+        mEngine->suspend();
+    }
+}
+
+/*!
+ \fn bool NmHsWidget::loadDocML(HbDocumentLoader &loader)
+ 
+ loads layout data and child items from docml file. Must be called after constructor.
+ /return true if loading succeeded, otherwise false. False indicates that object is unusable
+ */
+bool NmHsWidget::loadDocML(HbDocumentLoader &loader)
+{
+    NM_FUNCTION;
+    
+    bool ok(false);
+    loader.load(KNmHsWidgetDocML, &ok);
+    
+    if(ok) {
+        mMainContainer = static_cast<HbWidget*> (loader.findWidget(KNmHsWidgetMainContainer));  
+        mWidgetContainer = static_cast<HbWidget*> (loader.findWidget(KNmHsWidgetContainer));
+        mContentContainer = static_cast<HbWidget*> (loader.findWidget(KNmHsWidgetContentContainer));
+        mEmptySpaceContainer = static_cast<HbWidget*> (loader.findWidget(KNmHsWidgetEmptySpaceContainer));
+        mNoMailsLabel = static_cast<HbLabel*> (loader.findWidget(KNmHsWidgetNoMailsLabel));
+        if (!mMainContainer || !mWidgetContainer || !mContentContainer 
+                || !mEmptySpaceContainer || !mNoMailsLabel ) {
+            //something failed in documentloader, no point to continue
+            NM_ERROR(1,"NmHsWidget::loadDocML fail @ containers or label");
+            ok = false;
+        }
+    }
+    return ok;
+}
+
+/*!
+ Initializes Localization.
+ /post mTranslator constructed & localization file loaded
+ */
+void NmHsWidget::setupLocalization()
+{
+    NM_FUNCTION;
+
+    //Use correct localisation
+    mTranslator = new QTranslator();
+    QString lang = QLocale::system().name();
+    mTranslator->load(KNmHsWidgetLocFileName + lang, KNmHsWidgetLocLocation);
+    QCoreApplication::installTranslator(mTranslator);
+}
+
+/*!
+ Initializes UI. Everything that is not done in docml files should be here.
+ return true if ok, in error false.
+ */
+void NmHsWidget::setupUi()
+{
+    NM_FUNCTION;
+
+    //main level layout needed to control docml objects
+    QGraphicsLinearLayout *widgetLayout = new QGraphicsLinearLayout(Qt::Vertical);
+    widgetLayout->setContentsMargins(KNmHsWidgetContentsMargin, KNmHsWidgetContentsMargin,
+            KNmHsWidgetContentsMargin, KNmHsWidgetContentsMargin);
+    widgetLayout->setSpacing(KNmHsWidgetContentsMargin);
+    widgetLayout->addItem(mMainContainer);
+    this->setLayout(widgetLayout);
+
+    //fetch pointer to content container layout
+    //to be able to add/remove email rows and no mails label
+    mContentLayout = (QGraphicsLinearLayout*) mContentContainer->layout();
+    
+    //set noMailsLabel properties not supported by doc loader 
+    QColor newFontColor;
+    newFontColor = HbColorScheme::color("qtc_hs_list_item_content_normal");
+    mNoMailsLabel->setTextColor(newFontColor);
+    mNoMailsLabel->setVisible(true);   
+    
+    mContentLayout->removeItem(mNoMailsLabel);
+    
+    //widget background
+    mBackgroundFrameDrawer = new HbFrameDrawer(KNmHsWidgetBackgroundImage,
+        HbFrameDrawer::NinePieces);
+    HbFrameItem* backgroundLayoutItem = new HbFrameItem(mBackgroundFrameDrawer);
+    //set to NULL to indicate that ownership transferred
+    mBackgroundFrameDrawer = NULL;
+    mWidgetContainer->setBackgroundItem(backgroundLayoutItem);
+}
+
+/*!
+ Initializes the widget.
+ 
+ called by home screen fw when widget is added to home screen
+ */
+void NmHsWidget::onInitialize()
+{
+    NM_FUNCTION;
+    
+    QT_TRY {
+	    // Use document loader to load the contents
+	    HbDocumentLoader loader;
+		//setup localization before docml loading
+	    setupLocalization();
+		
+	    //load containers and mNoMailsLabel
+        if (!loadDocML(loader)) {
+            NM_ERROR(1,"NmHsWidget::onInitialize Fail @ loader");
+            emit error(); //failure, no point to continue
+            return;
+        }
+
+        //construct title row
+        mTitleRow = new NmHsWidgetTitleRow(this);
+        if (!mTitleRow->setupUI(loader)) {
+            //title row creation failed
+            NM_ERROR(1,"NmHsWidget::onInitialize fail @ titlerow");
+            emit error(); //failure, no point to continue
+            return;            
+        }
+				
+        setupUi();
+
+        //Engine construction is 2 phased. 
+        mEngine = new NmHsWidgetEmailEngine(mAccountId);
+        //Client must connect to exception signals before calling the initialize function
+        //because we don't want to miss any signals.
+        connect(mEngine, SIGNAL( exceptionOccured(const int&) ), this,
+            SLOT( onEngineException(const int&) ));
+        if (!mEngine->initialize()) {
+            //engine construction failed. Give up.
+            NM_ERROR(1,"NmHsWidget::onInitialize fail @ engine");
+            emit error();
+            return;
+        }
+
+        mTitleRow->updateAccountName(mEngine->accountName());
+
+        //create observer for date/time change events
+        mDateObserver = new NmHsWidgetDateTimeObserver();
+
+        //Crete MailRows and associated connections
+        createMailRowsList();
+
+        updateMailData();
+        mTitleRow->updateUnreadCount(mEngine->unreadCount());
+        mTitleRow->setAccountIcon(mAccountIconName);
+        mTitleRow->setExpandCollapseIcon(mIsExpanded);
+
+        //Get signals about changes in mail data
+        connect(mEngine, SIGNAL( mailDataChanged() ), this, SLOT( updateMailData() ));
+
+        //Get Signals about changes in unread count
+        connect(mEngine, SIGNAL( unreadCountChanged(const int&) )
+                ,mTitleRow, SLOT( updateUnreadCount(const int&) ) );
+        
+        //Get signals about account name changes
+        connect(mEngine, SIGNAL( accountNameChanged(const QString&) )
+                ,mTitleRow, SLOT( updateAccountName(const QString&) ) );
+
+	    //Get signals about user actions
+	    connect(mTitleRow, SIGNAL( mailboxLaunchTriggered() )
+	            ,mEngine, SLOT( launchMailAppInboxView() ) );
+	    connect(mTitleRow, SIGNAL( expandCollapseButtonPressed() )
+	            ,this, SLOT( handleExpandCollapseEvent() ) );
+	    
+	    setMinimumSize(mTitleRow->minimumWidth(), 
+	            mEmptySpaceContainer->minimumHeight() + mTitleRow->minimumHeight());
+    }
+    QT_CATCH(...) {
+        NM_ERROR(1,"NmHsWidget::onInitialize fail @ catch");
+        emit error();
+    }
+}
+
+/*!
+ updateMailData slot
+ */
+void NmHsWidget::updateMailData()
+{
+    NM_FUNCTION;
+
+    QList<NmMessageEnvelope> envelopes;
+    int count = 0;
+    if (mIsExpanded) {
+        count = mEngine->getEnvelopes(envelopes, KMaxNumberOfMailsShown);
+    }
+
+    updateLayout(count);
+    //count is safe for envelopes and mMailRows
+    for (int i = 0; i < count; i++) {
+        mMailRows.at(i)->updateMailData(envelopes.at(i));
+    }
+}
+
+/*!
+ Sets monitored account id from given string
+ Needed for home screen framework which supports only QString type properties
+ */
+void NmHsWidget::setAccountId(const QString &text)
+{
+    NM_FUNCTION;
+
+    bool ok;
+    quint64 id = text.toULongLong(&ok);
+    if (!ok) {
+        NM_ERROR(1, "NmHsWidget::setAccountId: invalid account ID data, signal finished()!!!");
+        //No valid account id so give up
+        emit finished();
+        return;
+    }
+
+    mAccountId.setId(id);
+}
+
+/*!
+ Returns monitored account id as a string
+ Needed for home screen framework which supports only QString type properties
+ */
+QString NmHsWidget::accountId() const
+{
+    NM_FUNCTION;
+    return QString::number(mAccountId.id());
+}
+
+/*!
+ Sets monitored account icon name from given string
+ */
+void NmHsWidget::setAccountIconName(const QString &text)
+{
+    NM_FUNCTION;
+    mAccountIconName = text;
+}
+
+/*!
+ Returns monitored account icon name
+ */
+QString NmHsWidget::accountIconName() const
+{
+    NM_FUNCTION;
+    return mAccountIconName;
+}
+
+/*!
+ Slot to handle expand/collapse trigger event
+ */
+void NmHsWidget::handleExpandCollapseEvent()
+{
+    NM_FUNCTION;
+    toggleExpansionState();
+}
+
+/*!
+ Sets widget expand/collapse state
+ /post widget expansion state is changed
+ */
+void NmHsWidget::toggleExpansionState()
+{
+    NM_FUNCTION;
+
+    mIsExpanded = !mIsExpanded;
+
+    //save new state to home screen
+    QStringList propertiesList;
+    propertiesList.append("widgetState");
+    emit setPreferences(propertiesList);
+
+    //handle state change drawing
+    updateMailData();
+
+    mTitleRow->setExpandCollapseIcon(mIsExpanded);
+}
+
+/*!
+ Sets expand/collapse state from given string (needed by homescreen)
+ */
+void NmHsWidget::setWidgetStateProperty(QString value)
+{
+    NM_FUNCTION;
+    if (value == KNmHsWidgetStateCollapsed) {
+        mIsExpanded = false;
+    }
+    else {
+        mIsExpanded = true;
+    }
+}
+
+/*!
+ Returns widget expand/collapse state as string (needed by homescreen) 
+ */
+QString NmHsWidget::widgetStateProperty()
+{
+    NM_FUNCTION;
+    if (mIsExpanded) {
+        return KNmHsWidgetStateExpanded;
+    }
+    else {
+        return KNmHsWidgetStateCollapsed;
+    }
+}
+
+/*!
+ Updates mMailRows list to include KMaxNumberOfMailsShown mail row widgets
+ /post mMailRows contains KMaxNumberOfMailsShown mailRows 
+ */
+void NmHsWidget::createMailRowsList()
+{
+    NM_FUNCTION;
+
+    //make sure that there are as many email rows as needed
+    while (mMailRows.count() < KMaxNumberOfMailsShown) {
+        NmHsWidgetEmailRow *row = new NmHsWidgetEmailRow(this);
+        if (!row->setupUI()) {
+            NM_ERROR(1, "NmHsWidget::createMailRowsList row->setUpUI() fails");
+            //if setupUI fails no point to proceed
+            emit error();
+            return;
+        }
+        connect(row, SIGNAL(mailViewerLaunchTriggered(const NmId&)), mEngine,
+            SLOT(launchMailAppMailViewer(const NmId&)));
+        connect(mDateObserver, SIGNAL(dateTimeChanged()), row, SLOT(updateDateTime()));
+        mMailRows.append(row);
+    }
+
+}
+
+/*!
+ Updates the Layout to contain the right items
+ /param mailCount defines how many emails is to be shown
+ /post If widget is collapsed, the layout contains only titleRow widget.
+ If widget is expanded and mailCount is 0 layout will contain
+ titlerow & noMailsLabel. 
+ If widget is expanded and mailCount is greter
+ than zero, layout will contain titlerow and KMaxNumberOfMailsShown times
+ emailrow(s)
+ */
+void NmHsWidget::updateLayout(const int mailCount)
+{
+    NM_FUNCTION;
+
+    if (mIsExpanded) {
+        //set container height to content height 
+        qreal contentHeight = KMaxNumberOfMailsShown
+                * mMailRows.first()->maximumHeight();
+        mContentContainer->setMaximumHeight(contentHeight);
+        mContentContainer->setVisible(true);
+        if (mailCount == 0) {
+            addNoMailsLabelToLayout();
+            removeEmailRowsFromLayout();
+        }
+        else {
+            removeNoMailsLabelFromLayout();
+            addEmailRowsToLayout();
+        }
+    }
+    else {
+        removeNoMailsLabelFromLayout();
+        removeEmailRowsFromLayout();
+        mContentContainer->setVisible(false);
+        mContentContainer->setMaximumHeight(0);        
+    }
+
+    //resize the widget to new layout size
+    qreal totalHeight = mEmptySpaceContainer->preferredHeight() + mTitleRow->containerHeight() + mContentContainer->maximumHeight();
+    //set maximum sizes, otherwise widget will stay huge also when collapsed
+    setMaximumHeight(totalHeight);
+    mMainContainer->setMaximumHeight(totalHeight);
+    mWidgetContainer->setMaximumHeight(totalHeight - mEmptySpaceContainer->preferredHeight());
+    //resize here or widget cannot draw mail rows when expanding
+    resize(mTitleRow->maximumWidth(), totalHeight);
+    mMainContainer->resize(mTitleRow->maximumWidth(), totalHeight);
+    mWidgetContainer->resize(mTitleRow->maximumWidth(), totalHeight - mEmptySpaceContainer->preferredHeight());
+
+    updateMailRowsVisibility(mailCount);
+}
+
+/*!
+ Updates mNoMailsLabel visibility based on widget state
+ /param mailCount defines how many mail rows is needed
+ /post if mail count is 0 and mIsExpanded equals true, then
+ the mNoMailLabel is added to the mContentLayout. 
+ */
+void NmHsWidget::addNoMailsLabelToLayout()
+{
+    NM_FUNCTION;
+
+    if (mNoMailsLabel->isVisible() || mMailRows.isEmpty()) {
+        return;
+    }
+    //Add mNoMailsLabel to layout if not yet there and show it
+    mContentLayout->addItem(mNoMailsLabel);
+    //resize the widget to new layout size
+    mNoMailsLabel->show();
+}
+
+/*!
+ removeNoMailsLabelFromLayout removes mNoMailsLabel from the layout
+ /post mNoMailsLabel is not in mContentLayout
+ */
+void NmHsWidget::removeNoMailsLabelFromLayout()
+{
+    NM_FUNCTION;
+    //remove mNoMailsLabel from Layout and hide it
+    mContentLayout->removeItem(mNoMailsLabel);
+    mNoMailsLabel->hide();
+}
+
+/*!
+ addEmailRowsToLayout adds every emailrow to the layout
+ /post all elements in mMailRows are added to mContentLayout
+ */
+void NmHsWidget::addEmailRowsToLayout()
+{
+    NM_FUNCTION;
+    foreach(NmHsWidgetEmailRow *row, mMailRows)
+        {
+            mContentLayout->addItem(row);
+        }
+}
+
+/*!
+ removeEmailRowsFromLayout removes every emailrow from the layout
+ /post none of the elements in mMailRows are in mContentLayout
+ */
+void NmHsWidget::removeEmailRowsFromLayout()
+{
+    NM_FUNCTION;
+    foreach(NmHsWidgetEmailRow *row, mMailRows)
+        {
+            mContentLayout->removeItem(row);
+        }
+}
+
+/*!
+ Updates mail row visibilities in static widget
+ /param visibleCount defines how many items do have mail data
+ /post all row items having mail data are visible, other rows are hidden
+ */
+void NmHsWidget::updateMailRowsVisibility(const int visibleCount)
+{
+    NM_FUNCTION;
+
+    // set visible as many rows as requested by visibleCount param
+    bool isVisible;
+
+    for (int i = 0; i < mMailRows.count(); i++) {
+        isVisible = false;
+        if ((mIsExpanded) && (i < visibleCount)) {
+            isVisible = true;
+        }
+        mMailRows.at(i)->setVisible(isVisible);
+    }
+}
+
+/*!
+ onEngineException (NmHsWidgetEmailEngineExceptionCode exc)
+ signals widget to be finalized
+ /param exc exception type
+ */
+void NmHsWidget::onEngineException(const int& exc)
+{
+    NM_FUNCTION;
+    switch (exc) {
+        case (NmEngineExcAccountDeleted):
+            emit finished(); //succesful ending
+            break;
+        case (NmEngineExcFailure):
+            emit error(); //failure
+            break;
+        default:
+            break;
+    }
+}