1 // vim: set tabstop=4 shiftwidth=4 noexpandtab:
3 Gwenview: an image viewer
4 Copyright 2007 Aurélien Gâteau <aurelien.gateau@free.fr>
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include "cropsidebar.moc"
26 #include <QPushButton>
32 #include "cropimageoperation.h"
34 #include "imageview.h"
35 #include "ui_cropsidebar.h"
40 struct CropSideBarPrivate
: public Ui_CropSideBar
{
41 Document::Ptr mDocument
;
43 QPointer
<CropTool
> mCropTool
;
44 bool mUpdatingFromCropTool
;
47 double cropRatio() const {
48 int width
= ratioWidthSpinBox
->value();
49 int height
= ratioHeightSpinBox
->value();
50 return height
/ double(width
);
54 void addRatioToComboBox(const QSize
& size
, const QString
& _label
= QString()) {
55 QString label
= _label
;
56 if (label
.isEmpty()) {
57 label
= QString("%1 x %2").arg(size
.width()).arg(size
.height());
59 ratioComboBox
->addItem(label
, QVariant(size
));
63 void addSeparatorToComboBox() {
64 ratioComboBox
->insertSeparator(ratioComboBox
->count());
68 void initRatioComboBox() {
69 QList
<QSize
> ratioList
;
78 addRatioToComboBox(QSize(1, 1), i18n("Square"));
79 addSeparatorToComboBox();
81 Q_FOREACH(const QSize
& size
, ratioList
) {
82 addRatioToComboBox(size
);
84 addSeparatorToComboBox();
85 Q_FOREACH(QSize size
, ratioList
) {
87 addRatioToComboBox(size
);
90 ratioComboBox
->setMaxVisibleItems(ratioComboBox
->count());
94 void initSpinBoxes() {
95 QSize size
= mDocument
->size();
96 leftSpinBox
->setMaximum(size
.width());
97 widthSpinBox
->setMaximum(size
.width());
98 topSpinBox
->setMaximum(size
.height());
99 heightSpinBox
->setMaximum(size
.height());
104 CropSideBar::CropSideBar(QWidget
* parent
, ImageView
* imageView
, Document::Ptr document
)
106 , d(new CropSideBarPrivate
) {
107 d
->mDocument
= document
;
108 d
->mUpdatingFromCropTool
= false;
109 d
->mCropTool
= new CropTool(imageView
);
110 imageView
->setCurrentTool(d
->mCropTool
);
111 d
->mWidget
= new QWidget(this);
112 d
->setupUi(d
->mWidget
);
113 d
->mWidget
->layout()->setMargin(0);
115 QVBoxLayout
* layout
= new QVBoxLayout(this);
116 layout
->addWidget(d
->mWidget
);
118 QPushButton
* ok
= d
->buttonBox
->button(QDialogButtonBox::Ok
);
120 ok
->setText(i18n("Crop"));
122 d
->initRatioComboBox();
124 connect(d
->mCropTool
, SIGNAL(rectUpdated(const QRect
&)),
125 SLOT(setCropRect(const QRect
&)) );
127 connect(d
->leftSpinBox
, SIGNAL(valueChanged(int)),
128 SLOT(slotPositionChanged()) );
129 connect(d
->topSpinBox
, SIGNAL(valueChanged(int)),
130 SLOT(slotPositionChanged()) );
131 connect(d
->widthSpinBox
, SIGNAL(valueChanged(int)),
132 SLOT(slotWidthChanged()) );
133 connect(d
->heightSpinBox
, SIGNAL(valueChanged(int)),
134 SLOT(slotHeightChanged()) );
136 connect(d
->buttonBox
, SIGNAL(accepted()),
137 SLOT(slotAccepted()) );
139 connect(d
->buttonBox
, SIGNAL(rejected()),
142 connect(d
->constrainRatioCheckBox
, SIGNAL(toggled(bool)),
143 SLOT(applyRatioConstraint()) );
144 connect(d
->ratioWidthSpinBox
, SIGNAL(valueChanged(int)),
145 SLOT(applyRatioConstraint()) );
146 connect(d
->ratioHeightSpinBox
, SIGNAL(valueChanged(int)),
147 SLOT(applyRatioConstraint()) );
149 connect(d
->ratioComboBox
, SIGNAL(activated(int)),
150 SLOT(setRatioConstraintFromComboBox()) );
152 // Don't do this before signals are connected, otherwise the tool won't get
158 CropSideBar::~CropSideBar() {
159 // The crop tool is owned by the image view, so it may already have been
160 // deleted, for example if we quit while the dialog is still opened.
162 d
->mCropTool
->imageView()->setCurrentTool(0);
168 QRect
CropSideBar::cropRect() const {
170 d
->leftSpinBox
->value(),
171 d
->topSpinBox
->value(),
172 d
->widthSpinBox
->value(),
173 d
->heightSpinBox
->value()
179 void CropSideBar::setCropRect(const QRect
& rect
) {
180 d
->mUpdatingFromCropTool
= true;
181 d
->leftSpinBox
->setValue(rect
.left());
182 d
->topSpinBox
->setValue(rect
.top());
183 d
->widthSpinBox
->setValue(rect
.width());
184 d
->heightSpinBox
->setValue(rect
.height());
185 d
->mUpdatingFromCropTool
= false;
189 void CropSideBar::slotPositionChanged() {
190 if (d
->mUpdatingFromCropTool
) {
193 d
->mCropTool
->setRect(cropRect());
197 void CropSideBar::slotWidthChanged() {
198 if (d
->mUpdatingFromCropTool
) {
201 if (d
->constrainRatioCheckBox
->isChecked()) {
202 int height
= int(d
->widthSpinBox
->value() * d
->cropRatio());
203 d
->heightSpinBox
->setValue(height
);
205 d
->mCropTool
->setRect(cropRect());
209 void CropSideBar::slotHeightChanged() {
210 if (d
->mUpdatingFromCropTool
) {
213 if (d
->constrainRatioCheckBox
->isChecked()) {
214 int width
= int(d
->heightSpinBox
->value() / d
->cropRatio());
215 d
->widthSpinBox
->setValue(width
);
217 d
->mCropTool
->setRect(cropRect());
221 void CropSideBar::slotAccepted() {
222 CropImageOperation
* op
= new CropImageOperation(cropRect());
223 emit
imageOperationRequested(op
);
228 void CropSideBar::applyRatioConstraint() {
229 if (!d
->constrainRatioCheckBox
->isChecked()) {
230 d
->mCropTool
->setCropRatio(0);
234 double ratio
= d
->cropRatio();
235 d
->mCropTool
->setCropRatio(ratio
);
237 d
->heightSpinBox
->setValue(int(d
->widthSpinBox
->value() * ratio
));
241 void CropSideBar::setRatioConstraintFromComboBox() {
242 QVariant data
= d
->ratioComboBox
->itemData(d
->ratioComboBox
->currentIndex());
243 if (!data
.isValid()) {
247 QSize size
= data
.toSize();
248 d
->ratioWidthSpinBox
->blockSignals(true);
249 d
->ratioWidthSpinBox
->setValue(size
.width());
250 d
->ratioWidthSpinBox
->blockSignals(false);
251 d
->ratioHeightSpinBox
->setValue(size
.height());