Click again on a member of a selected group to pick it on its own

Clicking an item of a group selects the whole group (#1070). Clicking
again on one of its items is meant to select just that item, to edit it
on its own -- what discussion #1070 proposed -- but the second click
selected the whole group again: Qt left only the clicked item selected on
release, and the group completion pulled the others back in.

A press on a member of a group that is selected whole now notes that
member (ItemGroups::memberToPick(), which also finds the member when the
click lands on a symbol's own text). If the click ends without a drag and
Qt has left only that member selected, the selection stays so. A drag
still moves the whole group; Ctrl+click keeps its meaning; a group of one
is not picked from.

In the GUI, on two grouped texts: one click then Delete removes both
(master and this); click, click again, Delete removes only the clicked
text here, both on master; dragging after one click moves both texts by
the same amount on both. tst_itemgroups: 5 new checks; removing the
whole-group or the group-of-one condition fails one each. ctest 24/24.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-09-28 22:33:28 +13:00
parent 5ca047a05d
commit 6ed41bbfd0
5 changed files with 120 additions and 0 deletions
+41
View File
@@ -62,6 +62,47 @@ QUuid ItemGroups::read(const QDomElement &xml)
return QUuid(xml.attribute(QString::fromLatin1(xml_attribute)));
}
/**
@return @a item, or its nearest ancestor, that belongs to a group -- a
click on a symbol's own text hits the text, but the symbol is the member
-- or nullptr if none does.
*/
QGraphicsItem *ItemGroups::groupedItem(QGraphicsItem *item)
{
for (; item; item = item->parentItem()) {
if (!groupOf(item).isNull()) {
return item;
}
}
return nullptr;
}
/**
@return the member a click on @a hit may pick out on its own: the grouped
item hit, when every member of its group is selected already. A first
click selects the whole group; a second click, on a member of the group
it selected, is how the user asks for that member alone (discussion
#1070). nullptr when the click is not that.
*/
QGraphicsItem *ItemGroups::memberToPick(QGraphicsItem *hit)
{
QGraphicsItem *member = groupedItem(hit);
if (!member || !member->isSelected() || !member->scene()) {
return nullptr;
}
const QUuid group = groupOf(member);
int members = 0;
for (QGraphicsItem *item : member->scene()->items()) {
if (groupOf(item) == group) {
if (!item->isSelected()) {
return nullptr;
}
++members;
}
}
return members > 1 ? member : nullptr;
}
/**
Make the selection of @a scene whole groups again after it changed.
A group with a selected member is selected entirely, except when the