File indexing completed on 2024-05-19 04:29:07

0001 
0002 /*
0003  *  SPDX-FileCopyrightText: 2004 Boudewijn Rempt <boud@valdyas.org>
0004  *  SPDX-FileCopyrightText: 2007 Sven Langkamp <sven.langkamp@gmail.com>
0005  *
0006  *  The outline algorithm uses the limn algorithm of fontutils by
0007  *  Karl Berry <karl@cs.umb.edu> and Kathryn Hargreaves <letters@cs.umb.edu>
0008  *
0009  *  SPDX-License-Identifier: GPL-2.0-or-later
0010  */
0011 
0012 #include "kis_selection_manager.h"
0013 #include <QApplication>
0014 #include <QClipboard>
0015 #include <QColor>
0016 #include <QTimer>
0017 #include <QMimeData>
0018 
0019 #include <QAction>
0020 #include <ktoggleaction.h>
0021 #include <klocalizedstring.h>
0022 #include <kstandardaction.h>
0023 #include <kactioncollection.h>
0024 
0025 #include <KoProperties.h>
0026 #include "KoCanvasController.h"
0027 #include "KoChannelInfo.h"
0028 #include "KoIntegerMaths.h"
0029 #include <KisDocument.h>
0030 #include <KisMainWindow.h>
0031 #include <KoSelection.h>
0032 #include <KoShapeManager.h>
0033 #include <KoSelectedShapesProxy.h>
0034 #include <KoShapeStroke.h>
0035 #include <KoColorSpace.h>
0036 #include <KoCompositeOp.h>
0037 #include <KoToolProxy.h>
0038 #include <KoSvgPaste.h>
0039 #include <kis_icon.h>
0040 
0041 #include "kis_adjustment_layer.h"
0042 #include "kis_node_manager.h"
0043 #include "canvas/kis_canvas2.h"
0044 #include "kis_config.h"
0045 #include "kis_convolution_painter.h"
0046 #include "kis_convolution_kernel.h"
0047 #include "kis_debug.h"
0048 #include "kis_fill_painter.h"
0049 #include "kis_group_layer.h"
0050 #include "kis_layer.h"
0051 #include "kis_statusbar.h"
0052 #include "kis_paint_device.h"
0053 #include "kis_paint_layer.h"
0054 #include "kis_painter.h"
0055 #include "kis_transaction.h"
0056 #include "kis_selection.h"
0057 #include "kis_types.h"
0058 #include "kis_canvas_resource_provider.h"
0059 #include "kis_undo_adapter.h"
0060 #include "kis_pixel_selection.h"
0061 #include "flake/kis_shape_selection.h"
0062 #include "commands/kis_selection_commands.h"
0063 #include "kis_selection_mask.h"
0064 #include "flake/kis_shape_layer.h"
0065 #include "kis_selection_decoration.h"
0066 #include "canvas/kis_canvas_decoration.h"
0067 #include "kis_node_commands_adapter.h"
0068 #include "kis_iterator_ng.h"
0069 #include "kis_clipboard.h"
0070 #include "KisViewManager.h"
0071 #include "kis_selection_filters.h"
0072 #include "kis_figure_painting_tool_helper.h"
0073 #include "KisView.h"
0074 #include "dialogs/kis_dlg_stroke_selection_properties.h"
0075 
0076 #include "actions/kis_selection_action_factories.h"
0077 #include "actions/KisPasteActionFactories.h"
0078 #include "kis_action.h"
0079 #include "kis_action_manager.h"
0080 #include "operations/kis_operation_configuration.h"
0081 //new
0082 #include "kis_node_query_path.h"
0083 #include "kis_tool_shape.h"
0084 
0085 KisSelectionManager::KisSelectionManager(KisViewManager * view)
0086         : m_view(view)
0087         , m_adapter(new KisNodeCommandsAdapter(view))
0088 {
0089     m_clipboard = KisClipboard::instance();
0090 }
0091 
0092 KisSelectionManager::~KisSelectionManager()
0093 {
0094 }
0095 
0096 void KisSelectionManager::setup(KisActionManager* actionManager)
0097 {
0098     m_cut = actionManager->createStandardAction(KStandardAction::Cut, this, SLOT(cut()));
0099     m_copy = actionManager->createStandardAction(KStandardAction::Copy, this, SLOT(copy()));
0100     m_paste = actionManager->createStandardAction(KStandardAction::Paste, this, SLOT(paste()));
0101 
0102     KisAction *action = actionManager->createAction("copy_sharp");
0103     connect(action, SIGNAL(triggered()), this, SLOT(copySharp()));
0104 
0105     action = actionManager->createAction("cut_sharp");
0106     connect(action, SIGNAL(triggered()), this, SLOT(cutSharp()));
0107 
0108     m_pasteNew = actionManager->createAction("paste_new");
0109     connect(m_pasteNew, SIGNAL(triggered()), this, SLOT(pasteNew()));
0110 
0111     m_pasteAt = actionManager->createAction("paste_at");
0112     connect(m_pasteAt, SIGNAL(triggered()), this, SLOT(pasteAt()));
0113 
0114     m_pasteInto = actionManager->createAction("paste_into");
0115     connect(m_pasteInto, SIGNAL(triggered()), this, SLOT(pasteInto()));
0116 
0117     m_pasteAsReference = actionManager->createAction("paste_as_reference");
0118     connect(m_pasteAsReference, SIGNAL(triggered()), this, SLOT(pasteAsReference()));
0119 
0120     m_pasteShapeStyle = actionManager->createAction("paste_shape_style");
0121     connect(m_pasteShapeStyle, SIGNAL(triggered()), this, SLOT(pasteShapeStyle()));
0122 
0123     m_copyMerged = actionManager->createAction("copy_merged");
0124     connect(m_copyMerged, SIGNAL(triggered()), this, SLOT(copyMerged()));
0125 
0126     m_selectAll = actionManager->createAction("select_all");
0127     connect(m_selectAll, SIGNAL(triggered()), this, SLOT(selectAll()));
0128 
0129     m_deselect = actionManager->createAction("deselect");
0130     connect(m_deselect, SIGNAL(triggered()), this, SLOT(deselect()));
0131 
0132     m_clear = actionManager->createAction("clear");
0133     connect(m_clear, SIGNAL(triggered()), SLOT(clear()));
0134 
0135     m_reselect = actionManager->createAction("reselect");
0136     connect(m_reselect, SIGNAL(triggered()), this, SLOT(reselect()));
0137 
0138     m_invert = actionManager->createAction("invert_selection");
0139     m_invert->setOperationID("invertselection");
0140 
0141     actionManager->registerOperation(new KisInvertSelectionOperation);
0142 
0143     m_copyToNewLayer = actionManager->createAction("copy_selection_to_new_layer");
0144     connect(m_copyToNewLayer, SIGNAL(triggered()), this, SLOT(copySelectionToNewLayer()));
0145 
0146     m_cutToNewLayer = actionManager->createAction("cut_selection_to_new_layer");
0147     connect(m_cutToNewLayer, SIGNAL(triggered()), this, SLOT(cutToNewLayer()));
0148 
0149     m_fillForegroundColor = actionManager->createAction("fill_selection_foreground_color");
0150     connect(m_fillForegroundColor, SIGNAL(triggered()), this, SLOT(fillForegroundColor()));
0151 
0152     m_fillBackgroundColor  = actionManager->createAction("fill_selection_background_color");
0153     connect(m_fillBackgroundColor, SIGNAL(triggered()), this, SLOT(fillBackgroundColor()));
0154 
0155     m_fillPattern = actionManager->createAction("fill_selection_pattern");
0156     connect(m_fillPattern, SIGNAL(triggered()), this, SLOT(fillPattern()));
0157 
0158     m_fillForegroundColorOpacity  = actionManager->createAction("fill_selection_foreground_color_opacity");
0159     connect(m_fillForegroundColorOpacity, SIGNAL(triggered()), this, SLOT(fillForegroundColorOpacity()));
0160 
0161     m_fillBackgroundColorOpacity  = actionManager->createAction("fill_selection_background_color_opacity");
0162     connect(m_fillBackgroundColorOpacity, SIGNAL(triggered()), this, SLOT(fillBackgroundColorOpacity()));
0163 
0164     m_fillPatternOpacity  = actionManager->createAction("fill_selection_pattern_opacity");
0165     connect(m_fillPatternOpacity, SIGNAL(triggered()), this, SLOT(fillPatternOpacity()));
0166 
0167     m_strokeShapes  = actionManager->createAction("stroke_shapes");
0168     connect(m_strokeShapes, SIGNAL(triggered()), this, SLOT(paintSelectedShapes()));
0169 
0170     m_toggleDisplaySelection  = actionManager->createAction("toggle_display_selection");
0171     connect(m_toggleDisplaySelection, SIGNAL(triggered()), this, SLOT(toggleDisplaySelection()));
0172     m_toggleDisplaySelection->setChecked(true);
0173 
0174     m_imageResizeToSelection  = actionManager->createAction("resizeimagetoselection");
0175     connect(m_imageResizeToSelection, SIGNAL(triggered()), this, SLOT(imageResizeToSelection()));
0176 
0177     action = actionManager->createAction("edit_selection");
0178     connect(action, SIGNAL(triggered()), SLOT(editSelection()));
0179 
0180     action = actionManager->createAction("convert_to_vector_selection");
0181     connect(action, SIGNAL(triggered()), SLOT(convertToVectorSelection()));
0182 
0183     action = actionManager->createAction("convert_to_raster_selection");
0184     connect(action, SIGNAL(triggered()), SLOT(convertToRasterSelection()));
0185 
0186     action = actionManager->createAction("convert_shapes_to_vector_selection");
0187     connect(action, SIGNAL(triggered()), SLOT(convertShapesToVectorSelection()));
0188 
0189     action = actionManager->createAction("convert_selection_to_shape");
0190     connect(action, SIGNAL(triggered()), SLOT(convertToShape()));
0191 
0192     m_toggleSelectionOverlayMode  = actionManager->createAction("toggle-selection-overlay-mode");
0193     connect(m_toggleSelectionOverlayMode, SIGNAL(triggered()), SLOT(slotToggleSelectionDecoration()));
0194 
0195     m_strokeSelected = actionManager->createAction("stroke_selection");
0196     connect(m_strokeSelected, SIGNAL(triggered()), SLOT(slotStrokeSelection()));
0197 
0198     QClipboard *cb = QApplication::clipboard();
0199     connect(cb, SIGNAL(dataChanged()), SLOT(clipboardDataChanged()));
0200 }
0201 
0202 
0203 void KisSelectionManager::setView(QPointer<KisView>imageView)
0204 {
0205     if (m_imageView && m_imageView->canvasBase()) {
0206         disconnect(m_imageView->canvasBase()->toolProxy(), SIGNAL(toolChanged(QString)), this, SLOT(clipboardDataChanged()));
0207 
0208         KoSelection *selection = m_imageView->canvasBase()->globalShapeManager()->selection();
0209         selection->disconnect(this, SLOT(shapeSelectionChanged()));
0210         KisSelectionDecoration *decoration = qobject_cast<KisSelectionDecoration*>(m_imageView->canvasBase()->decoration("selection").data());
0211         if (decoration) {
0212             disconnect(SIGNAL(currentSelectionChanged()), decoration);
0213         }
0214         m_imageView->image()->undoAdapter()->disconnect(this);
0215         m_selectionDecoration = 0;
0216     }
0217 
0218     m_imageView = imageView;
0219     if (m_imageView) {
0220         connect(m_imageView->canvasBase()->selectedShapesProxy(), SIGNAL(selectionChanged()), this, SLOT(shapeSelectionChanged()), Qt::UniqueConnection);
0221 
0222         KisSelectionDecoration* decoration = qobject_cast<KisSelectionDecoration*>(m_imageView->canvasBase()->decoration("selection").data());
0223         if (!decoration) {
0224             decoration = new KisSelectionDecoration(m_imageView);
0225             decoration->setVisible(true);
0226             m_imageView->canvasBase()->addDecoration(decoration);
0227         }
0228         m_selectionDecoration = decoration;
0229         connect(this, SIGNAL(currentSelectionChanged()), decoration, SLOT(selectionChanged()));
0230         connect(m_imageView->image()->undoAdapter(), SIGNAL(selectionChanged()), SLOT(selectionChanged()));
0231         connect(m_imageView->canvasBase()->toolProxy(), SIGNAL(toolChanged(QString)), SLOT(clipboardDataChanged()));
0232 
0233     }
0234 }
0235 
0236 
0237 void KisSelectionManager::clipboardDataChanged()
0238 {
0239     m_view->updateGUI();
0240 }
0241 
0242 bool KisSelectionManager::havePixelsSelected()
0243 {
0244     KisSelectionSP activeSelection = m_view->selection();
0245     return activeSelection && !activeSelection->selectedRect().isEmpty();
0246 }
0247 
0248 bool KisSelectionManager::havePixelsInClipboard()
0249 {
0250     return m_clipboard->hasClip();
0251 }
0252 
0253 bool KisSelectionManager::haveShapesSelected()
0254 {
0255     if (m_view && m_view->canvasBase()) {
0256         return m_view->canvasBase()->selectedShapesProxy()->selection()->count() > 0;
0257     }
0258     return false;
0259 }
0260 
0261 bool KisSelectionManager::haveShapesInClipboard()
0262 {
0263     KoSvgPaste paste;
0264     return paste.hasShapes();
0265 }
0266 
0267 bool KisSelectionManager::haveAnySelectionWithPixels()
0268 {
0269     KisSelectionSP selection = m_view->selection();
0270     return selection && selection->hasNonEmptyPixelSelection();
0271 }
0272 
0273 bool KisSelectionManager::haveShapeSelectionWithShapes()
0274 {
0275     KisSelectionSP selection = m_view->selection();
0276     return selection && selection->hasNonEmptyShapeSelection();
0277 }
0278 
0279 bool KisSelectionManager::haveRasterSelectionWithPixels()
0280 {
0281     KisSelectionSP selection = m_view->selection();
0282     return selection && selection->hasNonEmptyPixelSelection() && !selection->hasNonEmptyShapeSelection();
0283 }
0284 
0285 bool KisSelectionManager::canReselectDeactivatedSelection()
0286 {
0287     if (!m_view) return false;
0288 
0289     KisLayerSP layer = m_view->activeLayer();
0290 
0291     if (layer) {
0292         /**
0293          * If we have an active selection mask, then
0294          * no reselection is possible
0295          */
0296         if (layer->selectionMask()) return false;
0297 
0298         KoProperties properties;
0299         properties.setProperty("active", false);
0300         properties.setProperty("visible", true);
0301         QList<KisNodeSP> masks = layer->childNodes(QStringList("KisSelectionMask"), properties);
0302 
0303         if (!masks.isEmpty()) {
0304             return true;
0305         }
0306     }
0307 
0308     KisImageSP image = m_view->image();
0309     return image && image->canReselectGlobalSelection();
0310 }
0311 
0312 void KisSelectionManager::updateGUI()
0313 {
0314     Q_ASSERT(m_view);
0315     Q_ASSERT(m_clipboard);
0316     if (!m_view || !m_clipboard) return;
0317 
0318     bool havePixelsInClipboard = this->havePixelsInClipboard();
0319     bool haveDevice = m_view->activeDevice();
0320 
0321     KisLayerSP activeLayer = m_view->activeLayer();
0322     KisImageWSP image = activeLayer ? activeLayer->image() : 0;
0323 
0324     // FIXME: how about pasting shapes?
0325     // TODO: check if these manual update actually work and not
0326     //       overridden by KisActionManager
0327     m_pasteNew->setEnabled(havePixelsInClipboard);
0328     m_pasteAsReference->setEnabled(haveDevice);
0329 
0330     updateStatusBar();
0331     emit signalUpdateGUI();
0332 }
0333 
0334 void KisSelectionManager::updateStatusBar()
0335 {
0336     if (m_view && m_view->statusBar()) {
0337         m_view->statusBar()->setSelection(m_view->image());
0338     }
0339 }
0340 
0341 void KisSelectionManager::selectionChanged()
0342 {
0343     m_view->updateGUI();
0344     emit currentSelectionChanged();
0345 }
0346 
0347 void KisSelectionManager::cut()
0348 {
0349     KisCutCopyActionFactory factory;
0350     factory.run(true, false, m_view);
0351 }
0352 
0353 void KisSelectionManager::copy()
0354 {
0355     KisCutCopyActionFactory factory;
0356     factory.run(false, false, m_view);
0357 }
0358 
0359 void KisSelectionManager::cutSharp()
0360 {
0361     KisCutCopyActionFactory factory;
0362     factory.run(true, true, m_view);
0363 }
0364 
0365 void KisSelectionManager::copySharp()
0366 {
0367     KisCutCopyActionFactory factory;
0368     factory.run(false, true, m_view);
0369 }
0370 
0371 void KisSelectionManager::copyMerged()
0372 {
0373     KisCopyMergedActionFactory factory;
0374     factory.run(m_view);
0375 }
0376 
0377 void KisSelectionManager::paste()
0378 {
0379     KisPasteActionFactory factory;
0380     factory.run(false, m_view);
0381 }
0382 
0383 void KisSelectionManager::pasteAt()
0384 {
0385     KisPasteActionFactory factory;
0386     factory.run(true, m_view);
0387 }
0388 
0389 void KisSelectionManager::pasteInto()
0390 {
0391     KisPasteIntoActionFactory factory;
0392     factory.run(m_view);
0393 }
0394 
0395 void KisSelectionManager::pasteAsReference()
0396 {
0397     KisPasteReferenceActionFactory factory;
0398     factory.run(m_view);
0399 }
0400 
0401 void KisSelectionManager::pasteNew()
0402 {
0403     KisPasteNewActionFactory factory;
0404     factory.run(m_view);
0405 }
0406 
0407 void KisSelectionManager::pasteShapeStyle()
0408 {
0409     KisPasteShapeStyleActionFactory factory;
0410     factory.run(m_view);
0411 }
0412 
0413 void KisSelectionManager::selectAll()
0414 {
0415     KisSelectAllActionFactory factory;
0416     factory.run(m_view);
0417 }
0418 
0419 void KisSelectionManager::deselect()
0420 {
0421     KisDeselectActionFactory factory;
0422     factory.run(m_view);
0423 }
0424 
0425 void KisSelectionManager::invert()
0426 {
0427     if(m_invert)
0428         m_invert->trigger();
0429 }
0430 
0431 void KisSelectionManager::reselect()
0432 {
0433     KisReselectActionFactory factory;
0434     factory.run(m_view);
0435 }
0436 
0437 
0438 #include <KoToolManager.h>
0439 #include <KoInteractionTool.h>
0440 
0441 void KisSelectionManager::editSelection()
0442 {
0443     KisSelectionSP selection = m_view->selection();
0444     if (!selection) return;
0445 
0446     KisAction *action = m_view->actionManager()->actionByName("show-global-selection-mask");
0447     KIS_SAFE_ASSERT_RECOVER_RETURN(action);
0448 
0449     if (!action->isChecked()) {
0450         action->setChecked(true);
0451         emit action->toggled(true);
0452         emit action->triggered(true);
0453     }
0454 
0455     KisNodeSP node = selection->parentNode();
0456     KIS_SAFE_ASSERT_RECOVER_RETURN(node);
0457 
0458     m_view->nodeManager()->slotNonUiActivatedNode(node);
0459 
0460     if (selection->hasShapeSelection()) {
0461         KisShapeSelection *shapeSelection = dynamic_cast<KisShapeSelection*>(selection->shapeSelection());
0462         KIS_SAFE_ASSERT_RECOVER_RETURN(shapeSelection);
0463 
0464         KoToolManager::instance()->switchToolRequested(KoInteractionTool_ID);
0465 
0466         QList<KoShape*> shapes = shapeSelection->shapes();
0467 
0468         if (shapes.isEmpty()) {
0469             KIS_SAFE_ASSERT_RECOVER_NOOP(0 && "no shapes");
0470             return;
0471         }
0472 
0473         Q_FOREACH (KoShape *shape, shapes) {
0474             m_view->canvasBase()->selectedShapesProxy()->selection()->select(shape);
0475         }
0476     } else {
0477         KoToolManager::instance()->switchToolRequested("KisToolTransform");
0478     }
0479 }
0480 
0481 void KisSelectionManager::convertToVectorSelection()
0482 {
0483     KisSelectionToVectorActionFactory factory;
0484     factory.run(m_view);
0485 }
0486 
0487 void KisSelectionManager::convertToRasterSelection()
0488 {
0489     KisSelectionToRasterActionFactory factory;
0490     factory.run(m_view);
0491 }
0492 
0493 void KisSelectionManager::convertShapesToVectorSelection()
0494 {
0495     KisShapesToVectorSelectionActionFactory factory;
0496     factory.run(m_view);
0497 }
0498 
0499 void KisSelectionManager::convertToShape()
0500 {
0501     KisSelectionToShapeActionFactory factory;
0502     factory.run(m_view);
0503 }
0504 
0505 void KisSelectionManager::clear()
0506 {
0507     KisClearActionFactory factory;
0508     factory.run(m_view);
0509 }
0510 
0511 void KisSelectionManager::fillForegroundColor()
0512 {
0513     KisFillActionFactory  factory;
0514     factory.run("fg", m_view);
0515 }
0516 
0517 void KisSelectionManager::fillBackgroundColor()
0518 {
0519     KisFillActionFactory factory;
0520     factory.run("bg", m_view);
0521 }
0522 
0523 void KisSelectionManager::fillPattern()
0524 {
0525     KisFillActionFactory factory;
0526     factory.run("pattern", m_view);
0527 }
0528 
0529 void KisSelectionManager::fillForegroundColorOpacity()
0530 {
0531     KisFillActionFactory  factory;
0532     factory.run("fg_opacity", m_view);
0533 }
0534 
0535 void KisSelectionManager::fillBackgroundColorOpacity()
0536 {
0537     KisFillActionFactory factory;
0538     factory.run("bg_opacity", m_view);
0539 }
0540 
0541 void KisSelectionManager::fillPatternOpacity()
0542 {
0543     KisFillActionFactory factory;
0544     factory.run("pattern_opacity", m_view);
0545 }
0546 
0547 void KisSelectionManager::copySelectionToNewLayer()
0548 {
0549     copy();
0550     paste();
0551 }
0552 
0553 void KisSelectionManager::cutToNewLayer()
0554 {
0555     cut();
0556     paste();
0557 }
0558 
0559 void KisSelectionManager::toggleDisplaySelection()
0560 {
0561     KIS_ASSERT_RECOVER_RETURN(m_selectionDecoration);
0562 
0563     m_selectionDecoration->toggleVisibility();
0564     m_toggleDisplaySelection->blockSignals(true);
0565     m_toggleDisplaySelection->setChecked(m_selectionDecoration->visible());
0566     m_toggleDisplaySelection->blockSignals(false);
0567 
0568     emit displaySelectionChanged();
0569 }
0570 
0571 bool KisSelectionManager::displaySelection()
0572 {
0573     return m_toggleDisplaySelection->isChecked();
0574 }
0575 
0576 void KisSelectionManager::shapeSelectionChanged()
0577 {
0578     KoShapeManager* shapeManager = m_view->canvasBase()->globalShapeManager();
0579 
0580     KoSelection * selection = shapeManager->selection();
0581     QList<KoShape*> selectedShapes = selection->selectedShapes();
0582 
0583     KoShapeStrokeSP border(new KoShapeStroke(0, Qt::lightGray));
0584     Q_FOREACH (KoShape* shape, shapeManager->shapes()) {
0585         if (dynamic_cast<KisShapeSelection*>(shape->parent())) {
0586             if (selectedShapes.contains(shape))
0587                 shape->setStroke(border);
0588             else
0589                 shape->setStroke(KoShapeStrokeSP());
0590         }
0591     }
0592     m_view->updateGUI();
0593 }
0594 
0595 void KisSelectionManager::imageResizeToSelection()
0596 {
0597     KisImageResizeToSelectionActionFactory factory;
0598     factory.run(m_view);
0599 }
0600 
0601 void KisSelectionManager::paintSelectedShapes()
0602 {
0603     KisImageWSP image = m_view->image();
0604     if (!image) return;
0605 
0606     KisLayerSP layer = m_view->activeLayer();
0607     if (!layer) return;
0608 
0609     QList<KoShape*> shapes = m_view->canvasBase()->shapeManager()->selection()->selectedShapes();
0610 
0611     KisPaintLayerSP paintLayer = new KisPaintLayer(image, i18n("Stroked Shapes"), OPACITY_OPAQUE_U8);
0612 
0613     KUndo2MagicString actionName = kundo2_i18n("Stroke Shapes");
0614 
0615     m_adapter->beginMacro(actionName);
0616     m_adapter->addNode(paintLayer.data(), layer->parent().data(), layer.data());
0617 
0618     KisFigurePaintingToolHelper helper(actionName,
0619                                        image,
0620                                        paintLayer.data(),
0621                                        m_view->canvasResourceProvider()->resourceManager(),
0622                                        KisToolShapeUtils::StrokeStyleForeground,
0623                                        KisToolShapeUtils::FillStyleNone);
0624 
0625     Q_FOREACH (KoShape* shape, shapes) {
0626         QTransform matrix = shape->absoluteTransformation() * QTransform::fromScale(image->xRes(), image->yRes());
0627         QPainterPath mappedOutline = matrix.map(shape->outline());
0628         helper.paintPainterPath(mappedOutline);
0629     }
0630     m_adapter->endMacro();
0631 }
0632 
0633 void KisSelectionManager::slotToggleSelectionDecoration()
0634 {
0635     KIS_ASSERT_RECOVER_RETURN(m_selectionDecoration);
0636 
0637     KisSelectionDecoration::Mode mode =
0638         m_selectionDecoration->mode() ?
0639         KisSelectionDecoration::Ants : KisSelectionDecoration::Mask;
0640 
0641     m_selectionDecoration->setMode(mode);
0642     emit displaySelectionChanged();
0643 }
0644 
0645 bool KisSelectionManager::showSelectionAsMask() const
0646 {
0647     if (m_selectionDecoration) {
0648         return m_selectionDecoration->mode() == KisSelectionDecoration::Mask;
0649     }
0650     return false;
0651 }
0652 void KisSelectionManager::slotStrokeSelection()
0653 {
0654     KisImageWSP image = m_view->image();
0655 
0656     if (!image ) {
0657         return;
0658     }
0659 
0660     KisNodeSP currentNode = m_view->canvasResourceProvider()->resourceManager()->resource(KoCanvasResource::CurrentKritaNode).value<KisNodeWSP>();
0661     bool isVectorLayer = false;
0662     if (currentNode->inherits("KisShapeLayer")) {
0663         isVectorLayer = true;
0664     }
0665 
0666     QPointer<KisDlgStrokeSelection> dlg = new KisDlgStrokeSelection(image, m_view, isVectorLayer);
0667 
0668     if (dlg->exec() == QDialog::Accepted) {
0669         StrokeSelectionOptions params = dlg->getParams();
0670         if (params.brushSelected){
0671             KisStrokeBrushSelectionActionFactory factory;
0672             factory.run(m_view, params);
0673         }
0674         else {
0675             KisStrokeSelectionActionFactory factory;
0676             factory.run(m_view, params);
0677         }
0678     }
0679     delete dlg;
0680 
0681 
0682 }
0683 
0684 #include "KisImageBarrierLock.h"
0685 #include "kis_selection_tool_helper.h"
0686 
0687 void KisSelectionManager::selectOpaqueOnNode(KisNodeSP node, SelectionAction action)
0688 {
0689     KisImageSP image = m_view->image();
0690 
0691     if (!m_view->blockUntilOperationsFinished(image)) {
0692         return;
0693     }
0694 
0695     KUndo2MagicString actionName;
0696     KisPixelSelectionSP tmpSel = KisPixelSelectionSP(new KisPixelSelection());
0697     KisCanvas2 *canvas = m_view->canvasBase();
0698 
0699 
0700     {
0701         KisImageBarrierLock lock(image);
0702 
0703         KisPaintDeviceSP device = node->projection();
0704         if (!device) device = node->paintDevice();
0705         if (!device) device = node->original();
0706 
0707         if (!device) return;
0708 
0709         QRect rc = device->exactBounds();
0710         if (rc.isEmpty()) {
0711 
0712             if (action == SELECTION_REPLACE || action == SELECTION_INTERSECT) {
0713                 KUndo2Command *deselectCommand = new KisDeselectActiveSelectionCommand(m_view->selection(), m_view->image());
0714                 KisProcessingApplicator::runSingleCommandStroke(m_view->image(), deselectCommand);
0715             }
0716 
0717             return;
0718         }
0719 
0720         KIS_ASSERT_RECOVER_RETURN(canvas);
0721 
0722         /**
0723          * If there is nothing selected, just create a new selection
0724          */
0725         if (!canvas->imageView()->selection()) {
0726             action = SELECTION_REPLACE;
0727         }
0728 
0729         switch (action) {
0730         case SELECTION_ADD:
0731             actionName = kundo2_i18n("Select Opaque (Add)");
0732             break;
0733         case SELECTION_SUBTRACT:
0734             actionName = kundo2_i18n("Select Opaque (Subtract)");
0735             break;
0736         case SELECTION_INTERSECT:
0737             actionName = kundo2_i18n("Select Opaque (Intersect)");
0738             break;
0739         case SELECTION_SYMMETRICDIFFERENCE:
0740             actionName = kundo2_i18n("Select Opaque (Symmetric Difference)");
0741             break;
0742         default:
0743             actionName = kundo2_i18n("Select Opaque");
0744             break;
0745         }
0746 
0747         qint32 x, y, w, h;
0748         rc.getRect(&x, &y, &w, &h);
0749 
0750         const KoColorSpace * cs = device->colorSpace();
0751 
0752         KisHLineConstIteratorSP deviter = device->createHLineConstIteratorNG(x, y, w);
0753         KisHLineIteratorSP selIter = tmpSel ->createHLineIteratorNG(x, y, w);
0754 
0755         for (int row = y; row < h + y; ++row) {
0756             do {
0757                 *selIter->rawData() = cs->opacityU8(deviter->oldRawData());
0758             } while (deviter->nextPixel() && selIter->nextPixel());
0759             deviter->nextRow();
0760             selIter->nextRow();
0761         }
0762     }
0763 
0764     KisSelectionToolHelper helper(canvas, actionName);
0765     tmpSel->invalidateOutlineCache();
0766     helper.selectPixelSelection(tmpSel, action);
0767 }