emailuis/nmhswidget/src/nmhswidget.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 14 May 2010 15:41:10 +0300
changeset 23 2dc6caa42ec3
parent 20 ecc8def7944a
child 30 759dc5235cdb
permissions -rw-r--r--
Revision: 201017 Kit: 201019

/*
 * 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 <QDebug>
#include <QtGui>
#include <QGraphicsLinearLayout>
#include <hbcolorscheme.h>
#include <QTranslator>
#include <hbframedrawer.h>
#include <hbframeitem.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"

NmHsWidget::NmHsWidget(QGraphicsItem *parent, Qt::WindowFlags flags)
    : HbWidget(parent, flags), 
      mEngine(0),
      mRowLayout(0),
      mTitleRow(0),
      mAccountId(0),
      mAccountIconName(0),
      mTranslator(0),
      mBackgroundFrameDrawer(0),
      mIsExpanded(true),
      mStaticWidget(true),
      mDateObserver(0)
{
    qDebug() << "NmHsWidget::NmHsWidget IN -->>";
       
    qDebug() << "NmHsWidget::NmHsWidget OUT <<--";
}

/*!
    Destructor
*/
NmHsWidget::~NmHsWidget()
{
    qDebug() << "NmHsWidget::~NmHsWidget IN -->>";
    if(mTranslator){
        delete mTranslator;
        mTranslator = NULL;
    }
    
    if(mEngine){
        delete mEngine;
        mEngine = NULL;
        }
    
    if(mBackgroundFrameDrawer){
        delete mBackgroundFrameDrawer;
        mBackgroundFrameDrawer = NULL;
        }
		
	if(mDateObserver){
        delete mDateObserver;
        mDateObserver = NULL;
        }
    qDebug() << "NmHsWidget::~NmHsWidget OUT <<--";
}

/*!
    \fn void NmHsWidget::onShow()

    called by home screen fw when widget gets visible
*/
void NmHsWidget::onShow()
{
    qDebug() << "NmHsWidget::onShow IN -->>";
    if (mEngine)
        {
        mEngine->activate();
        }
    qDebug() << "NmHsWidget::onShow OUT <<--";
}

/*!
    \fn void NmHsWidget::onHide()

    called by home screen fw when widget gets hidden
*/
void NmHsWidget::onHide()
{
    qDebug() << "NmHsWidget::onHide IN -->>";
    if (mEngine)
        {
        mEngine->suspend();
        }
    qDebug() << "NmHsWidget::onHide OUT <<--";
}

/*!
    Initializes Localization.
    /post mTranslator constructed & localization file loaded
    returns false in failure, otherwise true
*/
bool NmHsWidget::setupLocalization()
{
    qDebug() << "NmHsWidget::setupLocalization IN -->>";
    
    //Use correct localisation
    bool ret(false); 
    mTranslator = new QTranslator();
    QString lang = QLocale::system().name();
    ret = mTranslator->load(KNmHsWidgetLocFileName + lang, KNmHsWidgetLocLocation);
    qDebug() << "NmHsWidget::setupLocalization mTranslator->load loadSucceed:"<<ret;
    QCoreApplication::installTranslator(mTranslator);

    qDebug() << "NmHsWidget::setupLocalization OUT <<--";
    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()
{
    qDebug() << "NmHsWidget::setupUi IN -->>";
    setContentsMargins( KNmHsWidgetContentsMargin, KNmHsWidgetContentsMargin,
            KNmHsWidgetContentsMargin, KNmHsWidgetContentsMargin);
    
    //Setup layout
    mRowLayout = new QGraphicsLinearLayout(Qt::Vertical);

    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 );
   
   qDebug() << "NmHsWidget::setupUi OUT -->>";
}

/*!
    Initializes the widget.
    
    called by home screen fw when widget is added to home screen
*/
void NmHsWidget::onInitialize()
{
    QT_TRY{
        qDebug() << "NmHsWidget::onInitialize IN -->>";
        
        setupUi();
        //emit error if localization fails
        if(!setupLocalization()){
            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;
            }

        //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();
    
        updateMailData();
        mTitleRow->updateUnreadCount(mEngine->unreadCount());
        mTitleRow->setAccountIcon(mAccountIconName);
        
        //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() ) );

	    //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()); 
		}
        qDebug() << "NmHsWidget::onInitialize OUT <<--";  
    }
    QT_CATCH(...){
        emit error();
    }

}

/*!
    Uninitializes the widget.
    
    called by home screen fw when widget is removed from home screen
*/
void NmHsWidget::onUninitialize()
{
    qDebug() << "NmHsWidget::onUninitialize IN -->>";
    
    qDebug() << "NmHsWidget::onUninitialize OUT <<--";
}

/*!
    updateMailData slot
*/
void NmHsWidget::updateMailData()
{
    qDebug() << "NmHsWidget::updateData IN -->>";
    QList<NmMessageEnvelope> envelopes;
    int count = 0;
    if (mIsExpanded) {
        count = mEngine->getEnvelopes(envelopes, KMaxNumberOfMailsShown);
        }

    updateMailRowsList(count);
    
    for(int i=0; i<envelopes.count(); i++)
        {
        mMailRows[i]->updateMailData( envelopes[i] );
        }
    qDebug() << "NmHsWidget::updateData OUT <<--"; 
}

/*!
    Sets monitored account id from given string
    Needed for home screen framework which supports only QString type properties
*/
void NmHsWidget::setAccountId(const QString &text)
{
    qDebug() << "NmHsWidget::setAccountId IN -->>"; 
    bool ok;
    quint64 id = text.toULongLong(&ok);
    if (!ok)
        {
        qDebug() << "NmHsWidget::setAccountId: invalid account ID data, signal finished()!!!"; 
        //No valid account id so give up
        emit finished();
        }
    else
        {
        mAccountId.setId(id);
        }
    qDebug() << "NmHsWidget::setAccountId OUT <<--"; 
}

/*!
    Returns monitored account id as a string
    Needed for home screen framework which supports only QString type properties
*/
QString NmHsWidget::accountId() const
{
    qDebug() << "NmHsWidget::accountId()"; 
    return QString::number(mAccountId.id());
}

/*!
    Sets monitored account icon name from given string
*/
void NmHsWidget::setAccountIconName(const QString &text)
{
    qDebug() << "NmHsWidget::setAccountIconName IN -->>"; 
    mAccountIconName = text;
    qDebug() << "NmHsWidget::setAccountIconName OUT <<--"; 
}

/*!
    Returns monitored account icon name
*/
QString NmHsWidget::accountIconName() const
{
    qDebug() << "NmHsWidget::accountIconName()"; 
    return mAccountIconName;
}

/*!
    Slot to handle expand/collapse trigger event
*/
void NmHsWidget::handleExpandCollapseEvent()
{
    qDebug() << "NmHsWidget::handleExpandCollapseEvent IN -->>";
    toggleExpansionState();
    qDebug() << "NmHsWidget::handleExpandCollapseEvent OUT <<--"; 
}

/*!
    Sets widget expand/collapse state
    /post widget expansion state is changed
*/
void NmHsWidget::toggleExpansionState()
{
    qDebug() << "NmHsWidget::setExpanded IN -->>"; 

    mIsExpanded = !mIsExpanded;
    
    //save new state to home screen
    QStringList propertiesList;
    propertiesList.append("widgetState");
    emit setPreferences(propertiesList);
    
    //handle state change drawing
    updateMailData();
    
    qDebug() << "NmHsWidget::setExpanded OUT <<--"; 
}

/*!
    Sets expand/collapse state from given string (needed by homescreen)
*/
void NmHsWidget::setWidgetStateProperty(QString value)
{
    qDebug() << "NmHsWidget::setWidgetStateProperty IN -->>"; 
    if (value == KNmHsWidgetStateCollapsed)
        {
        mIsExpanded = false;
        }
    else
        {
        mIsExpanded = true;
        }
    qDebug() << "NmHsWidget::setWidgetStateProperty OUT <<--"; 
}

/*!
    Returns widget expand/collapse state as string (needed by homescreen) 
*/
QString NmHsWidget::widgetStateProperty()
{
    qDebug() << "NmHsWidget::widgetStateProperty()";
    if (mIsExpanded)
        {
        return KNmHsWidgetStateExpanded;
        }
    else
        {
        return KNmHsWidgetStateCollapsed;
        }
}

/*!
    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)
{
    qDebug() << "NmHsWidget::updateMailRowsList IN -->>";
    qDebug() << "NmHsWidget - mMailRows.count() == " <<  mMailRows.count();
    qDebug() << "NmHsWidget - ordered count == " <<  mailCount;
    
    int neededRowsCount = mailCount;
    //force size when static and expanded
    if (mStaticWidget && mIsExpanded)
        {
        neededRowsCount = KMaxNumberOfMailsShown;
        }
    
    while (mMailRows.count() != neededRowsCount)
        {
        //more mails to show than rows
        if (mMailRows.count() < neededRowsCount)
            {
            qDebug() << "NmHsWidget - add new mail row";
            NmHsWidgetEmailRow *row = new NmHsWidgetEmailRow();
            if( !row->loadDocML()){
                qDebug() << "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)
            {
            qDebug() << "NmHsWidget - remove mail row";
            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);
        }
    qDebug() << "NmHsWidget::updateMailRowsList OUT <<--";
}

/*!
    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)
{
    qDebug() << "NmHsWidget::updateMailRowsVisibility IN -->>";
  
    // 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);
        }
    
    qDebug() << "NmHsWidget::updateMailRowsVisibility OUT <<--";
}

/*!
    onEngineException (NmHsWidgetEmailEngineExceptionCode exc)
    signals widget to be finalized
    /param exc exception type
*/
void NmHsWidget::onEngineException(const int& exc)
    {
    qDebug() << "NmHsWidget:onEngineException IN -->>";
    switch (exc)
        {
        case (NmEngineExcAccountDeleted):
             emit finished(); //succesful ending
             break;
        case (NmEngineExcFailure):
             emit error(); //failure
             break;
        default: 
            break; 
        }
    }