mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-09-30 06:34:13 +02:00
a8f940505d
Discussion #1070 proposed that rotate, like move, copy and delete, works on the whole group once one of its items is clicked. Rotate (Space) turned each member on its own spot instead, so rotating a group pulled it apart: two grouped texts side by side ended up each turned in place, no longer side by side. When the selection is exactly one whole group -- wires aside, which follow their symbols -- Rotate now turns it as one piece around its centre, as "Pivoter le groupe" (Shift+Space) already does (ItemGroups::soleWholeGroup()). Any other selection, including a single member picked out of its group, rotates as before. In the GUI, on two grouped texts selected by one click: Space on master leaves both where they were, turned; here it gives exactly what Shift+Space gives on both (both texts swung around the group's centre). tst_itemgroups: 4 new checks; without the whole-group condition, a picked member counts as a group and fails. ctest 24/24. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
171 lines
3.9 KiB
C++
171 lines
3.9 KiB
C++
#include <QtTest>
|
|
#include <QDomDocument>
|
|
#include <QGraphicsRectItem>
|
|
#include <QGraphicsScene>
|
|
|
|
#include "itemgroups.h"
|
|
|
|
class tst_itemgroups : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
QGraphicsScene *scene = nullptr;
|
|
QGraphicsRectItem *a = nullptr, *b = nullptr, *c = nullptr, *d = nullptr, *e = nullptr;
|
|
QUuid g1, g2;
|
|
|
|
QGraphicsRectItem *add()
|
|
{
|
|
auto item = scene->addRect(0, 0, 10, 10);
|
|
item->setFlag(QGraphicsItem::ItemIsSelectable);
|
|
return item;
|
|
}
|
|
|
|
QList<QGraphicsItem *> selection() const { return scene->selectedItems(); }
|
|
|
|
// Select exactly @a items, as Qt leaves the scene after a click.
|
|
void select(const QList<QGraphicsItem *> &items)
|
|
{
|
|
scene->clearSelection();
|
|
for (auto item : items) {
|
|
item->setSelected(true);
|
|
}
|
|
}
|
|
|
|
bool selected(std::initializer_list<QGraphicsItem *> expected) const
|
|
{
|
|
QList<QGraphicsItem *> got = selection();
|
|
if (got.size() != int(expected.size())) {
|
|
return false;
|
|
}
|
|
for (auto item : expected) {
|
|
if (!got.contains(item)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private slots:
|
|
// a, b in g1; c alone; d, e in g2
|
|
void init()
|
|
{
|
|
scene = new QGraphicsScene;
|
|
a = add(); b = add(); c = add(); d = add(); e = add();
|
|
g1 = QUuid::createUuid();
|
|
g2 = QUuid::createUuid();
|
|
ItemGroups::setGroup(a, g1);
|
|
ItemGroups::setGroup(b, g1);
|
|
ItemGroups::setGroup(d, g2);
|
|
ItemGroups::setGroup(e, g2);
|
|
}
|
|
|
|
void cleanup()
|
|
{
|
|
delete scene;
|
|
scene = nullptr;
|
|
}
|
|
|
|
void clickingAMemberSelectsTheGroup()
|
|
{
|
|
select({a});
|
|
QVERIFY(ItemGroups::completeSelection(scene, {}, false));
|
|
QVERIFY(selected({a, b}));
|
|
}
|
|
|
|
// Releasing a click on one member of the selected group leaves only it
|
|
// selected in Qt; the group must stay whole.
|
|
void reclickingAMemberKeepsTheGroup()
|
|
{
|
|
select({b});
|
|
ItemGroups::completeSelection(scene, {a, b}, false);
|
|
QVERIFY(selected({a, b}));
|
|
}
|
|
|
|
void ctrlClickingAMemberOffDeselectsTheGroup()
|
|
{
|
|
select({b});
|
|
ItemGroups::completeSelection(scene, {a, b}, true);
|
|
QVERIFY(selected({}));
|
|
}
|
|
|
|
void ctrlClickingAMemberOnAddsTheGroup()
|
|
{
|
|
select({c, a});
|
|
ItemGroups::completeSelection(scene, {c}, true);
|
|
QVERIFY(selected({a, b, c}));
|
|
}
|
|
|
|
void otherGroupsAreUntouched()
|
|
{
|
|
select({b, d, e});
|
|
ItemGroups::completeSelection(scene, {a, b, d, e}, true);
|
|
QVERIFY(selected({d, e}));
|
|
}
|
|
|
|
void ungroupedItemsAreUntouched()
|
|
{
|
|
select({c});
|
|
QVERIFY(!ItemGroups::completeSelection(scene, {}, false));
|
|
QVERIFY(selected({c}));
|
|
}
|
|
|
|
// A member taken off the scene (deleted, kept by the undo stack) must
|
|
// not count as "deselected".
|
|
void itemsLeavingTheSceneAreIgnored()
|
|
{
|
|
select({a, b});
|
|
scene->removeItem(b);
|
|
ItemGroups::completeSelection(scene, {a, b}, true);
|
|
QVERIFY(selected({a}));
|
|
delete b;
|
|
b = nullptr;
|
|
}
|
|
|
|
void xmlRoundTrip()
|
|
{
|
|
QDomDocument doc;
|
|
QDomElement grouped = doc.createElement(QStringLiteral("element"));
|
|
ItemGroups::write(grouped, a);
|
|
QCOMPARE(ItemGroups::read(grouped), g1);
|
|
|
|
QDomElement alone = doc.createElement(QStringLiteral("element"));
|
|
ItemGroups::write(alone, c);
|
|
QVERIFY(!alone.hasAttribute(QStringLiteral("group")));
|
|
QVERIFY(ItemGroups::read(alone).isNull());
|
|
|
|
ItemGroups::setGroup(a, QUuid());
|
|
QVERIFY(ItemGroups::groupOf(a).isNull());
|
|
}
|
|
|
|
// Rotate turns a selection that is exactly one whole group as one piece.
|
|
void aWholeGroupAloneIsASoleWholeGroup()
|
|
{
|
|
select({a, b});
|
|
QCOMPARE(ItemGroups::soleWholeGroup(selection()), g1);
|
|
}
|
|
|
|
void aPickedMemberIsNotAWholeGroup()
|
|
{
|
|
select({a});
|
|
QVERIFY(ItemGroups::soleWholeGroup(selection()).isNull());
|
|
}
|
|
|
|
void aGroupWithOtherItemsIsNotASoleGroup()
|
|
{
|
|
select({a, b, c});
|
|
QVERIFY(ItemGroups::soleWholeGroup(selection()).isNull());
|
|
select({a, b, d, e});
|
|
QVERIFY(ItemGroups::soleWholeGroup(selection()).isNull());
|
|
}
|
|
|
|
void ungroupedItemsAreNotAGroup()
|
|
{
|
|
select({c});
|
|
QVERIFY(ItemGroups::soleWholeGroup(selection()).isNull());
|
|
QVERIFY(ItemGroups::soleWholeGroup({}).isNull());
|
|
}
|
|
};
|
|
|
|
QTEST_MAIN(tst_itemgroups)
|
|
#include "tst_itemgroups.moc"
|