File indexing completed on 2024-05-12 16:34:23
0001 /* This file is part of the KDE project 0002 Copyright 2011 Silvio Heinrich <plassy@web.de> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "CropWidget.h" 0021 #include "PictureShape.h" 0022 #include "KoImageData.h" 0023 0024 #include <KoClipPath.h> 0025 0026 #include <QPainter> 0027 #include <QResizeEvent> 0028 0029 qreal calcScale(const QSizeF& imgSize, const QSizeF viewSize, bool fitView) 0030 { 0031 if (qFuzzyCompare(imgSize.width(), qreal(0)) || qFuzzyCompare(imgSize.height(), qreal(0)) || 0032 qFuzzyCompare(viewSize.width(), qreal(0)) || qFuzzyCompare(viewSize.height(), qreal(0))) { 0033 return 1; 0034 } 0035 0036 qreal viewAspect = viewSize.width() / viewSize.height(); 0037 qreal imgAspect = imgSize.width() / imgSize.height(); 0038 0039 if (fitView) { 0040 if (viewAspect > imgAspect) { 0041 return viewSize.height() / imgSize.height(); 0042 } 0043 else { 0044 return viewSize.width() / imgSize.width(); 0045 } 0046 } 0047 else { 0048 if (viewAspect > imgAspect) { 0049 return viewSize.width() / imgSize.width(); 0050 } 0051 else { 0052 return viewSize.height() / imgSize.height(); 0053 } 0054 } 0055 } 0056 0057 QRectF centerRectHorizontally(const QRectF& rect, const QSizeF viewSize) 0058 { 0059 QSizeF diff = viewSize - rect.size(); 0060 return QRectF(diff.width() / 2.0, rect.y(), rect.width(), rect.height()); 0061 } 0062 0063 bool compareRects(const QRectF &a, const QRectF &b, qreal epsilon) 0064 { 0065 qreal x = qAbs(a.x() - b.x()); 0066 qreal y = qAbs(a.y() - b.y()); 0067 qreal w = qAbs(a.width() - b.width()); 0068 qreal h = qAbs(a.height() - b.height()); 0069 0070 return x <= epsilon && y <= epsilon && w <= epsilon && h <= epsilon; 0071 } 0072 0073 // ---------------------------------------------------------------- // 0074 0075 CropWidget::CropWidget(QWidget *parent): 0076 QWidget(parent) 0077 , m_pictureShape(0) 0078 , m_isMousePressed(false) 0079 , m_undoLast(false) 0080 { 0081 setMinimumSize(100, 100); 0082 setMouseTracking(true); 0083 } 0084 0085 void CropWidget::paintEvent(QPaintEvent *event) 0086 { 0087 Q_UNUSED(event); 0088 0089 if(!m_pictureShape || m_imageRect.isNull()) 0090 return; 0091 0092 QPainter painter(this); 0093 QImage image = m_pictureShape->imageData()->image(); 0094 0095 painter.translate(m_imageRect.topLeft()); 0096 painter.scale(m_imageRect.width(), m_imageRect.height()); 0097 0098 painter.drawImage(QRectF(0, 0, 1, 1), image); 0099 0100 painter.setBrush(QColor(0, 0, 0, 127)); 0101 painter.setPen(Qt::NoPen); 0102 painter.drawPolygon(QPolygonF(QRectF(0, 0, 1 , 1)).subtracted(m_selectionRect.getRect())); 0103 0104 painter.setBrush(Qt::NoBrush); 0105 painter.setPen(QPen(this->palette().color(QPalette::Highlight), 0)); 0106 painter.drawRect(m_selectionRect.getRect()); 0107 0108 painter.setBrush(QBrush(this->palette().color(QPalette::Highlight).darker())); 0109 for (int i=0; i<m_selectionRect.getNumHandles(); ++i) 0110 painter.drawRect(m_selectionRect.getHandleRect(m_selectionRect.getHandleFlags(i))); 0111 0112 KoClipPath *clipPath = m_pictureShape->clipPath(); 0113 if (clipPath) { 0114 painter.scale(0.01, 0.01); // the path is defined in 100x100 equaling shapesize 0115 painter.setBrush(Qt::NoBrush); 0116 painter.setPen(QPen(Qt::red, 0)); 0117 painter.drawPath(clipPath->path()); 0118 } 0119 0120 } 0121 0122 void CropWidget::mousePressEvent(QMouseEvent *event) 0123 { 0124 m_selectionRect.beginDragging(toUniformCoord(event->localPos())); 0125 m_isMousePressed = true; 0126 } 0127 0128 void CropWidget::mouseMoveEvent(QMouseEvent *event) 0129 { 0130 QPointF pos = toUniformCoord(event->localPos()); 0131 SelectionRect::HandleFlags flags = m_selectionRect.getHandleFlags(pos); 0132 0133 switch (flags) 0134 { 0135 case SelectionRect::TOP_HANDLE: 0136 case SelectionRect::BOTTOM_HANDLE: 0137 QWidget::setCursor(Qt::SizeVerCursor); 0138 break; 0139 0140 case SelectionRect::LEFT_HANDLE: 0141 case SelectionRect::RIGHT_HANDLE: 0142 QWidget::setCursor(Qt::SizeHorCursor); 0143 break; 0144 0145 case SelectionRect::LEFT_HANDLE|SelectionRect::TOP_HANDLE: 0146 case SelectionRect::RIGHT_HANDLE|SelectionRect::BOTTOM_HANDLE: 0147 QWidget::setCursor(Qt::SizeFDiagCursor); 0148 break; 0149 0150 case SelectionRect::LEFT_HANDLE|SelectionRect::BOTTOM_HANDLE: 0151 case SelectionRect::RIGHT_HANDLE|SelectionRect::TOP_HANDLE: 0152 QWidget::setCursor(Qt::SizeBDiagCursor); 0153 break; 0154 0155 case SelectionRect::INSIDE_RECT: 0156 QWidget::setCursor(Qt::SizeAllCursor); 0157 break; 0158 0159 default: 0160 QWidget::setCursor(Qt::ArrowCursor); 0161 break; 0162 } 0163 0164 if (m_isMousePressed) { 0165 m_selectionRect.doDragging(pos); 0166 update(); 0167 emitCropRegionChanged(); 0168 } 0169 } 0170 0171 void CropWidget::mouseReleaseEvent(QMouseEvent *event) 0172 { 0173 Q_UNUSED(event); 0174 m_selectionRect.finishDragging(); 0175 m_isMousePressed = false; 0176 emitCropRegionChanged(); 0177 m_undoLast = false; // we are done dragging 0178 } 0179 0180 void CropWidget::resizeEvent(QResizeEvent* event) 0181 { 0182 Q_UNUSED(event); 0183 calcImageRect(); 0184 } 0185 0186 void CropWidget::setPictureShape(PictureShape *shape) 0187 { 0188 m_pictureShape = shape; 0189 0190 calcImageRect(); 0191 m_oldSelectionRect = shape->cropRect(); 0192 m_selectionRect.setRect(shape->cropRect()); 0193 m_selectionRect.setConstrainingRect(QRectF(0, 0, 1, 1)); 0194 m_selectionRect.setHandleSize(0.04); 0195 //emit sigCropRegionChanged(shape->cropRect()); 0196 update(); 0197 } 0198 0199 void CropWidget::setCropRect(const QRectF &rect) 0200 { 0201 m_selectionRect.setRect(rect); 0202 emitCropRegionChanged(); 0203 } 0204 0205 void CropWidget::setKeepPictureProportion(bool keepProportion) 0206 { 0207 qreal aspect = keepProportion ? (m_pictureShape->size().width() / m_pictureShape->size().height()) : 0.0; 0208 m_selectionRect.setConstrainingAspectRatio(aspect); 0209 emitCropRegionChanged(); 0210 } 0211 0212 void CropWidget::maximizeCroppedArea() 0213 { 0214 m_selectionRect.setRect(QRectF(0, 0, 1, 1)); 0215 emitCropRegionChanged(); 0216 } 0217 0218 QPointF CropWidget::toUniformCoord(const QPointF& coord) const 0219 { 0220 QPointF result = coord - m_imageRect.topLeft(); 0221 return QPointF(result.x() / m_imageRect.width(), result.y() / m_imageRect.height()); 0222 } 0223 0224 QPointF CropWidget::fromUniformCoord(const QPointF& coord) const 0225 { 0226 return m_imageRect.topLeft() + QPointF(coord.x()*m_imageRect.width(), coord.y()*m_imageRect.height()); 0227 } 0228 0229 void CropWidget::emitCropRegionChanged() 0230 { 0231 if (!compareRects(m_oldSelectionRect, m_selectionRect.getRect(), 0.01)) { 0232 m_oldSelectionRect = m_selectionRect.getRect(); 0233 emit sigCropRegionChanged(m_selectionRect.getRect(), m_undoLast); 0234 update(); 0235 0236 m_undoLast = m_isMousePressed; 0237 } 0238 } 0239 0240 void CropWidget::calcImageRect() 0241 { 0242 if (m_pictureShape) { 0243 QSizeF imageSize = m_pictureShape->imageData()->image().size(); 0244 imageSize = imageSize * calcScale(imageSize, size(), true); 0245 m_imageRect = centerRectHorizontally (QRect(0, 0, imageSize.width(), imageSize.height()), size()); 0246 m_selectionRect.setAspectRatio(m_imageRect.width() / m_imageRect.height()); 0247 } 0248 else { 0249 m_imageRect = QRectF(); 0250 } 0251 }