aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2024-03-25 10:02:57 +0100
committerRichard Moe Gustavsen <richard.gustavsen@qt.io>2024-03-26 21:33:04 +0100
commitf0fbedbe69532d9f5d1bc622f0b5b1ed16f23f2b (patch)
treeace446031511c8862f5a6acd145e57ad924c584a /src/quick
parent1f7a34d20ad39dec7aac959facf0064c7d68be60 (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.h7
-rw-r--r--src/quick/items/qquicktableview.cpp38
-rw-r--r--src/quick/items/qquicktableview_p_p.h4
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);