aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquicktableview.cpp122
-rw-r--r--src/quick/items/qquicktableview_p.h13
-rw-r--r--src/quick/items/qquicktableview_p_p.h2
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp48
4 files changed, 177 insertions, 8 deletions
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index c88311cc14..5c89394e62 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -355,6 +355,38 @@
*/
/*!
+ \qmlproperty int QtQuick::TableView::leftColumn
+
+ This property holds the leftmost column that is currently visible inside the view.
+
+ \sa rightColumn, topRow, bottomRow
+*/
+
+/*!
+ \qmlproperty int QtQuick::TableView::rightColumn
+
+ This property holds the rightmost column that is currently visible inside the view.
+
+ \sa leftColumn, topRow, bottomRow
+*/
+
+/*!
+ \qmlproperty int QtQuick::TableView::topRow
+
+ This property holds the topmost row that is currently visible inside the view.
+
+ \sa leftColumn, rightColumn, bottomRow
+*/
+
+/*!
+ \qmlproperty int QtQuick::TableView::bottomRow
+
+ This property holds the bottom-most row that is currently visible inside the view.
+
+ \sa leftColumn, rightColumn, topRow
+*/
+
+/*!
\qmlmethod QtQuick::TableView::positionViewAtCell(point cell, Qt.Alignment alignment, point offset)
Positions \l contentX and \l contentY such that \a cell is at the position specified by
@@ -1111,6 +1143,8 @@ void QQuickTableViewPrivate::forceLayout()
void QQuickTableViewPrivate::syncLoadedTableFromLoadRequest()
{
+ Q_Q(QQuickTableView);
+
if (loadRequest.edge() == Qt::Edge(0)) {
// No edge means we're loading the top-left item
loadedColumns.insert(loadRequest.column(), 0);
@@ -1120,12 +1154,24 @@ void QQuickTableViewPrivate::syncLoadedTableFromLoadRequest()
switch (loadRequest.edge()) {
case Qt::LeftEdge:
+ loadedColumns.insert(loadRequest.column(), 0);
+ if (rebuildState == RebuildState::Done)
+ emit q->leftColumnChanged();
+ break;
case Qt::RightEdge:
loadedColumns.insert(loadRequest.column(), 0);
+ if (rebuildState == RebuildState::Done)
+ emit q->rightColumnChanged();
break;
case Qt::TopEdge:
+ loadedRows.insert(loadRequest.row(), 0);
+ if (rebuildState == RebuildState::Done)
+ emit q->topRowChanged();
+ break;
case Qt::BottomEdge:
loadedRows.insert(loadRequest.row(), 0);
+ if (rebuildState == RebuildState::Done)
+ emit q->bottomRowChanged();
break;
}
}
@@ -1776,6 +1822,9 @@ void QQuickTableViewPrivate::processRebuildTable()
else
Q_TABLEVIEW_UNREACHABLE(rebuildOptions);
}
+
+ edgesBeforeRebuild = loadedItems.isEmpty() ? QMargins()
+ : QMargins(q->leftColumn(), q->topRow(), q->rightColumn(), q->bottomRow());
}
moveToNextRebuildState();
@@ -1833,11 +1882,23 @@ void QQuickTableViewPrivate::processRebuildTable()
return;
}
+ if (rebuildState == RebuildState::Done) {
+ if (edgesBeforeRebuild.left() != q->leftColumn())
+ emit q->leftColumnChanged();
+ if (edgesBeforeRebuild.right() != q->rightColumn())
+ emit q->rightColumnChanged();
+ if (edgesBeforeRebuild.top() != q->topRow())
+ emit q->topRowChanged();
+ if (edgesBeforeRebuild.bottom() != q->bottomRow())
+ emit q->bottomRowChanged();
+
+ qCDebug(lcTableViewDelegateLifecycle()) << "current table:" << tableLayoutToString();
+ qCDebug(lcTableViewDelegateLifecycle()) << "rebuild completed!";
+ qCDebug(lcTableViewDelegateLifecycle()) << "################################################";
+ qCDebug(lcTableViewDelegateLifecycle());
+ }
+
Q_TABLEVIEW_ASSERT(rebuildState == RebuildState::Done, int(rebuildState));
- qCDebug(lcTableViewDelegateLifecycle()) << "current table:" << tableLayoutToString();
- qCDebug(lcTableViewDelegateLifecycle()) << "rebuild completed!";
- qCDebug(lcTableViewDelegateLifecycle()) << "################################################";
- qCDebug(lcTableViewDelegateLifecycle());
}
bool QQuickTableViewPrivate::moveToNextRebuildState()
@@ -2137,24 +2198,45 @@ void QQuickTableViewPrivate::adjustViewportYAccordingToAlignment()
void QQuickTableViewPrivate::unloadEdge(Qt::Edge edge)
{
+ Q_Q(QQuickTableView);
qCDebug(lcTableViewDelegateLifecycle) << edge;
switch (edge) {
- case Qt::LeftEdge:
+ case Qt::LeftEdge: {
+ const int column = leftColumn();
+ for (auto r = loadedRows.cbegin(); r != loadedRows.cend(); ++r)
+ unloadItem(QPoint(column, r.key()));
+ loadedColumns.remove(column);
+ syncLoadedTableRectFromLoadedTable();
+ if (rebuildState == RebuildState::Done)
+ emit q->leftColumnChanged();
+ break; }
case Qt::RightEdge: {
- const int column = edge == Qt::LeftEdge ? leftColumn() : rightColumn();
+ const int column = rightColumn();
for (auto r = loadedRows.cbegin(); r != loadedRows.cend(); ++r)
unloadItem(QPoint(column, r.key()));
loadedColumns.remove(column);
syncLoadedTableRectFromLoadedTable();
+ if (rebuildState == RebuildState::Done)
+ emit q->rightColumnChanged();
+ break; }
+ case Qt::TopEdge: {
+ const int row = topRow();
+ for (auto c = loadedColumns.cbegin(); c != loadedColumns.cend(); ++c)
+ unloadItem(QPoint(c.key(), row));
+ loadedRows.remove(row);
+ syncLoadedTableRectFromLoadedTable();
+ if (rebuildState == RebuildState::Done)
+ emit q->topRowChanged();
break; }
- case Qt::TopEdge:
case Qt::BottomEdge: {
- const int row = edge == Qt::TopEdge ? topRow() : bottomRow();
+ const int row = bottomRow();
for (auto c = loadedColumns.cbegin(); c != loadedColumns.cend(); ++c)
unloadItem(QPoint(c.key(), row));
loadedRows.remove(row);
syncLoadedTableRectFromLoadedTable();
+ if (rebuildState == RebuildState::Done)
+ emit q->bottomRowChanged();
break; }
}
@@ -3088,6 +3170,30 @@ void QQuickTableView::setSyncDirection(Qt::Orientations direction)
emit syncDirectionChanged();
}
+int QQuickTableView::leftColumn() const
+{
+ Q_D(const QQuickTableView);
+ return d->loadedItems.isEmpty() ? -1 : d_func()->leftColumn();
+}
+
+int QQuickTableView::rightColumn() const
+{
+ Q_D(const QQuickTableView);
+ return d->loadedItems.isEmpty() ? -1 : d_func()->rightColumn();
+}
+
+int QQuickTableView::topRow() const
+{
+ Q_D(const QQuickTableView);
+ return d->loadedItems.isEmpty() ? -1 : d_func()->topRow();
+}
+
+int QQuickTableView::bottomRow() const
+{
+ Q_D(const QQuickTableView);
+ return d->loadedItems.isEmpty() ? -1 : d_func()->bottomRow();
+}
+
void QQuickTableView::positionViewAtCell(const QPoint &cell, Qt::Alignment alignment, const QPointF &offset)
{
positionViewAtRow(cell.y(), alignment & Qt::AlignVertical_Mask, offset.y());
diff --git a/src/quick/items/qquicktableview_p.h b/src/quick/items/qquicktableview_p.h
index 831bf20b0a..2682f4306d 100644
--- a/src/quick/items/qquicktableview_p.h
+++ b/src/quick/items/qquicktableview_p.h
@@ -81,6 +81,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTableView : public QQuickFlickable
Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged)
Q_PROPERTY(QQuickTableView *syncView READ syncView WRITE setSyncView NOTIFY syncViewChanged REVISION(2, 14))
Q_PROPERTY(Qt::Orientations syncDirection READ syncDirection WRITE setSyncDirection NOTIFY syncDirectionChanged REVISION(2, 14))
+ Q_PROPERTY(int leftColumn READ leftColumn NOTIFY leftColumnChanged REVISION(6, 0))
+ Q_PROPERTY(int rightColumn READ rightColumn NOTIFY rightColumnChanged REVISION(6, 0))
+ Q_PROPERTY(int topRow READ topRow NOTIFY topRowChanged REVISION(6, 0))
+ Q_PROPERTY(int bottomRow READ bottomRow NOTIFY bottomRowChanged REVISION(6, 0))
QML_NAMED_ELEMENT(TableView)
QML_ADDED_IN_VERSION(2, 12)
@@ -122,6 +126,11 @@ public:
Qt::Orientations syncDirection() const;
void setSyncDirection(Qt::Orientations direction);
+ int leftColumn() const;
+ int rightColumn() const;
+ int topRow() const;
+ int bottomRow() const;
+
Q_INVOKABLE void forceLayout();
Q_INVOKABLE void positionViewAtCell(const QPoint &cell, Qt::Alignment alignment, const QPointF &offset = QPointF());
Q_INVOKABLE void positionViewAtCell(int column, int row, Qt::Alignment alignment, const QPointF &offset = QPointF());
@@ -146,6 +155,10 @@ Q_SIGNALS:
void reuseItemsChanged();
Q_REVISION(2, 14) void syncViewChanged();
Q_REVISION(2, 14) void syncDirectionChanged();
+ Q_REVISION(6, 0) void leftColumnChanged();
+ Q_REVISION(6, 0) void rightColumnChanged();
+ Q_REVISION(6, 0) void topRowChanged();
+ Q_REVISION(6, 0) void bottomRowChanged();
protected:
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h
index ab53a07dd0..876a175d87 100644
--- a/src/quick/items/qquicktableview_p_p.h
+++ b/src/quick/items/qquicktableview_p_p.h
@@ -321,6 +321,8 @@ public:
Qt::Alignment positionViewAtRowAlignment = Qt::AlignTop;
Qt::Alignment positionViewAtColumnAlignment = Qt::AlignLeft;
+ QMargins edgesBeforeRebuild;
+
const static QPoint kLeft;
const static QPoint kRight;
const static QPoint kUp;
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index 414a76d1db..6e13044390 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -186,6 +186,8 @@ private slots:
void positionViewAtColumn();
void itemAtCell_data();
void itemAtCell();
+ void leftRightTopBottomProperties_data();
+ void leftRightTopBottomProperties();
};
tst_QQuickTableView::tst_QQuickTableView()
@@ -3058,6 +3060,52 @@ void tst_QQuickTableView::itemAtCell()
}
}
+void tst_QQuickTableView::leftRightTopBottomProperties_data()
+{
+ QTest::addColumn<QPointF>("contentStartPos");
+ QTest::addColumn<QMargins>("expectedTable");
+ QTest::addColumn<QMargins>("expectedSignalCount");
+
+ QTest::newRow("1") << QPointF(0, 0) << QMargins(0, 0, 5, 7) << QMargins(0, 0, 1, 1);
+ QTest::newRow("2") << QPointF(100, 50) << QMargins(1, 1, 6, 8) << QMargins(1, 1, 2, 2);
+ QTest::newRow("3") << QPointF(220, 120) << QMargins(2, 2, 8, 10) << QMargins(2, 2, 4, 4);
+ QTest::newRow("4") << QPointF(1000, 1000) << QMargins(9, 19, 15, 27) << QMargins(1, 1, 2, 2);
+}
+
+void tst_QQuickTableView::leftRightTopBottomProperties()
+{
+ QFETCH(QPointF, contentStartPos);
+ QFETCH(QMargins, expectedTable);
+ QFETCH(QMargins, expectedSignalCount);
+
+ LOAD_TABLEVIEW("plaintableview.qml");
+ auto model = TestModelAsVariant(100, 100);
+ tableView->setModel(model);
+
+ QSignalSpy leftSpy(tableView, &QQuickTableView::leftColumnChanged);
+ QSignalSpy rightSpy(tableView, &QQuickTableView::rightColumnChanged);
+ QSignalSpy topSpy(tableView, &QQuickTableView::topRowChanged);
+ QSignalSpy bottomSpy(tableView, &QQuickTableView::bottomRowChanged);
+
+ WAIT_UNTIL_POLISHED;
+
+ tableView->setContentX(contentStartPos.x());
+ tableView->setContentY(contentStartPos.y());
+
+ tableView->polish();
+ WAIT_UNTIL_POLISHED;
+
+ QCOMPARE(tableView->leftColumn(), expectedTable.left());
+ QCOMPARE(tableView->topRow(), expectedTable.top());
+ QCOMPARE(tableView->rightColumn(), expectedTable.right());
+ QCOMPARE(tableView->bottomRow(), expectedTable.bottom());
+
+ QCOMPARE(leftSpy.count(), expectedSignalCount.left());
+ QCOMPARE(rightSpy.count(), expectedSignalCount.right());
+ QCOMPARE(topSpy.count(), expectedSignalCount.top());
+ QCOMPARE(bottomSpy.count(), expectedSignalCount.bottom());
+}
+
QTEST_MAIN(tst_QQuickTableView)
#include "tst_qquicktableview.moc"