[krita] /: Implement Ctrl+click shortcuts for selecting opaque pixels on a layer

Dmitry Kazakov null at kde.org
Wed Aug 22 12:19:32 BST 2018


Git commit 09ce1d040f3ad9f3dc1a2d7185639b06d4c50fb3 by Dmitry Kazakov.
Committed on 22/08/2018 at 11:19.
Pushed by dkazakov into branch 'master'.

Implement Ctrl+click shortcuts for selecting opaque pixels on a layer

Now one can click on a layer's thumbnail in the Layers docker to
have all the opaque pixels selected.

* ctrl+click --- replace selection
* ctrl+shift+click --- add selection
* ctrl+alt+click --- subtract selection
* ctrl+shift+alt+click --- intersect selection

CC:kimageshop at kde.org
CCBUG:346892

A  +18   -0    libs/image/KisSelectionTags.h     [License: UNKNOWN]  *
M  +1    -12   libs/image/kis_selection.h
M  +12   -2    libs/libqml/plugins/kritasketchplugin/models/LayerModel.cpp
M  +1    -0    libs/ui/CMakeLists.txt
M  +40   -2    libs/ui/KisNodeDelegate.cpp
M  +1    -1    libs/ui/KisNodeDelegate.h
A  +15   -0    libs/ui/KisSelectionActionsAdapter.cpp     [License: UNKNOWN]  *
A  +21   -0    libs/ui/KisSelectionActionsAdapter.h     [License: UNKNOWN]  *
M  +1    -1    libs/ui/kis_node_filter_proxy_model.cpp
M  +18   -2    libs/ui/kis_node_model.cpp
M  +15   -3    libs/ui/kis_node_model.h
M  +71   -0    libs/ui/kis_selection_manager.cc
M  +3    -0    libs/ui/kis_selection_manager.h
M  +2    -2    libs/ui/tests/kis_model_index_converter_test.cpp
M  +5    -5    libs/ui/tests/kis_node_model_test.cpp
M  +1    -1    libs/ui/tests/kis_node_view_test.cpp
M  +12   -2    plugins/dockers/defaultdockers/kis_layer_box.cpp
M  +2    -0    plugins/dockers/defaultdockers/kis_layer_box.h
M  +4    -58   plugins/extensions/colorrange/colorrange.cc
M  +0    -6    plugins/extensions/colorrange/colorrange.h

The files marked with a * at the end have a non valid license. Please read: https://community.kde.org/Policies/Licensing_Policy and use the headers which are listed at that page.


https://commits.kde.org/krita/09ce1d040f3ad9f3dc1a2d7185639b06d4c50fb3

diff --git a/libs/image/KisSelectionTags.h b/libs/image/KisSelectionTags.h
new file mode 100644
index 00000000000..8558af5f00f
--- /dev/null
+++ b/libs/image/KisSelectionTags.h
@@ -0,0 +1,18 @@
+#ifndef KISSELECTIONTAGS_H
+#define KISSELECTIONTAGS_H
+
+
+enum SelectionMode {
+    PIXEL_SELECTION,
+    SHAPE_PROTECTION
+};
+
+enum SelectionAction {
+    SELECTION_REPLACE,
+    SELECTION_ADD,
+    SELECTION_SUBTRACT,
+    SELECTION_INTERSECT,
+    SELECTION_DEFAULT
+};
+
+#endif // KISSELECTIONTAGS_H
diff --git a/libs/image/kis_selection.h b/libs/image/kis_selection.h
index e72a7f028a1..48930d815e3 100644
--- a/libs/image/kis_selection.h
+++ b/libs/image/kis_selection.h
@@ -25,18 +25,7 @@
 #include "kis_default_bounds.h"
 #include "kis_image.h"
 
-enum SelectionMode {
-    PIXEL_SELECTION,
-    SHAPE_PROTECTION
-};
-
-enum SelectionAction {
-    SELECTION_REPLACE,
-    SELECTION_ADD,
-    SELECTION_SUBTRACT,
-    SELECTION_INTERSECT,
-    SELECTION_DEFAULT
-};
+#include "KisSelectionTags.h"
 
 #include "kis_pixel_selection.h"
 
diff --git a/libs/libqml/plugins/kritasketchplugin/models/LayerModel.cpp b/libs/libqml/plugins/kritasketchplugin/models/LayerModel.cpp
index 2c13f720b19..6ce5a76e8bf 100644
--- a/libs/libqml/plugins/kritasketchplugin/models/LayerModel.cpp
+++ b/libs/libqml/plugins/kritasketchplugin/models/LayerModel.cpp
@@ -42,6 +42,7 @@
 #include <KoProperties.h>
 #include <QQmlEngine>
 #include <kis_base_node.h>
+#include "KisSelectionActionsAdapter.h"
 
 struct LayerModelMetaInfo {
     LayerModelMetaInfo()
@@ -94,6 +95,7 @@ public:
     bool aboutToRemoveRoots;
     KisViewManager* view;
     KisCanvas2* canvas;
+    QScopedPointer<KisSelectionActionsAdapter> selectionActionsAdapter;
     QPointer<KisNodeManager> nodeManager;
     KisImageWSP image;
     KisNodeSP activeNode;
@@ -266,7 +268,8 @@ void LayerModel::setView(QObject *newView)
         d->layers.clear();
         d->activeNode.clear();
         d->canvas = 0;
-        d->nodeModel->setDummiesFacade(0, 0, 0, 0, 0);
+        d->nodeModel->setDummiesFacade(0, 0, 0, 0, 0, 0);
+        d->selectionActionsAdapter.reset();
 
     }
 
@@ -288,7 +291,14 @@ void LayerModel::setView(QObject *newView)
 
         KisDummiesFacadeBase *kritaDummiesFacade = dynamic_cast<KisDummiesFacadeBase*>(d->canvas->imageView()->document()->shapeController());
         KisShapeController *shapeController = dynamic_cast<KisShapeController*>(d->canvas->imageView()->document()->shapeController());
-        d->nodeModel->setDummiesFacade(kritaDummiesFacade, d->image, shapeController, d->nodeManager->nodeSelectionAdapter(), d->nodeManager->nodeInsertionAdapter());
+
+        d->selectionActionsAdapter.reset(new KisSelectionActionsAdapter(d->canvas->viewManager()->selectionManager()));
+        d->nodeModel->setDummiesFacade(kritaDummiesFacade,
+                                       d->image,
+                                       shapeController,
+                                       d->nodeManager->nodeSelectionAdapter(),
+                                       d->nodeManager->nodeInsertionAdapter(),
+                                       d->selectionActionsAdapter.data());
 
         connect(d->image, SIGNAL(sigAboutToBeDeleted()), SLOT(notifyImageDeleted()));
         connect(d->image, SIGNAL(sigNodeChanged(KisNodeSP)), SLOT(nodeChanged(KisNodeSP)));
diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt
index e09778b4073..d829b68381c 100644
--- a/libs/ui/CMakeLists.txt
+++ b/libs/ui/CMakeLists.txt
@@ -140,6 +140,7 @@ set(kritaui_LIB_SRCS
     KisSelectedShapesProxy.cpp
     kis_selection_decoration.cc
     kis_selection_manager.cc
+    KisSelectionActionsAdapter.cpp
     kis_statusbar.cc
     kis_zoom_manager.cc
     kis_favorite_resource_manager.cpp
diff --git a/libs/ui/KisNodeDelegate.cpp b/libs/ui/KisNodeDelegate.cpp
index 328e38abc49..0e73f9ba793 100644
--- a/libs/ui/KisNodeDelegate.cpp
+++ b/libs/ui/KisNodeDelegate.cpp
@@ -264,11 +264,24 @@ void KisNodeDelegate::drawFrame(QPainter *p, const QStyleOptionViewItem &option,
     p->setPen(oldPen);
 }
 
-void KisNodeDelegate::drawThumbnail(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
+QRect KisNodeDelegate::thumbnailClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const
 {
-    KisNodeViewColorScheme scm;
+    Q_UNUSED(index);
 
+    const int steps = 0;
 
+    KisNodeViewColorScheme scm;
+    return QRect(scm.border() +
+                 2 * scm.visibilityMargin() + scm.visibilitySize() +
+                 scm.border() + steps * scm.indentation(),
+                 scm.border() + option.rect.top(),
+                 2 * scm.thumbnailMargin() + scm.thumbnailSize(),
+                 scm.rowHeight() - scm.border());
+}
+
+void KisNodeDelegate::drawThumbnail(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+    KisNodeViewColorScheme scm;
 
     const int thumbSize = scm.thumbnailSize();
     const qreal oldOpacity = p->opacity(); // remember previous opacity
@@ -686,6 +699,9 @@ bool KisNodeDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, cons
 
         const bool leftButton = mouseEvent->buttons() & Qt::LeftButton;
 
+        const QRect thumbnailRect = thumbnailClickRect(option, index);
+        const bool thumbnailClicked = thumbnailRect.contains(mouseEvent->pos());
+
         if (leftButton && iconsClicked) {
             KisBaseNode::PropertyList props = index.data(KisNodeModel::PropertiesRole).value<KisBaseNode::PropertyList>();
             QList<OptionalProperty> realProps = d->rightmostProperties(props);
@@ -717,6 +733,28 @@ bool KisNodeDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, cons
             if (isExpandable) {
                 bool isExpanded = d->view->isExpanded(index);
                 d->view->setExpanded(index, !isExpanded);
+            }
+            return true;
+        } else if (leftButton && thumbnailClicked) {
+            bool hasCorrectModifier = false;
+            SelectionAction action = SELECTION_REPLACE;
+
+            if (mouseEvent->modifiers() == Qt::ControlModifier) {
+                action = SELECTION_REPLACE;
+                hasCorrectModifier = true;
+            } else if (mouseEvent->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) {
+                action = SELECTION_ADD;
+                hasCorrectModifier = true;
+            } else if (mouseEvent->modifiers() == (Qt::ControlModifier | Qt::AltModifier)) {
+                action = SELECTION_SUBTRACT;
+                hasCorrectModifier = true;
+            } else if (mouseEvent->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier | Qt::AltModifier)) {
+                action = SELECTION_INTERSECT;
+                hasCorrectModifier = true;
+            }
+
+            if (hasCorrectModifier) {
+                model->setData(index, QVariant(int(action)), KisNodeModel::SelectOpaqueRole);
                 return true;
             }
         }
diff --git a/libs/ui/KisNodeDelegate.h b/libs/ui/KisNodeDelegate.h
index cdf6c5e73c1..ad53f443e19 100644
--- a/libs/ui/KisNodeDelegate.h
+++ b/libs/ui/KisNodeDelegate.h
@@ -54,7 +54,6 @@ public:
 protected:
     bool eventFilter(QObject *object, QEvent *event) override;
 
-
 private:
     typedef KisNodeModel Model;
     typedef KisNodeView View;
@@ -74,6 +73,7 @@ private:
     void drawIcons(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
     QRect visibilityClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const;
     QRect decorationClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const;
+    QRect thumbnailClickRect(const QStyleOptionViewItem &option, const QModelIndex &index) const;
     void drawVisibilityIconHijack(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
     void drawDecoration(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
     void drawExpandButton(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const;
diff --git a/libs/ui/KisSelectionActionsAdapter.cpp b/libs/ui/KisSelectionActionsAdapter.cpp
new file mode 100644
index 00000000000..63834378969
--- /dev/null
+++ b/libs/ui/KisSelectionActionsAdapter.cpp
@@ -0,0 +1,15 @@
+#include "KisSelectionActionsAdapter.h"
+
+#include "kis_selection_manager.h"
+
+
+KisSelectionActionsAdapter::KisSelectionActionsAdapter(KisSelectionManager *selectionManager)
+    : m_selectionManager(selectionManager)
+{
+}
+
+void KisSelectionActionsAdapter::selectOpaqueOnNode(KisNodeSP node, SelectionAction action)
+{
+    KIS_SAFE_ASSERT_RECOVER_RETURN(m_selectionManager);
+    m_selectionManager->selectOpaqueOnNode(node, action);
+}
diff --git a/libs/ui/KisSelectionActionsAdapter.h b/libs/ui/KisSelectionActionsAdapter.h
new file mode 100644
index 00000000000..ae70736d392
--- /dev/null
+++ b/libs/ui/KisSelectionActionsAdapter.h
@@ -0,0 +1,21 @@
+#ifndef KISSELECTIONACTIONSADAPTER_H
+#define KISSELECTIONACTIONSADAPTER_H
+
+#include "kritaui_export.h"
+#include "kis_types.h"
+#include "KisSelectionTags.h"
+
+class KisSelectionManager;
+
+
+class KRITAUI_EXPORT KisSelectionActionsAdapter
+{
+public:
+    KisSelectionActionsAdapter(KisSelectionManager *selectionManager);
+    void selectOpaqueOnNode(KisNodeSP node, SelectionAction action);
+
+private:
+    KisSelectionManager *m_selectionManager;
+};
+
+#endif // KISSELECTIONACTIONSADAPTER_H
diff --git a/libs/ui/kis_node_filter_proxy_model.cpp b/libs/ui/kis_node_filter_proxy_model.cpp
index 083741e1af1..8686863b7a8 100644
--- a/libs/ui/kis_node_filter_proxy_model.cpp
+++ b/libs/ui/kis_node_filter_proxy_model.cpp
@@ -163,7 +163,7 @@ void KisNodeFilterProxyModel::slotUpdateCurrentNodeFilter()
 
 void KisNodeFilterProxyModel::unsetDummiesFacade()
 {
-    m_d->nodeModel->setDummiesFacade(0, 0, 0, 0, 0);
+    m_d->nodeModel->setDummiesFacade(0, 0, 0, 0, 0, 0);
     m_d->pendingActiveNode = 0;
     m_d->activeNode = 0;
 }
diff --git a/libs/ui/kis_node_model.cpp b/libs/ui/kis_node_model.cpp
index 916d3f9ed30..4938070cdb0 100644
--- a/libs/ui/kis_node_model.cpp
+++ b/libs/ui/kis_node_model.cpp
@@ -48,6 +48,7 @@
 #include "kis_model_index_converter_show_all.h"
 #include "kis_node_selection_adapter.h"
 #include "kis_node_insertion_adapter.h"
+#include <KisSelectionActionsAdapter.h>
 
 #include "kis_config.h"
 #include "kis_config_notifier.h"
@@ -60,6 +61,7 @@ struct KisNodeModel::Private
     KisShapeController *shapeController = 0;
     KisNodeSelectionAdapter *nodeSelectionAdapter = 0;
     KisNodeInsertionAdapter *nodeInsertionAdapter = 0;
+    KisSelectionActionsAdapter *selectionActionsAdapter = 0;
     QList<KisNodeDummy*> updateQueue;
     QTimer updateTimer;
 
@@ -252,7 +254,12 @@ void KisNodeModel::connectDummies(KisNodeDummy *dummy, bool needConnect)
     }
 }
 
-void KisNodeModel::setDummiesFacade(KisDummiesFacadeBase *dummiesFacade, KisImageWSP image, KisShapeController *shapeController, KisNodeSelectionAdapter *nodeSelectionAdapter, KisNodeInsertionAdapter *nodeInsertionAdapter)
+void KisNodeModel::setDummiesFacade(KisDummiesFacadeBase *dummiesFacade,
+                                    KisImageWSP image,
+                                    KisShapeController *shapeController,
+                                    KisNodeSelectionAdapter *nodeSelectionAdapter,
+                                    KisNodeInsertionAdapter *nodeInsertionAdapter,
+                                    KisSelectionActionsAdapter *selectionActionsAdapter)
 {
     QPointer<KisDummiesFacadeBase> oldDummiesFacade(m_d->dummiesFacade);
     KisShapeController  *oldShapeController = m_d->shapeController;
@@ -260,6 +267,7 @@ void KisNodeModel::setDummiesFacade(KisDummiesFacadeBase *dummiesFacade, KisImag
     m_d->shapeController = shapeController;
     m_d->nodeSelectionAdapter = nodeSelectionAdapter;
     m_d->nodeInsertionAdapter = nodeInsertionAdapter;
+    m_d->selectionActionsAdapter = selectionActionsAdapter;
 
     if (oldDummiesFacade && m_d->image) {
         m_d->image->disconnect(this);
@@ -558,6 +566,7 @@ bool KisNodeModel::setData(const QModelIndex &index, const QVariant &value, int
     if(!m_d->dummiesFacade || !index.isValid()) return false;
 
     bool result = true;
+    bool shouldUpdate = true;
     bool shouldUpdateRecursively = false;
     KisNodeSP node = nodeFromIndex(index);
 
@@ -575,11 +584,18 @@ bool KisNodeModel::setData(const QModelIndex &index, const QVariant &value, int
 
             break;
         }
+    case KisNodeModel::SelectOpaqueRole:
+        if (node && m_d->selectionActionsAdapter) {
+            SelectionAction action = SelectionAction(value.toInt());
+            m_d->selectionActionsAdapter->selectOpaqueOnNode(node, action);
+        }
+        shouldUpdate = false;
+        break;
     default:
         result = false;
     }
 
-    if(result) {
+    if (result && shouldUpdate) {
         if (shouldUpdateRecursively) {
             QSet<QModelIndex> indexes;
             addChangedIndex(index, &indexes);
diff --git a/libs/ui/kis_node_model.h b/libs/ui/kis_node_model.h
index 7d737af260f..52e4e3146cb 100644
--- a/libs/ui/kis_node_model.h
+++ b/libs/ui/kis_node_model.h
@@ -26,12 +26,15 @@
 #include <QString>
 #include <QVariant>
 
+#include <KisSelectionTags.h>
+
 class KisDummiesFacadeBase;
 class KisNodeDummy;
 class KisShapeController;
 class KisModelIndexConverterBase;
 class KisNodeSelectionAdapter;
 class KisNodeInsertionAdapter;
+class KisSelectionActionsAdapter;
 
 /**
  * KisNodeModel offers a Qt model-view compatible view of the node
@@ -84,8 +87,13 @@ public:
         // reflect if the item allows an "onto" drop of the given QMimeData*.
         DropEnabled,
 
+        // Instructs the model to activate "select opaque" action,
+        // the selection action (of type SelectionAction) value
+        // is passed via QVariant as integer
+        SelectOpaqueRole,
+
         /// This is to ensure that we can extend the data role in the future, since it's not possible to add a role after BeginThumbnailRole (due to "Hack")
-        ReservedRole = 99,
+        ReservedRole = Qt::UserRole + 99,
 
         /**
          * For values of BeginThumbnailRole or higher, a thumbnail of the layer of which neither dimension
@@ -101,12 +109,16 @@ public: // from QAbstractItemModel
     KisNodeModel(QObject * parent);
     ~KisNodeModel() override;
 
-    void setDummiesFacade(KisDummiesFacadeBase *dummiesFacade, KisImageWSP image, KisShapeController *shapeController, KisNodeSelectionAdapter *nodeSelectionAdapter, KisNodeInsertionAdapter *nodeInsertionAdapter);
+    void setDummiesFacade(KisDummiesFacadeBase *dummiesFacade,
+                          KisImageWSP image,
+                          KisShapeController *shapeController,
+                          KisNodeSelectionAdapter *nodeSelectionAdapter,
+                          KisNodeInsertionAdapter *nodeInsertionAdapter,
+                          KisSelectionActionsAdapter *selectionActionsAdapter);
     KisNodeSP nodeFromIndex(const QModelIndex &index) const;
     QModelIndex indexFromNode(KisNodeSP node) const;
 
     bool showGlobalSelection() const;
-    
 
 public Q_SLOTS:
     void setShowGlobalSelection(bool value);
diff --git a/libs/ui/kis_selection_manager.cc b/libs/ui/kis_selection_manager.cc
index ebdb5628923..b7ff5766631 100644
--- a/libs/ui/kis_selection_manager.cc
+++ b/libs/ui/kis_selection_manager.cc
@@ -605,3 +605,74 @@ void KisSelectionManager::slotStrokeSelection()
 
 
 }
+
+#include "kis_image_barrier_locker.h"
+#include "kis_selection_tool_helper.h"
+
+void KisSelectionManager::selectOpaqueOnNode(KisNodeSP node, SelectionAction action)
+{
+    KisImageSP image = m_view->image();
+
+    if (!m_view->blockUntilOperationsFinished(image)) {
+        return;
+    }
+
+    KUndo2MagicString actionName;
+    KisPixelSelectionSP tmpSel = KisPixelSelectionSP(new KisPixelSelection());
+    KisCanvas2 *canvas = m_view->canvasBase();
+
+
+    {
+        KisImageBarrierLocker locker(image);
+
+        KisPaintDeviceSP device = node->projection();
+        if (!device) device = node->paintDevice();
+        if (!device) device = node->original();
+        KIS_ASSERT_RECOVER_RETURN(canvas && device);
+
+        QRect rc = device->exactBounds();
+        if (rc.isEmpty()) return;
+
+        /**
+         * If there is nothing selected, just create a new selection
+         */
+        if (!canvas->imageView()->selection()) {
+            action = SELECTION_REPLACE;
+        }
+
+        switch (action) {
+        case SELECTION_ADD:
+            actionName = kundo2_i18n("Select Opaque (Add)");
+            break;
+        case SELECTION_SUBTRACT:
+            actionName = kundo2_i18n("Select Opaque (Subtract)");
+            break;
+        case SELECTION_INTERSECT:
+            actionName = kundo2_i18n("Select Opaque (Intersect)");
+            break;
+        default:
+            actionName = kundo2_i18n("Select Opaque");
+            break;
+        }
+
+        qint32 x, y, w, h;
+        rc.getRect(&x, &y, &w, &h);
+
+        const KoColorSpace * cs = device->colorSpace();
+
+        KisHLineConstIteratorSP deviter = device->createHLineConstIteratorNG(x, y, w);
+        KisHLineIteratorSP selIter = tmpSel ->createHLineIteratorNG(x, y, w);
+
+        for (int row = y; row < h + y; ++row) {
+            do {
+                *selIter->rawData() = cs->opacityU8(deviter->oldRawData());
+            } while (deviter->nextPixel() && selIter->nextPixel());
+            deviter->nextRow();
+            selIter->nextRow();
+        }
+    }
+
+    KisSelectionToolHelper helper(canvas, actionName);
+    tmpSel->invalidateOutlineCache();
+    helper.selectPixelSelection(tmpSel, action);
+}
diff --git a/libs/ui/kis_selection_manager.h b/libs/ui/kis_selection_manager.h
index 5b8046030ed..bd165eb9522 100644
--- a/libs/ui/kis_selection_manager.h
+++ b/libs/ui/kis_selection_manager.h
@@ -24,6 +24,7 @@
 
 #include <kis_image.h>
 #include "KisView.h"
+#include <KisSelectionTags.h>
 
 #include <kritaui_export.h>
 
@@ -111,6 +112,8 @@ public Q_SLOTS:
 
     void slotStrokeSelection();
 
+    void selectOpaqueOnNode(KisNodeSP node, SelectionAction action);
+
 Q_SIGNALS:
     void currentSelectionChanged();
     void signalUpdateGUI();
diff --git a/libs/ui/tests/kis_model_index_converter_test.cpp b/libs/ui/tests/kis_model_index_converter_test.cpp
index 795217d45d4..e2cd6e2660a 100644
--- a/libs/ui/tests/kis_model_index_converter_test.cpp
+++ b/libs/ui/tests/kis_model_index_converter_test.cpp
@@ -36,12 +36,12 @@ void KisModelIndexConverterTest::init()
     addSelectionMasks();
 
     m_dummiesFacade->setImage(m_image);
-    m_nodeModel->setDummiesFacade(m_dummiesFacade, m_image, 0, 0, 0);
+    m_nodeModel->setDummiesFacade(m_dummiesFacade, m_image, 0, 0, 0, 0);
 }
 
 void KisModelIndexConverterTest::cleanup()
 {
-    m_nodeModel->setDummiesFacade(0, 0, 0, 0, 0);
+    m_nodeModel->setDummiesFacade(0, 0, 0, 0, 0, 0);
     m_dummiesFacade->setImage(0);
 
     cleanupBase();
diff --git a/libs/ui/tests/kis_node_model_test.cpp b/libs/ui/tests/kis_node_model_test.cpp
index 2e6e55cd5b8..db97778d7c4 100644
--- a/libs/ui/tests/kis_node_model_test.cpp
+++ b/libs/ui/tests/kis_node_model_test.cpp
@@ -57,14 +57,14 @@ void KisNodeModelTest::testSetImage()
 {
     constructImage();
     m_shapeController->setImage(m_image);
-    m_nodeModel->setDummiesFacade(m_shapeController, m_image, 0, 0, 0);
+    m_nodeModel->setDummiesFacade(m_shapeController, m_image, 0, 0, 0, 0);
     new ModelTest(m_nodeModel, this);
 }
 
 void KisNodeModelTest::testAddNode()
 {
     m_shapeController->setImage(m_image);
-    m_nodeModel->setDummiesFacade(m_shapeController, m_image, 0, 0, 0);
+    m_nodeModel->setDummiesFacade(m_shapeController, m_image, 0, 0, 0, 0);
     new ModelTest(m_nodeModel, this);
 
     constructImage();
@@ -75,7 +75,7 @@ void KisNodeModelTest::testRemoveAllNodes()
 {
     constructImage();
     m_shapeController->setImage(m_image);
-    m_nodeModel->setDummiesFacade(m_shapeController, m_image, 0, 0, 0);
+    m_nodeModel->setDummiesFacade(m_shapeController, m_image, 0, 0, 0, 0);
     new ModelTest(m_nodeModel, this);
 
     m_image->removeNode(m_layer4);
@@ -88,7 +88,7 @@ void KisNodeModelTest::testRemoveIncludingRoot()
 {
     constructImage();
     m_shapeController->setImage(m_image);
-    m_nodeModel->setDummiesFacade(m_shapeController, m_image, 0, 0, 0);
+    m_nodeModel->setDummiesFacade(m_shapeController, m_image, 0, 0, 0, 0);
     new ModelTest(m_nodeModel, this);
 
     m_image->removeNode(m_layer4);
@@ -104,7 +104,7 @@ void KisNodeModelTest::testSubstituteRootNode()
 {
     constructImage();
     m_shapeController->setImage(m_image);
-    m_nodeModel->setDummiesFacade(m_shapeController, m_image, 0, 0, 0);
+    m_nodeModel->setDummiesFacade(m_shapeController, m_image, 0, 0, 0, 0);
     new ModelTest(m_nodeModel, this);
 
     m_image->flatten();
diff --git a/libs/ui/tests/kis_node_view_test.cpp b/libs/ui/tests/kis_node_view_test.cpp
index bb40cd6e626..923a6013033 100644
--- a/libs/ui/tests/kis_node_view_test.cpp
+++ b/libs/ui/tests/kis_node_view_test.cpp
@@ -80,7 +80,7 @@ void KisNodeViewTest::testLayers()
     addSelectionMasks();
     m_shapeController->setImage(m_image);
 
-    model->setDummiesFacade(m_shapeController, m_image, m_shapeController, 0, 0);
+    model->setDummiesFacade(m_shapeController, m_image, m_shapeController, 0, 0, 0);
 
     QVBoxLayout *layout = new QVBoxLayout(&dlg);
     KisColorFilterCombo *cb = new KisColorFilterCombo(&dlg);
diff --git a/plugins/dockers/defaultdockers/kis_layer_box.cpp b/plugins/dockers/defaultdockers/kis_layer_box.cpp
index 5c7f23c00c9..006cccba708 100644
--- a/plugins/dockers/defaultdockers/kis_layer_box.cpp
+++ b/plugins/dockers/defaultdockers/kis_layer_box.cpp
@@ -90,6 +90,7 @@
 #include "kis_selection.h"
 #include "kis_processing_applicator.h"
 #include "commands/kis_set_global_selection_command.h"
+#include "KisSelectionActionsAdapter.h"
 
 #include "kis_layer_utils.h"
 
@@ -379,7 +380,8 @@ void KisLayerBox::setCanvas(KoCanvasBase *canvas)
 
     if (m_canvas) {
         m_canvas->disconnectCanvasObserver(this);
-        m_nodeModel->setDummiesFacade(0, 0, 0, 0, 0);
+        m_nodeModel->setDummiesFacade(0, 0, 0, 0, 0, 0);
+        m_selectionActionsAdapter.reset();
 
         if (m_image) {
             KisImageAnimationInterface *animation = m_image->animationInterface();
@@ -403,7 +405,15 @@ void KisLayerBox::setCanvas(KoCanvasBase *canvas)
                 dynamic_cast<KisShapeController*>(doc->shapeController());
         KisDummiesFacadeBase *kritaDummiesFacade =
                 static_cast<KisDummiesFacadeBase*>(kritaShapeController);
-        m_nodeModel->setDummiesFacade(kritaDummiesFacade, m_image, kritaShapeController, m_nodeManager->nodeSelectionAdapter(), m_nodeManager->nodeInsertionAdapter());
+
+
+        m_selectionActionsAdapter.reset(new KisSelectionActionsAdapter(m_canvas->viewManager()->selectionManager()));
+        m_nodeModel->setDummiesFacade(kritaDummiesFacade,
+                                      m_image,
+                                      kritaShapeController,
+                                      m_nodeManager->nodeSelectionAdapter(),
+                                      m_nodeManager->nodeInsertionAdapter(),
+                                      m_selectionActionsAdapter.data());
 
         connect(m_image, SIGNAL(sigAboutToBeDeleted()), SLOT(notifyImageDeleted()));
         connect(m_image, SIGNAL(sigNodeCollapsedChanged()), SLOT(slotNodeCollapsedChanged()));
diff --git a/plugins/dockers/defaultdockers/kis_layer_box.h b/plugins/dockers/defaultdockers/kis_layer_box.h
index 9cd1e51048d..e392cf09337 100644
--- a/plugins/dockers/defaultdockers/kis_layer_box.h
+++ b/plugins/dockers/defaultdockers/kis_layer_box.h
@@ -57,6 +57,7 @@ class KisNodeJugglerCompressed;
 class KisColorLabelSelectorWidget;
 class QWidgetAction;
 class KisKeyframeChannel;
+class KisSelectionActionsAdapter;
 
 /**
  * A widget that shows a visualization of the layer structure.
@@ -146,6 +147,7 @@ private:
 private:
 
     QPointer<KisCanvas2> m_canvas;
+    QScopedPointer<KisSelectionActionsAdapter> m_selectionActionsAdapter;
     QMenu *m_newLayerMenu;
     KisImageWSP m_image;
     QPointer<KisNodeModel> m_nodeModel;
diff --git a/plugins/extensions/colorrange/colorrange.cc b/plugins/extensions/colorrange/colorrange.cc
index cbec33f7259..72161a6bf0c 100644
--- a/plugins/extensions/colorrange/colorrange.cc
+++ b/plugins/extensions/colorrange/colorrange.cc
@@ -85,65 +85,11 @@ void ColorRange::slotActivated()
 
 void ColorRange::selectOpaque(int id)
 {
-    selectOpaqueImpl(SelectionAction(id));
-}
+    KisNodeSP node = viewManager()->activeNode();
+    if (!node) return;
 
-void ColorRange::selectOpaqueImpl(SelectionAction action)
-{
-    KisCanvas2 *canvas = viewManager()->canvasBase();
-    KisPaintDeviceSP device = viewManager()->activeNode()->projection();
-    if (!device) device = viewManager()->activeNode()->paintDevice();
-    if (!device) device = viewManager()->activeNode()->original();
-    KIS_ASSERT_RECOVER_RETURN(canvas && device);
-
-    QRect rc = device->exactBounds();
-    if (rc.isEmpty()) return;
-
-    /**
-     * If there is nothing selected, just create a new selection
-     */
-    if (!canvas->imageView()->selection()) {
-        action = SELECTION_REPLACE;
-    }
-
-    KUndo2MagicString actionName;
-
-    switch (action) {
-    case SELECTION_ADD:
-        actionName = kundo2_i18n("Select Opaque (Add)");
-        break;
-    case SELECTION_SUBTRACT:
-        actionName = kundo2_i18n("Select Opaque (Subtract)");
-        break;
-    case SELECTION_INTERSECT:
-        actionName = kundo2_i18n("Select Opaque (Intersect)");
-        break;
-    default:
-        actionName = kundo2_i18n("Select Opaque");
-        break;
-    }
-
-    KisSelectionToolHelper helper(canvas, actionName);
-
-    qint32 x, y, w, h;
-    rc.getRect(&x, &y, &w, &h);
-
-    const KoColorSpace * cs = device->colorSpace();
-    KisPixelSelectionSP tmpSel = KisPixelSelectionSP(new KisPixelSelection());
-
-    KisHLineConstIteratorSP deviter = device->createHLineConstIteratorNG(x, y, w);
-    KisHLineIteratorSP selIter = tmpSel ->createHLineIteratorNG(x, y, w);
-
-    for (int row = y; row < h + y; ++row) {
-        do {
-            *selIter->rawData() = cs->opacityU8(deviter->oldRawData());
-        } while (deviter->nextPixel() && selIter->nextPixel());
-        deviter->nextRow();
-        selIter->nextRow();
-    }
-
-    tmpSel->invalidateOutlineCache();
-    helper.selectPixelSelection(tmpSel, action);
+    viewManager()->selectionManager()->
+        selectOpaqueOnNode(node, SelectionAction(id));
 }
 
 #include "colorrange.moc"
diff --git a/plugins/extensions/colorrange/colorrange.h b/plugins/extensions/colorrange/colorrange.h
index e373ef0fa0e..ef5c197be91 100644
--- a/plugins/extensions/colorrange/colorrange.h
+++ b/plugins/extensions/colorrange/colorrange.h
@@ -25,9 +25,6 @@
 
 #include <KisActionPlugin.h>
 
-#include "kis_selection.h"
-
-
 class ColorRange : public KisActionPlugin
 {
     Q_OBJECT
@@ -38,9 +35,6 @@ public:
 private Q_SLOTS:
     void slotActivated();
     void selectOpaque(int id);
-
-private:
-    void selectOpaqueImpl(SelectionAction action);
 };
 
 #endif // COLORRANGE_H


More information about the kimageshop mailing list