Krita Source Code Documentation
Loading...
Searching...
No Matches
KisToolOutlineBase.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2000 John Califf <jcaliff@compuzone.net>
3 * SPDX-FileCopyrightText: 2002 Patrick Julien <freak@codepimps.org>
4 * SPDX-FileCopyrightText: 2004 Boudewijn Rempt <boud@valdyas.org>
5 * SPDX-FileCopyrightText: 2007 Sven Langkamp <sven.langkamp@gmail.com>
6 * SPDX-FileCopyrightText: 2015 Michael Abrahams <miabraha@gmail.com>
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11#include <QAction>
12
13#include <KoPointerEvent.h>
14#include <KoShapeController.h>
15#include <KoViewConverter.h>
16#include <KisViewManager.h>
17#include <KoCanvasBase.h>
18#include <kis_icon.h>
19#include <kis_canvas2.h>
21
22#include "KisToolOutlineBase.h"
24
25KisToolOutlineBase::KisToolOutlineBase(KoCanvasBase * canvas, ToolType type, const QCursor & cursor)
26 : KisToolShape(canvas, cursor)
27 , m_continuedMode(false)
28 , m_type(type)
29 , m_numberOfContinuedModePoints(0)
30 , m_hasUserInteractionRunning(false)
31{}
32
35
37{
38 // Allow to enter continued mode only if we started drawing the shape
39 if (mode() == PAINT_MODE && event->key() == Qt::Key_Control) {
40 m_continuedMode = true;
42 }
44}
45
47{
48 if (event->key() == Qt::Key_Control ||
49 !(event->modifiers() & Qt::ControlModifier)) {
50 m_continuedMode = false;
51 if (mode() != PAINT_MODE) {
52 endStroke();
53 }
54 }
56}
57
72
73void KisToolOutlineBase::activate(const QSet<KoShape *> &shapes)
74{
76 connect(action("undo_polygon_selection"), SIGNAL(triggered()), SLOT(undoLastPoint()), Qt::UniqueConnection);
77
78 KisInputManager *inputManager = (static_cast<KisCanvas2*>(canvas()))->globalInputManager();
79 if (inputManager) {
80 inputManager->attachPriorityEventFilter(this);
81 }
82}
83
85{
87
88 KisCanvas2 * kisCanvas = dynamic_cast<KisCanvas2*>(canvas());
90 kisCanvas->updateCanvas();
91
92 m_continuedMode = false;
93
94 KisInputManager *inputManager = kisCanvas->globalInputManager();
95 if (inputManager) {
96 inputManager->detachPriorityEventFilter(this);
97 }
98
100}
101
106
107// Install an event filter to catch right-click events.
108// The simplest way to accommodate the popup palette binding.
109bool KisToolOutlineBase::eventFilter(QObject *obj, QEvent *event)
110{
111 Q_UNUSED(obj);
112
113 if (m_points.isEmpty()) {
114 return false;
115 }
116 if (event->type() == QEvent::MouseButtonPress ||
117 event->type() == QEvent::MouseButtonDblClick) {
118 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
119 if (mouseEvent->button() == Qt::RightButton) {
121 return true;
122 }
123 } else if (event->type() == QEvent::TabletPress) {
124 QTabletEvent *tabletEvent = static_cast<QTabletEvent*>(event);
125 if (tabletEvent->button() == Qt::RightButton) {
127 return true;
128 }
129 }
130 return false;
131}
132
134{
135 if(!m_points.isEmpty() && m_continuedMode && mode() != PAINT_MODE && m_numberOfContinuedModePoints > 0) {
136 // Initialize with the dragging segment's rect
137 QRectF updateRect = dragBoundingRect();
138
139 if (m_points.size() > 1) {
140 // Add the rect for the last segment
141 const QRectF lastSegmentRect =
142 pixelToView(QRectF(m_points.last(), m_points.at(m_points.size() - 2)).normalized())
144 updateRect = updateRect.united(lastSegmentRect);
145
146 m_points.pop_back();
148 }
149
150 // Add the new dragging segment's rect
151 updateRect = updateRect.united(dragBoundingRect());
152 updateCanvasViewRect(updateRect);
153 }
154}
155
157{
158 NodePaintAbility paintability = nodePaintAbility();
159 if ((m_type == PAINT && (!nodeEditable() || paintability == UNPAINTABLE || paintability == KisToolPaint::CLONE || paintability == KisToolPaint::MYPAINTBRUSH_UNPAINTABLE)) || (m_type == SELECT && !selectionEditable())) {
160
161 if (paintability == KisToolPaint::CLONE){
162 KisCanvas2 * kiscanvas = static_cast<KisCanvas2*>(canvas());
163 QString message = i18n("This tool cannot paint on clone layers. Please select a paint or vector layer or mask.");
164 kiscanvas->viewManager()->showFloatingMessage(message, koIcon("object-locked"));
165 }
166
167 if (paintability == KisToolPaint::MYPAINTBRUSH_UNPAINTABLE) {
168 KisCanvas2 * kiscanvas = static_cast<KisCanvas2*>(canvas());
169 QString message = i18n("The MyPaint Brush Engine is not available for this colorspace");
170 kiscanvas->viewManager()->showFloatingMessage(message, koIcon("object-locked"));
171 }
172
173 event->ignore();
174 return;
175 }
176
178
179 if (!m_continuedMode || m_points.isEmpty()) {
181 beginShape();
182 }
183
184 if (m_continuedMode) {
187 } else {
189 m_points.append(convertToPixelCoord(event));
190 }
191}
192
201
203{
206 if (!m_continuedMode) {
207 // If the event was not originated by the user releasing the button
208 // (for example due to the canvas loosing focus), then we just cancel
209 // the operation. This prevents some issues with shapes being added
210 // after the image was closed while the shape was being made
211 if (event->spontaneous()) {
212 endStroke();
213 } else {
214 cancelStroke();
215 }
216 event->accept();
217 }
218}
219
220void KisToolOutlineBase::paint(QPainter& gc, const KoViewConverter &converter)
221{
222 if ((mode() == KisTool::PAINT_MODE || m_continuedMode) && !m_points.isEmpty()) {
223 QPainterPath outline;
224 outline.moveTo(pixelToView(m_points.first()));
225 for (qint32 i = 1; i < m_points.size(); ++i) {
226 outline.lineTo(pixelToView(m_points[i]));
227 }
229 outline.lineTo(pixelToView(m_lastCursorPos));
230 }
231 paintToolOutline(&gc, outline);
232 }
233
234 KisToolShape::paint(gc, converter);
235}
236
238{
239 if (m_points.count() > 1) {
240 qint32 lastPointIndex = m_points.count() - 1;
241
242 QRectF updateRect = QRectF(m_points[lastPointIndex - 1], m_points[lastPointIndex]).normalized();
243 updateRect = kisGrowRect(updateRect, FEEDBACK_LINE_WIDTH);
244
245 updateCanvasPixelRect(updateRect);
246 }
247}
248
250{
251 QRectF updateRect = pixelToView(QRectF(m_points.last(), m_lastCursorPos).normalized());
252 updateRect = kisGrowRect(updateRect, FEEDBACK_LINE_WIDTH);
253 return updateRect;
254}
255
262
267
281
283{
285 return;
286 }
290
291 m_points.clear();
292 endShape();
293}
294
299
304
314
@ ToolInvoactionActionGroup
@ ViewTransformActionGroup
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
KisInputManager * globalInputManager() const
void updateCanvas(const QRectF &rc) override
KisViewManager * viewManager() const
Central object to manage canvas input.
void detachPriorityEventFilter(QObject *filter)
detachPriorityEventFilter
void attachPriorityEventFilter(QObject *filter, int priority=0)
attachPriorityEventFilter
The PopupWidgetInterface abstract class defines the basic interface that will be used by all popup wi...
QScopedPointer< KisInputActionGroupsMaskGuard > m_blockModifyingActionsGuard
void requestStrokeCancellation() override
KisPopupWidgetInterface * popupWidget() override
KisToolOutlineBase(KoCanvasBase *canvas, ToolType type, const QCursor &cursor=KisCursor::load("tool_outline_selection_cursor.png", 6, 6))
static constexpr int FEEDBACK_LINE_WIDTH
void continuePrimaryAction(KoPointerEvent *event) override
void beginPrimaryAction(KoPointerEvent *event) override
bool hasUserInteractionRunning() const
bool eventFilter(QObject *obj, QEvent *event) override
void endPrimaryAction(KoPointerEvent *event) override
void activate(const QSet< KoShape * > &shapes) override
void keyPressEvent(QKeyEvent *event) override
void requestStrokeEnd() override
void deactivate() override
void paint(QPainter &gc, const KoViewConverter &converter) override
QVector< QPointF > m_points
void mouseMoveEvent(KoPointerEvent *event) override
void keyReleaseEvent(QKeyEvent *event) override
virtual void finishOutline(const QVector< QPointF > &points)=0
virtual void requestUpdateOutline(const QPointF &outlineDocPoint, const KoPointerEvent *event)
void setMode(ToolMode mode) override
virtual void beginShape()
virtual void endShape()
void activate(const QSet< KoShape * > &shapes) override
void showFloatingMessage(const QString &message, const QIcon &icon, int timeout=4500, KisFloatingMessage::Priority priority=KisFloatingMessage::Medium, int alignment=Qt::AlignCenter|Qt::TextWordWrap)
shows a floating message in the top right corner of the canvas
bool spontaneous() const
return if this event was spontaneous (see QMouseEvent::spontaneous())
QPointF point
The point in document coordinates.
virtual KisPopupWidgetInterface * popupWidget()
Definition KoToolBase.h:340
virtual void keyReleaseEvent(QKeyEvent *event)
virtual void mouseMoveEvent(KoPointerEvent *event)=0
virtual void keyPressEvent(QKeyEvent *event)
virtual void deactivate()
QAction * action(const QString &name) const
virtual void paint(QPainter &painter, const KoViewConverter &converter)=0
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75
T kisGrowRect(const T &rect, U offset)
Definition kis_global.h:186
#define koIcon(name)
Use these macros for icons without any issues.
Definition kis_icon.h:25
#define CHECK_MODE_SANITY_OR_RETURN(_mode)
Definition kis_tool.h:27
QPointF convertToPixelCoord(KoPointerEvent *e)
Definition kis_tool.cc:189
virtual ToolMode mode() const
Definition kis_tool.cc:407
void updateCanvasPixelRect(const QRectF &pixelRect)
Update the canvas for the given rectangle in image pixel coordinates.
Definition kis_tool.cc:322
KisTool::NodePaintAbility nodePaintAbility()
Definition kis_tool.cc:539
bool nodeEditable()
Checks checks if the current node is editable.
Definition kis_tool.cc:651
QPointF pixelToView(const QPoint &pixelCoord) const
Definition kis_tool.cc:269
void paintToolOutline(QPainter *painter, const KisOptimizedBrushOutline &path)
Definition kis_tool.cc:589
@ PAINT_MODE
Definition kis_tool.h:300
@ HOVER_MODE
Definition kis_tool.h:299
QPointF convertToPixelCoordAndSnap(KoPointerEvent *e, const QPointF &offset=QPointF(), bool useModifiers=true)
Definition kis_tool.cc:214
bool selectionEditable()
Checks checks if the selection is editable, only applies to local selection as global selection is al...
Definition kis_tool.cc:696
void updateCanvasViewRect(const QRectF &viewRect)
Update the canvas for the given rectangle in view coordinates.
Definition kis_tool.cc:327
NodePaintAbility
Definition kis_tool.h:148
@ MYPAINTBRUSH_UNPAINTABLE
Definition kis_tool.h:153
@ UNPAINTABLE
Definition kis_tool.h:152
KisCanvas2 * canvas