1 // Copyright (C) 2012-2019 The VPaint Developers.
2 // See the COPYRIGHT file at the top-level directory of this distribution
3 // and at https://github.com/dalboris/vpaint/blob/master/COPYRIGHT
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16
17 #include "ExportPngDialog.h"
18
19 #include "Scene.h"
20
21 #include <cmath>
22
23 #include <QDoubleSpinBox>
24 #include <QVBoxLayout>
25 #include <QDialogButtonBox>
26 #include <QFormLayout>
27 #include <QCheckBox>
28 #include <QLabel>
29
ExportPngDialog(Scene * scene)30 ExportPngDialog::ExportPngDialog(Scene * scene) :
31 scene_(scene),
32 ignoreSceneChanged_(false),
33 ignoreWidthHeightChanged_(false)
34 {
35 // Set window title
36 setWindowTitle(tr("Export as PNG"));
37
38 // Edit Canvas
39 QFormLayout * formLayoutCanvas = new QFormLayout();
40
41 leftSpinBox_ = new QDoubleSpinBox();
42 leftSpinBox_->setRange(-100000,100000);
43 formLayoutCanvas->addRow(tr("Left"), leftSpinBox_);
44
45 topSpinBox_ = new QDoubleSpinBox();
46 topSpinBox_->setRange(-100000,100000);
47 formLayoutCanvas->addRow(tr("Top"), topSpinBox_);
48
49 widthSpinBox_ = new QDoubleSpinBox();
50 widthSpinBox_->setRange(0,100000);
51 formLayoutCanvas->addRow(tr("Width"), widthSpinBox_);
52
53 heightSpinBox_ = new QDoubleSpinBox();
54 heightSpinBox_->setRange(0,100000);
55 formLayoutCanvas->addRow(tr("Height"), heightSpinBox_);
56
57 // PNG Export options
58 QFormLayout * formLayoutPng = new QFormLayout();
59
60 pngWidthSpinBox_ = new QSpinBox();
61 pngWidthSpinBox_->setRange(1,100000);
62 pngWidthSpinBox_->setValue(1280);
63 formLayoutPng->addRow(tr("PNG Width"), pngWidthSpinBox_);
64
65 pngHeightSpinBox_ = new QSpinBox();
66 pngHeightSpinBox_->setRange(1,100000);
67 pngHeightSpinBox_->setValue(720);
68 formLayoutPng->addRow(tr("PNG Height"), pngHeightSpinBox_);
69
70 preserveAspectRatioCheckBox_ = new QCheckBox();
71 preserveAspectRatioCheckBox_->setChecked(true);
72 formLayoutPng->addRow(tr("Preserve Aspect Ratio"), preserveAspectRatioCheckBox_);
73
74 exportSequenceCheckBox_ = new QCheckBox();
75 exportSequenceCheckBox_->setChecked(false);
76 formLayoutPng->addRow(tr("Export Sequence"), exportSequenceCheckBox_);
77
78 useViewSettings_ = new QCheckBox();
79 useViewSettings_->setChecked(false);
80 formLayoutPng->addRow(tr("Use View Settings"), useViewSettings_);
81
82 // Export/Cancel dialog buttons
83 QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel);
84 buttonBox->addButton(tr("Export"), QDialogButtonBox::AcceptRole);
85
86 // Main layout
87 QVBoxLayout * layout = new QVBoxLayout();
88 //layout->addWidget(new QLabel(tr("<b>Canvas Size</b>")));
89 //layout->addLayout(formLayoutCanvas);
90 //layout->addWidget(new QLabel(tr("<b>PNG Export Options</b>")));
91 layout->addLayout(formLayoutPng);
92 layout->addStretch();
93 layout->addWidget(buttonBox);
94 setLayout(layout);
95
96 // Set initial widget values
97 updateDialogFromScene();
98
99 // Store initial values to allow Cancel
100 backupCurrentCanvasSize_();
101
102 // Create connections
103 connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
104 connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
105
106 connect(scene_, SIGNAL(changed()), this, SLOT(updateDialogFromScene()));
107
108 connect(topSpinBox_, SIGNAL(valueChanged(double)), this, SLOT(processCanvasSizeChanged_()));
109 connect(leftSpinBox_, SIGNAL(valueChanged(double)), this, SLOT(processCanvasSizeChanged_()));
110 connect(widthSpinBox_, SIGNAL(valueChanged(double)), this, SLOT(processCanvasSizeChanged_()));
111 connect(heightSpinBox_, SIGNAL(valueChanged(double)), this, SLOT(processCanvasSizeChanged_()));
112
113 connect(pngWidthSpinBox_, SIGNAL(valueChanged(int)), this, SLOT(processPngWidthChanged_(int)));
114 connect(pngHeightSpinBox_, SIGNAL(valueChanged(int)), this, SLOT(processPngHeightChanged_(int)));
115 connect(preserveAspectRatioCheckBox_, SIGNAL(toggled(bool)), this, SLOT(processPreserveAspectRatioChanged_(bool)));
116 }
117
left() const118 double ExportPngDialog::left() const
119 {
120 return leftSpinBox_->value();
121 }
122
top() const123 double ExportPngDialog::top() const
124 {
125 return topSpinBox_->value();
126 }
127
width() const128 double ExportPngDialog::width() const
129 {
130 return widthSpinBox_->value();
131 }
132
height() const133 double ExportPngDialog::height() const
134 {
135 return heightSpinBox_->value();
136 }
137
pngWidth() const138 int ExportPngDialog::pngWidth() const
139 {
140 return pngWidthSpinBox_->value();
141 }
142
pngHeight() const143 int ExportPngDialog::pngHeight() const
144 {
145 return pngHeightSpinBox_->value();
146 }
147
preserveAspectRatio() const148 bool ExportPngDialog::preserveAspectRatio() const
149 {
150 return preserveAspectRatioCheckBox_->isChecked();
151 }
152
exportSequence() const153 bool ExportPngDialog::exportSequence() const
154 {
155 return exportSequenceCheckBox_->isChecked();
156 }
157
useViewSettings() const158 bool ExportPngDialog::useViewSettings() const
159 {
160 return useViewSettings_->isChecked();
161 }
162
setPngWidthForHeight_()163 void ExportPngDialog::setPngWidthForHeight_()
164 {
165 ignoreWidthHeightChanged_ = true; // prevent infinite recursion with pngWidthChanged()
166 if(height() > 0)
167 pngWidthSpinBox_->setValue(floor(0.5+width() * pngHeight() / height()));
168 ignoreWidthHeightChanged_ = false;
169 }
170
setPngHeightForWidth_()171 void ExportPngDialog::setPngHeightForWidth_()
172 {
173 ignoreWidthHeightChanged_ = true; // prevent infinite recursion with pngHeightChanged()
174 if(width() > 0)
175 pngHeightSpinBox_->setValue(floor(0.5+height() * pngWidth() / width()));
176 ignoreWidthHeightChanged_ = false;
177 }
178
enforcePngAspectRatio_()179 void ExportPngDialog::enforcePngAspectRatio_()
180 {
181 if(preserveAspectRatio())
182 {
183 if(width() > height())
184 setPngHeightForWidth_();
185 else
186 setPngWidthForHeight_();
187 }
188
189 }
190
processPngWidthChanged_(int)191 void ExportPngDialog::processPngWidthChanged_(int )
192 {
193 if(!ignoreWidthHeightChanged_ && preserveAspectRatio())
194 {
195 setPngHeightForWidth_();
196 }
197 }
198
processPngHeightChanged_(int)199 void ExportPngDialog::processPngHeightChanged_(int )
200 {
201 if(!ignoreWidthHeightChanged_ && preserveAspectRatio())
202 {
203 setPngWidthForHeight_();
204 }
205 }
206
processPreserveAspectRatioChanged_(bool)207 void ExportPngDialog::processPreserveAspectRatioChanged_(bool )
208 {
209 enforcePngAspectRatio_();
210 }
211
backupCurrentCanvasSize_()212 void ExportPngDialog::backupCurrentCanvasSize_()
213 {
214 oldTop_ = scene_->top();
215 oldLeft_ = scene_->left();
216 oldWidth_ = scene_->width();
217 oldHeight_ = scene_->height();
218 }
219
setVisible(bool visible)220 void ExportPngDialog::setVisible(bool visible)
221 {
222 if(visible)
223 {
224 backupCurrentCanvasSize_();
225 enforcePngAspectRatio_();
226 }
227
228 QDialog::setVisible(visible);
229 }
230
scene() const231 Scene * ExportPngDialog::scene() const
232 {
233 return scene_;
234 }
235
accept()236 void ExportPngDialog::accept()
237 {
238 QDialog::accept();
239 }
240
reject()241 void ExportPngDialog::reject()
242 {
243 scene_->setTop(oldTop_);
244 scene_->setLeft(oldLeft_);
245 scene_->setWidth(oldWidth_);
246 scene_->setHeight(oldHeight_);
247
248 QDialog::reject();
249 }
250
processCanvasSizeChanged_()251 void ExportPngDialog::processCanvasSizeChanged_()
252 {
253 enforcePngAspectRatio_();
254 updateSceneFromDialog();
255 }
256
updateDialogFromScene()257 void ExportPngDialog::updateDialogFromScene()
258 {
259 if(!ignoreSceneChanged_)
260 {
261 topSpinBox_->setValue(scene()->top());
262 leftSpinBox_->setValue(scene()->left());
263 widthSpinBox_->setValue(scene()->width());
264 heightSpinBox_->setValue(scene()->height());
265 }
266 }
267
updateSceneFromDialog()268 void ExportPngDialog::updateSceneFromDialog()
269 {
270 ignoreSceneChanged_ = true;
271
272 scene()->setTop(topSpinBox_->value());
273 scene()->setLeft(leftSpinBox_->value());
274 scene()->setWidth(widthSpinBox_->value());
275 scene()->setHeight(heightSpinBox_->value());
276
277 ignoreSceneChanged_ = false;
278 }
279