File indexing completed on 2024-05-19 04:24:59

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 #include <QApplication>
0034 
0035 KoToolBase::KoToolBase(KoCanvasBase *canvas)
0036     : d_ptr(new KoToolBasePrivate(this, canvas))
0037 {
0038     Q_D(KoToolBase);
0039     d->connectSignals();
0040 }
0041 
0042 KoToolBase::KoToolBase(KoToolBasePrivate &dd)
0043     : d_ptr(&dd)
0044 {
0045     Q_D(KoToolBase);
0046     d->connectSignals();
0047 }
0048 
0049 KoToolBase::~KoToolBase()
0050 {
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
0128 {
0129     Q_D(const KoToolBase);
0130     if (d->canvas->canvasWidget() == 0)
0131         return QVariant();
0132 
0133     switch (query) {
0134     case Qt::ImEnabled:
0135         return isInTextMode();
0136     case Qt::ImCursorRectangle:
0137         return QRect(d->canvas->canvasWidget()->width() / 2, 0, 1, d->canvas->canvasWidget()->height());
0138     case Qt::ImFont:
0139         return d->canvas->canvasWidget()->font();
0140     default:
0141         return QVariant();
0142     }
0143 }
0144 
0145 void KoToolBase::inputMethodEvent(QInputMethodEvent * event)
0146 {
0147     if (! event->commitString().isEmpty()) {
0148         QKeyEvent ke(QEvent::KeyPress, -1, QFlags<Qt::KeyboardModifier>(), event->commitString());
0149         keyPressEvent(&ke);
0150     }
0151     event->accept();
0152 }
0153 
0154 void KoToolBase::focusInEvent(QFocusEvent *event)
0155 {
0156     event->ignore();
0157 }
0158 
0159 void KoToolBase::focusOutEvent(QFocusEvent *event)
0160 {
0161     event->ignore();
0162 }
0163 
0164 void KoToolBase::customPressEvent(KoPointerEvent * event)
0165 {
0166     event->ignore();
0167 }
0168 
0169 void KoToolBase::customReleaseEvent(KoPointerEvent * event)
0170 {
0171     event->ignore();
0172 }
0173 
0174 void KoToolBase::customMoveEvent(KoPointerEvent * event)
0175 {
0176     event->ignore();
0177 }
0178 
0179 void KoToolBase::useCursor(const QCursor &cursor)
0180 {
0181     Q_D(KoToolBase);
0182     d->currentCursor = cursor;
0183     emit cursorChanged(d->currentCursor);
0184 }
0185 
0186 QList<QPointer<QWidget> > KoToolBase::optionWidgets()
0187 {
0188     Q_D(KoToolBase);
0189     if (!d->optionWidgetsCreated) {
0190         d->optionWidgets = createOptionWidgets();
0191         d->optionWidgetsCreated = true;
0192     }
0193     return d->optionWidgets;
0194 }
0195 
0196 QAction *KoToolBase::action(const QString &name) const
0197 {
0198     Q_D(const KoToolBase);
0199     if (d->canvas && d->canvas->canvasController() && d->canvas->canvasController()) {
0200         return d->canvas->canvasController()->actionCollection()->action(name);
0201     }
0202     return 0;
0203 }
0204 
0205 QWidget * KoToolBase::createOptionWidget()
0206 {
0207     return 0;
0208 }
0209 
0210 QList<QPointer<QWidget> >  KoToolBase::createOptionWidgets()
0211 {
0212     QList<QPointer<QWidget> > ow;
0213     if (QWidget *widget = createOptionWidget()) {
0214         if (widget->objectName().isEmpty()) {
0215             widget->setObjectName(toolId());
0216         }
0217         ow.append(widget);
0218     }
0219     return ow;
0220 }
0221 
0222 void KoToolBase::setFactory(KoToolFactoryBase *factory)
0223 {
0224     Q_D(KoToolBase);
0225     d->factory = factory;
0226 }
0227 
0228 KoToolFactoryBase* KoToolBase::factory() const
0229 {
0230     Q_D(const KoToolBase);
0231     return d->factory;
0232 }
0233 
0234 QString KoToolBase::toolId() const
0235 {
0236     Q_D(const KoToolBase);
0237     return d->factory ? d->factory->id() : 0;
0238 }
0239 
0240 QCursor KoToolBase::cursor() const
0241 {
0242     Q_D(const KoToolBase);
0243     return d->currentCursor;
0244 }
0245 
0246 void KoToolBase::deleteSelection()
0247 {
0248 }
0249 
0250 void KoToolBase::cut()
0251 {
0252     copy();
0253     deleteSelection();
0254 }
0255 
0256 KoCanvasBase * KoToolBase::canvas() const
0257 {
0258     Q_D(const KoToolBase);
0259     return d->canvas;
0260 }
0261 
0262 void KoToolBase::setStatusText(const QString &statusText)
0263 {
0264     emit statusTextChanged(statusText);
0265 }
0266 
0267 int KoToolBase::handleRadius() const
0268 {
0269     Q_D(const KoToolBase);
0270     if (d->canvas
0271             && d->canvas->resourceManager()
0272        )
0273     {
0274         return d->canvas->resourceManager()->handleRadius();
0275     }
0276     else {
0277         return 3;
0278     }
0279 }
0280 
0281 qreal KoToolBase::handleDocRadius() const
0282 {
0283     Q_D(const KoToolBase);
0284     const KoViewConverter * converter = d->canvas->viewConverter();
0285     const QPointF doc = converter->viewToDocument(QPointF(handleRadius(), handleRadius()));
0286     return qMax(doc.x(), doc.y());
0287 }
0288 
0289 int KoToolBase::decorationThickness() const
0290 {
0291     Q_D(const KoToolBase);
0292     if (d->canvas
0293             && d->canvas->resourceManager()
0294        )
0295     {
0296         return d->canvas->resourceManager()->decorationThickness();
0297     }
0298     else {
0299         return 1;
0300     }
0301 }
0302 
0303 int KoToolBase::grabSensitivity() const
0304 {
0305     Q_D(const KoToolBase);
0306     if(d->canvas->shapeController()->resourceManager())
0307     {
0308         return d->canvas->shapeController()->resourceManager()->grabSensitivity();
0309     } else {
0310         return 3;
0311     }
0312 }
0313 
0314 QRectF KoToolBase::handleGrabRect(const QPointF &position) const
0315 {
0316     Q_D(const KoToolBase);
0317     const KoViewConverter * converter = d->canvas->viewConverter();
0318     uint handleSize = 2*grabSensitivity();
0319     QRectF r = converter->viewToDocument(QRectF(0, 0, handleSize, handleSize));
0320     r.moveCenter(position);
0321     return r;
0322 }
0323 
0324 QRectF KoToolBase::handlePaintRect(const QPointF &position) const
0325 {
0326     Q_D(const KoToolBase);
0327     const KoViewConverter * converter = d->canvas->viewConverter();
0328     uint handleSize = 2*handleRadius();
0329     QRectF r = converter->viewToDocument(QRectF(0, 0, handleSize, handleSize));
0330     r.moveCenter(position);
0331     return r;
0332 }
0333 
0334 void KoToolBase::setTextMode(bool value)
0335 {
0336     Q_D(KoToolBase);
0337     d->isInTextMode = value;
0338     qApp->inputMethod()->update(Qt::ImEnabled);
0339     emit textModeChanged(d->isInTextMode);
0340 }
0341 
0342 bool KoToolBase::paste()
0343 {
0344     return false;
0345 }
0346 
0347 bool KoToolBase::selectAll()
0348 {
0349     return false;
0350 }
0351 
0352 void KoToolBase::deselect()
0353 {
0354 }
0355 
0356 void KoToolBase::copy() const
0357 {
0358 }
0359 
0360 void KoToolBase::dragMoveEvent(QDragMoveEvent *event, const QPointF &point)
0361 {
0362     Q_UNUSED(event);
0363     Q_UNUSED(point);
0364 }
0365 
0366 void KoToolBase::dragLeaveEvent(QDragLeaveEvent *event)
0367 {
0368     Q_UNUSED(event);
0369 }
0370 
0371 void KoToolBase::dropEvent(QDropEvent *event, const QPointF &point)
0372 {
0373     Q_UNUSED(event);
0374     Q_UNUSED(point);
0375 }
0376 
0377 bool KoToolBase::hasSelection()
0378 {
0379     KoToolSelection *sel = selection();
0380     return (sel && sel->hasSelection());
0381 }
0382 
0383 KoToolSelection *KoToolBase::selection()
0384 {
0385     return 0;
0386 }
0387 
0388 void KoToolBase::repaintDecorations()
0389 {
0390     Q_D(KoToolBase);
0391 
0392     QRectF dirtyRect = d->lastDecorationsRect;
0393     d->lastDecorationsRect = decorationsRect();
0394     dirtyRect |= d->lastDecorationsRect;
0395 
0396     if (!dirtyRect.isEmpty()) {
0397         canvas()->updateCanvas(dirtyRect);
0398     }
0399 }
0400 
0401 QRectF KoToolBase::decorationsRect() const
0402 {
0403     return QRectF();
0404 }
0405 
0406 bool KoToolBase::isInTextMode() const
0407 {
0408     Q_D(const KoToolBase);
0409     return d->isInTextMode;
0410 }
0411 
0412 void KoToolBase::requestUndoDuringStroke()
0413 {
0414     /**
0415      * Default implementation just cancels the stroke
0416      */
0417     requestStrokeCancellation();
0418 }
0419 
0420 
0421 void KoToolBase::requestRedoDuringStroke()
0422 {
0423 }
0424 
0425 void KoToolBase::requestStrokeCancellation()
0426 {
0427 }
0428 
0429 void KoToolBase::requestStrokeEnd()
0430 {
0431 }
0432 
0433 bool KoToolBase::maskSyntheticEvents() const
0434 {
0435     Q_D(const KoToolBase);
0436     return d->maskSyntheticEvents;
0437 }
0438 
0439 void KoToolBase::setMaskSyntheticEvents(bool value)
0440 {
0441     Q_D(KoToolBase);
0442     d->maskSyntheticEvents = value;
0443 }
0444 
0445 void KoToolBase::updateOptionsWidgetIcons()
0446 {
0447     Q_D(KoToolBase);
0448     if (d->optionWidgetsCreated) {
0449         QObjectList objects;
0450         Q_FOREACH (QPointer<QWidget> widget, d->optionWidgets) {
0451             objects.append(widget);
0452         }
0453         while (!objects.isEmpty()) {
0454             QObject* object = objects.takeFirst();
0455             objects.append(object->children());
0456             KisIconUtils::updateIconCommon(object);
0457         }
0458     }
0459 }