#include "DialogDesk.h" #include "IO/ProjectController.h" #include "UI/CanvasSizeSheet.h" #include "UI/ColorPickerSheet.h" #include "UI/ImageSizeSheet.h" #include #include #include // The controller's Canvas Size and Image Size: sheet, resize, step. class ProjectResizeTests : public QObject { Q_OBJECT private slots: void theCanvasSizeSheetResizesTheCanvasAsOneStep(); void aCancelledOrRefusedSheetChangesNothing(); void theImageSizeSheetScalesThePixelsAsOneStep(); void aResizeThatFailsIsExplained(); }; namespace { struct Desk { EditorSession session; ProjectController controller{session}; QWidget window; bool done = false; Desk() { session.createDocument(100, 50); session.insert(ImportedImage(QImage(10, 10, QImage::Format_RGBA8888_Premultiplied), QImage(), "Image"), QPointF(45, 25)); window.resize(600, 400); window.show(); controller.window = &window; } QDialog &dialog() { auto *shown = window.findChild(); if (!shown) throw std::runtime_error("no sheet shown"); return *shown; } // Typed, then Return: the field commits, then the default button. void type(const char *name, const QString &text) { auto *field = dialog().findChild(QString::fromLatin1(name)); if (!field) throw std::runtime_error(std::string("no field named ") + name); field->setFocus(); field->selectAll(); QTest::keyClicks(field, text); QTest::keyClick(field, Qt::Key_Return); } std::function finished() { done = false; return [this] { done = true; }; } }; } void ProjectResizeTests::theCanvasSizeSheetResizesTheCanvasAsOneStep() { Desk desk; const int steps = desk.session.history.undoCount(); desk.controller.canvasSize(desk.finished()); // The sheet holds the window; the project is busy meanwhile. QVERIFY(desk.session.isProjectBusy()); QCOMPARE(desk.dialog().windowTitle(), QString("Canvas Size")); QVERIFY(desk.dialog().isVisible() && desk.dialog().windowModality() == Qt::WindowModal); QCOMPARE(desk.dialog().minimumSize(), desk.dialog().maximumSize()); QVERIFY(desk.dialog().findChild()); desk.type("canvasWidth", "200"); QTRY_VERIFY(desk.done); QCOMPARE(desk.session.document().value().width, 200); QCOMPARE(desk.session.document().value().height, 50); // Centred: the layer moves half the growth to the right. QCOMPARE(desk.session.activeLayer().value().origin(), QPointF(90, 20)); QCOMPARE(desk.session.history.undoCount(), steps + 1); QCOMPARE(desk.session.history.undoName(), QString("Canvas Size")); QVERIFY(!desk.session.isProjectBusy()); QTRY_VERIFY(!desk.window.findChild()); } void ProjectResizeTests::aCancelledOrRefusedSheetChangesNothing() { Desk desk; const CanvasDocument before = desk.session.document().value(); // Escape and Cancel close the sheet; the project frees. desk.controller.canvasSize(desk.finished()); QTest::keyClick(&desk.dialog(), Qt::Key_Escape); QTRY_VERIFY(desk.done); QVERIFY(!desk.session.isProjectBusy()); desk.controller.imageSize(desk.finished()); desk.dialog().findChild(QStringLiteral("imageCancel"))->click(); QTRY_VERIFY(desk.done); QVERIFY(desk.session.document().value() == before); QVERIFY(!desk.session.isProjectBusy()); QTRY_VERIFY(!desk.window.findChild()); // Busy, or without a window, no sheet opens. desk.session.setIsProjectBusy(true); desk.controller.canvasSize(desk.finished()); QTRY_VERIFY(desk.done); QVERIFY(!desk.window.findChild()); desk.session.setIsProjectBusy(false); desk.controller.window = nullptr; desk.controller.imageSize(desk.finished()); QTRY_VERIFY(desk.done); desk.controller.canvasSize(desk.finished()); QTRY_VERIFY(desk.done); QVERIFY(!desk.session.isProjectBusy()); QVERIFY(desk.session.document().value() == before); } void ProjectResizeTests::theImageSizeSheetScalesThePixelsAsOneStep() { Desk desk; desk.controller.imageSize(desk.finished()); QCOMPARE(desk.dialog().windowTitle(), QString("Image Size")); QVERIFY(desk.dialog().findChild()); desk.type("imageWidth", "50"); QTRY_VERIFY(desk.done); QCOMPARE(desk.session.document().value().width, 50); QCOMPARE(desk.session.document().value().height, 25); QCOMPARE(desk.session.activeLayer().value().transform.size, QSizeF(5, 5)); QCOMPARE(desk.session.history.undoName(), QString("Image Size")); QVERIFY(!desk.session.isProjectBusy()); } void ProjectResizeTests::aResizeThatFailsIsExplained() { Desk desk; // Stretched past what twice the size may hold. LayerTransform wide = desk.session.activeLayer().value().transform; wide.size = QSizeF(20'000, 10); desk.session.beginTransform(); desk.session.previewTransform(wide); desk.session.commitTransform(); const CanvasDocument before = desk.session.document().value(); DialogDesk alerts; alerts.replies = {"OK"}; alerts.note = [&] { return QStringLiteral("busy %1").arg(desk.session.isProjectBusy()); }; desk.controller.imageSize(desk.finished()); desk.type("imageWidth", "200"); QTRY_VERIFY(desk.done); QCOMPARE(alerts.seen, (QStringList{QStringLiteral("alert|2|Couldn’t resize the image|%1|OK|busy 1") .arg(QString::fromUtf8(ProjectError(ProjectError::Kind::tooLarge).what()))})); QVERIFY(desk.session.document().value() == before); QVERIFY(!desk.session.isProjectBusy()); // The canvas's own failure, alike, under its own title. alerts.replies = {"OK"}; wide.origin = QPointF(999'000, 0); wide.size = QSizeF(10, 10); desk.session.beginTransform(); desk.session.previewTransform(wide); desk.session.commitTransform(); desk.controller.canvasSize(desk.finished()); desk.type("canvasWidth", "5000"); QTRY_VERIFY(desk.done); QCOMPARE(alerts.seen.size(), 2); QVERIFY(alerts.seen.last().startsWith("alert|2|Couldn’t change canvas size|")); } QTEST_MAIN(ProjectResizeTests) #include "ProjectResizeTests.moc"