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"