src/hbwidgets/dataform/hbdataformmodel.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hbwidgets/dataform/hbdataformmodel.cpp	Mon Apr 19 14:02:13 2010 +0300
@@ -0,0 +1,706 @@
+/****************************************************************************
+**
+** 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 <hbdataformmodelitem.h>
+#include <hbdataformmodel.h>
+
+#include "hbdataformmodel_p.h"
+
+/*
+    \internal
+
+    adds the dataformviewitem or page or group depending upon /a itemType
+    and return pointer to newly created form item.
+    \a label : Label for the dataformItem. In case of GroupPage and FormPage,
+               label is added to parents combobox as one of the selectors.
+    \a parent : is parent of item 
+
+*/
+HbDataFormModelItem* HbDataFormModelPrivate::addItem(
+    HbDataFormModelItem::DataItemType itemType , const QString& label, HbDataFormModelItem *parent)
+{
+    if(!parent) {
+        parent = mRoot;
+    }
+    return insertItem( parent->childCount(), itemType , label , parent);
+}
+
+/*
+    \internal
+
+    insert  data form item or page or group depending upon /a itemType
+    and return pointer to newly created form item.
+    \a label :  Heading for data group , group tital in case of group page and page tital in case
+    item us data page item.
+    \a parent : is parent of item 
+
+*/
+HbDataFormModelItem* HbDataFormModelPrivate::insertItem(
+    int index,HbDataFormModelItem::DataItemType itemType ,const QString& label, HbDataFormModelItem *parent)
+{
+    if(!parent) {
+        parent = mRoot;
+    }
+    if(itemType == HbDataFormModelItem::GroupPageItem && (parent->type() != HbDataFormModelItem::GroupItem)) {
+        return 0;        
+    }
+    HbDataFormModelItem *item = new HbDataFormModelItem(itemType, label);
+    parent->insertChild(index , item);
+    return item;
+}
+
+/*
+  \internal
+*/
+void HbDataFormModelPrivate::rowsAboutToBeInserted(HbDataFormModelItem *parent,
+    int start, int end)
+{
+    Q_Q(HbDataFormModel);
+    QModelIndex index = q->indexFromItem(parent);
+    q->beginInsertRows(index, start, end);
+}
+
+/*
+  \internal
+*/
+void HbDataFormModelPrivate::rowsAboutToBeRemoved(HbDataFormModelItem *parent,
+    int start, int end)
+{
+    Q_Q(HbDataFormModel);
+    QModelIndex index = q->indexFromItem(parent);
+    q->beginRemoveRows(index, start, end);
+}
+
+/*
+  \internal
+*/
+void HbDataFormModelPrivate::rowsInserted()
+{
+    Q_Q(HbDataFormModel);
+    q->endInsertRows();
+}
+
+/*
+  \internal
+*/
+void HbDataFormModelPrivate::rowsRemoved()
+{
+    Q_Q(HbDataFormModel);
+    q->endRemoveRows();
+}
+
+
+/*!
+   @beta
+   @hbwidgets
+   \class HbDataFormModel hbdataformmodel.h
+   \brief The HbDataFormModel class provides data model for HbDataForm.
+   \ingroup model-view
+
+    HbDataFormModel is derived from QAbstractItemModel. So applications can use,
+    QAbstractItemModel API's to create their datamodel. HbDataFormModel also provides
+    convenience API's specific to HbDataForm. These convinience API's are useful in creating 
+    form page, group, group page and data item.
+
+    A HbDataForm can be used to display the contents of the model.
+    HbDataFormModel also has Apis to return modelindex of the items and vice-versa.
+    So applications can individually modify the items data and set it to the HbDataForm.
+ */
+
+/*!
+    Constructs a new data form model with the given \a parent.
+    
+*/
+HbDataFormModel::HbDataFormModel(QObject *parent)
+    :QAbstractItemModel(parent),d_ptr(new HbDataFormModelPrivate )
+{
+    Q_D(HbDataFormModel);
+    d->q_ptr = this; 
+    d->mRoot->setModel(this);
+}
+
+HbDataFormModel::~HbDataFormModel()
+{
+    Q_D(HbDataFormModel);
+    removeItem(d->mRoot);
+    delete d_ptr;
+}
+
+/*!
+    @beta
+
+    Appends FormPageItem and return pointer to newly created HbDataFormModelItem.
+    The parent of FormPageItem is always model's root item. The DataItemType is set
+    as FormPageItem.
+
+    \a label Label for data page. This label will be added in the top level combo box.
+
+    \sa insertDataFormPage
+
+*/
+HbDataFormModelItem* HbDataFormModel::appendDataFormPage(const QString &label)
+{
+    Q_D(HbDataFormModel);
+    return d->addItem(HbDataFormModelItem::FormPageItem,label,0);
+}
+
+/*!
+    @beta
+
+    Appends GroupItem and returns pointer to newly created HbDataFormModelItem.
+    The DataItemType is set as GroupItem.
+
+    \a label Label for data group. This label will be set as a group heading.
+    \a parent Parent of item. The parent of GroupItem can be either model's root
+        index or FormPageItem.
+
+    \sa insertDataFormGroup
+    
+*/
+HbDataFormModelItem* HbDataFormModel::appendDataFormGroup(const QString &label,
+    HbDataFormModelItem *parent)
+{
+    Q_D(HbDataFormModel);
+    return d->addItem(HbDataFormModelItem::GroupItem,label,parent);
+}
+
+/*!
+    @beta
+
+    Appends GroupPageItem and returns pointer to newly created HbDataFormModelItem.
+    The parent of GroupPageItem can only be GroupItem. If parent passed is other than
+    GroupItem then this item is not appended to model and returns 0. The DataItemType
+    is set as GroupPageItem.
+
+    \a label Label for data group page. This label will be added in group combo box.
+
+    \a parent Parent of item which can be only GroupItem.
+
+    \sa insertDataFormGroupPage
+    
+*/
+HbDataFormModelItem* HbDataFormModel::appendDataFormGroupPage(const QString &label,
+    HbDataFormModelItem *parent)
+{
+    Q_D(HbDataFormModel);    
+    return d->addItem(HbDataFormModelItem::GroupPageItem,label,parent);
+    
+}
+
+/*!
+    @beta
+
+    Appends data item and returns pointer to newly created HbDataFormModelItem.
+
+    \a itemType Type of data item. It can be anything in 
+        HbDataFormModelItem::DataItemType other than FormPageItem, GroupItem and 
+        GroupPageItem.
+    \a label Label for data item.
+    \a parent Parent of data item. Parent can be model's root index, FormPageItem, 
+       GroupPageItem or GroupItem.
+
+    \sa insertDataFormItem
+    
+*/
+HbDataFormModelItem* HbDataFormModel::appendDataFormItem(
+    HbDataFormModelItem::DataItemType itemType ,const QString &label,
+    HbDataFormModelItem *parent)
+{
+    Q_D(HbDataFormModel);
+    return d->addItem(itemType,label,parent);
+}
+
+/*!
+    @beta
+
+    This is a convenience API. If user wants then he can create HbDataFormModelItem 
+    individually and then add that item in model using this API.
+    If the \a data is of FormpageItemtype then parent is not considered. FormPage Items are always added
+    to rootItem. Also GroupPage Item has to be inserted in GroupItem.
+
+    \a data Child item to be inserted.
+    \a parent Parent of DataFormViewItem
+
+    \sa insertDataFormItem
+    
+*/
+void HbDataFormModel::appendDataFormItem(HbDataFormModelItem *data, HbDataFormModelItem *parent)
+{
+    if(!data)
+        return;
+   
+    HbDataFormModelItem::DataItemType itemType = data->type();
+
+    if(!parent || itemType == HbDataFormModelItem::FormPageItem) {
+        parent = invisibleRootItem();
+    }
+
+    
+    HbDataFormModelItem::DataItemType parentType = parent->type();
+
+    if(itemType == HbDataFormModelItem::GroupPageItem && parentType != HbDataFormModelItem::GroupItem)
+        return;
+
+    
+    parent->appendChild(data);
+}
+
+/*!
+    @beta
+
+    Inserts FormPageItem at the specified index and returns pointer to newly created 
+    HbDataFormModelItem. The parent can be only model's root index.
+
+    \a index Index where FormPageItem has to be inserted.
+    \a label Label of FormPageItem. This will be added in top level combo
+
+    \sa appendDataFormPage
+    
+*/
+HbDataFormModelItem* HbDataFormModel::insertDataFormPage(int index,const QString &label)
+{
+    Q_D(HbDataFormModel);
+    return d->insertItem(index , HbDataFormModelItem::FormPageItem , label);
+}
+
+/*!
+    @beta
+
+    Inserts GroupItem at the specified index and returns pointer to newly created 
+    HbDataFormModelItem.
+
+    \a index Index where GroupItem has to be inserted.
+    \a label Label for GroupItem. This will be group heading.
+    \a parent Parent of item 
+
+    \sa appendDataFormGroup
+    
+*/
+HbDataFormModelItem* HbDataFormModel::insertDataFormGroup(int index, const QString &label,
+    HbDataFormModelItem *parent)
+{
+    Q_D(HbDataFormModel);
+    return d->insertItem(index , HbDataFormModelItem::GroupItem ,label ,parent);
+}
+
+/*!
+    @beta
+
+    Inserts GroupPageItem at the specified index and returns pointer to newly created 
+    HbDataFormModelItem. Return 0 if parent passed is other than GroupItem.
+
+    \a index Index where GroupPageItem has to be inserted.
+    \a label Label for GroupPageItem. This will be added in group combo box.
+    \a parent Parent of item
+
+    \sa appendDataFormGroupPage
+    
+*/
+HbDataFormModelItem* HbDataFormModel::insertDataFormGroupPage(
+    int index, const QString &label, HbDataFormModelItem *parent)
+{
+    Q_D(HbDataFormModel);    
+    return d->insertItem(index , HbDataFormModelItem::GroupPageItem, label ,parent);  
+}
+
+/*!
+    @beta
+
+    Inserts data item at the specified index and returns pointer to newly created 
+    HbDataFormModelItem.
+
+    \a index Index where data item has to be inserted.
+    \a label Label for data page.
+    \a parent Parent of item
+
+    \sa appendDataFormItem
+    
+*/
+HbDataFormModelItem* HbDataFormModel::insertDataFormItem(int index,
+    HbDataFormModelItem::DataItemType itemType ,const QString &label,
+    HbDataFormModelItem *parent)
+{
+    Q_D(HbDataFormModel);
+    return d->insertItem(index ,itemType , label ,parent);
+}
+
+/*!
+    @beta
+
+    Inserts given HbDataFormModelItem \a data in the \a parent at the specified \a index.
+
+    \a index Index where data has to be inserted in parent
+    \a data HbDataFormModelItem which has to be inserted
+    \a parent Parent of item
+
+    \sa appendDataFormItem
+    
+*/
+void HbDataFormModel::insertDataFormItem(int index, HbDataFormModelItem *data,
+    HbDataFormModelItem *parent)
+{
+    if(!parent || (data->data(HbDataFormModelItem::ItemTypeRole) == HbDataFormModelItem::FormPageItem )) {
+        parent = invisibleRootItem();
+    }
+    parent->insertChild(index,data);    
+}
+
+
+/*!
+   \deprecated  HbDataFormModel::insertRows(int row, int count, const QModelIndex &index)
+        is deprecated. Please use other insert and additem API's in HbDataFormModel instead.
+*/
+bool HbDataFormModel::insertRows(int row, int count, const QModelIndex &index)
+{
+    Q_D(HbDataFormModel);
+    HbDataFormModelItem *item = index.isValid() ? itemFromIndex(index) : d->mRoot;
+    if (item == 0) {
+        return false;
+    }
+
+    QList<HbDataFormModelItem*> items;
+    for(int i =0 ; i < count ; i ++) {
+        items.append(new HbDataFormModelItem());
+    }
+    item->insertChildren(row,count,items);
+    return true;
+}
+
+
+/*!
+    @beta
+
+    Removes and deletes the model item from the model at the given \a index. The visualization
+    corresponding to this \a index is also deleted. Returns true if \a index is removed otherwise
+    returns false.
+
+    \sa removeItem
+*/
+bool HbDataFormModel::removeItem(const QModelIndex &index )
+{
+    return removeItem(itemFromIndex(index));
+}
+
+/*!
+    @beta
+
+    Removes and deletes given \a item. The visualization corresponding to this \a item
+    is also deleted. If the \a item has childrens, all the children items are removed and deleted.
+    \a item is deleted only if \a item belongs to current model. Returns true if \a item is removed 
+    otherwise returns false.
+
+    \sa removeItem
+*/
+bool HbDataFormModel::removeItem(HbDataFormModelItem *item)
+{
+    if( !item ) {
+        return false;
+    }
+    HbDataFormModelItem* parent = const_cast<HbDataFormModelItem*>(item->parent());
+    if ( item->model() != this ) {
+               return false;
+    }
+    
+    if( parent ) {
+        int index = parent->indexOf(item);
+        parent->removeChild(index);
+        return true;
+    } else if ( item == invisibleRootItem() ) {
+        delete item;
+        item = 0;
+        return true;
+    }
+
+    return false;
+
+}
+
+/*!
+  \reimp
+*/
+bool HbDataFormModel::removeRows(int row, int count, const QModelIndex &index)
+{   
+    HbDataFormModelItem *item = itemFromIndex(index);
+    if ((item == 0) || (count < 1) || (row < 0) || ((row + count) > item->childCount())) {
+        return false;
+    }
+
+    item->removeChildren(row, count);
+    return true;
+}
+
+/*!
+  \reimp
+    Column value should be 0 as DataForm has only one column.If the value is not 0
+    function returns invalid index.
+    If index is not valid then rootItem's index is considered.
+*/
+QModelIndex HbDataFormModel::index(int row, int column,
+    const QModelIndex &index) const
+{
+    
+    if (!hasIndex(row, column, index) && column > 0) {
+         return QModelIndex();
+    }
+    HbDataFormModelItem *parentItem = 0;
+
+    if (!index.isValid()) {
+        parentItem = invisibleRootItem();
+    } else {
+        parentItem = itemFromIndex(index);
+    }
+
+    HbDataFormModelItem *childItem = parentItem->childAt(row);
+    if (childItem) {
+        return createIndex(row, column, childItem);
+    } else {
+        return QModelIndex();
+    }
+}
+
+/*!
+  \reimp
+*/
+QModelIndex HbDataFormModel::parent(const QModelIndex &index) const
+{
+    if (!index.isValid()) {
+        return QModelIndex();
+    }
+
+    HbDataFormModelItem *childItem =itemFromIndex(index);        
+    HbDataFormModelItem *parentItem = childItem->parent();
+
+    if (parentItem == invisibleRootItem()) {
+        return QModelIndex();
+    }
+
+       return indexFromItem(parentItem);    
+}
+
+/*!
+  \reimp
+*/
+int HbDataFormModel::rowCount(const QModelIndex &item ) const
+{
+    HbDataFormModelItem *parentItem;
+    if (item.column() > 0) {
+        return 0;
+    }
+
+    if (!item.isValid()) {
+        parentItem = invisibleRootItem();
+    } else {
+        parentItem = static_cast<HbDataFormModelItem*>(item.internalPointer());
+    }
+    return parentItem->childCount();
+}
+
+/*!
+  \reimp
+*/
+int HbDataFormModel::columnCount(const QModelIndex & /*parent*/) const
+{
+    return 1;
+}
+
+/*!
+    \reimp
+
+    Returns true if given /a index has children, other wise false
+*/
+bool HbDataFormModel::hasChildren(const QModelIndex &index) const
+{
+    HbDataFormModelItem* item = 0;
+    if(index.isValid()) {
+        item = static_cast<HbDataFormModelItem*>(index.internalPointer());
+        if(item && item->childCount()) {
+            return true;
+        }
+    }
+    return false;
+}
+
+/*!
+    @beta
+
+    Returns child count for given parent index /a parent
+*/
+int HbDataFormModel::childCount(const QModelIndex &index) const
+{
+    return rowCount(index);
+}
+
+/*!
+  \reimp
+*/
+QVariant HbDataFormModel::data(const QModelIndex &index, int role) const
+{
+    HbDataFormModelItem *item = static_cast<HbDataFormModelItem*>(index.internalPointer());
+    return item ? item->data(role) : QVariant();
+}
+
+/*!
+  \reimp
+*/
+bool HbDataFormModel::setData(const QModelIndex &index, const QVariant &value,
+    int role)
+{
+    if (!index.isValid()) {
+        return false;
+    }
+    HbDataFormModelItem *item = itemFromIndex(index);
+    if (item == 0) {
+        return false;
+    }
+    item->setData(role , value);   
+    return true;
+}
+
+/*!
+    @beta
+
+    Removes all items  from the model and sets the
+    number of rows and columns to zero.
+
+    \sa removeColumns(), removeRows()
+*/
+void HbDataFormModel::clear()
+{
+    Q_D(HbDataFormModel);
+    removeItem(invisibleRootItem());
+    d->mRoot = new HbDataFormModelItem();
+    d->mRoot->setModel(this);
+    reset();
+}
+
+/*!
+    \reimp
+
+    Returns a pointer to the HbDataFormModelItem associated with the given \a index.
+
+    Calling this function is typically the initial step when processing
+    QModelIndex-based signals from a view, such as
+    HbAbstractItemView::activated(). In your slot, you call itemFromIndex(),
+    with the QModelIndex carried by the signal as argument, to obtain a
+    pointer to the corresponding HbDataFormModelItem.
+
+    NOTE: index passed should be the one returned from HbDataFromModel Only.
+
+    If \a index is an invalid index, this function returns 0.
+
+    \sa indexFromItem()
+*/
+HbDataFormModelItem* HbDataFormModel::itemFromIndex(const QModelIndex &index) const
+{
+    if ((index.row() < 0) || (index.column() < 0) || (index.model() != this)) {
+        return 0;
+    }
+         
+    HbDataFormModelItem *item = static_cast<HbDataFormModelItem*>(index.internalPointer());
+    if (item) {
+        return item;
+    }   
+    return 0;
+}
+
+/*!
+    \reimp
+
+    Returns the QModelIndex associated with the given \a item.
+    Use this function when you want to perform an operation that requires the
+    QModelIndex of the item, such as HbAbstractItemView::scrollTo(). 
+   
+    \sa itemFromIndex()
+*/
+QModelIndex HbDataFormModel::indexFromItem(const HbDataFormModelItem* item) const
+{
+    if(item) {          
+        HbDataFormModelItem* parentItem = item->parent();
+        if (parentItem) {
+            return createIndex(parentItem->indexOf(item), 0, (void*)item);
+        }
+    }
+    return QModelIndex();
+}
+
+/*! @beta
+
+    Returns the HbDataFormModelItem at given \a row and with given parent /a index.
+*/
+HbDataFormModelItem* HbDataFormModel::item(int row, const QModelIndex &index) const
+{
+    if(index.isValid()) {
+        return itemFromIndex(index)->childAt(row);
+    } else {
+        return invisibleRootItem()->childAt(row);
+    }
+}
+
+/*!
+    \reimp 
+   
+    Returns the model's invisible root item.
+
+    The invisible root item provides access to the model's top-level items
+    through the HbDataFormModelItem API, making it possible to write functions that
+    can treat top-level items and their children in a uniform way.
+    for example,recursive functions involving a tree model.
+
+*/
+HbDataFormModelItem* HbDataFormModel::invisibleRootItem() const
+{
+    Q_D(const HbDataFormModel);
+    return d->mRoot;
+}
+
+/*
+    \reimp
+*/
+bool HbDataFormModel::canFetchMore ( const QModelIndex & parent ) const
+{
+    if(parent.isValid()) {
+        if((hasChildren(parent)) || (sibling(parent.row() + 1,0,parent)).isValid()) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+/*
+    \reimp
+*/
+Qt::ItemFlags HbDataFormModel::flags(const QModelIndex &index) const
+{
+    if (index.isValid()) {
+        const HbDataFormModelItem *item = itemFromIndex(index);
+        if (item) {
+            return item->flags();
+        } 
+    }
+    return 0;
+}
+
+