src/hbwidgets/itemviews/hbtreeview.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
equal deleted inserted replaced
-1:000000000000 0:16d8024aca5e
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (developer.feedback@nokia.com)
       
     6 **
       
     7 ** This file is part of the HbWidgets module of the UI Extensions for Mobile.
       
     8 **
       
     9 ** GNU Lesser General Public License Usage
       
    10 ** This file may be used under the terms of the GNU Lesser General Public
       
    11 ** License version 2.1 as published by the Free Software Foundation and
       
    12 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
       
    13 ** Please review the following information to ensure the GNU Lesser General
       
    14 ** Public License version 2.1 requirements will be met:
       
    15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    16 **
       
    17 ** In addition, as a special exception, Nokia gives you certain additional
       
    18 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    20 **
       
    21 ** If you have questions regarding the use of this file, please contact
       
    22 ** Nokia at developer.feedback@nokia.com.
       
    23 **
       
    24 ****************************************************************************/
       
    25 
       
    26 #include "hbtreeview.h"
       
    27 #include "hbtreeview_p.h"
       
    28 #include "hbtreeitemcontainer_p.h"
       
    29 #include "hbtreeviewitem.h"
       
    30 #include "hbtreeitemselectionmodel_p.h"
       
    31 #include <hbwidgetfeedback.h>
       
    32 #include "hbtreemodeliterator_p.h"
       
    33 
       
    34 #include <QItemSelection>
       
    35 #include <QGraphicsSceneMouseEvent>
       
    36 
       
    37 /*!
       
    38     @alpha
       
    39     @hbwidgets
       
    40     \class HbTreeView
       
    41     \brief HbTreeView represents a hierarchical list
       
    42 
       
    43     The HbTreeView class provides a default model/view implementation of a tree view.
       
    44 
       
    45     A HbTreeView implements a tree representation of items from a model. This class is used to provide standard hierarchical 
       
    46     lists.
       
    47 
       
    48     HbTreeView implements the interfaces defined by the HbAbstractItemView class to allow it to display data provided 
       
    49     by models derived from the QAbstractItemModel class. 
       
    50 
       
    51     It is simple to construct a tree view displaying data from a model. In the following example, the contents of a directory 
       
    52     are supplied by a QDirModel and displayed as a tree:
       
    53 
       
    54     \snippet{ultimatecodesnippet/ultimatecodesnippet.cpp,43}
       
    55 
       
    56     The model/view architecture ensures that the contents of the tree view are updated as the model changes.
       
    57 
       
    58     Items that have children can be in an expanded (children are visible) or collapsed (children are hidden) state. 
       
    59 
       
    60     Each tree view item is represented by an instance of HbTreeViewItem. HbTreeView
       
    61     uses HbTreeViewItem prototype to instantiate the tree view items. HbTreeViewItem
       
    62     can be subclassed for customization purposes.
       
    63     
       
    64     By default, HbTreeView uses item recycling. This means that only the
       
    65     visible tree view items plus a small buffer of items above and below the visible
       
    66     list are instantiated at a time. When the view is scrolled the tree view items are
       
    67     recycled so that the buffer size above and below the tree view is kept constant.
       
    68 */
       
    69 
       
    70 /*!
       
    71     Constructs a tree view with \a parent.
       
    72  */
       
    73 HbTreeView::HbTreeView(QGraphicsItem *parent)
       
    74     : HbAbstractItemView(*new HbTreeViewPrivate(), new HbTreeItemContainer(), new HbTreeModelIterator(), parent)
       
    75 {
       
    76     Q_D( HbTreeView );
       
    77 
       
    78     d->q_ptr = this;
       
    79     d->init();
       
    80 }
       
    81 
       
    82 /*!
       
    83     \private
       
    84 */
       
    85 HbTreeView::HbTreeView(HbTreeViewPrivate &dd, HbAbstractItemContainer *container, QGraphicsItem *parent) :
       
    86     HbAbstractItemView(dd, container, new HbTreeModelIterator(), parent)
       
    87 {
       
    88     Q_D( HbTreeView );
       
    89 
       
    90     d->q_ptr = this;
       
    91     d->init();
       
    92 }
       
    93 
       
    94 
       
    95 /*!
       
    96     Destructs the tree view.
       
    97  */
       
    98 HbTreeView::~HbTreeView()
       
    99 {
       
   100 }
       
   101 
       
   102 /*!
       
   103     \reimp
       
   104 */
       
   105 void HbTreeView::scrollTo(const QModelIndex &index, ScrollHint hint)
       
   106 {
       
   107     Q_D(HbTreeView);
       
   108 
       
   109     if (    !index.isValid()
       
   110         ||  index.model() != d->mModelIterator->model()) {
       
   111         return;
       
   112     }
       
   113 
       
   114     QModelIndex newIndex = index;
       
   115     if (!d->mContainer->itemByIndex(index)) {
       
   116         QModelIndex parentIndex = index.parent();
       
   117         QModelIndex root = rootIndex();
       
   118         if (d->isParentValid(parentIndex) || root == index) {
       
   119             while (parentIndex.isValid() && parentIndex != root) {
       
   120                 if (!isExpanded(parentIndex)) {
       
   121                     newIndex = parentIndex;
       
   122                 }
       
   123                 parentIndex = parentIndex.parent();
       
   124             }
       
   125         }
       
   126     }
       
   127 
       
   128     if ( itemRecycling()) {
       
   129         bool itemBuffered = d->mContainer->itemByIndex(newIndex);
       
   130         if (! (     itemBuffered
       
   131                 &&  hint == PositionAtTop)) {
       
   132             if ( hint != PositionAtTop ) {
       
   133                 // Following two variable applies only for hint EnsureVisible.
       
   134                 // It is position relative to the view
       
   135                 bool belowBottom = false;
       
   136                 bool aboveTop = false;
       
   137                 if (hint == EnsureVisible) {
       
   138                     QModelIndex firstVisibleIndex;
       
   139                     QModelIndex lastVisibleIndex;
       
   140                     d->mContainer->firstAndLastVisibleModelIndex(firstVisibleIndex, lastVisibleIndex);
       
   141 
       
   142                     belowBottom = d->treeModelIterator()->lessThan(lastVisibleIndex, newIndex);
       
   143                     aboveTop = d->treeModelIterator()->lessThan(newIndex, firstVisibleIndex);
       
   144                 }
       
   145 
       
   146                 if (    hint == PositionAtBottom 
       
   147                     ||  hint == PositionAtCenter
       
   148                     ||  belowBottom ) {
       
   149                     // resolve index to be put to top of the recycle buffer
       
   150                     int stepCount = 0;
       
   151                     if (hint == PositionAtCenter) {
       
   152                         stepCount = d->mContainer->items().count() / 2;
       
   153                     } else {
       
   154                         stepCount = d->mContainer->items().count()-1;
       
   155                     }
       
   156                     QModelIndex topIndex = d->searchIndexUp(newIndex, stepCount);
       
   157                     d->mContainer->setModelIndexes(topIndex);
       
   158                 } else if (aboveTop) {
       
   159                     d->mContainer->setModelIndexes(newIndex);
       
   160                 }
       
   161                 // else - hint is EnsureVisible & item is already visible
       
   162             } else {
       
   163                 d->mContainer->setModelIndexes(newIndex);
       
   164             }
       
   165         }
       
   166     }
       
   167     HbAbstractItemView::scrollTo(newIndex, hint);
       
   168 }
       
   169 
       
   170 /*!
       
   171     \deprecated HbTreeView::indexCount() const
       
   172         is deprecated. Use \a HbModelIterator::indexCount() const
       
   173 
       
   174     \reimp
       
   175 
       
   176     Children of collapsed parents are not taken into account.
       
   177 */
       
   178 int HbTreeView::indexCount() const
       
   179 {
       
   180     qWarning("HbTreeView::indexCount() const is deprecated! Use HbModelIterator::indexCount() const.");
       
   181 
       
   182     return modelIterator()->indexCount();
       
   183 }
       
   184 
       
   185 /*!
       
   186     \deprecated HbTreeView::indexPosition(const QModelIndex&) const
       
   187         is deprecated. Use \a HbModelIterator::indexPosition(const QModelIndex&) const
       
   188 
       
   189     \reimp
       
   190 */
       
   191 int HbTreeView::indexPosition(const QModelIndex &index) const
       
   192 {
       
   193     qWarning("HbTreeView::indexPosition(const QModelIndex&) const is deprecated! Use HbModelIterator::indexPosition(const QModelIndex&) const.");
       
   194 
       
   195     return modelIterator()->indexPosition(index);
       
   196 }
       
   197 
       
   198 /*!
       
   199     \deprecated HbTreeView::nextIndex(const QModelIndex&) const
       
   200         is deprecated. Use \a HbModelIterator::nextIndex(const QModelIndex&) const
       
   201 
       
   202     \reimp
       
   203 
       
   204     Next index for valid index is determined in following way:
       
   205 
       
   206     - If index has children and it is expanded then first child is returned
       
   207     - Otherwise if index has next sibling then that is returned
       
   208     - Otherwise next valid sibling for parent is returned
       
   209     - Otherwise QModelIndex is returned
       
   210 */
       
   211 QModelIndex HbTreeView::nextIndex(const QModelIndex &index) const
       
   212 {
       
   213     qWarning("HbTreeView::nextIndex(const QModelIndex&) const is deprecated! Use HbModelIterator::nextIndex(const QModelIndex&) const.");
       
   214 
       
   215     return modelIterator()->nextIndex(index);
       
   216 }
       
   217 
       
   218 /*!
       
   219     \deprecated HbTreeView::previousIndex(const QModelIndex&) const
       
   220         is deprecated. Use \a HbModelIterator::previousIndex(const QModelIndex&) const
       
   221 
       
   222     \reimp
       
   223 
       
   224     Previous index for valid index is determined in following way:
       
   225 
       
   226     - If index has previous sibling last child from it is returned
       
   227     - Otherwise previous sibling is returned
       
   228     - Otherwise parent index is returned
       
   229     - Otherwise QModelIndex is returned
       
   230 */
       
   231 QModelIndex HbTreeView::previousIndex(const QModelIndex &index) const
       
   232 {
       
   233     qWarning("HbTreeView::previousIndex(const QModelIndex&) const is deprecated! Use HbModelIterator::previousIndex(const QModelIndex&) const.");
       
   234 
       
   235     return modelIterator()->previousIndex(index);
       
   236 }
       
   237 
       
   238 /*!
       
   239     \reimp
       
   240 */
       
   241 void HbTreeView::rowsInserted(const QModelIndex &parent, int start, int end)
       
   242 {
       
   243     Q_D(HbTreeView);
       
   244 
       
   245     if (d->mModelIterator->model()->columnCount(parent) == 0) {
       
   246         return;
       
   247     }
       
   248 
       
   249     if (d->isParentValid(parent)) {
       
   250         if (isExpanded(parent) || parent == d->mModelIterator->rootIndex()) {
       
   251             HbAbstractItemView::rowsInserted(parent, start, end);
       
   252         }
       
   253 
       
   254         HbAbstractViewItem *parentItem = d->mContainer->itemByIndex(parent);
       
   255         if (parentItem) {
       
   256             parentItem->updateChildItems();
       
   257         }            
       
   258     }
       
   259 }
       
   260 
       
   261 /*!
       
   262     \reimp
       
   263 */
       
   264 void HbTreeView::rowsRemoved(const QModelIndex &parent, int start, int end)
       
   265 {
       
   266     Q_D(HbTreeView);
       
   267 
       
   268     if (d->isParentValid(parent)) {
       
   269         if (parent == d->mCurrentIndex.parent() 
       
   270             && start <= d->mCurrentIndex.row()
       
   271             && d->mCurrentIndex.row() <= end) {
       
   272             // new current: 1) next after last deleted (note that
       
   273             // start and end index in model prior to deleting)
       
   274             // 2) just before first deleted
       
   275             QModelIndex newCurrentIndex = d->mModelIterator->nextIndex(d->mCurrentIndex);
       
   276             if (!newCurrentIndex.isValid()) {
       
   277                 newCurrentIndex = d->mModelIterator->previousIndex(d->mCurrentIndex);
       
   278             }
       
   279 
       
   280             if (d->mSelectionModel) {
       
   281                 d->mSelectionModel->setCurrentIndex(newCurrentIndex, QItemSelectionModel::NoUpdate);
       
   282             } 
       
   283         }  
       
   284 
       
   285         if (isExpanded(parent) || parent == d->mModelIterator->rootIndex()) {
       
   286             for (int i = d->mItemsToBeDeleted.count() - 1; i >= 0; --i) {
       
   287                 int pos = d->mItemsToBeDeleted.at(i);
       
   288                 d->mContainer->removeItem(pos);
       
   289             }
       
   290         }
       
   291 
       
   292         HbAbstractViewItem *parentItem = d->mContainer->itemByIndex(parent);
       
   293         if (parentItem) {
       
   294             parentItem->updateChildItems();
       
   295         }
       
   296     }
       
   297 
       
   298     d->mItemsToBeDeleted.clear();
       
   299 }
       
   300 
       
   301 /*!
       
   302     \reimp
       
   303 */
       
   304 void HbTreeView::rowsAboutToBeRemoved(const QModelIndex &index, int start, int end)
       
   305 {
       
   306     Q_D(HbTreeView);
       
   307 
       
   308     d->mItemsToBeDeleted.clear();
       
   309         
       
   310     QList <HbAbstractViewItem *> items = d->mContainer->items();
       
   311     int itemCount = items.count();
       
   312 
       
   313     // Add the view items given as parameters and all their child items to a list for deletion.    
       
   314     for (int i = start; i <= end; ++i) {
       
   315         QModelIndex parent = model()->index(i, 0, index);
       
   316         
       
   317         for (int j = 0; j < itemCount; ++j) {
       
   318             QModelIndex itemIndex = items.at(j)->modelIndex();
       
   319             if (itemIndex == parent || d->isChild(itemIndex, parent)) {
       
   320                 d->mItemsToBeDeleted.append(j);
       
   321             }
       
   322         }
       
   323     }
       
   324 }
       
   325 
       
   326 /*!
       
   327     \reimp
       
   328 */
       
   329 void HbTreeView::columnsInserted(const QModelIndex &parent, int start, int end)
       
   330 {
       
   331     Q_UNUSED(end)
       
   332     Q_UNUSED(start)
       
   333 
       
   334     Q_D(HbTreeView);
       
   335 
       
   336     if (d->isParentValid(parent)) {
       
   337         if (d->mModelIterator->model()->columnCount(parent) == 1){
       
   338             rowsInserted(parent, 0, d->mModelIterator->indexCount(parent));
       
   339         }
       
   340     }
       
   341 }
       
   342 
       
   343 /*!
       
   344     \reimp
       
   345 */
       
   346 void HbTreeView::columnsRemoved(const QModelIndex &parent, int start, int end)
       
   347 {
       
   348     Q_UNUSED(end)
       
   349     Q_UNUSED(start)
       
   350 
       
   351     Q_D(HbTreeView);
       
   352 
       
   353     if (d->isParentValid(parent)) {
       
   354         if (d->mModelIterator->model()->columnCount(parent) == 0){
       
   355             rowsRemoved(parent, 0, d->mModelIterator->indexCount(parent));
       
   356         }
       
   357     }
       
   358 
       
   359 }
       
   360 
       
   361 /*!
       
   362     \reimp
       
   363 */
       
   364 void HbTreeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
       
   365 {
       
   366     Q_D(HbTreeView);
       
   367     if (d->isParentValid(topLeft.parent())) {
       
   368         HbAbstractItemView::dataChanged(topLeft, bottomRight);
       
   369     }
       
   370 }
       
   371 
       
   372 
       
   373 /*!
       
   374     \reimp
       
   375     This function is involded in partial selecting and deselecting parent items.
       
   376     Selecting items are implemented by internal selection model class.
       
   377 */
       
   378 void HbTreeView::currentSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
       
   379 {
       
   380     Q_D(HbTreeView);
       
   381     bool selectionRoot = false;
       
   382     if (!d->mSelectionStarted) {
       
   383         d->mSelectionStarted = true;
       
   384         selectionRoot = true;
       
   385     }
       
   386 
       
   387     HbAbstractItemView::currentSelectionChanged(selected, deselected);
       
   388 
       
   389     if (selectionRoot) {
       
   390         QModelIndexList selectedIndexes(selected.indexes());
       
   391         QMap<QModelIndex, Qt::CheckState> parentItems;
       
   392 
       
   393         int count = selectedIndexes.count();
       
   394         for (int i = 0; i < count; ++i) {
       
   395             QModelIndex index = selectedIndexes.at(i);
       
   396 
       
   397             // Parents are always partially selected when one of the
       
   398             // children is selected.
       
   399             QModelIndex parentIndex = index.parent();
       
   400             if (!parentItems.contains(parentIndex)) {
       
   401                 while (parentIndex != d->mModelIterator->rootIndex()) {
       
   402                     if (!d->mSelectionModel->isSelected(parentIndex)) {
       
   403                         parentItems.insert(parentIndex, Qt::PartiallyChecked);
       
   404                     } 
       
   405                     // else - occurs when node is selected. Node
       
   406                     // may come first in the selection list and only after that its children
       
   407                     parentIndex = parentIndex.parent();
       
   408                 }
       
   409             }
       
   410         }
       
   411 
       
   412         QModelIndexList deselectedIndexes(deselected.indexes());
       
   413         QItemSelection deselectedChildren;
       
   414 
       
   415         count = deselectedIndexes.count();
       
   416         for (int i = 0; i < count; ++i) {
       
   417             QModelIndex index = deselectedIndexes.at(i);
       
   418             bool solveParentCheckState = true;
       
   419 
       
   420             // Solves the partial selection/non-selection state for the parents
       
   421             // by checking status of siblings. Parent will PartiallyChecked, if
       
   422             // sibling is either checked or partially checked.
       
   423 
       
   424             // There is one exception, which this slot cannot handle. It is handled by HbTreeItemSelectionModel::select().
       
   425             // See its documentation
       
   426             QModelIndex parentIndex = index.parent();
       
   427             while (parentIndex != d->mModelIterator->rootIndex()) {
       
   428                 Qt::CheckState parentCheckState = Qt::PartiallyChecked;
       
   429                 if (solveParentCheckState) {
       
   430                     int childCount = model()->rowCount(parentIndex);
       
   431                     for (int current = 0; current < childCount; ++current) {
       
   432                         QModelIndex childIndex = parentIndex.child(current, parentIndex.column());
       
   433 
       
   434                         // Resolves child check state.
       
   435                         Qt::CheckState childCheckState = Qt::Unchecked;
       
   436                         if (d->mSelectionModel->isSelected(childIndex)) {
       
   437                             childCheckState = Qt::PartiallyChecked;
       
   438                         } else if (parentItems.contains(childIndex)) {
       
   439                             // handles use case: node1, which has child node2, which has child leaf1.
       
   440                             // Initially node1 is selected, then leaf1 is selected.
       
   441                             // Node2 may have been set Unchecked into map before node1.
       
   442                             // When node1 will be handled, node2 is unchecked in the map but not yet in the view item
       
   443                             childCheckState = parentItems.value(childIndex);
       
   444                         } else {
       
   445                             QVariant value = d->mContainer->itemState(childIndex).value(HbTreeViewItem::CheckStateKey);
       
   446                             if (value.isValid()) {
       
   447                                 childCheckState = (Qt::CheckState)value.toInt();
       
   448                             }
       
   449                         }
       
   450                         if (childCheckState != Qt::Unchecked) {
       
   451                             // No need to solve further parents check state as
       
   452                             // one child item is selected -> all parents are partially
       
   453                             // selected.
       
   454                             solveParentCheckState = false;
       
   455                             break;
       
   456                         }
       
   457 
       
   458                         if (current == childCount - 1) {
       
   459                             parentCheckState = Qt::Unchecked;
       
   460                         }
       
   461                     }   
       
   462                 }
       
   463                 if (!parentItems.contains(parentIndex)) {
       
   464                     // handling use case: parent initially multi selected, then a leaf is multi deselected
       
   465                     QItemSelection selection(parentIndex, parentIndex);
       
   466                     // Using HbTreeItemSelectionModel must be bypassed, because it would deselect every children, too
       
   467                     d->mSelectionModel->QItemSelectionModel::select(selection, QItemSelectionModel::Deselect);
       
   468                 }
       
   469                 parentItems.insert(parentIndex, parentCheckState);
       
   470                 parentIndex = parentIndex.parent();
       
   471             }
       
   472         }
       
   473 
       
   474         QMap<QModelIndex, Qt::CheckState>::iterator iterator = parentItems.begin();
       
   475         while (iterator != parentItems.end()) {
       
   476             HbAbstractViewItem *item = d->mContainer->itemByIndex(iterator.key());
       
   477             if (item) {
       
   478                 item->setCheckState(iterator.value());
       
   479             } 
       
   480 
       
   481             d->mContainer->setItemStateValue(iterator.key(), HbAbstractViewItem::CheckStateKey, iterator.value());
       
   482             iterator++;
       
   483         }
       
   484 
       
   485         d->mSelectionStarted = false;
       
   486     }
       
   487 }
       
   488 
       
   489 /*!
       
   490     Sets the item referred to by \a index to either collapse or expanded, depending on the value of \a expanded.
       
   491 
       
   492     \sa isExpanded
       
   493 */
       
   494 void HbTreeView::setExpanded(const QModelIndex &index, bool expanded)
       
   495 {
       
   496     Q_D(HbTreeView);
       
   497 
       
   498     if (isExpanded(index) != expanded) {
       
   499         d->treeModelIterator()->itemStateChanged(index, HbTreeViewItem::ExpansionKey);
       
   500         HbTreeItemContainer *container = qobject_cast<HbTreeItemContainer *>(d->mContainer);
       
   501         container->setExpanded(index, expanded);
       
   502     }
       
   503 }
       
   504 
       
   505 /*!
       
   506     Returns true if the model item \a index is expanded; otherwise returns false.
       
   507 
       
   508     \sa setExpanded
       
   509 */
       
   510 bool HbTreeView::isExpanded(const QModelIndex &index) const
       
   511 {
       
   512     Q_D(const HbTreeView);
       
   513 
       
   514     HbTreeItemContainer *container = qobject_cast<HbTreeItemContainer *>(d->mContainer);
       
   515     return container->isExpanded(index);
       
   516 }
       
   517 /*!
       
   518     Overrides default indentation of tree view items defined in style sheet.
       
   519     Items, which are not immediate children of root item are indented by
       
   520     indentation * level pixels. 
       
   521     Level is count of parent items between item itself and root item.
       
   522 
       
   523     If negative value is set, then indentation from style sheet is used.
       
   524 
       
   525     \sa indentation
       
   526 */
       
   527 void HbTreeView::setIndentation(qreal indentation)
       
   528 {
       
   529     Q_ASSERT_X(qobject_cast<HbTreeItemContainer*>(container()), "HbTreeView::setIndentation", "wrong container type");
       
   530     qobject_cast<HbTreeItemContainer*>(container())->setIndentation(indentation);
       
   531 }
       
   532 
       
   533 /*!
       
   534     Returns indentation of tree view items. 
       
   535     The returned value is either default value or set by setIndentation().
       
   536 
       
   537     Default value is -1. In this case indentation from style sheet is used.
       
   538 
       
   539     \sa setIndentation
       
   540 */
       
   541 qreal HbTreeView::indentation() const
       
   542 {
       
   543     Q_ASSERT_X(qobject_cast<HbTreeItemContainer*>(container()), "HbTreeView::indentation", "wrong container type");
       
   544     return qobject_cast<HbTreeItemContainer*>(container())->indentation();
       
   545 }
       
   546 
       
   547 /*!
       
   548     \reimp
       
   549 */
       
   550 void HbTreeView::reset()
       
   551 {
       
   552     HbAbstractItemView::reset();
       
   553 }
       
   554 
       
   555 
       
   556 /*!
       
   557     \reimp
       
   558 */
       
   559 void HbTreeView::setRootIndex(const QModelIndex &index)
       
   560 {
       
   561     //Q_D(HbTreeView);
       
   562     HbAbstractItemView::setRootIndex(index);
       
   563     setExpanded(index, true); 
       
   564 }
       
   565 
       
   566 /*!
       
   567     This function handles expanding and collapsing parent items in tree view. 
       
   568     Parent item expands and collapses, when pressed down is released
       
   569     exluding following use cases:
       
   570     \li HbTreeViewItem::selectionAreaContains() has returned true for pressed down
       
   571     \li view is panned or scrolled 
       
   572 
       
   573     \sa HbTreeViewItem::selectionAreaContains() 
       
   574 */
       
   575 void HbTreeView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
       
   576 {
       
   577     Q_D(HbTreeView);
       
   578 
       
   579     HbTreeViewItem* hitItem = qobject_cast<HbTreeViewItem*>(d->itemAt(event->scenePos()));
       
   580 
       
   581     // check whether expansion collapsion can be done
       
   582     if (    d->mHitItem
       
   583         &&  d->mHitItem == hitItem
       
   584         &&  hitItem->primitive(HbStyle::P_TreeViewItem_expandicon)
       
   585         &&  hitItem->flags().testFlag(QGraphicsItem::ItemIsFocusable)
       
   586         &&  !d->mWasScrolling
       
   587         &&  (   d->mSelectionMode == SingleSelection
       
   588             || !d->mSelectionSettings.testFlag(HbAbstractItemViewPrivate::Selection))) {
       
   589         Hb::InteractionModifiers modifiers = 0;
       
   590         if (hitItem->isExpanded()) {
       
   591             d->mInstantClickedModifiers |= Hb::ModifierExpandedItem;
       
   592         } else {
       
   593             d->mInstantClickedModifiers |= Hb::ModifierCollapsedItem;
       
   594         }
       
   595         hitItem->setExpanded(!hitItem->isExpanded());
       
   596     }
       
   597 
       
   598     HbAbstractItemView::mouseReleaseEvent(event);
       
   599 }
       
   600 
       
   601 /*!
       
   602     \reimp
       
   603     Tree view has its internal selection model. Implementation of this virtual function is needed
       
   604     to take it into use with new model..
       
   605 */
       
   606 void HbTreeView::setModel(QAbstractItemModel *model, HbAbstractViewItem *prototype)
       
   607 {
       
   608     Q_D(HbTreeView);
       
   609     HbAbstractItemView::setModel(model, prototype);
       
   610     setSelectionModel(new HbTreeItemSelectionModel(model, d, this));
       
   611 }
       
   612 
       
   613 #include "moc_hbtreeview.cpp"
       
   614