File indexing completed on 2024-06-02 04:23:50
0001 /* 0002 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org> 0003 All rights reserved. 0004 0005 Redistribution and use in source and binary forms, with or without 0006 modification, are permitted provided that the following conditions 0007 are met: 0008 0009 1. Redistributions of source code must retain the above copyright 0010 notice, this list of conditions and the following disclaimer. 0011 2. Redistributions in binary form must reproduce the above copyright 0012 notice, this list of conditions and the following disclaimer in the 0013 documentation and/or other materials provided with the distribution. 0014 0015 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 0016 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 0017 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 0018 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 0019 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 0020 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0021 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0022 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0023 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 0024 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0025 */ 0026 0027 #define DEBUG_KP_TOOL_ROTATE 0 0028 0029 0030 #include "kpTransformRotateDialog.h" 0031 0032 #include "kpDefs.h" 0033 #include "document/kpDocument.h" 0034 #include "pixmapfx/kpPixmapFX.h" 0035 #include "tools/kpTool.h" 0036 #include "environments/dialogs/imagelib/transforms/kpTransformDialogEnvironment.h" 0037 #include "views/manager/kpViewManager.h" 0038 0039 #include "kpLogCategories.h" 0040 #include <KLocalizedString> 0041 0042 #include <QGroupBox> 0043 #include <QIcon> 0044 #include <QLabel> 0045 #include <QSpinBox> 0046 #include <QPushButton> 0047 #include <QRadioButton> 0048 #include <QTransform> 0049 #include <QGridLayout> 0050 0051 // private static 0052 int kpTransformRotateDialog::s_lastWidth = -1, 0053 kpTransformRotateDialog::s_lastHeight = -1; 0054 0055 // private static 0056 bool kpTransformRotateDialog::s_lastIsClockwise = true; 0057 int kpTransformRotateDialog::s_lastAngleCustom = 0; 0058 0059 0060 kpTransformRotateDialog::kpTransformRotateDialog (bool actOnSelection, 0061 kpTransformDialogEnvironment *_env, QWidget *parent) 0062 : kpTransformPreviewDialog (kpTransformPreviewDialog::AllFeatures, 0063 false/*don't reserve top row*/, 0064 actOnSelection ? i18nc ("@title:window", "Rotate Selection") : i18nc ("@title:window", "Rotate Image"), 0065 i18n ("After rotate:"), 0066 actOnSelection, 0067 _env, parent) 0068 { 0069 s_lastAngleCustom = 0; 0070 0071 0072 createDirectionGroupBox (); 0073 createAngleGroupBox (); 0074 0075 0076 if (s_lastWidth > 0 && s_lastHeight > 0) { 0077 resize (s_lastWidth, s_lastHeight); 0078 } 0079 0080 0081 slotAngleCustomRadioButtonToggled (m_angleCustomRadioButton->isChecked ()); 0082 slotUpdate (); 0083 } 0084 0085 kpTransformRotateDialog::~kpTransformRotateDialog () 0086 { 0087 s_lastWidth = width (); 0088 s_lastHeight = height (); 0089 } 0090 0091 0092 // private 0093 void kpTransformRotateDialog::createDirectionGroupBox () 0094 { 0095 auto *directionGroupBox = new QGroupBox (i18n ("Direction"), mainWidget ()); 0096 addCustomWidget (directionGroupBox); 0097 0098 QPixmap antiClockwisePixmap; 0099 const QIcon rotateLeftIcon = QIcon::fromTheme(QStringLiteral("object-rotate-left")); 0100 // Don't fall back to a generic "object-rotate" or "object" 0101 if (rotateLeftIcon.isNull() || rotateLeftIcon.name() != QLatin1String("object-rotate-left")) { 0102 antiClockwisePixmap = QPixmap(QStringLiteral(":/icons/image_rotate_anticlockwise")); 0103 } else { 0104 antiClockwisePixmap = rotateLeftIcon.pixmap(48); 0105 } 0106 0107 auto *antiClockwisePixmapLabel = new QLabel (directionGroupBox); 0108 antiClockwisePixmapLabel->setPixmap (antiClockwisePixmap); 0109 0110 QPixmap clockwisePixmap; 0111 const QIcon rotateRightIcon = QIcon::fromTheme(QStringLiteral("object-rotate-right")); 0112 if (rotateRightIcon.isNull() || rotateRightIcon.name() != QLatin1String("object-rotate-right")) { 0113 clockwisePixmap = QPixmap(QStringLiteral(":/icons/image_rotate_clockwise")); 0114 } else { 0115 clockwisePixmap = rotateRightIcon.pixmap(48); 0116 } 0117 0118 auto *clockwisePixmapLabel = new QLabel (directionGroupBox); 0119 clockwisePixmapLabel->setPixmap (clockwisePixmap); 0120 0121 m_antiClockwiseRadioButton = new QRadioButton (i18n ("Cou&nterclockwise"), directionGroupBox); 0122 m_clockwiseRadioButton = new QRadioButton (i18n ("C&lockwise"), directionGroupBox); 0123 0124 0125 m_antiClockwiseRadioButton->setChecked (!s_lastIsClockwise); 0126 m_clockwiseRadioButton->setChecked (s_lastIsClockwise); 0127 0128 0129 auto *directionLayout = new QGridLayout (directionGroupBox ); 0130 directionLayout->addWidget (antiClockwisePixmapLabel, 0, 0, Qt::AlignCenter); 0131 directionLayout->addWidget (clockwisePixmapLabel, 0, 1, Qt::AlignCenter); 0132 directionLayout->addWidget (m_antiClockwiseRadioButton, 1, 0, Qt::AlignCenter); 0133 directionLayout->addWidget (m_clockwiseRadioButton, 1, 1, Qt::AlignCenter); 0134 0135 0136 connect (m_antiClockwiseRadioButton, &QRadioButton::toggled, 0137 this, &kpTransformRotateDialog::slotUpdate); 0138 0139 connect (m_clockwiseRadioButton, &QRadioButton::toggled, 0140 this, &kpTransformRotateDialog::slotUpdate); 0141 } 0142 0143 // private 0144 void kpTransformRotateDialog::createAngleGroupBox () 0145 { 0146 auto *angleGroupBox = new QGroupBox (i18n ("Angle"), mainWidget ()); 0147 addCustomWidget (angleGroupBox); 0148 0149 0150 m_angle90RadioButton = new QRadioButton (i18n ("90 °rees"), angleGroupBox); 0151 m_angle180RadioButton = new QRadioButton (i18n ("180 d&egrees"), angleGroupBox); 0152 m_angle270RadioButton = new QRadioButton (i18n ("270 de&grees"), angleGroupBox); 0153 0154 m_angleCustomRadioButton = new QRadioButton (i18n ("C&ustom:"), angleGroupBox); 0155 m_angleCustomInput = new QSpinBox; 0156 m_angleCustomInput->setMinimum(-359); 0157 m_angleCustomInput->setMaximum(+359); 0158 m_angleCustomInput->setValue(s_lastAngleCustom); 0159 auto *degreesLabel = new QLabel (i18n ("degrees"), angleGroupBox); 0160 0161 0162 m_angleCustomRadioButton->setChecked (true); 0163 0164 0165 auto *angleLayout = new QGridLayout (angleGroupBox ); 0166 0167 angleLayout->addWidget (m_angle90RadioButton, 0, 0, 1, 3); 0168 angleLayout->addWidget (m_angle180RadioButton, 1, 0, 1, 3); 0169 angleLayout->addWidget (m_angle270RadioButton, 2, 0, 1, 3); 0170 0171 angleLayout->addWidget (m_angleCustomRadioButton, 3, 0); 0172 angleLayout->addWidget (m_angleCustomInput, 3, 1); 0173 angleLayout->addWidget (degreesLabel, 3, 2); 0174 0175 angleLayout->setColumnStretch (1, 2); // Stretch Custom Angle Input 0176 0177 0178 0179 connect (m_angle90RadioButton, &QRadioButton::toggled, 0180 this, &kpTransformRotateDialog::slotUpdate); 0181 connect (m_angle180RadioButton, &QRadioButton::toggled, 0182 this, &kpTransformRotateDialog::slotUpdate); 0183 connect (m_angle270RadioButton, &QRadioButton::toggled, 0184 this, &kpTransformRotateDialog::slotUpdate); 0185 0186 connect (m_angleCustomRadioButton, &QRadioButton::toggled, 0187 this, &kpTransformRotateDialog::slotAngleCustomRadioButtonToggled); 0188 connect (m_angleCustomRadioButton, &QRadioButton::toggled, 0189 this, &kpTransformRotateDialog::slotUpdate); 0190 0191 connect (m_angleCustomInput, 0192 static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), 0193 this, &kpTransformRotateDialog::slotUpdate); 0194 } 0195 0196 0197 // public virtual [base kpTransformPreviewDialog] 0198 bool kpTransformRotateDialog::isNoOp () const 0199 { 0200 return (angle () == 0); 0201 } 0202 0203 // public 0204 int kpTransformRotateDialog::angle () const 0205 { 0206 int retAngle; 0207 0208 0209 if (m_angle90RadioButton->isChecked ()) { 0210 retAngle = 90; 0211 } 0212 else if (m_angle180RadioButton->isChecked ()) { 0213 retAngle = 180; 0214 } 0215 else if (m_angle270RadioButton->isChecked ()) { 0216 retAngle = 270; 0217 } 0218 else { // if (m_angleCustomRadioButton->isChecked ()) 0219 retAngle = m_angleCustomInput->value (); 0220 } 0221 0222 0223 if (m_antiClockwiseRadioButton->isChecked ()) { 0224 retAngle *= -1; 0225 } 0226 0227 0228 if (retAngle < 0) { 0229 retAngle += ((0 - retAngle) / 360 + 1) * 360; 0230 } 0231 0232 if (retAngle >= 360) { 0233 retAngle -= ((retAngle - 360) / 360 + 1) * 360; 0234 } 0235 0236 0237 return retAngle; 0238 } 0239 0240 0241 // private virtual [base kpTransformPreviewDialog] 0242 QSize kpTransformRotateDialog::newDimensions () const 0243 { 0244 QTransform matrix = kpPixmapFX::rotateMatrix (m_oldWidth, m_oldHeight, angle ()); 0245 QRect rect = matrix.mapRect (QRect (0, 0, m_oldWidth, m_oldHeight)); 0246 return rect.size (); 0247 } 0248 0249 // private virtual [base kpTransformPreviewDialog] 0250 QImage kpTransformRotateDialog::transformPixmap (const QImage &image, 0251 int targetWidth, int targetHeight) const 0252 { 0253 return kpPixmapFX::rotate (image, angle (), 0254 m_environ->backgroundColor (m_actOnSelection), 0255 targetWidth, targetHeight); 0256 } 0257 0258 0259 // private slot 0260 void kpTransformRotateDialog::slotAngleCustomRadioButtonToggled (bool isChecked) 0261 { 0262 m_angleCustomInput->setEnabled (isChecked); 0263 0264 if (isChecked) { 0265 m_angleCustomInput->setFocus(); 0266 } 0267 } 0268 0269 // private slot virtual [base kpTransformPreviewDialog] 0270 void kpTransformRotateDialog::slotUpdate () 0271 { 0272 s_lastIsClockwise = m_clockwiseRadioButton->isChecked (); 0273 s_lastAngleCustom = m_angleCustomInput->value (); 0274 0275 kpTransformPreviewDialog::slotUpdate (); 0276 } 0277 0278 0279 // private slot virtual [base QDialog] 0280 void kpTransformRotateDialog::accept () 0281 { 0282 KLocalizedString message; 0283 QString caption, continueButtonText; 0284 0285 if (document ()->selection ()) 0286 { 0287 if (!document ()->textSelection ()) 0288 { 0289 message = 0290 ki18n ("<qt><p>Rotating the selection to %1x%2" 0291 " may take a substantial amount of memory." 0292 " This can reduce system" 0293 " responsiveness and cause other application resource" 0294 " problems.</p>" 0295 0296 "<p>Are you sure you want to rotate the selection?</p></qt>"); 0297 0298 caption = i18nc ("@title:window", "Rotate Selection?"); 0299 continueButtonText = i18n ("Rotat&e Selection"); 0300 } 0301 } 0302 else 0303 { 0304 message = 0305 ki18n ("<qt><p>Rotating the image to %1x%2" 0306 " may take a substantial amount of memory." 0307 " This can reduce system" 0308 " responsiveness and cause other application resource" 0309 " problems.</p>" 0310 0311 "<p>Are you sure you want to rotate the image?</p></qt>"); 0312 0313 caption = i18nc ("@title:window", "Rotate Image?"); 0314 continueButtonText = i18n ("Rotat&e Image"); 0315 } 0316 0317 0318 const int newWidth = newDimensions ().width (); 0319 const int newHeight = newDimensions ().height (); 0320 0321 if (kpTool::warnIfBigImageSize (m_oldWidth, 0322 m_oldHeight, 0323 newWidth, newHeight, 0324 message.subs (newWidth).subs (newHeight).toString (), 0325 caption, 0326 continueButtonText, 0327 this)) 0328 { 0329 QDialog::accept (); 0330 } 0331 } 0332 0333 #include "moc_kpTransformRotateDialog.cpp"