diff options
author | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2024-03-25 10:02:57 +0100 |
---|---|---|
committer | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2024-03-26 21:33:04 +0100 |
commit | f0fbedbe69532d9f5d1bc622f0b5b1ed16f23f2b (patch) | |
tree | ace446031511c8862f5a6acd145e57ad924c584a /src/quick | |
parent | 1f7a34d20ad39dec7aac959facf0064c7d68be60 (diff) |
SelectionRectangle: ensure we remove or update selection handles if selection changes
If you make a selection with SelectionRectangle and then resize a
row, the selection handles will not move to the resized position.
Likewise, if you do a selection, but then clear the selection
by interacting with the ItemSelectionModel directly, the
selection handles will not be updated to reflect the changes.
To fix this bug, this patch will add a callback from TableView to
SelectionRectangle that can be used to notify when changes are
done outside of SelectionRectangle. This especially allows us to:
- Remove the selection handles if the active selection is cleared
or changed programatically (or anyway not by SelectionRectangle).
- Keep the selection handles, and update their position, when rows
or columns are merely resized.
This change also allows us to clean up qquickselectionrectangle.cpp
a bit, and remove e.g a now superfluous tap handler listener.
Task-number: QTBUG-121143
Pick-to: 6.7 6.6 6.5
Change-Id: Id170520d49bc92c0bb9d16deaba741cab6f5c553
Reviewed-by: Santhosh Kumar <santhosh.kumar.selvaraj@qt.io>
Diffstat (limited to 'src/quick')
-rw-r--r-- | src/quick/items/qquickselectable_p.h | 7 | ||||
-rw-r--r-- | src/quick/items/qquicktableview.cpp | 38 | ||||
-rw-r--r-- | src/quick/items/qquicktableview_p_p.h | 4 |
3 files changed, 41 insertions, 8 deletions
diff --git a/src/quick/items/qquickselectable_p.h b/src/quick/items/qquickselectable_p.h index 16e1379e23..475660ab2d 100644 --- a/src/quick/items/qquickselectable_p.h +++ b/src/quick/items/qquickselectable_p.h @@ -23,6 +23,11 @@ QT_BEGIN_NAMESPACE class Q_QUICK_EXPORT QQuickSelectable { public: + enum class CallBackFlag { + CancelSelection, + SelectionRectangleChanged + }; + virtual QQuickItem *selectionPointerHandlerTarget() const = 0; virtual bool startSelection(const QPointF &pos) = 0; @@ -33,6 +38,8 @@ public: virtual QRectF selectionRectangle() const = 0; virtual QSizeF scrollTowardsSelectionPoint(const QPointF &pos, const QSizeF &step) = 0; + + virtual void setCallback(std::function<void(CallBackFlag)> func) = 0; }; QT_END_NAMESPACE diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp index 13b6de40fc..4d971525d4 100644 --- a/src/quick/items/qquicktableview.cpp +++ b/src/quick/items/qquicktableview.cpp @@ -1743,6 +1743,7 @@ void QQuickTableViewPrivate::setSelectionStartPos(const QPointF &pos) return; // Update selection model + QScopedValueRollback callbackGuard(inSelectionModelUpdate, true); updateSelection(prevSelection, selection()); } @@ -1791,6 +1792,7 @@ void QQuickTableViewPrivate::setSelectionEndPos(const QPointF &pos) return; // Update selection model + QScopedValueRollback callbackGuard(inSelectionModelUpdate, true); updateSelection(prevSelection, selection()); } @@ -1859,14 +1861,22 @@ void QQuickTableViewPrivate::updateSelection(const QRect &oldSelection, const QR selectionModel->select(select, QItemSelectionModel::Select); } -void QQuickTableViewPrivate::clearSelection() +void QQuickTableViewPrivate::cancelSelectionTracking() { + // Cancel any ongoing key/mouse aided selection tracking selectionStartCell = QPoint(-1, -1); selectionEndCell = QPoint(-1, -1); existingSelection.clear(); + if (selectableCallbackFunction) + selectableCallbackFunction(QQuickSelectable::CallBackFlag::CancelSelection); +} - if (selectionModel) - selectionModel->clearSelection(); +void QQuickTableViewPrivate::clearSelection() +{ + if (!selectionModel) + return; + QScopedValueRollback callbackGuard(inSelectionModelUpdate, true); + selectionModel->clearSelection(); } void QQuickTableViewPrivate::normalizeSelection() @@ -2004,6 +2014,11 @@ QSizeF QQuickTableViewPrivate::scrollTowardsSelectionPoint(const QPointF &pos, c return dist; } +void QQuickTableViewPrivate::setCallback(std::function<void (CallBackFlag)> func) +{ + selectableCallbackFunction = func; +} + QQuickTableViewAttached *QQuickTableViewPrivate::getAttachedObject(const QObject *object) const { QObject *attachedObject = qmlAttachedPropertiesObject<QQuickTableView>(object); @@ -4099,10 +4114,11 @@ bool QQuickTableViewPrivate::currentInSelectionModel(const QPoint &cell) const void QQuickTableViewPrivate::selectionChangedInSelectionModel(const QItemSelection &selected, const QItemSelection &deselected) { - if (!selectionModel->hasSelection()) { - // Ensure that we cancel any ongoing key/mouse-based selections - // if selectionModel.clearSelection() is called. - clearSelection(); + if (!inSelectionModelUpdate) { + // The selection model was manipulated outside of TableView + // and SelectionRectangle. In that case we cancel any ongoing + // selection tracking. + cancelSelectionTracking(); } const auto &selectedIndexes = selected.indexes(); @@ -4934,8 +4950,10 @@ void QQuickTableViewPrivate::handleTap(const QQuickHandlerPoint &point) // the current selection and move the current index instead. if (pointerNavigationEnabled) { q->closeEditor(); - if (selectionBehavior != QQuickTableView::SelectionDisabled) + if (selectionBehavior != QQuickTableView::SelectionDisabled) { clearSelection(); + cancelSelectionTracking(); + } setCurrentIndexFromTap(point.position()); } } @@ -5074,6 +5092,8 @@ bool QQuickTableViewPrivate::setCurrentIndexFromKeyEvent(QKeyEvent *e) if (loadedItems.contains(serializedStartIndex)) { const QRectF startGeometry = loadedItems.value(serializedStartIndex)->geometry(); setSelectionStartPos(startGeometry.center()); + if (selectableCallbackFunction) + selectableCallbackFunction(QQuickSelectable::CallBackFlag::SelectionRectangleChanged); } } }; @@ -5086,6 +5106,8 @@ bool QQuickTableViewPrivate::setCurrentIndexFromKeyEvent(QKeyEvent *e) if (loadedItems.contains(serializedEndIndex)) { const QRectF endGeometry = loadedItems.value(serializedEndIndex)->geometry(); setSelectionEndPos(endGeometry.center()); + if (selectableCallbackFunction) + selectableCallbackFunction(QQuickSelectable::CallBackFlag::SelectionRectangleChanged); } } selectionModel->setCurrentIndex(q->modelIndex(cell), QItemSelectionModel::NoUpdate); diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h index 0bfc2a9c0a..1f0c8549a5 100644 --- a/src/quick/items/qquicktableview_p_p.h +++ b/src/quick/items/qquicktableview_p_p.h @@ -360,6 +360,8 @@ public: QPointer<QItemSelectionModel> selectionModel; QQuickTableView::SelectionBehavior selectionBehavior = QQuickTableView::SelectCells; QQuickTableView::SelectionMode selectionMode = QQuickTableView::ExtendedSelection; + std::function<void(CallBackFlag)> selectableCallbackFunction; + bool inSelectionModelUpdate = false; int assignedPositionViewAtRowAfterRebuild = 0; int assignedPositionViewAtColumnAfterRebuild = 0; @@ -587,6 +589,8 @@ public: void normalizeSelection() override; QRectF selectionRectangle() const override; QSizeF scrollTowardsSelectionPoint(const QPointF &pos, const QSizeF &step) override; + void setCallback(std::function<void(CallBackFlag)> func) override; + void cancelSelectionTracking(); QPoint clampedCellAtPos(const QPointF &pos) const; virtual void updateSelection(const QRect &oldSelection, const QRect &newSelection); |