1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2005-02-14
7 * Description : a widget to insert a text over an image.
8 *
9 * Copyright (C) 2005-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
10 * Copyright (C) 2006-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
11 *
12 * This program is free software; you can redistribute it
13 * and/or modify it under the terms of the GNU General
14 * Public License as published by the Free Software Foundation;
15 * either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * ============================================================ */
24
25 #include "inserttextwidget.h"
26
27 // Qt includes
28
29 #include <QFont>
30 #include <QFontMetrics>
31 #include <QMouseEvent>
32 #include <QPaintEvent>
33 #include <QPainter>
34 #include <QPixmap>
35 #include <QResizeEvent>
36
37 namespace DigikamEditorInsertTextToolPlugin
38 {
39
40 class Q_DECL_HIDDEN InsertTextWidget::Private
41 {
42 public:
43
Private()44 explicit Private()
45 : currentMoving (false),
46 textBorder (false),
47 textTransparent (false),
48 alignMode (0),
49 textOpacity (0),
50 h (0),
51 textRotation (0),
52 transparency (0),
53 w (0),
54 xpos (0),
55 ypos (0),
56 pixmap (nullptr),
57 iface (nullptr)
58 {
59 }
60
61 bool currentMoving;
62 bool textBorder;
63 bool textTransparent;
64
65 int alignMode;
66 int textOpacity;
67 int h;
68 int textRotation;
69 int transparency;
70 int w;
71 int xpos;
72 int ypos;
73
74 QColor backgroundColor; // For text
75 QColor bgColor; // For Pixmap
76 QColor textColor;
77
78 QFont textFont;
79
80 QPixmap* pixmap;
81
82 QRect positionHint;
83 QRect rect;
84 QRect textRect;
85
86 QString textString;
87
88 ImageIface* iface;
89 };
90
InsertTextWidget(int w,int h,QWidget * const parent)91 InsertTextWidget::InsertTextWidget(int w, int h, QWidget* const parent)
92 : QWidget(parent),
93 d (new Private)
94 {
95 d->currentMoving = false;
96 d->bgColor = palette().color(QPalette::Window);
97 d->backgroundColor = QColor(0xCC, 0xCC, 0xCC);
98 d->transparency = 210;
99
100 d->iface = new ImageIface(QSize(w, h));
101 d->w = d->iface->previewSize().width();
102 d->h = d->iface->previewSize().height();
103 d->pixmap = new QPixmap(w, h);
104 d->pixmap->fill(d->bgColor);
105
106 setMinimumSize(w, h);
107 setMouseTracking(true);
108 setAttribute(Qt::WA_DeleteOnClose);
109
110 d->rect = QRect(width()/2-d->w/2, height()/2-d->h/2, d->w, d->h);
111 d->textRect = QRect();
112 }
113
~InsertTextWidget()114 InsertTextWidget::~InsertTextWidget()
115 {
116 delete d->iface;
117 delete d->pixmap;
118 delete d;
119 }
120
imageIface() const121 ImageIface* InsertTextWidget::imageIface() const
122 {
123 return d->iface;
124 }
125
resetEdit()126 void InsertTextWidget::resetEdit()
127 {
128 // signal this needs to be filled by makePixmap
129
130 d->textRect = QRect();
131 makePixmap();
132 repaint();
133 }
134
setText(const QString & text,const QFont & font,const QColor & color,int opacity,int alignMode,bool border,bool transparent,int rotation)135 void InsertTextWidget::setText(const QString& text, const QFont& font, const QColor& color, int opacity,
136 int alignMode, bool border, bool transparent, int rotation)
137 {
138 d->textString = text;
139 d->textColor = color;
140 d->textOpacity = opacity;
141 d->textBorder = border;
142 d->textTransparent = transparent;
143 d->textRotation = rotation;
144
145 switch (alignMode)
146 {
147 case ALIGN_LEFT:
148 d->alignMode = Qt::AlignLeft;
149 break;
150
151 case ALIGN_RIGHT:
152 d->alignMode = Qt::AlignRight;
153 break;
154
155 case ALIGN_CENTER:
156 d->alignMode = Qt::AlignHCenter;
157 break;
158
159 case ALIGN_BLOCK:
160 d->alignMode = Qt::AlignJustify;
161 break;
162 }
163
164 // Center text if top left corner text area is not visible.
165
166 /*
167 if (d->textFont.pointSize() != font.pointSize() &&
168 !rect().contains( d->textRect.x(), d->textRect.y()))
169 {
170 d->textFont = font;
171 resetEdit();
172 return;
173 }
174 */
175
176 d->textFont = font;
177
178 makePixmap();
179 repaint();
180 }
181
setBackgroundColor(const QColor & bg)182 void InsertTextWidget::setBackgroundColor(const QColor& bg)
183 {
184 d->bgColor = bg;
185 makePixmap();
186 repaint();
187 }
188
setPositionHint(const QRect & hint)189 void InsertTextWidget::setPositionHint(const QRect& hint)
190 {
191 // interpreted by composeImage
192
193 d->positionHint = hint;
194
195 if (d->textRect.isValid())
196 {
197 // invalidate current position so that hint is certainly interpreted
198
199 d->textRect = QRect();
200 makePixmap();
201 repaint();
202 }
203 }
204
getPositionHint() const205 QRect InsertTextWidget::getPositionHint() const
206 {
207 QRect hint;
208
209 if (d->textRect.isValid())
210 {
211 // We normalize on the size of the image, but we store as int. Precision loss is no problem.
212
213 hint.setX( (int) ((float)(d->textRect.x() - d->rect.x()) / (float)d->rect.width() * 10000.0));
214 hint.setY( (int) ((float)(d->textRect.y() - d->rect.y()) / (float)d->rect.height() * 10000.0));
215 hint.setWidth( (int) ((float)d->textRect.width() / (float)d->rect.width() * 10000.0));
216 hint.setHeight((int) ((float)d->textRect.height() / (float)d->rect.height() * 10000.0));
217 }
218
219 return hint;
220 }
221
makeInsertText()222 DImg InsertTextWidget::makeInsertText()
223 {
224 int orgW = d->iface->originalSize().width();
225 int orgH = d->iface->originalSize().height();
226 float ratioW = (float)orgW/(float)d->w;
227 float ratioH = (float)orgH/(float)d->h;
228
229 int x, y;
230
231 if (d->textRect.isValid())
232 {
233 // convert from widget to image coordinates, then to original size
234
235 x = qRound((d->textRect.x() - d->rect.x()) * ratioW);
236 y = qRound((d->textRect.y() - d->rect.y()) * ratioH);
237 }
238 else
239 {
240 x = -1;
241 y = -1;
242 }
243
244 // Get original image
245
246 DImg image = d->iface->original()->copy();
247 int borderWidth = qMax(1, qRound(ratioW));
248
249 // compose and draw result on image
250
251 composeImage(&image, nullptr, x, y,
252 d->textFont, d->textFont.pointSizeF(),
253 d->textRotation, d->textColor, d->textOpacity,
254 d->alignMode, d->textString, d->textTransparent, d->backgroundColor,
255 d->textBorder ? BORDER_NORMAL : BORDER_NONE, borderWidth, borderWidth);
256
257 return image;
258 }
259
makePixmap()260 void InsertTextWidget::makePixmap()
261 {
262 int orgW = d->iface->originalSize().width();
263 int orgH = d->iface->originalSize().height();
264 float ratioW = (float)d->w / (float)orgW;
265 float ratioH = (float)d->h / (float)orgH;
266
267 int x, y;
268
269 if (d->textRect.isValid())
270 {
271 // convert from widget to image coordinates
272
273 x = d->textRect.x() - d->rect.x();
274 y = d->textRect.y() - d->rect.y();
275 }
276 else
277 {
278 x = -1;
279 y = -1;
280 }
281
282 // get preview image data
283
284 DImg image = d->iface->preview();
285 image.setIccProfile(d->iface->original()->getIccProfile());
286
287 // paint pixmap for drawing this widget
288 // First, fill with background color
289
290 d->pixmap->fill(d->bgColor);
291 QPainter p(d->pixmap);
292
293 // Convert image to pixmap and draw it
294
295 QPixmap imagePixmap = d->iface->convertToPixmap(image);
296 p.drawPixmap(d->rect.x(), d->rect.y(),
297 imagePixmap, 0, 0, imagePixmap.width(), imagePixmap.height());
298
299 // prepare painter for use by compose image
300
301 p.setClipRect(d->rect);
302 p.translate(d->rect.x(), d->rect.y());
303
304 int borderWidth = qMax(1, qRound(ratioW));
305
306 // compose image and draw result directly on pixmap, with correct offset
307
308 QRect textRect = composeImage(&image, &p, x, y,
309 d->textFont, d->textFont.pointSizeF(),
310 d->textRotation, d->textColor, d->textOpacity,
311 d->alignMode, d->textString, d->textTransparent, d->backgroundColor,
312 d->textBorder ? BORDER_NORMAL : BORDER_SUPPORT, borderWidth, borderWidth,
313 (ratioW > ratioH) ? ratioW : ratioH);
314
315 p.end();
316
317 // store new text rectangle
318 // convert from image to widget coordinates
319
320 d->textRect.setX(textRect.x() + d->rect.x());
321 d->textRect.setY(textRect.y() + d->rect.y());
322 d->textRect.setSize(textRect.size());
323 }
324
325 /**
326 Take data from image, draw text at x|y with specified parameters.
327 If destPainter is null, draw to image,
328 if destPainter is not null, draw directly using the painter.
329 Returns modified area of image.
330 */
composeImage(DImg * const image,QPainter * const destPainter,int x,int y,QFont font,float pointSize,int textRotation,QColor textColor,int textOpacity,int alignMode,const QString & textString,bool transparentBackground,QColor backgroundColor,BorderMode borderMode,int borderWidth,int spacing,float fontScale)331 QRect InsertTextWidget::composeImage(DImg* const image, QPainter* const destPainter,
332 int x, int y,
333 QFont font, float pointSize, int textRotation, QColor textColor,
334 int textOpacity, int alignMode, const QString& textString,
335 bool transparentBackground, QColor backgroundColor,
336 BorderMode borderMode, int borderWidth, int spacing, float fontScale)
337 {
338 /*
339 The problem we have to solve is that we have no pixel access to font rendering,
340 we have to let Qt do the drawing. On the other hand we need to support 16 bit, which
341 cannot be done with QPixmap.
342 The current solution cuts out the text area, lets Qt do its drawing, converts back and blits to original.
343 */
344
345 int maxWidth, maxHeight;
346
347 if (x == -1 && y == -1)
348 {
349 maxWidth = image->width();
350 maxHeight = image->height();
351 }
352 else
353 {
354 maxWidth = image->width() - x;
355 maxHeight = image->height() - y;
356 }
357
358 fontScale = qMax(0.01f, fontScale);
359
360 // find out size of the area that we are drawing to
361
362 font.setPointSizeF(pointSize);
363 QFontMetrics fontMt(font);
364 QRect fontRect = fontMt.boundingRect(0, 0,
365 qRound(maxWidth / fontScale),
366 qRound(maxHeight / fontScale),
367 alignMode, textString);
368
369 fontRect.setWidth(qRound(fontRect.width() * fontScale));
370 fontRect.setHeight(qRound(fontRect.height() * fontScale));
371
372 if (!fontRect.isValid())
373 {
374 return QRect();
375 }
376
377 int fontWidth, fontHeight;
378
379 switch (textRotation)
380 {
381 case ROTATION_NONE:
382 case ROTATION_180:
383 default:
384 fontWidth = fontRect.width();
385 fontHeight = fontRect.height();
386 break;
387
388 case ROTATION_90:
389 case ROTATION_270:
390 fontWidth = fontRect.height();
391 fontHeight = fontRect.width();
392 break;
393 }
394
395 // x, y == -1 means that we have to find a good initial position for the text here
396
397 if ((x == -1) && (y == -1))
398 {
399 int boxWidth = fontWidth + 2 * borderWidth + 2 * spacing;
400 int boxHeight = fontHeight + 2 * borderWidth + 2 * spacing;
401
402 // was a valid position hint stored from last use?
403
404 if (d->positionHint.isValid())
405 {
406 // We assume that people tend to orient text along the edges,
407 // so we do some guessing so that positions such as "in the lower right corner"
408 // will be remembered across different image sizes.
409
410 // get relative positions
411
412 float fromTop = (float)d->positionHint.top() / 10000.0;
413 float fromBottom = 1.0 - (float)d->positionHint.bottom() / 10000.0;
414 float fromLeft = (float)d->positionHint.left() / 10000.0;
415 float fromRight = 1.0 - (float)d->positionHint.right() / 10000.0;
416
417 // calculate horizontal position
418
419 if (fromLeft < fromRight)
420 {
421 x = qRound(fromLeft * maxWidth);
422
423 // we are placing from the smaller distance,
424 // so if now the larger distance is actually too small,
425 // fall back to standard placement, nothing to lose.
426
427 if ((x + boxWidth) > maxWidth)
428 {
429 x = qMax( (maxWidth - boxWidth) / 2, 0);
430 }
431 }
432 else
433 {
434 x = maxWidth - qRound(fromRight * maxWidth) - boxWidth;
435
436 if (x < 0)
437 {
438 x = qMax( (maxWidth - boxWidth) / 2, 0);
439 }
440 }
441
442 // calculate vertical position
443
444 if (fromTop < fromBottom)
445 {
446 y = qRound(fromTop * maxHeight);
447
448 if (y + boxHeight > maxHeight)
449 {
450 y = qMax( (maxHeight - boxHeight) / 2, 0);
451 }
452 }
453 else
454 {
455 y = maxHeight - qRound(fromBottom * maxHeight) - boxHeight;
456
457 if (y < 0)
458 {
459 y = qMax( (maxHeight - boxHeight) / 2, 0);
460 }
461 }
462
463 if (!QRect(x, y, boxWidth, boxHeight).
464 intersects(QRect(0, 0, maxWidth, maxHeight)))
465 {
466 // emergency fallback - nothing is visible
467
468 x = qMax( (maxWidth - boxWidth) / 2, 0);
469 y = qMax( (maxHeight - boxHeight) / 2, 0);
470 }
471
472 // invalidate position hint, use only once
473
474 d->positionHint = QRect();
475 }
476 else
477 {
478 // use standard position
479
480 x = qMax( (maxWidth - boxWidth) / 2, 0);
481 y = qMax( (maxHeight - boxHeight) / 2, 0);
482 }
483 }
484
485 // create a rectangle relative to image
486
487 QRect drawRect(x, y, fontWidth + 2 * borderWidth + 2 * spacing, fontHeight + 2 * borderWidth + 2 * spacing);
488
489 // create a rectangle relative to textArea, excluding the border
490
491 QRect textAreaBackgroundRect(borderWidth, borderWidth, fontWidth + 2 * spacing, fontHeight + 2 * spacing);
492
493 // create a rectangle relative to textArea, excluding the border and spacing
494
495 QRect textAreaTextRect(borderWidth + spacing, borderWidth + spacing, fontWidth, fontHeight);
496
497 // create a rectangle relative to textArea, including the border,
498 // for drawing the rectangle, taking into account that the width of the QPen goes in and out in equal parts
499
500 QRect textAreaDrawRect(borderWidth / 2, borderWidth / 2, fontWidth + borderWidth + 2 * spacing,
501 fontHeight + borderWidth + 2 * spacing);
502
503 // cut out the text area
504
505 DImg textArea = image->copy(drawRect);
506
507 if (textArea.isNull())
508 {
509 return QRect();
510 }
511
512 // compose semi-transparent background over textArea
513
514 DColorComposer* const composer = DColorComposer::getComposer(DColorComposer::PorterDuffNone);
515
516 if (transparentBackground)
517 {
518 DImg transparentLayer(textAreaBackgroundRect.width(), textAreaBackgroundRect.height(), textArea.sixteenBit(), true);
519 DColor transparent(backgroundColor);
520 transparent.setAlpha(d->transparency);
521
522 if (image->sixteenBit())
523 {
524 transparent.convertToSixteenBit();
525 }
526
527 transparentLayer.fill(transparent);
528 textArea.bitBlendImage(composer, &transparentLayer, 0, 0, transparentLayer.width(), transparentLayer.height(),
529 textAreaBackgroundRect.x(), textAreaBackgroundRect.y());
530 }
531
532 DImg textNotDrawn;
533
534 if (textArea.sixteenBit())
535 {
536 textNotDrawn = textArea.copy();
537 textNotDrawn.convertToEightBit();
538 }
539 else
540 {
541 textNotDrawn = textArea;
542 }
543
544 // We have no direct pixel access to font rendering, so now we need to use Qt/X11 for the drawing
545
546 // convert text area to pixmap
547
548 QPixmap pixmap;
549
550 if (destPainter)
551 {
552 // We working on tool preview, deal with CM as well
553
554 pixmap = d->iface->convertToPixmap(textNotDrawn);
555 }
556 else
557 {
558 // We working on target image. Do no apply double CM adjustment here.
559
560 pixmap = textNotDrawn.convertToPixmap();
561 }
562
563 int fontScaleWidth = qRound(fontWidth / fontScale);
564 int fontScaleHeight = qRound(fontHeight / fontScale);
565
566 QPixmap textPixmap(fontScaleWidth, fontScaleHeight);
567 textPixmap.fill(Qt::transparent);
568
569 QPainter tp(&textPixmap);
570 tp.setOpacity((qreal)textOpacity / 100.0);
571 tp.setPen(QPen(textColor, 1));
572 tp.setFont(font);
573
574 switch (textRotation)
575 {
576 case ROTATION_NONE:
577 tp.drawText(0, 0, fontScaleWidth, fontScaleHeight,
578 alignMode, textString);
579 break;
580 case ROTATION_90:
581 tp.translate(fontScaleWidth, 0);
582 tp.rotate(90.0);
583 tp.drawText(0, 0, fontScaleHeight, fontScaleWidth,
584 alignMode, textString);
585 break;
586 case ROTATION_180:
587 tp.translate(fontScaleWidth, fontScaleHeight);
588 tp.rotate(180.0);
589 tp.drawText(0, 0, fontScaleWidth, fontScaleHeight,
590 alignMode, textString);
591 break;
592 case ROTATION_270:
593 tp.translate(0, fontScaleHeight);
594 tp.rotate(270.0);
595 tp.drawText(0, 0, fontScaleHeight, fontScaleWidth,
596 alignMode, textString);
597 break;
598 }
599
600 tp.end();
601
602 // paint on pixmap
603
604 QPainter p(&pixmap);
605
606 p.drawPixmap(textAreaTextRect, textPixmap.scaled(fontWidth,
607 fontHeight,
608 Qt::IgnoreAspectRatio,
609 Qt::SmoothTransformation));
610 // Drawing rectangle around text.
611
612 if (borderMode == BORDER_NORMAL) // Decorative border using text color.
613 {
614 p.setOpacity((qreal)textOpacity / 100.0);
615 p.setPen(QPen(textColor, borderWidth, Qt::SolidLine,
616 Qt::SquareCap, Qt::RoundJoin));
617 p.drawRect(textAreaDrawRect);
618 }
619 else if (borderMode == BORDER_SUPPORT) // Make simple dot line border to help user.
620 {
621 p.setPen(QPen(Qt::white, 1, Qt::SolidLine));
622 p.drawRect(textAreaDrawRect);
623 p.setPen(QPen(Qt::red, 1, Qt::DotLine));
624 p.drawRect(textAreaDrawRect);
625 }
626
627 p.end();
628
629 if (!destPainter)
630 {
631 // convert to QImage, then to DImg
632
633 QImage pixmapImage = pixmap.toImage();
634 DImg textDrawn(pixmapImage.width(), pixmapImage.height(), false, true, pixmapImage.bits());
635
636 // This does not work: during the conversion, colors are altered significantly (diffs of 1 to 10 in each component),
637 // so we cannot find out which pixels have actually been touched.
638 /*
639 // Compare the result of drawing with the previous version.
640 // Set all unchanged pixels to transparent
641 DColor color, ncolor;
642 uchar *ptr, *nptr;
643 ptr = textDrawn.bits();
644 nptr = textNotDrawn.bits();
645 int bytesDepth = textDrawn.bytesDepth();
646 int numPixels = textDrawn.width() * textDrawn.height();
647 for (int i = 0; i < numPixels; ++i, ptr+= bytesDepth, nptr += bytesDepth)
648 {
649 color.setColor(ptr, false);
650 ncolor.setColor(nptr, false);
651 if (color.red() == ncolor.red() &&
652 color.green() == ncolor.green() &&
653 color.blue() == ncolor.blue())
654 {
655 color.setAlpha(0);
656 color.setPixel(ptr);
657 }
658 }
659 // convert to 16 bit if needed
660 */
661 textDrawn.convertToDepthOfImage(&textArea);
662
663 // now compose to original: only pixels affected by drawing text and border are changed, not whole area
664
665 textArea.bitBlendImage(composer, &textDrawn, 0, 0, textDrawn.width(), textDrawn.height(), 0, 0);
666
667 // copy result to original image
668
669 image->bitBltImage(&textArea, drawRect.x(), drawRect.y());
670 }
671 else
672 {
673 destPainter->drawPixmap(drawRect.x(), drawRect.y(), pixmap, 0, 0, pixmap.width(), pixmap.height());
674 }
675
676 delete composer;
677
678 return drawRect;
679 }
680
paintEvent(QPaintEvent *)681 void InsertTextWidget::paintEvent(QPaintEvent*)
682 {
683 QPainter p(this);
684 p.drawPixmap(0, 0, *d->pixmap);
685 p.end();
686 }
687
resizeEvent(QResizeEvent * e)688 void InsertTextWidget::resizeEvent(QResizeEvent* e)
689 {
690 blockSignals(true);
691 delete d->pixmap;
692
693 int w = e->size().width();
694 int h = e->size().height();
695
696 int textX = d->textRect.x() - d->rect.x();
697 int textY = d->textRect.y() - d->rect.y();
698 int old_w = d->w;
699 int old_h = d->h;
700 d->iface->setPreviewSize(QSize(w, h));
701 d->w = d->iface->previewSize().width();
702 d->h = d->iface->previewSize().height();
703
704 d->pixmap = new QPixmap(w, h);
705 d->rect = QRect(w/2-d->w/2, h/2-d->h/2, d->w, d->h);
706
707 if (d->textRect.isValid())
708 {
709 int textWidth = d->textRect.width();
710 int textHeight = d->textRect.height();
711
712 textX = qRound(textX * (float)d->w / (float)old_w);
713 textY = qRound(textY * (float)d->h / (float)old_h);
714 textWidth = qRound(textWidth * (float)d->w / (float)old_w);
715 textHeight = qRound(textHeight * (float)d->h / (float)old_h);
716
717 d->textRect.setX(textX + d->rect.x());
718 d->textRect.setY(textY + d->rect.y());
719 d->textRect.setWidth(textWidth);
720 d->textRect.setHeight(textHeight);
721 makePixmap();
722 }
723
724 blockSignals(false);
725 }
726
mousePressEvent(QMouseEvent * e)727 void InsertTextWidget::mousePressEvent(QMouseEvent* e)
728 {
729 if (e->button() == Qt::LeftButton &&
730 d->textRect.contains( e->x(), e->y()))
731 {
732 d->xpos = e->x();
733 d->ypos = e->y();
734 setCursor(Qt::SizeAllCursor);
735 d->currentMoving = true;
736 }
737 }
738
mouseReleaseEvent(QMouseEvent *)739 void InsertTextWidget::mouseReleaseEvent(QMouseEvent*)
740 {
741 setCursor(Qt::ArrowCursor);
742 d->currentMoving = false;
743 }
744
mouseMoveEvent(QMouseEvent * e)745 void InsertTextWidget::mouseMoveEvent(QMouseEvent* e)
746 {
747 if (rect().contains( e->x(), e->y()))
748 {
749 if (e->buttons() == Qt::LeftButton && d->currentMoving)
750 {
751 uint newxpos = e->x();
752 uint newypos = e->y();
753
754 d->textRect.translate(newxpos - d->xpos, newypos - d->ypos);
755
756 if (d->textRect.x() - d->rect.x() < 0)
757 {
758 d->textRect.setX(d->rect.x());
759 }
760
761 if (d->textRect.y() - d->rect.y() < 0)
762 {
763 d->textRect.setY(d->rect.y());
764 }
765
766 makePixmap();
767 repaint();
768
769 d->xpos = newxpos;
770 d->ypos = newypos;
771 setCursor(Qt::PointingHandCursor);
772 }
773 else if (d->textRect.contains( e->x(), e->y()))
774 {
775 setCursor(Qt::SizeAllCursor);
776 }
777 else
778 {
779 setCursor(Qt::ArrowCursor);
780 }
781 }
782 }
783
784 } // namespace DigikamEditorInsertTextToolPlugin
785