Merge branch 'port-a'

This commit is contained in:
ZacharyZhang-NY committed 2026-10-01 20:00:54 -04:00
commit 8dfb6f0ae4
9 files changed
+64 -21

No files matched your search

+3 -1
View File
@@ -173,11 +173,13 @@ void KeyboardShortcutsTests::menusAndSheetsTakeTheirRemappedKeys()
{"Show Guides", QKeySequence(Qt::CTRL | Qt::Key_Semicolon)},
{"Show Rulers", QKeySequence(Qt::CTRL | Qt::Key_R)},
{"Snap", QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_Semicolon)},
{"Lock Guides", QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_Semicolon)}};
{"Lock Guides", QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_Semicolon)},
{"Ungroup Layers", QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_G)}};
for (const auto &[title, original] : view) {
QVERIFY(settings.save({{named(title).id(), ShortcutChord("k", 7)}}));
QVERIFY2(settings.menu(original) == QKeySequence(Qt::CTRL | Qt::ALT | Qt::META | Qt::Key_K), qPrintable(title));
}
QCOMPARE(named("Ungroup Layers").original, ShortcutChord("g", 9));
}
void KeyboardShortcutsTests::theCanvasTranslatesRemappedKeys()
+5
View File
@@ -91,6 +91,11 @@ void LayerDragGestureTests::altShowsTheClippingAndDuplicateCursors()
QCOMPARE(drawn.pixelColor(25, 23).alpha(), 255);
QCOMPARE(drawn.copy(0, 0, 18, 18), image(CanvasView::duplicateCursor(1)).copy(0, 0, 18, 18));
QCOMPARE(image(CanvasView::duplicateCursor(1)).pixelColor(23, 23).alpha(), 0);
// The arrows lie over the eye: opaque arrow pixels stay.
const QImage arrows = image(CanvasView::duplicateCursor(1));
for (int y = 0; y < arrows.height(); ++y)
for (int x = 0; x < arrows.width(); ++x)
QVERIFY(arrows.pixelColor(x, y).alpha() < 255 || drawn.pixelColor(x, y) == arrows.pixelColor(x, y));
session->setIsImporting(true);
QCOMPARE(image(shown.list.cursorFor(mask, Qt::AltModifier)), image(NativeLayerList::showMaskCursor(ratio)));
QCOMPARE(shown.list.cursorFor(mask, Qt::ControlModifier).shape(), Qt::ArrowCursor);
+26 -12
View File
@@ -1,4 +1,5 @@
#include "UI/ProjectTabs.h"
#include <QDialog>
#include <QMenu>
#include <QPropertyAnimation>
#include <QtTest>
@@ -40,7 +41,7 @@ struct Strip {
if (!QTest::qWaitForWindowExposed(&strip))
throw std::runtime_error("the strip never showed");
}
// QTest sends to a widget, not to the press's grab.
// Through the window, so the application tracks the buttons.
QToolButton *pressed = nullptr;
// Presses a tab; returns the point, in the strip.
QPoint press(const QString &title)
@@ -48,16 +49,11 @@ struct Strip {
ProjectTabButton &tab = button(strip, title);
const QPoint point = tab.mapTo(&strip, QPoint(20, 14));
pressed = &select(tab);
QTest::mousePress(pressed, Qt::LeftButton, {}, pressed->mapFrom(&strip, point));
QTest::mousePress(strip.windowHandle(), Qt::LeftButton, {}, point);
return point;
}
void move(QPoint point) { QTest::mouseMove(pressed, pressed->mapFrom(&strip, point)); }
// The release goes to the pressed title wherever it is.
void release(const QString &title, QPoint point)
{
QToolButton &title_ = select(button(strip, title));
QTest::mouseRelease(&title_, Qt::LeftButton, {}, title_.mapFrom(&strip, point));
}
void move(QPoint point) { QTest::mouseMove(strip.windowHandle(), point); }
void release(const QString &, QPoint point) { QTest::mouseRelease(strip.windowHandle(), Qt::LeftButton, {}, point); }
};
// Every slide finished: tabs rest at their slots.
@@ -215,13 +211,31 @@ void ProjectTabDragTests::aLostReleaseGivesWayToTheNextDrag()
Strip fixture;
const QPoint first = fixture.press("Untitled");
fixture.move(first + QPoint(5000, 0));
// Its release never comes; another tab is dragged.
QVERIFY(button(fixture.strip, "Untitled").x() > 100);
// A modal alert mid-drag: the strip misses the release.
QDialog alert;
alert.setModal(true);
alert.show();
QVERIFY(QTest::qWaitForWindowExposed(&alert));
fixture.release("Untitled", first + QPoint(5000, 0));
QCOMPARE(QGuiApplication::mouseButtons(), Qt::NoButton);
QVERIFY(button(fixture.strip, "Untitled").x() > 100);
alert.close();
// Swift's timer: the drag ends, nothing moves.
auto *watch = fixture.strip.findChild<QTimer *>("tabReleaseWatch");
QVERIFY(watch && watch->interval() == 100);
QTRY_VERIFY(!watch->isActive());
QTRY_VERIFY(settled(fixture.strip));
QCOMPARE(button(fixture.strip, "Untitled").x(), 0);
QCOMPARE(titles(fixture.workspace), (QStringList{"Untitled", "Untitled 2", "Untitled 3"}));
// Another drag works at once.
const QPoint next = fixture.press("Untitled 3");
fixture.move(next - QPoint(5000, 0));
// Held, the drag lasts past the timer.
QTest::qWait(250);
QVERIFY(button(fixture.strip, "Untitled 3").x() == 0 && watch->isActive());
fixture.release("Untitled 3", next - QPoint(5000, 0));
QCOMPARE(titles(fixture.workspace), (QStringList{"Untitled 3", "Untitled", "Untitled 2"}));
QTRY_VERIFY(settled(fixture.strip));
QCOMPARE(button(fixture.strip, "Untitled 3").x(), 0);
}
void ProjectTabDragTests::tabsThatDoNotFitGatherInAMenu()
+1
View File
@@ -74,6 +74,7 @@ void ProjectTabLayoutTests::overflowHidesTheLeftmostTabsAndPillsThem()
QCOMPARE(result.contentWidth(), 292.0);
// 292 exactly still holds two; a third at 398.
QCOMPARE(projectTabOverflow(order, widths(order), e, 292, pill).visible.size(), size_t(2));
QCOMPARE(projectTabOverflow(order, widths(order), e, 397, pill).visible.size(), size_t(2));
QCOMPARE(projectTabOverflow(order, widths(order), e, 398, pill).visible.size(), size_t(3));
// Too narrow for even one: one tab stays.
QVERIFY((ids(projectTabOverflow(order, widths(order), e, 50, pill)) == std::vector<QUuid>{e}));
+7
View File
@@ -1,6 +1,7 @@
#include "DialogDesk.h"
#include "IO/ImageExporter.h"
#include "IO/ProjectController.h"
#include "IO/ProjectDigest.h"
#include "ProjectFixtures.h"
#include <QBuffer>
#include <QColorSpace>
@@ -61,6 +62,12 @@ void QuickLookPreviewTests::theStoreWritesThePreviewAndLoadingIgnoresIt()
QCOMPARE(contents(path + "/QuickLook/Preview.jpg"), QByteArray("not even a JPEG"));
// Its bytes are never read.
QCOMPARE(ProjectStore::load(path).manifest.encoded(), snapshot.manifest.encoded());
// Rewritten or deleted, it is no external change.
const QByteArray digest = ProjectDigest::compute(path);
overwrite(path + "/QuickLook/Preview.jpg", QByteArray(5000, 'x'));
QCOMPARE(ProjectDigest::compute(path), digest);
QVERIFY(QDir(path + "/QuickLook").removeRecursively());
QCOMPARE(ProjectDigest::compute(path), digest);
// Saved without one, the project has none.
ProjectStore::save(snapshot, path);
QCOMPARE(QDir(path).entryList(everything), (QStringList{"images", "manifest.json"}));