aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquicktreeview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/items/qquicktreeview.cpp')
-rw-r--r--src/quick/items/qquicktreeview.cpp115
1 files changed, 66 insertions, 49 deletions
diff --git a/src/quick/items/qquicktreeview.cpp b/src/quick/items/qquicktreeview.cpp
index e73eb459d4..033884d58d 100644
--- a/src/quick/items/qquicktreeview.cpp
+++ b/src/quick/items/qquicktreeview.cpp
@@ -42,7 +42,7 @@
a set of properties that can be used to position and render each node
in the tree correctly.
- An example of a custom delegate is shown below:
+ An example of a custom delegate with an animating indicator is shown below:
\snippet qml/treeview/qml-customdelegate.qml 0
@@ -81,16 +81,26 @@
By default, TreeView \l {toggleExpanded()}{toggles} the expanded state
of a row when you double tap on it. Since this is in conflict with
- double tapping to edit a cell, TreeView sets \l editTriggers to
+ double tapping to edit a cell, TreeView sets \l {TableView::}{editTriggers} to
\c TableView.EditKeyPressed by default (which is different from TableView,
which uses \c {TableView.EditKeyPressed | TableView.DoubleTapped}.
- If you change \l editTriggers to also contain \c TableView.DoubleTapped,
+ If you change \l {TableView::}{editTriggers} to also contain \c TableView.DoubleTapped,
toggling the expanded state with a double tap will be disabled.
\note A TreeView only accepts a model that inherits \l QAbstractItemModel.
*/
/*!
+ \qmlproperty QModelIndex QtQuick::TreeView::rootIndex
+ \since 6.6
+
+ This property holds the model index of the root item in the tree.
+ By default, this is the same as the root index in the model, but you can
+ set it to be a child index instead, to show only a branch of the tree.
+ Set it to \c undefined to show the whole model.
+*/
+
+/*!
\qmlmethod int QtQuick::TreeView::depth(row)
Returns the depth (the number of parents up to the root) of the given \a row.
@@ -268,9 +278,6 @@ void QQuickTreeViewPrivate::setModelImpl(const QVariant &newModel)
{
Q_Q(QQuickTreeView);
- if (newModel == m_assignedModel)
- return;
-
m_assignedModel = newModel;
QVariant effectiveModel = m_assignedModel;
if (effectiveModel.userType() == qMetaTypeId<QJSValue>())
@@ -337,55 +344,39 @@ void QQuickTreeViewPrivate::updateSelection(const QRect &oldSelection, const QRe
{
Q_Q(QQuickTreeView);
- const QRect oldRect = oldSelection.normalized();
- const QRect newRect = newSelection.normalized();
-
if (oldSelection == newSelection)
return;
- // Select the rows inside newRect that doesn't overlap with oldRect
- for (int row = newRect.y(); row <= newRect.y() + newRect.height(); ++row) {
- if (oldRect.y() != -1 && oldRect.y() <= row && row <= oldRect.y() + oldRect.height())
- continue;
- const QModelIndex startIndex = q->modelIndex(row, newRect.x());
- const QModelIndex endIndex = q->modelIndex(row, newRect.x() + newRect.width());
- selectionModel->select(QItemSelection(startIndex, endIndex), QItemSelectionModel::Select);
+ QItemSelection select;
+ QItemSelection deselect;
+
+ // Because each row can have a different parent, we need to create separate QItemSelections
+ // per row. But all the cells in a given row have the same parent, so they can be combined.
+ // As a result, the final QItemSelection can end up more fragmented compared to a selection
+ // in QQuickTableView, where all cells have the same parent. In the end, if TreeView has
+ // a lot of columns and the selection mode is "SelectCells", using the mouse to adjust
+ // a selection containing a _large_ number of columns can be slow.
+ const QRect cells = newSelection.normalized();
+ for (int row = cells.y(); row <= cells.y() + cells.height(); ++row) {
+ const QModelIndex startIndex = q->index(row, cells.x());
+ const QModelIndex endIndex = q->index(row, cells.x() + cells.width());
+ select.merge(QItemSelection(startIndex, endIndex), QItemSelectionModel::Select);
}
- if (oldRect.x() != -1) {
- // Since oldRect is valid, this update is a continuation of an already existing selection!
-
- // Select the columns inside newRect that don't overlap with oldRect
- for (int column = newRect.x(); column <= newRect.x() + newRect.width(); ++column) {
- if (oldRect.x() <= column && column <= oldRect.x() + oldRect.width())
- continue;
- for (int row = newRect.y(); row <= newRect.y() + newRect.height(); ++row)
- selectionModel->select(q->modelIndex(row, column), QItemSelectionModel::Select);
- }
-
- // Unselect the rows inside oldRect that don't overlap with newRect
- for (int row = oldRect.y(); row <= oldRect.y() + oldRect.height(); ++row) {
- if (newRect.y() <= row && row <= newRect.y() + newRect.height())
- continue;
- const QModelIndex startIndex = q->modelIndex(row, oldRect.x());
- const QModelIndex endIndex = q->modelIndex(row, oldRect.x() + oldRect.width());
- selectionModel->select(QItemSelection(startIndex, endIndex), QItemSelectionModel::Deselect);
- }
+ const QModelIndexList indexes = selectionModel->selection().indexes();
+ for (const QModelIndex &index : indexes) {
+ if (!select.contains(index) && !existingSelection.contains(index))
+ deselect.merge(QItemSelection(index, index), QItemSelectionModel::Select);
+ }
- // Unselect the columns inside oldRect that don't overlap with newRect
- for (int column = oldRect.x(); column <= oldRect.x() + oldRect.width(); ++column) {
- if (newRect.x() <= column && column <= newRect.x() + newRect.width())
- continue;
- // Since we're not allowed to call select/unselect on the selectionModel with
- // indices from different parents, and since indicies from different parents are
- // expected when working with trees, we need to unselect the indices in the column
- // one by one, rather than the whole column in one go. This, however, can cause a
- // lot of selection fragments in the selectionModel, which eventually can hurt
- // performance. But large selections containing a lot of columns is not normally
- // the case for a treeview, so accept this potential corner case for now.
- for (int row = newRect.y(); row <= newRect.y() + newRect.height(); ++row)
- selectionModel->select(q->modelIndex(row, column), QItemSelectionModel::Deselect);
- }
+ if (selectionFlag == QItemSelectionModel::Select) {
+ selectionModel->select(deselect, QItemSelectionModel::Deselect);
+ selectionModel->select(select, QItemSelectionModel::Select);
+ } else {
+ QItemSelection oldSelection = existingSelection;
+ oldSelection.merge(select, QItemSelectionModel::Deselect);
+ selectionModel->select(oldSelection, QItemSelectionModel::Select);
+ selectionModel->select(select, QItemSelectionModel::Deselect);
}
}
@@ -403,6 +394,8 @@ QQuickTreeView::QQuickTreeView(QQuickItem *parent)
d->QQuickTableViewPrivate::setModelImpl(modelAsVariant);
QObjectPrivate::connect(&d->m_treeModelToTableModel, &QAbstractItemModel::dataChanged,
d, &QQuickTreeViewPrivate::dataChangedCallback);
+ QObject::connect(&d->m_treeModelToTableModel, &QQmlTreeModelToTableModel::rootIndexChanged,
+ this, &QQuickTreeView::rootIndexChanged);
auto tapHandler = new QQuickTapHandler(this);
tapHandler->setAcceptedModifiers(Qt::NoModifier);
@@ -421,6 +414,25 @@ QQuickTreeView::~QQuickTreeView()
{
}
+QModelIndex QQuickTreeView::rootIndex() const
+{
+ return d_func()->m_treeModelToTableModel.rootIndex();
+}
+
+void QQuickTreeView::setRootIndex(const QModelIndex &index)
+{
+ Q_D(QQuickTreeView);
+ d->m_treeModelToTableModel.setRootIndex(index);
+ positionViewAtCell({0, 0}, QQuickTableView::AlignTop | QQuickTableView::AlignLeft);
+}
+
+void QQuickTreeView::resetRootIndex()
+{
+ Q_D(QQuickTreeView);
+ d->m_treeModelToTableModel.resetRootIndex();
+ positionViewAtCell({0, 0}, QQuickTableView::AlignTop | QQuickTableView::AlignLeft);
+}
+
int QQuickTreeView::depth(int row) const
{
Q_D(const QQuickTreeView);
@@ -610,6 +622,7 @@ QPoint QQuickTreeView::cellAtIndex(const QModelIndex &index) const
return QPoint(tableIndex.column(), tableIndex.row());
}
+#if QT_DEPRECATED_SINCE(6, 4)
QModelIndex QQuickTreeView::modelIndex(int row, int column) const
{
static const bool compat6_4 = qEnvironmentVariable("QT_QUICK_TABLEVIEW_COMPAT_VERSION") == QStringLiteral("6.4");
@@ -621,9 +634,13 @@ QModelIndex QQuickTreeView::modelIndex(int row, int column) const
// to continue accepting calls to modelIndex(column, row).
return modelIndex({row, column});
} else {
+ qmlWarning(this) << "modelIndex(row, column) is deprecated. "
+ "Use index(row, column) instead. For more information, see "
+ "https://doc.qt.io/qt-6/qml-qtquick-tableview-obsolete.html";
return modelIndex({column, row});
}
}
+#endif
void QQuickTreeView::keyPressEvent(QKeyEvent *event)
{