source: trunk/src/gui/itemviews/qtreewidget.cpp@ 5

Last change on this file since 5 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 96.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information (qt-info@nokia.com)
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at qt-sales@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qtreewidget.h"
43
44#ifndef QT_NO_TREEWIDGET
45#include <qheaderview.h>
46#include <qpainter.h>
47#include <qitemdelegate.h>
48#include <qstack.h>
49#include <qdebug.h>
50#include <private/qtreewidget_p.h>
51#include <private/qwidgetitemdata_p.h>
52#include <private/qtreewidgetitemiterator_p.h>
53
54QT_BEGIN_NAMESPACE
55
56// workaround for VC++ 6.0 linker bug (?)
57typedef bool(*LessThan)(const QPair<QTreeWidgetItem*,int>&,const QPair<QTreeWidgetItem*,int>&);
58
59class QTreeModelLessThan
60{
61public:
62 inline bool operator()(QTreeWidgetItem *i1, QTreeWidgetItem *i2) const
63 { return *i1 < *i2; }
64};
65
66class QTreeModelGreaterThan
67{
68public:
69 inline bool operator()(QTreeWidgetItem *i1, QTreeWidgetItem *i2) const
70 { return *i2 < *i1; }
71};
72
73/*
74 \class QTreeModel
75 \brief The QTreeModel class manages the items stored in a tree view.
76
77 \ingroup model-view
78 \mainclass
79*/
80
81/*!
82 \enum QTreeWidgetItem::ChildIndicatorPolicy
83 \since 4.3
84
85 \value ShowIndicator The controls for expanding and collapsing will be shown for this item even if there are no children.
86 \value DontShowIndicator The controls for expanding and collapsing will never be shown even if there are children. If the node is forced open the user will not be able to expand or collapse the item.
87 \value DontShowIndicatorWhenChildless The controls for expanding and collapsing will be shown if the item contains children.
88*/
89
90/*!
91 \fn void QTreeWidgetItem::setDisabled(bool disabled)
92 \since 4.3
93
94 Disables the item if \a disabled is true; otherwise enables the item.
95
96 \sa setFlags()
97*/
98
99/*!
100 \fn bool QTreeWidgetItem::isDisabled() const
101 \since 4.3
102
103 Returns true if the item is disabled; otherwise returns false.
104
105 \sa setFlags()
106*/
107
108/*!
109 \internal
110
111 Constructs a tree model with a \a parent object and the given
112 number of \a columns.
113*/
114
115QTreeModel::QTreeModel(int columns, QTreeWidget *parent)
116 : QAbstractItemModel(parent), rootItem(new QTreeWidgetItem),
117 headerItem(new QTreeWidgetItem), skipPendingSort(false)
118{
119 rootItem->view = parent;
120 rootItem->itemFlags = Qt::ItemIsDropEnabled;
121 headerItem->view = parent;
122 setColumnCount(columns);
123}
124
125/*!
126 \internal
127
128*/
129
130QTreeModel::QTreeModel(QTreeModelPrivate &dd, QTreeWidget *parent)
131 : QAbstractItemModel(dd, parent), rootItem(new QTreeWidgetItem),
132 headerItem(new QTreeWidgetItem), skipPendingSort(false)
133{
134 rootItem->view = parent;
135 rootItem->itemFlags = Qt::ItemIsDropEnabled;
136 headerItem->view = parent;
137}
138
139/*!
140 \internal
141
142 Destroys this tree model.
143*/
144
145QTreeModel::~QTreeModel()
146{
147 clear();
148 delete headerItem;
149 rootItem->view = 0;
150 delete rootItem;
151}
152
153/*!
154 \internal
155
156 Removes all items in the model.
157*/
158
159void QTreeModel::clear()
160{
161 SkipSorting skipSorting(this);
162 for (int i = 0; i < rootItem->childCount(); ++i) {
163 QTreeWidgetItem *item = rootItem->children.at(i);
164 item->par = 0;
165 item->view = 0;
166 delete item;
167 }
168 rootItem->children.clear();
169 sortPendingTimer.stop();
170 reset();
171}
172
173/*!
174 \internal
175
176 Sets the number of \a columns in the tree model.
177*/
178
179void QTreeModel::setColumnCount(int columns)
180{
181 SkipSorting skipSorting(this);
182 if (columns < 0)
183 return;
184 if (!headerItem) {
185 headerItem = new QTreeWidgetItem();
186 headerItem->view = view();
187 }
188 int count = columnCount();
189 if (count == columns)
190 return;
191
192 if (columns < count) {
193 beginRemoveColumns(QModelIndex(), columns, count - 1);
194 headerItem->values.resize(columns);
195 endRemoveColumns();
196 } else {
197 beginInsertColumns(QModelIndex(), count, columns - 1);
198 headerItem->values.resize(columns);
199 for (int i = count; i < columns; ++i) {// insert data without emitting the dataChanged signal
200 headerItem->values[i].append(QWidgetItemData(Qt::DisplayRole, QString::number(i + 1)));
201 headerItem->d->display.append(QString::number(i + 1));
202 }
203 endInsertColumns();
204 }
205}
206
207/*!
208 \internal
209
210 Returns the tree view item corresponding to the \a index given.
211
212 \sa QModelIndex
213*/
214
215QTreeWidgetItem *QTreeModel::item(const QModelIndex &index) const
216{
217 if (!index.isValid())
218 return 0;
219 return static_cast<QTreeWidgetItem*>(index.internalPointer());
220}
221
222/*!
223 \internal
224
225 Returns the model index that refers to the
226 tree view \a item and \a column.
227*/
228
229QModelIndex QTreeModel::index(const QTreeWidgetItem *item, int column) const
230{
231 executePendingSort();
232
233 if (!item || (item == rootItem))
234 return QModelIndex();
235 const QTreeWidgetItem *par = item->parent();
236 QTreeWidgetItem *itm = const_cast<QTreeWidgetItem*>(item);
237 if (!par)
238 par = rootItem;
239 int row;
240 int guess = item->d->rowGuess;
241 if (guess >= 0
242 && par->children.count() > guess
243 && par->children.at(guess) == itm) {
244 row = guess;
245 } else {
246 row = par->children.lastIndexOf(itm);
247 itm->d->rowGuess = row;
248 }
249 return createIndex(row, column, itm);
250}
251
252/*!
253 \internal
254 \reimp
255
256 Returns the model index with the given \a row,
257 \a column and \a parent.
258*/
259
260QModelIndex QTreeModel::index(int row, int column, const QModelIndex &parent) const
261{
262 executePendingSort();
263
264 int c = columnCount(parent);
265 if (row < 0 || column < 0 || column >= c)
266 return QModelIndex();
267
268 QTreeWidgetItem *parentItem = parent.isValid() ? item(parent) : rootItem;
269 if (parentItem && row < parentItem->childCount()) {
270 QTreeWidgetItem *itm = parentItem->child(row);
271 if (itm)
272 return createIndex(row, column, itm);
273 return QModelIndex();
274 }
275
276 return QModelIndex();
277}
278
279/*!
280 \internal
281 \reimp
282
283 Returns the parent model index of the index given as
284 the \a child.
285*/
286
287QModelIndex QTreeModel::parent(const QModelIndex &child) const
288{
289 SkipSorting skipSorting(this); //The reason we don't sort here is that this might be called from a valid QPersistentModelIndex
290 //We don't want it to become suddenly invalid
291
292 if (!child.isValid())
293 return QModelIndex();
294 QTreeWidgetItem *itm = static_cast<QTreeWidgetItem *>(child.internalPointer());
295 if (!itm || itm == rootItem)
296 return QModelIndex();
297 QTreeWidgetItem *parent = itm->parent();
298 return index(parent, 0);
299}
300
301/*!
302 \internal
303 \reimp
304
305 Returns the number of rows in the \a parent model index.
306*/
307
308int QTreeModel::rowCount(const QModelIndex &parent) const
309{
310 if (!parent.isValid())
311 return rootItem->childCount();
312
313 QTreeWidgetItem *parentItem = item(parent);
314 if (parentItem)
315 return parentItem->childCount();
316 return 0;
317}
318
319/*!
320 \internal
321 \reimp
322
323 Returns the number of columns in the item referred to by
324 the given \a index.
325*/
326
327int QTreeModel::columnCount(const QModelIndex &index) const
328{
329 Q_UNUSED(index);
330 if (!headerItem)
331 return 0;
332 return headerItem->columnCount();
333}
334
335bool QTreeModel::hasChildren(const QModelIndex &parent) const
336{
337 if (!parent.isValid())
338 return (rootItem->childCount() > 0);
339
340 QTreeWidgetItem *itm = item(parent);
341 if (!itm)
342 return false;
343 switch (itm->d->policy) {
344 case QTreeWidgetItem::ShowIndicator:
345 return true;
346 case QTreeWidgetItem::DontShowIndicator:
347 return false;
348 case QTreeWidgetItem::DontShowIndicatorWhenChildless:
349 return (itm->childCount() > 0);
350 }
351 return false;
352}
353
354/*!
355 \internal
356 \reimp
357
358 Returns the data corresponding to the given model \a index
359 and \a role.
360*/
361
362QVariant QTreeModel::data(const QModelIndex &index, int role) const
363{
364 if (!index.isValid())
365 return QVariant();
366 QTreeWidgetItem *itm = item(index);
367 if (itm)
368 return itm->data(index.column(), role);
369 return QVariant();
370}
371
372/*!
373 \internal
374 \reimp
375
376 Sets the data for the item specified by the \a index and \a role
377 to that referred to by the \a value.
378
379 Returns true if successful; otherwise returns false.
380*/
381
382bool QTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
383{
384 if (!index.isValid())
385 return false;
386 QTreeWidgetItem *itm = item(index);
387 if (itm) {
388 itm->setData(index.column(), role, value);
389 return true;
390 }
391 return false;
392}
393
394QMap<int, QVariant> QTreeModel::itemData(const QModelIndex &index) const
395{
396 QMap<int, QVariant> roles;
397 QTreeWidgetItem *itm = item(index);
398 if (itm) {
399 int column = index.column();
400 if (column < itm->values.count()) {
401 for (int i = 0; i < itm->values.at(column).count(); ++i) {
402 roles.insert(itm->values.at(column).at(i).role,
403 itm->values.at(column).at(i).value);
404 }
405 }
406
407 // the two special cases
408 QVariant displayValue = itm->data(column, Qt::DisplayRole);
409 if (displayValue.isValid())
410 roles.insert(Qt::DisplayRole, displayValue);
411
412 QVariant checkValue = itm->data(column, Qt::CheckStateRole);
413 if (checkValue.isValid())
414 roles.insert(Qt::CheckStateRole, checkValue);
415 }
416 return roles;
417}
418
419/*!
420 \internal
421 \reimp
422*/
423bool QTreeModel::insertRows(int row, int count, const QModelIndex &parent)
424{
425 SkipSorting skipSorting(this);
426 if (count < 1 || row < 0 || row > rowCount(parent) || parent.column() > 0)
427 return false;
428
429 beginInsertRows(parent, row, row + count - 1);
430 QTreeWidgetItem *par = item(parent);
431 while (count > 0) {
432 QTreeWidgetItem *item = new QTreeWidgetItem();
433 item->view = view();
434 item->par = par;
435 if (par)
436 par->children.insert(row++, item);
437 else
438 rootItem->children.insert(row++, item);
439 --count;
440 }
441 endInsertRows();
442 return true;
443}
444
445/*!
446 \internal
447 \reimp
448*/
449bool QTreeModel::insertColumns(int column, int count, const QModelIndex &parent)
450{
451 SkipSorting skipSorting(this);
452 if (count < 1 || column < 0 || column > columnCount(parent) || parent.column() > 0 || !headerItem)
453 return false;
454
455 beginInsertColumns(parent, column, column + count - 1);
456
457 int oldCount = columnCount(parent);
458 column = qBound(0, column, oldCount);
459 headerItem->values.resize(oldCount + count);
460 for (int i = oldCount; i < oldCount + count; ++i) {
461 headerItem->values[i].append(QWidgetItemData(Qt::DisplayRole, QString::number(i + 1)));
462 headerItem->d->display.append(QString::number(i + 1));
463 }
464
465 QStack<QTreeWidgetItem*> itemstack;
466 itemstack.push(0);
467 while (!itemstack.isEmpty()) {
468 QTreeWidgetItem *par = itemstack.pop();
469 QList<QTreeWidgetItem*> children = par ? par->children : rootItem->children;
470 for (int row = 0; row < children.count(); ++row) {
471 QTreeWidgetItem *child = children.at(row);
472 if (child->children.count())
473 itemstack.push(child);
474 child->values.insert(column, count, QVector<QWidgetItemData>());
475 }
476 }
477
478 endInsertColumns();
479 return true;
480}
481
482/*!
483 \internal
484 \reimp
485*/
486bool QTreeModel::removeRows(int row, int count, const QModelIndex &parent) {
487 if (count < 1 || row < 0 || (row + count) > rowCount(parent))
488 return false;
489
490 beginRemoveRows(parent, row, row + count - 1);
491
492 bool blockSignal = signalsBlocked();
493 blockSignals(true);
494
495 QTreeWidgetItem *itm = item(parent);
496 for (int i = row + count - 1; i >= row; --i) {
497 QTreeWidgetItem *child = itm ? itm->takeChild(i) : rootItem->children.takeAt(i);
498 Q_ASSERT(child);
499 child->view = 0;
500 delete child;
501 child = 0;
502 }
503 blockSignals(blockSignal);
504
505 endRemoveRows();
506 return true;
507}
508
509/*!
510 \internal
511 \reimp
512
513 Returns the header data corresponding to the given header \a section,
514 \a orientation and data \a role.
515*/
516
517QVariant QTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
518{
519 if (orientation != Qt::Horizontal)
520 return QVariant();
521
522 if (headerItem)
523 return headerItem->data(section, role);
524 if (role == Qt::DisplayRole)
525 return QString::number(section + 1);
526 return QVariant();
527}
528
529/*!
530 \internal
531 \reimp
532
533 Sets the header data for the item specified by the header \a section,
534 \a orientation and data \a role to the given \a value.
535
536 Returns true if successful; otherwise returns false.
537*/
538
539bool QTreeModel::setHeaderData(int section, Qt::Orientation orientation,
540 const QVariant &value, int role)
541{
542 if (section < 0 || orientation != Qt::Horizontal || !headerItem || section >= columnCount())
543 return false;
544
545 headerItem->setData(section, role, value);
546 return true;
547}
548
549/*!
550 \reimp
551
552 Returns the flags for the item referred to the given \a index.
553
554*/
555
556Qt::ItemFlags QTreeModel::flags(const QModelIndex &index) const
557{
558 if (!index.isValid())
559 return rootItem->flags();
560 QTreeWidgetItem *itm = item(index);
561 Q_ASSERT(itm);
562 return itm->flags();
563}
564
565/*!
566 \internal
567
568 Sorts the entire tree in the model in the given \a order,
569 by the values in the given \a column.
570*/
571
572void QTreeModel::sort(int column, Qt::SortOrder order)
573{
574 SkipSorting skipSorting(this);
575 sortPendingTimer.stop();
576
577 if (column < 0 || column >= columnCount())
578 return;
579
580 //layoutAboutToBeChanged and layoutChanged will be called by sortChildren
581 rootItem->sortChildren(column, order, true);
582}
583
584/*!
585 \internal
586*/
587void QTreeModel::ensureSorted(int column, Qt::SortOrder order,
588 int start, int end, const QModelIndex &parent)
589{
590 if (isChanging())
591 return;
592
593 sortPendingTimer.stop();
594
595 if (column < 0 || column >= columnCount())
596 return;
597
598 SkipSorting skipSorting(this);
599
600 QTreeWidgetItem *itm = item(parent);
601 if (!itm)
602 itm = rootItem;
603 QList<QTreeWidgetItem*> lst = itm->children;
604
605 int count = end - start + 1;
606 QVector < QPair<QTreeWidgetItem*,int> > sorting(count);
607 for (int i = 0; i < count; ++i) {
608 sorting[i].first = lst.at(start + i);
609 sorting[i].second = start + i;
610 }
611
612 LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
613 qStableSort(sorting.begin(), sorting.end(), compare);
614
615 QModelIndexList oldPersistentIndexes;
616 QModelIndexList newPersistentIndexes;
617 QList<QTreeWidgetItem*>::iterator lit = lst.begin();
618 bool changed = false;
619
620 for (int i = 0; i < count; ++i) {
621 int oldRow = sorting.at(i).second;
622 QTreeWidgetItem *item = lst.takeAt(oldRow);
623 lit = sortedInsertionIterator(lit, lst.end(), order, item);
624 int newRow = qMax(lit - lst.begin(), 0);
625 lit = lst.insert(lit, item);
626 if (newRow != oldRow) {
627 // we are going to change the persistent indexes, so we need to prepare
628 if (!changed) { // this will only happen once
629 changed = true;
630 emit layoutAboutToBeChanged(); // the selection model needs to know
631 oldPersistentIndexes = persistentIndexList();
632 newPersistentIndexes = oldPersistentIndexes;
633 }
634 for (int j = i + 1; j < count; ++j) {
635 int otherRow = sorting.at(j).second;
636 if (oldRow < otherRow && newRow >= otherRow)
637 --sorting[j].second;
638 else if (oldRow > otherRow && newRow <= otherRow)
639 ++sorting[j].second;
640 }
641 for (int k = 0; k < newPersistentIndexes.count(); ++k) {
642 QModelIndex pi = newPersistentIndexes.at(k);
643 if (pi.parent() != parent)
644 continue;
645 int oldPersistentRow = pi.row();
646 int newPersistentRow = oldPersistentRow;
647 if (oldPersistentRow == oldRow)
648 newPersistentRow = newRow;
649 else if (oldRow < oldPersistentRow && newRow >= oldPersistentRow)
650 newPersistentRow = oldPersistentRow - 1;
651 else if (oldRow > oldPersistentRow && newRow <= oldPersistentRow)
652 newPersistentRow = oldPersistentRow + 1;
653 if (newPersistentRow != oldPersistentRow)
654 newPersistentIndexes[k] = createIndex(newPersistentRow,
655 pi.column(), pi.internalPointer());
656 }
657 }
658 }
659
660 if (changed) {
661 itm->children = lst;
662 changePersistentIndexList(oldPersistentIndexes, newPersistentIndexes);
663 emit layoutChanged();
664 }
665}
666
667/*!
668 \internal
669
670 Returns true if the value of the \a left item is
671 less than the value of the \a right item.
672
673 Used by the sorting functions.
674*/
675
676bool QTreeModel::itemLessThan(const QPair<QTreeWidgetItem*,int> &left,
677 const QPair<QTreeWidgetItem*,int> &right)
678{
679 return *(left.first) < *(right.first);
680}
681
682/*!
683 \internal
684
685 Returns true if the value of the \a left item is
686 greater than the value of the \a right item.
687
688 Used by the sorting functions.
689*/
690
691bool QTreeModel::itemGreaterThan(const QPair<QTreeWidgetItem*,int> &left,
692 const QPair<QTreeWidgetItem*,int> &right)
693{
694 return *(right.first) < *(left.first);
695}
696
697/*!
698 \internal
699*/
700QList<QTreeWidgetItem*>::iterator QTreeModel::sortedInsertionIterator(
701 const QList<QTreeWidgetItem*>::iterator &begin,
702 const QList<QTreeWidgetItem*>::iterator &end,
703 Qt::SortOrder order, QTreeWidgetItem *item)
704{
705 if (order == Qt::AscendingOrder)
706 return qLowerBound(begin, end, item, QTreeModelLessThan());
707 return qLowerBound(begin, end, item, QTreeModelGreaterThan());
708}
709
710QStringList QTreeModel::mimeTypes() const
711{
712 return view()->mimeTypes();
713}
714
715QMimeData *QTreeModel::internalMimeData() const
716{
717 return QAbstractItemModel::mimeData(cachedIndexes);
718}
719
720QMimeData *QTreeModel::mimeData(const QModelIndexList &indexes) const
721{
722 QList<QTreeWidgetItem*> items;
723 for (int i = 0; i < indexes.count(); ++i) {
724 if (indexes.at(i).column() == 0) // only one item per row
725 items << item(indexes.at(i));
726 }
727
728 // cachedIndexes is a little hack to avoid copying from QModelIndexList to
729 // QList<QTreeWidgetItem*> and back again in the view
730 cachedIndexes = indexes;
731 QMimeData *mimeData = view()->mimeData(items);
732 cachedIndexes.clear();
733 return mimeData;
734}
735
736bool QTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
737 int row, int column, const QModelIndex &parent)
738{
739 if (row == -1 && column == -1)
740 row = rowCount(parent); // append
741 return view()->dropMimeData(item(parent), row, data, action);
742}
743
744Qt::DropActions QTreeModel::supportedDropActions() const
745{
746 return view()->supportedDropActions();
747}
748
749void QTreeModel::itemChanged(QTreeWidgetItem *item)
750{
751 SkipSorting skipSorting(this); //this is kind of wrong, but not doing this would kill performence
752 QModelIndex left = index(item, 0);
753 QModelIndex right = index(item, item->columnCount() - 1);
754 emit dataChanged(left, right);
755}
756
757bool QTreeModel::isChanging() const
758{
759 Q_D(const QTreeModel);
760 return !d->changes.isEmpty();
761}
762
763/*!
764 \internal
765 Emits the dataChanged() signal for the given \a item.
766 if column is -1 then all columns have changed
767*/
768
769void QTreeModel::emitDataChanged(QTreeWidgetItem *item, int column)
770{
771 if (signalsBlocked())
772 return;
773
774 if (headerItem == item && column < item->columnCount()) {
775 if (column == -1)
776 emit headerDataChanged(Qt::Horizontal, 0, columnCount() - 1);
777 else
778 emit headerDataChanged(Qt::Horizontal, column, column);
779 return;
780 }
781
782 SkipSorting skipSorting(this); //This is a little bit wrong, but not doing it would kill performence
783
784 QModelIndex bottomRight, topLeft;
785 if (column == -1) {
786 topLeft = index(item, 0);
787 bottomRight = createIndex(topLeft.row(), columnCount() - 1, item);
788 } else {
789 topLeft = index(item, column);
790 bottomRight = topLeft;
791 }
792 emit dataChanged(topLeft, bottomRight);
793}
794
795void QTreeModel::beginInsertItems(QTreeWidgetItem *parent, int row, int count)
796{
797 QModelIndex par = index(parent, 0);
798 beginInsertRows(par, row, row + count - 1);
799}
800
801void QTreeModel::endInsertItems()
802{
803 endInsertRows();
804}
805
806void QTreeModel::beginRemoveItems(QTreeWidgetItem *parent, int row, int count)
807{
808 Q_ASSERT(row >= 0);
809 Q_ASSERT(count > 0);
810 beginRemoveRows(index(parent, 0), row, row + count - 1);
811 if (!parent)
812 parent = rootItem;
813 // now update the iterators
814 for (int i = 0; i < iterators.count(); ++i) {
815 for (int j = 0; j < count; j++) {
816 QTreeWidgetItem *c = parent->child(row + j);
817 iterators[i]->d_func()->ensureValidIterator(c);
818 }
819 }
820}
821
822void QTreeModel::endRemoveItems()
823{
824 endRemoveRows();
825}
826
827void QTreeModel::sortItems(QList<QTreeWidgetItem*> *items, int column, Qt::SortOrder order)
828{
829 // see QTreeViewItem::operator<
830 Q_UNUSED(column);
831 if (isChanging())
832 return;
833
834 // store the original order of indexes
835 QVector< QPair<QTreeWidgetItem*,int> > sorting(items->count());
836 for (int i = 0; i < sorting.count(); ++i) {
837 sorting[i].first = items->at(i);
838 sorting[i].second = i;
839 }
840
841 // do the sorting
842 LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
843 qStableSort(sorting.begin(), sorting.end(), compare);
844
845 QModelIndexList fromList;
846 QModelIndexList toList;
847 int colCount = columnCount();
848 for (int r = 0; r < sorting.count(); ++r) {
849 int oldRow = sorting.at(r).second;
850 if (oldRow == r)
851 continue;
852 QTreeWidgetItem *item = sorting.at(r).first;
853 items->replace(r, item);
854 for (int c = 0; c < colCount; ++c) {
855 QModelIndex from = createIndex(oldRow, c, item);
856 if (static_cast<QAbstractItemModelPrivate *>(d_ptr)->persistent.indexes.contains(from)) {
857 QModelIndex to = createIndex(r, c, item);
858 fromList << from;
859 toList << to;
860 }
861 }
862 }
863 changePersistentIndexList(fromList, toList);
864}
865
866void QTreeModel::timerEvent(QTimerEvent *ev)
867{
868 if (ev->timerId() == sortPendingTimer.timerId()) {
869 executePendingSort();
870 } else {
871 QAbstractItemModel::timerEvent(ev);
872 }
873}
874
875/*!
876 \class QTreeWidgetItem
877
878 \brief The QTreeWidgetItem class provides an item for use with the
879 QTreeWidget convenience class.
880
881 \ingroup model-view
882
883 Tree widget items are used to hold rows of information for tree widgets.
884 Rows usually contain several columns of data, each of which can contain
885 a text label and an icon.
886
887 The QTreeWidgetItem class is a convenience class that replaces the
888 QListViewItem class in Qt 3. It provides an item for use with
889 the QTreeWidget class.
890
891 Items are usually constructed with a parent that is either a QTreeWidget
892 (for top-level items) or a QTreeWidgetItem (for items on lower levels of
893 the tree). For example, the following code constructs a top-level item
894 to represent cities of the world, and adds a entry for Oslo as a child
895 item:
896
897 \snippet doc/src/snippets/qtreewidget-using/mainwindow.cpp 3
898
899 Items can be added in a particular order by specifying the item they
900 follow when they are constructed:
901
902 \snippet doc/src/snippets/qtreewidget-using/mainwindow.cpp 5
903
904 Each column in an item can have its own background brush which is set with
905 the setBackground() function. The current background brush can be
906 found with background().
907 The text label for each column can be rendered with its own font and brush.
908 These are specified with the setFont() and setForeground() functions,
909 and read with font() and foreground().
910
911 The main difference between top-level items and those in lower levels of
912 the tree is that a top-level item has no parent(). This information
913 can be used to tell the difference between items, and is useful to know
914 when inserting and removing items from the tree.
915 Children of an item can be removed with takeChild() and inserted at a
916 given index in the list of children with the insertChild() function.
917
918 By default, items are enabled, selectable, checkable, and can be the source
919 of a drag and drop operation.
920 Each item's flags can be changed by calling setFlags() with the appropriate
921 value (see \l{Qt::ItemFlags}). Checkable items can be checked and unchecked
922 with the setCheckState() function. The corresponding checkState() function
923 indicates whether the item is currently checked.
924
925 \section1 Subclassing
926
927 When subclassing QTreeWidgetItem to provide custom items, it is possible to
928 define new types for them so that they can be distinguished from standard
929 items. The constructors for subclasses that require this feature need to
930 call the base class constructor with a new type value equal to or greater
931 than \l UserType.
932
933 \sa QTreeWidget, QTreeWidgetItemIterator, {Model/View Programming},
934 QListWidgetItem, QTableWidgetItem
935*/
936
937/*!
938 \enum QTreeWidgetItem::ItemType
939
940 This enum describes the types that are used to describe tree widget items.
941
942 \value Type The default type for tree widget items.
943 \value UserType The minimum value for custom types. Values below UserType are
944 reserved by Qt.
945
946 You can define new user types in QTreeWidgetItem subclasses to ensure that
947 custom items are treated specially; for example, when items are sorted.
948
949 \sa type()
950*/
951
952/*!
953 \fn int QTreeWidgetItem::type() const
954
955 Returns the type passed to the QTreeWidgetItem constructor.
956*/
957
958/*!
959 \fn void QTreeWidgetItem::sortChildren(int column, Qt::SortOrder order)
960 \since 4.2
961
962 Sorts the children of the item using the given \a order,
963 by the values in the given \a column.
964
965 \note This function does nothing if the item is not associated with a
966 QTreeWidget.
967*/
968
969/*!
970 \fn QTreeWidget *QTreeWidgetItem::treeWidget() const
971
972 Returns the tree widget that contains the item.
973*/
974
975/*!
976 \fn void QTreeWidgetItem::setSelected(bool select)
977 \since 4.2
978
979 Sets the selected state of the item to \a select.
980
981 \sa isSelected()
982
983*/
984
985/*!
986 \fn bool QTreeWidgetItem::isSelected() const
987 \since 4.2
988
989 Returns true if the item is selected, otherwise returns false.
990
991 \sa setSelected()
992*/
993
994/*!
995 \fn void QTreeWidgetItem::setHidden(bool hide)
996 \since 4.2
997
998 Hides the item if \a hide is true, otherwise shows the item.
999
1000 \sa isHidden()
1001*/
1002
1003/*!
1004 \fn bool QTreeWidgetItem::isHidden() const
1005 \since 4.2
1006
1007 Returns true if the item is hidden, otherwise returns false.
1008
1009 \sa setHidden()
1010*/
1011
1012/*!
1013 \fn void QTreeWidgetItem::setExpanded(bool expand)
1014 \since 4.2
1015
1016 Expands the item if \a expand is true, otherwise collapses the item.
1017 \warning The QTreeWidgetItem must be added to the QTreeWidget before calling this function.
1018
1019 \sa isExpanded()
1020*/
1021
1022/*!
1023 \fn bool QTreeWidgetItem::isExpanded() const
1024 \since 4.2
1025
1026 Returns true if the item is expanded, otherwise returns false.
1027
1028 \sa setExpanded()
1029*/
1030
1031/*!
1032 \fn void QTreeWidgetItem::setFirstColumnSpanned(bool span)
1033 \since 4.3
1034
1035 Sets the first section to span all columns if \a span is true;
1036 otherwise all item sections are shown.
1037
1038 \sa isFirstColumnSpanned()
1039*/
1040
1041/*!
1042 \fn bool QTreeWidgetItem::isFirstColumnSpanned() const
1043 \since 4.3
1044
1045 Returns true if the item is spanning all the columns in a row; otherwise returns false.
1046
1047 \sa setFirstColumnSpanned()
1048*/
1049
1050/*!
1051 \fn QString QTreeWidgetItem::text(int column) const
1052
1053 Returns the text in the specified \a column.
1054
1055 \sa setText()
1056*/
1057
1058/*!
1059 \fn void QTreeWidgetItem::setText(int column, const QString &text)
1060
1061 Sets the text to be displayed in the given \a column to the given \a text.
1062
1063 \sa text() setFont() setForeground()
1064*/
1065
1066/*!
1067 \fn QIcon QTreeWidgetItem::icon(int column) const
1068
1069 Returns the icon that is displayed in the specified \a column.
1070
1071 \sa setIcon(), {QAbstractItemView::iconSize}{iconSize}
1072*/
1073
1074/*!
1075 \fn void QTreeWidgetItem::setIcon(int column, const QIcon &icon)
1076
1077 Sets the icon to be displayed in the given \a column to \a icon.
1078
1079 \sa icon(), setText(), {QAbstractItemView::iconSize}{iconSize}
1080*/
1081
1082/*!
1083 \fn QString QTreeWidgetItem::statusTip(int column) const
1084
1085 Returns the status tip for the contents of the given \a column.
1086
1087 \sa setStatusTip()
1088*/
1089
1090/*!
1091 \fn void QTreeWidgetItem::setStatusTip(int column, const QString &statusTip)
1092
1093 Sets the status tip for the given \a column to the given \a statusTip.
1094 QTreeWidget mouse tracking needs to be enabled for this feature to work.
1095
1096 \sa statusTip() setToolTip() setWhatsThis()
1097*/
1098
1099/*!
1100 \fn QString QTreeWidgetItem::toolTip(int column) const
1101
1102 Returns the tool tip for the given \a column.
1103
1104 \sa setToolTip()
1105*/
1106
1107/*!
1108 \fn void QTreeWidgetItem::setToolTip(int column, const QString &toolTip)
1109
1110 Sets the tooltip for the given \a column to \a toolTip.
1111
1112 \sa toolTip() setStatusTip() setWhatsThis()
1113*/
1114
1115/*!
1116 \fn QString QTreeWidgetItem::whatsThis(int column) const
1117
1118 Returns the "What's This?" help for the contents of the given \a column.
1119
1120 \sa setWhatsThis()
1121*/
1122
1123/*!
1124 \fn void QTreeWidgetItem::setWhatsThis(int column, const QString &whatsThis)
1125
1126 Sets the "What's This?" help for the given \a column to \a whatsThis.
1127
1128 \sa whatsThis() setStatusTip() setToolTip()
1129*/
1130
1131/*!
1132 \fn QFont QTreeWidgetItem::font(int column) const
1133
1134 Returns the font used to render the text in the specified \a column.
1135
1136 \sa setFont()
1137*/
1138
1139/*!
1140 \fn void QTreeWidgetItem::setFont(int column, const QFont &font)
1141
1142 Sets the font used to display the text in the given \a column to the given
1143 \a font.
1144
1145 \sa font() setText() setForeground()
1146*/
1147
1148/*!
1149 \fn QColor QTreeWidgetItem::backgroundColor(int column) const
1150 \obsolete
1151
1152 This function is deprecated. Use background() instead.
1153*/
1154
1155/*!
1156 \fn void QTreeWidgetItem::setBackgroundColor(int column, const QColor &color)
1157 \obsolete
1158
1159 This function is deprecated. Use setBackground() instead.
1160*/
1161
1162/*!
1163 \fn QBrush QTreeWidgetItem::background(int column) const
1164 \since 4.2
1165
1166 Returns the brush used to render the background of the specified \a column.
1167
1168 \sa foreground()
1169*/
1170
1171/*!
1172 \fn void QTreeWidgetItem::setBackground(int column, const QBrush &brush)
1173 \since 4.2
1174
1175 Sets the background brush of the label in the given \a column to the
1176 specified \a brush.
1177
1178 \sa setForeground()
1179*/
1180
1181/*!
1182 \fn QColor QTreeWidgetItem::textColor(int column) const
1183 \obsolete
1184
1185 This function is deprecated. Use foreground() instead.
1186*/
1187
1188/*!
1189 \fn void QTreeWidgetItem::setTextColor(int column, const QColor &color)
1190 \obsolete
1191
1192 This function is deprecated. Use setForeground() instead.
1193*/
1194
1195/*!
1196 \fn QBrush QTreeWidgetItem::foreground(int column) const
1197 \since 4.2
1198
1199 Returns the brush used to render the foreground (e.g. text) of the
1200 specified \a column.
1201
1202 \sa background()
1203*/
1204
1205/*!
1206 \fn void QTreeWidgetItem::setForeground(int column, const QBrush &brush)
1207 \since 4.2
1208
1209 Sets the foreground brush of the label in the given \a column to the
1210 specified \a brush.
1211
1212 \sa setBackground()
1213*/
1214
1215/*!
1216 \fn Qt::CheckState QTreeWidgetItem::checkState(int column) const
1217
1218 Returns the check state of the label in the given \a column.
1219
1220 \sa Qt::CheckState
1221*/
1222
1223/*!
1224 \fn void QTreeWidgetItem::setCheckState(int column, Qt::CheckState state)
1225
1226 Sets the item in the given \a column check state to be \a state.
1227
1228 \sa checkState()
1229*/
1230
1231/*!
1232 \fn QSize QTreeWidgetItem::sizeHint(int column) const
1233 \since 4.1
1234
1235 Returns the size hint set for the tree item in the given
1236 \a column (see \l{QSize}).
1237*/
1238
1239/*!
1240 \fn void QTreeWidgetItem::setSizeHint(int column, const QSize &size)
1241 \since 4.1
1242
1243 Sets the size hint for the tree item in the given \a column to be \a size.
1244 If no size hint is set, the item delegate will compute the size hint based
1245 on the item data.
1246*/
1247
1248/*!
1249 \fn QTreeWidgetItem *QTreeWidgetItem::parent() const
1250
1251 Returns the item's parent.
1252
1253 \sa child()
1254*/
1255
1256/*!
1257 \fn QTreeWidgetItem *QTreeWidgetItem::child(int index) const
1258
1259 Returns the item at the given \a index in the list of the item's children.
1260
1261 \sa parent()
1262*/
1263
1264/*!
1265 \fn int QTreeWidgetItem::childCount() const
1266
1267 Returns the number of child items.
1268*/
1269
1270/*!
1271 \fn int QTreeWidgetItem::columnCount() const
1272
1273 Returns the number of columns in the item.
1274*/
1275
1276/*!
1277 \fn int QTreeWidgetItem::textAlignment(int column) const
1278
1279 Returns the text alignment for the label in the given \a column
1280 (see \l{Qt::AlignmentFlag}).
1281*/
1282
1283/*!
1284 \fn void QTreeWidgetItem::setTextAlignment(int column, int alignment)
1285
1286 Sets the text alignment for the label in the given \a column to
1287 the \a alignment specified (see \l{Qt::AlignmentFlag}).
1288*/
1289
1290/*!
1291 \fn int QTreeWidgetItem::indexOfChild(QTreeWidgetItem *child) const
1292
1293 Returns the index of the given \a child in the item's list of children.
1294*/
1295
1296/*!
1297 Constructs a tree widget item of the specified \a type. The item
1298 must be inserted into a tree widget.
1299
1300 \sa type()
1301*/
1302QTreeWidgetItem::QTreeWidgetItem(int type)
1303 : rtti(type), view(0), d(new QTreeWidgetItemPrivate(this)), par(0),
1304 itemFlags(Qt::ItemIsSelectable
1305 |Qt::ItemIsUserCheckable
1306 |Qt::ItemIsEnabled
1307 |Qt::ItemIsDragEnabled
1308 |Qt::ItemIsDropEnabled)
1309{
1310}
1311
1312
1313/*!
1314 Constructs a tree widget item of the specified \a type. The item
1315 must be inserted into a tree widget.
1316 The given list of \a strings will be set as the item text for each
1317 column in the item.
1318
1319 \sa type()
1320*/
1321QTreeWidgetItem::QTreeWidgetItem(const QStringList &strings, int type)
1322 : rtti(type), view(0), d(new QTreeWidgetItemPrivate(this)), par(0),
1323 itemFlags(Qt::ItemIsSelectable
1324 |Qt::ItemIsUserCheckable
1325 |Qt::ItemIsEnabled
1326 |Qt::ItemIsDragEnabled
1327 |Qt::ItemIsDropEnabled)
1328{
1329 for (int i = 0; i < strings.count(); ++i)
1330 setText(i, strings.at(i));
1331}
1332
1333/*!
1334 \fn QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *parent, int type)
1335
1336 Constructs a tree widget item of the specified \a type and appends it
1337 to the items in the given \a parent.
1338
1339 \sa type()
1340*/
1341
1342QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *view, int type)
1343 : rtti(type), view(0), d(new QTreeWidgetItemPrivate(this)), par(0),
1344 itemFlags(Qt::ItemIsSelectable
1345 |Qt::ItemIsUserCheckable
1346 |Qt::ItemIsEnabled
1347 |Qt::ItemIsDragEnabled
1348 |Qt::ItemIsDropEnabled)
1349{
1350 if (view && view->model()) {
1351 QTreeModel *model = qobject_cast<QTreeModel*>(view->model());
1352 model->rootItem->addChild(this);
1353 values.reserve(model->headerItem->columnCount());
1354 }
1355}
1356
1357/*!
1358 \fn QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *parent, const QStringList &strings, int type)
1359
1360 Constructs a tree widget item of the specified \a type and appends it
1361 to the items in the given \a parent. The given list of \a strings will be set as
1362 the item text for each column in the item.
1363
1364 \sa type()
1365*/
1366
1367QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *view, const QStringList &strings, int type)
1368 : rtti(type), view(0), d(new QTreeWidgetItemPrivate(this)), par(0),
1369 itemFlags(Qt::ItemIsSelectable
1370 |Qt::ItemIsUserCheckable
1371 |Qt::ItemIsEnabled
1372 |Qt::ItemIsDragEnabled
1373 |Qt::ItemIsDropEnabled)
1374{
1375 for (int i = 0; i < strings.count(); ++i)
1376 setText(i, strings.at(i));
1377 if (view && view->model()) {
1378 QTreeModel *model = qobject_cast<QTreeModel*>(view->model());
1379 model->rootItem->addChild(this);
1380 values.reserve(model->headerItem->columnCount());
1381 }
1382}
1383
1384/*!
1385 \fn QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *parent, QTreeWidgetItem *preceding, int type)
1386
1387 Constructs a tree widget item of the specified \a type and inserts it into
1388 the given \a parent after the \a preceding item.
1389
1390 \sa type()
1391*/
1392QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *view, QTreeWidgetItem *after, int type)
1393 : rtti(type), view(0), d(new QTreeWidgetItemPrivate(this)), par(0),
1394 itemFlags(Qt::ItemIsSelectable
1395 |Qt::ItemIsUserCheckable
1396 |Qt::ItemIsEnabled
1397 |Qt::ItemIsDragEnabled
1398 |Qt::ItemIsDropEnabled)
1399{
1400 if (view) {
1401 QTreeModel *model = qobject_cast<QTreeModel*>(view->model());
1402 if (model) {
1403 int i = model->rootItem->children.indexOf(after) + 1;
1404 model->rootItem->insertChild(i, this);
1405 values.reserve(model->headerItem->columnCount());
1406 }
1407 }
1408}
1409
1410/*!
1411 Constructs a tree widget item and append it to the given \a parent.
1412
1413 \sa type()
1414*/
1415QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, int type)
1416 : rtti(type), view(0), d(new QTreeWidgetItemPrivate(this)), par(0),
1417 itemFlags(Qt::ItemIsSelectable
1418 |Qt::ItemIsUserCheckable
1419 |Qt::ItemIsEnabled
1420 |Qt::ItemIsDragEnabled
1421 |Qt::ItemIsDropEnabled)
1422{
1423 if (parent)
1424 parent->addChild(this);
1425}
1426
1427/*!
1428 Constructs a tree widget item and append it to the given \a parent.
1429 The given list of \a strings will be set as the item text for each column in the item.
1430
1431 \sa type()
1432*/
1433QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, const QStringList &strings, int type)
1434 : rtti(type), view(0), d(new QTreeWidgetItemPrivate(this)), par(0),
1435 itemFlags(Qt::ItemIsSelectable
1436 |Qt::ItemIsUserCheckable
1437 |Qt::ItemIsEnabled
1438 |Qt::ItemIsDragEnabled
1439 |Qt::ItemIsDropEnabled)
1440{
1441 for (int i = 0; i < strings.count(); ++i)
1442 setText(i, strings.at(i));
1443 if (parent)
1444 parent->addChild(this);
1445}
1446
1447/*!
1448 \fn QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, QTreeWidgetItem *preceding, int type)
1449
1450 Constructs a tree widget item of the specified \a type that is inserted
1451 into the \a parent after the \a preceding child item.
1452
1453 \sa type()
1454*/
1455QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, QTreeWidgetItem *after, int type)
1456 : rtti(type), view(0), d(new QTreeWidgetItemPrivate(this)), par(0),
1457 itemFlags(Qt::ItemIsSelectable
1458 |Qt::ItemIsUserCheckable
1459 |Qt::ItemIsEnabled
1460 |Qt::ItemIsDragEnabled
1461 |Qt::ItemIsDropEnabled)
1462{
1463 if (parent) {
1464 int i = parent->children.indexOf(after) + 1;
1465 parent->insertChild(i, this);
1466 }
1467}
1468
1469/*!
1470 Destroys this tree widget item.
1471*/
1472
1473QTreeWidgetItem::~QTreeWidgetItem()
1474{
1475 QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0);
1476 bool wasSkipSort = false;
1477 if (model) {
1478 wasSkipSort = model->skipPendingSort;
1479 model->skipPendingSort = true;
1480 }
1481 if (par) {
1482 int i = par->children.indexOf(this);
1483 if (i >= 0) {
1484 if (model) model->beginRemoveItems(par, i, 1);
1485 // users _could_ do changes when connected to rowsAboutToBeRemoved,
1486 // so we check again to make sure 'i' is valid
1487 if (!par->children.isEmpty() && par->children.at(i) == this)
1488 par->children.takeAt(i);
1489 if (model) model->endRemoveItems();
1490 }
1491 } else if (model) {
1492 if (this == model->headerItem) {
1493 model->headerItem = 0;
1494 } else {
1495 int i = model->rootItem->children.indexOf(this);
1496 if (i >= 0) {
1497 model->beginRemoveItems(0, i, 1);
1498 // users _could_ do changes when connected to rowsAboutToBeRemoved,
1499 // so we check again to make sure 'i' is valid
1500 if (!model->rootItem->children.isEmpty() && model->rootItem->children.at(i) == this)
1501 model->rootItem->children.takeAt(i);
1502 model->endRemoveItems();
1503 }
1504 }
1505 }
1506 // at this point the persistent indexes for the children should also be invalidated
1507 // since we invalidated the parent
1508 for (int i = 0; i < children.count(); ++i) {
1509 QTreeWidgetItem *child = children.at(i);
1510 // make sure the child does not try to remove itself from our children list
1511 child->par = 0;
1512 // make sure the child does not try to remove itself from the top level list
1513 child->view = 0;
1514 delete child;
1515 }
1516
1517 children.clear();
1518 delete d;
1519 if (model) {
1520 model->skipPendingSort = wasSkipSort;
1521 }
1522}
1523
1524/*!
1525 Creates a deep copy of the item and of its children.
1526*/
1527QTreeWidgetItem *QTreeWidgetItem::clone() const
1528{
1529 QTreeWidgetItem *copy = 0;
1530
1531 QStack<const QTreeWidgetItem*> stack;
1532 QStack<QTreeWidgetItem*> parentStack;
1533 stack.push(this);
1534 parentStack.push(0);
1535
1536 QTreeWidgetItem *root = 0;
1537 const QTreeWidgetItem *item = 0;
1538 QTreeWidgetItem *parent = 0;
1539 while (!stack.isEmpty()) {
1540 // get current item, and copied parent
1541 item = stack.pop();
1542 parent = parentStack.pop();
1543
1544 // copy item
1545 copy = new QTreeWidgetItem(*item);
1546 if (!root)
1547 root = copy;
1548
1549 // set parent and add to parents children list
1550 if (parent) {
1551 copy->par = parent;
1552 parent->children.insert(0, copy);
1553 }
1554
1555 for (int i = 0; i < item->childCount(); ++i) {
1556 stack.push(item->child(i));
1557 parentStack.push(copy);
1558 }
1559 }
1560 return root;
1561}
1562
1563/*!
1564 Sets the item indicator \a policy. This policy decides when the
1565 tree branch expand/collapse indicator is shown.
1566 The default value is ShowForChildren.
1567
1568 \sa childIndicatorPolicy()
1569*/
1570void QTreeWidgetItem::setChildIndicatorPolicy(QTreeWidgetItem::ChildIndicatorPolicy policy)
1571{
1572 if (d->policy == policy)
1573 return;
1574 d->policy = policy;
1575
1576 if (!view)
1577 return;
1578
1579 view->viewport()->update( view->d_func()->itemDecorationRect(view->d_func()->index(this)));
1580}
1581
1582/*!
1583 Returns the item indicator policy. This policy decides when the
1584 tree branch expand/collapse indicator is shown.
1585
1586 \sa setChildIndicatorPolicy()
1587*/
1588QTreeWidgetItem::ChildIndicatorPolicy QTreeWidgetItem::childIndicatorPolicy() const
1589{
1590 return d->policy;
1591}
1592
1593/*!
1594 \fn void QTreeWidgetItem::setFlags(Qt::ItemFlags flags)
1595
1596 Sets the flags for the item to the given \a flags. These determine whether
1597 the item can be selected or modified. This is often used to disable an item.
1598
1599 \sa flags()
1600*/
1601void QTreeWidgetItem::setFlags(Qt::ItemFlags flags)
1602{
1603 const bool enable = (flags & Qt::ItemIsEnabled);
1604 const bool changedState = bool(itemFlags & Qt::ItemIsEnabled) != enable;
1605 const bool changedExplicit = d->disabled != !enable;
1606
1607 d->disabled = !enable;
1608
1609 if (enable && par && !(par->itemFlags & Qt::ItemIsEnabled)) // inherit from parent
1610 itemFlags = flags & ~Qt::ItemIsEnabled;
1611 else // this item is explicitly disabled or has no parent
1612 itemFlags = flags;
1613
1614 if (changedState && changedExplicit) { // if the propagate the change to the children
1615 QStack<QTreeWidgetItem*> parents;
1616 parents.push(this);
1617 while (!parents.isEmpty()) {
1618 QTreeWidgetItem *parent = parents.pop();
1619 for (int i = 0; i < parent->children.count(); ++i) {
1620 QTreeWidgetItem *child = parent->children.at(i);
1621 if (!child->d->disabled) { // if not explicitly disabled
1622 parents.push(child);
1623 if (enable)
1624 child->itemFlags = child->itemFlags | Qt::ItemIsEnabled;
1625 else
1626 child->itemFlags = child->itemFlags & ~Qt::ItemIsEnabled;
1627 child->itemChanged(); // ### we may want to optimize this
1628 }
1629 }
1630 }
1631 }
1632 itemChanged();
1633}
1634
1635void QTreeWidgetItemPrivate::propagateDisabled(QTreeWidgetItem *item)
1636{
1637 Q_ASSERT(item);
1638 const bool enable = item->par ? (item->par->itemFlags.testFlag(Qt::ItemIsEnabled)) : true;
1639
1640 QStack<QTreeWidgetItem*> parents;
1641 parents.push(item);
1642 while (!parents.isEmpty()) {
1643 QTreeWidgetItem *parent = parents.pop();
1644 if (!parent->d->disabled) { // if not explicitly disabled
1645 Qt::ItemFlags oldFlags = parent->itemFlags;
1646 if (enable)
1647 parent->itemFlags = parent->itemFlags | Qt::ItemIsEnabled;
1648 else
1649 parent->itemFlags = parent->itemFlags & ~Qt::ItemIsEnabled;
1650 if (parent->itemFlags != oldFlags)
1651 parent->itemChanged();
1652 }
1653
1654 for (int i = 0; i < parent->children.count(); ++i) {
1655 QTreeWidgetItem *child = parent->children.at(i);
1656 parents.push(child);
1657 }
1658 }
1659}
1660/*!
1661 \fn Qt::ItemFlags QTreeWidgetItem::flags() const
1662
1663 Returns the flags used to describe the item. These determine whether
1664 the item can be checked, edited, and selected.
1665
1666 The default value for flags is
1667 Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled.
1668 If the item was constructed with a parent, flags will in addition contain Qt::ItemIsDropEnabled.
1669
1670 \sa setFlags()
1671*/
1672Qt::ItemFlags QTreeWidgetItem::flags() const
1673{
1674 return itemFlags;
1675}
1676
1677/*!
1678 Sets the value for the item's \a column and \a role to the given
1679 \a value.
1680
1681 The \a role describes the type of data specified by \a value, and is defined by
1682 the Qt::ItemDataRole enum.
1683*/
1684void QTreeWidgetItem::setData(int column, int role, const QVariant &value)
1685{
1686 if (column < 0)
1687 return;
1688
1689 QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0);
1690 switch (role) {
1691 case Qt::EditRole:
1692 case Qt::DisplayRole: {
1693 if (values.count() <= column) {
1694 if (model && this == model->headerItem)
1695 model->setColumnCount(column + 1);
1696 else
1697 values.resize(column + 1);
1698 }
1699 if (d->display.count() <= column) {
1700 for (int i = d->display.count() - 1; i < column - 1; ++i)
1701 d->display.append(QVariant());
1702 d->display.append(value);
1703 } else if (d->display[column] != value) {
1704 d->display[column] = value;
1705 } else {
1706 return; // value is unchanged
1707 }
1708 } break;
1709 case Qt::CheckStateRole:
1710 if (itemFlags & Qt::ItemIsTristate) {
1711 for (int i = 0; i < children.count(); ++i) {
1712 QTreeWidgetItem *child = children.at(i);
1713 if (child->data(column, role).isValid()) {// has a CheckState
1714 Qt::ItemFlags f = itemFlags; // a little hack to avoid multiple dataChanged signals
1715 itemFlags &= ~Qt::ItemIsTristate;
1716 child->setData(column, role, value);
1717 itemFlags = f;
1718 }
1719 }
1720 }
1721 // Don't break, but fall through
1722 default:
1723 if (column < values.count()) {
1724 bool found = false;
1725 QVector<QWidgetItemData> column_values = values.at(column);
1726 for (int i = 0; i < column_values.count(); ++i) {
1727 if (column_values.at(i).role == role) {
1728 if (column_values.at(i).value == value)
1729 return; // value is unchanged
1730 values[column][i].value = value;
1731 found = true;
1732 break;
1733 }
1734 }
1735 if (!found)
1736 values[column].append(QWidgetItemData(role, value));
1737 } else {
1738 if (model && this == model->headerItem)
1739 model->setColumnCount(column + 1);
1740 else
1741 values.resize(column + 1);
1742 values[column].append(QWidgetItemData(role, value));
1743 }
1744 }
1745
1746 if (model) {
1747 model->emitDataChanged(this, column);
1748 if (role == Qt::CheckStateRole) {
1749 QTreeWidgetItem *p;
1750 for (p = par; p && (p->itemFlags & Qt::ItemIsTristate); p = p->par)
1751 model->emitDataChanged(p, column);
1752 }
1753 }
1754}
1755
1756/*!
1757 Returns the value for the item's \a column and \a role.
1758*/
1759QVariant QTreeWidgetItem::data(int column, int role) const
1760{
1761 switch (role) {
1762 case Qt::EditRole:
1763 case Qt::DisplayRole:
1764 if (column >= 0 && column < d->display.count())
1765 return d->display.at(column);
1766 break;
1767 case Qt::CheckStateRole:
1768 // special case for check state in tristate
1769 if (children.count() && (itemFlags & Qt::ItemIsTristate))
1770 return childrenCheckState(column);
1771 default:
1772 if (column >= 0 && column < values.size()) {
1773 const QVector<QWidgetItemData> &column_values = values.at(column);
1774 for (int i = 0; i < column_values.count(); ++i)
1775 if (column_values.at(i).role == role)
1776 return column_values.at(i).value;
1777 }
1778 }
1779 return QVariant();
1780}
1781
1782/*!
1783 Returns true if the text in the item is less than the text in the
1784 \a other item, otherwise returns false.
1785*/
1786
1787bool QTreeWidgetItem::operator<(const QTreeWidgetItem &other) const
1788{
1789 int column = view ? view->sortColumn() : 0;
1790 return text(column) < other.text(column);
1791}
1792
1793#ifndef QT_NO_DATASTREAM
1794
1795/*!
1796 Reads the item from stream \a in. This only reads data into a single item.
1797
1798 \sa write()
1799*/
1800void QTreeWidgetItem::read(QDataStream &in)
1801{
1802 // convert from streams written before we introduced display (4.2.0)
1803 if (in.version() < QDataStream::Qt_4_2) {
1804 d->display.clear();
1805 in >> values;
1806 // move the display value over to the display string list
1807 for (int column = 0; column < values.count(); ++column) {
1808 d->display << QVariant();
1809 for (int i = 0; i < values.at(column).count(); ++i) {
1810 if (values.at(column).at(i).role == Qt::DisplayRole) {
1811 d->display[column] = values.at(column).at(i).value;
1812 values[column].remove(i--);
1813 }
1814 }
1815 }
1816 } else {
1817 in >> values >> d->display;
1818 }
1819}
1820
1821/*!
1822 Writes the item to stream \a out. This only writes data from one single item.
1823
1824 \sa read()
1825*/
1826void QTreeWidgetItem::write(QDataStream &out) const
1827{
1828 out << values << d->display;
1829}
1830
1831/*!
1832 \since 4.1
1833
1834 Constructs a copy of \a other. Note that type() and treeWidget()
1835 are not copied.
1836
1837 This function is useful when reimplementing clone().
1838
1839 \sa data(), flags()
1840*/
1841QTreeWidgetItem::QTreeWidgetItem(const QTreeWidgetItem &other)
1842 : rtti(Type), values(other.values), view(0),
1843 d(new QTreeWidgetItemPrivate(this)), par(0),
1844 itemFlags(other.itemFlags)
1845{
1846 d->display = other.d->display;
1847}
1848
1849/*!
1850 Assigns \a other's data and flags to this item. Note that type()
1851 and treeWidget() are not copied.
1852
1853 This function is useful when reimplementing clone().
1854
1855 \sa data(), flags()
1856*/
1857QTreeWidgetItem &QTreeWidgetItem::operator=(const QTreeWidgetItem &other)
1858{
1859 values = other.values;
1860 d->display = other.d->display;
1861 d->policy = other.d->policy;
1862 itemFlags = other.itemFlags;
1863 return *this;
1864}
1865
1866#endif // QT_NO_DATASTREAM
1867
1868/*!
1869 Appends the \a child item to the list of children.
1870
1871 \sa insertChild() takeChild()
1872*/
1873void QTreeWidgetItem::addChild(QTreeWidgetItem *child)
1874{
1875 if (child) {
1876 insertChild(children.count(), child);
1877 child->d->rowGuess = children.count() - 1;
1878 }
1879}
1880
1881/*!
1882 Inserts the \a child item at \a index in the list of children.
1883
1884 If the child has already been inserted somewhere else it wont be inserted again.
1885*/
1886void QTreeWidgetItem::insertChild(int index, QTreeWidgetItem *child)
1887{
1888 if (index < 0 || index > children.count() || child == 0 || child->view != 0 || child->par != 0)
1889 return;
1890
1891 if (QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0)) {
1892 const bool wasSkipSort = model->skipPendingSort;
1893 model->skipPendingSort = true;
1894 if (model->rootItem == this)
1895 child->par = 0;
1896 else
1897 child->par = this;
1898 if (view->isSortingEnabled()) {
1899 // do a delayed sort instead
1900 if (!model->sortPendingTimer.isActive())
1901 model->sortPendingTimer.start(0, model);
1902 }
1903 model->beginInsertItems(this, index, 1);
1904 int cols = model->columnCount();
1905 QStack<QTreeWidgetItem*> stack;
1906 stack.push(child);
1907 while (!stack.isEmpty()) {
1908 QTreeWidgetItem *i = stack.pop();
1909 i->view = view;
1910 i->values.reserve(cols);
1911 for (int c = 0; c < i->children.count(); ++c)
1912 stack.push(i->children.at(c));
1913 }
1914 children.insert(index, child);
1915 model->endInsertItems();
1916 model->skipPendingSort = wasSkipSort;
1917 } else {
1918 child->par = this;
1919 children.insert(index, child);
1920 }
1921 if (child->par)
1922 d->propagateDisabled(child);
1923}
1924
1925/*!
1926 Removes the given item indicated by \a child.
1927 The removed item will not be deleted.
1928*/
1929void QTreeWidgetItem::removeChild(QTreeWidgetItem *child)
1930{
1931 (void)takeChild(children.indexOf(child));
1932}
1933
1934/*!
1935 Removes the item at \a index and returns it, otherwise return 0.
1936*/
1937QTreeWidgetItem *QTreeWidgetItem::takeChild(int index)
1938{
1939 // we move this outside the check of the index to allow executing
1940 // pending sorts from inline functions, using this function (hack)
1941 QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0);
1942 if (model) {
1943 // This will trigger a layoutChanged signal, thus we might want to optimize
1944 // this function by not emitting the rowsRemoved signal etc to the view.
1945 // On the other hand we also need to make sure that the selectionmodel
1946 // is updated in case we take an item that is selected.
1947 model->skipPendingSort = false;
1948 model->executePendingSort();
1949 }
1950 if (index >= 0 && index < children.count()) {
1951 if (model) model->beginRemoveItems(this, index, 1);
1952 QTreeWidgetItem *item = children.takeAt(index);
1953 item->par = 0;
1954 QStack<QTreeWidgetItem*> stack;
1955 stack.push(item);
1956 while (!stack.isEmpty()) {
1957 QTreeWidgetItem *i = stack.pop();
1958 i->view = 0;
1959 for (int c = 0; c < i->children.count(); ++c)
1960 stack.push(i->children.at(c));
1961 }
1962 d->propagateDisabled(item);
1963 if (model) model->endRemoveRows();
1964 return item;
1965 }
1966 return 0;
1967}
1968
1969/*!
1970 \since 4.1
1971
1972 Appends the given list of \a children to the item.
1973
1974 \sa insertChildren() takeChildren()
1975*/
1976void QTreeWidgetItem::addChildren(const QList<QTreeWidgetItem*> &children)
1977{
1978 insertChildren(this->children.count(), children);
1979}
1980
1981/*!
1982 \since 4.1
1983
1984 Inserts the given list of \a children into the list of the item children at \a index .
1985
1986 Children that have already been inserted somewhere else wont be inserted.
1987*/
1988void QTreeWidgetItem::insertChildren(int index, const QList<QTreeWidgetItem*> &children)
1989{
1990 if (view && view->isSortingEnabled()) {
1991 for (int n = 0; n < children.count(); ++n)
1992 insertChild(index, children.at(n));
1993 return;
1994 }
1995 QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0);
1996 QStack<QTreeWidgetItem*> stack;
1997 QList<QTreeWidgetItem*> itemsToInsert;
1998 for (int n = 0; n < children.count(); ++n) {
1999 QTreeWidgetItem *child = children.at(n);
2000 if (child->view || child->par)
2001 continue;
2002 itemsToInsert.append(child);
2003 if (view && model) {
2004 if (child->childCount() == 0)
2005 child->view = view;
2006 else
2007 stack.push(child);
2008 }
2009 if (model && (model->rootItem == this))
2010 child->par = 0;
2011 else
2012 child->par = this;
2013 }
2014 if (!itemsToInsert.isEmpty()) {
2015 while (!stack.isEmpty()) {
2016 QTreeWidgetItem *i = stack.pop();
2017 i->view = view;
2018 for (int c = 0; c < i->children.count(); ++c)
2019 stack.push(i->children.at(c));
2020 }
2021 if (model) model->beginInsertItems(this, index, itemsToInsert.count());
2022 for (int n = 0; n < itemsToInsert.count(); ++n) {
2023 QTreeWidgetItem *child = itemsToInsert.at(n);
2024 this->children.insert(index + n, child);
2025 if (child->par)
2026 d->propagateDisabled(child);
2027 }
2028 if (model) model->endInsertItems();
2029 }
2030}
2031
2032/*!
2033 \since 4.1
2034
2035 Removes the list of children and returns it, otherwise returns an empty list.
2036*/
2037QList<QTreeWidgetItem*> QTreeWidgetItem::takeChildren()
2038{
2039 QList<QTreeWidgetItem*> removed;
2040 if (children.count() > 0) {
2041 QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0);
2042 if (model) {
2043 // This will trigger a layoutChanged signal, thus we might want to optimize
2044 // this function by not emitting the rowsRemoved signal etc to the view.
2045 // On the other hand we also need to make sure that the selectionmodel
2046 // is updated in case we take an item that is selected.
2047 model->executePendingSort();
2048 }
2049 if (model) model->beginRemoveItems(this, 0, children.count());
2050 for (int n = 0; n < children.count(); ++n) {
2051 QTreeWidgetItem *item = children.at(n);
2052 item->par = 0;
2053 QStack<QTreeWidgetItem*> stack;
2054 stack.push(item);
2055 while (!stack.isEmpty()) {
2056 QTreeWidgetItem *i = stack.pop();
2057 i->view = 0;
2058 for (int c = 0; c < i->children.count(); ++c)
2059 stack.push(i->children.at(c));
2060 }
2061 d->propagateDisabled(item);
2062 }
2063 removed = children;
2064 children.clear(); // detach
2065 if (model) model->endRemoveItems();
2066 }
2067 return removed;
2068}
2069
2070
2071void QTreeWidgetItemPrivate::sortChildren(int column, Qt::SortOrder order, bool climb)
2072{
2073 QTreeModel *model = (q->view ? qobject_cast<QTreeModel*>(q->view->model()) : 0);
2074 model->sortItems(&q->children, column, order);
2075 if (climb) {
2076 QList<QTreeWidgetItem*>::iterator it = q->children.begin();
2077 for (; it != q->children.end(); ++it) {
2078 //here we call the private object's method to avoid emitting
2079 //the layoutAboutToBeChanged and layoutChanged signals
2080 (*it)->d->sortChildren(column, order, climb);
2081 }
2082 }
2083}
2084
2085/*!
2086 \internal
2087
2088 Sorts the children by the value in the given \a column, in the \a order
2089 specified. If \a climb is true, the items below each of the children will
2090 also be sorted.
2091*/
2092void QTreeWidgetItem::sortChildren(int column, Qt::SortOrder order, bool climb)
2093{
2094 QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0);
2095 if (!model)
2096 return;
2097 if (model->isChanging())
2098 return;
2099 int oldSortColumn = view->d_func()->explicitSortColumn;
2100 view->d_func()->explicitSortColumn = column;
2101 emit model->layoutAboutToBeChanged();
2102 d->sortChildren(column, order, climb);
2103 emit model->layoutChanged();
2104 view->d_func()->explicitSortColumn = oldSortColumn;
2105}
2106
2107/*!
2108 \internal
2109
2110 Calculates the checked state of the item based on the checked state
2111 of its children. E.g. if all children checked => this item is also
2112 checked; if some children checked => this item is partially checked;
2113 if no children checked => this item is unchecked.
2114*/
2115QVariant QTreeWidgetItem::childrenCheckState(int column) const
2116{
2117 if (column < 0)
2118 return QVariant();
2119 bool checkedChildren = false;
2120 bool uncheckedChildren = false;
2121 for (int i = 0; i < children.count(); ++i) {
2122 QVariant value = children.at(i)->data(column, Qt::CheckStateRole);
2123 if (!value.isValid())
2124 return QVariant();
2125
2126 switch (static_cast<Qt::CheckState>(value.toInt()))
2127 {
2128 case Qt::Unchecked:
2129 uncheckedChildren = true;
2130 break;
2131 case Qt::Checked:
2132 checkedChildren = true;
2133 break;
2134 case Qt::PartiallyChecked:
2135 default:
2136 return Qt::PartiallyChecked;
2137 }
2138 }
2139
2140 if (uncheckedChildren && checkedChildren)
2141 return Qt::PartiallyChecked;
2142 if (uncheckedChildren)
2143 return Qt::Unchecked;
2144 else if (checkedChildren)
2145 return Qt::Checked;
2146 else
2147 return QVariant(); // value was not defined
2148}
2149
2150/*!
2151 \since 4.5
2152
2153 Causes the model associated with this item to emit a
2154 \l{QAbstractItemModel::dataChanged()}{dataChanged}() signal for this
2155 item.
2156
2157 You normally only need to call this function if you have subclassed
2158 QTreeWidgetItem and reimplemented data() and/or setData().
2159
2160 \sa setData()
2161*/
2162void QTreeWidgetItem::emitDataChanged()
2163{
2164 itemChanged();
2165}
2166
2167/*!
2168 \internal
2169*/
2170void QTreeWidgetItem::itemChanged()
2171{
2172 if (QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0))
2173 model->itemChanged(this);
2174}
2175
2176/*!
2177 \internal
2178*/
2179void QTreeWidgetItem::executePendingSort() const
2180{
2181 if (QTreeModel *model = (view ? qobject_cast<QTreeModel*>(view->model()) : 0))
2182 model->executePendingSort();
2183}
2184
2185
2186#ifndef QT_NO_DATASTREAM
2187/*!
2188 \relates QTreeWidgetItem
2189
2190 Writes the tree widget item \a item to stream \a out.
2191
2192 This operator uses QTreeWidgetItem::write().
2193
2194 \sa {Format of the QDataStream Operators}
2195*/
2196QDataStream &operator<<(QDataStream &out, const QTreeWidgetItem &item)
2197{
2198 item.write(out);
2199 return out;
2200}
2201
2202/*!
2203 \relates QTreeWidgetItem
2204
2205 Reads a tree widget item from stream \a in into \a item.
2206
2207 This operator uses QTreeWidgetItem::read().
2208
2209 \sa {Format of the QDataStream Operators}
2210*/
2211QDataStream &operator>>(QDataStream &in, QTreeWidgetItem &item)
2212{
2213 item.read(in);
2214 return in;
2215}
2216#endif // QT_NO_DATASTREAM
2217
2218
2219void QTreeWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
2220{
2221 Q_Q(QTreeWidget);
2222 emit q->itemPressed(item(index), index.column());
2223}
2224
2225void QTreeWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
2226{
2227 Q_Q(QTreeWidget);
2228 emit q->itemClicked(item(index), index.column());
2229}
2230
2231void QTreeWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
2232{
2233 Q_Q(QTreeWidget);
2234 emit q->itemDoubleClicked(item(index), index.column());
2235}
2236
2237void QTreeWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
2238{
2239 Q_Q(QTreeWidget);
2240 emit q->itemActivated(item(index), index.column());
2241}
2242
2243void QTreeWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
2244{
2245 Q_Q(QTreeWidget);
2246 emit q->itemEntered(item(index), index.column());
2247}
2248
2249void QTreeWidgetPrivate::_q_emitItemChanged(const QModelIndex &index)
2250{
2251 Q_Q(QTreeWidget);
2252 QTreeWidgetItem *indexItem = item(index);
2253 if (indexItem)
2254 emit q->itemChanged(indexItem, index.column());
2255}
2256
2257void QTreeWidgetPrivate::_q_emitItemExpanded(const QModelIndex &index)
2258{
2259 Q_Q(QTreeWidget);
2260 emit q->itemExpanded(item(index));
2261}
2262
2263void QTreeWidgetPrivate::_q_emitItemCollapsed(const QModelIndex &index)
2264{
2265 Q_Q(QTreeWidget);
2266 emit q->itemCollapsed(item(index));
2267}
2268
2269void QTreeWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
2270 const QModelIndex &previous)
2271{
2272 Q_Q(QTreeWidget);
2273 QTreeWidgetItem *currentItem = item(current);
2274 QTreeWidgetItem *previousItem = item(previous);
2275 emit q->currentItemChanged(currentItem, previousItem);
2276}
2277
2278void QTreeWidgetPrivate::_q_sort()
2279{
2280 Q_Q(QTreeWidget);
2281 if (sortingEnabled) {
2282 int column = q->header()->sortIndicatorSection();
2283 Qt::SortOrder order = q->header()->sortIndicatorOrder();
2284 model()->sort(column, order);
2285 }
2286}
2287
2288void QTreeWidgetPrivate::_q_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
2289{
2290 Q_Q(QTreeWidget);
2291 QModelIndexList indices = selected.indexes();
2292 int i;
2293 QTreeModel *m = model();
2294 for (i = 0; i < indices.count(); ++i) {
2295 QTreeWidgetItem *item = m->item(indices.at(i));
2296 item->d->selected = true;
2297 }
2298
2299 indices = deselected.indexes();
2300 for (i = 0; i < indices.count(); ++i) {
2301 QTreeWidgetItem *item = m->item(indices.at(i));
2302 item->d->selected = false;
2303 }
2304
2305 emit q->itemSelectionChanged();
2306}
2307
2308void QTreeWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
2309 const QModelIndex &bottomRight)
2310{
2311 Q_Q(QTreeWidget);
2312 if (sortingEnabled && topLeft.isValid() && bottomRight.isValid()
2313 && !model()->sortPendingTimer.isActive()) {
2314 int column = q->header()->sortIndicatorSection();
2315 if (column >= topLeft.column() && column <= bottomRight.column()) {
2316 Qt::SortOrder order = q->header()->sortIndicatorOrder();
2317 model()->ensureSorted(column, order, topLeft.row(),
2318 bottomRight.row(), topLeft.parent());
2319 }
2320 }
2321}
2322
2323/*!
2324 \class QTreeWidget
2325
2326 \brief The QTreeWidget class provides a tree view that uses a predefined
2327 tree model.
2328
2329 \ingroup model-view
2330 \mainclass
2331
2332 The QTreeWidget class is a convenience class that provides a standard
2333 tree widget with a classic item-based interface similar to that used by
2334 the QListView class in Qt 3.
2335 This class is based on Qt's Model/View architecture and uses a default
2336 model to hold items, each of which is a QTreeWidgetItem.
2337
2338 Developers who do not need the flexibility of the Model/View framework
2339 can use this class to create simple hierarchical lists very easily. A more
2340 flexible approach involves combining a QTreeView with a standard item model.
2341 This allows the storage of data to be separated from its representation.
2342
2343 In its simplest form, a tree widget can be constructed in the following way:
2344
2345 \snippet doc/src/snippets/code/src_gui_itemviews_qtreewidget.cpp 0
2346
2347 Before items can be added to the tree widget, the number of columns must
2348 be set with setColumnCount(). This allows each item to have one or more
2349 labels or other decorations. The number of columns in use can be found
2350 with the columnCount() function.
2351
2352 The tree can have a header that contains a section for each column in
2353 the widget. It is easiest to set up the labels for each section by
2354 supplying a list of strings with setHeaderLabels(), but a custom header
2355 can be constructed with a QTreeWidgetItem and inserted into the tree
2356 with the setHeaderItem() function.
2357
2358 The items in the tree can be sorted by column according to a predefined
2359 sort order. If sorting is enabled, the user can sort the items by clicking
2360 on a column header. Sorting can be enabled or disabled by calling
2361 \l{QTreeView::setSortingEnabled()}{setSortingEnabled()}. The
2362 \l{QTreeView::isSortingEnabled()}{isSortingEnabled()} function indicates
2363 whether sorting is enabled.
2364
2365 \table 100%
2366 \row \o \inlineimage windowsxp-treeview.png Screenshot of a Windows XP style tree widget
2367 \o \inlineimage macintosh-treeview.png Screenshot of a Macintosh style tree widget
2368 \o \inlineimage plastique-treeview.png Screenshot of a Plastique style tree widget
2369 \row \o A \l{Windows XP Style Widget Gallery}{Windows XP style} tree widget.
2370 \o A \l{Macintosh Style Widget Gallery}{Macintosh style} tree widget.
2371 \o A \l{Plastique Style Widget Gallery}{Plastique style} tree widget.
2372 \endtable
2373
2374 \sa QTreeWidgetItem, QTreeWidgetItemIterator, QTreeView,
2375 {Model/View Programming}, {Settings Editor Example}
2376*/
2377
2378/*!
2379 \property QTreeWidget::columnCount
2380 \brief the number of columns displayed in the tree widget
2381
2382 By default, this property has a value of 1.
2383*/
2384
2385/*!
2386 \fn void QTreeWidget::itemActivated(QTreeWidgetItem *item, int column)
2387
2388 This signal is emitted when the user activates an item by single-
2389 or double-clicking (depending on the platform, i.e. on the
2390 QStyle::SH_ItemView_ActivateItemOnSingleClick style hint) or
2391 pressing a special key (e.g., \key Enter).
2392
2393 The specified \a item is the item that was clicked, or 0 if no
2394 item was clicked. The \a column is the item's column that was
2395 clicked, or -1 if no item was clicked.
2396*/
2397
2398/*!
2399 \fn void QTreeWidget::itemPressed(QTreeWidgetItem *item, int column)
2400
2401 This signal is emitted when the user presses a mouse button inside
2402 the widget.
2403
2404 The specified \a item is the item that was clicked, or 0 if no
2405 item was clicked. The \a column is the item's column that was
2406 clicked, or -1 if no item was clicked.
2407*/
2408
2409/*!
2410 \fn void QTreeWidget::itemClicked(QTreeWidgetItem *item, int column)
2411
2412 This signal is emitted when the user clicks inside the widget.
2413
2414 The specified \a item is the item that was clicked. The \a column is the
2415 item's column that was clicked. If no item was clicked, no signal will be
2416 emitted.
2417*/
2418
2419/*!
2420 \fn void QTreeWidget::itemDoubleClicked(QTreeWidgetItem *item, int column)
2421
2422 This signal is emitted when the user double clicks inside the
2423 widget.
2424
2425 The specified \a item is the item that was clicked, or 0 if no
2426 item was clicked. The \a column is the item's column that was
2427 clicked. If no item was double clicked, no signal will be emitted.
2428*/
2429
2430/*!
2431 \fn void QTreeWidget::itemExpanded(QTreeWidgetItem *item)
2432
2433 This signal is emitted when the specified \a item is expanded so that
2434 all of its children are displayed.
2435
2436 \note This signal will not be emitted if an item changes its state when
2437 expandAll() is invoked.
2438
2439 \sa isItemExpanded(), itemCollapsed(), expandItem()
2440*/
2441
2442/*!
2443 \fn void QTreeWidget::itemCollapsed(QTreeWidgetItem *item)
2444
2445 This signal is emitted when the specified \a item is collapsed so that
2446 none of its children are displayed.
2447
2448 \note This signal will not be emitted if an item changes its state when
2449 collapseAll() is invoked.
2450
2451 \sa isItemExpanded(), itemExpanded(), collapseItem()
2452*/
2453
2454/*!
2455 \fn void QTreeWidget::currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
2456
2457 This signal is emitted when the current item changes. The current
2458 item is specified by \a current, and this replaces the \a previous
2459 current item.
2460
2461 \sa setCurrentItem()
2462*/
2463
2464/*!
2465 \fn void QTreeWidget::itemSelectionChanged()
2466
2467 This signal is emitted when the selection changes in the tree widget.
2468 The current selection can be found with selectedItems().
2469*/
2470
2471/*!
2472 \fn void QTreeWidget::itemEntered(QTreeWidgetItem *item, int column)
2473
2474 This signal is emitted when the mouse cursor enters an \a item over the
2475 specified \a column.
2476 QTreeWidget mouse tracking needs to be enabled for this feature to work.
2477*/
2478
2479/*!
2480 \fn void QTreeWidget::itemChanged(QTreeWidgetItem *item, int column)
2481
2482 This signal is emitted when the contents of the \a column in the specified
2483 \a item changes.
2484*/
2485
2486/*!
2487 \since 4.3
2488
2489 \fn void QTreeWidget::removeItemWidget(QTreeWidgetItem *item, int column)
2490
2491 Removes the widget set in the given \a item in the given \a column.
2492*/
2493
2494/*!
2495 Constructs a tree widget with the given \a parent.
2496*/
2497QTreeWidget::QTreeWidget(QWidget *parent)
2498 : QTreeView(*new QTreeWidgetPrivate(), parent)
2499{
2500 QTreeView::setModel(new QTreeModel(1, this));
2501 connect(this, SIGNAL(pressed(QModelIndex)),
2502 SLOT(_q_emitItemPressed(QModelIndex)));
2503 connect(this, SIGNAL(clicked(QModelIndex)),
2504 SLOT(_q_emitItemClicked(QModelIndex)));
2505 connect(this, SIGNAL(doubleClicked(QModelIndex)),
2506 SLOT(_q_emitItemDoubleClicked(QModelIndex)));
2507 connect(this, SIGNAL(activated(QModelIndex)),
2508 SLOT(_q_emitItemActivated(QModelIndex)));
2509 connect(this, SIGNAL(entered(QModelIndex)),
2510 SLOT(_q_emitItemEntered(QModelIndex)));
2511 connect(this, SIGNAL(expanded(QModelIndex)),
2512 SLOT(_q_emitItemExpanded(QModelIndex)));
2513 connect(this, SIGNAL(collapsed(QModelIndex)),
2514 SLOT(_q_emitItemCollapsed(QModelIndex)));
2515 connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
2516 this, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex)));
2517 connect(model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
2518 this, SLOT(_q_emitItemChanged(QModelIndex)));
2519 connect(model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
2520 this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
2521 connect(model(), SIGNAL(columnsRemoved(QModelIndex,int,int)),
2522 this, SLOT(_q_sort()));
2523 connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
2524 this, SLOT(_q_selectionChanged(QItemSelection,QItemSelection)));
2525 header()->setClickable(false);
2526}
2527
2528/*!
2529 Destroys the tree widget and all its items.
2530*/
2531
2532QTreeWidget::~QTreeWidget()
2533{
2534}
2535
2536/*
2537 Retuns the number of header columns in the view.
2538
2539 \sa sortColumn(), currentColumn(), topLevelItemCount()
2540*/
2541
2542int QTreeWidget::columnCount() const
2543{
2544 Q_D(const QTreeWidget);
2545 return d->model()->columnCount();
2546}
2547
2548/*
2549 Sets the number of header \a columns in the tree widget.
2550*/
2551
2552void QTreeWidget::setColumnCount(int columns)
2553{
2554 Q_D(QTreeWidget);
2555 if (columns < 0)
2556 return;
2557 d->model()->setColumnCount(columns);
2558}
2559
2560/*!
2561 \since 4.2
2562
2563 Returns the tree widget's invisible root item.
2564
2565 The invisible root item provides access to the tree widget's top-level items
2566 through the QTreeWidgetItem API, making it possible to write functions that
2567 can treat top-level items and their children in a uniform way; for example,
2568 recursive functions.
2569*/
2570
2571QTreeWidgetItem *QTreeWidget::invisibleRootItem() const
2572{
2573 Q_D(const QTreeWidget);
2574 return d->model()->rootItem;
2575}
2576
2577/*!
2578 Returns the top level item at the given \a index, or 0 if the item does
2579 not exist.
2580
2581 \sa topLevelItemCount(), insertTopLevelItem()
2582*/
2583
2584QTreeWidgetItem *QTreeWidget::topLevelItem(int index) const
2585{
2586 Q_D(const QTreeWidget);
2587 return d->model()->rootItem->child(index);
2588}
2589
2590/*!
2591 \property QTreeWidget::topLevelItemCount
2592 \brief the number of top-level items
2593
2594 By default, this property has a value of 0.
2595
2596 \sa columnCount(), currentItem()
2597*/
2598
2599int QTreeWidget::topLevelItemCount() const
2600{
2601 Q_D(const QTreeWidget);
2602 return d->model()->rootItem->childCount();
2603}
2604
2605/*!
2606 Inserts the \a item at \a index in the top level in the view.
2607
2608 If the item has already been inserted somewhere else it wont be inserted.
2609
2610 \sa addTopLevelItem(), columnCount()
2611*/
2612
2613void QTreeWidget::insertTopLevelItem(int index, QTreeWidgetItem *item)
2614{
2615 Q_D(QTreeWidget);
2616 d->model()->rootItem->insertChild(index, item);
2617}
2618
2619/*!
2620 \since 4.1
2621
2622 Appends the \a item as a top-level item in the widget.
2623
2624 \sa insertTopLevelItem()
2625*/
2626void QTreeWidget::addTopLevelItem(QTreeWidgetItem *item)
2627{
2628 insertTopLevelItem(topLevelItemCount(), item);
2629}
2630
2631/*!
2632 Removes the top-level item at the given \a index in the tree and
2633 returns it, otherwise returns 0;
2634
2635 \sa insertTopLevelItem(), topLevelItem(), topLevelItemCount()
2636*/
2637
2638QTreeWidgetItem *QTreeWidget::takeTopLevelItem(int index)
2639{
2640 Q_D(QTreeWidget);
2641 return d->model()->rootItem->takeChild(index);
2642}
2643
2644/*!
2645 \internal
2646*/
2647int QTreeWidget::indexOfTopLevelItem(QTreeWidgetItem *item)
2648{
2649 Q_D(QTreeWidget);
2650 d->model()->executePendingSort();
2651 return d->model()->rootItem->children.indexOf(item);
2652}
2653
2654/*!
2655 Returns the index of the given top-level \a item, or -1 if the item
2656 cannot be found.
2657
2658 \sa sortItems(), topLevelItemCount()
2659 */
2660int QTreeWidget::indexOfTopLevelItem(QTreeWidgetItem *item) const
2661{
2662 Q_D(const QTreeWidget);
2663 d->model()->executePendingSort();
2664 return d->model()->rootItem->children.indexOf(item);
2665}
2666
2667/*!
2668 \since 4.1
2669
2670 Inserts the list of \a items at \a index in the top level in the view.
2671
2672 Items that have already been inserted somewhere else wont be inserted.
2673
2674 \sa addTopLevelItems()
2675*/
2676void QTreeWidget::insertTopLevelItems(int index, const QList<QTreeWidgetItem*> &items)
2677{
2678 Q_D(QTreeWidget);
2679 d->model()->rootItem->insertChildren(index, items);
2680}
2681
2682/*!
2683 Appends the list of \a items as a top-level items in the widget.
2684
2685 \sa insertTopLevelItems()
2686*/
2687void QTreeWidget::addTopLevelItems(const QList<QTreeWidgetItem*> &items)
2688{
2689 insertTopLevelItems(topLevelItemCount(), items);
2690}
2691
2692/*!
2693 Returns the item used for the tree widget's header.
2694
2695 \sa setHeaderItem()
2696*/
2697
2698QTreeWidgetItem *QTreeWidget::headerItem() const
2699{
2700 Q_D(const QTreeWidget);
2701 return d->model()->headerItem;
2702}
2703
2704/*!
2705 Sets the header \a item for the tree widget. The label for each column in
2706 the header is supplied by the corresponding label in the item.
2707
2708 The tree widget takes ownership of the item.
2709
2710 \sa headerItem(), setHeaderLabels()
2711*/
2712
2713void QTreeWidget::setHeaderItem(QTreeWidgetItem *item)
2714{
2715 Q_D(QTreeWidget);
2716 if (!item)
2717 return;
2718 item->view = this;
2719
2720 int oldCount = columnCount();
2721 if (oldCount < item->columnCount())
2722 d->model()->beginInsertColumns(QModelIndex(), oldCount, item->columnCount());
2723 else
2724 d->model()->beginRemoveColumns(QModelIndex(), item->columnCount(), oldCount);
2725 delete d->model()->headerItem;
2726 d->model()->headerItem = item;
2727 if (oldCount < item->columnCount())
2728 d->model()->endInsertColumns();
2729 else
2730 d->model()->endRemoveColumns();
2731 d->model()->headerDataChanged(Qt::Horizontal, 0, oldCount);
2732}
2733
2734
2735/*!
2736 Adds a column in the header for each item in the \a labels list, and sets
2737 the label for each column.
2738
2739 Note that setHeaderLabels() won't remove existing columns.
2740
2741 \sa setHeaderItem(), setHeaderLabel()
2742*/
2743void QTreeWidget::setHeaderLabels(const QStringList &labels)
2744{
2745 Q_D(QTreeWidget);
2746 if (columnCount() < labels.count())
2747 setColumnCount(labels.count());
2748 QTreeModel *model = d->model();
2749 QTreeWidgetItem *item = model->headerItem;
2750 for (int i = 0; i < labels.count(); ++i)
2751 item->setText(i, labels.at(i));
2752}
2753
2754/*!
2755 \fn void QTreeWidget::setHeaderLabel(const QString &label)
2756 \since 4.2
2757
2758 Same as setHeaderLabels(QStringList(\a label)).
2759*/
2760
2761/*!
2762 Returns the current item in the tree widget.
2763
2764 \sa setCurrentItem(), currentItemChanged()
2765*/
2766QTreeWidgetItem *QTreeWidget::currentItem() const
2767{
2768 Q_D(const QTreeWidget);
2769 return d->item(currentIndex());
2770}
2771
2772/*!
2773 \since 4.1
2774 Returns the current column in the tree widget.
2775
2776 \sa setCurrentItem(), columnCount()
2777*/
2778int QTreeWidget::currentColumn() const
2779{
2780 return currentIndex().column();
2781}
2782
2783/*!
2784 Sets the current \a item in the tree widget.
2785
2786 Depending on the current selection mode, the item may also be selected.
2787
2788 \sa currentItem(), currentItemChanged()
2789*/
2790void QTreeWidget::setCurrentItem(QTreeWidgetItem *item)
2791{
2792 setCurrentItem(item, 0);
2793}
2794
2795/*!
2796 \since 4.1
2797 Sets the current \a item in the tree widget and the current column to \a column.
2798
2799 \sa currentItem()
2800*/
2801void QTreeWidget::setCurrentItem(QTreeWidgetItem *item, int column)
2802{
2803 Q_D(QTreeWidget);
2804 setCurrentIndex(d->index(item, column));
2805}
2806
2807/*!
2808 \since 4.4
2809 Sets the current \a item in the tree widget and the current column to \a column,
2810 using the given \a command.
2811
2812 \sa currentItem()
2813*/
2814void QTreeWidget::setCurrentItem(QTreeWidgetItem *item, int column,
2815 QItemSelectionModel::SelectionFlags command)
2816{
2817 Q_D(QTreeWidget);
2818 d->selectionModel->setCurrentIndex(d->index(item, column), command);
2819}
2820
2821
2822/*!
2823 Returns a pointer to the item at the coordinates \a p.
2824
2825 \sa visualItemRect()
2826*/
2827QTreeWidgetItem *QTreeWidget::itemAt(const QPoint &p) const
2828{
2829 Q_D(const QTreeWidget);
2830 return d->item(indexAt(p));
2831}
2832
2833/*!
2834 \fn QTreeWidgetItem *QTreeWidget::itemAt(int x, int y) const
2835 \overload
2836
2837 Returns a pointer to the item at the coordinates (\a x, \a y).
2838*/
2839
2840/*!
2841 Returns the rectangle on the viewport occupied by the item at \a item.
2842
2843 \sa itemAt()
2844*/
2845QRect QTreeWidget::visualItemRect(const QTreeWidgetItem *item) const
2846{
2847 Q_D(const QTreeWidget);
2848 return visualRect(d->index(item));
2849}
2850
2851/*!
2852 \since 4.1
2853
2854 Returns the column used to sort the contents of the widget.
2855
2856 \sa sortItems()
2857*/
2858int QTreeWidget::sortColumn() const
2859{
2860 Q_D(const QTreeWidget);
2861 return (d->explicitSortColumn != -1
2862 ? d->explicitSortColumn
2863 : header()->sortIndicatorSection());
2864}
2865
2866/*!
2867 Sorts the items in the widget in the specified \a order by the values in
2868 the given \a column.
2869
2870 \sa sortColumn()
2871*/
2872
2873void QTreeWidget::sortItems(int column, Qt::SortOrder order)
2874{
2875 Q_D(QTreeWidget);
2876 header()->setSortIndicator(column, order);
2877 d->model()->sort(column, order);
2878}
2879
2880/*!
2881 \internal
2882
2883 ### Qt 5: remove
2884*/
2885void QTreeWidget::setSortingEnabled(bool enable)
2886{
2887 QTreeView::setSortingEnabled(enable);
2888}
2889
2890/*!
2891 \internal
2892
2893 ### Qt 5: remove
2894*/
2895bool QTreeWidget::isSortingEnabled() const
2896{
2897 return QTreeView::isSortingEnabled();
2898}
2899
2900/*!
2901 Starts editing the \a item in the given \a column if it is editable.
2902*/
2903
2904void QTreeWidget::editItem(QTreeWidgetItem *item, int column)
2905{
2906 Q_D(QTreeWidget);
2907 edit(d->index(item, column));
2908}
2909
2910/*!
2911 Opens a persistent editor for the \a item in the given \a column.
2912
2913 \sa closePersistentEditor()
2914*/
2915
2916void QTreeWidget::openPersistentEditor(QTreeWidgetItem *item, int column)
2917{
2918 Q_D(QTreeWidget);
2919 QAbstractItemView::openPersistentEditor(d->index(item, column));
2920}
2921
2922/*!
2923 Closes the persistent editor for the \a item in the given \a column.
2924
2925 This function has no effect if no persistent editor is open for this
2926 combination of item and column.
2927
2928 \sa openPersistentEditor()
2929*/
2930
2931void QTreeWidget::closePersistentEditor(QTreeWidgetItem *item, int column)
2932{
2933 Q_D(QTreeWidget);
2934 QAbstractItemView::closePersistentEditor(d->index(item, column));
2935}
2936
2937/*!
2938 \since 4.1
2939
2940 Returns the widget displayed in the cell specified by \a item and the given \a column.
2941
2942 \note The tree takes ownership of the widget.
2943
2944*/
2945QWidget *QTreeWidget::itemWidget(QTreeWidgetItem *item, int column) const
2946{
2947 Q_D(const QTreeWidget);
2948 return QAbstractItemView::indexWidget(d->index(item, column));
2949}
2950
2951/*!
2952 \since 4.1
2953
2954 Sets the given \a widget to be displayed in the cell specified by the given
2955 \a item and \a column.
2956
2957 The given \a widget's \l {QWidget::}{autoFillBackground} property must be
2958 set to true, otherwise the widget's background will be transparent, showing
2959 both the model data and the tree widget item.
2960
2961 This function should only be used to display static content in the place of
2962 a tree widget item. If you want to display custom dynamic content or
2963 implement a custom editor widget, use QTreeView and subclass QItemDelegate
2964 instead.
2965
2966 This function cannot be called before the item hierarchy has been set up,
2967 i.e., the QTreeWidgetItem that will hold \a widget must have been added to
2968 the view before \a widget is set.
2969
2970 \note The tree takes ownership of the widget.
2971
2972 \sa {Delegate Classes}
2973*/
2974void QTreeWidget::setItemWidget(QTreeWidgetItem *item, int column, QWidget *widget)
2975{
2976 Q_D(QTreeWidget);
2977 QAbstractItemView::setIndexWidget(d->index(item, column), widget);
2978}
2979
2980/*!
2981 Returns true if the \a item is selected; otherwise returns false.
2982
2983 \sa itemSelectionChanged()
2984
2985 \obsolete
2986
2987 This function is deprecated. Use \l{QTreeWidgetItem::isSelected()} instead.
2988*/
2989bool QTreeWidget::isItemSelected(const QTreeWidgetItem *item) const
2990{
2991 if (!item)
2992 return false;
2993 return item->d->selected;
2994}
2995
2996/*!
2997 If \a select is true, the given \a item is selected; otherwise it is
2998 deselected.
2999
3000 \sa itemSelectionChanged()
3001
3002 \obsolete
3003
3004 This function is deprecated. Use \l{QTreeWidgetItem::setSelected()} instead.
3005*/
3006void QTreeWidget::setItemSelected(const QTreeWidgetItem *item, bool select)
3007{
3008 Q_D(QTreeWidget);
3009
3010 if (!item)
3011 return;
3012
3013 selectionModel()->select(d->index(item), (select ? QItemSelectionModel::Select
3014 : QItemSelectionModel::Deselect)
3015 |QItemSelectionModel::Rows);
3016 item->d->selected = select;
3017}
3018
3019/*!
3020 Returns a list of all selected non-hidden items.
3021
3022 \sa itemSelectionChanged()
3023*/
3024QList<QTreeWidgetItem*> QTreeWidget::selectedItems() const
3025{
3026 Q_D(const QTreeWidget);
3027 QModelIndexList indexes = selectionModel()->selectedIndexes();
3028 QList<QTreeWidgetItem*> items;
3029 for (int i = 0; i < indexes.count(); ++i) {
3030 QTreeWidgetItem *item = d->item(indexes.at(i));
3031 if (isItemHidden(item) || items.contains(item)) // ### slow, optimize later
3032 continue;
3033 items.append(item);
3034 }
3035 return items;
3036}
3037
3038/*!
3039 Returns a list of items that match the given \a text, using the given \a flags, in the given \a column.
3040*/
3041QList<QTreeWidgetItem*> QTreeWidget::findItems(const QString &text, Qt::MatchFlags flags, int column) const
3042{
3043 Q_D(const QTreeWidget);
3044 QModelIndexList indexes = d->model()->match(model()->index(0, column, QModelIndex()),
3045 Qt::DisplayRole, text, -1, flags);
3046 QList<QTreeWidgetItem*> items;
3047 for (int i = 0; i < indexes.size(); ++i)
3048 items.append(d->item(indexes.at(i)));
3049 return items;
3050}
3051
3052/*!
3053 Returns true if the \a item is explicitly hidden, otherwise returns false.
3054
3055 \obsolete
3056
3057 This function is deprecated. Use \l{QTreeWidgetItem::isHidden()} instead.
3058*/
3059bool QTreeWidget::isItemHidden(const QTreeWidgetItem *item) const
3060{
3061 Q_D(const QTreeWidget);
3062 if (item == d->model()->headerItem)
3063 return header()->isHidden();
3064 if (d->hiddenIndexes.isEmpty())
3065 return false;
3066 QTreeModel::SkipSorting skipSorting(d->model());
3067 return d->isRowHidden(d->index(item));
3068}
3069
3070/*!
3071 Hides the given \a item if \a hide is true; otherwise shows the item.
3072
3073 \sa itemChanged()
3074
3075 \obsolete
3076
3077 This function is deprecated. Use \l{QTreeWidgetItem::setHidden()} instead.
3078*/
3079void QTreeWidget::setItemHidden(const QTreeWidgetItem *item, bool hide)
3080{
3081 Q_D(QTreeWidget);
3082 if (item == d->model()->headerItem) {
3083 header()->setHidden(hide);
3084 } else {
3085 const QModelIndex index = d->index(item);
3086 setRowHidden(index.row(), index.parent(), hide);
3087 }
3088}
3089
3090/*!
3091 Returns true if the given \a item is open; otherwise returns false.
3092
3093 \sa itemExpanded()
3094
3095 \obsolete
3096
3097 This function is deprecated. Use \l{QTreeWidgetItem::isExpanded()} instead.
3098*/
3099bool QTreeWidget::isItemExpanded(const QTreeWidgetItem *item) const
3100{
3101 Q_D(const QTreeWidget);
3102 QTreeModel::SkipSorting skipSorting(d->model());
3103 return isExpanded(d->index(item));
3104}
3105
3106/*!
3107 Sets the item referred to by \a item to either closed or opened,
3108 depending on the value of \a expand.
3109
3110 \sa expandItem(), collapseItem(), itemExpanded()
3111
3112 \obsolete
3113
3114 This function is deprecated. Use \l{QTreeWidgetItem::setExpanded()} instead.
3115*/
3116void QTreeWidget::setItemExpanded(const QTreeWidgetItem *item, bool expand)
3117{
3118 Q_D(QTreeWidget);
3119 QTreeModel::SkipSorting skipSorting(d->model());
3120 setExpanded(d->index(item), expand);
3121}
3122
3123/*!
3124 \since 4.3
3125
3126 Returns true if the given \a item is set to show only one section over all columns;
3127 otherwise returns false.
3128
3129 \sa setFirstItemColumnSpanned()
3130*/
3131bool QTreeWidget::isFirstItemColumnSpanned(const QTreeWidgetItem *item) const
3132{
3133 Q_D(const QTreeWidget);
3134 if (item == d->model()->headerItem)
3135 return false; // We can't set the header items to spanning
3136 const QModelIndex index = d->index(item);
3137 return isFirstColumnSpanned(index.row(), index.parent());
3138}
3139
3140/*!
3141 \since 4.3
3142
3143 Sets the given \a item to only show one section for all columns if \a span is true;
3144 otherwise the item will show one section per column.
3145
3146 \sa isFirstItemColumnSpanned()
3147*/
3148void QTreeWidget::setFirstItemColumnSpanned(const QTreeWidgetItem *item, bool span)
3149{
3150 Q_D(QTreeWidget);
3151 if (item == d->model()->headerItem)
3152 return; // We can't set header items to spanning
3153 const QModelIndex index = d->index(item);
3154 setFirstColumnSpanned(index.row(), index.parent(), span);
3155}
3156
3157/*!
3158 \since 4.3
3159
3160 Returns the item above the given \a item.
3161*/
3162QTreeWidgetItem *QTreeWidget::itemAbove(const QTreeWidgetItem *item) const
3163{
3164 Q_D(const QTreeWidget);
3165 if (item == d->model()->headerItem)
3166 return 0;
3167 const QModelIndex index = d->index(item);
3168 const QModelIndex above = indexAbove(index);
3169 return d->item(above);
3170}
3171
3172/*!
3173 \since 4.3
3174
3175 Returns the item visually below the given \a item.
3176*/
3177QTreeWidgetItem *QTreeWidget::itemBelow(const QTreeWidgetItem *item) const
3178{
3179 Q_D(const QTreeWidget);
3180 if (item == d->model()->headerItem)
3181 return 0;
3182 const QModelIndex index = d->index(item);
3183 const QModelIndex below = indexBelow(index);
3184 return d->item(below);
3185}
3186
3187/*!
3188 \reimp
3189 */
3190void QTreeWidget::setSelectionModel(QItemSelectionModel *selectionModel)
3191{
3192 Q_D(QTreeWidget);
3193 QTreeView::setSelectionModel(selectionModel);
3194 QItemSelection newSelection = selectionModel->selection();
3195 if (!newSelection.isEmpty())
3196 d->_q_selectionChanged(newSelection, QItemSelection());
3197}
3198
3199/*!
3200 Ensures that the \a item is visible, scrolling the view if necessary using
3201 the specified \a hint.
3202
3203 \sa currentItem(), itemAt(), topLevelItem()
3204*/
3205void QTreeWidget::scrollToItem(const QTreeWidgetItem *item, QAbstractItemView::ScrollHint hint)
3206{
3207 Q_D(QTreeWidget);
3208 QTreeView::scrollTo(d->index(item), hint);
3209}
3210
3211/*!
3212 Expands the \a item. This causes the tree containing the item's children
3213 to be expanded.
3214
3215 \sa collapseItem(), currentItem(), itemAt(), topLevelItem(), itemExpanded()
3216*/
3217void QTreeWidget::expandItem(const QTreeWidgetItem *item)
3218{
3219 Q_D(QTreeWidget);
3220 QTreeModel::SkipSorting skipSorting(d->model());
3221 expand(d->index(item));
3222}
3223
3224/*!
3225 Closes the \a item. This causes the tree containing the item's children
3226 to be collapsed.
3227
3228 \sa expandItem(), currentItem(), itemAt(), topLevelItem()
3229*/
3230void QTreeWidget::collapseItem(const QTreeWidgetItem *item)
3231{
3232 Q_D(QTreeWidget);
3233 QTreeModel::SkipSorting skipSorting(d->model());
3234 collapse(d->index(item));
3235}
3236
3237/*!
3238 Clears the tree widget by removing all of its items and selections.
3239
3240 \bold{Note:} Since each item is removed from the tree widget before being
3241 deleted, the return value of QTreeWidgetItem::treeWidget() will be invalid
3242 when called from an item's destructor.
3243
3244 \sa takeTopLevelItem(), topLevelItemCount(), columnCount()
3245*/
3246void QTreeWidget::clear()
3247{
3248 Q_D(QTreeWidget);
3249 selectionModel()->clear();
3250 d->model()->clear();
3251}
3252
3253/*!
3254 Returns a list of MIME types that can be used to describe a list of
3255 treewidget items.
3256
3257 \sa mimeData()
3258*/
3259QStringList QTreeWidget::mimeTypes() const
3260{
3261 return model()->QAbstractItemModel::mimeTypes();
3262}
3263
3264/*!
3265 Returns an object that contains a serialized description of the specified
3266 \a items. The format used to describe the items is obtained from the
3267 mimeTypes() function.
3268
3269 If the list of items is empty, 0 is returned rather than a serialized
3270 empty list.
3271*/
3272QMimeData *QTreeWidget::mimeData(const QList<QTreeWidgetItem*> items) const
3273{
3274 Q_D(const QTreeWidget);
3275 if (d->model()->cachedIndexes.isEmpty()) {
3276 QList<QModelIndex> indexes;
3277 for (int i = 0; i < items.count(); ++i) {
3278 QTreeWidgetItem *item = items.at(i);
3279 for (int c = 0; c < item->values.count(); ++c) {
3280 indexes << indexFromItem(item, c);
3281 }
3282 }
3283 return model()->QAbstractItemModel::mimeData(indexes);
3284 }
3285 return d->model()->internalMimeData();
3286}
3287
3288/*!
3289 Handles the \a data supplied by a drag and drop operation that ended with
3290 the given \a action in the \a index in the given \a parent item.
3291
3292 The default implementation returns true if the drop was
3293 successfully handled by decoding the mime data and inserting it
3294 into the model; otherwise it returns false.
3295
3296 \sa supportedDropActions()
3297*/
3298bool QTreeWidget::dropMimeData(QTreeWidgetItem *parent, int index,
3299 const QMimeData *data, Qt::DropAction action)
3300{
3301 QModelIndex idx;
3302 if (parent) idx = indexFromItem(parent);
3303 return model()->QAbstractItemModel::dropMimeData(data, action , index, 0, idx);
3304}
3305
3306/*!
3307 Returns the drop actions supported by this view.
3308
3309 \sa Qt::DropActions
3310*/
3311Qt::DropActions QTreeWidget::supportedDropActions() const
3312{
3313 return model()->QAbstractItemModel::supportedDropActions() | Qt::MoveAction;
3314}
3315
3316/*!
3317 \obsolete
3318 Returns an empty list
3319
3320 \sa mimeData()
3321*/
3322QList<QTreeWidgetItem*> QTreeWidget::items(const QMimeData *data) const
3323{
3324 Q_UNUSED(data);
3325 return QList<QTreeWidgetItem*>();
3326}
3327
3328/*!
3329 Returns the QModelIndex assocated with the given \a item in the given \a column.
3330
3331 \sa itemFromIndex(), topLevelItem()
3332*/
3333QModelIndex QTreeWidget::indexFromItem(QTreeWidgetItem *item, int column) const
3334{
3335 Q_D(const QTreeWidget);
3336 return d->index(item, column);
3337}
3338
3339/*!
3340 Returns a pointer to the QTreeWidgetItem assocated with the given \a index.
3341
3342 \sa indexFromItem()
3343*/
3344QTreeWidgetItem *QTreeWidget::itemFromIndex(const QModelIndex &index) const
3345{
3346 Q_D(const QTreeWidget);
3347 return d->item(index);
3348}
3349
3350#ifndef QT_NO_DRAGANDDROP
3351/*! \reimp */
3352void QTreeWidget::dropEvent(QDropEvent *event) {
3353 Q_D(QTreeWidget);
3354 if (event->source() == this && (event->dropAction() == Qt::MoveAction ||
3355 dragDropMode() == QAbstractItemView::InternalMove)) {
3356 QModelIndex topIndex;
3357 int col = -1;
3358 int row = -1;
3359 if (d->dropOn(event, &row, &col, &topIndex)) {
3360 QList<QModelIndex> idxs = selectedIndexes();
3361 QList<QPersistentModelIndex> indexes;
3362 for (int i = 0; i < idxs.count(); i++)
3363 indexes.append(idxs.at(i));
3364
3365 if (indexes.contains(topIndex))
3366 return;
3367
3368 // When removing items the drop location could shift
3369 QPersistentModelIndex dropRow = model()->index(row, col, topIndex);
3370
3371 // Remove the items
3372 QList<QTreeWidgetItem *> taken;
3373 for (int i = indexes.count() - 1; i >= 0; --i) {
3374 QTreeWidgetItem *parent = itemFromIndex(indexes.at(i));
3375 if (!parent || !parent->parent()) {
3376 taken.append(takeTopLevelItem(indexes.at(i).row()));
3377 } else {
3378 taken.append(parent->parent()->takeChild(indexes.at(i).row()));
3379 }
3380 }
3381
3382 // insert them back in at their new positions
3383 for (int i = 0; i < indexes.count(); ++i) {
3384 // Either at a specific point or appended
3385 if (row == -1) {
3386 if (topIndex.isValid()) {
3387 QTreeWidgetItem *parent = itemFromIndex(topIndex);
3388 parent->insertChild(parent->childCount(), taken.takeFirst());
3389 } else {
3390 insertTopLevelItem(topLevelItemCount(), taken.takeFirst());
3391 }
3392 } else {
3393 int r = dropRow.row() >= 0 ? dropRow.row() : row;
3394 if (topIndex.isValid()) {
3395 QTreeWidgetItem *parent = itemFromIndex(topIndex);
3396 parent->insertChild(qMin(r, parent->childCount()), taken.takeFirst());
3397 } else {
3398 insertTopLevelItem(qMin(r, topLevelItemCount()), taken.takeFirst());
3399 }
3400 }
3401 }
3402
3403 event->accept();
3404 // Don't want QAbstractItemView to delete it because it was "moved" we already did it
3405 event->setDropAction(Qt::CopyAction);
3406 }
3407 }
3408
3409 QTreeView::dropEvent(event);
3410}
3411#endif
3412
3413/*!
3414 \reimp
3415*/
3416
3417void QTreeWidget::setModel(QAbstractItemModel * /*model*/)
3418{
3419 Q_ASSERT(!"QTreeWidget::setModel() - Changing the model of the QTreeWidget is not allowed.");
3420}
3421
3422/*!
3423 \reimp
3424*/
3425bool QTreeWidget::event(QEvent *e)
3426{
3427 Q_D(QTreeWidget);
3428 if (e->type() == QEvent::Polish)
3429 d->model()->executePendingSort();
3430 return QTreeView::event(e);
3431}
3432
3433QT_END_NAMESPACE
3434
3435#include "moc_qtreewidget.cpp"
3436
3437#endif // QT_NO_TREEWIDGET
Note: See TracBrowser for help on using the repository browser.