src/gui/itemviews/qtreewidget.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the QtGui module of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include "qtreewidget.h"
00025 
00026 #ifndef QT_NO_TREEWIDGET
00027 #include <qheaderview.h>
00028 #include <qpainter.h>
00029 #include <qitemdelegate.h>
00030 #include <qstack.h>
00031 #include <qdebug.h>
00032 #include <private/qtreeview_p.h>
00033 #include <private/qwidgetitemdata_p.h>
00034 #include <private/qtreewidget_p.h>
00035 #include <private/qtreewidgetitemiterator_p.h>
00036 
00037 // workaround for VC++ 6.0 linker bug (?)
00038 typedef bool(*LessThan)(const QPair<QTreeWidgetItem*,int>&,const QPair<QTreeWidgetItem*,int>&);
00039 
00040 class QTreeWidgetMimeData : public QMimeData
00041 {
00042     Q_OBJECT
00043 public:
00044     QList<QTreeWidgetItem*> items;
00045 };
00046 
00047 class QTreeModelLessThan
00048 {
00049 public:
00050     inline bool operator()(QTreeWidgetItem *i1, QTreeWidgetItem *i2) const
00051         { return *i1 < *i2; }
00052 };
00053 
00054 class QTreeModelGreaterThan
00055 {
00056 public:
00057     inline bool operator()(QTreeWidgetItem *i1, QTreeWidgetItem *i2) const
00058         { return *i2 < *i1; }
00059 };
00060 
00061 #include "qtreewidget.moc"
00062 
00063 /*
00064     \class QTreeModel
00065     \brief The QTreeModel class manages the items stored in a tree view.
00066 
00067     \ingroup model-view
00068     \mainclass
00069 */
00070 
00078 QTreeModel::QTreeModel(int columns, QTreeWidget *parent)
00079     : QAbstractItemModel(parent), rootItem(new QTreeWidgetItem),
00080       headerItem(new QTreeWidgetItem), sortPending(false)
00081 {
00082     rootItem->view = parent;
00083     headerItem->view = parent;
00084     setColumnCount(columns);
00085 }
00086 
00092 QTreeModel::QTreeModel(QTreeModelPrivate &dd, QTreeWidget *parent)
00093     : QAbstractItemModel(dd, parent), rootItem(new QTreeWidgetItem),
00094       headerItem(new QTreeWidgetItem), sortPending(false)
00095 {
00096     rootItem->view = parent;
00097     headerItem->view = parent;
00098 }
00099 
00106 QTreeModel::~QTreeModel()
00107 {
00108     clear();
00109     delete headerItem;
00110     rootItem->view = 0;
00111     delete rootItem;
00112 }
00113 
00120 void QTreeModel::clear()
00121 {
00122     for (int i = 0; i < rootItem->childCount(); ++i) {
00123         QTreeWidgetItem *item = rootItem->children.at(i);
00124         item->par = 0;
00125         item->view = 0;
00126         delete item;
00127     }
00128     rootItem->children.clear();
00129     sortPending = false;
00130     reset();
00131 }
00132 
00139 void QTreeModel::setColumnCount(int columns)
00140 {
00141     if (columns < 0)
00142         return;
00143     if (!headerItem) {
00144         headerItem = new QTreeWidgetItem();
00145         headerItem->view = view();
00146     }
00147     int count = columnCount();
00148     if (count == columns)
00149         return;
00150 
00151     if (columns < count) {
00152         beginRemoveColumns(QModelIndex(), columns, count - 1);
00153         headerItem->values.resize(columns);
00154         endRemoveColumns();
00155     } else {
00156         beginInsertColumns(QModelIndex(), count, columns - 1);
00157         headerItem->values.resize(columns);
00158         for (int i = count; i < columns; ++i) {// insert data without emitting the dataChanged signal
00159             headerItem->values[i].append(QWidgetItemData(Qt::DisplayRole, QString::number(i + 1)));
00160             headerItem->display.append(QString::number(i + 1));
00161         }
00162         endInsertColumns();
00163     }
00164 }
00165 
00174 QTreeWidgetItem *QTreeModel::item(const QModelIndex &index) const
00175 {
00176     if (!index.isValid())
00177         return 0;
00178     return static_cast<QTreeWidgetItem*>(index.internalPointer());
00179 }
00180 
00188 QModelIndex QTreeModel::index(const QTreeWidgetItem *item, int column) const
00189 {
00190     if (!item || (item == rootItem))
00191         return QModelIndex();
00192     const QTreeWidgetItem *par = item->parent();
00193     QTreeWidgetItem *itm = const_cast<QTreeWidgetItem*>(item);
00194     if (!par)
00195         par = rootItem;
00196     return createIndex(par->children.lastIndexOf(itm), column, itm);
00197 }
00198 
00207 QModelIndex QTreeModel::index(int row, int column, const QModelIndex &parent) const
00208 {
00209     int c = columnCount(parent);
00210 
00211     if (row < 0 || column < 0 || column >= c)
00212         return QModelIndex();
00213 
00214     QTreeWidgetItem *parentItem = parent.isValid() ? item(parent) : rootItem;
00215     if (parentItem && row < parentItem->childCount()) {
00216         QTreeWidgetItem *itm = parentItem->child(row);
00217         if (itm)
00218             return createIndex(row, column, itm);
00219         return QModelIndex();
00220     }
00221 
00222     return QModelIndex();
00223 }
00224 
00233 QModelIndex QTreeModel::parent(const QModelIndex &child) const
00234 {
00235     if (!child.isValid())
00236         return QModelIndex();
00237     QTreeWidgetItem *itm = static_cast<QTreeWidgetItem *>(child.internalPointer());
00238     if (!itm)
00239         return QModelIndex();
00240     QTreeWidgetItem *parent = itm->parent();
00241     return index(parent, 0);
00242 }
00243 
00251 int QTreeModel::rowCount(const QModelIndex &parent) const
00252 {
00253     executePendingSort();
00254 
00255     if (!parent.isValid())
00256         return rootItem->childCount();
00257 
00258     QTreeWidgetItem *parentItem = item(parent);
00259     if (parentItem)
00260         return parentItem->childCount();
00261     return 0;
00262 }
00263 
00272 int QTreeModel::columnCount(const QModelIndex &index) const
00273 {
00274     Q_UNUSED(index);
00275     if (!headerItem)
00276         return 0;
00277     return headerItem->columnCount();
00278 }
00279 
00280 bool QTreeModel::hasChildren(const QModelIndex &parent) const
00281 {
00282     executePendingSort();
00283 
00284     if (!parent.isValid())
00285         return (rootItem->childCount() > 0);
00286 
00287     QTreeWidgetItem *itm = item(parent);
00288     if (!itm)
00289         return false;
00290     return (itm->childCount() > 0);
00291 }
00292 
00301 QVariant QTreeModel::data(const QModelIndex &index, int role) const
00302 {
00303     if (!index.isValid())
00304         return QVariant();
00305     QTreeWidgetItem *itm = item(index);
00306     if (itm)
00307         return itm->data(index.column(), role);
00308     return QVariant();
00309 }
00310 
00321 bool QTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
00322 {
00323     if (!index.isValid())
00324         return false;
00325     QTreeWidgetItem *itm = item(index);
00326     if (itm) {
00327         itm->setData(index.column(), role, value);
00328         return true;
00329     }
00330     return false;
00331 }
00332 
00337 bool QTreeModel::insertRows(int row, int count, const QModelIndex &parent)
00338 {
00339     if (count < 1 || row < 0 || row > rowCount(parent) || parent.column() > 0)
00340         return false;
00341 
00342     beginInsertRows(parent, row, row + count - 1);
00343     QTreeWidgetItem *par = item(parent);
00344     while (count > 0) {
00345         QTreeWidgetItem *item = new QTreeWidgetItem();
00346         item->view = view();
00347         item->par = par;
00348         if (par)
00349             par->children.insert(row++, item);
00350         else
00351             rootItem->children.insert(row++, item);
00352         --count;
00353     }
00354     endInsertRows();
00355     return true;
00356 }
00357 
00362 bool QTreeModel::insertColumns(int column, int count, const QModelIndex &parent)
00363 {
00364     if (count < 1 || column < 0 || column > columnCount(parent) || parent.column() > 0 || !headerItem)
00365         return false;
00366 
00367     beginInsertColumns(parent, column, column + count - 1);
00368 
00369     int oldCount = columnCount(parent);
00370     column = qBound(0, column, oldCount);
00371     headerItem->values.resize(oldCount + count);
00372     for (int i = oldCount; i < oldCount + count; ++i) {
00373         headerItem->values[i].append(QWidgetItemData(Qt::DisplayRole, QString::number(i + 1)));
00374         headerItem->display.append(QString::number(i + 1));
00375     }
00376 
00377     QStack<QTreeWidgetItem*> itemstack;
00378     itemstack.push(0);
00379     while (!itemstack.isEmpty()) {
00380         QTreeWidgetItem *par = itemstack.pop();
00381         QList<QTreeWidgetItem*> children = par ? par->children : rootItem->children;
00382         for (int row = 0; row < children.count(); ++row) {
00383             QTreeWidgetItem *child = children.at(row);
00384             if (child->children.count())
00385                 itemstack.push(child);
00386             child->values.insert(column, count, QVector<QWidgetItemData>());
00387         }
00388     }
00389 
00390     endInsertColumns();
00391     return true;
00392 }
00393 
00398 bool QTreeModel::removeRows(int row, int count, const QModelIndex &parent) {
00399     if (count < 1 || row < 0 || (row + count) > rowCount(parent))
00400         return false;
00401 
00402     beginRemoveRows(parent, row, row + count - 1);
00403 
00404     bool blockSignal = signalsBlocked();
00405     blockSignals(true);
00406 
00407     QTreeWidgetItem *itm = item(parent);
00408     for (int i = row + count - 1; i >= row; --i) {
00409         QTreeWidgetItem *child = itm ? itm->takeChild(i) : rootItem->children.takeAt(i);
00410         Q_ASSERT(child);
00411         child->view = 0;
00412         delete child;
00413         child = 0;
00414     }
00415     blockSignals(blockSignal);
00416 
00417     endRemoveRows();
00418     return true;
00419 }
00420 
00429 QVariant QTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
00430 {
00431     if (orientation != Qt::Horizontal)
00432         return QVariant();
00433 
00434     if (headerItem)
00435         return headerItem->data(section, role);
00436     if (role == Qt::DisplayRole)
00437         return QString::number(section + 1);
00438     return QVariant();
00439 }
00440 
00451 bool QTreeModel::setHeaderData(int section, Qt::Orientation orientation,
00452                                const QVariant &value, int role)
00453 {
00454     if (section < 0 || orientation != Qt::Horizontal || !headerItem)
00455         return false;
00456 
00457     headerItem->setData(section, role, value);
00458     return true;
00459 }
00460 
00468 Qt::ItemFlags QTreeModel::flags(const QModelIndex &index) const
00469 {
00470     if (!index.isValid())
00471         return Qt::ItemIsDropEnabled; // can drop on the viewport
00472     QTreeWidgetItem *itm = item(index);
00473     Q_ASSERT(itm);
00474     return itm->flags();
00475 }
00476 
00484 void QTreeModel::sort(int column, Qt::SortOrder order)
00485 {
00486     sortPending = false;
00487 
00488     if (column < 0 || column >= columnCount())
00489         return;
00490 
00491     emit layoutAboutToBeChanged();
00492     rootItem->sortChildren(column, order, true);
00493     emit layoutChanged();
00494 }
00495 
00499 void QTreeModel::ensureSorted(int column, Qt::SortOrder order,
00500                               int start, int end, const QModelIndex &parent)
00501 {
00502     sortPending = false;
00503 
00504     if (column < 0 || column >= columnCount())
00505         return;
00506 
00507     QTreeWidgetItem *itm = item(parent);
00508     if (!itm)
00509         itm = rootItem;
00510     QList<QTreeWidgetItem*> lst = itm->children;
00511 
00512     int count = end - start + 1;
00513     QVector < QPair<QTreeWidgetItem*,int> > sorting(count);
00514     for (int i = 0; i < count; ++i) {
00515         sorting[i].first = lst.at(start + i);
00516         sorting[i].second = start + i;
00517     }
00518 
00519     LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
00520     qStableSort(sorting.begin(), sorting.end(), compare);
00521 
00522     QModelIndexList oldPersistentIndexes = persistentIndexList();
00523     QModelIndexList newPersistentIndexes = oldPersistentIndexes;
00524     QList<QTreeWidgetItem*>::iterator lit = lst.begin();
00525     bool changed = false;
00526     for (int i = 0; i < count; ++i) {
00527         int oldRow = sorting.at(i).second;
00528         QTreeWidgetItem *item = lst.takeAt(oldRow);
00529         lit = sortedInsertionIterator(lit, lst.end(), order, item);
00530         int newRow = qMax(lit - lst.begin(), 0);
00531         lit = lst.insert(lit, item);
00532         if (newRow != oldRow) {
00533             changed = true;
00534             for (int j = i + 1; j < count; ++j) {
00535                 int otherRow = sorting.at(j).second;
00536                 if (oldRow < otherRow && newRow >= otherRow)
00537                     --sorting[j].second;
00538                 else if (oldRow > otherRow && newRow <= otherRow)
00539                     ++sorting[j].second;
00540             }
00541             for (int k = 0; k < newPersistentIndexes.count(); ++k) {
00542                 QModelIndex pi = newPersistentIndexes.at(k);
00543                 if (pi.parent() != parent)
00544                     continue;
00545                 int oldPersistentRow = pi.row();
00546                 int newPersistentRow = oldPersistentRow;
00547                 if (oldPersistentRow == oldRow)
00548                     newPersistentRow = newRow;
00549                 else if (oldRow < oldPersistentRow && newRow >= oldPersistentRow)
00550                     newPersistentRow = oldPersistentRow - 1;
00551                 else if (oldRow > oldPersistentRow && newRow <= oldPersistentRow)
00552                     newPersistentRow = oldPersistentRow + 1;
00553                 if (newPersistentRow != oldPersistentRow)
00554                     newPersistentIndexes[k] = createIndex(newPersistentRow,
00555                                                           pi.column(), pi.internalPointer());
00556             }
00557         }
00558     }
00559 
00560     if (changed) {
00561         emit layoutAboutToBeChanged();
00562         itm->children = lst;
00563         changePersistentIndexList(oldPersistentIndexes, newPersistentIndexes);
00564         emit layoutChanged();
00565     }
00566 }
00567 
00577 bool QTreeModel::itemLessThan(const QPair<QTreeWidgetItem*,int> &left,
00578                               const QPair<QTreeWidgetItem*,int> &right)
00579 {
00580     return *(left.first) < *(right.first);
00581 }
00582 
00592 bool QTreeModel::itemGreaterThan(const QPair<QTreeWidgetItem*,int> &left,
00593                                  const QPair<QTreeWidgetItem*,int> &right)
00594 {
00595     return !(*(left .first) < *(right.first));
00596 }
00597 
00601 QList<QTreeWidgetItem*>::iterator QTreeModel::sortedInsertionIterator(
00602     const QList<QTreeWidgetItem*>::iterator &begin,
00603     const QList<QTreeWidgetItem*>::iterator &end,
00604     Qt::SortOrder order, QTreeWidgetItem *item)
00605 {
00606     if (order == Qt::AscendingOrder)
00607         return qLowerBound(begin, end, item, QTreeModelLessThan());
00608     return qLowerBound(begin, end, item, QTreeModelGreaterThan());
00609 }
00610 
00611 QStringList QTreeModel::mimeTypes() const
00612 {
00613     return view()->mimeTypes();
00614 }
00615 
00616 QMimeData *QTreeModel::internalMimeData()  const
00617 {
00618     return QAbstractItemModel::mimeData(cachedIndexes);
00619 }
00620 
00621 QMimeData *QTreeModel::mimeData(const QModelIndexList &indexes) const
00622 {
00623     QList<QTreeWidgetItem*> items;
00624     for (int i = 0; i < indexes.count(); ++i) {
00625         if (indexes.at(i).column() == 0) // only one item per row
00626             items << item(indexes.at(i));
00627     }
00628 
00629     // cachedIndexes is a little hack to avoid copying from QModelIndexList to
00630     // QList<QTreeWidgetItem*> and back again in the view
00631     cachedIndexes = indexes;
00632     QMimeData *mimeData = view()->mimeData(items);
00633     cachedIndexes.clear();
00634     return mimeData;
00635 }
00636 
00637 bool QTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
00638                               int row, int column, const QModelIndex &parent)
00639 {
00640     if (row == -1 && column == -1)
00641         row = rowCount(parent); // append
00642     return view()->dropMimeData(item(parent), row, data, action);
00643 }
00644 
00645 Qt::DropActions QTreeModel::supportedDropActions() const
00646 {
00647     return view()->supportedDropActions();
00648 }
00649 
00650 void QTreeModel::itemChanged(QTreeWidgetItem *item)
00651 {
00652     QModelIndex left = index(item, 0);
00653     QModelIndex right = index(item, item->columnCount() - 1);
00654     emit dataChanged(left, right);
00655 }
00656 
00657 bool QTreeModel::executePendingSort() const
00658 {
00659     if (sortPending) {
00660         sortPending = false;
00661         int column = view()->header()->sortIndicatorSection();
00662         Qt::SortOrder order = view()->header()->sortIndicatorOrder();
00663         QTreeModel *that = const_cast<QTreeModel*>(this);
00664         const bool blocked = that->signalsBlocked();
00665         that->blockSignals(true);
00666         that->sort(column, order);
00667         that->blockSignals(blocked);
00668         return true;
00669     }
00670     return false;
00671 }
00672 
00679 void QTreeModel::emitDataChanged(QTreeWidgetItem *item, int column)
00680 {
00681     if (signalsBlocked())
00682         return;
00683 
00684     if (headerItem == item && column < item->columnCount()) {
00685         if (column == -1)
00686             emit headerDataChanged(Qt::Horizontal, 0, columnCount() - 1);
00687         else
00688             emit headerDataChanged(Qt::Horizontal, column, column);
00689         return;
00690     }
00691 
00692     QModelIndex bottomRight, topLeft;
00693     if (column == -1) {
00694         topLeft = index(item, 0);
00695         bottomRight = createIndex(topLeft.row(), columnCount() - 1, item);
00696     } else {
00697         topLeft = index(item, column);
00698         bottomRight = topLeft;
00699     }
00700     emit dataChanged(topLeft, bottomRight);
00701 }
00702 
00703 void QTreeModel::beginInsertItems(QTreeWidgetItem *parent, int row, int count)
00704 {
00705     beginInsertRows(index(parent, 0), row, row + count - 1);
00706 }
00707 
00708 void QTreeModel::endInsertItems()
00709 {
00710     endInsertRows();
00711 }
00712 
00713 void QTreeModel::beginRemoveItems(QTreeWidgetItem *parent, int row, int count)
00714 {
00715     Q_ASSERT(row >= 0);
00716     Q_ASSERT(count > 0);
00717     beginRemoveRows(index(parent, 0), row, row + count - 1);
00718     if (!parent)
00719         parent = rootItem;
00720     // now update the iterators
00721     for (int i = 0; i < iterators.count(); ++i) {
00722         for (int j = 0; j < count; j++) {
00723             QTreeWidgetItem *c = parent->child(row + j);
00724             iterators[i]->d_func()->ensureValidIterator(c);
00725         }
00726     }
00727 }
00728 
00729 void QTreeModel::endRemoveItems()
00730 {
00731     endRemoveRows();
00732 }
00733 
00734 void QTreeModel::sortItems(QList<QTreeWidgetItem*> *items, int column, Qt::SortOrder order)
00735 {
00736     Q_UNUSED(column);
00737     // store the original order of indexes
00738     QVector< QPair<QTreeWidgetItem*,int> > sorting(items->count());
00739     for (int i = 0; i < sorting.count(); ++i) {
00740         sorting[i].first = items->at(i);
00741         sorting[i].second = i;
00742     }
00743 
00744     // do the sorting
00745     LessThan compare = (order == Qt::AscendingOrder ? &itemLessThan : &itemGreaterThan);
00746     qStableSort(sorting.begin(), sorting.end(), compare);
00747 
00748     int colCount = columnCount();
00749     for (int r = 0; r < sorting.count(); ++r) {
00750         QTreeWidgetItem *item = sorting.at(r).first;
00751         items->replace(r, item);
00752         int oldRow = sorting.at(r).second;
00753         for (int c = 0; c < colCount; ++c) {
00754             QModelIndex from = createIndex(oldRow, c, item);
00755             QModelIndex to = createIndex(r, c, item);
00756             changePersistentIndex(from, to);
00757         }
00758     }
00759 }
00760 
01188 QTreeWidgetItem::QTreeWidgetItem(int type)
01189     : rtti(type), view(0), par(0),
01190       itemFlags(Qt::ItemIsSelectable
01191                 |Qt::ItemIsUserCheckable
01192                 |Qt::ItemIsEnabled
01193                 |Qt::ItemIsDragEnabled
01194                 |Qt::ItemIsDropEnabled)
01195 {
01196 }
01197 
01198 
01207 QTreeWidgetItem::QTreeWidgetItem(const QStringList &strings, int type)
01208     : rtti(type), view(0), par(0),
01209       itemFlags(Qt::ItemIsSelectable
01210                 |Qt::ItemIsUserCheckable
01211                 |Qt::ItemIsEnabled
01212                 |Qt::ItemIsDragEnabled
01213                 |Qt::ItemIsDropEnabled)
01214 {
01215     for (int i = 0; i < strings.count(); ++i)
01216         setText(i, strings.at(i));
01217 }
01218 
01228 QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *view, int type)
01229     : rtti(type), view(0), par(0),
01230       itemFlags(Qt::ItemIsSelectable
01231                 |Qt::ItemIsUserCheckable
01232                 |Qt::ItemIsEnabled
01233                 |Qt::ItemIsDragEnabled
01234                 |Qt::ItemIsDropEnabled)
01235 {
01236     if (view && view->model()) {
01237         QTreeModel *model = ::qobject_cast<QTreeModel*>(view->model());
01238         model->rootItem->addChild(this);
01239         values.reserve(model->headerItem->columnCount());
01240     }
01241 }
01242 
01253 QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *view, const QStringList &strings, int type)
01254     : rtti(type), view(0), par(0),
01255       itemFlags(Qt::ItemIsSelectable
01256                 |Qt::ItemIsUserCheckable
01257                 |Qt::ItemIsEnabled
01258                 |Qt::ItemIsDragEnabled
01259                 |Qt::ItemIsDropEnabled)
01260 {
01261     for (int i = 0; i < strings.count(); ++i)
01262         setText(i, strings.at(i));
01263     if (view && view->model()) {
01264         QTreeModel *model = ::qobject_cast<QTreeModel*>(view->model());
01265         model->rootItem->addChild(this);
01266         values.reserve(model->headerItem->columnCount());
01267     }
01268 }
01269 
01278 QTreeWidgetItem::QTreeWidgetItem(QTreeWidget *view, QTreeWidgetItem *after, int type)
01279     : rtti(type), view(0), par(0),
01280       itemFlags(Qt::ItemIsSelectable
01281                 |Qt::ItemIsUserCheckable
01282                 |Qt::ItemIsEnabled
01283                 |Qt::ItemIsDragEnabled
01284                 |Qt::ItemIsDropEnabled)
01285 {
01286     if (view) {
01287         QTreeModel *model = ::qobject_cast<QTreeModel*>(view->model());
01288         if (model) {
01289             int i = model->rootItem->indexOfChild(after) + 1;
01290             model->rootItem->insertChild(i, this);
01291             values.reserve(model->headerItem->columnCount());
01292         }
01293     }
01294 }
01295 
01301 QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, int type)
01302     : rtti(type), view(0), par(0),
01303       itemFlags(Qt::ItemIsSelectable
01304                 |Qt::ItemIsUserCheckable
01305                 |Qt::ItemIsEnabled
01306                 |Qt::ItemIsDragEnabled
01307                 |Qt::ItemIsDropEnabled)
01308 {
01309     if (parent)
01310         parent->addChild(this);
01311 }
01312 
01319 QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, const QStringList &strings, int type)
01320     : rtti(type), view(0), par(0),
01321       itemFlags(Qt::ItemIsSelectable
01322                 |Qt::ItemIsUserCheckable
01323                 |Qt::ItemIsEnabled
01324                 |Qt::ItemIsDragEnabled
01325                 |Qt::ItemIsDropEnabled)
01326 {
01327     for (int i = 0; i < strings.count(); ++i)
01328         setText(i, strings.at(i));
01329     if (parent)
01330         parent->addChild(this);
01331 
01332 }
01333 
01342 QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem *parent, QTreeWidgetItem *after, int type)
01343     : rtti(type), view(0), par(0),
01344       itemFlags(Qt::ItemIsSelectable
01345                 |Qt::ItemIsUserCheckable
01346                 |Qt::ItemIsEnabled
01347                 |Qt::ItemIsDragEnabled
01348                 |Qt::ItemIsDropEnabled)
01349 {
01350     if (parent) {
01351         int i = parent->indexOfChild(after) + 1;
01352         parent->insertChild(i, this);
01353     }
01354 }
01355 
01360 QTreeWidgetItem::~QTreeWidgetItem()
01361 {
01362     QTreeModel *model = (view ? ::qobject_cast<QTreeModel*>(view->model()) : 0);
01363     if (par) {
01364         int i = par->children.indexOf(this);
01365         if (model) model->beginRemoveItems(par, i, 1);
01366         par->children.takeAt(i);
01367         if (model) model->endRemoveItems();
01368     } else if (model) {
01369         if (this == model->headerItem) {
01370             model->headerItem = 0;
01371         } else {
01372             int i = model->rootItem->children.indexOf(this);
01373             model->beginRemoveItems(0, i, 1);
01374             model->rootItem->children.takeAt(i);
01375             model->endRemoveItems();
01376         }
01377     }
01378     // at this point the persistent indexes for the children should also be invalidated
01379     // since we invalidated the parent
01380     for (int i = 0; i < children.count(); ++i) {
01381         QTreeWidgetItem *child = children.at(i);
01382         // make sure the child does not try to remove itself from our children list
01383         child->par = 0;
01384         // make sure the child does not try to remove itself from the top level list
01385         child->view = 0;
01386         delete child;
01387     }
01388 
01389     children.clear();
01390 }
01391 
01395 QTreeWidgetItem *QTreeWidgetItem::clone() const
01396 {
01397     QTreeWidgetItem *copy = 0;
01398 
01399     QStack<const QTreeWidgetItem*> stack;
01400     QStack<QTreeWidgetItem*> parentStack;
01401     stack.push(this);
01402     parentStack.push(0);
01403 
01404     QTreeWidgetItem *root = 0;
01405     const QTreeWidgetItem *item = 0;
01406     QTreeWidgetItem *parent = 0;
01407     while (!stack.isEmpty()) {
01408         // get current item, and copied parent
01409         item = stack.pop();
01410         parent = parentStack.pop();
01411 
01412         // copy item
01413         copy = new QTreeWidgetItem(*item);
01414         if (!root)
01415             root = copy;
01416 
01417         // set parent and add to parents children list
01418         if (parent) {
01419             copy->par = parent;
01420             parent->children.append(copy);
01421         }
01422 
01423         for (int i=0; i<item->childCount(); ++i) {
01424             stack.push(item->child(i));
01425             parentStack.push(copy);
01426         }
01427     }
01428     return root;
01429 }
01430 
01438 void QTreeWidgetItem::setData(int column, int role, const QVariant &value)
01439 {
01440     if (column < 0)
01441         return;
01442 
01443     QTreeModel *model = (view ? ::qobject_cast<QTreeModel*>(view->model()) : 0);
01444     switch (role) {
01445     case Qt::EditRole:
01446     case Qt::DisplayRole: {
01447         if (values.count() <= column) {
01448             if (model && this == model->headerItem)
01449                 model->setColumnCount(column + 1);
01450             else
01451                 values.resize(column + 1);
01452         }
01453         if (display.count() <= column) {
01454             for (int i = display.count() - 1; i < column - 1; ++i)
01455                 display.append(QVariant());
01456             display.append(value);
01457         } else if (display[column] != value) {
01458             display[column] = value;
01459         } else {
01460             return; // value is unchanged
01461         }
01462     } break;
01463     case Qt::CheckStateRole:
01464         if (itemFlags & Qt::ItemIsTristate) {
01465             for (int i = 0; i < children.count(); ++i) {
01466                 QTreeWidgetItem *child = children.at(i);
01467                 if (child->data(column, role).isValid()) {// has a CheckState
01468                     Qt::ItemFlags f = itemFlags; // a little hack to avoid multiple dataChanged signals
01469                     itemFlags &= ~Qt::ItemIsTristate;
01470                     child->setData(column, role, value);
01471                     itemFlags = f;
01472                 }
01473             }
01474         }
01475         // Don't break, but fall through
01476     default:
01477         if (column < values.count()) {
01478             bool found = false;
01479             QVector<QWidgetItemData> column_values = values.at(column);
01480             for (int i = 0; i < column_values.count(); ++i) {
01481                 if (column_values.at(i).role == role) {
01482                     if (column_values.at(i).value == value)
01483                         return; // value is unchanged
01484                     values[column][i].value = value;
01485                     found = true;
01486                     break;
01487                 }
01488             }
01489             if (!found)
01490                 values[column].append(QWidgetItemData(role, value));
01491         } else {
01492             if (model && this == model->headerItem)
01493                 model->setColumnCount(column + 1);
01494             else
01495                 values.resize(column + 1);
01496             values[column].append(QWidgetItemData(role, value));
01497         }
01498     }
01499 
01500     if (model) {
01501         model->emitDataChanged(this, column);
01502         if (role == Qt::CheckStateRole) {
01503             QTreeWidgetItem *p;
01504             for (p = par; p && (p->itemFlags & Qt::ItemIsTristate); p = p->par)
01505                 model->emitDataChanged(p, column);
01506         }
01507     }
01508 }
01509 
01513 QVariant QTreeWidgetItem::data(int column, int role) const
01514 {
01515     switch (role) {
01516     case Qt::EditRole:
01517     case Qt::DisplayRole:
01518         if (column >= 0 && column < display.count())
01519             return display.at(column);
01520         break;
01521     case Qt::CheckStateRole:
01522         // special case for check state in tristate
01523         if (children.count() && (itemFlags & Qt::ItemIsTristate))
01524             return childrenCheckState(column);
01525    default:
01526         if (column >= 0 && column < values.size()) {
01527             const QVector<QWidgetItemData> &column_values = values.at(column);
01528             for (int i = 0; i < column_values.count(); ++i)
01529                 if (column_values.at(i).role == role)
01530                     return column_values.at(i).value;
01531         }
01532     }
01533     return QVariant();
01534 }
01535 
01541 bool QTreeWidgetItem::operator<(const QTreeWidgetItem &other) const
01542 {
01543     int column = view ? view->sortColumn() : 0;
01544     return text(column) < other.text(column);
01545 }
01546 
01547 #ifndef QT_NO_DATASTREAM
01548 
01554 void QTreeWidgetItem::read(QDataStream &in)
01555 {
01556     // convert from streams written before we introduced display (4.2.0)
01557     if (in.version() < QDataStream::Qt_4_2) {
01558         display.clear();
01559         in >> values;
01560         // move the display value over to the display string list
01561         for (int column = 0; column < values.count(); ++column) {
01562             display << QVariant();
01563             for (int i = 0; i < values.at(column).count(); ++i) {
01564                 if (values.at(column).at(i).role == Qt::DisplayRole) {
01565                     display[column] = values.at(column).at(i).value;
01566                     values[column].remove(i--);
01567                 }
01568             }
01569         }
01570     } else {
01571         in >> values >> display;
01572     }
01573 }
01574 
01580 void QTreeWidgetItem::write(QDataStream &out) const
01581 {
01582     out << values << display;
01583 }
01584 
01595 QTreeWidgetItem::QTreeWidgetItem(const QTreeWidgetItem &other)
01596     : rtti(Type), values(other.values), view(0), display(other.display),
01597       par(0), itemFlags(other.itemFlags)
01598 {
01599 }
01600 
01609 QTreeWidgetItem &QTreeWidgetItem::operator=(const QTreeWidgetItem &other)
01610 {
01611     values = other.values;
01612     display = other.display;
01613     itemFlags = other.itemFlags;
01614     return *this;
01615 }
01616 
01617 #endif // QT_NO_DATASTREAM
01618 
01624 void QTreeWidgetItem::addChild(QTreeWidgetItem *child)
01625 {
01626     insertChild(children.count(), child);
01627 }
01628 
01634 void QTreeWidgetItem::insertChild(int index, QTreeWidgetItem *child)
01635 {
01636     if (index < 0 || index > children.count() || child == 0 || child->view != 0 || child->par != 0)
01637         return;
01638 
01639     if (QTreeModel *model = (view ? ::qobject_cast<QTreeModel*>(view->model()) : 0)) {
01640         if (model->rootItem == this)
01641             child->par = 0;
01642         else
01643             child->par = this;
01644         if (view->isSortingEnabled()) {
01645 #if 0
01646             Qt::SortOrder order = view->header()->sortIndicatorOrder();
01647             QList<QTreeWidgetItem*>::iterator it;
01648             it = model->sortedInsertionIterator(children.begin(), children.end(),
01649                                                 order, child);
01650             index = qMax(it - children.begin(), 0);
01651 #else
01652             // do a delayed sort instead
01653             index = children.count(); // append
01654             model->sortPending = true;
01655 #endif
01656         }
01657         model->beginInsertItems(this, index, 1);
01658         int cols = model->columnCount();
01659         QStack<QTreeWidgetItem*> stack;
01660         stack.push(child);
01661         while (!stack.isEmpty()) {
01662             QTreeWidgetItem *i = stack.pop();
01663             i->view = view;
01664             i->values.reserve(cols);
01665             for (int c = 0; c < i->children.count(); ++c)
01666                 stack.push(i->children.at(c));
01667         }
01668         children.insert(index, child);
01669         model->endInsertItems();
01670     } else {
01671         child->par = this;
01672         children.insert(index, child);
01673     }
01674 }
01675 
01679 QTreeWidgetItem *QTreeWidgetItem::takeChild(int index)
01680 {
01681     if (index >= 0 && index < children.count()) {
01682         QTreeModel *model = (view ? ::qobject_cast<QTreeModel*>(view->model()) : 0);
01683         if (model && model->executePendingSort())
01684             model = 0; // no need to emit signals
01685         if (model) model->beginRemoveItems(this, index, 1);
01686         QTreeWidgetItem *item = children.takeAt(index);
01687         item->par = 0;
01688         QStack<QTreeWidgetItem*> stack;
01689         stack.push(item);
01690         while (!stack.isEmpty()) {
01691             QTreeWidgetItem *i = stack.pop();
01692             i->view = 0;
01693             for (int c = 0; c < i->children.count(); ++c)
01694                 stack.push(i->children.at(c));
01695         }
01696         if (model) model->endRemoveRows();
01697         return item;
01698     }
01699     return 0;
01700 }
01701 
01709 void QTreeWidgetItem::addChildren(const QList<QTreeWidgetItem*> &children)
01710 {
01711     insertChildren(this->children.count(), children);
01712 }
01713 
01721 void QTreeWidgetItem::insertChildren(int index, const QList<QTreeWidgetItem*> &children)
01722 {
01723     if (view && view->isSortingEnabled()) {
01724         for (int n = 0; n < children.count(); ++n)
01725             insertChild(index, children.at(n));
01726         return;
01727     }
01728     QTreeModel *model = (view ? ::qobject_cast<QTreeModel*>(view->model()) : 0);
01729     QStack<QTreeWidgetItem*> stack;
01730     QList<QTreeWidgetItem*> itemsToInsert;
01731     for (int n = 0; n < children.count(); ++n) {
01732         QTreeWidgetItem *child = children.at(n);
01733         if (child->view || child->par)
01734             continue;
01735         itemsToInsert.append(child);
01736         if (view && model) {
01737             if (child->childCount() == 0)
01738                 child->view = view;
01739             else
01740                 stack.push(child);
01741         }
01742         if (model && (model->rootItem == this))
01743             child->par = 0;
01744         else
01745             child->par = this;
01746     }
01747     if (!itemsToInsert.isEmpty()) {
01748         while (!stack.isEmpty()) {
01749             QTreeWidgetItem *i = stack.pop();
01750             i->view = view;
01751             for (int c = 0; c < i->children.count(); ++c)
01752                 stack.push(i->children.at(c));
01753         }
01754         if (model) model->beginInsertItems(this, index, itemsToInsert.count());
01755         for (int n = 0; n < itemsToInsert.count(); ++n)
01756             this->children.insert(index + n, itemsToInsert.at(n));
01757         if (model) model->endInsertItems();
01758     }
01759 }
01760 
01766 QList<QTreeWidgetItem*> QTreeWidgetItem::takeChildren()
01767 {
01768     QList<QTreeWidgetItem*> removed;
01769     if (children.count() > 0) {
01770         QTreeModel *model = (view ? ::qobject_cast<QTreeModel*>(view->model()) : 0);
01771         if (model && model->executePendingSort())
01772             model = 0; // no need to emit signals
01773         if (model) model->beginRemoveItems(this, 0, children.count());
01774         for (int n = 0; n < children.count(); ++n) {
01775             QTreeWidgetItem *item = children.at(n);
01776             item->par = 0;
01777             QStack<QTreeWidgetItem*> stack;
01778             stack.push(item);
01779             while (!stack.isEmpty()) {
01780                 QTreeWidgetItem *i = stack.pop();
01781                 i->view = 0;
01782                 for (int c = 0; c < i->children.count(); ++c)
01783                     stack.push(i->children.at(c));
01784             }
01785         }
01786         removed = children;
01787         children.clear(); // detach
01788         if (model) model->endRemoveItems();
01789     }
01790     return removed;
01791 }
01792 
01800 void QTreeWidgetItem::sortChildren(int column, Qt::SortOrder order, bool climb)
01801 {
01802     QTreeModel *model = (view ? ::qobject_cast<QTreeModel*>(view->model()) : 0);
01803     if (!model)
01804         return;
01805     model->sortItems(&children, column, order);
01806     if (climb) {
01807         QList<QTreeWidgetItem*>::iterator it = children.begin();
01808         for (; it != children.end(); ++it)
01809             (*it)->sortChildren(column, order, climb);
01810     }
01811 }
01812 
01821 QVariant QTreeWidgetItem::childrenCheckState(int column) const
01822 {
01823     if (column < 0)
01824         return QVariant();
01825     int checkedChildrenCount = 0;
01826     int uncheckedChildrenCount = 0;
01827     int validChildrenCount = 0;
01828     for (int i = 0; i < children.count(); ++i) {
01829         QVariant value = children.at(i)->data(column, Qt::CheckStateRole);
01830         if (!value.isValid())
01831             continue;
01832         Qt::CheckState checkState = static_cast<Qt::CheckState>(value.toInt());
01833         if (checkState == Qt::Unchecked)
01834             ++uncheckedChildrenCount;
01835         else
01836             ++checkedChildrenCount; // includes partially checked items
01837         ++validChildrenCount;
01838     }
01839     if (checkedChildrenCount + uncheckedChildrenCount == 0)
01840         return QVariant(); // value was not defined
01841     if (checkedChildrenCount == validChildrenCount)
01842         return Qt::Checked;
01843     if (uncheckedChildrenCount == validChildrenCount)
01844         return Qt::Unchecked;
01845     return Qt::PartiallyChecked;
01846 }
01847 
01851 void QTreeWidgetItem::itemChanged()
01852 {
01853     if (QTreeModel *model = (view ? ::qobject_cast<QTreeModel*>(view->model()) : 0))
01854         model->itemChanged(this);
01855 }
01856 
01860 void QTreeWidgetItem::executePendingSort() const
01861 {
01862     if (QTreeModel *model = (view ? ::qobject_cast<QTreeModel*>(view->model()) : 0))
01863         model->executePendingSort();
01864 }
01865 
01866 
01867 #ifndef QT_NO_DATASTREAM
01868 
01877 QDataStream &operator<<(QDataStream &out, const QTreeWidgetItem &item)
01878 {
01879     item.write(out);
01880     return out;
01881 }
01882 
01892 QDataStream &operator>>(QDataStream &in, QTreeWidgetItem &item)
01893 {
01894     item.read(in);
01895     return in;
01896 }
01897 #endif // QT_NO_DATASTREAM
01898 
01899 class QTreeWidgetPrivate : public QTreeViewPrivate
01900 {
01901     Q_DECLARE_PUBLIC(QTreeWidget)
01902 public:
01903     QTreeWidgetPrivate() : QTreeViewPrivate() {}
01904     inline QTreeModel *model() const
01905         { return ::qobject_cast<QTreeModel*>(q_func()->model()); }
01906     inline QModelIndex index(const QTreeWidgetItem *item, int column = 0) const
01907         { return model()->index(item, column); }
01908     inline QTreeWidgetItem *item(const QModelIndex &index) const
01909         { return model()->item(index); }
01910     void _q_emitItemPressed(const QModelIndex &index);
01911     void _q_emitItemClicked(const QModelIndex &index);
01912     void _q_emitItemDoubleClicked(const QModelIndex &index);
01913     void _q_emitItemActivated(const QModelIndex &index);
01914     void _q_emitItemEntered(const QModelIndex &index);
01915     void _q_emitItemChanged(const QModelIndex &index);
01916     void _q_emitItemExpanded(const QModelIndex &index);
01917     void _q_emitItemCollapsed(const QModelIndex &index);
01918     void _q_emitCurrentItemChanged(const QModelIndex &previous, const QModelIndex &index);
01919     void _q_sort();
01920     void _q_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
01921 };
01922 
01923 void QTreeWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
01924 {
01925     Q_Q(QTreeWidget);
01926     emit q->itemPressed(item(index), index.column());
01927 }
01928 
01929 void QTreeWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
01930 {
01931     Q_Q(QTreeWidget);
01932     emit q->itemClicked(item(index), index.column());
01933 }
01934 
01935 void QTreeWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
01936 {
01937     Q_Q(QTreeWidget);
01938     emit q->itemDoubleClicked(item(index), index.column());
01939 }
01940 
01941 void QTreeWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
01942 {
01943     Q_Q(QTreeWidget);
01944     emit q->itemActivated(item(index), index.column());
01945 }
01946 
01947 void QTreeWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
01948 {
01949     Q_Q(QTreeWidget);
01950     emit q->itemEntered(item(index), index.column());
01951 }
01952 
01953 void QTreeWidgetPrivate::_q_emitItemChanged(const QModelIndex &index)
01954 {
01955     Q_Q(QTreeWidget);
01956     emit q->itemChanged(item(index), index.column());
01957 }
01958 
01959 void QTreeWidgetPrivate::_q_emitItemExpanded(const QModelIndex &index)
01960 {
01961     Q_Q(QTreeWidget);
01962     emit q->itemExpanded(item(index));
01963 }
01964 
01965 void QTreeWidgetPrivate::_q_emitItemCollapsed(const QModelIndex &index)
01966 {
01967     Q_Q(QTreeWidget);
01968     emit q->itemCollapsed(item(index));
01969 }
01970 
01971 void QTreeWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
01972                                                 const QModelIndex &previous)
01973 {
01974     Q_Q(QTreeWidget);
01975     QTreeWidgetItem *currentItem = model()->item(current);
01976     QTreeWidgetItem *previousItem = model()->item(previous);
01977     emit q->currentItemChanged(currentItem, previousItem);
01978 }
01979 
01980 void QTreeWidgetPrivate::_q_sort()
01981 {
01982     Q_Q(QTreeWidget);
01983     if (sortingEnabled) {
01984         int column = q->header()->sortIndicatorSection();
01985         Qt::SortOrder order = q->header()->sortIndicatorOrder();
01986         model()->sort(column, order);
01987     }
01988 }
01989 
01990 void QTreeWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
01991                                         const QModelIndex &bottomRight)
01992 {
01993     Q_Q(QTreeWidget);
01994     if (sortingEnabled && topLeft.isValid() && bottomRight.isValid()
01995         && !model()->sortPending) {
01996         int column = q->header()->sortIndicatorSection();
01997         if (column >= topLeft.column() && column <= bottomRight.column()) {
01998             Qt::SortOrder order = q->header()->sortIndicatorOrder();
01999             model()->ensureSorted(column, order, topLeft.row(),
02000                                   bottomRight.row(), topLeft.parent());
02001         }
02002     }
02003 }
02004 
02169 QTreeWidget::QTreeWidget(QWidget *parent)
02170     : QTreeView(*new QTreeWidgetPrivate(), parent)
02171 {
02172     QTreeView::setModel(new QTreeModel(1, this));
02173     connect(this, SIGNAL(pressed(QModelIndex)),
02174             SLOT(_q_emitItemPressed(QModelIndex)));
02175     connect(this, SIGNAL(clicked(QModelIndex)),
02176             SLOT(_q_emitItemClicked(QModelIndex)));
02177     connect(this, SIGNAL(doubleClicked(QModelIndex)),
02178             SLOT(_q_emitItemDoubleClicked(QModelIndex)));
02179     connect(this, SIGNAL(activated(QModelIndex)),
02180             SLOT(_q_emitItemActivated(QModelIndex)));
02181     connect(this, SIGNAL(entered(QModelIndex)),
02182             SLOT(_q_emitItemEntered(QModelIndex)));
02183     connect(this, SIGNAL(expanded(QModelIndex)),
02184             SLOT(_q_emitItemExpanded(QModelIndex)));
02185     connect(this, SIGNAL(collapsed(QModelIndex)),
02186             SLOT(_q_emitItemCollapsed(QModelIndex)));
02187     connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
02188             this, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex)));
02189     connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
02190             this, SIGNAL(itemSelectionChanged()));
02191     connect(model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
02192             this, SLOT(_q_emitItemChanged(QModelIndex)));
02193     QObject::connect(model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
02194                      this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
02195     QObject::connect(model(), SIGNAL(columnsRemoved(QModelIndex,int,int)),
02196                      this, SLOT(_q_sort()));
02197 
02198     header()->setClickable(false);
02199 }
02200 
02205 QTreeWidget::~QTreeWidget()
02206 {
02207 }
02208 
02209 /*
02210   Retuns the number of header columns in the view.
02211 
02212   \sa sortColumn(), currentColumn(), topLevelItemCount()
02213 */
02214 
02215 int QTreeWidget::columnCount() const
02216 {
02217     Q_D(const QTreeWidget);
02218     return d->model()->columnCount();
02219 }
02220 
02221 /*
02222   Sets the number of header \a columns in the tree widget.
02223 */
02224 
02225 void QTreeWidget::setColumnCount(int columns)
02226 {
02227     Q_D(QTreeWidget);
02228     if (columns < 0)
02229         return;
02230     d->model()->setColumnCount(columns);
02231 }
02232 
02244 QTreeWidgetItem *QTreeWidget::invisibleRootItem() const
02245 {
02246     Q_D(const QTreeWidget);
02247     return d->model()->rootItem;
02248 }
02249 
02257 QTreeWidgetItem *QTreeWidget::topLevelItem(int index) const
02258 {
02259     Q_D(const QTreeWidget);
02260     d->model()->executePendingSort();
02261     return d->model()->rootItem->child(index);
02262 }
02263 
02270 int QTreeWidget::topLevelItemCount() const
02271 {
02272     Q_D(const QTreeWidget);
02273     return d->model()->rootItem->childCount();
02274 }
02275 
02284 void QTreeWidget::insertTopLevelItem(int index, QTreeWidgetItem *item)
02285 {
02286     Q_D(QTreeWidget);
02287     d->model()->rootItem->insertChild(index, item);
02288 }
02289 
02297 void QTreeWidget::addTopLevelItem(QTreeWidgetItem *item)
02298 {
02299     insertTopLevelItem(topLevelItemCount(), item);
02300 }
02301 
02309 QTreeWidgetItem *QTreeWidget::takeTopLevelItem(int index)
02310 {
02311     Q_D(QTreeWidget);
02312     return d->model()->rootItem->takeChild(index);
02313 }
02314 
02318 int QTreeWidget::indexOfTopLevelItem(QTreeWidgetItem *item)
02319 {
02320     Q_D(QTreeWidget);
02321     d->model()->executePendingSort();
02322     return d->model()->rootItem->indexOfChild(item);
02323 }
02324 
02331 int QTreeWidget::indexOfTopLevelItem(QTreeWidgetItem *item) const
02332 {
02333     Q_D(const QTreeWidget);
02334     d->model()->executePendingSort();
02335     return d->model()->rootItem->indexOfChild(item);
02336 }
02337 
02347 void QTreeWidget::insertTopLevelItems(int index, const QList<QTreeWidgetItem*> &items)
02348 {
02349     Q_D(QTreeWidget);
02350     d->model()->rootItem->insertChildren(index, items);
02351 }
02352 
02358 void QTreeWidget::addTopLevelItems(const QList<QTreeWidgetItem*> &items)
02359 {
02360     insertTopLevelItems(topLevelItemCount(), items);
02361 }
02362 
02369 QTreeWidgetItem *QTreeWidget::headerItem() const
02370 {
02371     Q_D(const QTreeWidget);
02372     return d->model()->headerItem;
02373 }
02374 
02384 void QTreeWidget::setHeaderItem(QTreeWidgetItem *item)
02385 {
02386     Q_D(QTreeWidget);
02387     if (!item)
02388         return;
02389     item->view = this;
02390 
02391     int oldCount = columnCount();
02392     if (oldCount < item->columnCount())
02393          d->model()->beginInsertColumns(QModelIndex(), oldCount, item->columnCount());
02394     else
02395          d->model()->beginRemoveColumns(QModelIndex(), item->columnCount(), oldCount);
02396     delete d->model()->headerItem;
02397     d->model()->headerItem = item;
02398     if (oldCount < item->columnCount())
02399         d->model()->endInsertColumns();
02400     else
02401         d->model()->endRemoveColumns();
02402     d->model()->headerDataChanged(Qt::Horizontal, 0, oldCount);
02403 }
02404 
02405 
02414 void QTreeWidget::setHeaderLabels(const QStringList &labels)
02415 {
02416     Q_D(QTreeWidget);
02417     if (columnCount() < labels.count())
02418         setColumnCount(labels.count());
02419     QTreeModel *model = d->model();
02420     QTreeWidgetItem *item = model->headerItem;
02421     for (int i = 0; i < labels.count(); ++i)
02422         item->setText(i, labels.at(i));
02423 }
02424 
02437 QTreeWidgetItem *QTreeWidget::currentItem() const
02438 {
02439     Q_D(const QTreeWidget);
02440     return d->item(currentIndex());
02441 }
02442 
02449 int QTreeWidget::currentColumn() const
02450 {
02451     return currentIndex().column();
02452 }
02453 
02461 void QTreeWidget::setCurrentItem(QTreeWidgetItem *item)
02462 {
02463     setCurrentItem(item, 0);
02464 }
02465 
02472 void QTreeWidget::setCurrentItem(QTreeWidgetItem *item, int column)
02473 {
02474     Q_D(const QTreeWidget);
02475     setCurrentIndex(d->index(item, column));
02476 }
02477 
02483 QTreeWidgetItem *QTreeWidget::itemAt(const QPoint &p) const
02484 {
02485     Q_D(const QTreeWidget);
02486     return d->item(indexAt(p));
02487 }
02488 
02501 QRect QTreeWidget::visualItemRect(const QTreeWidgetItem *item) const
02502 {
02503     Q_D(const QTreeWidget);
02504     return visualRect(d->index(item));
02505 }
02506 
02514 int QTreeWidget::sortColumn() const
02515 {
02516     return header()->sortIndicatorSection();
02517 }
02518 
02526 void QTreeWidget::sortItems(int column, Qt::SortOrder order)
02527 {
02528     Q_D(QTreeWidget);
02529     header()->setSortIndicator(column, order);
02530     d->model()->sort(column, order);
02531 }
02532 
02538 void QTreeWidget::setSortingEnabled(bool enable)
02539 {
02540     QTreeView::setSortingEnabled(enable);
02541 }
02542 
02548 bool QTreeWidget::isSortingEnabled() const
02549 {
02550     return QTreeView::isSortingEnabled();
02551 }
02552 
02557 void QTreeWidget::editItem(QTreeWidgetItem *item, int column)
02558 {
02559     Q_D(QTreeWidget);
02560     edit(d->index(item, column));
02561 }
02562 
02569 void QTreeWidget::openPersistentEditor(QTreeWidgetItem *item, int column)
02570 {
02571     Q_D(QTreeWidget);
02572     QAbstractItemView::openPersistentEditor(d->index(item, column));
02573 }
02574 
02584 void QTreeWidget::closePersistentEditor(QTreeWidgetItem *item, int column)
02585 {
02586     Q_D(QTreeWidget);
02587     QAbstractItemView::closePersistentEditor(d->index(item, column));
02588 }
02589 
02595 QWidget *QTreeWidget::itemWidget(QTreeWidgetItem *item, int column) const
02596 {
02597     Q_D(const QTreeWidget);
02598     return QAbstractItemView::indexWidget(d->index(item, column));
02599 }
02600 
02619 void QTreeWidget::setItemWidget(QTreeWidgetItem *item, int column, QWidget *widget)
02620 {
02621     Q_D(QTreeWidget);
02622     QAbstractItemView::setIndexWidget(d->index(item, column), widget);
02623 }
02624 
02634 bool QTreeWidget::isItemSelected(const QTreeWidgetItem *item) const
02635 {
02636     Q_D(const QTreeWidget);
02637     return selectionModel()->isSelected(d->index(item));
02638 
02639 }
02640 
02651 void QTreeWidget::setItemSelected(const QTreeWidgetItem *item, bool select)
02652 {
02653     Q_D(QTreeWidget);
02654     selectionModel()->select(d->index(item), (select ? QItemSelectionModel::Select
02655                                               : QItemSelectionModel::Deselect)
02656                              |QItemSelectionModel::Rows);
02657 }
02658 
02664 QList<QTreeWidgetItem*> QTreeWidget::selectedItems() const
02665 {
02666     Q_D(const QTreeWidget);
02667     QModelIndexList indexes = selectionModel()->selectedIndexes();
02668     QList<QTreeWidgetItem*> items;
02669     for (int i = 0; i < indexes.count(); ++i) {
02670         QTreeWidgetItem *item = d->item(indexes.at(i));
02671         if (!items.contains(item)) // ### slow, optimize later
02672             items.append(item);
02673     }
02674     return items;
02675 }
02676 
02680 QList<QTreeWidgetItem*> QTreeWidget::findItems(const QString &text, Qt::MatchFlags flags, int column) const
02681 {
02682     Q_D(const QTreeWidget);
02683     QModelIndexList indexes = d->model()->match(model()->index(0, column, QModelIndex()),
02684                                                 Qt::DisplayRole, text, -1, flags);
02685     QList<QTreeWidgetItem*> items;
02686     for (int i = 0; i < indexes.size(); ++i)
02687         items.append(d->item(indexes.at(i)));
02688     return items;
02689 }
02690 
02698 bool QTreeWidget::isItemHidden(const QTreeWidgetItem *item) const
02699 {
02700     Q_D(const QTreeWidget);
02701     if (item == d->model()->headerItem)
02702         return header()->isHidden();
02703     const QModelIndex index = d->index(item);
02704     return isRowHidden(index.row(), index.parent());
02705 }
02706 
02716 void QTreeWidget::setItemHidden(const QTreeWidgetItem *item, bool hide)
02717 {
02718     Q_D(QTreeWidget);
02719     if (item == d->model()->headerItem) {
02720         header()->setHidden(hide);
02721     } else {
02722         const QModelIndex index = d->index(item);
02723         setRowHidden(index.row(), index.parent(), hide);
02724     }
02725 }
02726 
02736 bool QTreeWidget::isItemExpanded(const QTreeWidgetItem *item) const
02737 {
02738     Q_D(const QTreeWidget);
02739     return isExpanded(d->index(item));
02740 }
02741 
02752 void QTreeWidget::setItemExpanded(const QTreeWidgetItem *item, bool expand)
02753 {
02754     Q_D(QTreeWidget);
02755     setExpanded(d->index(item), expand);
02756 }
02757 
02764 void QTreeWidget::scrollToItem(const QTreeWidgetItem *item, QAbstractItemView::ScrollHint hint)
02765 {
02766     Q_D(QTreeWidget);
02767     QTreeView::scrollTo(d->index(item), hint);
02768 }
02769 
02776 void QTreeWidget::expandItem(const QTreeWidgetItem *item)
02777 {
02778     Q_D(QTreeWidget);
02779     expand(d->index(item));
02780 }
02781 
02788 void QTreeWidget::collapseItem(const QTreeWidgetItem *item)
02789 {
02790     Q_D(QTreeWidget);
02791     collapse(d->index(item));
02792 }
02793 
02803 void QTreeWidget::clear()
02804 {
02805     Q_D(QTreeWidget);
02806     selectionModel()->clear();
02807     d->model()->clear();
02808 }
02809 
02816 QStringList QTreeWidget::mimeTypes() const
02817 {
02818     return model()->QAbstractItemModel::mimeTypes();
02819 }
02820 
02829 QMimeData *QTreeWidget::mimeData(const QList<QTreeWidgetItem*>) const
02830 {
02831     return d_func()->model()->internalMimeData();
02832 }
02833 
02844 bool QTreeWidget::dropMimeData(QTreeWidgetItem *parent, int index,
02845                                const QMimeData *data, Qt::DropAction action)
02846 {
02847     QModelIndex idx;
02848     if (parent) idx = indexFromItem(parent);
02849     return model()->QAbstractItemModel::dropMimeData(data, action , index, 0, idx);
02850 }
02851 
02857 Qt::DropActions QTreeWidget::supportedDropActions() const
02858 {
02859     return model()->QAbstractItemModel::supportedDropActions() | Qt::MoveAction;
02860 }
02861 
02868 QList<QTreeWidgetItem*> QTreeWidget::items(const QMimeData *data) const
02869 {
02870     const QTreeWidgetMimeData *twd = qobject_cast<const QTreeWidgetMimeData*>(data);
02871     if (twd)
02872         return twd->items;
02873     return QList<QTreeWidgetItem*>();
02874 }
02875 
02881 QModelIndex QTreeWidget::indexFromItem(QTreeWidgetItem *item, int column) const
02882 {
02883     Q_D(const QTreeWidget);
02884     return d->index(item, column);
02885 }
02886 
02892 QTreeWidgetItem *QTreeWidget::itemFromIndex(const QModelIndex &index) const
02893 {
02894     Q_D(const QTreeWidget);
02895     return d->item(index);
02896 }
02897 
02898 #ifndef QT_NO_DRAGANDDROP
02899 
02900 void QTreeWidget::dropEvent(QDropEvent *event) {
02901     Q_D(QTreeWidget);
02902     if (event->source() == this && (event->proposedAction() == Qt::MoveAction ||
02903                                     dragDropMode() == QAbstractItemView::InternalMove)) {
02904         QModelIndex topIndex;
02905         int col = -1;
02906         int row = -1;
02907         if (d->dropOn(event, &row, &col, &topIndex)) {
02908             QList<QModelIndex> idxs = selectedIndexes();
02909             QList<QPersistentModelIndex> indexes;
02910             for (int i = 0; i < idxs.count(); i++)
02911                 indexes.append(idxs.at(i));
02912 
02913             if (indexes.contains(topIndex))
02914                 return;
02915 
02916             // When removing items the drop location could shift
02917             QPersistentModelIndex dropRow = model()->index(row, col, topIndex);
02918 
02919             // Remove the items
02920             QList<QTreeWidgetItem *> taken;
02921             for (int i = indexes.count() - 1; i >= 0; --i) {
02922                 QTreeWidgetItem *parent = itemFromIndex(indexes.at(i));
02923                 if (!parent || !parent->parent()) {
02924                     taken.append(takeTopLevelItem(indexes.at(i).row()));
02925                 } else {
02926                     taken.append(parent->parent()->takeChild(indexes.at(i).row()));
02927                 }
02928             }
02929 
02930             // insert them back in at their new positions
02931             for (int i = 0; i < indexes.count(); ++i) {
02932                 // Either at a specific point or appended
02933                 if (row == -1) {
02934                     if (topIndex.isValid()) {
02935                         QTreeWidgetItem *parent = itemFromIndex(topIndex);
02936                         parent->insertChild(parent->childCount(), taken.takeFirst());
02937                     } else {
02938                         insertTopLevelItem(topLevelItemCount(), taken.takeFirst());
02939                     }
02940                 } else {
02941                     int r = dropRow.row() >= 0 ? dropRow.row() : row;
02942                     if (topIndex.isValid()) {
02943                         QTreeWidgetItem *parent = itemFromIndex(topIndex);
02944                         parent->insertChild(qMin(r, parent->childCount()), taken.takeFirst());
02945                     } else {
02946                         insertTopLevelItem(qMin(r, topLevelItemCount()), taken.takeFirst());
02947                     }
02948                 }
02949             }
02950 
02951             event->accept();
02952             // Don't want QAbstractItemView to delete it because it was "moved" we already did it
02953             event->setDropAction(Qt::CopyAction);
02954         }
02955     }
02956 
02957     QTreeView::dropEvent(event);
02958 }
02959 #endif
02960 
02965 void QTreeWidget::setModel(QAbstractItemModel * /*model*/)
02966 {
02967     qFatal("QTreeWidget::setModel() - Changing the model of the QTreeWidget is not allowed.");
02968 }
02969 
02973 bool QTreeWidget::event(QEvent *e)
02974 {
02975     return QTreeView::event(e);
02976 }
02977 
02978 #include "moc_qtreewidget.cpp"
02979 #endif // QT_NO_TREEWIDGET

Generated on Thu Mar 15 11:55:01 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1