Files
OmaPhoto/tests/CanvasNavigationTests.cpp
T
雷电芽衣andClaude c864304695
Release / deb (push) Canceled after 0s
Release / rpm (push) Canceled after 0s
Release / arch (push) Canceled after 0s
Release / publish (push) Canceled after 0s
OmaPhoto 1.0.0: the Linux port of Compositor
A layered image editor for Linux and Omarchy, ported from Compositor
(github.com/robbietilton/Compositor), whose Swift source is its
specification. It reads and writes Compositor's .comp projects.

Packages for Ubuntu, Fedora and Arch come from the release workflow;
scripts/install/ holds one install script per distribution family,
and flake.nix serves NixOS.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-26 00:44:52 -04:00

172 lines
8.0 KiB
C++

#include "CanvasFixtures.h"
#include <QSignalSpy>
// The canvas: Zoom, Hand, Space, the wheel, a pinch.
class CanvasNavigationTests : public QObject {
Q_OBJECT
private slots:
void theZoomToolClicksAndDrags();
void theHandToolAndSpaceDragTheView();
void theWheelPansAndZoomsWithAModifier();
void aPinchZoomsAboutThePointer();
};
void CanvasNavigationTests::theZoomToolClicksAndDrags()
{
Shown shown;
CanvasView &canvas = *shown.canvas;
EditorSession &session = shown.session;
shown.settle();
session.zoom(1);
session.selectTool(NavigationTool::zoom);
const QSizeF size = shown.documentSize();
const QPointF click(120, 90);
const QPointF under = session.viewport.documentPoint(click, size);
QTest::mouseClick(&canvas, Qt::LeftButton, Qt::NoModifier, click.toPoint());
QCOMPARE(session.viewport.zoom(), 2.0);
QCOMPARE(session.viewport.documentPoint(click, size), under);
QTest::mouseClick(&canvas, Qt::LeftButton, Qt::AltModifier, click.toPoint());
QCOMPARE(session.viewport.zoom(), 1.0);
// Dragging 100 points doubles about the start; release adds nothing.
const QPointF start(260, 110);
const QPointF anchor = session.viewport.documentPoint(start, size);
QTest::mousePress(&canvas, Qt::LeftButton, Qt::NoModifier, start.toPoint());
drag(canvas, QPointF(360, 110));
QCOMPARE(session.viewport.zoom(), 2.0);
QCOMPARE(session.viewport.documentPoint(start, size), anchor);
drag(canvas, QPointF(310, 110));
QVERIFY(qFuzzyCompare(session.viewport.zoom(), std::sqrt(2.0)));
QCOMPARE(session.viewport.documentPoint(start, size), anchor);
QTest::mouseRelease(&canvas, Qt::LeftButton, Qt::NoModifier, QPoint(310, 110));
QVERIFY(qFuzzyCompare(session.viewport.zoom(), std::sqrt(2.0)));
// Two points of drift still count as a click.
QTest::mousePress(&canvas, Qt::LeftButton, Qt::NoModifier, QPoint(100, 100));
drag(canvas, QPointF(102, 100));
QTest::mouseRelease(&canvas, Qt::LeftButton, Qt::NoModifier, QPoint(102, 100));
QVERIFY(qFuzzyCompare(session.viewport.zoom(), 2 * std::sqrt(2.0)));
// Busy, importing or without a document a press does nothing.
session.setIsProjectBusy(true);
QTest::mouseClick(&canvas, Qt::LeftButton, Qt::NoModifier, click.toPoint());
QVERIFY(qFuzzyCompare(session.viewport.zoom(), 2 * std::sqrt(2.0)));
session.setIsProjectBusy(false);
session.setIsImporting(true);
QTest::mouseClick(&canvas, Qt::LeftButton, Qt::NoModifier, click.toPoint());
QVERIFY(qFuzzyCompare(session.viewport.zoom(), 2 * std::sqrt(2.0)));
session.setIsImporting(false);
QTest::mouseClick(&canvas, Qt::RightButton, Qt::NoModifier, click.toPoint());
QVERIFY(qFuzzyCompare(session.viewport.zoom(), 2 * std::sqrt(2.0)));
Shown empty(std::nullopt);
empty.session.selectTool(NavigationTool::zoom);
QTest::mouseClick(empty.canvas, Qt::LeftButton, Qt::NoModifier, click.toPoint());
QCOMPARE(empty.session.viewport.zoom(), 1.0);
}
void CanvasNavigationTests::theHandToolAndSpaceDragTheView()
{
Shown shown;
CanvasView &canvas = *shown.canvas;
EditorSession &session = shown.session;
shown.settle();
session.zoom(1);
session.selectTool(NavigationTool::hand);
canvas.synchronizeDisplay();
QCOMPARE(canvas.cursor().shape(), Qt::OpenHandCursor);
QSignalSpy changes(&session, &EditorSession::changed);
const QSizeF pan = session.viewport.pan;
QTest::mousePress(&canvas, Qt::LeftButton, Qt::NoModifier, QPoint(100, 100));
QCOMPARE(canvas.cursor().shape(), Qt::ClosedHandCursor);
drag(canvas, QPointF(130, 120));
QCOMPARE(session.viewport.pan, pan + QSizeF(30, 20));
QVERIFY(!session.viewport.followsFit());
QCOMPARE(changes.count(), 1);
drag(canvas, QPointF(135, 120));
QCOMPARE(session.viewport.pan, pan + QSizeF(35, 20));
QCOMPARE(changes.count(), 2);
QTest::mouseRelease(&canvas, Qt::LeftButton, Qt::NoModifier, QPoint(135, 120));
QCOMPARE(canvas.cursor().shape(), Qt::OpenHandCursor);
drag(canvas, QPointF(150, 120));
QCOMPARE(session.viewport.pan, pan + QSizeF(35, 20));
// Space drags the view in any tool.
session.selectTool(NavigationTool::move);
canvas.synchronizeDisplay();
QCOMPARE(canvas.cursor().shape(), Qt::ArrowCursor);
QTRY_VERIFY(canvas.hasFocus());
QTest::keyPress(&canvas, Qt::Key_Space);
QCOMPARE(canvas.cursor().shape(), Qt::OpenHandCursor);
QTest::mousePress(&canvas, Qt::LeftButton, Qt::NoModifier, QPoint(50, 50));
drag(canvas, QPointF(60, 70));
QCOMPARE(session.viewport.pan, pan + QSizeF(45, 40));
QTest::mouseRelease(&canvas, Qt::LeftButton, Qt::NoModifier, QPoint(60, 70));
QTest::keyRelease(&canvas, Qt::Key_Space);
QCOMPARE(canvas.cursor().shape(), Qt::ArrowCursor);
// Importing, a press starts no drag.
session.selectTool(NavigationTool::hand);
session.setIsImporting(true);
QTest::mousePress(&canvas, Qt::LeftButton, Qt::NoModifier, QPoint(50, 50));
drag(canvas, QPointF(90, 90));
QCOMPARE(session.viewport.pan, pan + QSizeF(45, 40));
QTest::mouseRelease(&canvas, Qt::LeftButton, Qt::NoModifier, QPoint(90, 90));
}
void CanvasNavigationTests::theWheelPansAndZoomsWithAModifier()
{
Shown shown;
CanvasView &canvas = *shown.canvas;
EditorSession &session = shown.session;
shown.settle();
session.zoom(1);
const QSizeF size = shown.documentSize();
const QPointF pointer(120, 90);
const double lines = QApplication::wheelScrollLines();
QSizeF pan = session.viewport.pan;
// Pixels count as they are, and win over notches.
wheel(canvas, pointer, QPoint(0, -30), QPoint(0, -240), Qt::NoModifier);
pan += QSizeF(0, -30);
QCOMPARE(session.viewport.pan, pan);
QVERIFY(!session.viewport.followsFit());
// A notch is a few lines, twelve points each.
wheel(canvas, pointer, QPoint(), QPoint(0, 120), Qt::NoModifier);
pan += QSizeF(0, 12 * lines);
QCOMPARE(session.viewport.pan, pan);
wheel(canvas, pointer, QPoint(), QPoint(-60, 0), Qt::NoModifier);
pan += QSizeF(-6 * lines, 0);
QCOMPARE(session.viewport.pan, pan);
// Ctrl or Alt zooms about the pointer, by Swift's curve.
const QPointF under = session.viewport.documentPoint(pointer, size);
wheel(canvas, pointer, QPoint(), QPoint(0, 120), Qt::ControlModifier);
QVERIFY(qFuzzyCompare(session.viewport.zoom(), std::exp(-lines * 0.015)));
QCOMPARE(session.viewport.documentPoint(pointer, size), under);
wheel(canvas, pointer, QPoint(0, 10), QPoint(), Qt::AltModifier);
QVERIFY(qFuzzyCompare(session.viewport.zoom(), std::exp(-lines * 0.015) * std::exp(-10 * 0.015)));
QCOMPARE(session.viewport.documentPoint(pointer, size), under);
// Without a document the wheel does nothing.
Shown empty(std::nullopt);
wheel(*empty.canvas, pointer, QPoint(0, -30), QPoint(), Qt::NoModifier);
QCOMPARE(empty.session.viewport.pan, QSizeF(0, 0));
wheel(*empty.canvas, pointer, QPoint(), QPoint(0, 120), Qt::ControlModifier);
QCOMPARE(empty.session.viewport.zoom(), 1.0);
}
void CanvasNavigationTests::aPinchZoomsAboutThePointer()
{
Shown shown;
shown.settle();
shown.session.zoom(1);
const QSizeF size = shown.documentSize();
const QPointF pointer(120, 90);
const QPointF under = shown.session.viewport.documentPoint(pointer, size);
QNativeGestureEvent pinch(Qt::ZoomNativeGesture, QPointingDevice::primaryPointingDevice(), 2, pointer, pointer,
shown.canvas->mapToGlobal(pointer.toPoint()), 0.5, QPointF());
QVERIFY(QApplication::sendEvent(shown.canvas, &pinch));
QCOMPARE(shown.session.viewport.zoom(), 1.5);
QCOMPARE(shown.session.viewport.documentPoint(pointer, size), under);
// Other gestures pass on.
QNativeGestureEvent swipe(Qt::SwipeNativeGesture, QPointingDevice::primaryPointingDevice(), 3, pointer, pointer,
shown.canvas->mapToGlobal(pointer.toPoint()), 0.5, QPointF());
QApplication::sendEvent(shown.canvas, &swipe);
QCOMPARE(shown.session.viewport.zoom(), 1.5);
}
QTEST_MAIN(CanvasNavigationTests)
#include "CanvasNavigationTests.moc"