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 }