Krita Source Code Documentation
Loading...
Searching...
No Matches
KisSelectionToolHelper Class Reference

#include <kis_selection_tool_helper.h>

Public Member Functions

void addSelectionShape (KoShape *shape, SelectionAction action=SELECTION_DEFAULT)
 
void addSelectionShapes (QList< KoShape * > shapes, SelectionAction action=SELECTION_DEFAULT)
 
bool canShortcutToDeselect (const QRect &rect, SelectionAction action)
 
bool canShortcutToNoop (const QRect &rect, SelectionAction action)
 
 KisSelectionToolHelper (KisCanvas2 *canvas, const KUndo2MagicString &name)
 
void selectPixelSelection (KisPixelSelectionSP selection, SelectionAction action)
 
void selectPixelSelection (KisProcessingApplicator &applicator, KisPixelSelectionSP selection, SelectionAction action)
 
bool tryDeselectCurrentSelection (const QRectF selectionViewRect, SelectionAction action)
 
SelectionMode tryOverrideSelectionMode (KisSelectionSP activeSelection, SelectionMode currentMode, SelectionAction currentAction) const
 
virtual ~KisSelectionToolHelper ()
 

Static Public Member Functions

static QMenu * getSelectionContextMenu (KisCanvas2 *canvas)
 

Private Attributes

QPointer< KisCanvas2m_canvas
 
KisImageSP m_image
 
KisLayerSP m_layer
 
KUndo2MagicString m_name
 

Detailed Description

XXX: Doc!

Definition at line 24 of file kis_selection_tool_helper.h.

Constructor & Destructor Documentation

◆ KisSelectionToolHelper()

KisSelectionToolHelper::KisSelectionToolHelper ( KisCanvas2 * canvas,
const KUndo2MagicString & name )

Definition at line 40 of file kis_selection_tool_helper.cpp.

41 : m_canvas(canvas)
42 , m_name(name)
43{
44 m_image = m_canvas->viewManager()->image();
45}
QPointer< KisCanvas2 > m_canvas

References m_canvas, and m_image.

◆ ~KisSelectionToolHelper()

KisSelectionToolHelper::~KisSelectionToolHelper ( )
virtual

Definition at line 47 of file kis_selection_tool_helper.cpp.

48{
49}

Member Function Documentation

◆ addSelectionShape()

void KisSelectionToolHelper::addSelectionShape ( KoShape * shape,
SelectionAction action = SELECTION_DEFAULT )

Definition at line 162 of file kis_selection_tool_helper.cpp.

163{
164 QList<KoShape*> shapes;
165 shapes.append(shape);
166 addSelectionShapes(shapes, action);
167}
void addSelectionShapes(QList< KoShape * > shapes, SelectionAction action=SELECTION_DEFAULT)

References addSelectionShapes().

◆ addSelectionShapes()

void KisSelectionToolHelper::addSelectionShapes ( QList< KoShape * > shapes,
SelectionAction action = SELECTION_DEFAULT )

Mark the shapes that they belong to a shape selection

Definition at line 169 of file kis_selection_tool_helper.cpp.

170{
171 KisView *view = m_canvas->imageView();
172
173 if (view->image()->wrapAroundModePermitted()) {
175 i18n("Shape selection does not fully "
176 "support wraparound mode. Please "
177 "use pixel selection instead"),
178 KisIconUtils::loadIcon("selection-info"));
179 }
180
181 KisProcessingApplicator applicator(view->image(),
182 0 /* we need no automatic updates */,
185 m_name);
186
187 applicator.applyCommand(new LazyInitGlobalSelection(view));
188
189 struct ClearPixelSelection : public KisTransactionBasedCommand {
190 ClearPixelSelection(KisView *view) : m_view(view) {}
191 KisView *m_view;
192
193 KUndo2Command* paint() override {
194
195 KisPixelSelectionSP pixelSelection = m_view->selection()->pixelSelection();
196 KIS_ASSERT_RECOVER(pixelSelection) { return 0; }
197
198 KisSelectionTransaction transaction(pixelSelection);
199 pixelSelection->clear();
200 return transaction.endAndTake();
201 }
202 };
203
204 if (action == SELECTION_REPLACE || action == SELECTION_DEFAULT) {
205 applicator.applyCommand(new ClearPixelSelection(view));
206 }
207
208 struct AddSelectionShape : public KisTransactionBasedCommand {
209 AddSelectionShape(KisView *view, QList<KoShape*> shapes, SelectionAction action)
210 : m_view(view),
211 m_shapes(shapes),
212 m_action(action) {}
213
214 KisView *m_view;
215 QList<KoShape*> m_shapes;
216 SelectionAction m_action;
217
218 KUndo2Command* paint() override {
219 KUndo2Command *resultCommand = 0;
220
221 KisSelectionSP selection = m_view->selection();
222 if (selection) {
223 KisShapeSelection * shapeSelection = static_cast<KisShapeSelection*>(selection->shapeSelection());
224
225 if (shapeSelection ||
226 m_action == SELECTION_SUBTRACT) {
227
228 QPainterPath path1;
229 QList<KoShape*> existingShapes;
230
231 if (shapeSelection) {
232 existingShapes = shapeSelection->shapes();
233
234 path1.setFillRule(Qt::WindingFill);
235 Q_FOREACH(KoShape *shape, existingShapes) {
236 path1 += shape->absoluteTransformation().map(shape->outline());
237 }
238 } else if (m_action == SELECTION_SUBTRACT) {
239 KisImageSP image = m_view->image();
240 path1.addRect(m_view->viewConverter()->imageRectInDocumentPixels());
241 }
242
243 QPainterPath path2;
244 path2.setFillRule(Qt::WindingFill);
245 Q_FOREACH(KoShape *shape, m_shapes) {
246 path2 += shape->absoluteTransformation().map(shape->outline());
247 }
248
249 const QTransform booleanWorkaroundTransform =
251
252 path1 = booleanWorkaroundTransform.map(path1);
253 path2 = booleanWorkaroundTransform.map(path2);
254
255 QPainterPath path = path2;
256
257 switch (m_action) {
260 path = path2;
261 break;
262
264 path = path1 & path2;
266 break;
267 case SELECTION_ADD:
268 path = path1 | path2;
269 break;
270
272 path = path1 - path2;
273 break;
275 path = (path1 | path2) - (path1 & path2);
276 break;
277 }
278
279 path = booleanWorkaroundTransform.inverted().map(path);
280
283
284 KUndo2Command *parentCommand = new KUndo2Command();
285
286 if (!existingShapes.isEmpty()) {
287 m_view->canvasBase()->shapeController()->removeShapes(existingShapes, parentCommand);
288 }
289 m_view->canvasBase()->shapeController()->addShape(newShape, 0, parentCommand);
290
291 if (path.isEmpty()) {
293 cmd->addCommand(parentCommand);
294 cmd->addCommand(new KisDeselectActiveSelectionCommand(m_view->selection(), m_view->image()));
295 parentCommand = cmd;
296 }
297
298 resultCommand = parentCommand;
299 } else if (m_action == SELECTION_INTERSECT) {
300 // just do nothing if there is nothing to intersect with
301 return nullptr;
302 }
303 }
304
305 if (!resultCommand) {
309 Q_FOREACH(KoShape *shape, m_shapes) {
310 if(!shape->userData()) {
312 }
313 }
314
315 resultCommand = m_view->canvasBase()->shapeController()->addShapesDirect(m_shapes, 0);
316 }
317 return resultCommand;
318 }
319 };
320
321 applicator.applyCommand(
322 new KisGuiContextCommand(new AddSelectionShape(view, shapes, action), view));
323 applicator.end();
324}
SelectionAction
@ SELECTION_REPLACE
@ SELECTION_INTERSECT
@ SELECTION_SYMMETRICDIFFERENCE
@ SELECTION_DEFAULT
@ SELECTION_SUBTRACT
@ SELECTION_ADD
bool wrapAroundModePermitted() const
KisCanvas2 * canvasBase() const
Definition KisView.cpp:427
bool showFloatingMessage
Definition KisView.cpp:134
KisCoordinatesConverter viewConverter
Definition KisView.cpp:125
KisImageWSP image() const
Definition KisView.cpp:432
KisSelectionSP selection()
Definition KisView.cpp:1337
QPointer< KoShapeController > shapeController
static KoPathShape * createShapeFromPainterPath(const QPainterPath &path)
Creates path shape from given QPainterPath.
QList< KoShape * > shapes() const
KoShapeUserData * userData() const
Definition KoShape.cpp:710
virtual QPainterPath outline() const
Definition KoShape.cpp:630
QTransform absoluteTransformation() const
Definition KoShape.cpp:382
void setUserData(KoShapeUserData *userData)
Definition KoShape.cpp:705
#define KIS_ASSERT_RECOVER(cond)
Definition kis_assert.h:55
QIcon loadIcon(const QString &name)
QTransform pathShapeBooleanSpaceWorkaround(KisImageSP image)
QPainterPath tryCloseTornSubpathsAfterIntersection(QPainterPath path)
void clear(const QRect &r)
KisPixelSelectionSP pixelSelection
KisSelectionComponent * shapeSelection

References KoShape::absoluteTransformation(), KisCommandUtils::CompositeCommand::addCommand(), KisProcessingApplicator::applyCommand(), KisView::canvasBase(), KisPixelSelection::clear(), KoPathShape::createShapeFromPainterPath(), KisProcessingApplicator::end(), KisTransaction::endAndTake(), KisView::image(), KisCoordinatesConverter::imageRectInDocumentPixels(), KIS_ASSERT_RECOVER, KisIconUtils::loadIcon(), m_canvas, m_name, KisProcessingApplicator::NONE, KoShape::outline(), KritaUtils::pathShapeBooleanSpaceWorkaround(), KisSelection::pixelSelection, KisView::selection(), SELECTION_ADD, SELECTION_DEFAULT, SELECTION_INTERSECT, SELECTION_REPLACE, SELECTION_SUBTRACT, SELECTION_SYMMETRICDIFFERENCE, KoShape::setUserData(), KoCanvasBase::shapeController, KoShapeContainer::shapes(), KisSelection::shapeSelection, KisView::showFloatingMessage, KritaUtils::tryCloseTornSubpathsAfterIntersection(), KoShape::userData(), KisView::viewConverter, and KisImage::wrapAroundModePermitted().

◆ canShortcutToDeselect()

bool KisSelectionToolHelper::canShortcutToDeselect ( const QRect & rect,
SelectionAction action )

Definition at line 326 of file kis_selection_tool_helper.cpp.

327{
328 return rect.isEmpty() && (action == SELECTION_INTERSECT || action == SELECTION_REPLACE);
329}

References SELECTION_INTERSECT, and SELECTION_REPLACE.

◆ canShortcutToNoop()

bool KisSelectionToolHelper::canShortcutToNoop ( const QRect & rect,
SelectionAction action )

Definition at line 331 of file kis_selection_tool_helper.cpp.

332{
333 return rect.isEmpty() && action == SELECTION_ADD;
334}

References SELECTION_ADD.

◆ getSelectionContextMenu()

QMenu * KisSelectionToolHelper::getSelectionContextMenu ( KisCanvas2 * canvas)
static

Definition at line 352 of file kis_selection_tool_helper.cpp.

353{
354 QMenu *m_contextMenu = new QMenu();
355
356 KisKActionCollection *actionCollection = canvas->viewManager()->actionCollection();
357
358 m_contextMenu->addSection(i18n("Selection Actions"));
359 m_contextMenu->addSeparator();
360
361 m_contextMenu->addAction(actionCollection->action("select_all"));
362 m_contextMenu->addAction(actionCollection->action("deselect"));
363 m_contextMenu->addAction(actionCollection->action("reselect"));
364 m_contextMenu->addAction(actionCollection->action("invert_selection"));
365
366
367 m_contextMenu->addSeparator();
368
369 m_contextMenu->addAction(actionCollection->action("cut_selection_to_new_layer"));
370 m_contextMenu->addAction(actionCollection->action("copy_selection_to_new_layer"));
371
372 m_contextMenu->addSeparator();
373
374 KisSelectionSP selection = canvas->viewManager()->selection();
375 if (selection && canvas->viewManager()->selectionEditable()) {
376 m_contextMenu->addAction(actionCollection->action("edit_selection"));
377
378 if (!selection->hasShapeSelection()) {
379 m_contextMenu->addAction(actionCollection->action("convert_to_vector_selection"));
380 } else {
381 m_contextMenu->addAction(actionCollection->action("convert_to_raster_selection"));
382 }
383
384 m_contextMenu->addAction(actionCollection->action("convert_selection_to_shape"));
385
386 QMenu *transformMenu = m_contextMenu->addMenu(i18n("Transform"));
387 transformMenu->addAction(actionCollection->action("KisToolTransform"));
388 transformMenu->addAction(actionCollection->action("selectionscale"));
389 transformMenu->addAction(actionCollection->action("growselection"));
390 transformMenu->addAction(actionCollection->action("shrinkselection"));
391 transformMenu->addAction(actionCollection->action("borderselection"));
392 transformMenu->addAction(actionCollection->action("smoothselection"));
393 transformMenu->addAction(actionCollection->action("featherselection"));
394 transformMenu->addAction(actionCollection->action("stroke_selection"));
395
396 m_contextMenu->addSeparator();
397 }
398
399 m_contextMenu->addAction(actionCollection->action("resizeimagetoselection"));
400
401 m_contextMenu->addSeparator();
402
403 m_contextMenu->addAction(actionCollection->action("toggle_display_selection"));
404 m_contextMenu->addAction(actionCollection->action("show-global-selection-mask"));
405
406 return m_contextMenu;
407}
KisViewManager * viewManager() const
A container for a set of QAction objects.
QAction * action(int index) const
KisSelectionSP selection()
virtual KisKActionCollection * actionCollection() const
bool selectionEditable()
Checks if the current global or local selection is editable.
bool hasShapeSelection() const

References KisKActionCollection::action(), KisViewManager::actionCollection(), KisSelection::hasShapeSelection(), KisViewManager::selection(), KisViewManager::selectionEditable(), and KisCanvas2::viewManager().

◆ selectPixelSelection() [1/2]

void KisSelectionToolHelper::selectPixelSelection ( KisPixelSelectionSP selection,
SelectionAction action )

Definition at line 62 of file kis_selection_tool_helper.cpp.

63{
64 KisView* view = m_canvas->imageView();
65 KisProcessingApplicator applicator(view->image(),
66 0 /* we need no automatic updates */,
69 m_name);
70
71 selectPixelSelection(applicator, selection, action);
72
73 applicator.end();
74
75}
void selectPixelSelection(KisProcessingApplicator &applicator, KisPixelSelectionSP selection, SelectionAction action)

References KisProcessingApplicator::end(), KisView::image(), m_canvas, m_name, selectPixelSelection(), and KisProcessingApplicator::SUPPORTS_WRAPAROUND_MODE.

◆ selectPixelSelection() [2/2]

void KisSelectionToolHelper::selectPixelSelection ( KisProcessingApplicator & applicator,
KisPixelSelectionSP selection,
SelectionAction action )

Definition at line 77 of file kis_selection_tool_helper.cpp.

78{
79
80 KisView* view = m_canvas->imageView();
81
83
85
86 struct ApplyToPixelSelection : public KisTransactionBasedCommand {
87 ApplyToPixelSelection(KisView *view,
88 KisPixelSelectionSP selection,
89 SelectionAction action,
90 QPointer<KisCanvas2> canvas) : m_view(view),
91 m_selection(selection),
92 m_action(action),
93 m_canvas(canvas) {}
94 KisView *m_view;
95 KisPixelSelectionSP m_selection;
96 SelectionAction m_action;
97 QPointer<KisCanvas2> m_canvas;
98
99 KUndo2Command* paint() override {
100
101 KUndo2Command *savedCommand = 0;
102 if (!m_selection->selectedExactRect().isEmpty()) {
103
104 KisSelectionSP selection = m_view->selection();
105 KIS_SAFE_ASSERT_RECOVER(selection) { return 0; }
106
107 KisPixelSelectionSP pixelSelection = selection->pixelSelection();
108 KIS_SAFE_ASSERT_RECOVER(pixelSelection) { return 0; }
109
110 bool hasSelection = !pixelSelection->isEmpty();
111
112 KisSelectionTransaction transaction(pixelSelection);
113
114 if (!hasSelection && m_action == SELECTION_SYMMETRICDIFFERENCE) {
115 m_action = SELECTION_REPLACE;
116 }
117
118 if (!hasSelection && m_action == SELECTION_SUBTRACT) {
119 pixelSelection->invert();
120 }
121
122 pixelSelection->applySelection(m_selection, m_action);
123
124 QRect dirtyRect = m_view->image()->bounds();
125 if (hasSelection &&
126 m_action != SELECTION_REPLACE &&
127 m_action != SELECTION_INTERSECT &&
128 m_action != SELECTION_SYMMETRICDIFFERENCE) {
129
130 dirtyRect = m_selection->selectedRect();
131 }
132 m_view->selection()->updateProjection(dirtyRect);
133
134 savedCommand = transaction.endAndTake();
135 pixelSelection->setDirty(dirtyRect);
136
137 // release resources: transaction will care about
138 // undo/redo, we don't need the selection anymore
139 m_selection.clear();
140 }
141
142 if (m_view->selection()->selectedExactRect().isEmpty()) {
143 KUndo2Command *deselectCommand = new KisDeselectActiveSelectionCommand(m_view->selection(), m_view->image());
144 if (savedCommand) {
146 cmd->addCommand(savedCommand);
147 cmd->addCommand(deselectCommand);
148 savedCommand = cmd;
149 } else {
150 savedCommand = deselectCommand;
151 }
152 }
153
154 return savedCommand;
155 }
156 };
157
158 applicator.applyCommand(new ApplyToPixelSelection(view, selection, action, canvas), KisStrokeJobData::SEQUENTIAL);
159
160}
QRect bounds() const override
void setDirty(const QRect &rc)
void applyCommand(KUndo2Command *command, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
bool isEmpty() const override
QRect selectedExactRect() const
void applySelection(KisPixelSelectionSP selection, SelectionAction action)
void updateProjection(const QRect &rect)
QRect selectedExactRect() const
Slow, but exact way of determining the rectangle that encloses the selection.

References KisCommandUtils::CompositeCommand::addCommand(), KisProcessingApplicator::applyCommand(), KisPixelSelection::applySelection(), KisImage::bounds(), KisSharedPtr< T >::clear(), KisTransaction::endAndTake(), KisView::image(), KisPixelSelection::invert(), KisPixelSelection::isEmpty(), KIS_SAFE_ASSERT_RECOVER, m_canvas, KisSelection::pixelSelection, KisPixelSelection::selectedExactRect(), KisSelection::selectedExactRect(), KisPixelSelection::selectedRect(), KisView::selection(), SELECTION_INTERSECT, SELECTION_REPLACE, SELECTION_SUBTRACT, SELECTION_SYMMETRICDIFFERENCE, KisStrokeJobData::SEQUENTIAL, KisPaintDevice::setDirty(), and KisSelection::updateProjection().

◆ tryDeselectCurrentSelection()

bool KisSelectionToolHelper::tryDeselectCurrentSelection ( const QRectF selectionViewRect,
SelectionAction action )

Definition at line 336 of file kis_selection_tool_helper.cpp.

337{
338 bool result = false;
339
340 if (KisAlgebra2D::maxDimension(selectionViewRect) < KisConfig(true).selectionViewSizeMinimum() &&
341 (action == SELECTION_INTERSECT || action == SELECTION_SYMMETRICDIFFERENCE || action == SELECTION_REPLACE)) {
342
343 // Queueing this action to ensure we avoid a race condition when unlocking the node system
344 QTimer::singleShot(0, m_canvas->viewManager()->selectionManager(), SLOT(deselect()));
345 result = true;
346 }
347
348 return result;
349}
QAction * deselect(const QObject *recvr, const char *slot, QObject *parent)
auto maxDimension(Size size) -> decltype(size.width())

References m_canvas, KisAlgebra2D::maxDimension(), SELECTION_INTERSECT, SELECTION_REPLACE, and SELECTION_SYMMETRICDIFFERENCE.

◆ tryOverrideSelectionMode()

SelectionMode KisSelectionToolHelper::tryOverrideSelectionMode ( KisSelectionSP activeSelection,
SelectionMode currentMode,
SelectionAction currentAction ) const

Definition at line 409 of file kis_selection_tool_helper.cpp.

410{
411 if (currentAction != SELECTION_DEFAULT && currentAction != SELECTION_REPLACE) {
412 if (activeSelection) {
413 currentMode = activeSelection->hasShapeSelection() ? SHAPE_PROTECTION : PIXEL_SELECTION;
414 }
415 }
416
417 return currentMode;
418}
@ PIXEL_SELECTION
@ SHAPE_PROTECTION

References KisSelection::hasShapeSelection(), PIXEL_SELECTION, SELECTION_DEFAULT, SELECTION_REPLACE, and SHAPE_PROTECTION.

Member Data Documentation

◆ m_canvas

QPointer<KisCanvas2> KisSelectionToolHelper::m_canvas
private

Definition at line 47 of file kis_selection_tool_helper.h.

◆ m_image

KisImageSP KisSelectionToolHelper::m_image
private

Definition at line 48 of file kis_selection_tool_helper.h.

◆ m_layer

KisLayerSP KisSelectionToolHelper::m_layer
private

Definition at line 49 of file kis_selection_tool_helper.h.

◆ m_name

KUndo2MagicString KisSelectionToolHelper::m_name
private

Definition at line 50 of file kis_selection_tool_helper.h.


The documentation for this class was generated from the following files: