File indexing completed on 2025-01-05 03:59:44

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2004-11-16
0007  * Description : a widget to display an image with guides
0008  *
0009  * SPDX-FileCopyrightText: 2004-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #include "imageguidewidget.h"
0016 
0017 // Qt includes
0018 
0019 #include <QRegion>
0020 #include <QPainter>
0021 #include <QPen>
0022 #include <QTimer>
0023 #include <QRect>
0024 #include <QBrush>
0025 #include <QFont>
0026 #include <QFontMetrics>
0027 
0028 // KDE includes
0029 
0030 #include <klocalizedstring.h>
0031 
0032 // Local includes
0033 
0034 #include "dimg.h"
0035 #include "digikam_debug.h"
0036 #include "previewtoolbar.h"
0037 #include "exposurecontainer.h"
0038 #include "iccsettingscontainer.h"
0039 
0040 namespace Digikam
0041 {
0042 
0043 static const KLocalizedString beforeLabel = ki18nc("Preview image (before filter has been applied)", "Before");
0044 static const KLocalizedString afterLabel  = ki18nc("Preview image (after filter has been applied)",  "After");
0045 
0046 class Q_DECL_HIDDEN ImageGuideWidget::Private
0047 {
0048 public:
0049 
0050     explicit Private()
0051       : sixteenBit                  (false),
0052         focus                       (false),
0053         spotVisible                 (false),
0054         onMouseMovePreviewToggled   (true),
0055         drawLineBetweenPoints       (false),
0056         drawingMask                 (false),
0057         enableDrawMask              (false),
0058         eraseMask                   (false),
0059         timerID                     (0),
0060         guideMode                   (0),
0061         guideSize                   (0),
0062         flicker                     (0),
0063         renderingPreviewMode        (PreviewToolBar::NoPreviewMode),
0064         penWidth                    (10),
0065         pixmap                      (nullptr),
0066         maskPixmap                  (nullptr),
0067         previewPixmap               (nullptr),
0068         iface                       (nullptr)
0069     {
0070     }
0071 
0072     bool        sixteenBit;
0073     bool        focus;
0074     bool        spotVisible;
0075     bool        onMouseMovePreviewToggled;
0076     bool        drawLineBetweenPoints;
0077     bool        drawingMask;
0078     bool        enableDrawMask;
0079     bool        eraseMask;
0080 
0081     int         timerID;
0082     int         guideMode;
0083     int         guideSize;
0084     int         flicker;
0085     int         renderingPreviewMode;
0086     int         penWidth;
0087 
0088     /// Current spot position in preview coordinates.
0089     QPoint      spot;
0090     QPolygon    selectedPoints;
0091 
0092     QRect       rect;
0093 
0094     QColor      guideColor;
0095     QColor      paintColor;
0096     QColor      bgColor;
0097 
0098     QPixmap*    pixmap;
0099     QPixmap*    maskPixmap;
0100     QPixmap*    previewPixmap;
0101 
0102     QCursor     maskCursor;
0103 
0104     QPoint      lastPoint;
0105 
0106     ImageIface* iface;
0107 
0108     DImg        preview;
0109 };
0110 
0111 ImageGuideWidget::ImageGuideWidget(QWidget* const parent,
0112                                    bool spotVisible,
0113                                    int guideMode,
0114                                    const QColor& guideColor,
0115                                    int guideSize,
0116                                    bool blink, ImageIface::PreviewType type)
0117     : QWidget(parent),
0118       d      (new Private)
0119 {
0120     int w            = 480;
0121     int h            = 320;
0122     d->spotVisible   = spotVisible;
0123     d->guideMode     = guideMode;
0124     d->guideColor    = guideColor;
0125     d->guideSize     = guideSize;
0126     d->bgColor       = palette().color(QPalette::Base);
0127 
0128     setMinimumSize(w, h);
0129     setMouseTracking(true);
0130     setAttribute(Qt::WA_DeleteOnClose);
0131 
0132     d->iface         = new ImageIface(QSize(w, h));
0133     d->iface->setPreviewType(type);
0134     d->preview       = d->iface->preview();
0135     d->preview.setIccProfile(d->iface->original() ? d->iface->original()->getIccProfile() : IccProfile());
0136 
0137     d->pixmap        = new QPixmap(w, h);
0138     d->rect          = QRect(w / 2 - d->preview.width() / 2, h / 2 - d->preview.height() / 2, d->preview.width(), d->preview.height());
0139     d->maskPixmap    = new QPixmap(d->rect.width(), d->rect.height());
0140     d->previewPixmap = new QPixmap(d->rect.width(), d->rect.height());
0141     d->maskPixmap->fill(QColor(0, 0, 0, 0));
0142     d->previewPixmap->fill(QColor(0, 0, 0, 0));
0143 
0144     d->paintColor.setRgb(255, 255, 255, 255);
0145 
0146     d->lastPoint     = QPoint(d->rect.x(), d->rect.y());
0147 
0148     resetSpotPosition();
0149     setSpotVisible(d->spotVisible, blink);
0150 }
0151 
0152 ImageGuideWidget::~ImageGuideWidget()
0153 {
0154     delete d->iface;
0155 
0156     if (d->timerID)
0157     {
0158         killTimer(d->timerID);
0159     }
0160 
0161     delete d->pixmap;
0162     delete d->maskPixmap;
0163     delete d->previewPixmap;
0164     delete d;
0165 }
0166 
0167 ImageIface* ImageGuideWidget::imageIface() const
0168 {
0169     return d->iface;
0170 }
0171 
0172 void ImageGuideWidget::setBackgroundColor(const QColor& bg)
0173 {
0174     d->bgColor = bg;
0175     updatePreview();
0176 }
0177 
0178 void ImageGuideWidget::ICCSettingsChanged()
0179 {
0180     updatePreview();
0181 }
0182 
0183 void ImageGuideWidget::exposureSettingsChanged()
0184 {
0185     updatePreview();
0186 }
0187 
0188 void ImageGuideWidget::resetSpotPosition()
0189 {
0190     d->spot.setX(d->preview.width()  / 2);
0191     d->spot.setY(d->preview.height() / 2);
0192     updatePreview();
0193 }
0194 
0195 void ImageGuideWidget::slotPreviewModeChanged(int mode)
0196 {
0197     d->renderingPreviewMode = mode;
0198     updatePreview();
0199 }
0200 
0201 int ImageGuideWidget::previewMode() const
0202 {
0203     return (d->renderingPreviewMode);
0204 }
0205 
0206 QPoint ImageGuideWidget::getSpotPosition() const
0207 {
0208     return (QPoint((int)((float)d->spot.x() * (float)d->iface->originalSize().width()  / (float)d->preview.width()),
0209                    (int)((float)d->spot.y() * (float)d->iface->originalSize().height() / (float)d->preview.height())));
0210 }
0211 
0212 DColor ImageGuideWidget::getSpotColor(int getColorFrom) const
0213 {
0214     if      (getColorFrom == OriginalImage)                          // Get point color from full original image
0215     {
0216         return (d->iface->colorInfoFromOriginal(getSpotPosition()));
0217     }
0218     else if (getColorFrom == PreviewImage)                      // Get point color from full preview image
0219     {
0220         return (d->iface->colorInfoFromPreview(d->spot));
0221     }
0222 
0223     // In other cases, get point color from preview target image
0224 
0225     return (d->iface->colorInfoFromTargetPreview(d->spot));
0226 }
0227 
0228 void ImageGuideWidget::setSpotVisible(bool spotVisible, bool blink)
0229 {
0230     d->spotVisible = spotVisible;
0231 
0232     if (blink)
0233     {
0234         if (d->spotVisible)
0235         {
0236             d->timerID = startTimer(800);
0237         }
0238         else
0239         {
0240             killTimer(d->timerID);
0241             d->timerID = 0;
0242         }
0243     }
0244 
0245     updatePreview();
0246 }
0247 
0248 void ImageGuideWidget::setSpotVisibleNoUpdate(bool spotVisible)
0249 {
0250     d->spotVisible = spotVisible;
0251 }
0252 
0253 void ImageGuideWidget::slotChangeGuideColor(const QColor& color)
0254 {
0255     d->guideColor = color;
0256     updatePreview();
0257 }
0258 
0259 void ImageGuideWidget::slotChangeGuideSize(int size)
0260 {
0261     d->guideSize = size;
0262     updatePreview();
0263 }
0264 
0265 void ImageGuideWidget::updatePreview()
0266 {
0267     updatePixmap();
0268     update();
0269 }
0270 
0271 void ImageGuideWidget::updatePixmap()
0272 {
0273     QPainter p(d->pixmap);
0274     p.setRenderHint(QPainter::Antialiasing, true);
0275     p.setBackgroundMode(Qt::TransparentMode);
0276 
0277     QString text;
0278     p.setPen(QPen(Qt::red, 1));
0279 
0280     d->pixmap->fill(d->bgColor);
0281 
0282     if      ((d->renderingPreviewMode == PreviewToolBar::PreviewOriginalImage) ||
0283              ((d->renderingPreviewMode == PreviewToolBar::PreviewToggleOnMouseOver) && !d->onMouseMovePreviewToggled))
0284     {
0285         p.drawPixmap(d->rect, *d->previewPixmap);
0286         drawText(&p, QPoint(d->rect.x() + 20, d->rect.y() + 20), beforeLabel.toString());
0287     }
0288     else if ((d->renderingPreviewMode == PreviewToolBar::PreviewTargetImage) ||
0289              (d->renderingPreviewMode == PreviewToolBar::NoPreviewMode)      ||
0290              ((d->renderingPreviewMode == PreviewToolBar::PreviewToggleOnMouseOver) && d->onMouseMovePreviewToggled))
0291     {
0292         d->iface->paint(d->pixmap, d->rect, &p);
0293 
0294         if ((d->renderingPreviewMode == PreviewToolBar::PreviewTargetImage) ||
0295             (d->renderingPreviewMode == PreviewToolBar::PreviewToggleOnMouseOver))
0296         {
0297             drawText(&p, QPoint(d->rect.x() + 20, d->rect.y() + 20), afterLabel.toString());
0298         }
0299     }
0300     else if ((d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVert) ||
0301              (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVertCont))
0302     {
0303         if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVert)
0304         {
0305             // Drawing original image.
0306 
0307             p.drawPixmap(d->rect, *d->previewPixmap);
0308 
0309             // Drawing target image under the original.
0310 
0311             d->iface->paint(d->pixmap, QRect(d->rect.x() + d->rect.width() / 2, d->rect.y(), d->rect.width() / 2, d->rect.height()), &p);
0312         }
0313         else
0314         {
0315             // Drawing target image.
0316 
0317             d->iface->paint(d->pixmap, d->rect, &p);
0318 
0319             // Drawing original image under the target.
0320 
0321             p.drawPixmap(d->rect.x(), d->rect.y(), *d->previewPixmap, 0, 0, d->rect.width() / 2, d->rect.height());
0322         }
0323 
0324         // Drawing information and others stuff.
0325 
0326         p.fillRect(d->rect.right(), 0, width(), height(), palette().color(QPalette::Window));
0327 
0328         p.setPen(QPen(Qt::white, 2, Qt::SolidLine));
0329         p.drawLine(d->rect.x() + d->rect.width() / 2 - 1, d->rect.y(),
0330                    d->rect.x() + d->rect.width() / 2 - 1, d->rect.y() + d->rect.height());
0331         p.setPen(QPen(Qt::red, 2, Qt::DotLine));
0332         p.drawLine(d->rect.x() + d->rect.width() / 2 - 1, d->rect.y(),
0333                    d->rect.x() + d->rect.width() / 2 - 1, d->rect.y() + d->rect.height());
0334 
0335         drawText(&p, QPoint(d->rect.x() + 20, d->rect.y() + 20), beforeLabel.toString());
0336         drawText(&p, QPoint(d->rect.x() + d->rect.width() / 2 + 20, d->rect.y() + 20), afterLabel.toString());
0337     }
0338     else if ((d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorz) ||
0339              (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorzCont))
0340     {
0341         if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorz)
0342         {
0343             // Drawing original image.
0344 
0345             p.drawPixmap(d->rect, *d->previewPixmap);
0346 
0347             // Drawing target image under the original.
0348 
0349             d->iface->paint(d->pixmap, QRect(d->rect.x(), d->rect.y() + d->rect.height() / 2, d->rect.width(), d->rect.height() / 2), &p);
0350         }
0351         else
0352         {
0353             // Drawing target image.
0354 
0355             d->iface->paint(d->pixmap, d->rect, &p);
0356 
0357             // Drawing original image under the target.
0358 
0359             p.drawPixmap(d->rect.x(), d->rect.y(), *d->previewPixmap,
0360                          0, 0, d->rect.width(), d->rect.height() / 2);
0361         }
0362 
0363         p.fillRect(0, d->rect.bottom(), width(), height(), palette().color(QPalette::Window));
0364 
0365         p.setPen(QPen(Qt::white, 2, Qt::SolidLine));
0366         p.drawLine(d->rect.x(),
0367                    d->rect.y() + d->rect.height() / 2 - 1,
0368                    d->rect.x() + d->rect.width(),
0369                    d->rect.y() + d->rect.height() / 2 - 1);
0370         p.setPen(QPen(Qt::red, 2, Qt::DotLine));
0371         p.drawLine(d->rect.x(),
0372                    d->rect.y() + d->rect.height() / 2 - 1,
0373                    d->rect.x() + d->rect.width(),
0374                    d->rect.y() + d->rect.height() / 2 - 1);
0375 
0376         drawText(&p, QPoint(d->rect.x() + 20, d->rect.y() + 20), beforeLabel.toString());
0377         drawText(&p, QPoint(d->rect.x() + 20, d->rect.y() + d->rect.height() / 2 + 20), afterLabel.toString());
0378     }
0379 
0380     if (d->spotVisible)
0381     {
0382         // Adapt spot from image coordinate to widget coordinate.
0383 
0384         int xspot = d->spot.x() + d->rect.x();
0385         int yspot = d->spot.y() + d->rect.y();
0386 
0387         switch (d->guideMode)
0388         {
0389             case HVGuideMode:
0390             {
0391                 p.setPen(QPen(Qt::white, d->guideSize, Qt::SolidLine));
0392                 p.drawLine(xspot, d->rect.top() + d->flicker, xspot, d->rect.bottom() - d->flicker);
0393                 p.drawLine(d->rect.left() + d->flicker, yspot, d->rect.right() - d->flicker, yspot);
0394                 p.setPen(QPen(d->guideColor, d->guideSize, Qt::DotLine));
0395                 p.drawLine(xspot, d->rect.top() + d->flicker, xspot, d->rect.bottom() - d->flicker);
0396                 p.drawLine(d->rect.left() + d->flicker, yspot, d->rect.right() - d->flicker, yspot);
0397                 break;
0398             }
0399 
0400             case PickColorMode:
0401             {
0402                 p.setPen(QPen(d->guideColor, 1, Qt::SolidLine));
0403                 p.drawLine(xspot - 10, yspot - 10, xspot + 10, yspot + 10);
0404                 p.drawLine(xspot + 10, yspot - 10, xspot - 10, yspot + 10);
0405                 p.setPen(QPen(d->guideColor, 3, Qt::SolidLine));
0406                 p.drawEllipse(xspot - 5, yspot - 5, 11, 11);
0407 
0408                 if (d->flicker % 2 != 0)
0409                 {
0410                     p.setPen(QPen(Qt::white, 1, Qt::SolidLine));
0411                     p.drawEllipse(xspot - 5, yspot - 5, 11, 11);
0412                 }
0413 
0414                 break;
0415             }
0416         }
0417     }
0418 
0419     // draw additional points added by the image tool
0420 
0421     if (d->selectedPoints.count() > 0)
0422     {
0423         QPainter::RenderHints hints = p.renderHints();
0424         QColor semiTransGuideColor  = QColor(d->guideColor.red(), d->guideColor.green(), d->guideColor.blue(), 75);
0425 
0426         QPoint point;
0427         int x = 0;
0428         int y = 0;
0429 
0430         for (int i = 0 ; i < d->selectedPoints.count() ; ++i)
0431         {
0432             point = d->selectedPoints.point(i);
0433             point = translatePointPosition(point);
0434             x     = point.x();
0435             y     = point.y();
0436 
0437             p.save();
0438             p.setRenderHint(QPainter::Antialiasing, true);
0439             p.setPen(QPen(d->guideColor, 2, Qt::SolidLine));
0440             p.setBrush(QBrush(semiTransGuideColor));
0441             p.drawEllipse(point, 6, 6);
0442 
0443             p.restore();
0444             p.setPen(QPen(d->guideColor, 1, Qt::SolidLine));
0445             p.setBrush(Qt::NoBrush);
0446             p.setRenderHint(QPainter::Antialiasing, false);
0447             p.drawPoint(point);
0448             p.drawText(QPoint(x + 10, y - 5), QString::number(i + 1));
0449 
0450             // draw a line between the points
0451 
0452             if (d->drawLineBetweenPoints &&
0453                 ((i + 1) < d->selectedPoints.count()) && !d->selectedPoints.point(i + 1).isNull())
0454             {
0455                 p.save();
0456                 p.setPen(QPen(d->guideColor, d->guideSize, Qt::SolidLine));
0457                 QPoint point2 = d->selectedPoints.point(i + 1);
0458                 point2        = translatePointPosition(point2);
0459                 p.setRenderHint(QPainter::Antialiasing, true);
0460                 p.drawLine(point, point2);
0461                 p.restore();
0462             }
0463         }
0464 
0465         p.setRenderHints(hints);
0466     }
0467 
0468     p.end();
0469 }
0470 
0471 void ImageGuideWidget::drawText(QPainter* const p, const QPoint& corner, const QString& text)
0472 {
0473     p->save();
0474     QFontMetrics fontMt = p->fontMetrics();
0475     QRect      fontRect = fontMt.boundingRect(text);
0476     QRect textRect;
0477     textRect.setTopLeft(corner);
0478     textRect.setSize(QSize(fontRect.width() + 5, fontRect.height() + 2));
0479 
0480     // Draw background
0481 
0482     p->setPen(Qt::black);
0483     QColor semiTransBg = palette().color(QPalette::Window);
0484     semiTransBg.setAlpha(190);
0485     p->setBrush(semiTransBg);
0486 /*
0487     p->translate(0.5, 0.5);
0488 */
0489     p->drawRoundedRect(textRect, 10.0, 10.0);
0490 
0491     // Draw shadow and text
0492 
0493     p->setPen(palette().color(QPalette::Window).darker(115));
0494     p->drawText(textRect.translated(3, 1), text);
0495     p->setPen(palette().color(QPalette::WindowText));
0496     p->drawText(textRect.translated(2, 0), text);
0497 
0498     p->restore();
0499 }
0500 
0501 void ImageGuideWidget::paintEvent(QPaintEvent*)
0502 {
0503     QPainter p(this);
0504     p.drawPixmap(0, 0, *d->pixmap);
0505 
0506     if (d->enableDrawMask && d->onMouseMovePreviewToggled == false)
0507     {
0508         p.setOpacity(0.7);
0509         p.drawPixmap(d->rect.x(), d->rect.y(), *d->maskPixmap);
0510 
0511         if ((d->renderingPreviewMode == PreviewToolBar::PreviewOriginalImage) ||
0512             ((d->renderingPreviewMode == PreviewToolBar::PreviewToggleOnMouseOver) && !d->onMouseMovePreviewToggled))
0513         {
0514             drawText(&p, QPoint(d->rect.x() + 20, d->rect.y() + 20), beforeLabel.toString());
0515         }
0516         else if ((d->renderingPreviewMode == PreviewToolBar::PreviewTargetImage) ||
0517                  (d->renderingPreviewMode == PreviewToolBar::NoPreviewMode)      ||
0518                  ((d->renderingPreviewMode == PreviewToolBar::PreviewToggleOnMouseOver) && d->onMouseMovePreviewToggled))
0519         {
0520             drawText(&p, QPoint(d->rect.x() + 20, d->rect.y() + 20), afterLabel.toString());
0521         }
0522     }
0523 
0524     p.end();
0525 }
0526 
0527 void ImageGuideWidget::timerEvent(QTimerEvent* e)
0528 {
0529     if (e->timerId() == d->timerID)
0530     {
0531         if (d->flicker == 5)
0532         {
0533             d->flicker = 0;
0534         }
0535         else
0536         {
0537             d->flicker++;
0538         }
0539 
0540         updatePreview();
0541     }
0542     else
0543     {
0544         QWidget::timerEvent(e);
0545     }
0546 }
0547 
0548 void ImageGuideWidget::resizeEvent(QResizeEvent* e)
0549 {
0550     blockSignals(true);
0551     delete d->pixmap;
0552     delete d->previewPixmap;
0553 
0554     int w             = e->size().width();
0555     int h             = e->size().height();
0556     int old_w         = d->preview.width();
0557     int old_h         = d->preview.height();
0558     d->preview        = d->iface->setPreviewSize(QSize(w, h));
0559     d->preview.setIccProfile(d->iface->original() ? d->iface->original()->getIccProfile() : IccProfile());
0560 
0561     d->pixmap         = new QPixmap(w, h);
0562     d->previewPixmap  = new QPixmap(w, h);
0563     d->rect           = QRect(w / 2 - d->preview.width() / 2, h / 2 - d->preview.height() / 2, d->preview.width(), d->preview.height());
0564     *d->maskPixmap    = d->maskPixmap->scaled(d->preview.width(), d->preview.height(), Qt::IgnoreAspectRatio);
0565     *d->previewPixmap = d->iface->convertToPixmap(d->preview);
0566 
0567     d->spot.setX((int)((float)d->spot.x() * ((float)d->preview.width()  / (float)old_w)));
0568     d->spot.setY((int)((float)d->spot.y() * ((float)d->preview.height() / (float)old_h)));
0569     updatePixmap();
0570 
0571     blockSignals(false);
0572     Q_EMIT signalResized();
0573 }
0574 
0575 void ImageGuideWidget::mousePressEvent(QMouseEvent* e)
0576 {
0577     if (e->button() == Qt::LeftButton)
0578     {
0579 
0580 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0581 
0582         if      (!d->focus && d->rect.contains(e->position().toPoint().x(), e->position().toPoint().y()) && d->spotVisible)
0583 
0584 #else
0585 
0586         if      (!d->focus && d->rect.contains(e->x(), e->y()) && d->spotVisible)
0587 
0588 #endif
0589 
0590         {
0591             d->focus = true;
0592 
0593 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0594 
0595             d->spot.setX(e->position().toPoint().x() - d->rect.x());
0596             d->spot.setY(e->position().toPoint().y() - d->rect.y());
0597 
0598 #else
0599 
0600             d->spot.setX(e->x() - d->rect.x());
0601             d->spot.setY(e->y() - d->rect.y());
0602 
0603 #endif
0604 
0605         }
0606         else if (d->enableDrawMask)
0607         {
0608 
0609 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0610 
0611             d->lastPoint   = QPoint(e->position().toPoint().x() - d->rect.x(), e->position().toPoint().y() - d->rect.y());
0612 
0613 #else
0614 
0615             d->lastPoint   = QPoint(e->x() - d->rect.x(), e->y() - d->rect.y());
0616 
0617 #endif
0618 
0619             d->drawingMask = true;
0620         }
0621 
0622         updatePreview();
0623     }
0624 }
0625 
0626 void ImageGuideWidget::mouseReleaseEvent(QMouseEvent* e)
0627 {
0628 
0629 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0630 
0631     if (d->rect.contains(e->position().toPoint().x(), e->position().toPoint().y()))
0632 
0633 #else
0634 
0635     if (d->rect.contains(e->x(), e->y()))
0636 
0637 #endif
0638 
0639     {
0640         if (d->focus && d->spotVisible)
0641         {
0642             d->focus = false;
0643             updatePreview();
0644 
0645 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0646 
0647             d->spot.setX(e->position().toPoint().x() - d->rect.x());
0648             d->spot.setY(e->position().toPoint().y() - d->rect.y());
0649 
0650 #else
0651 
0652             d->spot.setX(e->x() - d->rect.x());
0653             d->spot.setY(e->y() - d->rect.y());
0654 
0655 #endif
0656 
0657             DColor color;
0658 /*
0659             QPoint point = getSpotPosition();
0660 */
0661             if      (d->renderingPreviewMode == PreviewToolBar::PreviewOriginalImage)
0662             {
0663                 color = getSpotColor(OriginalImage);
0664                 Q_EMIT spotPositionChangedFromOriginal(color, d->spot);
0665             }
0666             else if ((d->renderingPreviewMode == PreviewToolBar::PreviewTargetImage) ||
0667                      (d->renderingPreviewMode == PreviewToolBar::NoPreviewMode))
0668             {
0669                 color = getSpotColor(TargetPreviewImage);
0670                 Q_EMIT spotPositionChangedFromTarget(color, d->spot);
0671             }
0672             else if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVert)
0673             {
0674                 if (d->spot.x() > (d->rect.width() / 2))
0675                 {
0676                     color = getSpotColor(TargetPreviewImage);
0677                     Q_EMIT spotPositionChangedFromTarget(color, QPoint(d->spot.x() - d->rect.width() / 2,
0678                                                                      d->spot.y()));
0679                 }
0680                 else
0681                 {
0682                     color = getSpotColor(OriginalImage);
0683                     Q_EMIT spotPositionChangedFromOriginal(color, d->spot);
0684                 }
0685             }
0686             else if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesVertCont)
0687             {
0688                 if (d->spot.x() > (d->rect.width() / 2))
0689                 {
0690                     color = getSpotColor(TargetPreviewImage);
0691                     Q_EMIT spotPositionChangedFromTarget(color, d->spot);
0692                 }
0693                 else
0694                 {
0695                     color = getSpotColor(OriginalImage);
0696                     Q_EMIT spotPositionChangedFromOriginal(color, d->spot);
0697                 }
0698             }
0699             else if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorz)
0700             {
0701                 if (d->spot.y() > (d->rect.height() / 2))
0702                 {
0703                     color = getSpotColor(TargetPreviewImage);
0704                     Q_EMIT spotPositionChangedFromTarget(color, QPoint(d->spot.x(),
0705                                                                      d->spot.y() - d->rect.height() / 2));
0706                 }
0707                 else
0708                 {
0709                     color = getSpotColor(OriginalImage);
0710                     Q_EMIT spotPositionChangedFromOriginal(color, d->spot);
0711                 }
0712             }
0713             else if (d->renderingPreviewMode == PreviewToolBar::PreviewBothImagesHorzCont)
0714             {
0715                 if (d->spot.y() > (d->rect.height() / 2))
0716                 {
0717                     color = getSpotColor(TargetPreviewImage);
0718                     Q_EMIT spotPositionChangedFromTarget(color, d->spot);
0719                 }
0720                 else
0721                 {
0722                     color = getSpotColor(OriginalImage);
0723                     Q_EMIT spotPositionChangedFromOriginal(color, d->spot);
0724                 }
0725             }
0726         }
0727         else if (e->button() == Qt::LeftButton && d->drawingMask)
0728         {
0729             d->drawingMask = false;
0730             updatePreview();
0731         }
0732     }
0733 }
0734 
0735 void ImageGuideWidget::mouseMoveEvent(QMouseEvent* e)
0736 {
0737 
0738 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0739 
0740     if (d->rect.contains(e->position().toPoint().x(), e->position().toPoint().y()))
0741 
0742 #else
0743 
0744     if (d->rect.contains(e->x(), e->y()))
0745 
0746 #endif
0747 
0748     {
0749         if      (d->focus && d->spotVisible)
0750         {
0751             setCursor(Qt::CrossCursor);
0752 
0753 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0754 
0755             d->spot.setX(e->position().toPoint().x() - d->rect.x());
0756             d->spot.setY(e->position().toPoint().y() - d->rect.y());
0757 
0758 #else
0759 
0760             d->spot.setX(e->x() - d->rect.x());
0761             d->spot.setY(e->y() - d->rect.y());
0762 
0763 #endif
0764 
0765         }
0766         else if (d->enableDrawMask)
0767         {
0768             setCursor(d->maskCursor);
0769 
0770             if ((e->buttons() & Qt::LeftButton) && d->drawingMask)
0771             {
0772 
0773 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0774 
0775                 QPoint currentPos = QPoint(e->position().toPoint().x() - d->rect.x(), e->position().toPoint().y() - d->rect.y());
0776 
0777 #else
0778 
0779                 QPoint currentPos = QPoint(e->x() - d->rect.x(), e->y() - d->rect.y());
0780 
0781 #endif
0782 
0783                 drawLineTo(currentPos);
0784                 updatePreview();
0785             }
0786         }
0787     }
0788     else
0789     {
0790         unsetCursor();
0791     }
0792 }
0793 
0794 
0795 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0796 
0797 void ImageGuideWidget::enterEvent(QEnterEvent* event)
0798 
0799 #else
0800 
0801 void ImageGuideWidget::enterEvent(QEvent* event)
0802 
0803 #endif
0804 
0805 {
0806     Q_UNUSED(event);
0807 
0808     if (!d->focus && (d->renderingPreviewMode == PreviewToolBar::PreviewToggleOnMouseOver))
0809     {
0810         d->onMouseMovePreviewToggled = false;
0811         updatePixmap();
0812         repaint();
0813     }
0814 }
0815 
0816 void ImageGuideWidget::leaveEvent(QEvent*)
0817 {
0818     if (!d->focus && (d->renderingPreviewMode == PreviewToolBar::PreviewToggleOnMouseOver))
0819     {
0820         d->onMouseMovePreviewToggled = true;
0821         updatePixmap();
0822         update();
0823     }
0824 }
0825 
0826 void ImageGuideWidget::setPoints(const QPolygon& p, bool drawLine)
0827 {
0828     d->selectedPoints        = p;
0829     d->drawLineBetweenPoints = drawLine;
0830     updatePreview();
0831 }
0832 
0833 void ImageGuideWidget::resetPoints()
0834 {
0835     d->selectedPoints.clear();
0836 }
0837 
0838 void ImageGuideWidget::drawLineTo(const QPoint& endPoint)
0839 {
0840     drawLineTo(d->penWidth, d->eraseMask, d->paintColor, d->lastPoint, endPoint);
0841 }
0842 
0843 void ImageGuideWidget::drawLineTo(int width, bool erase, const QColor& color, const QPoint& start, const QPoint& end)
0844 {
0845 
0846     QPainter painter(d->maskPixmap);
0847 
0848     if (erase)
0849     {
0850         // drawLine() seems to ignore composition modes, use a tmp pixmap and combine it later on
0851 
0852         QPixmap tmpMask(d->maskPixmap->width(), d->maskPixmap->height());
0853         tmpMask.fill(Qt::transparent);
0854         QPainter tmpPainter(&tmpMask);
0855 
0856         painter.setRenderHint(QPainter::Antialiasing, false);
0857         painter.setCompositionMode(QPainter::CompositionMode_DestinationOut);
0858 
0859         QPen eraser;
0860         eraser.setColor(Qt::yellow);
0861         eraser.setStyle(Qt::SolidLine);
0862         eraser.setWidth(width);
0863         eraser.setCapStyle(Qt::RoundCap);
0864         eraser.setJoinStyle(Qt::RoundJoin);
0865 
0866         tmpPainter.setPen(eraser);
0867         tmpPainter.setBrush(QBrush());
0868         tmpPainter.drawLine(start, end);
0869         tmpPainter.end();
0870 
0871         painter.drawPixmap(0, 0, tmpMask);
0872     }
0873     else
0874     {
0875         painter.setPen(QPen(color, width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
0876         painter.drawLine(start, end);
0877     }
0878 
0879     int rad      = (width / 2) + 2;
0880 
0881     update(QRect(start, end).normalized().adjusted(-rad, -rad, +rad, +rad));
0882     d->lastPoint = end;
0883 
0884     painter.end();
0885 }
0886 
0887 void ImageGuideWidget::setPaintColor(const QColor& color)
0888 {
0889     d->paintColor = color;
0890 }
0891 
0892 void ImageGuideWidget::setMaskEnabled(bool enabled)
0893 {
0894     d->enableDrawMask = enabled;
0895     unsetCursor();
0896     updatePreview();
0897 }
0898 
0899 void ImageGuideWidget::setEraseMode(bool erase)
0900 {
0901     d->eraseMask = erase;
0902 }
0903 
0904 QImage ImageGuideWidget::getMask() const
0905 {
0906     QImage mask = d->maskPixmap->toImage();
0907     return mask;
0908 }
0909 
0910 QPoint ImageGuideWidget::translatePointPosition(const QPoint& point) const
0911 {
0912     int x = d->rect.x() + 1 + (int)(point.x() * (float)d->preview.width()  /
0913                                                 (float)d->iface->originalSize().width());
0914     int y = d->rect.y() + 1 + (int)(point.y() * (float)d->preview.height() /
0915                                                 (float)d->iface->originalSize().height());
0916 
0917     return (QPoint(x, y));
0918 }
0919 
0920 void ImageGuideWidget::setMaskPenSize(int size)
0921 {
0922     d->penWidth = size;
0923     updateMaskCursor();
0924 }
0925 
0926 void ImageGuideWidget::updateMaskCursor()
0927 {
0928     int size = d->penWidth;
0929 
0930     if (size > 64)
0931     {
0932         size = 64;
0933     }
0934 
0935     if (size < 3)
0936     {
0937         size = 3;
0938     }
0939 
0940     QPixmap pix(size, size);
0941     pix.fill(Qt::transparent);
0942 
0943     QPainter p(&pix);
0944     p.setRenderHint(QPainter::Antialiasing, true);
0945 
0946     p.drawEllipse(1, 1, size - 2, size - 2);
0947 
0948     d->maskCursor = QCursor(pix);
0949 }
0950 
0951 void ImageGuideWidget::setSpotPosition(const QPoint& point)
0952 {
0953     d->spot.setX(point.x());
0954     d->spot.setY(point.y());
0955     updatePreview();
0956 }
0957 
0958 void ImageGuideWidget::updateSpotPosition(int x, int y)
0959 {
0960     QPoint origin = d->rect.topLeft();
0961     x            -= origin.x();
0962     y            -= origin.y();
0963     d->spot.setX(x);
0964     d->spot.setY(y);
0965     updatePreview();
0966 }
0967 
0968 QPoint ImageGuideWidget::translateItemPosition(const QPoint& point, bool src) const
0969 {
0970     int x = (int)(point.x() * (float)d->preview.width()  /
0971                               (float) d->iface->originalSize().width());
0972     int y = (int)(point.y() * (float)d->preview.height() /
0973                               (float) d->iface->originalSize().height());
0974 
0975     if (!src)
0976     {
0977         x  = (int)(point.x());
0978         y  = (int)(point.y());
0979         x -= (int)(d->rect.topLeft().x()) + 1;
0980         y -= (int)(d->rect.topLeft().y()) + 1;
0981     }
0982 
0983     return (QPoint(x, y));
0984 }
0985 
0986 void ImageGuideWidget::setMaskCursor()
0987 {
0988     if (d->enableDrawMask)
0989     {
0990         updateMaskCursor();
0991         setCursor(d->maskCursor);
0992         updatePreview();
0993     }
0994 }
0995 
0996 } // namespace Digikam
0997 
0998 #include "moc_imageguidewidget.cpp"