Krita Source Code Documentation
Loading...
Searching...
No Matches
KoToolProxy.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 * SPDX-FileCopyrightText: 2006-2007 Thomas Zander <zander@kde.org>
3 * SPDX-FileCopyrightText: 2006-2011 Boudewijn Rempt <boud@valdyas.org>
4 *
5 * SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7#include "KoToolProxy.h"
8#include "KoToolProxy_p.h"
9
10#include <QMimeData>
11#include <QUrl>
12#include <QApplication>
13#include <QTouchEvent>
14#include <QClipboard>
15#include <QEvent>
16
17#include <kundo2command.h>
18#include <KoProperties.h>
19
20#include <FlakeDebug.h>
21#include <klocalizedstring.h>
22
23#include "KoToolBase.h"
24#include "KoPointerEvent.h"
25#include "KoInputDevice.h"
26#include "KoToolManager_p.h"
27#include "KoToolSelection.h"
28#include "KoCanvasBase.h"
29#include "KoCanvasController.h"
30#include "KoShapeManager.h"
31#include "KoSelection.h"
32#include "KoShapeLayer.h"
33#include "KoShapeRegistry.h"
34#include "KoShapeController.h"
35#include "KoViewConverter.h"
36#include "KoShapeFactoryBase.h"
37#include "kis_assert.h"
38#include "kactioncollection.h"
39
40
42 : parent(p)
43{
44 scrollTimer.setInterval(100);
45}
46
47void KoToolProxyPrivate::timeout() // Auto scroll the canvas
48{
49 Q_ASSERT(controller);
50
51 const QPoint originalWidgetPoint = parent->documentToWidget(widgetScrollPointDoc).toPoint();
52
53 QRectF mouseArea(widgetScrollPointDoc, QSizeF(10, 10));
54 mouseArea.setTopLeft(mouseArea.center());
55
56 controller->ensureVisibleDoc(mouseArea, true);
57
58 widgetScrollPointDoc = parent->widgetToDocument(originalWidgetPoint);
59
60 QMouseEvent event(QEvent::MouseMove, originalWidgetPoint, Qt::LeftButton, Qt::LeftButton, QFlags<Qt::KeyboardModifier>());
63}
64
66{
67 if (controller == 0) return;
68 if (!activeTool) return;
69 if (!activeTool->wantsAutoScroll()) return;
70 if (!event.isAccepted()) return;
71 if (!isToolPressed) return;
72 if (event.buttons() != Qt::LeftButton) return;
73
74
75 widgetScrollPointDoc = event.point;
76
77 if (! scrollTimer.isActive())
78 scrollTimer.start();
79}
80
82{
83 if (hasSelection == newSelection)
84 return;
85 hasSelection = newSelection;
87}
88
90{
91 if (!activeTool)
92 return false;
93
94 KoShapeManager * shapeManager = activeTool->canvas()->shapeManager();
95 KoShapeLayer * activeLayer = shapeManager->selection()->activeLayer();
96 if (activeLayer && !activeLayer->isShapeEditable())
97 return false;
98 return true;
99}
100
101KoToolProxy::KoToolProxy(KoCanvasBase *canvas, QObject *parent)
102 : QObject(parent),
103 d(new KoToolProxyPrivate(this))
104{
105 KoToolManager::instance()->priv()->registerToolProxy(this, canvas);
106
107 connect(&d->scrollTimer, SIGNAL(timeout()), this, SLOT(timeout()));
108}
109
111{
112 delete d;
113}
114
115void KoToolProxy::paint(QPainter &painter, const KoViewConverter &converter)
116{
117 if (d->activeTool) d->activeTool->paint(painter, converter);
118}
119
124
126{
127 return d->controller->canvas();
128}
129
131{
132 QPointF globalPoint = ev->globalPos();
133
134 if (d->multiClickSource != eventType) {
135 d->multiClickCount = 0;
136 }
137
138 if (d->multiClickGlobalPoint != globalPoint) {
139 if (qAbs(globalPoint.x() - d->multiClickGlobalPoint.x()) > 5||
140 qAbs(globalPoint.y() - d->multiClickGlobalPoint.y()) > 5) {
141 d->multiClickCount = 0;
142 }
143 d->multiClickGlobalPoint = globalPoint;
144 }
145
146 if (d->multiClickCount && d->multiClickTimeStamp.elapsed() < QApplication::doubleClickInterval()) {
147 // One more multiclick;
149 } else {
150 d->multiClickTimeStamp.start();
151 d->multiClickCount = 1;
152 d->multiClickSource = QEvent::Type(eventType);
153 }
154
155 if (d->activeTool) {
156 switch (d->multiClickCount) {
157 case 0:
158 case 1:
160 break;
161 case 2:
163 break;
164 case 3:
165 default:
167 break;
168 }
169 } else {
170 d->multiClickCount = 0;
171 ev->ignore();
172 }
173
174}
175
176void KoToolProxy::tabletEvent(QTabletEvent *event, const QPointF &point)
177{
178 // We get these events exclusively from KisToolProxy - accept them
179 event->accept();
180
182 KoInputDevice::convertPointerType(event), event->uniqueId());
183 KoToolManager::instance()->priv()->switchInputDevice(id);
184
185 KoPointerEvent ev(event, point);
186
187 switch (event->type()) {
188 case QEvent::TabletPress:
189 countMultiClick(&ev, event->type());
190 break;
191 case QEvent::TabletRelease:
192 d->scrollTimer.stop();
193 if (d->activeTool)
195 break;
196 case QEvent::TabletMove:
197 if (d->activeTool)
199 d->checkAutoScroll(ev);
200 default:
201 ; // ignore the rest.
202 }
203
204 d->mouseLeaveWorkaround = true;
206}
207
209{
210 d->mouseLeaveWorkaround = false;
211 KoInputDevice id;
212 KoToolManager::instance()->priv()->switchInputDevice(id);
213 d->mouseDownPoint = ev->pos();
214
215
216 // this tries to make sure another mouse press event doesn't happen
217 // before a release event happens
218 if (d->isToolPressed) {
220 d->scrollTimer.stop();
221
222 if (d->activeTool) {
224 }
225
226 d->isToolPressed = false;
227
228 return;
229 }
230
231 countMultiClick(ev, QEvent::MouseButtonPress);
232
233 d->isToolPressed = true;
234}
235
236void KoToolProxy::mousePressEvent(QMouseEvent *event, const QPointF &point)
237{
238 KoPointerEvent ev(event, point);
239 mousePressEvent(&ev);
241}
242
243void KoToolProxy::mouseDoubleClickEvent(QMouseEvent *event, const QPointF &point)
244{
245 KoPointerEvent ev(event, point);
248}
249
251{
252 // let us handle it as any other mousepress (where we then detect multi clicks
253 mousePressEvent(event);
254}
255
256void KoToolProxy::mouseMoveEvent(QMouseEvent *event, const QPointF &point)
257{
258 KoPointerEvent ev(event, point);
259 mouseMoveEvent(&ev);
261}
262
264{
265 if (d->mouseLeaveWorkaround) {
266 d->mouseLeaveWorkaround = false;
267 return;
268 }
269 KoInputDevice id;
270 KoToolManager::instance()->priv()->switchInputDevice(id);
271 if (d->activeTool == 0) {
272 event->ignore();
273 return;
274 }
275
276 d->activeTool->mouseMoveEvent(event);
277
278 d->checkAutoScroll(*event);
279}
280
281void KoToolProxy::mouseReleaseEvent(QMouseEvent *event, const QPointF &point)
282{
283 KoPointerEvent ev(event, point);
286}
287
289{
290 d->mouseLeaveWorkaround = false;
291 KoInputDevice id;
292 KoToolManager::instance()->priv()->switchInputDevice(id);
293 d->scrollTimer.stop();
294
295 if (d->activeTool) {
297 } else {
298 event->ignore();
299 }
300
301 d->isToolPressed = false;
302}
303
304void KoToolProxy::keyPressEvent(QKeyEvent *event)
305{
306 if (d->activeTool)
307 d->activeTool->keyPressEvent(event);
308 else
309 event->ignore();
310}
311
312void KoToolProxy::keyReleaseEvent(QKeyEvent *event)
313{
314 if (d->activeTool)
316 else
317 event->ignore();
318
319 d->isToolPressed = false;
320}
321
328
329QVariant KoToolProxy::inputMethodQuery(Qt::InputMethodQuery query) const
330{
331 if (d->activeTool)
332 return d->activeTool->inputMethodQuery(query);
333 return QVariant();
334}
335
336void KoToolProxy::inputMethodEvent(QInputMethodEvent *event)
337{
339}
340
341void KoToolProxy::focusInEvent(QFocusEvent *event)
342{
343 if (d->activeTool) d->activeTool->focusInEvent(event);
344}
345
346void KoToolProxy::focusOutEvent(QFocusEvent *event)
347{
348 if (d->activeTool) d->activeTool->focusOutEvent(event);
349}
350
352{
353 return d->activeTool ? d->activeTool->popupActionsMenu() : 0;
354}
355
360
362{
363 if (d->activeTool) {
364 disconnect(d->activeTool, SIGNAL(selectionChanged(bool)), this, SLOT(selectionChanged(bool)));
365 d->toolPriorityShortcuts.clear();
366 }
367
368 d->activeTool = tool;
369
370 if (tool) {
373 if (collection) {
374 Q_FOREACH(QAction *action, collection->actions()) {
375
376 const QVariant prop = action->property("tool_action");
377
378 if (prop.isValid()) {
379 const QStringList tools = prop.toStringList();
380
381 if (tools.contains(d->activeTool->toolId())) {
382 const QList<QKeySequence> shortcuts = action->shortcuts();
383 std::copy(shortcuts.begin(), shortcuts.end(),
384 std::back_inserter(d->toolPriorityShortcuts));
385 }
386 }
387 }
388 }
389
390 connect(d->activeTool, SIGNAL(selectionChanged(bool)), this, SLOT(selectionChanged(bool)));
392 Q_EMIT toolChanged(tool->toolId());
393 }
394}
395
396void KoToolProxy::touchEvent(QTouchEvent* event, const QPointF& point)
397{
398 // only one "touchpoint" events should be here
399 KoPointerEvent ev(event, point);
400
401 if (!d->activeTool) return;
402
403 switch (event->touchPointStates())
404 {
405 case Qt::TouchPointPressed:
406 countMultiClick(&ev, QEvent::TouchBegin);
407 break;
408 case Qt::TouchPointMoved:
410 break;
411 case Qt::TouchPointReleased:
413 break;
414 default: // don't care
415 ;
416 }
417
419}
420
425
430
435
437{
438 return d->activeTool ? d->activeTool->hasSelection() : false;
439}
440
442{
444 d->activeTool->cut();
445}
446
448{
449 if (d->activeTool)
450 d->activeTool->copy();
451}
452
454{
455 bool success = false;
456
457 if (d->activeTool && d->isActiveLayerEditable()) {
458 success = d->activeTool->paste();
459 }
460
461 return success;
462}
463
465{
466 bool success = false;
467
468 if (d->activeTool && d->isActiveLayerEditable()) {
469 success = d->activeTool->selectAll();
470 }
471
472 return success;
473}
474
476{
477 if (d->activeTool)
479}
480
481void KoToolProxy::dragMoveEvent(QDragMoveEvent *event, const QPointF &point)
482{
483 if (d->activeTool)
484 d->activeTool->dragMoveEvent(event, point);
485}
486
487void KoToolProxy::dragLeaveEvent(QDragLeaveEvent *event)
488{
489 if (d->activeTool)
490 d->activeTool->dragLeaveEvent(event);
491}
492
493void KoToolProxy::dropEvent(QDropEvent *event, const QPointF &point)
494{
495 if (d->activeTool)
496 d->activeTool->dropEvent(event, point);
497}
498
504
505void KoToolProxy::processEvent(QEvent *e) const
506{
507 if(e->type()==QEvent::ShortcutOverride
508 && d->activeTool
510 && (static_cast<QKeyEvent*>(e)->modifiers()==Qt::NoModifier ||
511 static_cast<QKeyEvent*>(e)->modifiers()==Qt::ShiftModifier
512#ifdef Q_OS_WIN
513 // we should disallow AltGr shortcuts if a text box is in focus
514 || (static_cast<QKeyEvent*>(e)->modifiers()==(Qt::AltModifier | Qt::ControlModifier) &&
515 static_cast<QKeyEvent*>(e)->key() < Qt::Key_Escape)
516#endif
517 )) {
518 e->accept();
519 }
520}
521
528
535
542
544{
545 if (d->activeTool) {
547 }
548}
549
551{
552 return d;
553}
554
555//have to include this because of Q_PRIVATE_SLOT
556#include "moc_KoToolProxy.cpp"
const Params2D p
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
A container for a set of QAction objects.
QList< QAction * > actions() const
The PopupWidgetInterface abstract class defines the basic interface that will be used by all popup wi...
virtual KoShapeManager * shapeManager() const =0
virtual void ensureVisibleDoc(const QRectF &docRect, bool smooth)=0
Scrolls the content of the canvas so that the given rect is visible.
KisKActionCollection * actionCollection
virtual KoCanvasBase * canvas() const
static InputDevice convertDeviceType(QTabletEvent *event)
static Pointer convertPointerType(QTabletEvent *event)
QPoint globalPos() const
Return the position screen coordinates.
Qt::MouseButtons buttons() const
return buttons pressed (see QMouseEvent::buttons());
bool isAccepted() const
return if the event has been accepted.
KoPointerEventWrapper deepCopyEvent() const
QPoint pos() const
return the position in widget coordinates
KoShapeLayer * activeLayer() const
KoSelection * selection
virtual bool isShapeEditable(bool recursive=true) const
checks recursively if the shape or one of its parents is not visible or locked
Definition KoShape.cpp:1165
virtual void requestRedoDuringStroke()
KoCanvasBase * canvas() const
Returns the canvas the tool is working on.
virtual void deleteSelection()
virtual void requestUndoDuringStroke()
virtual void requestStrokeCancellation()
virtual KisPopupWidgetInterface * popupWidget()
Definition KoToolBase.h:340
virtual void mouseTripleClickEvent(KoPointerEvent *event)
Q_INVOKABLE QString toolId() const
virtual void keyReleaseEvent(QKeyEvent *event)
virtual void focusInEvent(QFocusEvent *event)
virtual void dropEvent(QDropEvent *event, const QPointF &point)
virtual void copy() const
virtual bool paste()
virtual void focusOutEvent(QFocusEvent *event)
virtual void mousePressEvent(KoPointerEvent *event)=0
virtual void deselect()
deselect the tool should clear the selection if it has one.
virtual void repaintDecorations()
virtual void mouseMoveEvent(KoPointerEvent *event)=0
virtual bool hasSelection()
virtual void mouseReleaseEvent(KoPointerEvent *event)=0
virtual void keyPressEvent(QKeyEvent *event)
bool isInTextMode() const
virtual bool selectAll()
selectAll select all data the tool can select.
virtual QMenu * popupActionsMenu()
Definition KoToolBase.h:334
virtual void cut()
virtual void mouseDoubleClickEvent(KoPointerEvent *event)
virtual void requestStrokeEnd()
virtual void inputMethodEvent(QInputMethodEvent *event)
virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const
virtual void paint(QPainter &painter, const KoViewConverter &converter)=0
virtual bool wantsAutoScroll() const
virtual void dragMoveEvent(QDragMoveEvent *event, const QPointF &point)
virtual void explicitUserStrokeEndRequest()
explicitUserStrokeEndRequest is called by the input manager when the user presses Enter key or any eq...
virtual void dragLeaveEvent(QDragLeaveEvent *event)
KoToolManager::Private * priv()
static KoToolManager * instance()
Return the toolmanager singleton.
void selectionChanged(bool newSelection)
KoToolBase * activeTool
void setCanvasController(KoCanvasController *controller)
the toolManager tells us which KoCanvasController this toolProxy is working for.
QEvent::Type multiClickSource
QElapsedTimer multiClickTimeStamp
void checkAutoScroll(const KoPointerEvent &event)
boost::optional< KoPointerEventWrapper > lastPointerEvent
KoCanvasController * controller
KoToolProxyPrivate(KoToolProxy *p)
QPointF widgetScrollPointDoc
QPointF multiClickGlobalPoint
KoToolProxy * parent
QVector< QKeySequence > toolPriorityShortcuts
void mouseMoveEvent(QMouseEvent *event, const QPointF &point)
Forwarded to the current KoToolBase.
KisPopupWidgetInterface * popupWidget()
Forwarded to the current KoToolBase.
void mousePressEvent(QMouseEvent *event, const QPointF &point)
Forwarded to the current KoToolBase.
void copy() const
Forwarded to the current KoToolBase.
void deselect()
Forwarded to the current KoToolBase.
void cut()
Forwarded to the current KoToolBase.
bool hasSelection() const
returns true if the current tool holds a selection
void dragLeaveEvent(QDragLeaveEvent *event)
Forwarded to the current KoToolBase.
KoToolProxyPrivate *const d
void requestUndoDuringStroke()
Forwarded to the current KoToolBase.
KoPointerEvent * lastDeliveredPointerEvent() const
void processEvent(QEvent *) const
virtual QPointF widgetToDocument(const QPointF &widgetPoint) const =0
void requestRedoDuringStroke()
Forwarded to the current KoToolBase.
KoCanvasBase * canvas() const
void paint(QPainter &painter, const KoViewConverter &converter)
Forwarded to the current KoToolBase.
void explicitUserStrokeEndRequest()
Forwarded to the current KoToolBase.
void tabletEvent(QTabletEvent *event, const QPointF &point)
Forwarded to the current KoToolBase.
virtual QPointF documentToWidget(const QPointF &documentPoint) const =0
QMenu * popupActionsMenu()
Forwarded to the current KoToolBase.
void touchEvent(QTouchEvent *event, const QPointF &point)
void countMultiClick(KoPointerEvent *ev, int eventType)
void focusInEvent(QFocusEvent *event)
Forwarded to the current KoToolBase.
void deleteSelection()
Forwarded to the current KoToolBase.
bool paste()
Forwarded to the current KoToolBase.
bool selectAll()
Forwarded to the current KoToolBase.
void mouseDoubleClickEvent(QMouseEvent *event, const QPointF &point)
Forwarded to the current KoToolBase.
void focusOutEvent(QFocusEvent *event)
Forwarded to the current KoToolBase.
KoToolProxy(KoCanvasBase *canvas, QObject *parent=0)
QVector< QKeySequence > toolPriorityShortcuts() const
KoToolProxyPrivate * priv()
void keyReleaseEvent(QKeyEvent *event)
Forwarded to the current KoToolBase.
void toolChanged(const QString &toolId)
void requestStrokeEnd()
Forwarded to the current KoToolBase.
void requestStrokeCancellation()
Forwarded to the current KoToolBase.
void inputMethodEvent(QInputMethodEvent *event)
Forwarded to the current KoToolBase.
virtual void setActiveTool(KoToolBase *tool)
Set the new active tool.
QVariant inputMethodQuery(Qt::InputMethodQuery query) const
Forwarded to the current KoToolBase.
~KoToolProxy() override
void keyPressEvent(QKeyEvent *event)
Forwarded to the current KoToolBase.
void dropEvent(QDropEvent *event, const QPointF &point)
Forwarded to the current KoToolBase.
void dragMoveEvent(QDragMoveEvent *event, const QPointF &point)
Forwarded to the current KoToolBase.
void mouseReleaseEvent(QMouseEvent *event, const QPointF &point)
Forwarded to the current KoToolBase.
void repaintDecorations()
Forwarded to the current KoToolBase.
void selectionChanged(bool hasSelection)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130