diff -r bf7eb7911fc5 -r 997a02608b3a emailuis/nmhswidget/src/nmhswidget.cpp --- a/emailuis/nmhswidget/src/nmhswidget.cpp Wed Jun 23 18:00:21 2010 +0300 +++ b/emailuis/nmhswidget/src/nmhswidget.cpp Tue Jul 06 14:04:34 2010 +0300 @@ -17,9 +17,11 @@ #include #include #include +#include #include #include #include +#include #include "nmcommon.h" #include "nmhswidget.h" #include "nmhswidgetemailengine.h" @@ -33,22 +35,24 @@ NmHsWidget::NmHsWidget(QGraphicsItem *parent, Qt::WindowFlags flags) : HbWidget(parent, flags), mEngine(0), - mRowLayout(0), mTitleRow(0), mAccountId(0), mAccountIconName(), mTranslator(0), mBackgroundFrameDrawer(0), mIsExpanded(false), - mStaticWidget(true), - mDateObserver(0) + mDateObserver(0), + mNoMailsLabel(0), + mWidgetContainer(0), + mContentContainer(0), + mContentLayout(0) { NM_FUNCTION; } /*! - Destructor -*/ + Destructor + */ NmHsWidget::~NmHsWidget() { NM_FUNCTION; @@ -67,134 +71,195 @@ } /*! - \fn void NmHsWidget::onShow() + \fn QPainterPath NmHsWidget::shape() - called by home screen fw when widget gets visible -*/ + 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); + + path.addRect(this->rect()); + if (mTitleRow){ + path.addPath(mTitleRow->shape()); + } + return path.simplified(); +} + +/*! + \fn void NmHsWidget::onShow() + + called by home screen fw when widget gets visible + */ void NmHsWidget::onShow() { NM_FUNCTION; - if (mEngine) - { + if (mEngine) { mEngine->activate(); - } + } } /*! - \fn void NmHsWidget::onHide() + \fn void NmHsWidget::onHide() - called by home screen fw when widget gets hidden -*/ + called by home screen fw when widget gets hidden + */ void NmHsWidget::onHide() { NM_FUNCTION; - if (mEngine) - { + if (mEngine) { mEngine->suspend(); - } + } } /*! - Initializes Localization. - /post mTranslator constructed & localization file loaded - returns false in failure, otherwise true -*/ -bool NmHsWidget::setupLocalization() -{ - NM_FUNCTION; - - //Use correct localisation - bool ret(false); - mTranslator = new QTranslator(); - QString lang = QLocale::system().name(); - ret = mTranslator->load(KNmHsWidgetLocFileName + lang, KNmHsWidgetLocLocation); - QCoreApplication::installTranslator(mTranslator); - - return ret; -} - -/*! - Initializes UI. Everything that is not done in docml files should be here. - return true if ok, in error false. -*/ -void NmHsWidget::setupUi() + \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; - setContentsMargins( KNmHsWidgetContentsMargin, KNmHsWidgetContentsMargin, - KNmHsWidgetContentsMargin, KNmHsWidgetContentsMargin); + bool ok(false); + loader.load(KNmHsWidgetDocML, &ok); - //Setup layout - mRowLayout = new QGraphicsLinearLayout(Qt::Vertical); + if(ok) { + mWidgetContainer = static_cast (loader.findWidget(KNmHsWidgetContainer)); + mContentContainer = static_cast (loader.findWidget(KNmHsWidgetContentContainer)); + mNoMailsLabel = static_cast (loader.findWidget(KNmHsWidgetNoMailsLabel)); + if (!mWidgetContainer || !mContentContainer || !mNoMailsLabel) { + //something failed in documentloader, no point to continue + NM_ERROR(1,"NmHsWidget::loadDocML fail @ containers or label"); + ok = false; + } + } + return ok; +} - mRowLayout->setContentsMargins(KNmHsWidgetContentsMargin, KNmHsWidgetContentsMargin, - KNmHsWidgetContentsMargin, KNmHsWidgetContentsMargin); - mRowLayout->setSpacing(KNmHsWidgetContentsMargin); - setLayout(mRowLayout); - - //background - mBackgroundFrameDrawer = new HbFrameDrawer( KNmHsWidgetBackgroundImage, HbFrameDrawer::NinePieces ); - HbFrameItem* backgroundLayoutItem = new HbFrameItem( mBackgroundFrameDrawer ); - //set to NULL to indicate that ownership transferred - mBackgroundFrameDrawer = NULL; - setBackgroundItem( backgroundLayoutItem ); +/*! + 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 the widget. + 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(mWidgetContainer); + 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(); - called by home screen fw when widget is added to home screen -*/ + //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; + setBackgroundItem(backgroundLayoutItem); +} + + +/*! + Initializes the widget. + + called by home screen fw when widget is added to home screen + */ void NmHsWidget::onInitialize() { NM_FUNCTION; - - QT_TRY{ + + QT_TRY { + + // Use document loader to load the contents + HbDocumentLoader loader; + + //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(); - //emit error if localization fails - if(!setupLocalization()){ + setupLocalization(); + + //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; } - - //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. - emit error(); - return; - } + + + mTitleRow->updateAccountName(mEngine->accountName()); - //construct and load docml for title row - mTitleRow = new NmHsWidgetTitleRow(); - if( !mTitleRow->loadDocML()){ - //if docml loading fails no point to proceed - //but memoryleak must be prevented - delete mTitleRow; - mTitleRow = NULL; - emit error(); - return; - } - mRowLayout->addItem(mTitleRow); - mTitleRow->updateAccountName(mEngine->accountName()); - - //create observer for date/time change events - mDateObserver = new NmHsWidgetDateTimeObserver(); - + //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() ) ); - + 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&) ) ); @@ -208,77 +273,60 @@ ,mEngine, SLOT( launchMailAppInboxView() ) ); connect(mTitleRow, SIGNAL( expandCollapseButtonPressed() ) ,this, SLOT( handleExpandCollapseEvent() ) ); - - //resize here so homescreen will place widget correctly on screen - setPreferredSize( mRowLayout->preferredSize() ); - if (parentWidget()) { - //to place widget properly after adding to homescreen - parentWidget()->resize(preferredSize()); - } + + setMinimumSize(mTitleRow->minimumSize()); } - QT_CATCH(...){ + QT_CATCH(...) { + NM_ERROR(1,"NmHsWidget::onInitialize fail @ catch"); emit error(); } - } -/*! - Uninitializes the widget. - - called by home screen fw when widget is removed from home screen -*/ -void NmHsWidget::onUninitialize() -{ - NM_FUNCTION; -} /*! - updateMailData slot -*/ + updateMailData slot + */ void NmHsWidget::updateMailData() { NM_FUNCTION; - + QList envelopes; int count = 0; if (mIsExpanded) { count = mEngine->getEnvelopes(envelopes, KMaxNumberOfMailsShown); - } + } - updateMailRowsList(count); - - for(int i=0; iupdateMailData( envelopes[i] ); - } + 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 -*/ + 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()!!!"); + if (!ok) { + NM_ERROR(1, "NmHsWidget::setAccountId: invalid account ID data, signal finished()!!!"); //No valid account id so give up emit finished(); - } - else - { - mAccountId.setId(id); - } + return; + } + + mAccountId.setId(id); } /*! - Returns monitored account id as a string - Needed for home screen framework which supports only QString type properties -*/ + Returns monitored account id as a string + Needed for home screen framework which supports only QString type properties + */ QString NmHsWidget::accountId() const { NM_FUNCTION; @@ -286,8 +334,8 @@ } /*! - Sets monitored account icon name from given string -*/ + Sets monitored account icon name from given string + */ void NmHsWidget::setAccountIconName(const QString &text) { NM_FUNCTION; @@ -295,8 +343,8 @@ } /*! - Returns monitored account icon name -*/ + Returns monitored account icon name + */ QString NmHsWidget::accountIconName() const { NM_FUNCTION; @@ -304,8 +352,8 @@ } /*! - Slot to handle expand/collapse trigger event -*/ + Slot to handle expand/collapse trigger event + */ void NmHsWidget::handleExpandCollapseEvent() { NM_FUNCTION; @@ -313,153 +361,219 @@ } /*! - Sets widget expand/collapse state - /post widget expansion state is changed -*/ + 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) -*/ + Sets expand/collapse state from given string (needed by homescreen) + */ void NmHsWidget::setWidgetStateProperty(QString value) { NM_FUNCTION; - if (value == KNmHsWidgetStateCollapsed) - { + 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; } - else - { - mIsExpanded = true; - } + connect(row, SIGNAL(mailViewerLaunchTriggered(const NmId&)), mEngine, + SLOT(launchMailAppMailViewer(const NmId&))); + connect(mDateObserver, SIGNAL(dateTimeChanged()), row, SLOT(updateDateTime())); + mMailRows.append(row); + } + } /*! - Returns widget expand/collapse state as string (needed by homescreen) -*/ -QString NmHsWidget::widgetStateProperty() + 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) - { - return KNmHsWidgetStateExpanded; + + 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 + } + else { + removeNoMailsLabelFromLayout(); + removeEmailRowsFromLayout(); + mContentContainer->setVisible(false); + mContentContainer->setMaximumHeight(0); + } + + //resize the widget to new layout size + qreal totalHeight = mTitleRow->preferredHeight() + mContentContainer->maximumHeight(); + //set maximum size, otherwise widget will stay huge also when collapsed + this->setMaximumHeight(totalHeight); + //resize here or widget cannot draw mail rows when expanding + this->resize(mTitleRow->preferredWidth(), totalHeight); + + 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) { - return KNmHsWidgetStateCollapsed; + mContentLayout->addItem(row); } } /*! - Updates mMailRows list to include correct amount of mail row widgets - /param mailCount defines how many mail rows is needed - /post mMailRows list includes NmHsWidgetEmailRow for each mail item -*/ -void NmHsWidget::updateMailRowsList(const int mailCount) + removeEmailRowsFromLayout removes every emailrow from the layout + /post none of the elements in mMailRows are in mContentLayout + */ +void NmHsWidget::removeEmailRowsFromLayout() { NM_FUNCTION; - - int neededRowsCount = mailCount; - //force size when static and expanded - if (mStaticWidget && mIsExpanded) - { - neededRowsCount = KMaxNumberOfMailsShown; - } - - while (mMailRows.count() != neededRowsCount) + foreach(NmHsWidgetEmailRow *row, mMailRows) { - //more mails to show than rows - if (mMailRows.count() < neededRowsCount) - { - NmHsWidgetEmailRow *row = new NmHsWidgetEmailRow(); - if( !row->loadDocML()){ - NM_ERROR(1,"NmHsWidget::updateMailRowsList row->loadDocML() fails"); - //if docml loading fails no point to proceed - //but memoryleak must be prevented - delete row; - row = NULL; - emit error(); - return; - } - connect(row, SIGNAL(mailViewerLaunchTriggered(const NmId&)) - ,mEngine, SLOT(launchMailAppMailViewer(const NmId&))); - connect( mDateObserver, SIGNAL(dateTimeChanged()) - ,row, SLOT(updateDateTime()) ); - mMailRows.append(row); - mRowLayout->addItem(row); - } - //too many rows - else if (mMailRows.count() > neededRowsCount) - { - mRowLayout->removeItem(mMailRows.last()); - delete mMailRows.takeLast(); - } - } - __ASSERT_ALWAYS( mMailRows.count() == neededRowsCount, User::Panic(_L("Invalid"), 500) ); - - //resize the widget to new layout size - setPreferredSize( mRowLayout->preferredSize() ); - - if (mStaticWidget) - { - this->updateMailRowsVisibility(mailCount); + 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 -*/ + 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++) - { + + for (int i = 0; i < mMailRows.count(); i++) { isVisible = false; - if ((mIsExpanded) && (i < visibleCount)) - { + if ((mIsExpanded) && (i < visibleCount)) { isVisible = true; - } + } mMailRows.at(i)->setVisible(isVisible); - } + } } /*! - onEngineException (NmHsWidgetEmailEngineExceptionCode exc) - signals widget to be finalized - /param exc exception type -*/ + onEngineException (NmHsWidgetEmailEngineExceptionCode exc) + signals widget to be finalized + /param exc exception type + */ void NmHsWidget::onEngineException(const int& exc) - { +{ NM_FUNCTION; - switch (exc) - { + switch (exc) { case (NmEngineExcAccountDeleted): - emit finished(); //succesful ending - break; + emit finished(); //succesful ending + break; case (NmEngineExcFailure): - emit error(); //failure - break; - default: - break; - } + emit error(); //failure + break; + default: + break; } +}