Files
OmaPhoto/tests/ScrubbableSheetsTests.cpp
T

384 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "Document/BrushStroke.h"
#include "ScrubFixtures.h"
#include "UI/CanvasSizeSheet.h"
#include "UI/ColorPickerSheet.h"
#include "UI/EffectsSheet.h"
#include "UI/FilterSheet.h"
#include "UI/HueSaturationSheet.h"
#include "UI/ImageSizeSheet.h"
#include "UI/LevelsSheet.h"
#include <QCheckBox>
#include <QComboBox>
// Swift's scrubbable titles in the sheets and panels.
namespace {
// A document with one coloured layer, left active.
void paint(EditorSession &session)
{
session.createDocument(8, 8);
QImage image = BrushRaster::context(8, 8, false);
image.fill(QColor(120, 160, 200));
session.insert(ImportedImage(image, image, QStringLiteral("Colour")));
}
void choose(QComboBox &box, const QString &text)
{
const int index = box.findText(text);
box.setCurrentIndex(index);
emit box.activated(index);
}
}
class ScrubbableSheetsTests : public QObject {
Q_OBJECT
private slots:
void effectsTitlesScrubToTheTypedLimit();
void hueSaturationTitlesFollowColorize();
void levelsTitlesScrubTonesAndGamma();
void filterTitlesMoveALastDecimalAPoint();
void colorPickerChannelsScrubWholeLevels();
void filterTitlesKeepEveryDecimalsSensitivity();
void canvasSizeTitlesScrubInTheirUnit();
void canvasSizeCentimetresScrubTheirLimits();
void imageSizeTitlesScrubPixelsPrintSizeAndResolution();
void imageSizeLimitsFollowUnitsLockAndResolution();
};
void ScrubbableSheetsTests::effectsTitlesScrubToTheTypedLimit()
{
EditorSession session;
paint(session);
session.addEffect(LayerEffectKind::stroke);
EffectsSheet sheet(session, LayerEffectKind::stroke);
showActive(sheet);
const auto stroke = [&session] { return session.editingEffects().stroke.value(); };
drag(scrubbed(sheet, "Size"), 10);
QCOMPARE(stroke().size, 14.0);
// Past the slider's end, to what typing reaches.
drag(scrubbed(sheet, "Size"), 9000);
QCOMPARE(stroke().size, 500.0);
drag(scrubbed(sheet, "Size"), -9000);
QCOMPARE(stroke().size, 0.0);
drag(scrubbed(sheet, "Opacity"), -30.5);
QVERIFY(qAbs(stroke().opacity - 0.695) < 1e-12);
QCOMPARE(scrubOverTyping(find<QLineEdit>(sheet, "sizeField"), scrubbed(sheet, "Size"), 3), QString("3"));
}
void ScrubbableSheetsTests::hueSaturationTitlesFollowColorize()
{
EditorSession session;
paint(session);
session.beginHueSaturation();
HueSaturationSheet sheet(session);
showActive(sheet);
const auto settings = [&session] { return session.hueSaturation().value().settings; };
drag(scrubbed(sheet, "Hue"), 25.5);
QCOMPARE(settings().hue(), 25.5);
drag(scrubbed(sheet, "Hue"), 900);
QCOMPARE(settings().hue(), 180.0);
drag(scrubbed(sheet, "Hue"), -900);
QCOMPARE(settings().hue(), -180.0);
drag(scrubbed(sheet, "Saturation"), -900);
QCOMPARE(settings().saturation(), -100.0);
drag(scrubbed(sheet, "Lightness"), 40);
QCOMPARE(settings().lightness(), 40.0);
// Colorize sets hue and saturation outright: new ranges.
for (QCheckBox *box : sheet.findChildren<QCheckBox *>())
if (box->text() == "Colorize")
box->click();
QVERIFY(settings().colorize);
drag(scrubbed(sheet, "Hue"), 900);
QCOMPARE(settings().hue(), 360.0);
drag(scrubbed(sheet, "Saturation"), -900);
QCOMPARE(settings().saturation(), 0.0);
QCOMPARE(scrubOverTyping(find<QLineEdit>(sheet, "lightnessField"), scrubbed(sheet, "Lightness"), 3), QString("3"));
}
void ScrubbableSheetsTests::levelsTitlesScrubTonesAndGamma()
{
EditorSession session;
paint(session);
session.beginLevels();
LevelsSheet sheet(session);
showActive(sheet);
const auto range = [&session] { return session.levels().value().settings.current(); };
// Gamma moves a hundredth a point, within 0.1 and 9.99.
drag(scrubbed(sheet, "Gamma"), 50);
QVERIFY(qAbs(range().gamma - 1.5) < 1e-12);
drag(scrubbed(sheet, "Gamma"), 9000);
QCOMPARE(range().gamma, 9.99);
drag(scrubbed(sheet, "Gamma"), -9000);
QCOMPARE(range().gamma, 0.1);
drag(scrubbed(sheet, "Input black"), 20);
QCOMPARE(range().black, 20.0);
drag(scrubbed(sheet, "Input black"), -900);
QCOMPARE(range().black, 0.0);
drag(scrubbed(sheet, "Output white"), -30.5);
QCOMPARE(range().outputWhite, 224.5);
drag(scrubbed(sheet, "Output white"), 900);
QCOMPARE(range().outputWhite, 255.0);
QCOMPARE(scrubOverTyping(find<QLineEdit>(sheet, "levelsOutputblack"), scrubbed(sheet, "Output black"), 3), QString("3"));
}
void ScrubbableSheetsTests::filterTitlesMoveALastDecimalAPoint()
{
EditorSession session;
paint(session);
session.beginFilter(FilterKind::gaussianBlur);
FilterSheet sheet(session);
showActive(sheet);
const auto radius = [&session] { return session.filterEdit().value().settings.radius; };
const double start = radius();
// One decimal: a point is a tenth.
drag(scrubbed(sheet, "Radius"), 10);
QVERIFY(qAbs(radius() - (start + 1)) < 1e-9);
drag(scrubbed(sheet, "Radius"), 90000);
QCOMPARE(radius(), 250.0);
drag(scrubbed(sheet, "Radius"), -90000);
QCOMPARE(radius(), 0.1);
QCOMPARE(scrubOverTyping(find<QLineEdit>(sheet, "radiusField"), scrubbed(sheet, "Radius"), 30), QString("3.1"));
}
void ScrubbableSheetsTests::filterTitlesKeepEveryDecimalsSensitivity()
{
EditorSession session;
paint(session);
session.beginFilter(FilterKind::gaussianBlur);
{
FilterSheet sheet(session);
showActive(sheet);
const double start = session.filterEdit().value().settings.radius;
// No snap: a point and a half is 0.15.
drag(scrubbed(sheet, "Radius"), 1.5);
QVERIFY(qAbs(session.filterEdit().value().settings.radius - (start + 0.15)) < 1e-9);
}
session.cancelFilter();
session.beginFilter(FilterKind::exposure);
{
FilterSheet sheet(session);
showActive(sheet);
const auto exposure = [&session] { return session.filterEdit().value().settings.exposure; };
drag(scrubbed(sheet, "Exposure"), 50.5);
QVERIFY(qAbs(exposure().exposure - 0.505) < 1e-9);
// Four decimals: fifty points are 0.005.
drag(scrubbed(sheet, "Offset"), 50);
QVERIFY(qAbs(exposure().offset - 0.005) < 1e-12);
const double gamma = exposure().gamma;
drag(scrubbed(sheet, "Gamma"), 25);
QVERIFY(qAbs(exposure().gamma - (gamma + 0.25)) < 1e-9);
drag(scrubbed(sheet, "Gamma"), -90000);
QCOMPARE(exposure().gamma, 0.01);
}
session.cancelFilter();
session.beginFilter(FilterKind::motionBlur);
FilterSheet sheet(session);
showActive(sheet);
// No decimals: a point is a degree, fractions kept.
const double angle = session.filterEdit().value().settings.angle;
drag(scrubbed(sheet, "Angle"), 15.5);
QCOMPARE(session.filterEdit().value().settings.angle, angle + 15.5);
}
void ScrubbableSheetsTests::colorPickerChannelsScrubWholeLevels()
{
EditorSession session;
paint(session);
session.openColorPicker(false);
ColorPickerSheet sheet(session, [](bool) {});
showActive(sheet);
const auto color = [&session] { return session.colorPicker().value().color(); };
// Whole levels: 100.6 points lands on 101.
drag(scrubbed(sheet, "R"), 100.6);
QCOMPARE(color().red, 101 / 255.0);
drag(scrubbed(sheet, "G"), 900);
QCOMPARE(color().green, 1.0);
drag(scrubbed(sheet, "B"), 30);
QCOMPARE(std::lround(color().blue * 255), 30L);
drag(scrubbed(sheet, "R"), -900);
QCOMPARE(color().red, 0.0);
QCOMPARE(scrubOverTyping(find<QLineEdit>(sheet, "b"), scrubbed(sheet, "B"), 3), QString("33"));
}
void ScrubbableSheetsTests::canvasSizeTitlesScrubInTheirUnit()
{
CanvasDocument document{1200, 800};
document.resolution = 72;
CanvasSizeSheet sheet(document, PaletteColor::black(), PaletteColor::white(), [](std::optional<CanvasSizeOptions>) {});
showActive(sheet);
QLineEdit &width = find<QLineEdit>(sheet, "canvasWidth");
QLineEdit &height = find<QLineEdit>(sheet, "canvasHeight");
// A held drag keeps its start through each reshape.
QLabel &title = scrubbed(sheet, "Width");
drag(title, 10, false);
QCOMPARE(width.text(), QString("1210"));
send(title, QEvent::MouseMove, QPointF(22, 2), Qt::NoButton, Qt::LeftButton);
QCOMPARE(width.text(), QString("1220"));
send(title, QEvent::MouseButtonRelease, QPointF(22, 2), Qt::LeftButton, Qt::NoButton);
drag(title, -9.6);
QCOMPARE(width.text(), QString("1210"));
drag(scrubbed(sheet, "Height"), 90000);
QCOMPARE(height.text(), QString("30000"));
drag(scrubbed(sheet, "Height"), -90000);
QCOMPARE(height.text(), QString("1"));
// A percent is twelve points of a 1,200-pixel side.
choose(find<QComboBox>(sheet, "canvasUnits"), "Percent");
drag(scrubbed(sheet, "Width"), 12);
QCOMPARE(width.text(), QString("102"));
choose(find<QComboBox>(sheet, "canvasUnits"), "Inches");
drag(scrubbed(sheet, "Width"), -144);
QCOMPARE(width.text(), QString("15"));
// Relative counts from the current size, locked keeps the ratio.
choose(find<QComboBox>(sheet, "canvasUnits"), "Pixels");
find<QCheckBox>(sheet, "canvasRelative").click();
drag(scrubbed(sheet, "Width"), -90000);
QCOMPARE(width.text(), QString("-1199"));
find<QCheckBox>(sheet, "canvasRelative").click();
find<QCheckBox>(sheet, "canvasLocked").click();
drag(scrubbed(sheet, "Height"), -90000);
QCOMPARE(height.text(), QString("1"));
drag(scrubbed(sheet, "Width"), -90000);
QCOMPARE(width.text(), QString("1.5"));
drag(scrubbed(sheet, "Height"), 90000);
QCOMPARE(height.text(), QString("20000"));
drag(scrubbed(sheet, "Width"), 90000);
QCOMPARE(width.text(), QString("30000"));
QCOMPARE(height.text(), QString("20000"));
QCOMPARE(scrubOverTyping(find<QLineEdit>(sheet, "canvasWidth"), scrubbed(sheet, "Width"), -2), QString("29998"));
}
void ScrubbableSheetsTests::canvasSizeCentimetresScrubTheirLimits()
{
CanvasDocument document{1200, 800};
document.resolution = 72;
CanvasSizeSheet sheet(document, PaletteColor::black(), PaletteColor::white(), [](std::optional<CanvasSizeOptions>) {});
showActive(sheet);
QLineEdit &width = find<QLineEdit>(sheet, "canvasWidth");
QLineEdit &height = find<QLineEdit>(sheet, "canvasHeight");
choose(find<QComboBox>(sheet, "canvasUnits"), "Centimeters");
// A point is 2.54 / 72 cm; 72 add 2.54.
drag(scrubbed(sheet, "Width"), 72);
QCOMPARE(width.text(), QString("45"));
drag(scrubbed(sheet, "Width"), 90000);
QCOMPARE(width.text(), QString("1058.333"));
drag(scrubbed(sheet, "Width"), -90000);
QCOMPARE(width.text(), QString("0.035"));
find<QCheckBox>(sheet, "canvasRelative").click();
drag(scrubbed(sheet, "Height"), -90000);
QCOMPARE(height.text(), QString("-28.187"));
find<QCheckBox>(sheet, "canvasRelative").click();
find<QCheckBox>(sheet, "canvasLocked").click();
drag(scrubbed(sheet, "Height"), 90000);
QCOMPARE(height.text(), QString("705.556"));
}
void ScrubbableSheetsTests::imageSizeLimitsFollowUnitsLockAndResolution()
{
{
// Unlocked, a hundred megapixels over a 5,000-pixel height.
CanvasDocument tall{1000, 5000};
tall.resolution = 72;
ImageSizeSheet sheet(tall, [](std::optional<ImageSizeOptions>) {});
showActive(sheet);
find<QCheckBox>(sheet, "imageLocked").click();
drag(scrubbed(sheet, "Width"), 90000);
QCOMPARE(find<QLineEdit>(sheet, "imageWidth").text(), QString("20000"));
QCOMPARE(find<QLineEdit>(sheet, "imageHeight").text(), QString("5000"));
}
CanvasDocument document{1200, 800};
document.resolution = 72;
ImageSizeSheet sheet(document, [](std::optional<ImageSizeOptions>) {});
showActive(sheet);
QLineEdit &width = find<QLineEdit>(sheet, "imageWidth");
QLineEdit &height = find<QLineEdit>(sheet, "imageHeight");
QComboBox &units = find<QComboBox>(sheet, "imageUnits");
// A percent is twelve points of 1,200 pixels.
choose(units, "Percent");
drag(scrubbed(sheet, "Width"), 12);
QCOMPARE(width.text(), QString("101"));
drag(scrubbed(sheet, "Height"), -16);
QCOMPARE(height.text(), QString("99"));
// Resampled inches: 72 points an inch, the pixels following.
choose(units, "Inches");
drag(scrubbed(sheet, "Width"), 72);
QCOMPARE(width.text(), QString("18"));
QCOMPARE(find<QLabel>(sheet, "imageResult").text(), QString("Result: 1,296 × 864 pixels"));
// A resolution scrub keeps print sizes and scales the pixels.
drag(scrubbed(sheet, "Resolution"), 72);
QCOMPARE(find<QLineEdit>(sheet, "imageResolution").text(), QString("144"));
QCOMPARE(width.text(), QString("18"));
QCOMPARE(find<QLabel>(sheet, "imageResult").text(), QString("Result: 2,592 × 1,728 pixels"));
// Resampled centimetres: 144 points add 2.54 at 144 ppi.
choose(units, "Centimeters");
drag(scrubbed(sheet, "Width"), 144);
QCOMPARE(width.text(), QString("48"));
choose(units, "Inches");
drag(scrubbed(sheet, "Width"), 90000);
QCOMPARE(width.text(), QString("85.052"));
choose(units, "Centimeters");
drag(scrubbed(sheet, "Height"), -90000);
QCOMPARE(height.text(), QString("0.018"));
}
void ScrubbableSheetsTests::imageSizeTitlesScrubPixelsPrintSizeAndResolution()
{
CanvasDocument document{1200, 800};
document.resolution = 72;
ImageSizeSheet sheet(document, [](std::optional<ImageSizeOptions>) {});
showActive(sheet);
QLineEdit &width = find<QLineEdit>(sheet, "imageWidth");
QLineEdit &height = find<QLineEdit>(sheet, "imageHeight");
QLineEdit &resolution = find<QLineEdit>(sheet, "imageResolution");
// Locked, the height follows; a hundred megapixels at most.
drag(scrubbed(sheet, "Width"), 300);
QCOMPARE(width.text(), QString("1500"));
QCOMPARE(height.text(), QString("1000"));
drag(scrubbed(sheet, "Width"), 90000);
QCOMPARE(width.text(), QString("12247.449"));
drag(scrubbed(sheet, "Height"), -90000);
QCOMPARE(height.text(), QString("1"));
QCOMPARE(width.text(), QString("1.5"));
drag(scrubbed(sheet, "Resolution"), 10.4);
QCOMPARE(resolution.text(), QString("82"));
drag(scrubbed(sheet, "Resolution"), 90000);
QCOMPARE(resolution.text(), QString("9600"));
drag(scrubbed(sheet, "Resolution"), -90000);
QCOMPARE(resolution.text(), QString("1"));
// Without resampling a point is a hundredth of an inch.
find<QCheckBox>(sheet, "imageResample").click();
QCOMPARE(find<QComboBox>(sheet, "imageUnits").currentText(), QString("Inches"));
QCOMPARE(width.text(), QString("1200"));
drag(scrubbed(sheet, "Width"), -60000);
QCOMPARE(width.text(), QString("600"));
QCOMPARE(resolution.text(), QString("2"));
// Up to one pixel per inch, down to 9,600.
drag(scrubbed(sheet, "Width"), 90000);
QCOMPARE(width.text(), QString("1200"));
QCOMPARE(resolution.text(), QString("1"));
drag(scrubbed(sheet, "Width"), -200000);
QCOMPARE(width.text(), QString("0.125"));
// A point is 0.0254 cm: a hundred make 2.54.
choose(find<QComboBox>(sheet, "imageUnits"), "Centimeters");
drag(scrubbed(sheet, "Width"), 100);
QCOMPARE(width.text(), QString("3"));
QCOMPARE(resolution.text(), QString("1016"));
QCOMPARE(scrubOverTyping(resolution, scrubbed(sheet, "Resolution"), 4), QString("1020"));
// A resolution of nothing leaves no print size to scrub.
resolution.setFocus();
resolution.selectAll();
QTest::keyClicks(&resolution, QStringLiteral("0"));
QTest::keyClick(&resolution, Qt::Key_Return);
QVERIFY(!scrubbed(sheet, "Width").isEnabled());
QVERIFY(!scrubbed(sheet, "Height").isEnabled());
// A positive resolution again brings the titles back.
drag(scrubbed(sheet, "Resolution"), 72);
QCOMPARE(resolution.text(), QString("72"));
QVERIFY(scrubbed(sheet, "Width").isEnabled());
QVERIFY(scrubbed(sheet, "Height").isEnabled());
drag(scrubbed(sheet, "Height"), -100);
QCOMPARE(height.text(), QString("26"));
QCOMPARE(resolution.text(), QString("78.154"));
}
QTEST_MAIN(ScrubbableSheetsTests)
#include "ScrubbableSheetsTests.moc"