File indexing completed on 2024-05-26 04:26:41

0001 /* This file is part of the KDE project
0002 
0003    SPDX-FileCopyrightText: 2006-2007, 2010 Thomas Zander <zander@kde.org>
0004 
0005    SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "KoInteractionTool.h"
0009 #include "KoInteractionTool_p.h"
0010 #include "KoToolBase_p.h"
0011 #include "KoPointerEvent.h"
0012 #include "KoCanvasBase.h"
0013 
0014 #include "kis_global.h"
0015 #include "kis_assert.h"
0016 
0017 
0018 KoInteractionTool::KoInteractionTool(KoCanvasBase *canvas)
0019     : KoToolBase(*(new KoInteractionToolPrivate(this, canvas)))
0020 {
0021 }
0022 
0023 KoInteractionTool::~KoInteractionTool()
0024 {
0025 }
0026 
0027 void KoInteractionTool::paint(QPainter &painter, const KoViewConverter &converter)
0028 {
0029     Q_D(KoInteractionTool);
0030 
0031     if (d->currentStrategy) {
0032         d->currentStrategy->paint(painter, converter);
0033     } else {
0034         Q_FOREACH (KoInteractionStrategyFactorySP factory, d->interactionFactories) {
0035             // skip the rest of rendering if the factory asks for it
0036             if (factory->paintOnHover(painter, converter)) break;
0037         }
0038     }
0039 }
0040 
0041 void KoInteractionTool::mousePressEvent(KoPointerEvent *event)
0042 {
0043     Q_D(KoInteractionTool);
0044     if (d->currentStrategy) { // possible if the user presses an extra mouse button
0045         cancelCurrentStrategy();
0046         return;
0047     }
0048     d->currentStrategy = createStrategyBase(event);
0049     if (d->currentStrategy == 0)
0050         event->ignore();
0051 }
0052 
0053 void KoInteractionTool::mouseMoveEvent(KoPointerEvent *event)
0054 {
0055     Q_D(KoInteractionTool);
0056     d->lastPoint = event->point;
0057 
0058     if (d->currentStrategy) {
0059         d->currentStrategy->handleMouseMove(d->lastPoint, event->modifiers());
0060     } else {
0061         Q_FOREACH (KoInteractionStrategyFactorySP factory, d->interactionFactories) {
0062             // skip the rest of rendering if the factory asks for it
0063             if (factory->hoverEvent(event)) return;
0064         }
0065 
0066         event->ignore();
0067     }
0068 }
0069 
0070 void KoInteractionTool::mouseReleaseEvent(KoPointerEvent *event)
0071 {
0072     Q_D(KoInteractionTool);
0073     if (d->currentStrategy) {
0074         d->currentStrategy->finishInteraction(event->modifiers());
0075         KUndo2Command *command = d->currentStrategy->createCommand();
0076         if (command)
0077             d->canvas->addCommand(command);
0078         delete d->currentStrategy;
0079         d->currentStrategy = 0;
0080         repaintDecorations();
0081     } else
0082         event->ignore();
0083 }
0084 
0085 void KoInteractionTool::keyPressEvent(QKeyEvent *event)
0086 {
0087     Q_D(KoInteractionTool);
0088     event->ignore();
0089     if (d->currentStrategy &&
0090             (event->key() == Qt::Key_Control ||
0091              event->key() == Qt::Key_Alt || event->key() == Qt::Key_Shift ||
0092              event->key() == Qt::Key_Meta)) {
0093         d->currentStrategy->handleMouseMove(d->lastPoint, event->modifiers());
0094         event->accept();
0095     }
0096 }
0097 
0098 void KoInteractionTool::keyReleaseEvent(QKeyEvent *event)
0099 {
0100     Q_D(KoInteractionTool);
0101 
0102     if (!d->currentStrategy) {
0103         KoToolBase::keyReleaseEvent(event);
0104         return;
0105     }
0106 
0107     if (event->key() == Qt::Key_Escape) {
0108         cancelCurrentStrategy();
0109         event->accept();
0110     } else if (event->key() == Qt::Key_Control ||
0111                event->key() == Qt::Key_Alt || event->key() == Qt::Key_Shift ||
0112                event->key() == Qt::Key_Meta) {
0113         d->currentStrategy->handleMouseMove(d->lastPoint, event->modifiers());
0114     }
0115 }
0116 
0117 KoInteractionStrategy *KoInteractionTool::currentStrategy()
0118 {
0119     Q_D(KoInteractionTool);
0120     return d->currentStrategy;
0121 }
0122 
0123 void KoInteractionTool::cancelCurrentStrategy()
0124 {
0125     Q_D(KoInteractionTool);
0126     if (d->currentStrategy) {
0127         d->currentStrategy->cancelInteraction();
0128         delete d->currentStrategy;
0129         d->currentStrategy = 0;
0130     }
0131 }
0132 
0133 KoInteractionStrategy *KoInteractionTool::createStrategyBase(KoPointerEvent *event)
0134 {
0135     Q_D(KoInteractionTool);
0136 
0137     Q_FOREACH (KoInteractionStrategyFactorySP factory, d->interactionFactories) {
0138         KoInteractionStrategy *strategy = factory->createStrategy(event);
0139         if (strategy) {
0140             return strategy;
0141         }
0142     }
0143 
0144     return createStrategy(event);
0145 }
0146 
0147 void KoInteractionTool::addInteractionFactory(KoInteractionStrategyFactory *factory)
0148 {
0149     Q_D(KoInteractionTool);
0150 
0151     Q_FOREACH (auto f, d->interactionFactories) {
0152         KIS_SAFE_ASSERT_RECOVER_RETURN(f->id() != factory->id());
0153     }
0154 
0155     d->interactionFactories.append(toQShared(factory));
0156     std::sort(d->interactionFactories.begin(),
0157           d->interactionFactories.end(),
0158           KoInteractionStrategyFactory::compareLess);
0159 }
0160 
0161 void KoInteractionTool::removeInteractionFactory(const QString &id)
0162 {
0163     Q_D(KoInteractionTool);
0164     QList<KoInteractionStrategyFactorySP>::iterator it =
0165             d->interactionFactories.begin();
0166 
0167     while (it != d->interactionFactories.end()) {
0168         if ((*it)->id() == id) {
0169             it = d->interactionFactories.erase(it);
0170         } else {
0171             ++it;
0172         }
0173     }
0174 }
0175 
0176 bool KoInteractionTool::hasInteractionFactory(const QString &id)
0177 {
0178     Q_D(KoInteractionTool);
0179 
0180     Q_FOREACH (auto f, d->interactionFactories) {
0181         if (f->id() == id) {
0182             return true;
0183         }
0184     }
0185 
0186     return false;
0187 }
0188 
0189 bool KoInteractionTool::tryUseCustomCursor()
0190 {
0191     Q_D(KoInteractionTool);
0192 
0193     Q_FOREACH (auto f, d->interactionFactories) {
0194         if (f->tryUseCustomCursor()) {
0195             return true;
0196         }
0197     }
0198 
0199     return false;
0200 }
0201 
0202 KoInteractionTool::KoInteractionTool(KoInteractionToolPrivate &dd)
0203     : KoToolBase(dd)
0204 {
0205 }