summaryrefslogtreecommitdiffstats
path: root/src/gui/itemviews/qtreeview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/itemviews/qtreeview.cpp')
-rw-r--r--src/gui/itemviews/qtreeview.cpp3755
1 files changed, 0 insertions, 3755 deletions
diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp
deleted file mode 100644
index 21c9d3b31a..0000000000
--- a/src/gui/itemviews/qtreeview.cpp
+++ /dev/null
@@ -1,3755 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#include "qtreeview.h"
-
-#ifndef QT_NO_TREEVIEW
-#include <qheaderview.h>
-#include <qitemdelegate.h>
-#include <qapplication.h>
-#include <qscrollbar.h>
-#include <qpainter.h>
-#include <qstack.h>
-#include <qstyle.h>
-#include <qstyleoption.h>
-#include <qevent.h>
-#include <qpen.h>
-#include <qdebug.h>
-#ifndef QT_NO_ACCESSIBILITY
-#include <qaccessible.h>
-#endif
-
-#include <private/qtreeview_p.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QTreeView
- \brief The QTreeView class provides a default model/view implementation of a tree view.
-
- \ingroup model-view
- \ingroup advanced
-
-
- A QTreeView implements a tree representation of items from a
- model. This class is used to provide standard hierarchical lists that
- were previously provided by the \c QListView class, but using the more
- flexible approach provided by Qt's model/view architecture.
-
- The QTreeView class is one of the \l{Model/View Classes} and is part of
- Qt's \l{Model/View Programming}{model/view framework}.
-
- QTreeView implements the interfaces defined by the
- QAbstractItemView class to allow it to display data provided by
- models derived from the QAbstractItemModel class.
-
- It is simple to construct a tree view displaying data from a
- model. In the following example, the contents of a directory are
- supplied by a QDirModel and displayed as a tree:
-
- \snippet doc/src/snippets/shareddirmodel/main.cpp 3
- \snippet doc/src/snippets/shareddirmodel/main.cpp 6
-
- The model/view architecture ensures that the contents of the tree view
- are updated as the model changes.
-
- Items that have children can be in an expanded (children are
- visible) or collapsed (children are hidden) state. When this state
- changes a collapsed() or expanded() signal is emitted with the
- model index of the relevant item.
-
- The amount of indentation used to indicate levels of hierarchy is
- controlled by the \l indentation property.
-
- Headers in tree views are constructed using the QHeaderView class and can
- be hidden using \c{header()->hide()}. Note that each header is configured
- with its \l{QHeaderView::}{stretchLastSection} property set to true,
- ensuring that the view does not waste any of the space assigned to it for
- its header. If this value is set to true, this property will override the
- resize mode set on the last section in the header.
-
-
- \section1 Key Bindings
-
- QTreeView supports a set of key bindings that enable the user to
- navigate in the view and interact with the contents of items:
-
- \table
- \header \o Key \o Action
- \row \o Up \o Moves the cursor to the item in the same column on
- the previous row. If the parent of the current item has no more rows to
- navigate to, the cursor moves to the relevant item in the last row
- of the sibling that precedes the parent.
- \row \o Down \o Moves the cursor to the item in the same column on
- the next row. If the parent of the current item has no more rows to
- navigate to, the cursor moves to the relevant item in the first row
- of the sibling that follows the parent.
- \row \o Left \o Hides the children of the current item (if present)
- by collapsing a branch.
- \row \o Minus \o Same as LeftArrow.
- \row \o Right \o Reveals the children of the current item (if present)
- by expanding a branch.
- \row \o Plus \o Same as RightArrow.
- \row \o Asterisk \o Expands all children of the current item (if present).
- \row \o PageUp \o Moves the cursor up one page.
- \row \o PageDown \o Moves the cursor down one page.
- \row \o Home \o Moves the cursor to an item in the same column of the first
- row of the first top-level item in the model.
- \row \o End \o Moves the cursor to an item in the same column of the last
- row of the last top-level item in the model.
- \row \o F2 \o In editable models, this opens the current item for editing.
- The Escape key can be used to cancel the editing process and revert
- any changes to the data displayed.
- \endtable
-
- \omit
- Describe the expanding/collapsing concept if not covered elsewhere.
- \endomit
-
- \table 100%
- \row \o \inlineimage windowsxp-treeview.png Screenshot of a Windows XP style tree view
- \o \inlineimage macintosh-treeview.png Screenshot of a Macintosh style tree view
- \o \inlineimage plastique-treeview.png Screenshot of a Plastique style tree view
- \row \o A \l{Windows XP Style Widget Gallery}{Windows XP style} tree view.
- \o A \l{Macintosh Style Widget Gallery}{Macintosh style} tree view.
- \o A \l{Plastique Style Widget Gallery}{Plastique style} tree view.
- \endtable
-
- \section1 Improving Performance
-
- It is possible to give the view hints about the data it is handling in order
- to improve its performance when displaying large numbers of items. One approach
- that can be taken for views that are intended to display items with equal heights
- is to set the \l uniformRowHeights property to true.
-
- \sa QListView, QTreeWidget, {View Classes}, QAbstractItemModel, QAbstractItemView,
- {Dir View Example}
-*/
-
-
-/*!
- \fn void QTreeView::expanded(const QModelIndex &index)
-
- This signal is emitted when the item specified by \a index is expanded.
-*/
-
-
-/*!
- \fn void QTreeView::collapsed(const QModelIndex &index)
-
- This signal is emitted when the item specified by \a index is collapsed.
-*/
-
-/*!
- Constructs a tree view with a \a parent to represent a model's
- data. Use setModel() to set the model.
-
- \sa QAbstractItemModel
-*/
-QTreeView::QTreeView(QWidget *parent)
- : QAbstractItemView(*new QTreeViewPrivate, parent)
-{
- Q_D(QTreeView);
- d->initialize();
-}
-
-/*!
- \internal
-*/
-QTreeView::QTreeView(QTreeViewPrivate &dd, QWidget *parent)
- : QAbstractItemView(dd, parent)
-{
- Q_D(QTreeView);
- d->initialize();
-}
-
-/*!
- Destroys the tree view.
-*/
-QTreeView::~QTreeView()
-{
-}
-
-/*!
- \reimp
-*/
-void QTreeView::setModel(QAbstractItemModel *model)
-{
- Q_D(QTreeView);
- if (model == d->model)
- return;
- if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
- disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(rowsRemoved(QModelIndex,int,int)));
-
- disconnect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_modelAboutToBeReset()));
- }
-
- if (d->selectionModel) { // support row editing
- disconnect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
- d->model, SLOT(submit()));
- disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(rowsRemoved(QModelIndex,int,int)));
- disconnect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_modelAboutToBeReset()));
- }
- d->viewItems.clear();
- d->expandedIndexes.clear();
- d->hiddenIndexes.clear();
- d->header->setModel(model);
- QAbstractItemView::setModel(model);
-
- // QAbstractItemView connects to a private slot
- disconnect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
- // do header layout after the tree
- disconnect(d->model, SIGNAL(layoutChanged()),
- d->header, SLOT(_q_layoutChanged()));
- // QTreeView has a public slot for this
- connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(rowsRemoved(QModelIndex,int,int)));
-
- connect(d->model, SIGNAL(modelAboutToBeReset()), SLOT(_q_modelAboutToBeReset()));
-
- if (d->sortingEnabled)
- d->_q_sortIndicatorChanged(header()->sortIndicatorSection(), header()->sortIndicatorOrder());
-}
-
-/*!
- \reimp
-*/
-void QTreeView::setRootIndex(const QModelIndex &index)
-{
- Q_D(QTreeView);
- d->header->setRootIndex(index);
- QAbstractItemView::setRootIndex(index);
-}
-
-/*!
- \reimp
-*/
-void QTreeView::setSelectionModel(QItemSelectionModel *selectionModel)
-{
- Q_D(QTreeView);
- Q_ASSERT(selectionModel);
- if (d->selectionModel) {
- // support row editing
- disconnect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
- d->model, SLOT(submit()));
- }
-
- d->header->setSelectionModel(selectionModel);
- QAbstractItemView::setSelectionModel(selectionModel);
-
- if (d->selectionModel) {
- // support row editing
- connect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
- d->model, SLOT(submit()));
- }
-}
-
-/*!
- Returns the header for the tree view.
-
- \sa QAbstractItemModel::headerData()
-*/
-QHeaderView *QTreeView::header() const
-{
- Q_D(const QTreeView);
- return d->header;
-}
-
-/*!
- Sets the header for the tree view, to the given \a header.
-
- The view takes ownership over the given \a header and deletes it
- when a new header is set.
-
- \sa QAbstractItemModel::headerData()
-*/
-void QTreeView::setHeader(QHeaderView *header)
-{
- Q_D(QTreeView);
- if (header == d->header || !header)
- return;
- if (d->header && d->header->parent() == this)
- delete d->header;
- d->header = header;
- d->header->setParent(this);
-
- if (!d->header->model()) {
- d->header->setModel(d->model);
- if (d->selectionModel)
- d->header->setSelectionModel(d->selectionModel);
- }
-
- connect(d->header, SIGNAL(sectionResized(int,int,int)),
- this, SLOT(columnResized(int,int,int)));
- connect(d->header, SIGNAL(sectionMoved(int,int,int)),
- this, SLOT(columnMoved()));
- connect(d->header, SIGNAL(sectionCountChanged(int,int)),
- this, SLOT(columnCountChanged(int,int)));
- connect(d->header, SIGNAL(sectionHandleDoubleClicked(int)),
- this, SLOT(resizeColumnToContents(int)));
- connect(d->header, SIGNAL(geometriesChanged()),
- this, SLOT(updateGeometries()));
-
- setSortingEnabled(d->sortingEnabled);
-}
-
-/*!
- \property QTreeView::autoExpandDelay
- \brief The delay time before items in a tree are opened during a drag and drop operation.
- \since 4.3
-
- This property holds the amount of time in milliseconds that the user must wait over
- a node before that node will automatically open or close. If the time is
- set to less then 0 then it will not be activated.
-
- By default, this property has a value of -1, meaning that auto-expansion is disabled.
-*/
-int QTreeView::autoExpandDelay() const
-{
- Q_D(const QTreeView);
- return d->autoExpandDelay;
-}
-
-void QTreeView::setAutoExpandDelay(int delay)
-{
- Q_D(QTreeView);
- d->autoExpandDelay = delay;
-}
-
-/*!
- \property QTreeView::indentation
- \brief indentation of the items in the tree view.
-
- This property holds the indentation measured in pixels of the items for each
- level in the tree view. For top-level items, the indentation specifies the
- horizontal distance from the viewport edge to the items in the first column;
- for child items, it specifies their indentation from their parent items.
-
- By default, this property has a value of 20.
-*/
-int QTreeView::indentation() const
-{
- Q_D(const QTreeView);
- return d->indent;
-}
-
-void QTreeView::setIndentation(int i)
-{
- Q_D(QTreeView);
- if (i != d->indent) {
- d->indent = i;
- d->viewport->update();
- }
-}
-
-/*!
- \property QTreeView::rootIsDecorated
- \brief whether to show controls for expanding and collapsing top-level items
-
- Items with children are typically shown with controls to expand and collapse
- them, allowing their children to be shown or hidden. If this property is
- false, these controls are not shown for top-level items. This can be used to
- make a single level tree structure appear like a simple list of items.
-
- By default, this property is true.
-*/
-bool QTreeView::rootIsDecorated() const
-{
- Q_D(const QTreeView);
- return d->rootDecoration;
-}
-
-void QTreeView::setRootIsDecorated(bool show)
-{
- Q_D(QTreeView);
- if (show != d->rootDecoration) {
- d->rootDecoration = show;
- d->viewport->update();
- }
-}
-
-/*!
- \property QTreeView::uniformRowHeights
- \brief whether all items in the treeview have the same height
-
- This property should only be set to true if it is guaranteed that all items
- in the view has the same height. This enables the view to do some
- optimizations.
-
- The height is obtained from the first item in the view. It is updated
- when the data changes on that item.
-
- By default, this property is false.
-*/
-bool QTreeView::uniformRowHeights() const
-{
- Q_D(const QTreeView);
- return d->uniformRowHeights;
-}
-
-void QTreeView::setUniformRowHeights(bool uniform)
-{
- Q_D(QTreeView);
- d->uniformRowHeights = uniform;
-}
-
-/*!
- \property QTreeView::itemsExpandable
- \brief whether the items are expandable by the user.
-
- This property holds whether the user can expand and collapse items
- interactively.
-
- By default, this property is true.
-
-*/
-bool QTreeView::itemsExpandable() const
-{
- Q_D(const QTreeView);
- return d->itemsExpandable;
-}
-
-void QTreeView::setItemsExpandable(bool enable)
-{
- Q_D(QTreeView);
- d->itemsExpandable = enable;
-}
-
-/*!
- \property QTreeView::expandsOnDoubleClick
- \since 4.4
- \brief whether the items can be expanded by double-clicking.
-
- This property holds whether the user can expand and collapse items
- by double-clicking. The default value is true.
-
- \sa itemsExpandable
-*/
-bool QTreeView::expandsOnDoubleClick() const
-{
- Q_D(const QTreeView);
- return d->expandsOnDoubleClick;
-}
-
-void QTreeView::setExpandsOnDoubleClick(bool enable)
-{
- Q_D(QTreeView);
- d->expandsOnDoubleClick = enable;
-}
-
-/*!
- Returns the horizontal position of the \a column in the viewport.
-*/
-int QTreeView::columnViewportPosition(int column) const
-{
- Q_D(const QTreeView);
- return d->header->sectionViewportPosition(column);
-}
-
-/*!
- Returns the width of the \a column.
-
- \sa resizeColumnToContents(), setColumnWidth()
-*/
-int QTreeView::columnWidth(int column) const
-{
- Q_D(const QTreeView);
- return d->header->sectionSize(column);
-}
-
-/*!
- \since 4.2
-
- Sets the width of the given \a column to the \a width specified.
-
- \sa columnWidth(), resizeColumnToContents()
-*/
-void QTreeView::setColumnWidth(int column, int width)
-{
- Q_D(QTreeView);
- d->header->resizeSection(column, width);
-}
-
-/*!
- Returns the column in the tree view whose header covers the \a x
- coordinate given.
-*/
-int QTreeView::columnAt(int x) const
-{
- Q_D(const QTreeView);
- return d->header->logicalIndexAt(x);
-}
-
-/*!
- Returns true if the \a column is hidden; otherwise returns false.
-
- \sa hideColumn(), isRowHidden()
-*/
-bool QTreeView::isColumnHidden(int column) const
-{
- Q_D(const QTreeView);
- return d->header->isSectionHidden(column);
-}
-
-/*!
- If \a hide is true the \a column is hidden, otherwise the \a column is shown.
-
- \sa hideColumn(), setRowHidden()
-*/
-void QTreeView::setColumnHidden(int column, bool hide)
-{
- Q_D(QTreeView);
- if (column < 0 || column >= d->header->count())
- return;
- d->header->setSectionHidden(column, hide);
-}
-
-/*!
- \property QTreeView::headerHidden
- \brief whether the header is shown or not.
- \since 4.4
-
- If this property is true, the header is not shown otherwise it is.
- The default value is false.
-
- \sa header()
-*/
-bool QTreeView::isHeaderHidden() const
-{
- Q_D(const QTreeView);
- return d->header->isHidden();
-}
-
-void QTreeView::setHeaderHidden(bool hide)
-{
- Q_D(QTreeView);
- d->header->setHidden(hide);
-}
-
-/*!
- Returns true if the item in the given \a row of the \a parent is hidden;
- otherwise returns false.
-
- \sa setRowHidden(), isColumnHidden()
-*/
-bool QTreeView::isRowHidden(int row, const QModelIndex &parent) const
-{
- Q_D(const QTreeView);
- if (!d->model)
- return false;
- return d->isRowHidden(d->model->index(row, 0, parent));
-}
-
-/*!
- If \a hide is true the \a row with the given \a parent is hidden, otherwise the \a row is shown.
-
- \sa isRowHidden(), setColumnHidden()
-*/
-void QTreeView::setRowHidden(int row, const QModelIndex &parent, bool hide)
-{
- Q_D(QTreeView);
- if (!d->model)
- return;
- QModelIndex index = d->model->index(row, 0, parent);
- if (!index.isValid())
- return;
-
- if (hide) {
- d->hiddenIndexes.insert(index);
- } else if(d->isPersistent(index)) { //if the index is not persistent, it cannot be in the set
- d->hiddenIndexes.remove(index);
- }
-
- d->doDelayedItemsLayout();
-}
-
-/*!
- \since 4.3
-
- Returns true if the item in first column in the given \a row
- of the \a parent is spanning all the columns; otherwise returns false.
-
- \sa setFirstColumnSpanned()
-*/
-bool QTreeView::isFirstColumnSpanned(int row, const QModelIndex &parent) const
-{
- Q_D(const QTreeView);
- if (d->spanningIndexes.isEmpty() || !d->model)
- return false;
- QModelIndex index = d->model->index(row, 0, parent);
- for (int i = 0; i < d->spanningIndexes.count(); ++i)
- if (d->spanningIndexes.at(i) == index)
- return true;
- return false;
-}
-
-/*!
- \since 4.3
-
- If \a span is true the item in the first column in the \a row
- with the given \a parent is set to span all columns, otherwise all items
- on the \a row are shown.
-
- \sa isFirstColumnSpanned()
-*/
-void QTreeView::setFirstColumnSpanned(int row, const QModelIndex &parent, bool span)
-{
- Q_D(QTreeView);
- if (!d->model)
- return;
- QModelIndex index = d->model->index(row, 0, parent);
- if (!index.isValid())
- return;
-
- if (span) {
- QPersistentModelIndex persistent(index);
- if (!d->spanningIndexes.contains(persistent))
- d->spanningIndexes.append(persistent);
- } else {
- QPersistentModelIndex persistent(index);
- int i = d->spanningIndexes.indexOf(persistent);
- if (i >= 0)
- d->spanningIndexes.remove(i);
- }
-
- d->executePostedLayout();
- int i = d->viewIndex(index);
- if (i >= 0)
- d->viewItems[i].spanning = span;
-
- d->viewport->update();
-}
-
-/*!
- \reimp
-*/
-void QTreeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
-{
- Q_D(QTreeView);
-
- // if we are going to do a complete relayout anyway, there is no need to update
- if (d->delayedPendingLayout)
- return;
-
- // refresh the height cache here; we don't really lose anything by getting the size hint,
- // since QAbstractItemView::dataChanged() will get the visualRect for the items anyway
-
- bool sizeChanged = false;
- int topViewIndex = d->viewIndex(topLeft);
- if (topViewIndex == 0) {
- int newDefaultItemHeight = indexRowSizeHint(topLeft);
- sizeChanged = d->defaultItemHeight != newDefaultItemHeight;
- d->defaultItemHeight = newDefaultItemHeight;
- }
-
- if (topViewIndex != -1) {
- if (topLeft.row() == bottomRight.row()) {
- int oldHeight = d->itemHeight(topViewIndex);
- d->invalidateHeightCache(topViewIndex);
- sizeChanged |= (oldHeight != d->itemHeight(topViewIndex));
- if (topLeft.column() == 0)
- d->viewItems[topViewIndex].hasChildren = d->hasVisibleChildren(topLeft);
- } else {
- int bottomViewIndex = d->viewIndex(bottomRight);
- for (int i = topViewIndex; i <= bottomViewIndex; ++i) {
- int oldHeight = d->itemHeight(i);
- d->invalidateHeightCache(i);
- sizeChanged |= (oldHeight != d->itemHeight(i));
- if (topLeft.column() == 0)
- d->viewItems[i].hasChildren = d->hasVisibleChildren(d->viewItems.at(i).index);
- }
- }
- }
-
- if (sizeChanged) {
- d->updateScrollBars();
- d->viewport->update();
- }
- QAbstractItemView::dataChanged(topLeft, bottomRight);
-}
-
-/*!
- Hides the \a column given.
-
- \note This function should only be called after the model has been
- initialized, as the view needs to know the number of columns in order to
- hide \a column.
-
- \sa showColumn(), setColumnHidden()
-*/
-void QTreeView::hideColumn(int column)
-{
- Q_D(QTreeView);
- d->header->hideSection(column);
-}
-
-/*!
- Shows the given \a column in the tree view.
-
- \sa hideColumn(), setColumnHidden()
-*/
-void QTreeView::showColumn(int column)
-{
- Q_D(QTreeView);
- d->header->showSection(column);
-}
-
-/*!
- \fn void QTreeView::expand(const QModelIndex &index)
-
- Expands the model item specified by the \a index.
-
- \sa expanded()
-*/
-void QTreeView::expand(const QModelIndex &index)
-{
- Q_D(QTreeView);
- if (!d->isIndexValid(index))
- return;
- if (d->delayedPendingLayout) {
- //A complete relayout is going to be performed, just store the expanded index, no need to layout.
- if (d->storeExpanded(index))
- emit expanded(index);
- return;
- }
-
- int i = d->viewIndex(index);
- if (i != -1) { // is visible
- d->expand(i, true);
- if (!d->isAnimating()) {
- updateGeometries();
- d->viewport->update();
- }
- } else if (d->storeExpanded(index)) {
- emit expanded(index);
- }
-}
-
-/*!
- \fn void QTreeView::collapse(const QModelIndex &index)
-
- Collapses the model item specified by the \a index.
-
- \sa collapsed()
-*/
-void QTreeView::collapse(const QModelIndex &index)
-{
- Q_D(QTreeView);
- if (!d->isIndexValid(index))
- return;
- //if the current item is now invisible, the autoscroll will expand the tree to see it, so disable the autoscroll
- d->delayedAutoScroll.stop();
-
- if (d->delayedPendingLayout) {
- //A complete relayout is going to be performed, just un-store the expanded index, no need to layout.
- if (d->isPersistent(index) && d->expandedIndexes.remove(index))
- emit collapsed(index);
- return;
- }
- int i = d->viewIndex(index);
- if (i != -1) { // is visible
- d->collapse(i, true);
- if (!d->isAnimating()) {
- updateGeometries();
- viewport()->update();
- }
- } else {
- if (d->isPersistent(index) && d->expandedIndexes.remove(index))
- emit collapsed(index);
- }
-}
-
-/*!
- \fn bool QTreeView::isExpanded(const QModelIndex &index) const
-
- Returns true if the model item \a index is expanded; otherwise returns
- false.
-
- \sa expand(), expanded(), setExpanded()
-*/
-bool QTreeView::isExpanded(const QModelIndex &index) const
-{
- Q_D(const QTreeView);
- return d->isIndexExpanded(index);
-}
-
-/*!
- Sets the item referred to by \a index to either collapse or expanded,
- depending on the value of \a expanded.
-
- \sa expanded(), expand(), isExpanded()
-*/
-void QTreeView::setExpanded(const QModelIndex &index, bool expanded)
-{
- if (expanded)
- this->expand(index);
- else
- this->collapse(index);
-}
-
-/*!
- \since 4.2
- \property QTreeView::sortingEnabled
- \brief whether sorting is enabled
-
- If this property is true, sorting is enabled for the tree; if the property
- is false, sorting is not enabled. The default value is false.
-
- \note In order to avoid performance issues, it is recommended that
- sorting is enabled \e after inserting the items into the tree.
- Alternatively, you could also insert the items into a list before inserting
- the items into the tree.
-
- \sa sortByColumn()
-*/
-
-void QTreeView::setSortingEnabled(bool enable)
-{
- Q_D(QTreeView);
- header()->setSortIndicatorShown(enable);
- header()->setClickable(enable);
- if (enable) {
- //sortByColumn has to be called before we connect or set the sortingEnabled flag
- // because otherwise it will not call sort on the model.
- sortByColumn(header()->sortIndicatorSection(), header()->sortIndicatorOrder());
- connect(header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
- this, SLOT(_q_sortIndicatorChanged(int,Qt::SortOrder)), Qt::UniqueConnection);
- } else {
- disconnect(header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
- this, SLOT(_q_sortIndicatorChanged(int,Qt::SortOrder)));
- }
- d->sortingEnabled = enable;
-}
-
-bool QTreeView::isSortingEnabled() const
-{
- Q_D(const QTreeView);
- return d->sortingEnabled;
-}
-
-/*!
- \since 4.2
- \property QTreeView::animated
- \brief whether animations are enabled
-
- If this property is true the treeview will animate expandsion
- and collasping of branches. If this property is false, the treeview
- will expand or collapse branches immediately without showing
- the animation.
-
- By default, this property is false.
-*/
-
-void QTreeView::setAnimated(bool animate)
-{
- Q_D(QTreeView);
- d->animationsEnabled = animate;
-}
-
-bool QTreeView::isAnimated() const
-{
- Q_D(const QTreeView);
- return d->animationsEnabled;
-}
-
-/*!
- \since 4.2
- \property QTreeView::allColumnsShowFocus
- \brief whether items should show keyboard focus using all columns
-
- If this property is true all columns will show focus, otherwise only
- one column will show focus.
-
- The default is false.
-*/
-
-void QTreeView::setAllColumnsShowFocus(bool enable)
-{
- Q_D(QTreeView);
- if (d->allColumnsShowFocus == enable)
- return;
- d->allColumnsShowFocus = enable;
- d->viewport->update();
-}
-
-bool QTreeView::allColumnsShowFocus() const
-{
- Q_D(const QTreeView);
- return d->allColumnsShowFocus;
-}
-
-/*!
- \property QTreeView::wordWrap
- \brief the item text word-wrapping policy
- \since 4.3
-
- If this property is true then the item text is wrapped where
- necessary at word-breaks; otherwise it is not wrapped at all.
- This property is false by default.
-
- Note that even if wrapping is enabled, the cell will not be
- expanded to fit all text. Ellipsis will be inserted according to
- the current \l{QAbstractItemView::}{textElideMode}.
-*/
-void QTreeView::setWordWrap(bool on)
-{
- Q_D(QTreeView);
- if (d->wrapItemText == on)
- return;
- d->wrapItemText = on;
- d->doDelayedItemsLayout();
-}
-
-bool QTreeView::wordWrap() const
-{
- Q_D(const QTreeView);
- return d->wrapItemText;
-}
-
-
-/*!
- \reimp
- */
-void QTreeView::keyboardSearch(const QString &search)
-{
- Q_D(QTreeView);
- if (!d->model->rowCount(d->root) || !d->model->columnCount(d->root))
- return;
-
- QModelIndex start;
- if (currentIndex().isValid())
- start = currentIndex();
- else
- start = d->model->index(0, 0, d->root);
-
- bool skipRow = false;
- bool keyboardTimeWasValid = d->keyboardInputTime.isValid();
- qint64 keyboardInputTimeElapsed = d->keyboardInputTime.restart();
- if (search.isEmpty() || !keyboardTimeWasValid
- || keyboardInputTimeElapsed > QApplication::keyboardInputInterval()) {
- d->keyboardInput = search;
- skipRow = currentIndex().isValid(); //if it is not valid we should really start at QModelIndex(0,0)
- } else {
- d->keyboardInput += search;
- }
-
- // special case for searches with same key like 'aaaaa'
- bool sameKey = false;
- if (d->keyboardInput.length() > 1) {
- int c = d->keyboardInput.count(d->keyboardInput.at(d->keyboardInput.length() - 1));
- sameKey = (c == d->keyboardInput.length());
- if (sameKey)
- skipRow = true;
- }
-
- // skip if we are searching for the same key or a new search started
- if (skipRow) {
- if (indexBelow(start).isValid())
- start = indexBelow(start);
- else
- start = d->model->index(0, start.column(), d->root);
- }
-
- d->executePostedLayout();
- int startIndex = d->viewIndex(start);
- if (startIndex <= -1)
- return;
-
- int previousLevel = -1;
- int bestAbove = -1;
- int bestBelow = -1;
- QString searchString = sameKey ? QString(d->keyboardInput.at(0)) : d->keyboardInput;
- for (int i = 0; i < d->viewItems.count(); ++i) {
- if ((int)d->viewItems.at(i).level > previousLevel) {
- QModelIndex searchFrom = d->viewItems.at(i).index;
- if (searchFrom.parent() == start.parent())
- searchFrom = start;
- QModelIndexList match = d->model->match(searchFrom, Qt::DisplayRole, searchString);
- if (match.count()) {
- int hitIndex = d->viewIndex(match.at(0));
- if (hitIndex >= 0 && hitIndex < startIndex)
- bestAbove = bestAbove == -1 ? hitIndex : qMin(hitIndex, bestAbove);
- else if (hitIndex >= startIndex)
- bestBelow = bestBelow == -1 ? hitIndex : qMin(hitIndex, bestBelow);
- }
- }
- previousLevel = d->viewItems.at(i).level;
- }
-
- QModelIndex index;
- if (bestBelow > -1)
- index = d->viewItems.at(bestBelow).index;
- else if (bestAbove > -1)
- index = d->viewItems.at(bestAbove).index;
-
- if (index.isValid()) {
- QItemSelectionModel::SelectionFlags flags = (d->selectionMode == SingleSelection
- ? QItemSelectionModel::SelectionFlags(
- QItemSelectionModel::ClearAndSelect
- |d->selectionBehaviorFlags())
- : QItemSelectionModel::SelectionFlags(
- QItemSelectionModel::NoUpdate));
- selectionModel()->setCurrentIndex(index, flags);
- }
-}
-
-/*!
- Returns the rectangle on the viewport occupied by the item at \a index.
- If the index is not visible or explicitly hidden, the returned rectangle is invalid.
-*/
-QRect QTreeView::visualRect(const QModelIndex &index) const
-{
- Q_D(const QTreeView);
-
- if (!d->isIndexValid(index) || isIndexHidden(index))
- return QRect();
-
- d->executePostedLayout();
-
- int vi = d->viewIndex(index);
- if (vi < 0)
- return QRect();
-
- bool spanning = d->viewItems.at(vi).spanning;
-
- // if we have a spanning item, make the selection stretch from left to right
- int x = (spanning ? 0 : columnViewportPosition(index.column()));
- int w = (spanning ? d->header->length() : columnWidth(index.column()));
- // handle indentation
- if (index.column() == 0) {
- int i = d->indentationForItem(vi);
- w -= i;
- if (!isRightToLeft())
- x += i;
- }
-
- int y = d->coordinateForItem(vi);
- int h = d->itemHeight(vi);
-
- return QRect(x, y, w, h);
-}
-
-/*!
- Scroll the contents of the tree view until the given model item
- \a index is visible. The \a hint parameter specifies more
- precisely where the item should be located after the
- operation.
- If any of the parents of the model item are collapsed, they will
- be expanded to ensure that the model item is visible.
-*/
-void QTreeView::scrollTo(const QModelIndex &index, ScrollHint hint)
-{
- Q_D(QTreeView);
-
- if (!d->isIndexValid(index))
- return;
-
- d->executePostedLayout();
- d->updateScrollBars();
-
- // Expand all parents if the parent(s) of the node are not expanded.
- QModelIndex parent = index.parent();
- while (parent.isValid() && state() == NoState && d->itemsExpandable) {
- if (!isExpanded(parent))
- expand(parent);
- parent = d->model->parent(parent);
- }
-
- int item = d->viewIndex(index);
- if (item < 0)
- return;
-
- QRect area = d->viewport->rect();
-
- // vertical
- if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
- int top = verticalScrollBar()->value();
- int bottom = top + verticalScrollBar()->pageStep();
- if (hint == EnsureVisible && item >= top && item < bottom) {
- // nothing to do
- } else if (hint == PositionAtTop || (hint == EnsureVisible && item < top)) {
- verticalScrollBar()->setValue(item);
- } else { // PositionAtBottom or PositionAtCenter
- const int currentItemHeight = d->itemHeight(item);
- int y = (hint == PositionAtCenter
- //we center on the current item with a preference to the top item (ie. -1)
- ? area.height() / 2 + currentItemHeight - 1
- //otherwise we simply take the whole space
- : area.height());
- if (y > currentItemHeight) {
- while (item >= 0) {
- y -= d->itemHeight(item);
- if (y < 0) { //there is no more space left
- item++;
- break;
- }
- item--;
- }
- }
- verticalScrollBar()->setValue(item);
- }
- } else { // ScrollPerPixel
- QRect rect(columnViewportPosition(index.column()),
- d->coordinateForItem(item), // ### slow for items outside the view
- columnWidth(index.column()),
- d->itemHeight(item));
-
- if (rect.isEmpty()) {
- // nothing to do
- } else if (hint == EnsureVisible && area.contains(rect)) {
- d->viewport->update(rect);
- // nothing to do
- } else {
- bool above = (hint == EnsureVisible
- && (rect.top() < area.top()
- || area.height() < rect.height()));
- bool below = (hint == EnsureVisible
- && rect.bottom() > area.bottom()
- && rect.height() < area.height());
-
- int verticalValue = verticalScrollBar()->value();
- if (hint == PositionAtTop || above)
- verticalValue += rect.top();
- else if (hint == PositionAtBottom || below)
- verticalValue += rect.bottom() - area.height();
- else if (hint == PositionAtCenter)
- verticalValue += rect.top() - ((area.height() - rect.height()) / 2);
- verticalScrollBar()->setValue(verticalValue);
- }
- }
- // horizontal
- int viewportWidth = d->viewport->width();
- int horizontalOffset = d->header->offset();
- int horizontalPosition = d->header->sectionPosition(index.column());
- int cellWidth = d->header->sectionSize(index.column());
-
- if (hint == PositionAtCenter) {
- horizontalScrollBar()->setValue(horizontalPosition - ((viewportWidth - cellWidth) / 2));
- } else {
- if (horizontalPosition - horizontalOffset < 0 || cellWidth > viewportWidth)
- horizontalScrollBar()->setValue(horizontalPosition);
- else if (horizontalPosition - horizontalOffset + cellWidth > viewportWidth)
- horizontalScrollBar()->setValue(horizontalPosition - viewportWidth + cellWidth);
- }
-}
-
-/*!
- \reimp
-*/
-void QTreeView::timerEvent(QTimerEvent *event)
-{
- Q_D(QTreeView);
- if (event->timerId() == d->columnResizeTimerID) {
- updateGeometries();
- killTimer(d->columnResizeTimerID);
- d->columnResizeTimerID = 0;
- QRect rect;
- int viewportHeight = d->viewport->height();
- int viewportWidth = d->viewport->width();
- for (int i = d->columnsToUpdate.size() - 1; i >= 0; --i) {
- int column = d->columnsToUpdate.at(i);
- int x = columnViewportPosition(column);
- if (isRightToLeft())
- rect |= QRect(0, 0, x + columnWidth(column), viewportHeight);
- else
- rect |= QRect(x, 0, viewportWidth - x, viewportHeight);
- }
- d->viewport->update(rect.normalized());
- d->columnsToUpdate.clear();
- } else if (event->timerId() == d->openTimer.timerId()) {
- QPoint pos = d->viewport->mapFromGlobal(QCursor::pos());
- if (state() == QAbstractItemView::DraggingState
- && d->viewport->rect().contains(pos)) {
- QModelIndex index = indexAt(pos);
- setExpanded(index, !isExpanded(index));
- }
- d->openTimer.stop();
- }
-
- QAbstractItemView::timerEvent(event);
-}
-
-/*!
- \reimp
-*/
-#ifndef QT_NO_DRAGANDDROP
-void QTreeView::dragMoveEvent(QDragMoveEvent *event)
-{
- Q_D(QTreeView);
- if (d->autoExpandDelay >= 0)
- d->openTimer.start(d->autoExpandDelay, this);
- QAbstractItemView::dragMoveEvent(event);
-}
-#endif
-
-/*!
- \reimp
-*/
-bool QTreeView::viewportEvent(QEvent *event)
-{
- Q_D(QTreeView);
- switch (event->type()) {
- case QEvent::HoverEnter:
- case QEvent::HoverLeave:
- case QEvent::HoverMove: {
- QHoverEvent *he = static_cast<QHoverEvent*>(event);
- int oldBranch = d->hoverBranch;
- d->hoverBranch = d->itemDecorationAt(he->pos());
- if (oldBranch != d->hoverBranch) {
- //we need to paint the whole items (including the decoration) so that when the user
- //moves the mouse over those elements they are updated
- if (oldBranch >= 0) {
- int y = d->coordinateForItem(oldBranch);
- int h = d->itemHeight(oldBranch);
- viewport()->update(QRect(0, y, viewport()->width(), h));
- }
- if (d->hoverBranch >= 0) {
- int y = d->coordinateForItem(d->hoverBranch);
- int h = d->itemHeight(d->hoverBranch);
- viewport()->update(QRect(0, y, viewport()->width(), h));
- }
- }
- break; }
- default:
- break;
- }
- return QAbstractItemView::viewportEvent(event);
-}
-
-/*!
- \reimp
-*/
-void QTreeView::paintEvent(QPaintEvent *event)
-{
- Q_D(QTreeView);
- d->executePostedLayout();
- QPainter painter(viewport());
-#ifndef QT_NO_ANIMATION
- if (d->isAnimating()) {
- drawTree(&painter, event->region() - d->animatedOperation.rect());
- d->drawAnimatedOperation(&painter);
- } else
-#endif //QT_NO_ANIMATION
- {
- drawTree(&painter, event->region());
-#ifndef QT_NO_DRAGANDDROP
- d->paintDropIndicator(&painter);
-#endif
- }
-}
-
-void QTreeViewPrivate::paintAlternatingRowColors(QPainter *painter, QStyleOptionViewItemV4 *option, int y, int bottom) const
-{
- Q_Q(const QTreeView);
- if (!alternatingColors || !q->style()->styleHint(QStyle::SH_ItemView_PaintAlternatingRowColorsForEmptyArea, option, q))
- return;
- int rowHeight = defaultItemHeight;
- if (rowHeight <= 0) {
- rowHeight = itemDelegate->sizeHint(*option, QModelIndex()).height();
- if (rowHeight <= 0)
- return;
- }
- while (y <= bottom) {
- option->rect.setRect(0, y, viewport->width(), rowHeight);
- if (current & 1) {
- option->features |= QStyleOptionViewItemV2::Alternate;
- } else {
- option->features &= ~QStyleOptionViewItemV2::Alternate;
- }
- ++current;
- q->style()->drawPrimitive(QStyle::PE_PanelItemViewRow, option, painter, q);
- y += rowHeight;
- }
-}
-
-bool QTreeViewPrivate::expandOrCollapseItemAtPos(const QPoint &pos)
-{
- Q_Q(QTreeView);
- // we want to handle mousePress in EditingState (persistent editors)
- if ((state != QAbstractItemView::NoState
- && state != QAbstractItemView::EditingState)
- || !viewport->rect().contains(pos))
- return true;
-
- int i = itemDecorationAt(pos);
- if ((i != -1) && itemsExpandable && hasVisibleChildren(viewItems.at(i).index)) {
- if (viewItems.at(i).expanded)
- collapse(i, true);
- else
- expand(i, true);
- if (!isAnimating()) {
- q->updateGeometries();
- viewport->update();
- }
- return true;
- }
- return false;
-}
-
-void QTreeViewPrivate::_q_modelDestroyed()
-{
- //we need to clear that list because it contais QModelIndex to
- //the model currently being destroyed
- viewItems.clear();
- QAbstractItemViewPrivate::_q_modelDestroyed();
-}
-
-/*!
- \reimp
-
- We have a QTreeView way of knowing what elements are on the viewport
-*/
-QItemViewPaintPairs QTreeViewPrivate::draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const
-{
- Q_ASSERT(r);
- return QAbstractItemViewPrivate::draggablePaintPairs(indexes, r);
- Q_Q(const QTreeView);
- QRect &rect = *r;
- const QRect viewportRect = viewport->rect();
- int itemOffset = 0;
- int row = firstVisibleItem(&itemOffset);
- QPair<int, int> startEnd = startAndEndColumns(viewportRect);
- QVector<int> columns;
- for (int i = startEnd.first; i <= startEnd.second; ++i) {
- int logical = header->logicalIndex(i);
- if (!header->isSectionHidden(logical))
- columns += logical;
- }
- QSet<QModelIndex> visibleIndexes;
- for (; itemOffset < viewportRect.bottom() && row < viewItems.count(); ++row) {
- const QModelIndex &index = viewItems.at(row).index;
- for (int colIndex = 0; colIndex < columns.count(); ++colIndex)
- visibleIndexes += index.sibling(index.row(), columns.at(colIndex));
- itemOffset += itemHeight(row);
- }
-
- //now that we have the visible indexes, we can try to find those which are selected
- QItemViewPaintPairs ret;
- for (int i = 0; i < indexes.count(); ++i) {
- const QModelIndex &index = indexes.at(i);
- if (visibleIndexes.contains(index)) {
- const QRect current = q->visualRect(index);
- ret += qMakePair(current, index);
- rect |= current;
- }
- }
- rect &= viewportRect;
- return ret;
-}
-
-
-/*!
- \since 4.2
- Draws the part of the tree intersecting the given \a region using the specified
- \a painter.
-
- \sa paintEvent()
-*/
-void QTreeView::drawTree(QPainter *painter, const QRegion &region) const
-{
- Q_D(const QTreeView);
- const QVector<QTreeViewItem> viewItems = d->viewItems;
-
- QStyleOptionViewItemV4 option = d->viewOptionsV4();
- const QStyle::State state = option.state;
- d->current = 0;
-
- if (viewItems.count() == 0 || d->header->count() == 0 || !d->itemDelegate) {
- d->paintAlternatingRowColors(painter, &option, 0, region.boundingRect().bottom()+1);
- return;
- }
-
- int firstVisibleItemOffset = 0;
- const int firstVisibleItem = d->firstVisibleItem(&firstVisibleItemOffset);
- if (firstVisibleItem < 0) {
- d->paintAlternatingRowColors(painter, &option, 0, region.boundingRect().bottom()+1);
- return;
- }
-
- const int viewportWidth = d->viewport->width();
-
- QVector<QRect> rects = region.rects();
- QVector<int> drawn;
- bool multipleRects = (rects.size() > 1);
- for (int a = 0; a < rects.size(); ++a) {
- const QRect area = (multipleRects
- ? QRect(0, rects.at(a).y(), viewportWidth, rects.at(a).height())
- : rects.at(a));
- d->leftAndRight = d->startAndEndColumns(area);
-
- int i = firstVisibleItem; // the first item at the top of the viewport
- int y = firstVisibleItemOffset; // we may only see part of the first item
-
- // start at the top of the viewport and iterate down to the update area
- for (; i < viewItems.count(); ++i) {
- const int itemHeight = d->itemHeight(i);
- if (y + itemHeight > area.top())
- break;
- y += itemHeight;
- }
-
- // paint the visible rows
- for (; i < viewItems.count() && y <= area.bottom(); ++i) {
- const int itemHeight = d->itemHeight(i);
- option.rect.setRect(0, y, viewportWidth, itemHeight);
- option.state = state | (viewItems.at(i).expanded ? QStyle::State_Open : QStyle::State_None)
- | (viewItems.at(i).hasChildren ? QStyle::State_Children : QStyle::State_None)
- | (viewItems.at(i).hasMoreSiblings ? QStyle::State_Sibling : QStyle::State_None);
- d->current = i;
- d->spanning = viewItems.at(i).spanning;
- if (!multipleRects || !drawn.contains(i)) {
- drawRow(painter, option, viewItems.at(i).index);
- if (multipleRects) // even if the rect only intersects the item,
- drawn.append(i); // the entire item will be painted
- }
- y += itemHeight;
- }
-
- if (y <= area.bottom()) {
- d->current = i;
- d->paintAlternatingRowColors(painter, &option, y, area.bottom());
- }
- }
-}
-
-/// ### move to QObject :)
-static inline bool ancestorOf(QObject *widget, QObject *other)
-{
- for (QObject *parent = other; parent != 0; parent = parent->parent()) {
- if (parent == widget)
- return true;
- }
- return false;
-}
-
-/*!
- Draws the row in the tree view that contains the model item \a index,
- using the \a painter given. The \a option control how the item is
- displayed.
-
- \sa setAlternatingRowColors()
-*/
-void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option,
- const QModelIndex &index) const
-{
- Q_D(const QTreeView);
- QStyleOptionViewItemV4 opt = option;
- const QPoint offset = d->scrollDelayOffset;
- const int y = option.rect.y() + offset.y();
- const QModelIndex parent = index.parent();
- const QHeaderView *header = d->header;
- const QModelIndex current = currentIndex();
- const QModelIndex hover = d->hover;
- const bool reverse = isRightToLeft();
- const QStyle::State state = opt.state;
- const bool spanning = d->spanning;
- const int left = (spanning ? header->visualIndex(0) : d->leftAndRight.first);
- const int right = (spanning ? header->visualIndex(0) : d->leftAndRight.second);
- const bool alternate = d->alternatingColors;
- const bool enabled = (state & QStyle::State_Enabled) != 0;
- const bool allColumnsShowFocus = d->allColumnsShowFocus;
-
-
- // when the row contains an index widget which has focus,
- // we want to paint the entire row as active
- bool indexWidgetHasFocus = false;
- if ((current.row() == index.row()) && !d->editorIndexHash.isEmpty()) {
- const int r = index.row();
- QWidget *fw = QApplication::focusWidget();
- for (int c = 0; c < header->count(); ++c) {
- QModelIndex idx = d->model->index(r, c, parent);
- if (QWidget *editor = indexWidget(idx)) {
- if (ancestorOf(editor, fw)) {
- indexWidgetHasFocus = true;
- break;
- }
- }
- }
- }
-
- const bool widgetHasFocus = hasFocus();
- bool currentRowHasFocus = false;
- if (allColumnsShowFocus && widgetHasFocus && current.isValid()) {
- // check if the focus index is before or after the visible columns
- const int r = index.row();
- for (int c = 0; c < left && !currentRowHasFocus; ++c) {
- QModelIndex idx = d->model->index(r, c, parent);
- currentRowHasFocus = (idx == current);
- }
- QModelIndex parent = d->model->parent(index);
- for (int c = right; c < header->count() && !currentRowHasFocus; ++c) {
- currentRowHasFocus = (d->model->index(r, c, parent) == current);
- }
- }
-
- // ### special case: treeviews with multiple columns draw
- // the selections differently than with only one column
- opt.showDecorationSelected = (d->selectionBehavior & SelectRows)
- || option.showDecorationSelected;
-
- int width, height = option.rect.height();
- int position;
- QModelIndex modelIndex;
- int columnCount = header->count();
- const bool hoverRow = selectionBehavior() == QAbstractItemView::SelectRows
- && index.parent() == hover.parent()
- && index.row() == hover.row();
-
- /* 'left' and 'right' are the left-most and right-most visible visual indices.
- Compute the first visible logical indices before and after the left and right.
- We will use these values to determine the QStyleOptionViewItemV4::viewItemPosition. */
- int logicalIndexBeforeLeft = -1, logicalIndexAfterRight = -1;
- for (int visualIndex = left - 1; visualIndex >= 0; --visualIndex) {
- int logicalIndex = header->logicalIndex(visualIndex);
- if (!header->isSectionHidden(logicalIndex)) {
- logicalIndexBeforeLeft = logicalIndex;
- break;
- }
- }
- QVector<int> logicalIndices; // vector of currently visibly logical indices
- for (int visualIndex = left; visualIndex < columnCount; ++visualIndex) {
- int logicalIndex = header->logicalIndex(visualIndex);
- if (!header->isSectionHidden(logicalIndex)) {
- if (visualIndex > right) {
- logicalIndexAfterRight = logicalIndex;
- break;
- }
- logicalIndices.append(logicalIndex);
- }
- }
-
- for (int currentLogicalSection = 0; currentLogicalSection < logicalIndices.count(); ++currentLogicalSection) {
- int headerSection = logicalIndices.at(currentLogicalSection);
- position = columnViewportPosition(headerSection) + offset.x();
- width = header->sectionSize(headerSection);
-
- if (spanning) {
- int lastSection = header->logicalIndex(header->count() - 1);
- if (!reverse) {
- width = columnViewportPosition(lastSection) + header->sectionSize(lastSection) - position;
- } else {
- width += position - columnViewportPosition(lastSection);
- position = columnViewportPosition(lastSection);
- }
- }
-
- modelIndex = d->model->index(index.row(), headerSection, parent);
- if (!modelIndex.isValid())
- continue;
- opt.state = state;
-
- // determine the viewItemPosition depending on the position of column 0
- int nextLogicalSection = currentLogicalSection + 1 >= logicalIndices.count()
- ? logicalIndexAfterRight
- : logicalIndices.at(currentLogicalSection + 1);
- int prevLogicalSection = currentLogicalSection - 1 < 0
- ? logicalIndexBeforeLeft
- : logicalIndices.at(currentLogicalSection - 1);
- if (columnCount == 1 || (nextLogicalSection == 0 && prevLogicalSection == -1)
- || (headerSection == 0 && nextLogicalSection == -1) || spanning)
- opt.viewItemPosition = QStyleOptionViewItemV4::OnlyOne;
- else if (headerSection == 0 || (nextLogicalSection != 0 && prevLogicalSection == -1))
- opt.viewItemPosition = QStyleOptionViewItemV4::Beginning;
- else if (nextLogicalSection == 0 || nextLogicalSection == -1)
- opt.viewItemPosition = QStyleOptionViewItemV4::End;
- else
- opt.viewItemPosition = QStyleOptionViewItemV4::Middle;
-
- // fake activeness when row editor has focus
- if (indexWidgetHasFocus)
- opt.state |= QStyle::State_Active;
-
- if (d->selectionModel->isSelected(modelIndex))
- opt.state |= QStyle::State_Selected;
- if (widgetHasFocus && (current == modelIndex)) {
- if (allColumnsShowFocus)
- currentRowHasFocus = true;
- else
- opt.state |= QStyle::State_HasFocus;
- }
- if ((hoverRow || modelIndex == hover)
- && (option.showDecorationSelected || (d->hoverBranch == -1)))
- opt.state |= QStyle::State_MouseOver;
- else
- opt.state &= ~QStyle::State_MouseOver;
-
- if (enabled) {
- QPalette::ColorGroup cg;
- if ((d->model->flags(modelIndex) & Qt::ItemIsEnabled) == 0) {
- opt.state &= ~QStyle::State_Enabled;
- cg = QPalette::Disabled;
- } else if (opt.state & QStyle::State_Active) {
- cg = QPalette::Active;
- } else {
- cg = QPalette::Inactive;
- }
- opt.palette.setCurrentColorGroup(cg);
- }
-
- if (alternate) {
- if (d->current & 1) {
- opt.features |= QStyleOptionViewItemV2::Alternate;
- } else {
- opt.features &= ~QStyleOptionViewItemV2::Alternate;
- }
- }
-
- /* Prior to Qt 4.3, the background of the branch (in selected state and
- alternate row color was provided by the view. For backward compatibility,
- this is now delegated to the style using PE_PanelViewItemRow which
- does the appropriate fill */
- if (headerSection == 0) {
- const int i = d->indentationForItem(d->current);
- QRect branches(reverse ? position + width - i : position, y, i, height);
- const bool setClipRect = branches.width() > width;
- if (setClipRect) {
- painter->save();
- painter->setClipRect(QRect(position, y, width, height));
- }
- // draw background for the branch (selection + alternate row)
- opt.rect = branches;
- style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, this);
-
- // draw background of the item (only alternate row). rest of the background
- // is provided by the delegate
- QStyle::State oldState = opt.state;
- opt.state &= ~QStyle::State_Selected;
- opt.rect.setRect(reverse ? position : i + position, y, width - i, height);
- style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, this);
- opt.state = oldState;
-
- drawBranches(painter, branches, index);
- if (setClipRect)
- painter->restore();
- } else {
- QStyle::State oldState = opt.state;
- opt.state &= ~QStyle::State_Selected;
- opt.rect.setRect(position, y, width, height);
- style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter, this);
- opt.state = oldState;
- }
-
- d->delegateForIndex(modelIndex)->paint(painter, opt, modelIndex);
- }
-
- if (currentRowHasFocus) {
- QStyleOptionFocusRect o;
- o.QStyleOption::operator=(option);
- o.state |= QStyle::State_KeyboardFocusChange;
- QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled)
- ? QPalette::Normal : QPalette::Disabled;
- o.backgroundColor = option.palette.color(cg, d->selectionModel->isSelected(index)
- ? QPalette::Highlight : QPalette::Background);
- int x = 0;
- if (!option.showDecorationSelected)
- x = header->sectionPosition(0) + d->indentationForItem(d->current);
- QRect focusRect(x - header->offset(), y, header->length() - x, height);
- o.rect = style()->visualRect(layoutDirection(), d->viewport->rect(), focusRect);
- style()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter);
- // if we show focus on all columns and the first section is moved,
- // we have to split the focus rect into two rects
- if (allColumnsShowFocus && !option.showDecorationSelected
- && header->sectionsMoved() && (header->visualIndex(0) != 0)) {
- QRect sectionRect(0, y, header->sectionPosition(0), height);
- o.rect = style()->visualRect(layoutDirection(), d->viewport->rect(), sectionRect);
- style()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter);
- }
- }
-}
-
-/*!
- Draws the branches in the tree view on the same row as the model item
- \a index, using the \a painter given. The branches are drawn in the
- rectangle specified by \a rect.
-*/
-void QTreeView::drawBranches(QPainter *painter, const QRect &rect,
- const QModelIndex &index) const
-{
- Q_D(const QTreeView);
- const bool reverse = isRightToLeft();
- const int indent = d->indent;
- const int outer = d->rootDecoration ? 0 : 1;
- const int item = d->current;
- const QTreeViewItem &viewItem = d->viewItems.at(item);
- int level = viewItem.level;
- QRect primitive(reverse ? rect.left() : rect.right() + 1, rect.top(), indent, rect.height());
-
- QModelIndex parent = index.parent();
- QModelIndex current = parent;
- QModelIndex ancestor = current.parent();
-
- QStyleOptionViewItemV2 opt = viewOptions();
- QStyle::State extraFlags = QStyle::State_None;
- if (isEnabled())
- extraFlags |= QStyle::State_Enabled;
- if (window()->isActiveWindow())
- extraFlags |= QStyle::State_Active;
- QPoint oldBO = painter->brushOrigin();
- if (verticalScrollMode() == QAbstractItemView::ScrollPerPixel)
- painter->setBrushOrigin(QPoint(0, verticalOffset()));
-
- if (d->alternatingColors) {
- if (d->current & 1) {
- opt.features |= QStyleOptionViewItemV2::Alternate;
- } else {
- opt.features &= ~QStyleOptionViewItemV2::Alternate;
- }
- }
-
- // When hovering over a row, pass State_Hover for painting the branch
- // indicators if it has the decoration (aka branch) selected.
- bool hoverRow = selectionBehavior() == QAbstractItemView::SelectRows
- && opt.showDecorationSelected
- && index.parent() == d->hover.parent()
- && index.row() == d->hover.row();
-
- if (d->selectionModel->isSelected(index))
- extraFlags |= QStyle::State_Selected;
-
- if (level >= outer) {
- // start with the innermost branch
- primitive.moveLeft(reverse ? primitive.left() : primitive.left() - indent);
- opt.rect = primitive;
-
- const bool expanded = viewItem.expanded;
- const bool children = viewItem.hasChildren;
- bool moreSiblings = viewItem.hasMoreSiblings;
-
- opt.state = QStyle::State_Item | extraFlags
- | (moreSiblings ? QStyle::State_Sibling : QStyle::State_None)
- | (children ? QStyle::State_Children : QStyle::State_None)
- | (expanded ? QStyle::State_Open : QStyle::State_None);
- if (hoverRow || item == d->hoverBranch)
- opt.state |= QStyle::State_MouseOver;
- else
- opt.state &= ~QStyle::State_MouseOver;
- style()->drawPrimitive(QStyle::PE_IndicatorBranch, &opt, painter, this);
- }
- // then go out level by level
- for (--level; level >= outer; --level) { // we have already drawn the innermost branch
- primitive.moveLeft(reverse ? primitive.left() + indent : primitive.left() - indent);
- opt.rect = primitive;
- opt.state = extraFlags;
- bool moreSiblings = false;
- if (d->hiddenIndexes.isEmpty()) {
- moreSiblings = (d->model->rowCount(ancestor) - 1 > current.row());
- } else {
- int successor = item + viewItem.total + 1;
- while (successor < d->viewItems.size()
- && d->viewItems.at(successor).level >= uint(level)) {
- const QTreeViewItem &successorItem = d->viewItems.at(successor);
- if (successorItem.level == uint(level)) {
- moreSiblings = true;
- break;
- }
- successor += successorItem.total + 1;
- }
- }
- if (moreSiblings)
- opt.state |= QStyle::State_Sibling;
- if (hoverRow || item == d->hoverBranch)
- opt.state |= QStyle::State_MouseOver;
- else
- opt.state &= ~QStyle::State_MouseOver;
- style()->drawPrimitive(QStyle::PE_IndicatorBranch, &opt, painter, this);
- current = ancestor;
- ancestor = current.parent();
- }
- painter->setBrushOrigin(oldBO);
-}
-
-/*!
- \reimp
-*/
-void QTreeView::mousePressEvent(QMouseEvent *event)
-{
- Q_D(QTreeView);
- bool handled = false;
- if (style()->styleHint(QStyle::SH_Q3ListViewExpand_SelectMouseType, 0, this) == QEvent::MouseButtonPress)
- handled = d->expandOrCollapseItemAtPos(event->pos());
- if (!handled && d->itemDecorationAt(event->pos()) == -1)
- QAbstractItemView::mousePressEvent(event);
-}
-
-/*!
- \reimp
-*/
-void QTreeView::mouseReleaseEvent(QMouseEvent *event)
-{
- Q_D(QTreeView);
- if (d->itemDecorationAt(event->pos()) == -1) {
- QAbstractItemView::mouseReleaseEvent(event);
- } else {
- if (state() == QAbstractItemView::DragSelectingState)
- setState(QAbstractItemView::NoState);
- if (style()->styleHint(QStyle::SH_Q3ListViewExpand_SelectMouseType, 0, this) == QEvent::MouseButtonRelease)
- d->expandOrCollapseItemAtPos(event->pos());
- }
-}
-
-/*!
- \reimp
-*/
-void QTreeView::mouseDoubleClickEvent(QMouseEvent *event)
-{
- Q_D(QTreeView);
- if (state() != NoState || !d->viewport->rect().contains(event->pos()))
- return;
-
- int i = d->itemDecorationAt(event->pos());
- if (i == -1) {
- i = d->itemAtCoordinate(event->y());
- if (i == -1)
- return; // user clicked outside the items
-
- const QPersistentModelIndex firstColumnIndex = d->viewItems.at(i).index;
- const QPersistentModelIndex persistent = indexAt(event->pos());
-
- if (d->pressedIndex != persistent) {
- mousePressEvent(event);
- return;
- }
-
- // signal handlers may change the model
- emit doubleClicked(persistent);
-
- if (!persistent.isValid())
- return;
-
- if (edit(persistent, DoubleClicked, event) || state() != NoState)
- return; // the double click triggered editing
-
- if (!style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, 0, this))
- emit activated(persistent);
-
- d->executePostedLayout(); // we need to make sure viewItems is updated
- if (d->itemsExpandable
- && d->expandsOnDoubleClick
- && d->hasVisibleChildren(persistent)) {
- if (!((i < d->viewItems.count()) && (d->viewItems.at(i).index == firstColumnIndex))) {
- // find the new index of the item
- for (i = 0; i < d->viewItems.count(); ++i) {
- if (d->viewItems.at(i).index == firstColumnIndex)
- break;
- }
- if (i == d->viewItems.count())
- return;
- }
- if (d->viewItems.at(i).expanded)
- d->collapse(i, true);
- else
- d->expand(i, true);
- updateGeometries();
- viewport()->update();
- }
- }
-}
-
-/*!
- \reimp
-*/
-void QTreeView::mouseMoveEvent(QMouseEvent *event)
-{
- Q_D(QTreeView);
- if (d->itemDecorationAt(event->pos()) == -1) // ### what about expanding/collapsing state ?
- QAbstractItemView::mouseMoveEvent(event);
-}
-
-/*!
- \reimp
-*/
-void QTreeView::keyPressEvent(QKeyEvent *event)
-{
- Q_D(QTreeView);
- QModelIndex current = currentIndex();
- //this is the management of the expansion
- if (d->isIndexValid(current) && d->model && d->itemsExpandable) {
- switch (event->key()) {
- case Qt::Key_Asterisk: {
- QStack<QModelIndex> parents;
- parents.push(current);
- while (!parents.isEmpty()) {
- QModelIndex parent = parents.pop();
- for (int row = 0; row < d->model->rowCount(parent); ++row) {
- QModelIndex child = d->model->index(row, 0, parent);
- if (!d->isIndexValid(child))
- break;
- parents.push(child);
- expand(child);
- }
- }
- expand(current);
- break; }
- case Qt::Key_Plus:
- expand(current);
- break;
- case Qt::Key_Minus:
- collapse(current);
- break;
- }
- }
-
- QAbstractItemView::keyPressEvent(event);
-}
-
-/*!
- \reimp
-*/
-QModelIndex QTreeView::indexAt(const QPoint &point) const
-{
- Q_D(const QTreeView);
- d->executePostedLayout();
-
- int visualIndex = d->itemAtCoordinate(point.y());
- QModelIndex idx = d->modelIndex(visualIndex);
- if (!idx.isValid())
- return QModelIndex();
-
- if (d->viewItems.at(visualIndex).spanning)
- return idx;
-
- int column = d->columnAt(point.x());
- if (column == idx.column())
- return idx;
- if (column < 0)
- return QModelIndex();
- return idx.sibling(idx.row(), column);
-}
-
-/*!
- Returns the model index of the item above \a index.
-*/
-QModelIndex QTreeView::indexAbove(const QModelIndex &index) const
-{
- Q_D(const QTreeView);
- if (!d->isIndexValid(index))
- return QModelIndex();
- d->executePostedLayout();
- int i = d->viewIndex(index);
- if (--i < 0)
- return QModelIndex();
- return d->viewItems.at(i).index;
-}
-
-/*!
- Returns the model index of the item below \a index.
-*/
-QModelIndex QTreeView::indexBelow(const QModelIndex &index) const
-{
- Q_D(const QTreeView);
- if (!d->isIndexValid(index))
- return QModelIndex();
- d->executePostedLayout();
- int i = d->viewIndex(index);
- if (++i >= d->viewItems.count())
- return QModelIndex();
- return d->viewItems.at(i).index;
-}
-
-/*!
- \internal
-
- Lays out the items in the tree view.
-*/
-void QTreeView::doItemsLayout()
-{
- Q_D(QTreeView);
- if (d->hasRemovedItems) {
- //clean the QSet that may contains old (and this invalid) indexes
- d->hasRemovedItems = false;
- QSet<QPersistentModelIndex>::iterator it = d->expandedIndexes.begin();
- while (it != d->expandedIndexes.constEnd()) {
- if (!it->isValid())
- it = d->expandedIndexes.erase(it);
- else
- ++it;
- }
- it = d->hiddenIndexes.begin();
- while (it != d->hiddenIndexes.constEnd()) {
- if (!it->isValid())
- it = d->hiddenIndexes.erase(it);
- else
- ++it;
- }
- }
- d->viewItems.clear(); // prepare for new layout
- QModelIndex parent = d->root;
- if (d->model->hasChildren(parent)) {
- d->layout(-1);
- }
- QAbstractItemView::doItemsLayout();
- d->header->doItemsLayout();
-}
-
-/*!
- \reimp
-*/
-void QTreeView::reset()
-{
- Q_D(QTreeView);
- d->expandedIndexes.clear();
- d->hiddenIndexes.clear();
- d->spanningIndexes.clear();
- d->viewItems.clear();
- QAbstractItemView::reset();
-}
-
-/*!
- Returns the horizontal offset of the items in the treeview.
-
- Note that the tree view uses the horizontal header section
- positions to determine the positions of columns in the view.
-
- \sa verticalOffset()
-*/
-int QTreeView::horizontalOffset() const
-{
- Q_D(const QTreeView);
- return d->header->offset();
-}
-
-/*!
- Returns the vertical offset of the items in the tree view.
-
- \sa horizontalOffset()
-*/
-int QTreeView::verticalOffset() const
-{
- Q_D(const QTreeView);
- if (d->verticalScrollMode == QAbstractItemView::ScrollPerItem) {
- if (d->uniformRowHeights)
- return verticalScrollBar()->value() * d->defaultItemHeight;
- // If we are scrolling per item and have non-uniform row heights,
- // finding the vertical offset in pixels is going to be relatively slow.
- // ### find a faster way to do this
- d->executePostedLayout();
- int offset = 0;
- for (int i = 0; i < d->viewItems.count(); ++i) {
- if (i == verticalScrollBar()->value())
- return offset;
- offset += d->itemHeight(i);
- }
- return 0;
- }
- // scroll per pixel
- return verticalScrollBar()->value();
-}
-
-/*!
- Move the cursor in the way described by \a cursorAction, using the
- information provided by the button \a modifiers.
-*/
-QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
-{
- Q_D(QTreeView);
- Q_UNUSED(modifiers);
-
- d->executePostedLayout();
-
- QModelIndex current = currentIndex();
- if (!current.isValid()) {
- int i = d->below(-1);
- int c = 0;
- while (c < d->header->count() && d->header->isSectionHidden(c))
- ++c;
- if (i < d->viewItems.count() && c < d->header->count()) {
- return d->modelIndex(i, c);
- }
- return QModelIndex();
- }
- int vi = -1;
-#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
- // Selection behavior is slightly different on the Mac.
- if (d->selectionMode == QAbstractItemView::ExtendedSelection
- && d->selectionModel
- && d->selectionModel->hasSelection()) {
-
- const bool moveUpDown = (cursorAction == MoveUp || cursorAction == MoveDown);
- const bool moveNextPrev = (cursorAction == MoveNext || cursorAction == MovePrevious);
- const bool contiguousSelection = moveUpDown && (modifiers & Qt::ShiftModifier);
-
- // Use the outermost index in the selection as the current index
- if (!contiguousSelection && (moveUpDown || moveNextPrev)) {
-
- // Find outermost index.
- const bool useTopIndex = (cursorAction == MoveUp || cursorAction == MovePrevious);
- int index = useTopIndex ? INT_MAX : INT_MIN;
- const QItemSelection selection = d->selectionModel->selection();
- for (int i = 0; i < selection.count(); ++i) {
- const QItemSelectionRange &range = selection.at(i);
- int candidate = d->viewIndex(useTopIndex ? range.topLeft() : range.bottomRight());
- if (candidate >= 0)
- index = useTopIndex ? qMin(index, candidate) : qMax(index, candidate);
- }
-
- if (index >= 0 && index < INT_MAX)
- vi = index;
- }
- }
-#endif
- if (vi < 0)
- vi = qMax(0, d->viewIndex(current));
-
- if (isRightToLeft()) {
- if (cursorAction == MoveRight)
- cursorAction = MoveLeft;
- else if (cursorAction == MoveLeft)
- cursorAction = MoveRight;
- }
- switch (cursorAction) {
- case MoveNext:
- case MoveDown:
-#ifdef QT_KEYPAD_NAVIGATION
- if (vi == d->viewItems.count()-1 && QApplication::keypadNavigationEnabled())
- return d->model->index(0, current.column(), d->root);
-#endif
- return d->modelIndex(d->below(vi), current.column());
- case MovePrevious:
- case MoveUp:
-#ifdef QT_KEYPAD_NAVIGATION
- if (vi == 0 && QApplication::keypadNavigationEnabled())
- return d->modelIndex(d->viewItems.count() - 1, current.column());
-#endif
- return d->modelIndex(d->above(vi), current.column());
- case MoveLeft: {
- QScrollBar *sb = horizontalScrollBar();
- if (vi < d->viewItems.count() && d->viewItems.at(vi).expanded && d->itemsExpandable && sb->value() == sb->minimum()) {
- d->collapse(vi, true);
- d->moveCursorUpdatedView = true;
- } else {
- bool descend = style()->styleHint(QStyle::SH_ItemView_ArrowKeysNavigateIntoChildren, 0, this);
- if (descend) {
- QModelIndex par = current.parent();
- if (par.isValid() && par != rootIndex())
- return par;
- else
- descend = false;
- }
- if (!descend) {
- if (d->selectionBehavior == SelectItems || d->selectionBehavior == SelectColumns) {
- int visualColumn = d->header->visualIndex(current.column()) - 1;
- while (visualColumn >= 0 && isColumnHidden(d->header->logicalIndex(visualColumn)))
- visualColumn--;
- int newColumn = d->header->logicalIndex(visualColumn);
- QModelIndex next = current.sibling(current.row(), newColumn);
- if (next.isValid())
- return next;
- }
-
- int oldValue = sb->value();
- sb->setValue(sb->value() - sb->singleStep());
- if (oldValue != sb->value())
- d->moveCursorUpdatedView = true;
- }
-
- }
- updateGeometries();
- viewport()->update();
- break;
- }
- case MoveRight:
- if (vi < d->viewItems.count() && !d->viewItems.at(vi).expanded && d->itemsExpandable
- && d->hasVisibleChildren(d->viewItems.at(vi).index)) {
- d->expand(vi, true);
- d->moveCursorUpdatedView = true;
- } else {
- bool descend = style()->styleHint(QStyle::SH_ItemView_ArrowKeysNavigateIntoChildren, 0, this);
- if (descend) {
- QModelIndex idx = d->modelIndex(d->below(vi));
- if (idx.parent() == current)
- return idx;
- else
- descend = false;
- }
- if (!descend) {
- if (d->selectionBehavior == SelectItems || d->selectionBehavior == SelectColumns) {
- int visualColumn = d->header->visualIndex(current.column()) + 1;
- while (visualColumn < d->model->columnCount(current.parent()) && isColumnHidden(d->header->logicalIndex(visualColumn)))
- visualColumn++;
-
- QModelIndex next = current.sibling(current.row(), visualColumn);
- if (next.isValid())
- return next;
- }
-
- //last restort: we change the scrollbar value
- QScrollBar *sb = horizontalScrollBar();
- int oldValue = sb->value();
- sb->setValue(sb->value() + sb->singleStep());
- if (oldValue != sb->value())
- d->moveCursorUpdatedView = true;
- }
- }
- updateGeometries();
- viewport()->update();
- break;
- case MovePageUp:
- return d->modelIndex(d->pageUp(vi), current.column());
- case MovePageDown:
- return d->modelIndex(d->pageDown(vi), current.column());
- case MoveHome:
- return d->model->index(0, current.column(), d->root);
- case MoveEnd:
- return d->modelIndex(d->viewItems.count() - 1, current.column());
- }
- return current;
-}
-
-/*!
- Applies the selection \a command to the items in or touched by the
- rectangle, \a rect.
-
- \sa selectionCommand()
-*/
-void QTreeView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
-{
- Q_D(QTreeView);
- if (!selectionModel() || rect.isNull())
- return;
-
- d->executePostedLayout();
- QPoint tl(isRightToLeft() ? qMax(rect.left(), rect.right())
- : qMin(rect.left(), rect.right()), qMin(rect.top(), rect.bottom()));
- QPoint br(isRightToLeft() ? qMin(rect.left(), rect.right()) :
- qMax(rect.left(), rect.right()), qMax(rect.top(), rect.bottom()));
- QModelIndex topLeft = indexAt(tl);
- QModelIndex bottomRight = indexAt(br);
- if (!topLeft.isValid() && !bottomRight.isValid()) {
- if (command & QItemSelectionModel::Clear)
- selectionModel()->clear();
- return;
- }
- if (!topLeft.isValid() && !d->viewItems.isEmpty())
- topLeft = d->viewItems.first().index;
- if (!bottomRight.isValid() && !d->viewItems.isEmpty()) {
- const int column = d->header->logicalIndex(d->header->count() - 1);
- const QModelIndex index = d->viewItems.last().index;
- bottomRight = index.sibling(index.row(), column);
- }
-
- if (!d->isIndexEnabled(topLeft) || !d->isIndexEnabled(bottomRight))
- return;
-
- d->select(topLeft, bottomRight, command);
-}
-
-/*!
- Returns the rectangle from the viewport of the items in the given
- \a selection.
-
- Since 4.7, the returned region only contains rectangles intersecting
- (or included in) the viewport.
-*/
-QRegion QTreeView::visualRegionForSelection(const QItemSelection &selection) const
-{
- Q_D(const QTreeView);
- if (selection.isEmpty())
- return QRegion();
-
- QRegion selectionRegion;
- const QRect &viewportRect = d->viewport->rect();
- for (int i = 0; i < selection.count(); ++i) {
- QItemSelectionRange range = selection.at(i);
- if (!range.isValid())
- continue;
- QModelIndex parent = range.parent();
- QModelIndex leftIndex = range.topLeft();
- int columnCount = d->model->columnCount(parent);
- while (leftIndex.isValid() && isIndexHidden(leftIndex)) {
- if (leftIndex.column() + 1 < columnCount)
- leftIndex = d->model->index(leftIndex.row(), leftIndex.column() + 1, parent);
- else
- leftIndex = QModelIndex();
- }
- if (!leftIndex.isValid())
- continue;
- const QRect leftRect = visualRect(leftIndex);
- int top = leftRect.top();
- QModelIndex rightIndex = range.bottomRight();
- while (rightIndex.isValid() && isIndexHidden(rightIndex)) {
- if (rightIndex.column() - 1 >= 0)
- rightIndex = d->model->index(rightIndex.row(), rightIndex.column() - 1, parent);
- else
- rightIndex = QModelIndex();
- }
- if (!rightIndex.isValid())
- continue;
- const QRect rightRect = visualRect(rightIndex);
- int bottom = rightRect.bottom();
- if (top > bottom)
- qSwap<int>(top, bottom);
- int height = bottom - top + 1;
- if (d->header->sectionsMoved()) {
- for (int c = range.left(); c <= range.right(); ++c) {
- const QRect rangeRect(columnViewportPosition(c), top, columnWidth(c), height);
- if (viewportRect.intersects(rangeRect))
- selectionRegion += rangeRect;
- }
- } else {
- QRect combined = leftRect|rightRect;
- combined.setX(columnViewportPosition(isRightToLeft() ? range.right() : range.left()));
- if (viewportRect.intersects(combined))
- selectionRegion += combined;
- }
- }
- return selectionRegion;
-}
-
-/*!
- \reimp
-*/
-QModelIndexList QTreeView::selectedIndexes() const
-{
- QModelIndexList viewSelected;
- QModelIndexList modelSelected;
- if (selectionModel())
- modelSelected = selectionModel()->selectedIndexes();
- for (int i = 0; i < modelSelected.count(); ++i) {
- // check that neither the parents nor the index is hidden before we add
- QModelIndex index = modelSelected.at(i);
- while (index.isValid() && !isIndexHidden(index))
- index = index.parent();
- if (index.isValid())
- continue;
- viewSelected.append(modelSelected.at(i));
- }
- return viewSelected;
-}
-
-/*!
- Scrolls the contents of the tree view by (\a dx, \a dy).
-*/
-void QTreeView::scrollContentsBy(int dx, int dy)
-{
- Q_D(QTreeView);
-
- d->delayedAutoScroll.stop(); // auto scroll was canceled by the user scrolling
-
- dx = isRightToLeft() ? -dx : dx;
- if (dx) {
- if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
- int oldOffset = d->header->offset();
- if (horizontalScrollBar()->value() == horizontalScrollBar()->maximum())
- d->header->setOffsetToLastSection();
- else
- d->header->setOffsetToSectionPosition(horizontalScrollBar()->value());
- int newOffset = d->header->offset();
- dx = isRightToLeft() ? newOffset - oldOffset : oldOffset - newOffset;
- } else {
- d->header->setOffset(horizontalScrollBar()->value());
- }
- }
-
- const int itemHeight = d->defaultItemHeight <= 0 ? sizeHintForRow(0) : d->defaultItemHeight;
- if (d->viewItems.isEmpty() || itemHeight == 0)
- return;
-
- // guestimate the number of items in the viewport
- int viewCount = d->viewport->height() / itemHeight;
- int maxDeltaY = qMin(d->viewItems.count(), viewCount);
- // no need to do a lot of work if we are going to redraw the whole thing anyway
- if (qAbs(dy) > qAbs(maxDeltaY) && d->editorIndexHash.isEmpty()) {
- verticalScrollBar()->update();
- d->viewport->update();
- return;
- }
-
- if (dy && verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
- int currentScrollbarValue = verticalScrollBar()->value();
- int previousScrollbarValue = currentScrollbarValue + dy; // -(-dy)
- int currentViewIndex = currentScrollbarValue; // the first visible item
- int previousViewIndex = previousScrollbarValue;
- const QVector<QTreeViewItem> viewItems = d->viewItems;
- dy = 0;
- if (previousViewIndex < currentViewIndex) { // scrolling down
- for (int i = previousViewIndex; i < currentViewIndex; ++i) {
- if (i < d->viewItems.count())
- dy -= d->itemHeight(i);
- }
- } else if (previousViewIndex > currentViewIndex) { // scrolling up
- for (int i = previousViewIndex - 1; i >= currentViewIndex; --i) {
- if (i < d->viewItems.count())
- dy += d->itemHeight(i);
- }
- }
- }
-
- d->scrollContentsBy(dx, dy);
-}
-
-/*!
- This slot is called whenever a column has been moved.
-*/
-void QTreeView::columnMoved()
-{
- Q_D(QTreeView);
- updateEditorGeometries();
- d->viewport->update();
-}
-
-/*!
- \internal
-*/
-void QTreeView::reexpand()
-{
- // do nothing
-}
-
-/*!
- Informs the view that the rows from the \a start row to the \a end row
- inclusive have been inserted into the \a parent model item.
-*/
-void QTreeView::rowsInserted(const QModelIndex &parent, int start, int end)
-{
- Q_D(QTreeView);
- // if we are going to do a complete relayout anyway, there is no need to update
- if (d->delayedPendingLayout) {
- QAbstractItemView::rowsInserted(parent, start, end);
- return;
- }
-
- //don't add a hierarchy on a column != 0
- if (parent.column() != 0 && parent.isValid()) {
- QAbstractItemView::rowsInserted(parent, start, end);
- return;
- }
-
- const int parentRowCount = d->model->rowCount(parent);
- const int delta = end - start + 1;
- if (parent != d->root && !d->isIndexExpanded(parent) && parentRowCount > delta) {
- QAbstractItemView::rowsInserted(parent, start, end);
- return;
- }
-
- const int parentItem = d->viewIndex(parent);
- if (((parentItem != -1) && d->viewItems.at(parentItem).expanded)
- || (parent == d->root)) {
- d->doDelayedItemsLayout();
- } else if (parentItem != -1 && (d->model->rowCount(parent) == end - start + 1)) {
- // the parent just went from 0 children to more. update to re-paint the decoration
- d->viewItems[parentItem].hasChildren = true;
- viewport()->update();
- }
- QAbstractItemView::rowsInserted(parent, start, end);
-}
-
-/*!
- Informs the view that the rows from the \a start row to the \a end row
- inclusive are about to removed from the given \a parent model item.
-*/
-void QTreeView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
-{
- Q_D(QTreeView);
- QAbstractItemView::rowsAboutToBeRemoved(parent, start, end);
- d->viewItems.clear();
-}
-
-/*!
- \since 4.1
-
- Informs the view that the rows from the \a start row to the \a end row
- inclusive have been removed from the given \a parent model item.
-*/
-void QTreeView::rowsRemoved(const QModelIndex &parent, int start, int end)
-{
- Q_D(QTreeView);
- d->viewItems.clear();
- d->doDelayedItemsLayout();
- d->hasRemovedItems = true;
- d->_q_rowsRemoved(parent, start, end);
-}
-
-/*!
- Informs the tree view that the number of columns in the tree view has
- changed from \a oldCount to \a newCount.
-*/
-void QTreeView::columnCountChanged(int oldCount, int newCount)
-{
- Q_D(QTreeView);
- if (oldCount == 0 && newCount > 0) {
- //if the first column has just been added we need to relayout.
- d->doDelayedItemsLayout();
- }
-
- if (isVisible())
- updateGeometries();
- viewport()->update();
-}
-
-/*!
- Resizes the \a column given to the size of its contents.
-
- \sa columnWidth(), setColumnWidth()
-*/
-void QTreeView::resizeColumnToContents(int column)
-{
- Q_D(QTreeView);
- d->executePostedLayout();
- if (column < 0 || column >= d->header->count())
- return;
- int contents = sizeHintForColumn(column);
- int header = d->header->isHidden() ? 0 : d->header->sectionSizeHint(column);
- d->header->resizeSection(column, qMax(contents, header));
-}
-
-/*!
- \obsolete
- \overload
-
- Sorts the model by the values in the given \a column.
-*/
-void QTreeView::sortByColumn(int column)
-{
- Q_D(QTreeView);
- sortByColumn(column, d->header->sortIndicatorOrder());
-}
-
-/*!
- \since 4.2
-
- Sets the model up for sorting by the values in the given \a column and \a order.
-
- \a column may be -1, in which case no sort indicator will be shown
- and the model will return to its natural, unsorted order. Note that not
- all models support this and may even crash in this case.
-
- \sa sortingEnabled
-*/
-void QTreeView::sortByColumn(int column, Qt::SortOrder order)
-{
- Q_D(QTreeView);
-
- //If sorting is enabled will emit a signal connected to _q_sortIndicatorChanged, which then actually sorts
- d->header->setSortIndicator(column, order);
- //If sorting is not enabled, force to sort now.
- if (!d->sortingEnabled)
- d->model->sort(column, order);
-}
-
-/*!
- \reimp
-*/
-void QTreeView::selectAll()
-{
- Q_D(QTreeView);
- if (!selectionModel())
- return;
- SelectionMode mode = d->selectionMode;
- d->executePostedLayout(); //make sure we lay out the items
- if (mode != SingleSelection && !d->viewItems.isEmpty()) {
- const QModelIndex &idx = d->viewItems.last().index;
- QModelIndex lastItemIndex = idx.sibling(idx.row(), d->model->columnCount(idx.parent()) - 1);
- d->select(d->viewItems.first().index, lastItemIndex,
- QItemSelectionModel::ClearAndSelect
- |QItemSelectionModel::Rows);
- }
-}
-
-/*!
- \since 4.2
- Expands all expandable items.
-
- Warning: if the model contains a large number of items,
- this function will take some time to execute.
-
- \sa collapseAll() expand() collapse() setExpanded()
-*/
-void QTreeView::expandAll()
-{
- Q_D(QTreeView);
- d->viewItems.clear();
- d->interruptDelayedItemsLayout();
- d->layout(-1, true);
- updateGeometries();
- d->viewport->update();
-}
-
-/*!
- \since 4.2
-
- Collapses all expanded items.
-
- \sa expandAll() expand() collapse() setExpanded()
-*/
-void QTreeView::collapseAll()
-{
- Q_D(QTreeView);
- d->expandedIndexes.clear();
- doItemsLayout();
-}
-
-/*!
- \since 4.3
- Expands all expandable items to the given \a depth.
-
- \sa expandAll() collapseAll() expand() collapse() setExpanded()
-*/
-void QTreeView::expandToDepth(int depth)
-{
- Q_D(QTreeView);
- d->viewItems.clear();
- d->expandedIndexes.clear();
- d->interruptDelayedItemsLayout();
- d->layout(-1);
- for (int i = 0; i < d->viewItems.count(); ++i) {
- if (d->viewItems.at(i).level <= (uint)depth) {
- d->viewItems[i].expanded = true;
- d->layout(i);
- d->storeExpanded(d->viewItems.at(i).index);
- }
- }
- updateGeometries();
- d->viewport->update();
-}
-
-/*!
- This function is called whenever \a{column}'s size is changed in
- the header. \a oldSize and \a newSize give the previous size and
- the new size in pixels.
-
- \sa setColumnWidth()
-*/
-void QTreeView::columnResized(int column, int /* oldSize */, int /* newSize */)
-{
- Q_D(QTreeView);
- d->columnsToUpdate.append(column);
- if (d->columnResizeTimerID == 0)
- d->columnResizeTimerID = startTimer(0);
-}
-
-/*!
- \reimp
-*/
-void QTreeView::updateGeometries()
-{
- Q_D(QTreeView);
- if (d->header) {
- if (d->geometryRecursionBlock)
- return;
- d->geometryRecursionBlock = true;
- QSize hint = d->header->isHidden() ? QSize(0, 0) : d->header->sizeHint();
- setViewportMargins(0, hint.height(), 0, 0);
- QRect vg = d->viewport->geometry();
- QRect geometryRect(vg.left(), vg.top() - hint.height(), vg.width(), hint.height());
- d->header->setGeometry(geometryRect);
- //d->header->setOffset(horizontalScrollBar()->value()); // ### bug ???
- QMetaObject::invokeMethod(d->header, "updateGeometries");
- d->updateScrollBars();
- d->geometryRecursionBlock = false;
- }
- QAbstractItemView::updateGeometries();
-}
-
-/*!
- Returns the size hint for the \a column's width or -1 if there is no
- model.
-
- If you need to set the width of a given column to a fixed value, call
- QHeaderView::resizeSection() on the view's header.
-
- If you reimplement this function in a subclass, note that the value you
- return is only used when resizeColumnToContents() is called. In that case,
- if a larger column width is required by either the view's header or
- the item delegate, that width will be used instead.
-
- \sa QWidget::sizeHint, header()
-*/
-int QTreeView::sizeHintForColumn(int column) const
-{
- Q_D(const QTreeView);
- d->executePostedLayout();
- if (d->viewItems.isEmpty())
- return -1;
- ensurePolished();
- int w = 0;
- QStyleOptionViewItemV4 option = d->viewOptionsV4();
- const QVector<QTreeViewItem> viewItems = d->viewItems;
-
- int start = 0;
- int end = viewItems.count();
- if(end > 1000) { //if we have too many item this function would be too slow.
- //we get a good approximation by only iterate over 1000 items.
- start = qMax(0, d->firstVisibleItem() - 100);
- end = qMin(end, start + 900);
- }
-
- for (int i = start; i < end; ++i) {
- if (viewItems.at(i).spanning)
- continue; // we have no good size hint
- QModelIndex index = viewItems.at(i).index;
- index = index.sibling(index.row(), column);
- QWidget *editor = d->editorForIndex(index).widget.data();
- if (editor && d->persistent.contains(editor)) {
- w = qMax(w, editor->sizeHint().width());
- int min = editor->minimumSize().width();
- int max = editor->maximumSize().width();
- w = qBound(min, w, max);
- }
- int hint = d->delegateForIndex(index)->sizeHint(option, index).width();
- w = qMax(w, hint + (column == 0 ? d->indentationForItem(i) : 0));
- }
- return w;
-}
-
-/*!
- Returns the size hint for the row indicated by \a index.
-
- \sa sizeHintForColumn(), uniformRowHeights()
-*/
-int QTreeView::indexRowSizeHint(const QModelIndex &index) const
-{
- Q_D(const QTreeView);
- if (!d->isIndexValid(index) || !d->itemDelegate)
- return 0;
-
- int start = -1;
- int end = -1;
- int indexRow = index.row();
- int count = d->header->count();
- bool emptyHeader = (count == 0);
- QModelIndex parent = index.parent();
-
- if (count && isVisible()) {
- // If the sections have moved, we end up checking too many or too few
- start = d->header->visualIndexAt(0);
- } else {
- // If the header has not been laid out yet, we use the model directly
- count = d->model->columnCount(parent);
- }
-
- if (isRightToLeft()) {
- start = (start == -1 ? count - 1 : start);
- end = 0;
- } else {
- start = (start == -1 ? 0 : start);
- end = count - 1;
- }
-
- if (end < start)
- qSwap(end, start);
-
- int height = -1;
- QStyleOptionViewItemV4 option = d->viewOptionsV4();
- // ### If we want word wrapping in the items,
- // ### we need to go through all the columns
- // ### and set the width of the column
-
- // Hack to speed up the function
- option.rect.setWidth(-1);
-
- for (int column = start; column <= end; ++column) {
- int logicalColumn = emptyHeader ? column : d->header->logicalIndex(column);
- if (d->header->isSectionHidden(logicalColumn))
- continue;
- QModelIndex idx = d->model->index(indexRow, logicalColumn, parent);
- if (idx.isValid()) {
- QWidget *editor = d->editorForIndex(idx).widget.data();
- if (editor && d->persistent.contains(editor)) {
- height = qMax(height, editor->sizeHint().height());
- int min = editor->minimumSize().height();
- int max = editor->maximumSize().height();
- height = qBound(min, height, max);
- }
- int hint = d->delegateForIndex(idx)->sizeHint(option, idx).height();
- height = qMax(height, hint);
- }
- }
-
- return height;
-}
-
-/*!
- \since 4.3
- Returns the height of the row indicated by the given \a index.
- \sa indexRowSizeHint()
-*/
-int QTreeView::rowHeight(const QModelIndex &index) const
-{
- Q_D(const QTreeView);
- d->executePostedLayout();
- int i = d->viewIndex(index);
- if (i == -1)
- return 0;
- return d->itemHeight(i);
-}
-
-/*!
- \internal
-*/
-void QTreeView::horizontalScrollbarAction(int action)
-{
- QAbstractItemView::horizontalScrollbarAction(action);
-}
-
-/*!
- \reimp
-*/
-bool QTreeView::isIndexHidden(const QModelIndex &index) const
-{
- return (isColumnHidden(index.column()) || isRowHidden(index.row(), index.parent()));
-}
-
-/*
- private implementation
-*/
-void QTreeViewPrivate::initialize()
-{
- Q_Q(QTreeView);
- updateStyledFrameWidths();
- q->setSelectionBehavior(QAbstractItemView::SelectRows);
- q->setSelectionMode(QAbstractItemView::SingleSelection);
- q->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
- q->setAttribute(Qt::WA_MacShowFocusRect);
-
- QHeaderView *header = new QHeaderView(Qt::Horizontal, q);
- header->setMovable(true);
- header->setStretchLastSection(true);
- header->setDefaultAlignment(Qt::AlignLeft|Qt::AlignVCenter);
- q->setHeader(header);
-#ifndef QT_NO_ANIMATION
- QObject::connect(&animatedOperation, SIGNAL(finished()), q, SLOT(_q_endAnimatedOperation()));
-#endif //QT_NO_ANIMATION
-}
-
-void QTreeViewPrivate::expand(int item, bool emitSignal)
-{
- Q_Q(QTreeView);
-
- if (item == -1 || viewItems.at(item).expanded)
- return;
-
-#ifndef QT_NO_ANIMATION
- if (emitSignal && animationsEnabled)
- prepareAnimatedOperation(item, QVariantAnimation::Forward);
-#endif //QT_NO_ANIMATION
- stateBeforeAnimation = state;
- q->setState(QAbstractItemView::ExpandingState);
- const QModelIndex index = viewItems.at(item).index;
- storeExpanded(index);
- viewItems[item].expanded = true;
- layout(item);
- q->setState(stateBeforeAnimation);
-
- if (model->canFetchMore(index))
- model->fetchMore(index);
- if (emitSignal) {
- emit q->expanded(index);
-#ifndef QT_NO_ANIMATION
- if (animationsEnabled)
- beginAnimatedOperation();
-#endif //QT_NO_ANIMATION
- }
-}
-
-void QTreeViewPrivate::insertViewItems(int pos, int count, const QTreeViewItem &viewItem)
-{
- viewItems.insert(pos, count, viewItem);
- QTreeViewItem *items = viewItems.data();
- for (int i = pos + count; i < viewItems.count(); i++)
- if (items[i].parentItem >= pos)
- items[i].parentItem += count;
-}
-
-void QTreeViewPrivate::removeViewItems(int pos, int count)
-{
- viewItems.remove(pos, count);
- QTreeViewItem *items = viewItems.data();
- for (int i = pos; i < viewItems.count(); i++)
- if (items[i].parentItem >= pos)
- items[i].parentItem -= count;
-}
-
-#if 0
-bool QTreeViewPrivate::checkViewItems() const
-{
- for (int i = 0; i < viewItems.count(); ++i) {
- const QTreeViewItem &vi = viewItems.at(i);
- if (vi.parentItem == -1) {
- Q_ASSERT(!vi.index.parent().isValid() || vi.index.parent() == root);
- } else {
- Q_ASSERT(vi.index.parent() == viewItems.at(vi.parentItem).index);
- }
- }
- return true;
-}
-#endif
-
-void QTreeViewPrivate::collapse(int item, bool emitSignal)
-{
- Q_Q(QTreeView);
-
- if (item == -1 || expandedIndexes.isEmpty())
- return;
-
- //if the current item is now invisible, the autoscroll will expand the tree to see it, so disable the autoscroll
- delayedAutoScroll.stop();
-
- int total = viewItems.at(item).total;
- const QModelIndex &modelIndex = viewItems.at(item).index;
- if (!isPersistent(modelIndex))
- return; // if the index is not persistent, no chances it is expanded
- QSet<QPersistentModelIndex>::iterator it = expandedIndexes.find(modelIndex);
- if (it == expandedIndexes.end() || viewItems.at(item).expanded == false)
- return; // nothing to do
-
-#ifndef QT_NO_ANIMATION
- if (emitSignal && animationsEnabled)
- prepareAnimatedOperation(item, QVariantAnimation::Backward);
-#endif //QT_NO_ANIMATION
-
- stateBeforeAnimation = state;
- q->setState(QAbstractItemView::CollapsingState);
- expandedIndexes.erase(it);
- viewItems[item].expanded = false;
- int index = item;
- while (index > -1) {
- viewItems[index].total -= total;
- index = viewItems[index].parentItem;
- }
- removeViewItems(item + 1, total); // collapse
- q->setState(stateBeforeAnimation);
-
- if (emitSignal) {
- emit q->collapsed(modelIndex);
-#ifndef QT_NO_ANIMATION
- if (animationsEnabled)
- beginAnimatedOperation();
-#endif //QT_NO_ANIMATION
- }
-}
-
-#ifndef QT_NO_ANIMATION
-void QTreeViewPrivate::prepareAnimatedOperation(int item, QVariantAnimation::Direction direction)
-{
- animatedOperation.item = item;
- animatedOperation.viewport = viewport;
- animatedOperation.setDirection(direction);
-
- int top = coordinateForItem(item) + itemHeight(item);
- QRect rect = viewport->rect();
- rect.setTop(top);
- if (direction == QVariantAnimation::Backward) {
- const int limit = rect.height() * 2;
- int h = 0;
- int c = item + viewItems.at(item).total + 1;
- for (int i = item + 1; i < c && h < limit; ++i)
- h += itemHeight(i);
- rect.setHeight(h);
- animatedOperation.setEndValue(top + h);
- }
- animatedOperation.setStartValue(top);
- animatedOperation.before = renderTreeToPixmapForAnimation(rect);
-}
-
-void QTreeViewPrivate::beginAnimatedOperation()
-{
- Q_Q(QTreeView);
-
- QRect rect = viewport->rect();
- rect.setTop(animatedOperation.top());
- if (animatedOperation.direction() == QVariantAnimation::Forward) {
- const int limit = rect.height() * 2;
- int h = 0;
- int c = animatedOperation.item + viewItems.at(animatedOperation.item).total + 1;
- for (int i = animatedOperation.item + 1; i < c && h < limit; ++i)
- h += itemHeight(i);
- rect.setHeight(h);
- animatedOperation.setEndValue(animatedOperation.top() + h);
- }
-
- if (!rect.isEmpty()) {
- animatedOperation.after = renderTreeToPixmapForAnimation(rect);
-
- q->setState(QAbstractItemView::AnimatingState);
- animatedOperation.start(); //let's start the animation
- }
-}
-
-void QTreeViewPrivate::drawAnimatedOperation(QPainter *painter) const
-{
- const int start = animatedOperation.startValue().toInt(),
- end = animatedOperation.endValue().toInt(),
- current = animatedOperation.currentValue().toInt();
- bool collapsing = animatedOperation.direction() == QVariantAnimation::Backward;
- const QPixmap top = collapsing ? animatedOperation.before : animatedOperation.after;
- painter->drawPixmap(0, start, top, 0, end - current - 1, top.width(), top.height());
- const QPixmap bottom = collapsing ? animatedOperation.after : animatedOperation.before;
- painter->drawPixmap(0, current, bottom);
-}
-
-QPixmap QTreeViewPrivate::renderTreeToPixmapForAnimation(const QRect &rect) const
-{
- Q_Q(const QTreeView);
- QPixmap pixmap(rect.size());
- if (rect.size().isEmpty())
- return pixmap;
- pixmap.fill(Qt::transparent); //the base might not be opaque, and we don't want uninitialized pixels.
- QPainter painter(&pixmap);
- painter.fillRect(QRect(QPoint(0,0), rect.size()), q->palette().base());
- painter.translate(0, -rect.top());
- q->drawTree(&painter, QRegion(rect));
- painter.end();
-
- //and now let's render the editors the editors
- QStyleOptionViewItemV4 option = viewOptionsV4();
- for (QEditorIndexHash::const_iterator it = editorIndexHash.constBegin(); it != editorIndexHash.constEnd(); ++it) {
- QWidget *editor = it.key();
- const QModelIndex &index = it.value();
- option.rect = q->visualRect(index);
- if (option.rect.isValid()) {
-
- if (QAbstractItemDelegate *delegate = delegateForIndex(index))
- delegate->updateEditorGeometry(editor, option, index);
-
- const QPoint pos = editor->pos();
- if (rect.contains(pos)) {
- editor->render(&pixmap, pos - rect.topLeft());
- //the animation uses pixmap to display the treeview's content
- //the editor is rendered on this pixmap and thus can (should) be hidden
- editor->hide();
- }
- }
- }
-
-
- return pixmap;
-}
-
-void QTreeViewPrivate::_q_endAnimatedOperation()
-{
- Q_Q(QTreeView);
- q->setState(stateBeforeAnimation);
- q->updateGeometries();
- viewport->update();
-}
-#endif //QT_NO_ANIMATION
-
-void QTreeViewPrivate::_q_modelAboutToBeReset()
-{
- viewItems.clear();
-}
-
-void QTreeViewPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
-{
- if (start <= 0 && 0 <= end)
- viewItems.clear();
- QAbstractItemViewPrivate::_q_columnsAboutToBeRemoved(parent, start, end);
-}
-
-void QTreeViewPrivate::_q_columnsRemoved(const QModelIndex &parent, int start, int end)
-{
- if (start <= 0 && 0 <= end)
- doDelayedItemsLayout();
- QAbstractItemViewPrivate::_q_columnsRemoved(parent, start, end);
-}
-
-/** \internal
- creates and initialize the viewItem structure of the children of the element \i
-
- set \a recursiveExpanding if the function has to expand all the children (called from expandAll)
- \a afterIsUninitialized is when we recurse from layout(-1), it means all the items after 'i' are
- not yet initialized and need not to be moved
- */
-void QTreeViewPrivate::layout(int i, bool recursiveExpanding, bool afterIsUninitialized)
-{
- Q_Q(QTreeView);
- QModelIndex current;
- QModelIndex parent = (i < 0) ? (QModelIndex)root : modelIndex(i);
-
- if (i>=0 && !parent.isValid()) {
- //modelIndex() should never return something invalid for the real items.
- //This can happen if columncount has been set to 0.
- //To avoid infinite loop we stop here.
- return;
- }
-
- int count = 0;
- if (model->hasChildren(parent)) {
- if (model->canFetchMore(parent))
- model->fetchMore(parent);
- count = model->rowCount(parent);
- }
-
- bool expanding = true;
- if (i == -1) {
- if (uniformRowHeights) {
- QModelIndex index = model->index(0, 0, parent);
- defaultItemHeight = q->indexRowSizeHint(index);
- }
- viewItems.resize(count);
- afterIsUninitialized = true;
- } else if (viewItems[i].total != (uint)count) {
- if (!afterIsUninitialized)
- insertViewItems(i + 1, count, QTreeViewItem()); // expand
- else if (count > 0)
- viewItems.resize(viewItems.count() + count);
- } else {
- expanding = false;
- }
-
- int first = i + 1;
- int level = (i >= 0 ? viewItems.at(i).level + 1 : 0);
- int hidden = 0;
- int last = 0;
- int children = 0;
- QTreeViewItem *item = 0;
- for (int j = first; j < first + count; ++j) {
- current = model->index(j - first, 0, parent);
- if (isRowHidden(current)) {
- ++hidden;
- last = j - hidden + children;
- } else {
- last = j - hidden + children;
- if (item)
- item->hasMoreSiblings = true;
- item = &viewItems[last];
- item->index = current;
- item->parentItem = i;
- item->level = level;
- item->height = 0;
- item->spanning = q->isFirstColumnSpanned(current.row(), parent);
- item->expanded = false;
- item->total = 0;
- item->hasMoreSiblings = false;
- if (recursiveExpanding || isIndexExpanded(current)) {
- if (recursiveExpanding)
- expandedIndexes.insert(current);
- item->expanded = true;
- layout(last, recursiveExpanding, afterIsUninitialized);
- item = &viewItems[last];
- children += item->total;
- item->hasChildren = item->total > 0;
- last = j - hidden + children;
- } else {
- item->hasChildren = hasVisibleChildren(current);
- }
- }
- }
-
- // remove hidden items
- if (hidden > 0) {
- if (!afterIsUninitialized)
- removeViewItems(last + 1, hidden);
- else
- viewItems.resize(viewItems.size() - hidden);
- }
-
- if (!expanding)
- return; // nothing changed
-
- while (i > -1) {
- viewItems[i].total += count - hidden;
- i = viewItems[i].parentItem;
- }
-}
-
-int QTreeViewPrivate::pageUp(int i) const
-{
- int index = itemAtCoordinate(coordinateForItem(i) - viewport->height());
- while (isItemHiddenOrDisabled(index))
- index--;
- return index == -1 ? 0 : index;
-}
-
-int QTreeViewPrivate::pageDown(int i) const
-{
- int index = itemAtCoordinate(coordinateForItem(i) + viewport->height());
- while (isItemHiddenOrDisabled(index))
- index++;
- return index == -1 ? viewItems.count() - 1 : index;
-}
-
-int QTreeViewPrivate::indentationForItem(int item) const
-{
- if (item < 0 || item >= viewItems.count())
- return 0;
- int level = viewItems.at(item).level;
- if (rootDecoration)
- ++level;
- return level * indent;
-}
-
-int QTreeViewPrivate::itemHeight(int item) const
-{
- if (uniformRowHeights)
- return defaultItemHeight;
- if (viewItems.isEmpty())
- return 0;
- const QModelIndex &index = viewItems.at(item).index;
- if (!index.isValid())
- return 0;
- int height = viewItems.at(item).height;
- if (height <= 0) {
- height = q_func()->indexRowSizeHint(index);
- viewItems[item].height = height;
- }
- return qMax(height, 0);
-}
-
-
-/*!
- \internal
- Returns the viewport y coordinate for \a item.
-*/
-int QTreeViewPrivate::coordinateForItem(int item) const
-{
- if (verticalScrollMode == QAbstractItemView::ScrollPerPixel) {
- if (uniformRowHeights)
- return (item * defaultItemHeight) - vbar->value();
- // ### optimize (spans or caching)
- int y = 0;
- for (int i = 0; i < viewItems.count(); ++i) {
- if (i == item)
- return y - vbar->value();
- y += itemHeight(i);
- }
- } else { // ScrollPerItem
- int topViewItemIndex = vbar->value();
- if (uniformRowHeights)
- return defaultItemHeight * (item - topViewItemIndex);
- if (item >= topViewItemIndex) {
- // search in the visible area first and continue down
- // ### slow if the item is not visible
- int viewItemCoordinate = 0;
- int viewItemIndex = topViewItemIndex;
- while (viewItemIndex < viewItems.count()) {
- if (viewItemIndex == item)
- return viewItemCoordinate;
- viewItemCoordinate += itemHeight(viewItemIndex);
- ++viewItemIndex;
- }
- // below the last item in the view
- Q_ASSERT(false);
- return viewItemCoordinate;
- } else {
- // search the area above the viewport (used for editor widgets)
- int viewItemCoordinate = 0;
- for (int viewItemIndex = topViewItemIndex; viewItemIndex > 0; --viewItemIndex) {
- if (viewItemIndex == item)
- return viewItemCoordinate;
- viewItemCoordinate -= itemHeight(viewItemIndex - 1);
- }
- return viewItemCoordinate;
- }
- }
- return 0;
-}
-
-/*!
- \internal
- Returns the index of the view item at the
- given viewport \a coordinate.
-
- \sa modelIndex()
-*/
-int QTreeViewPrivate::itemAtCoordinate(int coordinate) const
-{
- const int itemCount = viewItems.count();
- if (itemCount == 0)
- return -1;
- if (uniformRowHeights && defaultItemHeight <= 0)
- return -1;
- if (verticalScrollMode == QAbstractItemView::ScrollPerPixel) {
- if (uniformRowHeights) {
- const int viewItemIndex = (coordinate + vbar->value()) / defaultItemHeight;
- return ((viewItemIndex >= itemCount || viewItemIndex < 0) ? -1 : viewItemIndex);
- }
- // ### optimize
- int viewItemCoordinate = 0;
- const int contentsCoordinate = coordinate + vbar->value();
- for (int viewItemIndex = 0; viewItemIndex < viewItems.count(); ++viewItemIndex) {
- viewItemCoordinate += itemHeight(viewItemIndex);
- if (viewItemCoordinate >= contentsCoordinate)
- return (viewItemIndex >= itemCount ? -1 : viewItemIndex);
- }
- } else { // ScrollPerItem
- int topViewItemIndex = vbar->value();
- if (uniformRowHeights) {
- if (coordinate < 0)
- coordinate -= defaultItemHeight - 1;
- const int viewItemIndex = topViewItemIndex + (coordinate / defaultItemHeight);
- return ((viewItemIndex >= itemCount || viewItemIndex < 0) ? -1 : viewItemIndex);
- }
- if (coordinate >= 0) {
- // the coordinate is in or below the viewport
- int viewItemCoordinate = 0;
- for (int viewItemIndex = topViewItemIndex; viewItemIndex < viewItems.count(); ++viewItemIndex) {
- viewItemCoordinate += itemHeight(viewItemIndex);
- if (viewItemCoordinate > coordinate)
- return (viewItemIndex >= itemCount ? -1 : viewItemIndex);
- }
- } else {
- // the coordinate is above the viewport
- int viewItemCoordinate = 0;
- for (int viewItemIndex = topViewItemIndex; viewItemIndex >= 0; --viewItemIndex) {
- if (viewItemCoordinate <= coordinate)
- return (viewItemIndex >= itemCount ? -1 : viewItemIndex);
- viewItemCoordinate -= itemHeight(viewItemIndex);
- }
- }
- }
- return -1;
-}
-
-int QTreeViewPrivate::viewIndex(const QModelIndex &_index) const
-{
- if (!_index.isValid() || viewItems.isEmpty())
- return -1;
-
- const int totalCount = viewItems.count();
- const QModelIndex index = _index.sibling(_index.row(), 0);
- const int row = index.row();
- const qint64 internalId = index.internalId();
-
- // We start nearest to the lastViewedItem
- int localCount = qMin(lastViewedItem - 1, totalCount - lastViewedItem);
- for (int i = 0; i < localCount; ++i) {
- const QModelIndex &idx1 = viewItems.at(lastViewedItem + i).index;
- if (idx1.row() == row && idx1.internalId() == internalId) {
- lastViewedItem = lastViewedItem + i;
- return lastViewedItem;
- }
- const QModelIndex &idx2 = viewItems.at(lastViewedItem - i - 1).index;
- if (idx2.row() == row && idx2.internalId() == internalId) {
- lastViewedItem = lastViewedItem - i - 1;
- return lastViewedItem;
- }
- }
-
- for (int j = qMax(0, lastViewedItem + localCount); j < totalCount; ++j) {
- const QModelIndex &idx = viewItems.at(j).index;
- if (idx.row() == row && idx.internalId() == internalId) {
- lastViewedItem = j;
- return j;
- }
- }
- for (int j = qMin(totalCount, lastViewedItem - localCount) - 1; j >= 0; --j) {
- const QModelIndex &idx = viewItems.at(j).index;
- if (idx.row() == row && idx.internalId() == internalId) {
- lastViewedItem = j;
- return j;
- }
- }
-
- // nothing found
- return -1;
-}
-
-QModelIndex QTreeViewPrivate::modelIndex(int i, int column) const
-{
- if (i < 0 || i >= viewItems.count())
- return QModelIndex();
-
- QModelIndex ret = viewItems.at(i).index;
- if (column)
- ret = ret.sibling(ret.row(), column);
- return ret;
-}
-
-int QTreeViewPrivate::firstVisibleItem(int *offset) const
-{
- const int value = vbar->value();
- if (verticalScrollMode == QAbstractItemView::ScrollPerItem) {
- if (offset)
- *offset = 0;
- return (value < 0 || value >= viewItems.count()) ? -1 : value;
- }
- // ScrollMode == ScrollPerPixel
- if (uniformRowHeights) {
- if (!defaultItemHeight)
- return -1;
-
- if (offset)
- *offset = -(value % defaultItemHeight);
- return value / defaultItemHeight;
- }
- int y = 0; // ### optimize (use spans ?)
- for (int i = 0; i < viewItems.count(); ++i) {
- y += itemHeight(i); // the height value is cached
- if (y > value) {
- if (offset)
- *offset = y - value - itemHeight(i);
- return i;
- }
- }
- return -1;
-}
-
-int QTreeViewPrivate::columnAt(int x) const
-{
- return header->logicalIndexAt(x);
-}
-
-void QTreeViewPrivate::updateScrollBars()
-{
- Q_Q(QTreeView);
- QSize viewportSize = viewport->size();
- if (!viewportSize.isValid())
- viewportSize = QSize(0, 0);
-
- if (viewItems.isEmpty()) {
- q->doItemsLayout();
- }
-
- int itemsInViewport = 0;
- if (uniformRowHeights) {
- if (defaultItemHeight <= 0)
- itemsInViewport = viewItems.count();
- else
- itemsInViewport = viewportSize.height() / defaultItemHeight;
- } else {
- const int itemsCount = viewItems.count();
- const int viewportHeight = viewportSize.height();
- for (int height = 0, item = itemsCount - 1; item >= 0; --item) {
- height += itemHeight(item);
- if (height > viewportHeight)
- break;
- ++itemsInViewport;
- }
- }
- if (verticalScrollMode == QAbstractItemView::ScrollPerItem) {
- if (!viewItems.isEmpty())
- itemsInViewport = qMax(1, itemsInViewport);
- vbar->setRange(0, viewItems.count() - itemsInViewport);
- vbar->setPageStep(itemsInViewport);
- vbar->setSingleStep(1);
- } else { // scroll per pixel
- int contentsHeight = 0;
- if (uniformRowHeights) {
- contentsHeight = defaultItemHeight * viewItems.count();
- } else { // ### optimize (spans or caching)
- for (int i = 0; i < viewItems.count(); ++i)
- contentsHeight += itemHeight(i);
- }
- vbar->setRange(0, contentsHeight - viewportSize.height());
- vbar->setPageStep(viewportSize.height());
- vbar->setSingleStep(qMax(viewportSize.height() / (itemsInViewport + 1), 2));
- }
-
- const int columnCount = header->count();
- const int viewportWidth = viewportSize.width();
- int columnsInViewport = 0;
- for (int width = 0, column = columnCount - 1; column >= 0; --column) {
- int logical = header->logicalIndex(column);
- width += header->sectionSize(logical);
- if (width > viewportWidth)
- break;
- ++columnsInViewport;
- }
- if (columnCount > 0)
- columnsInViewport = qMax(1, columnsInViewport);
- if (horizontalScrollMode == QAbstractItemView::ScrollPerItem) {
- hbar->setRange(0, columnCount - columnsInViewport);
- hbar->setPageStep(columnsInViewport);
- hbar->setSingleStep(1);
- } else { // scroll per pixel
- const int horizontalLength = header->length();
- const QSize maxSize = q->maximumViewportSize();
- if (maxSize.width() >= horizontalLength && vbar->maximum() <= 0)
- viewportSize = maxSize;
- hbar->setPageStep(viewportSize.width());
- hbar->setRange(0, qMax(horizontalLength - viewportSize.width(), 0));
- hbar->setSingleStep(qMax(viewportSize.width() / (columnsInViewport + 1), 2));
- }
-}
-
-int QTreeViewPrivate::itemDecorationAt(const QPoint &pos) const
-{
- executePostedLayout();
- int x = pos.x();
- int column = header->logicalIndexAt(x);
- if (column != 0)
- return -1; // no logical index at x
-
- int viewItemIndex = itemAtCoordinate(pos.y());
- QRect returning = itemDecorationRect(modelIndex(viewItemIndex));
- if (!returning.contains(pos))
- return -1;
-
- return viewItemIndex;
-}
-
-QRect QTreeViewPrivate::itemDecorationRect(const QModelIndex &index) const
-{
- Q_Q(const QTreeView);
- if (!rootDecoration && index.parent() == root)
- return QRect(); // no decoration at root
-
- int viewItemIndex = viewIndex(index);
- if (viewItemIndex < 0 || !hasVisibleChildren(viewItems.at(viewItemIndex).index))
- return QRect();
-
- int itemIndentation = indentationForItem(viewItemIndex);
- int position = header->sectionViewportPosition(0);
- int size = header->sectionSize(0);
-
- QRect rect;
- if (q->isRightToLeft())
- rect = QRect(position + size - itemIndentation, coordinateForItem(viewItemIndex),
- indent, itemHeight(viewItemIndex));
- else
- rect = QRect(position + itemIndentation - indent, coordinateForItem(viewItemIndex),
- indent, itemHeight(viewItemIndex));
- QStyleOption opt;
- opt.initFrom(q);
- opt.rect = rect;
- return q->style()->subElementRect(QStyle::SE_TreeViewDisclosureItem, &opt, q);
-}
-
-QList<QPair<int, int> > QTreeViewPrivate::columnRanges(const QModelIndex &topIndex,
- const QModelIndex &bottomIndex) const
-{
- const int topVisual = header->visualIndex(topIndex.column()),
- bottomVisual = header->visualIndex(bottomIndex.column());
-
- const int start = qMin(topVisual, bottomVisual);
- const int end = qMax(topVisual, bottomVisual);
-
- QList<int> logicalIndexes;
-
- //we iterate over the visual indexes to get the logical indexes
- for (int c = start; c <= end; c++) {
- const int logical = header->logicalIndex(c);
- if (!header->isSectionHidden(logical)) {
- logicalIndexes << logical;
- }
- }
- //let's sort the list
- qSort(logicalIndexes.begin(), logicalIndexes.end());
-
- QList<QPair<int, int> > ret;
- QPair<int, int> current;
- current.first = -2; // -1 is not enough because -1+1 = 0
- current.second = -2;
- for(int i = 0; i < logicalIndexes.count(); ++i) {
- const int logicalColumn = logicalIndexes.at(i);
- if (current.second + 1 != logicalColumn) {
- if (current.first != -2) {
- //let's save the current one
- ret += current;
- }
- //let's start a new one
- current.first = current.second = logicalColumn;
- } else {
- current.second++;
- }
- }
-
- //let's get the last range
- if (current.first != -2) {
- ret += current;
- }
-
- return ret;
-}
-
-void QTreeViewPrivate::select(const QModelIndex &topIndex, const QModelIndex &bottomIndex,
- QItemSelectionModel::SelectionFlags command)
-{
- Q_Q(QTreeView);
- QItemSelection selection;
- const int top = viewIndex(topIndex),
- bottom = viewIndex(bottomIndex);
-
- const QList< QPair<int, int> > colRanges = columnRanges(topIndex, bottomIndex);
- QList< QPair<int, int> >::const_iterator it;
- for (it = colRanges.begin(); it != colRanges.end(); ++it) {
- const int left = (*it).first,
- right = (*it).second;
-
- QModelIndex previous;
- QItemSelectionRange currentRange;
- QStack<QItemSelectionRange> rangeStack;
- for (int i = top; i <= bottom; ++i) {
- QModelIndex index = modelIndex(i);
- QModelIndex parent = index.parent();
- QModelIndex previousParent = previous.parent();
- if (previous.isValid() && parent == previousParent) {
- // same parent
- if (qAbs(previous.row() - index.row()) > 1) {
- //a hole (hidden index inside a range) has been detected
- if (currentRange.isValid()) {
- selection.append(currentRange);
- }
- //let's start a new range
- currentRange = QItemSelectionRange(index.sibling(index.row(), left), index.sibling(index.row(), right));
- } else {
- QModelIndex tl = model->index(currentRange.top(), currentRange.left(),
- currentRange.parent());
- currentRange = QItemSelectionRange(tl, index.sibling(index.row(), right));
- }
- } else if (previous.isValid() && parent == model->index(previous.row(), 0, previousParent)) {
- // item is child of previous
- rangeStack.push(currentRange);
- currentRange = QItemSelectionRange(index.sibling(index.row(), left), index.sibling(index.row(), right));
- } else {
- if (currentRange.isValid())
- selection.append(currentRange);
- if (rangeStack.isEmpty()) {
- currentRange = QItemSelectionRange(index.sibling(index.row(), left), index.sibling(index.row(), right));
- } else {
- currentRange = rangeStack.pop();
- index = currentRange.bottomRight(); //let's resume the range
- --i; //we process again the current item
- }
- }
- previous = index;
- }
- if (currentRange.isValid())
- selection.append(currentRange);
- for (int i = 0; i < rangeStack.count(); ++i)
- selection.append(rangeStack.at(i));
- }
- q->selectionModel()->select(selection, command);
-}
-
-QPair<int,int> QTreeViewPrivate::startAndEndColumns(const QRect &rect) const
-{
- Q_Q(const QTreeView);
- int start = header->visualIndexAt(rect.left());
- int end = header->visualIndexAt(rect.right());
- if (q->isRightToLeft()) {
- start = (start == -1 ? header->count() - 1 : start);
- end = (end == -1 ? 0 : end);
- } else {
- start = (start == -1 ? 0 : start);
- end = (end == -1 ? header->count() - 1 : end);
- }
- return qMakePair<int,int>(qMin(start, end), qMax(start, end));
-}
-
-bool QTreeViewPrivate::hasVisibleChildren(const QModelIndex& parent) const
-{
- Q_Q(const QTreeView);
- if (model->hasChildren(parent)) {
- if (hiddenIndexes.isEmpty())
- return true;
- if (q->isIndexHidden(parent))
- return false;
- int rowCount = model->rowCount(parent);
- for (int i = 0; i < rowCount; ++i) {
- if (!q->isRowHidden(i, parent))
- return true;
- }
- if (rowCount == 0)
- return true;
- }
- return false;
-}
-
-void QTreeViewPrivate::_q_sortIndicatorChanged(int column, Qt::SortOrder order)
-{
- model->sort(column, order);
-}
-
-/*!
- \reimp
- */
-void QTreeView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
-{
-#ifndef QT_NO_ACCESSIBILITY
- if (QAccessible::isActive()) {
- int entry = visualIndex(current) + 1;
- if (header())
- ++entry;
- QAccessible::updateAccessibility(viewport(), entry, QAccessible::Focus);
- }
-#endif
- QAbstractItemView::currentChanged(current, previous);
-
- if (allColumnsShowFocus()) {
- if (previous.isValid()) {
- QRect previousRect = visualRect(previous);
- previousRect.setX(0);
- previousRect.setWidth(viewport()->width());
- viewport()->update(previousRect);
- }
- if (current.isValid()) {
- QRect currentRect = visualRect(current);
- currentRect.setX(0);
- currentRect.setWidth(viewport()->width());
- viewport()->update(currentRect);
- }
- }
-}
-
-/*!
- \reimp
- */
-void QTreeView::selectionChanged(const QItemSelection &selected,
- const QItemSelection &deselected)
-{
-#ifndef QT_NO_ACCESSIBILITY
- if (QAccessible::isActive()) {
- // ### does not work properly for selection ranges.
- QModelIndex sel = selected.indexes().value(0);
- if (sel.isValid()) {
- int entry = visualIndex(sel) + 1;
- if (header())
- ++entry;
- QAccessible::updateAccessibility(viewport(), entry, QAccessible::Selection);
- }
- QModelIndex desel = deselected.indexes().value(0);
- if (desel.isValid()) {
- int entry = visualIndex(desel) + 1;
- if (header())
- ++entry;
- QAccessible::updateAccessibility(viewport(), entry, QAccessible::SelectionRemove);
- }
- }
-#endif
- QAbstractItemView::selectionChanged(selected, deselected);
-}
-
-int QTreeView::visualIndex(const QModelIndex &index) const
-{
- Q_D(const QTreeView);
- d->executePostedLayout();
- return d->viewIndex(index);
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qtreeview.cpp"
-
-#endif // QT_NO_TREEVIEW