src/hbwidgets/dataform/hbdatagroup_p.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 19 Apr 2010 14:02:13 +0300
changeset 0 16d8024aca5e
child 1 f7ac710697a9
permissions -rw-r--r--
Revision: 201011 Kit: 201015

/****************************************************************************
**
** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (developer.feedback@nokia.com)
**
** This file is part of the HbWidgets module of the UI Extensions for Mobile.
**
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at developer.feedback@nokia.com.
**
****************************************************************************/

#include <hbcombobox.h>
#include <hbdataformmodel.h>

#include "hbdatagroupheadingwidget_p.h"
#include "hbstyleoptiondatagroup_p.h"
#include "hbabstractitemcontainer_p.h"
#include "hbdataform_p.h"
#include "hbdatagroup_p_p.h"

#include <QStringListModel>
#include <QCoreApplication>


HbDataGroupPrivate::HbDataGroupPrivate( HbDataGroup* item ):
    HbDataFormViewItemPrivate( item ),
    mPageCombo( 0 ),
    mGroupDescriptionItem( 0 ),
    mGroupHeading( 0 ),
    mPageComboBackgroundItem( 0 )
{
}
HbDataGroupPrivate::HbDataGroupPrivate( const HbDataGroupPrivate &source ):
    HbDataFormViewItemPrivate( source ),
    mPageCombo( source.mPageCombo ),
    mGroupDescriptionItem( source.mGroupDescriptionItem ),
    mGroupHeading( source.mGroupHeading ),
    mPageComboBackgroundItem( source.mPageComboBackgroundItem )
{
}
HbDataGroupPrivate::~HbDataGroupPrivate( )
{
}

void HbDataGroupPrivate::init( )
{   
}

void HbDataGroupPrivate::expand( bool expanded )
{
    HbAbstractItemContainer *container = qobject_cast<HbAbstractItemContainer *>(
        static_cast<QGraphicsWidget *>( mSharedData->mItemView->contentWidget( ) ) );
    HbDataFormModelItem::DataItemType itemType = static_cast<HbDataFormModelItem::DataItemType>(
            ( mIndex.operator const QModelIndex & ( )).data( HbDataFormModelItem::ItemTypeRole).toInt( ) );

    if(container->itemState(
            mIndex.operator const QModelIndex & ( )).value( HbDataFormViewItem::ExpansionKey ) == expanded ) {
        return;
    }

    if( !expanded ) {

        //collapsing all the expanded child Types.
        QModelIndex index = mIndex.operator const QModelIndex & ( );
        QModelIndex childIndex = index.child(0,0);
        while(childIndex.isValid()) {

            HbDataFormModelItem::DataItemType childType = static_cast<HbDataFormModelItem::DataItemType>(
            childIndex.data(HbDataFormModelItem::ItemTypeRole).toInt());

            if(childType <= HbDataFormModelItem::GroupPageItem) {
                HbDataGroup* group_Item = 
                static_cast<HbDataGroup*>(mSharedData->mItemView->itemByIndex(
                    childIndex));
                if(group_Item && group_Item->isExpanded()) {
                    HbDataGroupPrivate::d_ptr(group_Item)->expand(false);               
                
                }
            }
            QModelIndex nextChild = index.child(childIndex.row() +1 ,0);
            childIndex = nextChild;
        }

        if( mGroupHeading ) {
            mGroupHeading->mExpanded = false;
        }

    } else { //expand
        
        if(itemType == HbDataFormModelItem::GroupItem){
            HbDataFormModelItem *modelItem = static_cast<HbDataFormModel*>(
                mSharedData->mItemView->model())->itemFromIndex(mIndex.operator const QModelIndex & ());
            QModelIndex childIndex = (mIndex.operator const QModelIndex & ()).child(0,0);
            HbDataFormModelItem::DataItemType childType = static_cast<HbDataFormModelItem::DataItemType>(
                childIndex.data(HbDataFormModelItem::ItemTypeRole).toInt());
            if( childType == HbDataFormModelItem::GroupPageItem ) {
                QVariant pageIndex = modelItem->contentWidgetData(QString("currentPage"));
                int activePage;
                if(!pageIndex.isValid()) {
                    activePage = 0;
                } else {
                    activePage = pageIndex.toInt();
                }
                //get the group page index
                QModelIndex groupPageIndex = mIndex.child(activePage,0);
                if(groupPageIndex.isValid()) {                    
                    container->setItemStateValue(groupPageIndex, HbDataFormViewItem::ExpansionKey, true);
                }
            }
            if (mGroupHeading )  {
                mGroupHeading->mExpanded = true;
            }
        }
    }

    container->setItemStateValue(mIndex.operator const QModelIndex & (), HbDataFormViewItem::ExpansionKey, expanded);
}


QString HbDataGroupPrivate::groupPage() const
{   
    return mPageString;
}


void HbDataGroupPrivate::setGroupPage( const QString &page ) 
{
   Q_Q(HbDataGroup);

    if( !mPageCombo ) {
        mPageCombo = new HbComboBox( q );
        mPageString = " ";
        q->setProperty("groupPage", page);
        HbStyle::setItemName(mPageCombo,"dataGroup_Combo");   

        if ( !mPageComboBackgroundItem) {
            mPageComboBackgroundItem = q->style()->createPrimitive(HbStyle::P_DataGroupComboBackground, q);
            HbStyle::setItemName(mPageComboBackgroundItem,"dataGroup_ComboBackground");
        }

        if( !mGroupDescription.isEmpty() ) {
            if( !mGroupDescriptionItem ) {
                mGroupDescriptionItem = q->style()->createPrimitive(HbStyle::P_DataGroup_description, q);
                HbStyle::setItemName(mGroupDescriptionItem, "dataGroup_Description");
            }
        }
        
        QEvent polishEvent(QEvent::Polish);
        QCoreApplication::sendEvent(q, &polishEvent);
    }

    // disconnecting to avoid pagechanged signal when setting group.
    QObject::disconnect(mPageCombo,SIGNAL(currentIndexChanged(int)),
            q,SLOT(pageChanged(int)));

    QStringList list  = mPageCombo->items();    
    if(!list.contains(page)) {
        mPageCombo->addItem(page);        
        mPageString = page; 
    }   
    mPageCombo->setCurrentIndex(activePage());

    QObject::connect(mPageCombo,SIGNAL(currentIndexChanged(int)),
            q ,SLOT(pageChanged(int)));
}

void HbDataGroupPrivate::removeGroupPage(const QString &page)
{    
    if(mPageCombo) {
        mPageCombo->removeItem(mPageCombo->findText(page));
    }
}

int HbDataGroupPrivate::activePage( )
{
    Q_Q( HbDataGroup );

    HbDataFormModelItem *modelItem = 
        static_cast<HbDataFormModel*>((q->itemView())->model())->itemFromIndex(
            q->modelIndex( ));
    int page = 0;
    if(modelItem){
        page = modelItem->contentWidgetData(QString("currentPage")).toInt();
    }
    return page;
}

void HbDataGroupPrivate::setActivePage(int pageindex)
{  
    Q_Q( HbDataGroup ); 
   
    HbDataFormModelItem *modelItem = 
        static_cast<HbDataFormModel*>((q->itemView())->model())->itemFromIndex(
            q->modelIndex());
    
    QObject::disconnect( mSharedData->mItemView->model(), SIGNAL( dataChanged( QModelIndex,QModelIndex ) ),
        mSharedData->mItemView, SLOT( dataChanged( QModelIndex,QModelIndex ) ) );

    // CRC : Is it reqired here to disconnect and connect signals. ( done)
    modelItem->setContentWidgetData(QString("currentPage"),pageindex);

    QObject::connect( mSharedData->mItemView->model(), SIGNAL( dataChanged( QModelIndex,QModelIndex ) ),
        mSharedData->mItemView, SLOT( dataChanged( QModelIndex,QModelIndex ) ) );
}

void HbDataGroupPrivate::setHeading( const QString &heading )
{ 
    Q_Q( HbDataGroup );
    mGroupHeading->mHeading = heading;
    mGroupHeading->createPrimitives( );    
    q->updatePrimitives( );
}


QString HbDataGroupPrivate::heading() const
{    
    return mGroupHeading->mHeading;
}

HbDataGroup::HbDataGroup(QGraphicsItem *parent)
    :HbDataFormViewItem(* new HbDataGroupPrivate( this ), parent)
{    
}

HbDataGroup::HbDataGroup(const HbDataGroup &source):
    HbDataFormViewItem( *new HbDataGroupPrivate(*source.d_func()), 0)
{
    Q_D(HbDataGroup);
    d->q_ptr = this;
    d->init( );   
}

HbDataGroup::~HbDataGroup()
{
}

void HbDataGroup::initStyleOption(HbStyleOptionDataGroup *option)
{
    Q_D(HbDataGroup);
    HbWidget::initStyleOption(option);
    option->description = d->mGroupDescription;
}

void HbDataGroup::setDescription( const QString &description )
{
    Q_D(HbDataGroup);
    d->mGroupDescription = description;
    if( !d->mGroupDescription.isEmpty() ) {
        if( !d->mGroupDescriptionItem ) {
            d->mGroupDescriptionItem = style()->createPrimitive(HbStyle::P_DataGroup_description, this);
        }
    } else {
        if( d->mGroupDescriptionItem ) {
            delete d->mGroupDescriptionItem;
            d->mGroupDescriptionItem = 0;
        }
    }
}


QString HbDataGroup::description() const
{
    Q_D(const HbDataGroup);
    return d->mGroupDescription;
}

bool HbDataGroup::setExpanded( bool expanded )
{
    Q_D(HbDataGroup);
    HB_SD(HbAbstractViewItem);
    HbAbstractItemContainer *container = 0;

    if(d->mSharedData->mItemView) {
        container = qobject_cast<HbAbstractItemContainer *>(
            static_cast<QGraphicsWidget *>(d->mSharedData->mItemView->contentWidget()));
        if(container->itemState(d->mIndex).value(HbDataFormViewItem::ExpansionKey) 
                == expanded || !sd->mItemView) {
            return true;
        }    
        d->expand(expanded);
       

        //if some one exlicitly calls setExpanded for data group then primitives needs to be
        //updated.
        HbDataFormModelItem::DataItemType itemType = 
            static_cast<HbDataFormModelItem::DataItemType>(
            d->mIndex.data(HbDataFormModelItem::ItemTypeRole).toInt());
        if(itemType == HbDataFormModelItem::GroupItem){
            if(d->mPageCombo) {
                if(expanded) {

                    HbStyle::setItemName(d->mPageCombo,"dataGroup_Combo");
                    HbStyle::setItemName(d->mPageComboBackgroundItem,"dataGroup_ComboBackground");
                    HbStyle::setItemName(d->mGroupDescriptionItem, "dataGroup_Description");

                } else {

                    HbStyle::setItemName(d->mPageCombo,"");
                    HbStyle::setItemName(d->mPageComboBackgroundItem,"");
                    HbStyle::setItemName(d->mGroupDescriptionItem, "");
                    setProperty("groupPage", "");
                    d->mPageString.clear();
                    delete d->mPageCombo;
                    d->mPageCombo = 0;
                    delete d->mPageComboBackgroundItem;
                    d->mPageComboBackgroundItem = 0;
                    delete d->mGroupDescriptionItem;
                    d->mGroupDescriptionItem = 0;

                    QEvent polishEvent(QEvent::Polish);
                    QCoreApplication::sendEvent(this, &polishEvent);
                }
            }
        }
        container->setModelIndexes(d->mIndex.operator const QModelIndex & ());
    }
    updatePrimitives();
    return true;
}

bool HbDataGroup::isExpanded() const
{
    Q_D(const HbDataGroup);
    if(d->mGroupHeading) {
        return d->mGroupHeading->mExpanded;
	}
    return false;
}

void HbDataGroup::updateGroupPageName(int index , const QString &page)
{
    Q_D(HbDataGroup);
    if(index >= 0 && d->mPageCombo) {       
        if( d->mPageCombo->itemText(index) != page)  {          
            d->mPageCombo->setItemText(index,page);           
        }       
    }
}
void HbDataGroup::updatePrimitives()
{
    Q_D(HbDataGroup);

    //update data group heading primitives
    if(d->mGroupHeading) {
        d->mGroupHeading->updatePrimitives();        

        if( d->mGroupHeading->mExpanded ) {
            //update data group primitives
            HbStyleOptionDataGroup opt;
            initStyleOption(&opt);

            //update the combo background
            if ( d->mPageComboBackgroundItem ) {
                style()->updatePrimitive(
                    d->mPageComboBackgroundItem, HbStyle::P_DataGroupComboBackground, &opt);
            }

            //update the data group description
            if(d->mGroupDescriptionItem) {
                style()->updatePrimitive( 
                    d->mGroupDescriptionItem, HbStyle::P_DataGroup_description, &opt);
            }
        }
    }
}


void HbDataGroup::pageChanged(int index)
{
    Q_D(HbDataGroup);
    QStringListModel *model = (QStringListModel*)d->mPageCombo->model();
    QModelIndex changedIndex = model->index(index, 0);
    if(!itemView()) {
        return;
    }
    if(changedIndex.isValid()) {
        // Get Previous Active Group Page
        QModelIndex previousPageIndex = modelIndex().child(d->activePage(),0);
        if(changedIndex.row() != d->activePage()) {// If the page is different
            // Collapse previous group page
            HbDataGroup* previousPage = static_cast<HbDataGroup*>(itemView()->itemByIndex(previousPageIndex));
            d->setActivePage(changedIndex.row());
            if(previousPage) {
                previousPage->setExpanded(false);
            }
            // Expand current selected page set as active page
            QModelIndex currentPageIndex = modelIndex().child(changedIndex.row(),0);
            if(currentPageIndex.isValid()) {
                HbDataGroup* currentPage = static_cast<HbDataGroup*>(
                    (itemView())->itemByIndex(currentPageIndex));
                if(currentPage) {
                    currentPage->setExpanded(true);
                }
            }
        } else {//If selected page is same then expand it if it is not expanded already
            HbDataGroup* currentPage = static_cast<HbDataGroup*>(
                (itemView())->itemByIndex(previousPageIndex));
            if(currentPage && !currentPage->isExpanded()) {
                currentPage->setExpanded(true);
            }
        }
    }
}


HbDataFormViewItem* HbDataGroup::createItem()
{
    return new HbDataGroup(*this);
}

void HbDataGroup::updateChildItems()
{
    Q_D(HbDataGroup);
    HB_SD(HbAbstractViewItem);

    HbDataFormModelItem::DataItemType contentWidgetType = 
            static_cast<HbDataFormModelItem::DataItemType>(
            (d->mIndex.data(HbDataFormModelItem::ItemTypeRole)).toInt());

    if ( contentWidgetType == HbDataFormModelItem::GroupItem ) {
        d->mGroupHeading = new HbDataGroupHeadingWidget();
        HbStyle::setItemName(d->mGroupHeading,"dataGroup_HeadingWidget");
        d->mGroupHeading->setParentItem(this);
        d->mGroupHeading->mParent = this;
        d->mGroupHeading->createPrimitives();
        QEvent polishEvent(QEvent::Polish);
        QCoreApplication::sendEvent(d->mGroupHeading, &polishEvent);

        //set the heading of data group
        QString groupHeading = d->mIndex.data(
                    HbDataFormModelItem::LabelRole).toString();
        d->setHeading(groupHeading);

        //set the heading of data group
        QString groupDescription = d->mIndex.data(
            HbDataFormModelItem::DescriptionRole).toString();
        setDescription(groupDescription);
  
    } 
    else if( contentWidgetType == HbDataFormModelItem::GroupPageItem){
            QModelIndex parentIndex = d->mIndex.parent();
            HbDataGroup *parentGroup =
                static_cast<HbDataGroup *>(sd->mItemView->itemByIndex(parentIndex));
            QString groupHeading = d->mIndex.data(
                HbDataFormModelItem::LabelRole).toString();            
            HbDataGroupPrivate::d_ptr(parentGroup)->setGroupPage(groupHeading);

    } else if( contentWidgetType == HbDataFormModelItem::FormPageItem) {
        QString formPageName = d->mIndex.data(
                HbDataFormModelItem::LabelRole).toString();
            HbDataFormPrivate::d_ptr(static_cast<HbDataForm*>(sd->mItemView))->addFormPage(
                formPageName);

    }
        HbAbstractViewItem::updateChildItems();

}

bool HbDataGroup::canSetModelIndex(const QModelIndex &index) const
{
    HbDataFormModelItem::DataItemType itemType = 
        static_cast<HbDataFormModelItem::DataItemType>(
        index.data(HbDataFormModelItem::ItemTypeRole).toInt());

    if( itemType < HbDataFormModelItem::SliderItem ){
        return true;
    }
    return false;
}

void HbDataGroup::polish(HbStyleParameters& params)
{
    Q_D(HbDataGroup);
    HbDataFormModelItem::DataItemType itemType = 
        static_cast<HbDataFormModelItem::DataItemType>(
        d->mIndex.data(HbDataFormModelItem::ItemTypeRole).toInt());
    if( itemType == HbDataFormModelItem::GroupItem ){
        HbDataFormViewItem::polish(params);
    }
}

/*!
    \reimp
*/
// TODO: remove this, temporary workaround to return size zero incase of no contentwidget
QSizeF HbDataGroup::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
	//TODO: remove this
    QSizeF size;
    HbDataFormModelItem::DataItemType itemType = 
        static_cast<HbDataFormModelItem::DataItemType>(
        modelIndex().data(HbDataFormModelItem::ItemTypeRole).toInt());

    if(( itemType == HbDataFormModelItem::GroupPageItem )
        ||( itemType == HbDataFormModelItem::FormPageItem )) {
        size.setHeight(0);
    } else {
        size = HbDataFormViewItem::sizeHint(which,constraint );
    }
    return size;       
}

/*!
    \reimp
*/
void HbDataGroup::pressStateChanged(bool value, bool animate)
{
    //Since there are no effects defined for mousePressed and mouseReleased for 
    //HbDataFormViewItem we are overriding this function so that redundant effects functions are
    //not called in HbDataFormViewItem::pressStateChanged.
    Q_UNUSED(value);
    Q_UNUSED(animate);
}