File indexing completed on 2024-05-12 15:56:51

0001 /* This file is part of the KDE project
0002  * SPDX-FileCopyrightText: 2006, 2010 Thomas Zander <zander@kde.org>
0003  * SPDX-FileCopyrightText: 2011 Jan Hambrecht <jaham@gmx.net>
0004  *
0005  * SPDX-License-Identifier: LGPL-2.0-or-later
0006  */
0007 
0008 #include <QDebug>
0009 
0010 #include <QAction>
0011 
0012 #include "KoToolBase.h"
0013 #include "KoToolBase_p.h"
0014 #include "KoToolFactoryBase.h"
0015 #include "KoCanvasBase.h"
0016 #include "KoPointerEvent.h"
0017 #include "KoDocumentResourceManager.h"
0018 #include "KoCanvasResourceProvider.h"
0019 #include "KoViewConverter.h"
0020 #include "KoShapeController.h"
0021 #include "KoShapeControllerBase.h"
0022 #include "KoToolSelection.h"
0023 #include "KoCanvasController.h"
0024 #include "KoToolProxy.h"
0025 #include <kis_icon_utils.h>
0026 
0027 #include <klocalizedstring.h>
0028 #include <kactioncollection.h>
0029 #include <QWidget>
0030 #include <QFile>
0031 #include <QDomDocument>
0032 #include <QDomElement>
0033 
0034 KoToolBase::KoToolBase(KoCanvasBase *canvas)
0035     : d_ptr(new KoToolBasePrivate(this, canvas))
0036 {
0037     Q_D(KoToolBase);
0038     d->connectSignals();
0039 }
0040 
0041 KoToolBase::KoToolBase(KoToolBasePrivate &dd)
0042     : d_ptr(&dd)
0043 {
0044     Q_D(KoToolBase);
0045     d->connectSignals();
0046 }
0047 
0048 KoToolBase::~KoToolBase()
0049 {
0050     qDeleteAll(d_ptr->optionWidgets);
0051     delete d_ptr;
0052 }
0053 
0054 
0055 bool KoToolBase::isActivated() const
0056 {
0057     Q_D(const KoToolBase);
0058     return d->isActivated;
0059 }
0060 
0061 KoPointerEvent *KoToolBase::lastDeliveredPointerEvent() const
0062 {
0063     Q_D(const KoToolBase);
0064 
0065     if (!d->canvas) return 0;
0066     if (!d->canvas->toolProxy()) return 0;
0067 
0068     return d->canvas->toolProxy()->lastDeliveredPointerEvent();
0069 }
0070 
0071 void KoToolBase::activate(const QSet<KoShape *> &shapes)
0072 {
0073     Q_UNUSED(shapes);
0074 
0075     Q_D(KoToolBase);
0076     d->isActivated = true;
0077 }
0078 
0079 void KoToolBase::deactivate()
0080 {
0081     Q_D(KoToolBase);
0082     d->isActivated = false;
0083 }
0084 
0085 void KoToolBase::canvasResourceChanged(int key, const QVariant & res)
0086 {
0087     Q_UNUSED(key);
0088     Q_UNUSED(res);
0089 }
0090 
0091 void KoToolBase::documentResourceChanged(int key, const QVariant &res)
0092 {
0093     Q_UNUSED(key);
0094     Q_UNUSED(res);
0095 }
0096 
0097 bool KoToolBase::wantsAutoScroll() const
0098 {
0099     return true;
0100 }
0101 
0102 void KoToolBase::mouseDoubleClickEvent(KoPointerEvent *event)
0103 {
0104     event->ignore();
0105 }
0106 
0107 void KoToolBase::mouseTripleClickEvent(KoPointerEvent *event)
0108 {
0109     event->ignore();
0110 }
0111 
0112 void KoToolBase::keyPressEvent(QKeyEvent *e)
0113 {
0114     e->ignore();
0115 }
0116 
0117 void KoToolBase::keyReleaseEvent(QKeyEvent *e)
0118 {
0119     e->ignore();
0120 }
0121 
0122 
0123 void KoToolBase::explicitUserStrokeEndRequest()
0124 {
0125 }
0126 
0127 QVariant KoToolBase::inputMethodQuery(Qt::InputMethodQuery query, const KoViewConverter &) const
0128 {
0129     Q_D(const KoToolBase);
0130     if (d->canvas->canvasWidget() == 0)
0131         return QVariant();
0132 
0133     switch (query) {
0134     case Qt::ImMicroFocus:
0135         return QRect(d->canvas->canvasWidget()->width() / 2, 0, 1, d->canvas->canvasWidget()->height());
0136     case Qt::ImFont:
0137         return d->canvas->canvasWidget()->font();
0138     default:
0139         return QVariant();
0140     }
0141 }
0142 
0143 void KoToolBase::inputMethodEvent(QInputMethodEvent * event)
0144 {
0145     if (! event->commitString().isEmpty()) {
0146         QKeyEvent ke(QEvent::KeyPress, -1, QFlags<Qt::KeyboardModifier>(), event->commitString());
0147         keyPressEvent(&ke);
0148     }
0149     event->accept();
0150 }
0151 
0152 void KoToolBase::customPressEvent(KoPointerEvent * event)
0153 {
0154     event->ignore();
0155 }
0156 
0157 void KoToolBase::customReleaseEvent(KoPointerEvent * event)
0158 {
0159     event->ignore();
0160 }
0161 
0162 void KoToolBase::customMoveEvent(KoPointerEvent * event)
0163 {
0164     event->ignore();
0165 }
0166 
0167 void KoToolBase::useCursor(const QCursor &cursor)
0168 {
0169     Q_D(KoToolBase);
0170     d->currentCursor = cursor;
0171     emit cursorChanged(d->currentCursor);
0172 }
0173 
0174 QList<QPointer<QWidget> > KoToolBase::optionWidgets()
0175 {
0176     Q_D(KoToolBase);
0177     if (!d->optionWidgetsCreated) {
0178         d->optionWidgets = createOptionWidgets();
0179         d->optionWidgetsCreated = true;
0180     }
0181     return d->optionWidgets;
0182 }
0183 
0184 QAction *KoToolBase::action(const QString &name) const
0185 {
0186     Q_D(const KoToolBase);
0187     if (d->canvas && d->canvas->canvasController() && d->canvas->canvasController()) {
0188         return d->canvas->canvasController()->actionCollection()->action(name);
0189     }
0190     return 0;
0191 }
0192 
0193 QWidget * KoToolBase::createOptionWidget()
0194 {
0195     return 0;
0196 }
0197 
0198 QList<QPointer<QWidget> >  KoToolBase::createOptionWidgets()
0199 {
0200     QList<QPointer<QWidget> > ow;
0201     if (QWidget *widget = createOptionWidget()) {
0202         if (widget->objectName().isEmpty()) {
0203             widget->setObjectName(toolId());
0204         }
0205         ow.append(widget);
0206     }
0207     return ow;
0208 }
0209 
0210 void KoToolBase::setFactory(KoToolFactoryBase *factory)
0211 {
0212     Q_D(KoToolBase);
0213     d->factory = factory;
0214 }
0215 
0216 KoToolFactoryBase* KoToolBase::factory() const
0217 {
0218     Q_D(const KoToolBase);
0219     return d->factory;
0220 }
0221 
0222 QString KoToolBase::toolId() const
0223 {
0224     Q_D(const KoToolBase);
0225     return d->factory ? d->factory->id() : 0;
0226 }
0227 
0228 QCursor KoToolBase::cursor() const
0229 {
0230     Q_D(const KoToolBase);
0231     return d->currentCursor;
0232 }
0233 
0234 void KoToolBase::deleteSelection()
0235 {
0236 }
0237 
0238 void KoToolBase::cut()
0239 {
0240     copy();
0241     deleteSelection();
0242 }
0243 
0244 KoCanvasBase * KoToolBase::canvas() const
0245 {
0246     Q_D(const KoToolBase);
0247     return d->canvas;
0248 }
0249 
0250 void KoToolBase::setStatusText(const QString &statusText)
0251 {
0252     emit statusTextChanged(statusText);
0253 }
0254 
0255 int KoToolBase::handleRadius() const
0256 {
0257     Q_D(const KoToolBase);
0258     if (d->canvas
0259             && d->canvas->shapeController()
0260             && d->canvas->shapeController()->resourceManager()
0261        )
0262     {
0263         return d->canvas->shapeController()->resourceManager()->handleRadius();
0264     }
0265     else {
0266         return 3;
0267     }
0268 }
0269 
0270 qreal KoToolBase::handleDocRadius() const
0271 {
0272     Q_D(const KoToolBase);
0273     const KoViewConverter * converter = d->canvas->viewConverter();
0274     const QPointF doc = converter->viewToDocument(QPointF(handleRadius(), handleRadius()));
0275     return qMax(doc.x(), doc.y());
0276 }
0277 
0278 int KoToolBase::grabSensitivity() const
0279 {
0280     Q_D(const KoToolBase);
0281     if(d->canvas->shapeController()->resourceManager())
0282     {
0283         return d->canvas->shapeController()->resourceManager()->grabSensitivity();
0284     } else {
0285         return 3;
0286     }
0287 }
0288 
0289 QRectF KoToolBase::handleGrabRect(const QPointF &position) const
0290 {
0291     Q_D(const KoToolBase);
0292     const KoViewConverter * converter = d->canvas->viewConverter();
0293     uint handleSize = 2*grabSensitivity();
0294     QRectF r = converter->viewToDocument(QRectF(0, 0, handleSize, handleSize));
0295     r.moveCenter(position);
0296     return r;
0297 }
0298 
0299 QRectF KoToolBase::handlePaintRect(const QPointF &position) const
0300 {
0301     Q_D(const KoToolBase);
0302     const KoViewConverter * converter = d->canvas->viewConverter();
0303     uint handleSize = 2*handleRadius();
0304     QRectF r = converter->viewToDocument(QRectF(0, 0, handleSize, handleSize));
0305     r.moveCenter(position);
0306     return r;
0307 }
0308 
0309 void KoToolBase::setTextMode(bool value)
0310 {
0311     Q_D(KoToolBase);
0312     d->isInTextMode=value;
0313 }
0314 
0315 bool KoToolBase::paste()
0316 {
0317     return false;
0318 }
0319 
0320 void KoToolBase::copy() const
0321 {
0322 }
0323 
0324 void KoToolBase::dragMoveEvent(QDragMoveEvent *event, const QPointF &point)
0325 {
0326     Q_UNUSED(event);
0327     Q_UNUSED(point);
0328 }
0329 
0330 void KoToolBase::dragLeaveEvent(QDragLeaveEvent *event)
0331 {
0332     Q_UNUSED(event);
0333 }
0334 
0335 void KoToolBase::dropEvent(QDropEvent *event, const QPointF &point)
0336 {
0337     Q_UNUSED(event);
0338     Q_UNUSED(point);
0339 }
0340 
0341 bool KoToolBase::hasSelection()
0342 {
0343     KoToolSelection *sel = selection();
0344     return (sel && sel->hasSelection());
0345 }
0346 
0347 KoToolSelection *KoToolBase::selection()
0348 {
0349     return 0;
0350 }
0351 
0352 void KoToolBase::repaintDecorations()
0353 {
0354     Q_D(KoToolBase);
0355 
0356     QRectF dirtyRect = d->lastDecorationsRect;
0357     d->lastDecorationsRect = decorationsRect();
0358     dirtyRect |= d->lastDecorationsRect;
0359 
0360     if (!dirtyRect.isEmpty()) {
0361         canvas()->updateCanvas(dirtyRect);
0362     }
0363 }
0364 
0365 QRectF KoToolBase::decorationsRect() const
0366 {
0367     return QRectF();
0368 }
0369 
0370 bool KoToolBase::isInTextMode() const
0371 {
0372     Q_D(const KoToolBase);
0373     return d->isInTextMode;
0374 }
0375 
0376 void KoToolBase::requestUndoDuringStroke()
0377 {
0378     /**
0379      * Default implementation just cancels the stroke
0380      */
0381     requestStrokeCancellation();
0382 }
0383 
0384 
0385 void KoToolBase::requestRedoDuringStroke()
0386 {
0387 }
0388 
0389 void KoToolBase::requestStrokeCancellation()
0390 {
0391 }
0392 
0393 void KoToolBase::requestStrokeEnd()
0394 {
0395 }
0396 
0397 bool KoToolBase::maskSyntheticEvents() const
0398 {
0399     Q_D(const KoToolBase);
0400     return d->maskSyntheticEvents;
0401 }
0402 
0403 void KoToolBase::setMaskSyntheticEvents(bool value)
0404 {
0405     Q_D(KoToolBase);
0406     d->maskSyntheticEvents = value;
0407 }
0408 
0409 void KoToolBase::updateOptionsWidgetIcons()
0410 {
0411     Q_D(KoToolBase);
0412     if (d->optionWidgetsCreated) {
0413         QObjectList objects;
0414         for (QPointer<QWidget> widget : d->optionWidgets) {
0415             objects.append(widget);
0416         }
0417         while (!objects.isEmpty()) {
0418             QObject* object = objects.takeFirst();
0419             objects.append(object->children());
0420             KisIconUtils::updateIconCommon(object);
0421         }
0422     }
0423 }