From 2e12479e06d6869f568f0a7ee939453cda9afdbf Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Sat, 18 Jun 2022 23:41:57 +0200 Subject: QGraphicsScene: respect that items can override selection changes QGraphicsItems may override itemChange to prevent certain attribute changes. Overriding ItemSelectedChange this way is explicitly documented to be allowed. However QGraphicsScene::clearSelection did not test whether items were in fact deselected after the call to setSelection, and always cleared the stored set of selected items. Fix this by checking the actual selected state of the item as we iterate over them, and store those items that are still selected in a set that becomes the new selectedItems set (which will be empty if no item overrides, which is the default). Add a test that also checks that clearing the selection emits the selectionChanged signal correctly (and does not if all selected items block being deselected). Fixes: QTBUG-85474 Pick-to: 6.4 6.3 6.2 Change-Id: I665afc132876e02e6e1061b7be37f4f6e4be418f Reviewed-by: Axel Spoerl Reviewed-by: Richard Moe Gustavsen --- src/widgets/graphicsview/qgraphicsscene.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/widgets/graphicsview/qgraphicsscene.cpp') diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp index 411eee0c4f..f65082ad55 100644 --- a/src/widgets/graphicsview/qgraphicsscene.cpp +++ b/src/widgets/graphicsview/qgraphicsscene.cpp @@ -2251,11 +2251,16 @@ void QGraphicsScene::clearSelection() ++d->selectionChanging; // iterate over a copy, as clearing selection might invalidate selectedItems const auto selectedItems = d->selectedItems; - bool changed = !selectedItems.isEmpty(); + QSet stillSelectedSet; - for (QGraphicsItem *item : selectedItems) + for (QGraphicsItem *item : selectedItems) { item->setSelected(false); - d->selectedItems.clear(); + // items might override itemChange to prevent deselection + if (item->isSelected()) + stillSelectedSet << item; + } + const bool changed = stillSelectedSet != selectedItems; + d->selectedItems = stillSelectedSet; // Re-enable emitting selectionChanged() for individual items. --d->selectionChanging; -- cgit v1.2.3