|
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 |