1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2005-02-17
7 * Description : a tool to change image perspective .
8 *
9 * Copyright (C) 2005-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
10 * Copyright (C) 2006-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
11 *
12 * This program is free software; you can redistribute it
13 * and/or modify it under the terms of the GNU General
14 * Public License as published by the Free Software Foundation;
15 * either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * ============================================================ */
24
25 #include "perspectivetool.h"
26
27 // Qt includes
28
29 #include <QCheckBox>
30 #include <QFrame>
31 #include <QGridLayout>
32 #include <QGroupBox>
33 #include <QLabel>
34 #include <QPushButton>
35 #include <QSpinBox>
36 #include <QVBoxLayout>
37 #include <QApplication>
38
39 // KDE includes
40
41 #include <klocalizedstring.h>
42 #include <ksharedconfig.h>
43 #include <kconfiggroup.h>
44
45 // Local includes
46
47 #include "dimg.h"
48 #include "editortoolsettings.h"
49 #include "imageiface.h"
50 #include "perspectivewidget.h"
51 #include "dexpanderbox.h"
52
53 namespace DigikamEditorPerspectiveToolPlugin
54 {
55
56 class Q_DECL_HIDDEN PerspectiveTool::Private
57 {
58 public:
59
Private()60 explicit Private()
61 : newWidthLabel (nullptr),
62 newHeightLabel (nullptr),
63 topLeftAngleLabel (nullptr),
64 topRightAngleLabel (nullptr),
65 bottomLeftAngleLabel (nullptr),
66 bottomRightAngleLabel (nullptr),
67 drawWhileMovingCheckBox (nullptr),
68 drawGridCheckBox (nullptr),
69 inverseTransformation (nullptr),
70 previewWidget (nullptr),
71 gboxSettings (nullptr)
72 {
73 }
74
75 static const QString configGroupName;
76 static const QString configDrawWhileMovingEntry;
77 static const QString configDrawGridEntry;
78 static const QString configInverseTransformationEntry;
79
80 QLabel* newWidthLabel;
81 QLabel* newHeightLabel;
82 QLabel* topLeftAngleLabel;
83 QLabel* topRightAngleLabel;
84 QLabel* bottomLeftAngleLabel;
85 QLabel* bottomRightAngleLabel;
86
87 QCheckBox* drawWhileMovingCheckBox;
88 QCheckBox* drawGridCheckBox;
89 QCheckBox* inverseTransformation;
90
91 PerspectiveWidget* previewWidget;
92 EditorToolSettings* gboxSettings;
93 };
94
95 const QString PerspectiveTool::Private::configGroupName(QLatin1String("perspective Tool"));
96 const QString PerspectiveTool::Private::configDrawWhileMovingEntry(QLatin1String("Draw While Moving"));
97 const QString PerspectiveTool::Private::configDrawGridEntry(QLatin1String("Draw Grid"));
98 const QString PerspectiveTool::Private::configInverseTransformationEntry(QLatin1String("Inverse Transformation"));
99
100 // --------------------------------------------------------
101
PerspectiveTool(QObject * const parent)102 PerspectiveTool::PerspectiveTool(QObject* const parent)
103 : EditorTool(parent),
104 d (new Private)
105 {
106 setObjectName(QLatin1String("perspective"));
107
108 // -------------------------------------------------------------
109
110 QFrame* const frame = new QFrame(nullptr);
111 frame->setFrameStyle(QFrame::Panel|QFrame::Sunken);
112 QVBoxLayout* const l = new QVBoxLayout(frame);
113 d->previewWidget = new PerspectiveWidget(525, 350, frame);
114 l->addWidget(d->previewWidget);
115 d->previewWidget->setWhatsThis(i18n("This is the perspective transformation operation preview. "
116 "You can use the mouse for dragging the corner to adjust the "
117 "perspective transformation area."));
118 setToolView(frame);
119
120 // -------------------------------------------------------------
121
122 QString temp;
123 ImageIface iface;
124
125 d->gboxSettings = new EditorToolSettings(nullptr);
126 d->gboxSettings->setTools(EditorToolSettings::ColorGuide);
127
128 // -------------------------------------------------------------
129
130 QLabel* const label1 = new QLabel(i18n("New width:"));
131 d->newWidthLabel = new QLabel(temp.setNum( iface.originalSize().width()) + i18n(" px"));
132 d->newWidthLabel->setAlignment( Qt::AlignBottom | Qt::AlignRight );
133
134 QLabel* const label2 = new QLabel(i18n("New height:"));
135 d->newHeightLabel = new QLabel(temp.setNum( iface.originalSize().height()) + i18n(" px"));
136 d->newHeightLabel->setAlignment( Qt::AlignBottom | Qt::AlignRight );
137
138 // -------------------------------------------------------------
139
140 DLineWidget* const line = new DLineWidget (Qt::Horizontal);
141 QLabel* const angleLabel = new QLabel(i18n("Angles (in degrees):"));
142 QLabel* const label3 = new QLabel(i18n(" Top left:"));
143 d->topLeftAngleLabel = new QLabel;
144 QLabel* const label4 = new QLabel(i18n(" Top right:"));
145 d->topRightAngleLabel = new QLabel;
146 QLabel* const label5 = new QLabel(i18n(" Bottom left:"));
147 d->bottomLeftAngleLabel = new QLabel;
148 QLabel* const label6 = new QLabel(i18n(" Bottom right:"));
149 d->bottomRightAngleLabel = new QLabel;
150
151 // -------------------------------------------------------------
152
153 DLineWidget* const line2 = new DLineWidget (Qt::Horizontal);
154 d->drawWhileMovingCheckBox = new QCheckBox(i18n("Draw preview while moving"));
155 d->drawGridCheckBox = new QCheckBox(i18n("Draw grid"));
156 d->inverseTransformation = new QCheckBox(i18n("Inverse transformation"));
157
158 // -------------------------------------------------------------
159
160 const int spacing = d->gboxSettings->spacingHint();
161
162 QGridLayout* const grid = new QGridLayout;
163 grid->addWidget(label1, 0, 0, 1, 1);
164 grid->addWidget(d->newWidthLabel, 0, 1, 1, 2);
165 grid->addWidget(label2, 1, 0, 1, 1);
166 grid->addWidget(d->newHeightLabel, 1, 1, 1, 2);
167 grid->addWidget(line, 2, 0, 1, 3);
168 grid->addWidget(angleLabel, 3, 0, 1, 3);
169 grid->addWidget(label3, 4, 0, 1, 1);
170 grid->addWidget(d->topLeftAngleLabel, 4, 1, 1, 2);
171 grid->addWidget(label4, 5, 0, 1, 1);
172 grid->addWidget(d->topRightAngleLabel, 5, 1, 1, 2);
173 grid->addWidget(label5, 6, 0, 1, 1);
174 grid->addWidget(d->bottomLeftAngleLabel, 6, 1, 1, 2);
175 grid->addWidget(label6, 7, 0, 1, 1);
176 grid->addWidget(d->bottomRightAngleLabel, 7, 1, 1, 2);
177 grid->addWidget(line2, 8, 0, 1, 3);
178 grid->addWidget(d->drawWhileMovingCheckBox, 9, 0, 1, 3);
179 grid->addWidget(d->drawGridCheckBox, 10, 0, 1, 3);
180 grid->addWidget(d->inverseTransformation, 11, 0, 1, 3);
181 grid->setColumnStretch(1, 10);
182 grid->setRowStretch(12, 10);
183 grid->setContentsMargins(spacing, spacing, spacing, spacing);
184 grid->setSpacing(spacing);
185 d->gboxSettings->plainPage()->setLayout(grid);
186
187 // -------------------------------------------------------------
188
189 setToolSettings(d->gboxSettings);
190
191 // -------------------------------------------------------------
192
193 connect(d->previewWidget, SIGNAL(signalPerspectiveChanged(QRect,float,float,float,float,bool)),
194 this, SLOT(slotUpdateInfo(QRect,float,float,float,float,bool)));
195
196 connect(d->drawWhileMovingCheckBox, SIGNAL(toggled(bool)),
197 d->previewWidget, SLOT(slotToggleDrawWhileMoving(bool)));
198
199 connect(d->drawGridCheckBox, SIGNAL(toggled(bool)),
200 d->previewWidget, SLOT(slotToggleDrawGrid(bool)));
201
202 connect(d->inverseTransformation, SIGNAL(toggled(bool)),
203 this, SLOT(slotInverseTransformationChanged(bool)));
204
205 connect(d->gboxSettings, SIGNAL(signalColorGuideChanged()),
206 this, SLOT(slotColorGuideChanged()));
207 }
208
~PerspectiveTool()209 PerspectiveTool::~PerspectiveTool()
210 {
211 delete d;
212 }
213
slotColorGuideChanged()214 void PerspectiveTool::slotColorGuideChanged()
215 {
216 d->previewWidget->slotChangeGuideColor(d->gboxSettings->guideColor());
217 d->previewWidget->slotChangeGuideSize(d->gboxSettings->guideSize());
218 }
219
readSettings()220 void PerspectiveTool::readSettings()
221 {
222 QColor defaultGuideColor(Qt::red);
223 KSharedConfig::Ptr config = KSharedConfig::openConfig();
224 KConfigGroup group = config->group(d->configGroupName);
225
226 d->drawWhileMovingCheckBox->setChecked(group.readEntry( d->configDrawWhileMovingEntry, true));
227 d->drawGridCheckBox->setChecked(group.readEntry( d->configDrawGridEntry, false));
228 d->inverseTransformation->setChecked(group.readEntry( d->configInverseTransformationEntry, false));
229
230 d->previewWidget->slotToggleDrawWhileMoving(d->drawWhileMovingCheckBox->isChecked());
231 d->previewWidget->slotToggleDrawGrid(d->drawGridCheckBox->isChecked());
232 }
233
writeSettings()234 void PerspectiveTool::writeSettings()
235 {
236 KSharedConfig::Ptr config = KSharedConfig::openConfig();
237 KConfigGroup group = config->group(d->configGroupName);
238
239 group.writeEntry(d->configDrawWhileMovingEntry, d->drawWhileMovingCheckBox->isChecked());
240 group.writeEntry(d->configDrawGridEntry, d->drawGridCheckBox->isChecked());
241 group.writeEntry(d->configInverseTransformationEntry, d->inverseTransformation->isChecked());
242 config->sync();
243 }
244
slotResetSettings()245 void PerspectiveTool::slotResetSettings()
246 {
247 d->previewWidget->reset();
248 }
249
finalRendering()250 void PerspectiveTool::finalRendering()
251 {
252 qApp->setOverrideCursor(Qt::WaitCursor);
253 d->previewWidget->applyPerspectiveAdjustment();
254 qApp->restoreOverrideCursor();
255 }
256
slotUpdateInfo(const QRect & newSize,float topLeftAngle,float topRightAngle,float bottomLeftAngle,float bottomRightAngle,bool valid)257 void PerspectiveTool::slotUpdateInfo(const QRect& newSize, float topLeftAngle, float topRightAngle,
258 float bottomLeftAngle, float bottomRightAngle, bool valid)
259 {
260 QString temp;
261 d->newWidthLabel->setText(temp.setNum(newSize.width()) + i18n(" px"));
262 d->newHeightLabel->setText(temp.setNum(newSize.height()) + i18n(" px"));
263
264 d->topLeftAngleLabel->setText(temp.setNum(topLeftAngle, 'f', 1));
265 d->topRightAngleLabel->setText(temp.setNum(topRightAngle, 'f', 1));
266 d->bottomLeftAngleLabel->setText(temp.setNum(bottomLeftAngle, 'f', 1));
267 d->bottomRightAngleLabel->setText(temp.setNum(bottomRightAngle, 'f', 1));
268
269 d->gboxSettings->button(EditorToolSettings::Ok)->setEnabled(valid);
270 }
271
slotInverseTransformationChanged(bool b)272 void PerspectiveTool::slotInverseTransformationChanged(bool b)
273 {
274 d->drawWhileMovingCheckBox->setEnabled(!b);
275 d->drawGridCheckBox->setEnabled(!b);
276 d->previewWidget->slotInverseTransformationChanged(b);
277 }
278
setBackgroundColor(const QColor & bg)279 void PerspectiveTool::setBackgroundColor(const QColor& bg)
280 {
281 d->previewWidget->setBackgroundColor(bg);
282 }
283
284 } // namespace DigikamEditorPerspectiveToolPlugin
285