Krita Source Code Documentation
Loading...
Searching...
No Matches
wdg_imagesize.cc
Go to the documentation of this file.
1/*
2 * dlg_imagesize.cc - part of KimageShop^WKrayon^WKrita
3 *
4 * SPDX-FileCopyrightText: 2004 Boudewijn Rempt <boud@valdyas.org>
5 * SPDX-FileCopyrightText: 2009 C. Boemann <cbo@boemann.dk>
6 * SPDX-FileCopyrightText: 2013 Juan Palacios <jpalaciosdev@gmail.com>
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11#include "wdg_imagesize.h"
12
13#include <QLocale>
14#include <kis_config.h>
15
16#include <KoUnit.h>
17#include <kis_size_group.h>
18#include <klocalizedstring.h>
19
20#include <kis_filter_strategy.h>
21
24#include "kis_signals_blocker.h"
25
28
29static const int maxImagePixelSize = 100000000;
31
32const QString WdgImageSize::PARAM_PREFIX = "imagesizedlg";
37const QString WdgImageSize::PARAM_PRINT_SIZE_SEPARATE = WdgImageSize::PARAM_PREFIX + "_printSizeSeparatly";
38
39#include "ui_wdg_imagesize.h"
40
41class PageImageSize : public QWidget, public Ui::WdgImageSize
42{
43 Q_OBJECT
44
45public:
46 PageImageSize(QWidget *parent) : QWidget(parent) {
47 setupUi(this);
48 }
49};
50
51
52static QString pixelsInchStr()
53{
54 static QString str = i18n("Pixels/Inch");
55 return str;
56}
57
58static const QString pixelsCentimeterStr()
59{
60 static QString str = i18n("Pixels/Centimeter");
61 return str;
62}
63
64WdgImageSize::WdgImageSize(QWidget *parent, int width, int height, double resolution)
65 : QWidget(parent)
66{
67 // Store original size.
68 m_originalSize.setWidth(width);
69 m_originalSize.setHeight(height);
70
71 m_page = new PageImageSize(this);
72
73 Q_CHECK_PTR(m_page);
74 m_page->layout()->setContentsMargins(0, 0, 0, 0);
75 m_page->setObjectName("image_size");
76
77 m_page->pixelFilterCmb->setIDList(KisFilterStrategyRegistry::instance()->listKeys());
78 m_page->pixelFilterCmb->allowAuto(true);
79 m_page->pixelFilterCmb->setToolTip(KisFilterStrategyRegistry::instance()->formattedDescriptions());
80
81 if (lastUsedFilter) { // Restore or Init..
82 m_page->pixelFilterCmb->setCurrent(lastUsedFilter->id());
83 } else {
84 m_page->pixelFilterCmb->setCurrent(KisCmbIDList::AutoOptionID);
85 }
86
87 connect(this, &WdgImageSize::sigDesiredSizeChanged, [this](qint32 width, qint32 height, double){
89 m_page->pixelFilterCmb->setAutoHint(filterStrategy->name());
90 });
91
98
99 KisConfig cfg(true);
100
104
105 m_widthUnitManager->syncWithOtherUnitManager(m_heightUnitManager); //sync the two managers, so that the units will be the same, but each manager will know a different reference for percents.
106
107 m_widthUnitManager->setApparentUnitFromSymbol("px"); //set unit to pixel.
108
109 m_page->pixelWidthDouble->setUnitManager(m_widthUnitManager);
110 m_page->pixelHeightDouble->setUnitManager(m_heightUnitManager);
111 m_page->pixelWidthDouble->setMaximum(maxImagePixelSize);
112 m_page->pixelHeightDouble->setMaximum(maxImagePixelSize);
113 m_page->pixelWidthDouble->changeValue(width);
114 m_page->pixelHeightDouble->changeValue(height);
115 m_page->pixelWidthDouble->setDisplayUnit(false);
116 m_page->pixelHeightDouble->setDisplayUnit(false);
117 m_page->pixelWidthDouble->setFocus();
118
119 connect(m_page->pixelWidthDouble, qOverload<double>(&KisDoubleParseUnitSpinBox::valueChanged), [this](){
120 Q_EMIT sigDesiredSizeChanged(desiredWidth(), desiredHeight(), desiredResolution());
121 });
122 connect(m_page->pixelHeightDouble, qOverload<double>(&KisDoubleParseUnitSpinBox::valueChanged), [this](){
123 Q_EMIT sigDesiredSizeChanged(desiredWidth(), desiredHeight(), desiredResolution());
124 });
125
127
129
130 m_page->pixelSizeUnit->setModel(m_widthUnitManager);
131 m_page->pixelSizeUnit->setCurrentIndex(unitId);
132
137 KisAcyclicSignalConnector *pixelUnitConnector = new KisAcyclicSignalConnector(this);
138 pixelUnitConnector->connectForwardInt(m_page->pixelSizeUnit, SIGNAL(currentIndexChanged(int)),
139 m_widthUnitManager, SLOT(selectApparentUnitFromIndex(int)));
140 pixelUnitConnector->connectBackwardInt(m_widthUnitManager, SIGNAL(unitChanged(int)),
141 m_page->pixelSizeUnit, SLOT(setCurrentIndex(int)));
142
143 QString imSizeUnit = cfg.readEntry<QString>(PARAM_IMSIZE_UNIT, "px");
144
146
152
153 m_page->printWidth->setUnitManager(m_printSizeUnitManager);
154 m_page->printHeight->setUnitManager(m_printSizeUnitManager);
155 m_page->printWidth->setDisplayUnit(false);
156 m_page->printHeight->setDisplayUnit(false);
157 m_page->printResolution->setAlignment(Qt::AlignRight);
158
159 m_page->printWidthUnit->setModel(m_printSizeUnitManager);
160
161 //TODO: create a resolution dimension in the unit manager.
162 m_page->printResolutionUnit->addItem(pixelsInchStr());
163 m_page->printResolutionUnit->addItem(pixelsCentimeterStr());
164
165
169 KisSizeGroup *labelsGroup = new KisSizeGroup(this);
170 labelsGroup->addWidget(m_page->lblPixelWidth);
171 labelsGroup->addWidget(m_page->lblPixelHeight);
172 labelsGroup->addWidget(m_page->lblPixelFilter);
173 labelsGroup->addWidget(m_page->lblPrintWidth);
174 labelsGroup->addWidget(m_page->lblPrintHeight);
175 labelsGroup->addWidget(m_page->lblResolution);
176
177 KisSizeGroup *spinboxesGroup = new KisSizeGroup(this);
178 spinboxesGroup->addWidget(m_page->pixelWidthDouble);
179 spinboxesGroup->addWidget(m_page->pixelHeightDouble);
180 spinboxesGroup->addWidget(m_page->printWidth);
181 spinboxesGroup->addWidget(m_page->printHeight);
182 spinboxesGroup->addWidget(m_page->printResolution);
183
184 KisSizeGroup *comboboxesGroup = new KisSizeGroup(this);
185 comboboxesGroup->addWidget(m_page->pixelSizeUnit);
186 comboboxesGroup->addWidget(m_page->printWidthUnit);
187 comboboxesGroup->addWidget(m_page->printResolutionUnit);
188 connect(this, SIGNAL(okClicked()), this, SLOT(accept()));
189
194 m_page->pixelAspectRatioBtn->setKeepAspectRatio(true);
195 m_page->printAspectRatioBtn->setKeepAspectRatio(true);
196 m_page->constrainProportionsCkb->setChecked(true);
197
199 m_pixelSizeLocker->connectSpinBoxes(m_page->pixelWidthDouble, m_page->pixelHeightDouble, m_page->pixelAspectRatioBtn);
200
202 m_printSizeLocker->connectSpinBoxes(m_page->printWidth, m_page->printHeight, m_page->printAspectRatioBtn);
203
208 KisAcyclicSignalConnector *constrainsConnector = new KisAcyclicSignalConnector(this);
209 constrainsConnector->connectBackwardBool(
210 m_page->constrainProportionsCkb, SIGNAL(toggled(bool)),
211 this, SLOT(slotLockAllRatioSwitched(bool)));
212
213 constrainsConnector->connectForwardBool(
214 m_pixelSizeLocker, SIGNAL(aspectButtonToggled(bool)),
215 this, SLOT(slotLockPixelRatioSwitched(bool)));
216
217 constrainsConnector->createCoordinatedConnector()->connectBackwardBool(
218 m_printSizeLocker, SIGNAL(aspectButtonToggled(bool)),
219 this, SLOT(slotLockPrintRatioSwitched(bool)));
220
221 constrainsConnector->createCoordinatedConnector()->connectBackwardBool(
222 m_page->adjustPrintSizeSeparatelyCkb, SIGNAL(toggled(bool)),
223 this, SLOT(slotAdjustSeparatelySwitched(bool)));
224
229 KisAcyclicSignalConnector *printUnitConnector = new KisAcyclicSignalConnector(this);
230 printUnitConnector->connectForwardInt(
231 m_page->printWidthUnit, SIGNAL(currentIndexChanged(int)),
232 m_printSizeUnitManager, SLOT(selectApparentUnitFromIndex(int)));
233
234 printUnitConnector->connectBackwardInt(
235 m_printSizeUnitManager, SIGNAL(unitChanged(int)),
236 m_page->printWidthUnit, SLOT(setCurrentIndex(int)));
237
239 connect(m_page->printResolutionUnit, SIGNAL(currentIndexChanged(int)),
240 this, SLOT(slotPrintResolutionUnitChanged()));
241
245 KisAcyclicSignalConnector *syncConnector = new KisAcyclicSignalConnector(this);
246 syncConnector->connectForwardVoid(
247 m_pixelSizeLocker, SIGNAL(sliderValueChanged()),
248 this, SLOT(slotSyncPixelToPrintSize()));
249
250 syncConnector->connectBackwardVoid(
251 m_printSizeLocker, SIGNAL(sliderValueChanged()),
252 this, SLOT(slotSyncPrintToPixelSize()));
253
255 m_page->printResolution, SIGNAL(valueChanged(double)),
256 this, SLOT(slotPrintResolutionChanged()));
257
258
262 QString printSizeUnit;
263
264 if (QLocale().measurementSystem() == QLocale::MetricSystem) {
265 printSizeUnit = "cm";
266 } else { // Imperial
267 printSizeUnit = "in";
268 }
269
270 printSizeUnit = cfg.readEntry<QString>(PARAM_SIZE_UNIT, printSizeUnit);
271
273
274 setCurrentResolutionPPI(resolution);
276
282
283 QString printResUnit = cfg.readEntry<QString>(PARAM_RES_UNIT, "");
284 m_page->printResolutionUnit->setCurrentText(printResUnit);
285
286 m_page->constrainProportionsCkb->setChecked(cfg.readEntry<bool>(PARAM_RATIO_LOCK, true));
287 m_page->adjustPrintSizeSeparatelyCkb->setChecked(cfg.readEntry<bool>(PARAM_PRINT_SIZE_SEPARATE, false));
288
289 QHBoxLayout *l = new QHBoxLayout();
290 l->addWidget(m_page);
291 this->setLayout(l);
292
293 m_page->pixelWidthDouble->setFocus();
294}
295
297{
298 KisConfig cfg(false);
299 cfg.writeEntry<bool>(PARAM_PRINT_SIZE_SEPARATE, m_page->adjustPrintSizeSeparatelyCkb->isChecked());
300 cfg.writeEntry<bool>(PARAM_RATIO_LOCK, m_page->constrainProportionsCkb->isChecked());
301
304 cfg.writeEntry<QString>(PARAM_RES_UNIT, m_page->printResolutionUnit->currentText());
305
306 delete m_page;
307}
308
310{
311 return qRound(m_page->pixelWidthDouble->value());
312}
313
315{
316 return qRound(m_page->pixelHeightDouble->value());
317}
318
323
325{
326 KoID filterID = m_page->pixelFilterCmb->currentItem();
327
328 KisFilterStrategy *filter;
329 if (filterID == KisCmbIDList::AutoOptionID) {
331 } else {
332 filter = KisFilterStrategyRegistry::instance()->value(filterID.id());
333 lastUsedFilter = filter; // Save for next time!
334 }
335
336 return filter;
337}
338
340{
341 const bool printIsSeparate = m_page->adjustPrintSizeSeparatelyCkb->isChecked();
342
343 if (!printIsSeparate) {
344 KisSignalsBlocker b(m_page->pixelWidthDouble, m_page->pixelHeightDouble);
345 m_page->pixelWidthDouble->changeValue(m_page->printWidth->value() * currentResolutionPPI());
346 m_page->pixelHeightDouble->changeValue(m_page->printHeight->value() * currentResolutionPPI());
347 } else if (m_page->pixelWidthDouble->value() != 0.0) {
348 const qreal resolution = qMax(0.001, m_page->pixelWidthDouble->value() / m_page->printWidth->value());
349 setCurrentResolutionPPI(resolution);
350 }
351}
352
354{
355 const qreal resolution = currentResolutionPPI();
356 if (resolution != 0.0) {
357 KisSignalsBlocker b(m_page->printWidth, m_page->printHeight);
358 m_page->printWidth->changeValue(m_page->pixelWidthDouble->value() / resolution);
359 m_page->printHeight->changeValue(m_page->pixelHeightDouble->value() / resolution);
360 }
361}
362
364{
365 const bool printIsSeparate = m_page->adjustPrintSizeSeparatelyCkb->isChecked();
366
367 if (printIsSeparate) {
369 } else {
371 }
372
374}
375
377{
378 qreal resolution = m_page->printResolution->value();
379
380 if (m_page->printResolutionUnit->currentText() == pixelsInchStr()) {
382 } else {
384 }
385
386 {
387 KisSignalsBlocker b(m_page->printResolution);
388 m_page->printResolution->setValue(resolution);
389 }
390}
391
393{
394 const bool printIsSeparate = m_page->adjustPrintSizeSeparatelyCkb->isChecked();
395
396 if (!printIsSeparate) {
397 m_page->printAspectRatioBtn->setKeepAspectRatio(value);
398 }
399 m_page->constrainProportionsCkb->setChecked(value);
400}
401
403{
404 m_page->pixelAspectRatioBtn->setKeepAspectRatio(value);
405 m_page->constrainProportionsCkb->setChecked(value);
406}
407
409{
410 const bool printIsSeparate = m_page->adjustPrintSizeSeparatelyCkb->isChecked();
411
412 m_page->pixelAspectRatioBtn->setKeepAspectRatio(value);
413
414 if (!printIsSeparate) {
415 m_page->printAspectRatioBtn->setKeepAspectRatio(value);
416 }
417}
418
420{
421 m_page->printAspectRatioBtn->setEnabled(!value);
422 m_page->printAspectRatioBtn->setKeepAspectRatio(!value ? m_page->constrainProportionsCkb->isChecked() : true);
423}
424
426{
427 qreal resolution = m_page->printResolution->value();
428
429 if (m_page->printResolutionUnit->currentText() == pixelsInchStr()) {
431 } else {
433 }
434
435 return resolution;
436}
437
439{
440 qreal newValue = value;
441
442 if (m_page->printResolutionUnit->currentText() == pixelsInchStr()) {
444 } else {
446 }
447
448 {
449 KisSignalsBlocker b(m_page->printResolution);
450 m_page->printResolution->setValue(newValue);
451 }
452
454}
455
457{
458 const qreal value = currentResolutionPPI();
459 if (value == 0.0) return;
460
461 m_page->printWidth->setMaximum(maxImagePixelSize / value);
462 m_page->printHeight->setMaximum(maxImagePixelSize / value);
463}
464
465#include "wdg_imagesize.moc"
float value(const T *src, size_t ch)
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
void connectForwardBool(QObject *sender, const char *signal, QObject *receiver, const char *method)
KisAcyclicSignalConnector * createCoordinatedConnector()
create a coordinated connector that can be used for extending the number of self-locking connection.
void connectBackwardInt(QObject *sender, const char *signal, QObject *receiver, const char *method)
void connectBackwardVoid(QObject *sender, const char *signal, QObject *receiver, const char *method)
void connectBackwardBool(QObject *sender, const char *signal, QObject *receiver, const char *method)
void connectForwardInt(QObject *sender, const char *signal, QObject *receiver, const char *method)
void connectForwardVoid(QObject *sender, const char *signal, QObject *receiver, const char *method)
void connectSpinBoxes(SpinBoxType *spinOne, SpinBoxType *spinTwo, KoAspectButton *aspectButton)
static const KoID AutoOptionID
void writeEntry(const QString &name, const T &value)
Definition kis_config.h:779
T readEntry(const QString &name, const T &defaultValue=T())
Definition kis_config.h:789
The KisDocumentAwareSpinBoxUnitManager class is a KisSpinBoxUnitManager that is able to connect to th...
static KisFilterStrategyRegistry * instance()
KisFilterStrategy * autoFilterStrategy(QSize originalSize, QSize desiredSize) const
void addWidget(QWidget *widget)
The KisSpinBoxUnitManager class is an abstract interface for the unitspinboxes classes to manage diff...
void setApparentUnitFromSymbol(QString pSymbol)
void syncWithOtherUnitManager(KisSpinBoxUnitManager *other)
void setUnitDimension(UnitDimension dimension)
int getApparentUnitId() const
get the position of the apparent unit in the list of units. It is useful if we want to build a model ...
const T value(const QString &id) const
Definition KoID.h:30
QString id() const
Definition KoID.cpp:63
static qreal convertFromUnitToUnit(const qreal value, const KoUnit &fromUnit, const KoUnit &toUnit, qreal factor=1.0)
Definition KoUnit.cpp:295
@ Point
Postscript point, 1/72th of an Inco.
Definition KoUnit.h:76
@ Centimeter
Definition KoUnit.h:78
@ Inch
Definition KoUnit.h:77
PageImageSize(QWidget *parent)
void slotLockPixelRatioSwitched(bool value)
void slotLockPrintRatioSwitched(bool value)
KisAspectRatioLocker * m_printSizeLocker
void sigDesiredSizeChanged(qint32 width, qint32 height, double resolution)
PageImageSize * m_page
void slotPrintResolutionUnitChanged()
static const QString PARAM_PRINT_SIZE_SEPARATE
KisFilterStrategy * filterType()
static const QString PARAM_RES_UNIT
QSize m_originalSize
void slotSyncPrintToPixelSize()
qint32 desiredWidth()
~WdgImageSize() override
double desiredResolution()
static const QString PARAM_PREFIX
KisDocumentAwareSpinBoxUnitManager * m_widthUnitManager
void slotAdjustSeparatelySwitched(bool value)
void updatePrintSizeMaximum()
void slotSyncPixelToPrintSize()
void slotPrintResolutionChanged()
qreal currentResolutionPPI() const
static const QString PARAM_IMSIZE_UNIT
KisAspectRatioLocker * m_pixelSizeLocker
KisSpinBoxUnitManager * m_printSizeUnitManager
void slotLockAllRatioSwitched(bool value)
KisDocumentAwareSpinBoxUnitManager * m_heightUnitManager
void setCurrentResolutionPPI(qreal value)
static const QString PARAM_RATIO_LOCK
WdgImageSize(QWidget *parent, int width, int height, double resolution)
static const QString PARAM_SIZE_UNIT
qint32 desiredHeight()
static KisFilterStrategy * lastUsedFilter
static KisFilterStrategy * lastUsedFilter
static const QString pixelsCentimeterStr()
static const int maxImagePixelSize
static QString pixelsInchStr()