Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_selection_decoration.cc
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2008 Sven Langkamp <sven.langkamp@gmail.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
9
10#include <QPainter>
11#include <QVarLengthArray>
12#include <QApplication>
13#include <QMainWindow>
14#include <QWindow>
15#include <QScreen>
16
17#include <kis_debug.h>
18#include <klocalizedstring.h>
19
20#include <KisMainWindow.h>
21#include "kis_types.h"
22#include "KisViewManager.h"
23#include "kis_selection.h"
24#include "kis_image.h"
26#include "kis_pixel_selection.h"
29#include "canvas/kis_canvas2.h"
32#include "kis_config.h"
33#include "kis_config_notifier.h"
34#include "kis_image_config.h"
36#include "kis_painting_tweaks.h"
37#include "KisView.h"
38#include "kis_selection_mask.h"
39#include <KisPart.h>
42
43static const unsigned int ANT_LENGTH = 4;
44static const unsigned int ANT_SPACE = 4;
45static const unsigned int ANT_ADVANCE_WIDTH = ANT_LENGTH + ANT_SPACE;
46
48 : KisCanvasDecoration("selection", _view),
49 m_signalCompressor(50 /*ms*/, KisSignalCompressor::FIRST_ACTIVE),
50 m_offset(0),
51 m_mode(Ants)
52{
54 connect(this->view()->canvasBase()->resourceManager(), SIGNAL(canvasResourceChanged(int, const QVariant&)), this, SLOT(slotCanvasResourcesChanged(int, const QVariant&)));
55
56 connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged()));
57 connect(KisImageConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged()));
58
59 m_antsTimer = new QTimer(this);
60 m_antsTimer->setInterval(150);
61 m_antsTimer->setSingleShot(false);
62 connect(m_antsTimer, SIGNAL(timeout()), SLOT(antsAttackEvent()));
63
64 connect(&m_signalCompressor, SIGNAL(timeout()), SLOT(slotStartUpdateSelection()));
65
66 // selections should be at the top of the stack
67 setPriority(100);
68
69 m_selectionActionsPanel = new KisSelectionActionsPanel(this->view()->viewManager());
70
72}
73
78
83
89
91{
92 KisSelectionSP selection = view()->selection();
93 return visible() && selection &&
94 (selection->hasNonEmptyPixelSelection() || selection->hasNonEmptyShapeSelection()) &&
95 selection->isVisible();
96}
97
99{
100 QColor white(Qt::white);
101 QColor black(Qt::black);
102
105 black, white);
106
107 m_antsPen.setWidth(decorationThickness());
109}
110
112{
113 KisSelectionMaskSP mask = qobject_cast<KisSelectionMask*>(view()->currentNode().data());
114 if (!mask || !mask->active() || !mask->visible(true)) {
115 mask = 0;
116 }
117
118 if (!view()->isCurrent() ||
119 view()->viewManager()->mainWindow() == KisPart::instance()->currentMainwindow()) {
120
121 view()->image()->setOverlaySelectionMask(mask);
122 }
123
124 KisSelectionSP selection = view()->selection();
125
126 if (!mask && selectionIsActive()) {
127 if ((m_mode == Ants && selection->outlineCacheValid()) ||
128 (m_mode == Mask && selection->thumbnailImageValid())) {
129
131
132 if (m_mode == Ants) {
133 m_outlinePath = selection->outlineCache();
134 m_antsTimer->start();
135 } else {
136 m_thumbnailImage = selection->thumbnailImage();
138 m_antsTimer->stop();
139 }
140
141 if (view() && view()->canvasBase()) {
142 view()->canvasBase()->updateCanvas();
143 }
144
145
147 } else {
149 }
150 } else {
152 m_outlinePath = QPainterPath();
153 m_thumbnailImage = QImage();
154 m_thumbnailImageTransform = QTransform();
155 view()->canvasBase()->updateCanvas();
156 m_antsTimer->stop();
157 }
158
159 if (!selection && !selectionIsActive()) {
161 }
162}
163
165{
166 KisSelectionSP selection = view()->selection();
167 if (!selection) return;
168
169 view()->image()->addSpontaneousJob(new KisUpdateOutlineJob(selection, m_mode == Mask, m_maskColor));
170}
171
182
184{
185 Q_UNUSED(v);
188 }
189}
190
192{
193 KisSelectionSP selection = view()->selection();
194 if (!selection) return;
195
196 if (selectionIsActive()) {
198 m_antsPen.setDashOffset(m_offset);
199 view()->canvasBase()->updateCanvas();
200 }
201}
202
206
210
211void KisSelectionDecoration::drawDecoration(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter *converter, KisCanvas2 *canvas)
212{
213 Q_UNUSED(updateRect);
214 Q_UNUSED(canvas);
215
216 // render Selection Action Bar first, so that it doesn't blink when making a new selection
217
218 if ((m_mode == Ants && m_outlinePath.isEmpty()) || (m_mode == Mask && m_thumbnailImage.isNull())
220 //The SAP needs to be drawn on top of the decoration, but to avoid the panel flashing when making a new selection, we also need to call draw here
222
223 return;
224 }
225
227 return;
228 }
229
230 QTransform transform = converter->imageToWidgetTransform();
231
232 gc.save();
233 gc.setTransform(transform, false);
234
235 if (m_mode == Mask) {
236 gc.setRenderHints(QPainter::SmoothPixmapTransform |
237 QPainter::Antialiasing, false);
238
239 gc.setTransform(m_thumbnailImageTransform, true);
240 gc.drawImage(QPoint(), m_thumbnailImage);
241
242 QRect r1 = m_thumbnailImageTransform.inverted().mapRect(view()->image()->bounds());
243 QRect r2 = m_thumbnailImage.rect();
244
245 QPainterPath p1;
246 p1.addRect(r1);
247
248 QPainterPath p2;
249 p2.addRect(r2);
250
251 KoColor c;
254 gc.setPen(Qt::NoPen);
255 gc.drawPath(p1 - p2);
256
257 } else /* if (m_mode == Ants) */ {
258
259 KoColor c;
260 c.fromQColor(Qt::white);
262 c.fromQColor(Qt::black);
264
265 gc.setRenderHints(QPainter::Antialiasing | QPainter::Antialiasing, m_antialiasSelectionOutline);
266
267 gc.setOpacity(m_opacity);
268
269 // render selection outline in white
270 gc.setPen(m_outlinePen);
271 gc.drawPath(m_outlinePath);
272
273 // render marching ants in black (above the white outline)
274 gc.setPen(m_antsPen);
275 gc.drawPath(m_outlinePath);
276 }
277
278 gc.restore();
280}
281
286
294
296{
297 if(minimized) {
298 m_antsTimer->stop();
299 } else {
301 }
302}
QPointF r2
qreal v
QPointF r1
QPointF p2
QPointF p1
KoColorDisplayRendererInterface * displayRendererInterface() const override
displayRendererInterface The display renderer interface has a number of color conversion functions wh...
KisDisplayColorConverter displayColorConverter
QPointer< KisView > view() const
virtual void setVisible(bool v)
static KisConfigNotifier * instance()
bool antialiasSelectionOutline(bool defaultValue=false) const
bool selectionActionBar(bool defaultValue=false) const
QColor convertColorToDisplayColorSpace(const KoColor color, bool applyOcio=false) const
convertColorToDisplayColorSpace This applies displayfiltering to the given KoColor,...
static KisImageConfigNotifier * instance()
qreal selectionOutlineOpacity(bool defaultValue=false) const
QColor selectionOverlayMaskColor(bool defaultValue=false) const
static KisPart * instance()
Definition KisPart.cpp:131
void canvasWidgetChanged(KisCanvasWidgetBase *canvas)
void draw(QPainter &painter, const KoColorDisplayRendererInterface *displayRendererInterface)
void notifyWindowMinimized(bool minimized) override
void setCanvasWidget(KisCanvasWidgetBase *canvas) override
void slotCanvasResourcesChanged(int key, const QVariant &v)
void drawDecoration(QPainter &gc, const QRectF &updateRect, const KisCoordinatesConverter *converter, KisCanvas2 *canvas) override
KisSignalCompressor m_signalCompressor
KisSelectionDecoration(QPointer< KisView > view)
KisSelectionActionsPanel * m_selectionActionsPanel
void fromQColor(const QColor &c)
Convenient function for converting from a QColor.
Definition KoColor.cpp:213
#define bounds(x, a, b)
static const unsigned int ANT_LENGTH
static const unsigned int ANT_ADVANCE_WIDTH
static const unsigned int ANT_SPACE
void initAntsPen(QPen *antsPen, QPen *outlinePen, int antLength, int antSpace, QColor black, QColor white)
@ DecorationThickness
Integer, the thickness of single px decorations, will be adjusted by HiDPI settings....
virtual bool visible(bool recursive=false) const
bool hasNonEmptyPixelSelection() const
bool thumbnailImageValid() const
QTransform thumbnailImageTransform() const
bool outlineCacheValid() const
QImage thumbnailImage() const
bool hasNonEmptyShapeSelection() const
QPainterPath outlineCache() const