Scrub numbers by dragging their titles in the sheets and panels (12.12c2)

This commit is contained in:
雷电芽衣 committed 2026-09-29 17:07:35 -04:00
1 parent 5bc7889387
commit aa253d9715
25 files changed
+830 -26

No files matched your search

+3 -1
View File
@@ -35,7 +35,7 @@ inline void drag(QWidget &label, double dx, bool release = true)
send(label, QEvent::MouseButtonRelease, QPointF(2 + dx, 2), Qt::LeftButton, Qt::NoButton);
}
// Types 7, which applies, then scrubs, holding the press.
// Types 7, then scrubs, holding the press.
inline QString scrubOverTyping(QLineEdit &field, QWidget &label, double dx)
{
field.setFocus();
@@ -48,6 +48,8 @@ inline QString scrubOverTyping(QLineEdit &field, QWidget &label, double dx)
send(label, QEvent::MouseButtonRelease, QPointF(2 + dx, 2), Qt::LeftButton, Qt::NoButton);
if (field.text() != during || !field.hasFocus())
throw std::runtime_error("the release changed the field");
// Leaves while its sheet lives, as a closing panel does.
field.clearFocus();
return during;
}
+195
View File
@@ -0,0 +1,195 @@
#include "Document/BrushStroke.h"
#include "ScrubFixtures.h"
#include "UI/CameraRawControls.h"
#include "UI/CameraRawRow.h"
#include <QAbstractButton>
// Swift's scrubbable Camera Raw titles, row by row.
namespace {
struct Panel {
EditorSession session;
std::unique_ptr<CameraRawControls> controls;
Panel()
{
session.createDocument(8, 8);
QImage image = BrushRaster::context(8, 8, false);
image.fill(QColor(200, 120, 60));
session.insert(ImportedImage(image, image, QStringLiteral("Warm")));
session.beginFilter(FilterKind::cameraRaw);
controls = std::make_unique<CameraRawControls>(session);
controls->resize(392, 700);
showActive(*controls);
}
CameraRawSettings raw() const { return session.filterEdit().value().settings.cameraRaw; }
void set(const std::function<void(CameraRawSettings &)> &change)
{
FilterSettings settings = session.filterEdit().value().settings;
change(settings.cameraRaw);
session.updateFilter(settings, true);
}
void panel(const std::function<void(CameraRawPanel &)> &change)
{
CameraRawPanel copy = session.filterEdit().value().rawPanel;
change(copy);
session.setCameraRawPanel(copy);
}
// The title of the row whose slider is `name`.
QLabel &title(const QString &name) const
{
auto *slider = controls->findChild<QSlider *>(name + QStringLiteral("Slider"));
if (!slider)
throw std::runtime_error(name.toStdString());
return *slider->parentWidget()->findChildren<QLabel *>(Qt::FindDirectChildrenOnly).value(0);
}
bool scrubs(const QString &name) const { return title(name).cursor().shape() == Qt::SizeHorCursor; }
};
// Presses twice, the second a double click, then drags.
void doubleClickDrag(QWidget &label, double dx)
{
send(label, QEvent::MouseButtonPress, QPointF(2, 2), Qt::LeftButton, Qt::LeftButton);
send(label, QEvent::MouseButtonRelease, QPointF(2, 2), Qt::LeftButton, Qt::NoButton);
send(label, QEvent::MouseButtonDblClick, QPointF(2, 2), Qt::LeftButton, Qt::LeftButton);
send(label, QEvent::MouseMove, QPointF(2 + dx, 2), Qt::NoButton, Qt::LeftButton);
send(label, QEvent::MouseButtonRelease, QPointF(2 + dx, 2), Qt::LeftButton, Qt::NoButton);
}
}
class ScrubbableCameraRawTests : public QObject {
Q_OBJECT
private slots:
void theMainRowsScrubALastDecimalAPoint();
void aDoubleClickResetsAndStillScrubs();
void curveAndHslFamilyTitlesScrubColorAndPointTitlesDoNot();
void detailOpticsGeometryAndCalibrationScrubAUnitAPoint();
void gradingTitlesStayPassive();
void altHeldScrubsShowNoPreview();
};
void ScrubbableCameraRawTests::theMainRowsScrubALastDecimalAPoint()
{
Panel panel;
// Two decimals: a point is a hundredth, unrounded.
drag(panel.title("exposure"), 50.5);
QVERIFY(qAbs(panel.raw().exposure - 0.505) < 1e-9);
drag(panel.title("exposure"), 9000);
QCOMPARE(panel.raw().exposure, 5.0);
drag(panel.title("exposure"), -90000);
QCOMPARE(panel.raw().exposure, -5.0);
drag(panel.title("contrast"), -30.5);
QCOMPARE(panel.raw().contrast, -30.5);
QCOMPARE(panel.raw().exposure, -5.0);
// The typed setter: Custom white balance, no clipping view.
panel.set([](CameraRawSettings &settings) { settings.whiteBalance = CameraRawWhiteBalance::automatic; });
panel.panel([](CameraRawPanel &raw) { raw.clipping = CameraRawClipping::highlights; });
drag(panel.title("temperature"), 12);
QCOMPARE(panel.raw().temperature, 12.0);
QVERIFY(panel.raw().whiteBalance == CameraRawWhiteBalance::custom);
QVERIFY(!panel.session.filterEdit().value().rawPanel.clipping);
panel.set([](CameraRawSettings &settings) { settings.whiteBalance = CameraRawWhiteBalance::automatic; });
drag(panel.title("tint"), -7);
QCOMPARE(panel.raw().tint, -7.0);
QVERIFY(panel.raw().whiteBalance == CameraRawWhiteBalance::custom);
QCOMPARE(scrubOverTyping(find<QLineEdit>(*panel.controls, "contrastField"), panel.title("contrast"), 3), QString("-28"));
}
void ScrubbableCameraRawTests::aDoubleClickResetsAndStillScrubs()
{
Panel panel;
drag(panel.title("contrast"), 40);
QCOMPARE(panel.raw().contrast, 40.0);
// The reset runs first; the second press scrubs from zero.
doubleClickDrag(panel.title("contrast"), 12);
QCOMPARE(panel.raw().contrast, 12.0);
drag(panel.title("contrast"), -900);
QCOMPARE(panel.raw().contrast, -100.0);
}
void ScrubbableCameraRawTests::curveAndHslFamilyTitlesScrubColorAndPointTitlesDoNot()
{
Panel panel;
drag(panel.title("curveHighlights"), 20.5);
QCOMPARE(panel.raw().curve.highlights, 20.5);
drag(panel.title("curveHighlights"), -900);
QCOMPARE(panel.raw().curve.highlights, -100.0);
drag(panel.title("refineSaturation"), 900);
QCOMPARE(panel.raw().curve.refineSaturation, 100.0);
// HSL families scrub the shown component.
drag(panel.title("familyReds"), 15);
QCOMPARE(panel.raw().mixer.hue[0], 15.0);
panel.panel([](CameraRawPanel &raw) { raw.mixerTab = CameraRawMixerTab::saturation; });
drag(panel.title("familyOranges"), -900);
QCOMPARE(panel.raw().mixer.saturation[1], -100.0);
QCOMPARE(panel.raw().mixer.hue[1], 0.0);
// Swift's colorSlider and pointSlider keep plain titles.
panel.panel([](CameraRawPanel &raw) { raw.mixerPage = CameraRawMixerPage::color; });
for (const QString &name : {QStringLiteral("colorHue"), QStringLiteral("colorSaturation"), QStringLiteral("colorLuminance")})
QVERIFY(!panel.scrubs(name));
panel.set([](CameraRawSettings &settings) { settings.mixer.points = {CameraRawPointColor{.hue = 30, .saturation = 1, .luminance = 0.5}}; });
panel.panel([](CameraRawPanel &raw) { raw.mixerPage = CameraRawMixerPage::point; });
QVERIFY(!panel.scrubs("hueShift"));
QVERIFY(!panel.scrubs("saturationShift"));
drag(panel.title("hueShift"), 30);
QCOMPARE(panel.raw().mixer.points[0].hueShift, 0.0);
}
void ScrubbableCameraRawTests::detailOpticsGeometryAndCalibrationScrubAUnitAPoint()
{
Panel panel;
// The typed setter: no sharpen-mask view, unrounded.
panel.panel([](CameraRawPanel &raw) { raw.sharpenMask = true; });
drag(panel.title("sharpenMasking"), 10.5);
QCOMPARE(panel.raw().detail.sharpenMasking, 10.5);
QVERIFY(!panel.session.filterEdit().value().rawPanel.sharpenMask);
drag(panel.title("sharpenAmount"), 900);
QCOMPARE(panel.raw().detail.sharpenAmount, 150.0);
drag(panel.title("sharpenAmount"), -900);
QCOMPARE(panel.raw().detail.sharpenAmount, 0.0);
drag(panel.title("distortion"), -12.5);
QCOMPARE(panel.raw().optics.distortion, -12.5);
drag(panel.title("lensMidpoint"), 900);
QCOMPARE(panel.raw().optics.vignetteMidpoint, 100.0);
drag(panel.title("rotate"), 900);
QCOMPARE(panel.raw().geometry.rotate, 45.0);
drag(panel.title("vertical"), 7.5);
QCOMPARE(panel.raw().geometry.vertical, 7.5);
drag(panel.title("shadowTint"), -900);
QCOMPARE(panel.raw().calibration.shadowTint, -100.0);
drag(panel.title("redHue"), 3.5);
QCOMPARE(panel.raw().calibration.redHue, 3.5);
}
void ScrubbableCameraRawTests::gradingTitlesStayPassive()
{
Panel panel;
QVERIFY(!panel.scrubs("gradeBlending"));
QVERIFY(!panel.scrubs("gradeBalance"));
const double blending = panel.raw().grading.blending;
drag(panel.title("gradeBlending"), 20);
QCOMPARE(panel.raw().grading.blending, blending);
}
void ScrubbableCameraRawTests::altHeldScrubsShowNoPreview()
{
Panel panel;
QWindow *window = panel.controls->windowHandle();
QTest::keyPress(window, Qt::Key_Alt, Qt::AltModifier);
QVERIFY(QGuiApplication::keyboardModifiers().testFlag(Qt::AltModifier));
// The slider shows clipping under Alt; a scrub never does.
drag(panel.title("exposure"), 10.5);
QVERIFY(qAbs(panel.raw().exposure - 0.105) < 1e-9);
QVERIFY(!panel.session.filterEdit().value().rawPanel.clipping);
drag(panel.title("blacks"), -12.5);
QCOMPARE(panel.raw().blacks, -12.5);
QVERIFY(!panel.session.filterEdit().value().rawPanel.clipping);
drag(panel.title("sharpenMasking"), 20.5);
QCOMPARE(panel.raw().detail.sharpenMasking, 20.5);
QVERIFY(!panel.session.filterEdit().value().rawPanel.sharpenMask);
// The slider itself, for contrast, shows the view under Alt.
panel.controls->findChild<QSlider *>(QStringLiteral("exposureSlider"))->setValue(100);
QVERIFY(panel.session.filterEdit().value().rawPanel.clipping.has_value());
QTest::keyRelease(window, Qt::Key_Alt, Qt::NoModifier);
}
QTEST_MAIN(ScrubbableCameraRawTests)
#include "ScrubbableCameraRawTests.moc"
+383
View File
@@ -0,0 +1,383 @@
#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"
+2
View File
@@ -146,6 +146,8 @@ compositor_test(LayerContextMenuEdgeTests)
compositor_test(NavigationToolHeaderTests)
compositor_test(NumericScrubTests)
compositor_test(ScrubbableLabelsTests)
compositor_test(ScrubbableSheetsTests)
compositor_test(ScrubbableCameraRawTests)
compositor_test(ScrubbableTransformTests)
compositor_test(NewCanvasSheetTests)
compositor_test(OmarchyThemeTests)