File indexing completed on 2024-05-12 16:34:24
0001 /* This file is part of the KDE project 0002 Copyright 2007 Montel Laurent <montel@kde.org> 0003 Copyright 2011 Silvio Heinrich <plassy@web.de> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "PictureTool.h" 0022 #include "PictureShape.h" 0023 #include "ChangeImageCommand.h" 0024 #include "ClipCommand.h" 0025 #include "CropWidget.h" 0026 0027 #include <QUrl> 0028 #include <QFileDialog> 0029 #include <QImageReader> 0030 0031 #include <klocalizedstring.h> 0032 #include <KIO/Job> 0033 0034 #include <KoIcon.h> 0035 #include <KoCanvasBase.h> 0036 #include <KoImageCollection.h> 0037 #include <KoImageData.h> 0038 #include <KoSelection.h> 0039 #include <KoShapeManager.h> 0040 #include <KoShapeController.h> 0041 #include <KoDocumentResourceManager.h> 0042 #include <KoPointerEvent.h> 0043 #include <KoFilterEffect.h> 0044 #include <KoFilterEffectRegistry.h> 0045 #include <KoFilterEffectConfigWidgetBase.h> 0046 #include <KoFilterEffectStack.h> 0047 0048 #include "ui_wdgPictureTool.h" 0049 0050 struct PictureToolUI: public QWidget, public Ui::PictureTool 0051 { 0052 PictureToolUI() 0053 { 0054 setupUi(this); 0055 } 0056 0057 void blockAllSignals(bool block) 0058 { 0059 leftDoubleSpinBox->blockSignals(block); 0060 rightDoubleSpinBox->blockSignals(block); 0061 topDoubleSpinBox->blockSignals(block); 0062 bottomDoubleSpinBox->blockSignals(block); 0063 cropWidget->blockSignals(block); 0064 cbAspect->blockSignals(block); 0065 cmbColorMode->blockSignals(block); 0066 } 0067 }; 0068 0069 // ---------------------------------------------------- // 0070 0071 PictureTool::PictureTool(KoCanvasBase* canvas) 0072 : KoToolBase(canvas), 0073 m_pictureshape(0), 0074 m_pictureToolUI(0) 0075 { 0076 } 0077 0078 void PictureTool::activate(ToolActivation toolActivation, const QSet<KoShape*> &shapes) 0079 { 0080 Q_UNUSED(toolActivation); 0081 0082 foreach (KoShape *shape, shapes) { 0083 if ((m_pictureshape = dynamic_cast<PictureShape*>(shape))) 0084 break; 0085 } 0086 0087 if (!m_pictureshape) { 0088 emit done(); 0089 return; 0090 } 0091 0092 if (m_pictureToolUI) { 0093 m_pictureToolUI->cropWidget->setPictureShape(m_pictureshape); 0094 updateControlElements(); 0095 } 0096 0097 useCursor(Qt::ArrowCursor); 0098 } 0099 0100 void PictureTool::deactivate() 0101 { 0102 m_pictureshape = 0; 0103 } 0104 0105 QWidget *PictureTool::createOptionWidget() 0106 { 0107 m_pictureToolUI = new PictureToolUI(); 0108 m_pictureToolUI->cmbColorMode->addItem(i18n("Standard") , PictureShape::Standard); 0109 m_pictureToolUI->cmbColorMode->addItem(i18n("Greyscale") , PictureShape::Greyscale); 0110 m_pictureToolUI->cmbColorMode->addItem(i18n("Monochrome"), PictureShape::Mono); 0111 m_pictureToolUI->cmbColorMode->addItem(i18n("Watermark") , PictureShape::Watermark); 0112 m_pictureToolUI->bnImageFile->setIcon(koIcon("document-open")); 0113 0114 updateControlElements(); 0115 0116 connect(m_pictureToolUI->bnImageFile, SIGNAL(clicked(bool)), this, SLOT(changeUrlPressed())); 0117 connect(m_pictureToolUI->cmbColorMode, SIGNAL(currentIndexChanged(int)), this, SLOT(colorModeChanged(int))); 0118 connect(m_pictureToolUI->leftDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(cropEditFieldsChanged())); 0119 connect(m_pictureToolUI->rightDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(cropEditFieldsChanged())); 0120 connect(m_pictureToolUI->topDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(cropEditFieldsChanged())); 0121 connect(m_pictureToolUI->bottomDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(cropEditFieldsChanged())); 0122 connect(m_pictureToolUI->cbAspect, SIGNAL(toggled(bool)), this, SLOT(aspectCheckBoxChanged(bool))); 0123 connect(m_pictureToolUI->bnFill, SIGNAL(pressed()), this, SLOT(fillButtonPressed())); 0124 connect(m_pictureToolUI->cbContour, SIGNAL(toggled(bool)), this, SLOT(contourCheckBoxChanged(bool))); 0125 connect(m_pictureToolUI->cropWidget, SIGNAL(sigCropRegionChanged(QRectF,bool)), this, SLOT(cropRegionChanged(QRectF,bool))); 0126 0127 return m_pictureToolUI; 0128 } 0129 0130 void PictureTool::updateControlElements() 0131 { 0132 if (m_pictureshape) { 0133 QSizeF imageSize = m_pictureshape->imageData()->imageSize(); 0134 PictureShape::ColorMode mode = m_pictureshape->colorMode(); 0135 ClippingRect clippingRect(m_pictureshape->cropRect()); 0136 0137 clippingRect.right = 1.0 - clippingRect.right; 0138 clippingRect.bottom = 1.0 - clippingRect.bottom; 0139 clippingRect.scale(imageSize); 0140 0141 m_pictureToolUI->blockAllSignals(true); 0142 m_pictureToolUI->cropWidget->setPictureShape(m_pictureshape); 0143 m_pictureToolUI->cropWidget->setKeepPictureProportion(m_pictureshape->isPictureInProportion()); 0144 m_pictureToolUI->cbAspect->setChecked(m_pictureshape->isPictureInProportion()); 0145 m_pictureToolUI->cmbColorMode->setCurrentIndex(m_pictureToolUI->cmbColorMode->findData(mode)); 0146 0147 m_pictureToolUI->leftDoubleSpinBox->setRange(0.0, imageSize.width()); 0148 m_pictureToolUI->rightDoubleSpinBox->setRange(0.0, imageSize.width()); 0149 m_pictureToolUI->topDoubleSpinBox->setRange(0.0, imageSize.height()); 0150 m_pictureToolUI->bottomDoubleSpinBox->setRange(0.0, imageSize.height()); 0151 m_pictureToolUI->leftDoubleSpinBox->setValue(clippingRect.left); 0152 m_pictureToolUI->rightDoubleSpinBox->setValue(clippingRect.right); 0153 m_pictureToolUI->topDoubleSpinBox->setValue(clippingRect.top); 0154 m_pictureToolUI->bottomDoubleSpinBox->setValue(clippingRect.bottom); 0155 m_pictureToolUI->cbContour->setChecked(m_pictureshape->clipPath() != 0); 0156 m_pictureToolUI->blockAllSignals(false); 0157 } 0158 } 0159 0160 void PictureTool::changeUrlPressed() 0161 { 0162 if (m_pictureshape == 0) 0163 return; 0164 // TODO: think about using KoFileDialog everywhere, after extending it to support remote urls 0165 QFileDialog *dialog = new QFileDialog(); 0166 QStringList imageMimeTypes; 0167 foreach(const QByteArray &mimeType, QImageReader::supportedMimeTypes()) { 0168 imageMimeTypes << QLatin1String(mimeType); 0169 } 0170 dialog->setMimeTypeFilters(imageMimeTypes); 0171 dialog->setFileMode(QFileDialog::ExistingFile); 0172 dialog->setAcceptMode(QFileDialog::AcceptOpen); 0173 dialog->exec(); 0174 QUrl url = dialog->selectedUrls().value(0); 0175 0176 if (!url.isEmpty()) { 0177 // TODO move this to an action in the libs, with a nice dialog or something. 0178 KIO::StoredTransferJob *job = KIO::storedGet(url, KIO::NoReload, 0); 0179 connect(job, SIGNAL(result(KJob*)), this, SLOT(setImageData(KJob*))); 0180 } 0181 } 0182 0183 void PictureTool::cropEditFieldsChanged() 0184 { 0185 ClippingRect clippingRect; 0186 clippingRect.left = m_pictureToolUI->leftDoubleSpinBox->value(); 0187 clippingRect.right = m_pictureToolUI->rightDoubleSpinBox->value(); 0188 clippingRect.top = m_pictureToolUI->topDoubleSpinBox->value(); 0189 clippingRect.bottom = m_pictureToolUI->bottomDoubleSpinBox->value(); 0190 clippingRect.uniform = false; 0191 clippingRect.inverted = true; 0192 clippingRect.normalize(m_pictureshape->imageData()->imageSize()); 0193 0194 m_pictureToolUI->cropWidget->setCropRect(clippingRect.toRect()); 0195 } 0196 0197 void PictureTool::cropRegionChanged(const QRectF& rect, bool undoPrev) 0198 { 0199 if (undoPrev) { 0200 canvas()->shapeController()->resourceManager()->undoStack()->undo(); 0201 } 0202 0203 ChangeImageCommand *cmd = new ChangeImageCommand(m_pictureshape, rect); 0204 // connect before adding the command, so that "updateControlElements()" is executed 0205 // when the command is added to the undo stack. 0206 connect(cmd, SIGNAL(sigExecuted()), this, SLOT(updateControlElements())); 0207 canvas()->addCommand(cmd); 0208 } 0209 0210 void PictureTool::colorModeChanged(int cmbIndex) 0211 { 0212 PictureShape::ColorMode mode = (PictureShape::ColorMode)m_pictureToolUI->cmbColorMode->itemData(cmbIndex).toInt(); 0213 ChangeImageCommand *cmd = new ChangeImageCommand(m_pictureshape, mode); 0214 canvas()->addCommand(cmd); 0215 // connect after adding the command to the undo stack to prevent a 0216 // call to "updateControlElements()" at this point 0217 connect(cmd, SIGNAL(sigExecuted()), this, SLOT(updateControlElements())); 0218 } 0219 0220 void PictureTool::aspectCheckBoxChanged(bool checked) 0221 { 0222 m_pictureToolUI->cropWidget->setKeepPictureProportion(checked); 0223 } 0224 0225 void PictureTool::contourCheckBoxChanged(bool checked) 0226 { 0227 canvas()->addCommand(new ClipCommand(m_pictureshape, checked)); 0228 } 0229 0230 void PictureTool::fillButtonPressed() 0231 { 0232 m_pictureToolUI->cropWidget->maximizeCroppedArea(); 0233 } 0234 0235 void PictureTool::setImageData(KJob *job) 0236 { 0237 if (m_pictureshape == 0) 0238 return; // ugh, the user deselected the image in between. We should move this code to main anyway redesign it 0239 0240 KIO::StoredTransferJob *transferJob = qobject_cast<KIO::StoredTransferJob*>(job); 0241 Q_ASSERT(transferJob); 0242 if (m_pictureshape->imageCollection()) { 0243 KoImageData *data = m_pictureshape->imageCollection()->createImageData(transferJob->data()); 0244 ChangeImageCommand *cmd = new ChangeImageCommand(m_pictureshape, data); 0245 // connect before adding the command, so that "updateControlElements()" is executed 0246 // when the command is added to the undo stack. 0247 connect(cmd, SIGNAL(sigExecuted()), this, SLOT(updateControlElements())); 0248 canvas()->addCommand(cmd); 0249 } 0250 } 0251 0252 void PictureTool::mousePressEvent(KoPointerEvent *event) 0253 { 0254 if (event->button() == Qt::RightButton) { 0255 event->ignore(); 0256 } 0257 } 0258 0259 void PictureTool::mouseDoubleClickEvent(KoPointerEvent *event) 0260 { 0261 if (canvas()->shapeManager()->shapeAt(event->point) != m_pictureshape) { 0262 event->ignore(); // allow the event to be used by another 0263 return; 0264 } 0265 0266 changeUrlPressed(); 0267 }