Krita Source Code Documentation
Loading...
Searching...
No Matches
dlg_canvassize.cc
Go to the documentation of this file.
1/*
2 *
3 * SPDX-FileCopyrightText: 2009 Edward Apap <schumifer@hotmail.com>
4 * SPDX-FileCopyrightText: 2013 Juan Palacios <jpalaciosdev@gmail.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#include "dlg_canvassize.h"
10#include "kcanvaspreview.h"
11
12#include <kis_config.h>
13#include <KoUnit.h>
14#include <kis_icon.h>
15#include <kis_size_group.h>
16#include <klocalizedstring.h>
17
19
20#include <QButtonGroup>
21
22const QString DlgCanvasSize::PARAM_PREFIX = "canvasizedlg";
27
28DlgCanvasSize::DlgCanvasSize(QWidget *parent, int width, int height, double resolution)
29 : KoDialog(parent)
30 , m_keepAspect(true)
31 , m_aspectRatio((double)width / height)
32 , m_resolution(resolution)
33 , m_originalWidth(width)
34 , m_originalHeight(height)
35 , m_newWidth(width)
36 , m_newHeight(height)
37 , m_xOffset(0)
38 , m_yOffset(0)
39{
40 setCaption(i18n("Resize Canvas"));
43
44 m_page = new WdgCanvasSize(this);
45 Q_CHECK_PTR(m_page);
46 m_page->layout()->setContentsMargins(0, 0, 0, 0);
47 m_page->setObjectName("canvas_size");
48
51
52 KisConfig cfg(true);
53
56
57 m_page->newWidthDouble->setUnitManager(_widthUnitManager);
58 m_page->newHeightDouble->setUnitManager(_heightUnitManager);
59 m_page->newWidthDouble->setDisplayUnit(false);
60 m_page->newHeightDouble->setDisplayUnit(false);
61
62 m_page->newWidthDouble->setValue(width);
63 m_page->newWidthDouble->setFocus();
64 m_page->newHeightDouble->setValue(height);
65
66 m_page->widthUnit->setModel(_widthUnitManager);
67 m_page->heightUnit->setModel(_heightUnitManager);
68
69 QString unitw = cfg.readEntry<QString>(PARAM_WIDTH_UNIT, "px");
70 QString unith = cfg.readEntry<QString>(PARAM_HEIGHT_UNIT, "px");
71
74
75 const int wUnitIndex = _widthUnitManager->getsUnitSymbolList().indexOf(unitw);
76 const int hUnitIndex = _widthUnitManager->getsUnitSymbolList().indexOf(unith);
77
78 m_page->widthUnit->setCurrentIndex(wUnitIndex);
79 m_page->heightUnit->setCurrentIndex(hUnitIndex);
80
83
86
87 m_page->xOffsetDouble->setUnitManager(_xOffsetUnitManager);
88 m_page->yOffsetDouble->setUnitManager(_yOffsetUnitManager);
89 m_page->xOffsetDouble->setDisplayUnit(false);
90 m_page->yOffsetDouble->setDisplayUnit(false);
91
92 m_page->xOffUnit->setModel(_xOffsetUnitManager);
93 m_page->yOffUnit->setModel(_yOffsetUnitManager);
94
95 m_page->xOffsetDouble->changeValue(m_xOffset);
96 m_page->yOffsetDouble->changeValue(m_yOffset);
97
98 QString unitx = cfg.readEntry<QString>(PARAM_XOFFSET_UNIT, "px");
99 QString unity = cfg.readEntry<QString>(PARAM_YOFFSET_UNIT, "px");
100
103
104 const int xUnitIndex = _xOffsetUnitManager->getsUnitSymbolList().indexOf(unitx);
105 const int yUnitIndex = _yOffsetUnitManager->getsUnitSymbolList().indexOf(unity);
106
107 m_page->xOffUnit->setCurrentIndex(xUnitIndex);
108 m_page->yOffUnit->setCurrentIndex(yUnitIndex);
109
110 QIcon lockedIcon = KisIconUtils::loadIcon("locked");
111 QIcon unlockedIcon = KisIconUtils::loadIcon("unlocked");
112 m_page->lockxOffset->setCheckable(true);
113 m_page->lockyOffset->setCheckable(true);
114 m_page->lockxOffset->setChecked(false);
115 m_page->lockyOffset->setChecked(false);
116 m_page->lockxOffset-> setIcon(m_page->lockxOffset->isChecked() ? lockedIcon : unlockedIcon);
117 m_page->lockyOffset-> setIcon(m_page->lockyOffset->isChecked() ? lockedIcon : unlockedIcon);
118
119 m_page->canvasPreview->setImageSize(m_originalWidth, m_originalHeight);
120 m_page->canvasPreview->setCanvasSize(m_originalWidth, m_originalHeight);
121 m_page->canvasPreview->setImageOffset(m_xOffset, m_yOffset);
122
123 m_page->aspectRatioBtn->setKeepAspectRatio(cfg.readEntry("CanvasSize/KeepAspectRatio", false));
124 m_page->constrainProportionsCkb->setChecked(cfg.readEntry("CanvasSize/ConstrainProportions", false));
125 m_keepAspect = cfg.readEntry("CanvasSize/KeepAspectRatio", false);
126
127
128 m_group = new QButtonGroup(m_page);
129 m_group->addButton(m_page->topLeft, NORTH_WEST);
130 m_group->addButton(m_page->topCenter, NORTH);
131 m_group->addButton(m_page->topRight, NORTH_EAST);
132
133 m_group->addButton(m_page->middleLeft, WEST);
134 m_group->addButton(m_page->middleCenter, CENTER);
135 m_group->addButton(m_page->middleRight, EAST);
136
137 m_group->addButton(m_page->bottomLeft, SOUTH_WEST);
138 m_group->addButton(m_page->bottomCenter, SOUTH);
139 m_group->addButton(m_page->bottomRight, SOUTH_EAST);
140
142 m_group->button(CENTER)->setChecked(true);
144
145 KisSizeGroup *labelsGroup = new KisSizeGroup(this);
146 labelsGroup->addWidget(m_page->lblNewWidth);
147 labelsGroup->addWidget(m_page->lblNewHeight);
148 labelsGroup->addWidget(m_page->lblXOff);
149 labelsGroup->addWidget(m_page->lblYOff);
150 labelsGroup->addWidget(m_page->lblAnchor);
151
152 KisSizeGroup *spinboxesGroup = new KisSizeGroup(this);
153 spinboxesGroup->addWidget(m_page->newWidthDouble);
154 spinboxesGroup->addWidget(m_page->newHeightDouble);
155 spinboxesGroup->addWidget(m_page->xOffsetDouble);
156 spinboxesGroup->addWidget(m_page->yOffsetDouble);
157
158 KisSizeGroup *comboboxesGroup = new KisSizeGroup(this);
159 comboboxesGroup->addWidget(m_page->widthUnit);
160 comboboxesGroup->addWidget(m_page->heightUnit);
161 comboboxesGroup->addWidget(m_page->xOffUnit);
162 comboboxesGroup->addWidget(m_page->yOffUnit);
163
165 connect(this, SIGNAL(okClicked()), this, SLOT(accept()));
166
167 connect(m_page->newWidthDouble, SIGNAL(valueChangedPt(double)), this, SLOT(slotWidthChanged(double)));
168 connect(m_page->newHeightDouble, SIGNAL(valueChangedPt(double)), this, SLOT(slotHeightChanged(double)));
169 connect(m_page->widthUnit, SIGNAL(currentIndexChanged(int)), _widthUnitManager, SLOT(selectApparentUnitFromIndex(int)));
170 connect(m_page->heightUnit, SIGNAL(currentIndexChanged(int)), _heightUnitManager, SLOT(selectApparentUnitFromIndex(int)));
171 connect(_widthUnitManager, SIGNAL(unitChanged(int)), m_page->widthUnit, SLOT(setCurrentIndex(int)));
172 connect(_heightUnitManager, SIGNAL(unitChanged(int)), m_page->heightUnit, SLOT(setCurrentIndex(int)));
173
174 connect(m_page->xOffsetDouble, SIGNAL(valueChangedPt(double)), this, SLOT(slotXOffsetChanged(double)));
175 connect(m_page->yOffsetDouble, SIGNAL(valueChangedPt(double)), this, SLOT(slotYOffsetChanged(double)));
176 connect(m_page->xOffUnit, SIGNAL(currentIndexChanged(int)), _xOffsetUnitManager, SLOT(selectApparentUnitFromIndex(int)));
177 connect(m_page->yOffUnit, SIGNAL(currentIndexChanged(int)), _yOffsetUnitManager, SLOT(selectApparentUnitFromIndex(int)));
178 connect(_xOffsetUnitManager, SIGNAL(unitChanged(int)), m_page->xOffUnit, SLOT(setCurrentIndex(int)));
179 connect(_yOffsetUnitManager, SIGNAL(unitChanged(int)), m_page->yOffUnit, SLOT(setCurrentIndex(int)));
180
181 connect(m_page->lockxOffset, SIGNAL(toggled(bool)), this, SLOT(updatexOffsetIcon(bool)));
182 connect(m_page->lockyOffset, SIGNAL(toggled(bool)), this, SLOT(updateyOffsetIcon(bool)));
183 connect(m_page->lockxOffset, SIGNAL(toggled(bool)), m_page->canvasPreview , SLOT(setxOffsetLock(bool)));
184 connect(m_page->lockyOffset, SIGNAL(toggled(bool)), m_page->canvasPreview , SLOT(setyOffsetLock(bool)));
185
186 connect(m_page->constrainProportionsCkb, SIGNAL(toggled(bool)), this, SLOT(slotAspectChanged(bool)));
187 connect(m_page->aspectRatioBtn, SIGNAL(keepAspectRatioChanged(bool)), this, SLOT(slotAspectChanged(bool)));
188
189 connect(m_group, SIGNAL(idClicked(int)), SLOT(slotAnchorButtonClicked(int)));
190 connect(m_page->canvasPreview, SIGNAL(sigModifiedXOffset(int)), this, SLOT(slotCanvasPreviewXOffsetChanged(int)));
191 connect(m_page->canvasPreview, SIGNAL(sigModifiedYOffset(int)), this, SLOT(slotCanvasPreviewYOffsetChanged(int)));
192}
193
195{
196 KisConfig cfg(false);
197 cfg.writeEntry<bool>("CanvasSize/KeepAspectRatio", m_page->aspectRatioBtn->keepAspectRatio());
198 cfg.writeEntry<bool>("CanvasSize/ConstrainProportions", m_page->constrainProportionsCkb->isChecked());
199
202
205
206 delete m_page;
207}
208
210{
211 return (qint32) m_newWidth;
212}
213
215{
216 return (qint32) m_newHeight;
217}
218
220{
221 return (qint32) m_xOffset;
222}
223
225{
226 return (qint32) m_yOffset;
227}
228
230{
231 m_page->aspectRatioBtn->blockSignals(true);
232 m_page->constrainProportionsCkb->blockSignals(true);
233
234 m_page->aspectRatioBtn->setKeepAspectRatio(keep);
235 m_page->constrainProportionsCkb->setChecked(keep);
236
237 m_page->aspectRatioBtn->blockSignals(false);
238 m_page->constrainProportionsCkb->blockSignals(false);
239
240 m_keepAspect = keep;
241
242
243 if (keep) {
244 // size values may be out of sync, so we need to reset it to defaults
245 m_xOffset = 0;
246 m_yOffset = 0;
247
248 m_page->canvasPreview->blockSignals(true);
249 m_page->canvasPreview->setCanvasSize(m_newWidth, m_newHeight);
250 m_page->newWidthDouble->setValue(m_newWidth);
251 m_page->newHeightDouble->setValue(m_newHeight);
252 m_page->canvasPreview->setImageOffset(m_xOffset, m_yOffset);
253 m_page->canvasPreview->blockSignals(false);
256
257 }
258}
259
265
267{
268 //this slot receives values in pt from the unitspinbox, so just use the resolution.
270 m_newWidth = qRound(resValue);
271
272 if (m_keepAspect) {
274 m_page->newHeightDouble->blockSignals(true);
275 m_page->newHeightDouble->changeValue(v / m_aspectRatio);
276 m_page->newHeightDouble->blockSignals(false);
277 }
278
279 int savedId = m_group->checkedId();
280 m_page->canvasPreview->blockSignals(true);
281 m_page->canvasPreview->setCanvasSize(m_newWidth, m_newHeight);
282 m_page->canvasPreview->blockSignals(false);
283 updateOffset(savedId);
284 updateButtons(savedId);
285}
286
288{
289 //this slot receives values in pt from the unitspinbox, so just use the resolution.
291 m_newHeight = qRound(resValue);
292
293 if (m_keepAspect) {
295 m_page->newWidthDouble->blockSignals(true);
296 m_page->newWidthDouble->changeValue(v * m_aspectRatio);
297 m_page->newWidthDouble->blockSignals(false);
298 }
299
300 int savedId = m_group->checkedId();
301 m_page->canvasPreview->blockSignals(true);
302 m_page->canvasPreview->setCanvasSize(m_newWidth, m_newHeight);
303 m_page->canvasPreview->blockSignals(false);
304 updateOffset(savedId);
305 updateButtons(savedId);
306}
307
309{
310 //this slot receives values in pt from the unitspinbox, so just use the resolution.
312 m_xOffset = qRound(resValue);
313
314 m_page->canvasPreview->blockSignals(true);
315 m_page->canvasPreview->setImageOffset(m_xOffset, m_yOffset);
316 m_page->canvasPreview->blockSignals(false);
317
318 updateButtons(-1);
319}
320
322{
323 //this slot receives values in pt from the unitspinbox, so just use the resolution.
325 m_yOffset = qRound(resValue);
326
327
328 m_page->canvasPreview->blockSignals(true);
329 m_page->canvasPreview->setImageOffset(m_xOffset, m_yOffset);
330 m_page->canvasPreview->blockSignals(false);
331
332 updateButtons(-1);
333}
334
336{
338 m_page->xOffsetDouble->changeValue(newVal);
339}
340
342{
343
345 m_page->yOffsetDouble->changeValue(newVal);
346}
347
362
364{
365 anchor iconLayout[10][9] = {
376 };
377
378 if (id == -1) {
379 id = SOUTH_EAST + 1;
380 }
381
382 // we are going to swap arrows direction based on width and height shrinking
383 bool shrinkWidth = (m_newWidth < m_originalWidth) ? true : false;
384 bool shrinkHeight = (m_newHeight < m_originalHeight) ? true : false;
385
386 for (int i = NORTH_WEST; i <= SOUTH_EAST; i++) {
387 anchor iconId = iconLayout[id][i];
388
389 // all corner arrows represents shrinking in some direction
390 if (shrinkWidth || shrinkHeight) {
391 switch (iconId) {
392 case NORTH_WEST: iconId = SOUTH_EAST; break;
393 case NORTH_EAST: iconId = SOUTH_WEST; break;
394 case SOUTH_WEST: iconId = NORTH_EAST; break;
395 case SOUTH_EAST: iconId = NORTH_WEST; break;
396 default: break;
397 }
398 }
399
400 if (shrinkWidth) {
401 switch (iconId) {
402 case WEST: iconId = EAST; break;
403 case EAST: iconId = WEST; break;
404 default: break;
405 }
406 }
407
408 if (shrinkHeight) {
409 switch (iconId) {
410 case NORTH: iconId = SOUTH; break;
411 case SOUTH: iconId = NORTH; break;
412 default: break;
413 }
414 }
415
416 QAbstractButton *button = m_group->button(i);
417
418 if (iconId == NONE) {
419 button->setIcon(QIcon());
420 } else {
421 button->setIcon(m_anchorIcons[iconId]);
422 }
423 }
424
425}
426
428{
429 int id = m_group->checkedId();
430
431 if (forceId != -1) {
432 m_group->setExclusive(true);
433 m_group->button(forceId)->setChecked(true);
434 updateAnchorIcons(forceId);
435 } else if (id != -1) {
436 double xOffset, yOffset;
438
439 // convert values to internal unit
440 int internalXOffset = 0;
441 int internalYOffset = 0;
442 const KoUnit xOffsetUnit = KoUnit::fromListForUi(m_page->xOffUnit->currentIndex());
443 internalXOffset = qRound(xOffsetUnit.fromUserValue(xOffset));
444 const KoUnit yOffsetUnit = KoUnit::fromListForUi(m_page->yOffUnit->currentIndex());
445 internalYOffset = qRound(yOffsetUnit.fromUserValue(yOffset));
446
447 bool offsetAsExpected =
448 internalXOffset == m_xOffset &&
449 internalYOffset == m_yOffset;
450
451 if (offsetAsExpected) {
452 m_group->setExclusive(true);
453 } else {
454 m_group->setExclusive(false);
455 m_group->button(id)->setChecked(false);
456 id = -1;
457 }
458
460 } else {
462 }
463}
464
466{
467 if (id == -1) return;
468
469 double xOffset;
470 double yOffset;
472
473 m_page->xOffsetDouble->changeValue(xOffset);
474 m_page->yOffsetDouble->changeValue(yOffset);
475}
477{
478 if (v) {
479 m_page->xOffsetDouble->setReadOnly(true);
480 m_page->lockxOffset->setIcon(KisIconUtils::loadIcon("locked"));
481 } else {
482 m_page->xOffsetDouble->setReadOnly(false);
483 m_page->lockxOffset->setIcon(KisIconUtils::loadIcon("unlocked"));
484 }
485}
487{
488 if (v) {
489 m_page->yOffsetDouble->setReadOnly(true);
490 m_page->lockyOffset->setIcon(KisIconUtils::loadIcon("locked"));
491 } else {
492 m_page->yOffsetDouble->setReadOnly(false);
493 m_page->lockyOffset->setIcon(KisIconUtils::loadIcon("unlocked"));
494 }
495}
496void DlgCanvasSize::expectedOffset(int id, double &xOffset, double &yOffset)
497{
498 const double xCoeff = (id % 3) * 0.5;
499 const double yCoeff = (int)(id / 3.0) * 0.5;
500
501 const int xDiff = m_newWidth - m_originalWidth;
502 const int yDiff = m_newHeight - m_originalHeight;
503
504 //convert to unitmanager default unit.
507}
qreal v
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
KisDocumentAwareSpinBoxUnitManager * _xOffsetUnitManager
void slotHeightChanged(double v)
static const QString PARAM_YOFFSET_UNIT
void updatexOffsetIcon(bool v)
void slotCanvasPreviewXOffsetChanged(int v)
const int m_originalWidth
static const QString PARAM_PREFIX
KisDocumentAwareSpinBoxUnitManager * _widthUnitManager
void updateyOffsetIcon(bool v)
QButtonGroup * m_group
static const QString PARAM_HEIGHT_UNIT
~DlgCanvasSize() override
WdgCanvasSize * m_page
void updateAnchorIcons(int id)
void slotYOffsetChanged(double v)
void expectedOffset(int id, double &xOffset, double &yOffset)
const int m_originalHeight
static const QString PARAM_XOFFSET_UNIT
void updateOffset(int id)
KisDocumentAwareSpinBoxUnitManager * _yOffsetUnitManager
const double m_aspectRatio
void slotCanvasPreviewYOffsetChanged(int v)
void slotAspectChanged(bool keep)
DlgCanvasSize(QWidget *parent, int width, int height, double resolution)
KisDocumentAwareSpinBoxUnitManager * _heightUnitManager
QIcon m_anchorIcons[9]
void slotWidthChanged(double v)
static const QString PARAM_WIDTH_UNIT
void updateButtons(int forceId)
void slotAnchorButtonClicked(int)
void slotXOffsetChanged(double v)
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...
qreal getConversionFactor(int dim, QString psymbol) const override
void addWidget(QWidget *widget)
void setApparentUnitFromSymbol(QString pSymbol)
virtual QStringList getsUnitSymbolList(bool withName=false) const
A dialog base class with standard buttons and predefined layouts.
Definition KoDialog.h:116
QPushButton * button(ButtonCode id) const
Definition KoDialog.cpp:591
void setMainWidget(QWidget *widget)
Definition KoDialog.cpp:354
virtual void setCaption(const QString &caption)
Definition KoDialog.cpp:498
void setButtons(ButtonCodes buttonMask)
Definition KoDialog.cpp:195
void setDefaultButton(ButtonCode id)
Definition KoDialog.cpp:302
@ Ok
Show Ok button. (this button accept()s the dialog; result set to QDialog::Accepted)
Definition KoDialog.h:127
@ Cancel
Show Cancel-button. (this button reject()s the dialog; result set to QDialog::Rejected)
Definition KoDialog.h:130
void okClicked()
qreal fromUserValue(qreal value) const
Definition KoUnit.cpp:201
static KoUnit fromListForUi(int index, ListOptions listOptions=ListAll, qreal factor=1.0)
Definition KoUnit.cpp:80
QIcon loadIcon(const QString &name)