File indexing completed on 2025-01-19 03:51:07
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2005-02-14 0007 * Description : a widget to insert a text over an image. 0008 * 0009 * SPDX-FileCopyrightText: 2005-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2006-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "inserttextwidget.h" 0017 0018 // Qt includes 0019 0020 #include <QFontMetrics> 0021 #include <QPainter> 0022 0023 namespace DigikamEditorInsertTextToolPlugin 0024 { 0025 0026 class Q_DECL_HIDDEN InsertTextWidget::Private 0027 { 0028 public: 0029 0030 explicit Private() 0031 : currentMoving (false), 0032 textBorder (false), 0033 textTransparent (false), 0034 alignMode (0), 0035 textOpacity (0), 0036 h (0), 0037 textRotation (0), 0038 transparency (0), 0039 w (0), 0040 xpos (0), 0041 ypos (0), 0042 pixmap (nullptr), 0043 iface (nullptr) 0044 { 0045 } 0046 0047 bool currentMoving; 0048 bool textBorder; 0049 bool textTransparent; 0050 0051 int alignMode; 0052 int textOpacity; 0053 int h; 0054 int textRotation; 0055 int transparency; 0056 int w; 0057 int xpos; 0058 int ypos; 0059 0060 QColor backgroundColor; // For text 0061 QColor bgColor; // For Pixmap 0062 QColor textColor; 0063 0064 QFont textFont; 0065 0066 QPixmap* pixmap; 0067 0068 QRect positionHint; 0069 QRect rect; 0070 QRect textRect; 0071 0072 QString textString; 0073 0074 ImageIface* iface; 0075 }; 0076 0077 InsertTextWidget::InsertTextWidget(int w, int h, QWidget* const parent) 0078 : QWidget(parent), 0079 d (new Private) 0080 { 0081 d->currentMoving = false; 0082 d->bgColor = palette().color(QPalette::Window); 0083 d->backgroundColor = QColor(0xCC, 0xCC, 0xCC); 0084 d->transparency = 210; 0085 0086 d->iface = new ImageIface(QSize(w, h)); 0087 d->w = d->iface->previewSize().width(); 0088 d->h = d->iface->previewSize().height(); 0089 d->pixmap = new QPixmap(w, h); 0090 d->pixmap->fill(d->bgColor); 0091 0092 setMinimumSize(w, h); 0093 setMouseTracking(true); 0094 setAttribute(Qt::WA_DeleteOnClose); 0095 0096 d->rect = QRect(width()/2-d->w/2, height()/2-d->h/2, d->w, d->h); 0097 d->textRect = QRect(); 0098 } 0099 0100 InsertTextWidget::~InsertTextWidget() 0101 { 0102 delete d->iface; 0103 delete d->pixmap; 0104 delete d; 0105 } 0106 0107 ImageIface* InsertTextWidget::imageIface() const 0108 { 0109 return d->iface; 0110 } 0111 0112 void InsertTextWidget::resetEdit() 0113 { 0114 // signal this needs to be filled by makePixmap 0115 0116 d->textRect = QRect(); 0117 makePixmap(); 0118 repaint(); 0119 } 0120 0121 void InsertTextWidget::setText(const QString& text, const QFont& font, const QColor& color, int opacity, 0122 int alignMode, bool border, bool transparent, int rotation) 0123 { 0124 d->textString = text; 0125 d->textColor = color; 0126 d->textOpacity = opacity; 0127 d->textBorder = border; 0128 d->textTransparent = transparent; 0129 d->textRotation = rotation; 0130 0131 switch (alignMode) 0132 { 0133 case ALIGN_LEFT: 0134 d->alignMode = Qt::AlignLeft; 0135 break; 0136 0137 case ALIGN_RIGHT: 0138 d->alignMode = Qt::AlignRight; 0139 break; 0140 0141 case ALIGN_CENTER: 0142 d->alignMode = Qt::AlignHCenter; 0143 break; 0144 0145 case ALIGN_BLOCK: 0146 d->alignMode = Qt::AlignJustify; 0147 break; 0148 } 0149 0150 // Center text if top left corner text area is not visible. 0151 0152 /* 0153 if (d->textFont.pointSize() != font.pointSize() && 0154 !rect().contains( d->textRect.x(), d->textRect.y())) 0155 { 0156 d->textFont = font; 0157 resetEdit(); 0158 return; 0159 } 0160 */ 0161 0162 d->textFont = font; 0163 0164 makePixmap(); 0165 repaint(); 0166 } 0167 0168 void InsertTextWidget::setBackgroundColor(const QColor& bg) 0169 { 0170 d->bgColor = bg; 0171 makePixmap(); 0172 repaint(); 0173 } 0174 0175 void InsertTextWidget::setPositionHint(const QRect& hint) 0176 { 0177 // interpreted by composeImage 0178 0179 d->positionHint = hint; 0180 0181 if (d->textRect.isValid()) 0182 { 0183 // invalidate current position so that hint is certainly interpreted 0184 0185 d->textRect = QRect(); 0186 makePixmap(); 0187 repaint(); 0188 } 0189 } 0190 0191 QRect InsertTextWidget::getPositionHint() const 0192 { 0193 QRect hint; 0194 0195 if (d->textRect.isValid()) 0196 { 0197 // We normalize on the size of the image, but we store as int. Precision loss is no problem. 0198 0199 hint.setX( (int) ((float)(d->textRect.x() - d->rect.x()) / (float)d->rect.width() * 10000.0)); 0200 hint.setY( (int) ((float)(d->textRect.y() - d->rect.y()) / (float)d->rect.height() * 10000.0)); 0201 hint.setWidth( (int) ((float)d->textRect.width() / (float)d->rect.width() * 10000.0)); 0202 hint.setHeight((int) ((float)d->textRect.height() / (float)d->rect.height() * 10000.0)); 0203 } 0204 0205 return hint; 0206 } 0207 0208 DImg InsertTextWidget::makeInsertText() 0209 { 0210 int orgW = d->iface->originalSize().width(); 0211 int orgH = d->iface->originalSize().height(); 0212 float ratioW = (float)orgW/(float)d->w; 0213 float ratioH = (float)orgH/(float)d->h; 0214 0215 int x, y; 0216 0217 if (d->textRect.isValid()) 0218 { 0219 // convert from widget to image coordinates, then to original size 0220 0221 x = qRound((d->textRect.x() - d->rect.x()) * ratioW); 0222 y = qRound((d->textRect.y() - d->rect.y()) * ratioH); 0223 } 0224 else 0225 { 0226 x = -1; 0227 y = -1; 0228 } 0229 0230 // Get original image 0231 0232 DImg image = d->iface->original()->copy(); 0233 int borderWidth = qMax(1, qRound(ratioW)); 0234 0235 // compose and draw result on image 0236 0237 composeImage(&image, nullptr, x, y, 0238 d->textFont, d->textFont.pointSizeF(), 0239 d->textRotation, d->textColor, d->textOpacity, 0240 d->alignMode, d->textString, d->textTransparent, d->backgroundColor, 0241 d->textBorder ? BORDER_NORMAL : BORDER_NONE, borderWidth, borderWidth); 0242 0243 return image; 0244 } 0245 0246 void InsertTextWidget::makePixmap() 0247 { 0248 int orgW = d->iface->originalSize().width(); 0249 int orgH = d->iface->originalSize().height(); 0250 float ratioW = (float)d->w / (float)orgW; 0251 float ratioH = (float)d->h / (float)orgH; 0252 0253 int x, y; 0254 0255 if (d->textRect.isValid()) 0256 { 0257 // convert from widget to image coordinates 0258 0259 x = d->textRect.x() - d->rect.x(); 0260 y = d->textRect.y() - d->rect.y(); 0261 } 0262 else 0263 { 0264 x = -1; 0265 y = -1; 0266 } 0267 0268 // get preview image data 0269 0270 DImg image = d->iface->preview(); 0271 image.setIccProfile(d->iface->original()->getIccProfile()); 0272 0273 // paint pixmap for drawing this widget 0274 // First, fill with background color 0275 0276 d->pixmap->fill(d->bgColor); 0277 QPainter p(d->pixmap); 0278 0279 // Convert image to pixmap and draw it 0280 0281 QPixmap imagePixmap = d->iface->convertToPixmap(image); 0282 p.drawPixmap(d->rect.x(), d->rect.y(), 0283 imagePixmap, 0, 0, imagePixmap.width(), imagePixmap.height()); 0284 0285 // prepare painter for use by compose image 0286 0287 p.setClipRect(d->rect); 0288 p.translate(d->rect.x(), d->rect.y()); 0289 0290 int borderWidth = qMax(1, qRound(ratioW)); 0291 0292 // compose image and draw result directly on pixmap, with correct offset 0293 0294 QRect textRect = composeImage(&image, &p, x, y, 0295 d->textFont, d->textFont.pointSizeF(), 0296 d->textRotation, d->textColor, d->textOpacity, 0297 d->alignMode, d->textString, d->textTransparent, d->backgroundColor, 0298 d->textBorder ? BORDER_NORMAL : BORDER_SUPPORT, borderWidth, borderWidth, 0299 (ratioW > ratioH) ? ratioW : ratioH); 0300 0301 p.end(); 0302 0303 // store new text rectangle 0304 // convert from image to widget coordinates 0305 0306 d->textRect.setX(textRect.x() + d->rect.x()); 0307 d->textRect.setY(textRect.y() + d->rect.y()); 0308 d->textRect.setSize(textRect.size()); 0309 } 0310 0311 /** 0312 Take data from image, draw text at x|y with specified parameters. 0313 If destPainter is null, draw to image, 0314 if destPainter is not null, draw directly using the painter. 0315 Returns modified area of image. 0316 */ 0317 QRect InsertTextWidget::composeImage(DImg* const image, QPainter* const destPainter, 0318 int x, int y, 0319 QFont font, float pointSize, int textRotation, QColor textColor, 0320 int textOpacity, int alignMode, const QString& textString, 0321 bool transparentBackground, QColor backgroundColor, 0322 BorderMode borderMode, int borderWidth, int spacing, float fontScale) 0323 { 0324 /* 0325 The problem we have to solve is that we have no pixel access to font rendering, 0326 we have to let Qt do the drawing. On the other hand we need to support 16 bit, which 0327 cannot be done with QPixmap. 0328 The current solution cuts out the text area, lets Qt do its drawing, converts back and blits to original. 0329 */ 0330 0331 int maxWidth, maxHeight; 0332 0333 if (x == -1 && y == -1) 0334 { 0335 maxWidth = image->width(); 0336 maxHeight = image->height(); 0337 } 0338 else 0339 { 0340 maxWidth = image->width() - x; 0341 maxHeight = image->height() - y; 0342 } 0343 0344 fontScale = qMax(0.01f, fontScale); 0345 0346 // find out size of the area that we are drawing to 0347 0348 font.setPointSizeF(pointSize); 0349 QFontMetrics fontMt(font); 0350 QRect fontRect = fontMt.boundingRect(0, 0, 0351 qRound(maxWidth / fontScale), 0352 qRound(maxHeight / fontScale), 0353 alignMode, textString); 0354 0355 fontRect.setWidth(qRound(fontRect.width() * fontScale)); 0356 fontRect.setHeight(qRound(fontRect.height() * fontScale)); 0357 0358 if (!fontRect.isValid()) 0359 { 0360 return QRect(); 0361 } 0362 0363 int fontWidth, fontHeight; 0364 0365 switch (textRotation) 0366 { 0367 case ROTATION_NONE: 0368 case ROTATION_180: 0369 default: 0370 fontWidth = fontRect.width(); 0371 fontHeight = fontRect.height(); 0372 break; 0373 0374 case ROTATION_90: 0375 case ROTATION_270: 0376 fontWidth = fontRect.height(); 0377 fontHeight = fontRect.width(); 0378 break; 0379 } 0380 0381 // x, y == -1 means that we have to find a good initial position for the text here 0382 0383 if ((x == -1) && (y == -1)) 0384 { 0385 int boxWidth = fontWidth + 2 * borderWidth + 2 * spacing; 0386 int boxHeight = fontHeight + 2 * borderWidth + 2 * spacing; 0387 0388 // was a valid position hint stored from last use? 0389 0390 if (d->positionHint.isValid()) 0391 { 0392 // We assume that people tend to orient text along the edges, 0393 // so we do some guessing so that positions such as "in the lower right corner" 0394 // will be remembered across different image sizes. 0395 0396 // get relative positions 0397 0398 float fromTop = (float)d->positionHint.top() / 10000.0; 0399 float fromBottom = 1.0 - (float)d->positionHint.bottom() / 10000.0; 0400 float fromLeft = (float)d->positionHint.left() / 10000.0; 0401 float fromRight = 1.0 - (float)d->positionHint.right() / 10000.0; 0402 0403 // calculate horizontal position 0404 0405 if (fromLeft < fromRight) 0406 { 0407 x = qRound(fromLeft * maxWidth); 0408 0409 // we are placing from the smaller distance, 0410 // so if now the larger distance is actually too small, 0411 // fall back to standard placement, nothing to lose. 0412 0413 if ((x + boxWidth) > maxWidth) 0414 { 0415 x = qMax( (maxWidth - boxWidth) / 2, 0); 0416 } 0417 } 0418 else 0419 { 0420 x = maxWidth - qRound(fromRight * maxWidth) - boxWidth; 0421 0422 if (x < 0) 0423 { 0424 x = qMax( (maxWidth - boxWidth) / 2, 0); 0425 } 0426 } 0427 0428 // calculate vertical position 0429 0430 if (fromTop < fromBottom) 0431 { 0432 y = qRound(fromTop * maxHeight); 0433 0434 if (y + boxHeight > maxHeight) 0435 { 0436 y = qMax( (maxHeight - boxHeight) / 2, 0); 0437 } 0438 } 0439 else 0440 { 0441 y = maxHeight - qRound(fromBottom * maxHeight) - boxHeight; 0442 0443 if (y < 0) 0444 { 0445 y = qMax( (maxHeight - boxHeight) / 2, 0); 0446 } 0447 } 0448 0449 if (!QRect(x, y, boxWidth, boxHeight). 0450 intersects(QRect(0, 0, maxWidth, maxHeight))) 0451 { 0452 // emergency fallback - nothing is visible 0453 0454 x = qMax( (maxWidth - boxWidth) / 2, 0); 0455 y = qMax( (maxHeight - boxHeight) / 2, 0); 0456 } 0457 0458 // invalidate position hint, use only once 0459 0460 d->positionHint = QRect(); 0461 } 0462 else 0463 { 0464 // use standard position 0465 0466 x = qMax( (maxWidth - boxWidth) / 2, 0); 0467 y = qMax( (maxHeight - boxHeight) / 2, 0); 0468 } 0469 } 0470 0471 // create a rectangle relative to image 0472 0473 QRect drawRect(x, y, fontWidth + 2 * borderWidth + 2 * spacing, fontHeight + 2 * borderWidth + 2 * spacing); 0474 0475 // create a rectangle relative to textArea, excluding the border 0476 0477 QRect textAreaBackgroundRect(borderWidth, borderWidth, fontWidth + 2 * spacing, fontHeight + 2 * spacing); 0478 0479 // create a rectangle relative to textArea, excluding the border and spacing 0480 0481 QRect textAreaTextRect(borderWidth + spacing, borderWidth + spacing, fontWidth, fontHeight); 0482 0483 // create a rectangle relative to textArea, including the border, 0484 // for drawing the rectangle, taking into account that the width of the QPen goes in and out in equal parts 0485 0486 QRect textAreaDrawRect(borderWidth / 2, borderWidth / 2, fontWidth + borderWidth + 2 * spacing, 0487 fontHeight + borderWidth + 2 * spacing); 0488 0489 // cut out the text area 0490 0491 DImg textArea = image->copy(drawRect); 0492 0493 if (textArea.isNull()) 0494 { 0495 return QRect(); 0496 } 0497 0498 // compose semi-transparent background over textArea 0499 0500 DColorComposer* const composer = DColorComposer::getComposer(DColorComposer::PorterDuffNone); 0501 0502 if (transparentBackground) 0503 { 0504 DImg transparentLayer(textAreaBackgroundRect.width(), textAreaBackgroundRect.height(), textArea.sixteenBit(), true); 0505 DColor transparent(backgroundColor); 0506 transparent.setAlpha(d->transparency); 0507 0508 if (image->sixteenBit()) 0509 { 0510 transparent.convertToSixteenBit(); 0511 } 0512 0513 transparentLayer.fill(transparent); 0514 textArea.bitBlendImage(composer, &transparentLayer, 0, 0, transparentLayer.width(), transparentLayer.height(), 0515 textAreaBackgroundRect.x(), textAreaBackgroundRect.y()); 0516 } 0517 0518 DImg textNotDrawn; 0519 0520 if (textArea.sixteenBit()) 0521 { 0522 textNotDrawn = textArea.copy(); 0523 textNotDrawn.convertToEightBit(); 0524 } 0525 else 0526 { 0527 textNotDrawn = textArea; 0528 } 0529 0530 // We have no direct pixel access to font rendering, so now we need to use Qt/X11 for the drawing 0531 0532 // convert text area to pixmap 0533 0534 QPixmap pixmap; 0535 0536 if (destPainter) 0537 { 0538 // We working on tool preview, deal with CM as well 0539 0540 pixmap = d->iface->convertToPixmap(textNotDrawn); 0541 } 0542 else 0543 { 0544 // We working on target image. Do no apply double CM adjustment here. 0545 0546 pixmap = textNotDrawn.convertToPixmap(); 0547 } 0548 0549 int fontScaleWidth = qRound(fontWidth / fontScale); 0550 int fontScaleHeight = qRound(fontHeight / fontScale); 0551 0552 QPixmap textPixmap(fontScaleWidth, fontScaleHeight); 0553 textPixmap.fill(Qt::transparent); 0554 0555 QPainter tp(&textPixmap); 0556 tp.setOpacity((qreal)textOpacity / 100.0); 0557 tp.setPen(QPen(textColor, 1)); 0558 tp.setFont(font); 0559 0560 switch (textRotation) 0561 { 0562 case ROTATION_NONE: 0563 tp.drawText(0, 0, fontScaleWidth, fontScaleHeight, 0564 alignMode, textString); 0565 break; 0566 case ROTATION_90: 0567 tp.translate(fontScaleWidth, 0); 0568 tp.rotate(90.0); 0569 tp.drawText(0, 0, fontScaleHeight, fontScaleWidth, 0570 alignMode, textString); 0571 break; 0572 case ROTATION_180: 0573 tp.translate(fontScaleWidth, fontScaleHeight); 0574 tp.rotate(180.0); 0575 tp.drawText(0, 0, fontScaleWidth, fontScaleHeight, 0576 alignMode, textString); 0577 break; 0578 case ROTATION_270: 0579 tp.translate(0, fontScaleHeight); 0580 tp.rotate(270.0); 0581 tp.drawText(0, 0, fontScaleHeight, fontScaleWidth, 0582 alignMode, textString); 0583 break; 0584 } 0585 0586 tp.end(); 0587 0588 // paint on pixmap 0589 0590 QPainter p(&pixmap); 0591 0592 p.drawPixmap(textAreaTextRect, textPixmap.scaled(fontWidth, 0593 fontHeight, 0594 Qt::IgnoreAspectRatio, 0595 Qt::SmoothTransformation)); 0596 // Drawing rectangle around text. 0597 0598 if (borderMode == BORDER_NORMAL) // Decorative border using text color. 0599 { 0600 p.setOpacity((qreal)textOpacity / 100.0); 0601 p.setPen(QPen(textColor, borderWidth, Qt::SolidLine, 0602 Qt::SquareCap, Qt::RoundJoin)); 0603 p.drawRect(textAreaDrawRect); 0604 } 0605 else if (borderMode == BORDER_SUPPORT) // Make simple dot line border to help user. 0606 { 0607 p.setPen(QPen(Qt::white, 1, Qt::SolidLine)); 0608 p.drawRect(textAreaDrawRect); 0609 p.setPen(QPen(Qt::red, 1, Qt::DotLine)); 0610 p.drawRect(textAreaDrawRect); 0611 } 0612 0613 p.end(); 0614 0615 if (!destPainter) 0616 { 0617 // convert to QImage, then to DImg 0618 0619 QImage pixmapImage = pixmap.toImage(); 0620 DImg textDrawn(pixmapImage.width(), pixmapImage.height(), false, true, pixmapImage.bits()); 0621 0622 // This does not work: during the conversion, colors are altered significantly (diffs of 1 to 10 in each component), 0623 // so we cannot find out which pixels have actually been touched. 0624 /* 0625 // Compare the result of drawing with the previous version. 0626 // Set all unchanged pixels to transparent 0627 DColor color, ncolor; 0628 uchar *ptr, *nptr; 0629 ptr = textDrawn.bits(); 0630 nptr = textNotDrawn.bits(); 0631 int bytesDepth = textDrawn.bytesDepth(); 0632 int numPixels = textDrawn.width() * textDrawn.height(); 0633 for (int i = 0; i < numPixels; ++i, ptr+= bytesDepth, nptr += bytesDepth) 0634 { 0635 color.setColor(ptr, false); 0636 ncolor.setColor(nptr, false); 0637 if (color.red() == ncolor.red() && 0638 color.green() == ncolor.green() && 0639 color.blue() == ncolor.blue()) 0640 { 0641 color.setAlpha(0); 0642 color.setPixel(ptr); 0643 } 0644 } 0645 // convert to 16 bit if needed 0646 */ 0647 textDrawn.convertToDepthOfImage(&textArea); 0648 0649 // now compose to original: only pixels affected by drawing text and border are changed, not whole area 0650 0651 textArea.bitBlendImage(composer, &textDrawn, 0, 0, textDrawn.width(), textDrawn.height(), 0, 0); 0652 0653 // copy result to original image 0654 0655 image->bitBltImage(&textArea, drawRect.x(), drawRect.y()); 0656 } 0657 else 0658 { 0659 destPainter->drawPixmap(drawRect.x(), drawRect.y(), pixmap, 0, 0, pixmap.width(), pixmap.height()); 0660 } 0661 0662 delete composer; 0663 0664 return drawRect; 0665 } 0666 0667 void InsertTextWidget::paintEvent(QPaintEvent*) 0668 { 0669 QPainter p(this); 0670 p.drawPixmap(0, 0, *d->pixmap); 0671 p.end(); 0672 } 0673 0674 void InsertTextWidget::resizeEvent(QResizeEvent* e) 0675 { 0676 blockSignals(true); 0677 delete d->pixmap; 0678 0679 int w = e->size().width(); 0680 int h = e->size().height(); 0681 0682 int textX = d->textRect.x() - d->rect.x(); 0683 int textY = d->textRect.y() - d->rect.y(); 0684 int old_w = d->w; 0685 int old_h = d->h; 0686 d->iface->setPreviewSize(QSize(w, h)); 0687 d->w = d->iface->previewSize().width(); 0688 d->h = d->iface->previewSize().height(); 0689 0690 d->pixmap = new QPixmap(w, h); 0691 d->rect = QRect(w/2-d->w/2, h/2-d->h/2, d->w, d->h); 0692 0693 if (d->textRect.isValid()) 0694 { 0695 int textWidth = d->textRect.width(); 0696 int textHeight = d->textRect.height(); 0697 0698 textX = qRound(textX * (float)d->w / (float)old_w); 0699 textY = qRound(textY * (float)d->h / (float)old_h); 0700 textWidth = qRound(textWidth * (float)d->w / (float)old_w); 0701 textHeight = qRound(textHeight * (float)d->h / (float)old_h); 0702 0703 d->textRect.setX(textX + d->rect.x()); 0704 d->textRect.setY(textY + d->rect.y()); 0705 d->textRect.setWidth(textWidth); 0706 d->textRect.setHeight(textHeight); 0707 makePixmap(); 0708 } 0709 0710 blockSignals(false); 0711 } 0712 0713 void InsertTextWidget::mousePressEvent(QMouseEvent* e) 0714 { 0715 if (e->button() == Qt::LeftButton && 0716 0717 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0718 0719 d->textRect.contains(e->position().toPoint().x(), e->position().toPoint().y())) 0720 { 0721 d->xpos = e->position().toPoint().x(); 0722 d->ypos = e->position().toPoint().y(); 0723 0724 #else 0725 0726 d->textRect.contains(e->x(), e->y())) 0727 { 0728 d->xpos = e->x(); 0729 d->ypos = e->y(); 0730 0731 #endif 0732 0733 setCursor(Qt::SizeAllCursor); 0734 d->currentMoving = true; 0735 } 0736 } 0737 0738 void InsertTextWidget::mouseReleaseEvent(QMouseEvent*) 0739 { 0740 setCursor(Qt::ArrowCursor); 0741 d->currentMoving = false; 0742 } 0743 0744 void InsertTextWidget::mouseMoveEvent(QMouseEvent* e) 0745 { 0746 0747 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0748 0749 if (rect().contains(e->position().toPoint().x(), e->position().toPoint().y())) 0750 0751 #else 0752 0753 if (rect().contains(e->x(), e->y())) 0754 0755 #endif 0756 0757 { 0758 if (e->buttons() == Qt::LeftButton && d->currentMoving) 0759 { 0760 0761 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0762 0763 uint newxpos = e->position().toPoint().x(); 0764 uint newypos = e->position().toPoint().y(); 0765 0766 #else 0767 uint newxpos = e->x(); 0768 uint newypos = e->y(); 0769 0770 #endif 0771 0772 d->textRect.translate(newxpos - d->xpos, newypos - d->ypos); 0773 0774 if (d->textRect.x() - d->rect.x() < 0) 0775 { 0776 d->textRect.setX(d->rect.x()); 0777 } 0778 0779 if (d->textRect.y() - d->rect.y() < 0) 0780 { 0781 d->textRect.setY(d->rect.y()); 0782 } 0783 0784 makePixmap(); 0785 repaint(); 0786 0787 d->xpos = newxpos; 0788 d->ypos = newypos; 0789 setCursor(Qt::PointingHandCursor); 0790 } 0791 0792 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0793 0794 else if (d->textRect.contains(e->position().toPoint().x(), e->position().toPoint().y())) 0795 0796 #else 0797 0798 else if (d->textRect.contains(e->x(), e->y())) 0799 0800 #endif 0801 0802 { 0803 setCursor(Qt::SizeAllCursor); 0804 } 0805 else 0806 { 0807 setCursor(Qt::ArrowCursor); 0808 } 0809 } 0810 } 0811 0812 } // namespace DigikamEditorInsertTextToolPlugin 0813 0814 #include "moc_inserttextwidget.cpp"