aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/doc/snippets/qml/tableview/overlay.qml46
-rw-r--r--src/quick/items/qquicktableview.cpp36
-rw-r--r--src/quick/items/qquicktableview_p.h1
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp47
4 files changed, 130 insertions, 0 deletions
diff --git a/src/quick/doc/snippets/qml/tableview/overlay.qml b/src/quick/doc/snippets/qml/tableview/overlay.qml
new file mode 100644
index 0000000000..b79e457f81
--- /dev/null
+++ b/src/quick/doc/snippets/qml/tableview/overlay.qml
@@ -0,0 +1,46 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Window
+
+Window {
+ width: 480
+ height: 640
+ visible: true
+ visibility: Window.AutomaticVisibility
+
+ TableView {
+ id: tableView
+ anchors.fill: parent
+ clip: true
+ }
+
+ //![0]
+ Rectangle {
+ id: overlay
+ width: 20
+ height: 20
+ radius: 10
+ color: "blue"
+
+ z: 10
+ parent: tableView.contentItem
+
+ Connections {
+ target: tableView
+ function onLayoutChanged() {
+ let item = tableView.itemAtCell(5, 5)
+ let insideViewport = item !== null
+
+ overlay.visible = insideViewport
+ if (insideViewport) {
+ overlay.x = item.x
+ overlay.y = item.y
+ }
+ }
+ }
+ }
+ //![0]
+
+}
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index 38807ba0b3..314408e357 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -194,6 +194,19 @@
\snippet qml/tableview/tableviewwithheader.qml 0
+ Here is another example that shows how to create an overlay item that
+ stays on top of a particular cell. This requires a bit more code, since
+ the location of a cell will \l {layoutChanged}{change} if the user, for
+ example, is resizing a column in front of it.
+
+ \snippet qml/tableview/overlay.qml 0
+
+ You could also parent the overlay directly to the cell instead of the
+ \l contentItem. But doing so will be fragile since the cell is unloaded
+ or reused whenever it's flicked out of the viewport.
+
+ \sa layoutChanged()
+
\section1 Selecting items
You can add selection support to TableView by assigning an \l ItemSelectionModel to
@@ -1198,6 +1211,22 @@
*/
/*!
+ \qmlsignal QtQuick::TableView::layoutChanged()
+ \since 6.5
+
+ This signal is emitted whenever the layout of the
+ \l {isColumnLoaded()}{loaded} rows and columns has potentially
+ changed. This will especially be the case when \l forceLayout()
+ is called, but also when e.g resizing a row or a column, or
+ when a row or column have entered or left the viewport.
+
+ This signal can be used to for example update the geometry
+ of overlays.
+
+ \sa forceLayout(), {Overlays and underlays}
+*/
+
+/*!
\qmlattachedproperty TableView QtQuick::TableView::view
This attached property holds the view that manages the delegate instance.
@@ -3098,6 +3127,8 @@ void QQuickTableViewPrivate::processLoadRequest()
if (editIndex.isValid())
updateEditItem();
+
+ emit q->layoutChanged();
}
loadRequest.markAsDone();
@@ -3204,6 +3235,8 @@ void QQuickTableViewPrivate::processRebuildTable()
updateEditItem();
updateCurrentRowAndColumn();
+ emit q->layoutChanged();
+
qCDebug(lcTableViewDelegateLifecycle()) << "current table:" << tableLayoutToString();
qCDebug(lcTableViewDelegateLifecycle()) << "rebuild completed!";
qCDebug(lcTableViewDelegateLifecycle()) << "################################################";
@@ -3556,6 +3589,9 @@ void QQuickTableViewPrivate::unloadEdge(Qt::Edge edge)
break; }
}
+ if (rebuildState == RebuildState::Done)
+ emit q->layoutChanged();
+
qCDebug(lcTableViewDelegateLifecycle) << tableLayoutToString();
}
diff --git a/src/quick/items/qquicktableview_p.h b/src/quick/items/qquicktableview_p.h
index 0366c9d250..bce6b55b54 100644
--- a/src/quick/items/qquicktableview_p.h
+++ b/src/quick/items/qquicktableview_p.h
@@ -242,6 +242,7 @@ Q_SIGNALS:
Q_REVISION(6, 5) void resizableColumnsChanged();
Q_REVISION(6, 5) void resizableRowsChanged();
Q_REVISION(6, 5) void editTriggersChanged();
+ Q_REVISION(6, 5) void layoutChanged();
protected:
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override;
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index 12c50185ea..408c3c7603 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -104,6 +104,7 @@ private slots:
void checkForceLayoutEndUpDoingALayout();
void checkForceLayoutDuringModelChange();
void checkForceLayoutWhenAllItemsAreHidden();
+ void checkLayoutChangedSignal();
void checkContentWidthAndHeight();
void checkContentWidthAndHeightForSmallTables();
void checkPageFlicking();
@@ -809,6 +810,52 @@ void tst_QQuickTableView::checkForceLayoutWhenAllItemsAreHidden()
QCOMPARE(tableViewPrivate->loadedItems.size(), rows * columns);
}
+void tst_QQuickTableView::checkLayoutChangedSignal()
+{
+ // Check that the layoutChanged signal is emitted
+ // when the layout has changed.
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ const QSignalSpy layoutChanges(tableView, &QQuickTableView::layoutChanged);
+ TestModel model(100, 100);
+ tableView->setModel(QVariant::fromValue(&model));
+
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(layoutChanges.size(), 1);
+
+ tableView->forceLayout();
+ QCOMPARE(layoutChanges.size(), 2);
+
+ tableView->setRowHeight(1, 10);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(layoutChanges.size(), 3);
+
+ tableView->setColumnWidth(1, 10);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(layoutChanges.size(), 4);
+
+ tableView->setContentX(30);
+ QCOMPARE(layoutChanges.size(), 5);
+
+ tableView->setContentY(30);
+ QCOMPARE(layoutChanges.size(), 6);
+
+ tableView->setContentX(0);
+ QCOMPARE(layoutChanges.size(), 7);
+
+ tableView->setContentY(0);
+ QCOMPARE(layoutChanges.size(), 8);
+
+ model.addRow(1);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(layoutChanges.size(), 9);
+
+ model.removeRow(1);
+ WAIT_UNTIL_POLISHED;
+ QCOMPARE(layoutChanges.size(), 10);
+}
+
void tst_QQuickTableView::checkContentWidthAndHeight()
{
// Check that contentWidth/Height reports the correct size of the