Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_select_layer_action.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 * SPDX-FileCopyrightText: 2012 Arjen Hiemstra <ahiemstra@heimr.nl>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <kis_debug.h>
10#include <QMouseEvent>
11#include <QApplication>
12#include <QMenu>
13
14#include <klocalizedstring.h>
15
16#include <kis_canvas2.h>
17#include <kis_image.h>
18#include <KisViewManager.h>
19#include <kis_node_manager.h>
20#include <kis_cursor.h>
21
22#include "kis_input_manager.h"
23#include "kis_tool_utils.h"
24#include <kis_group_layer.h>
25
26#include <kis_assert.h>
27
29{
30public:
33
37
39 {
40 // Store the layer selection mode on the second byte and the selection override mode on the first one
42 }
43
45 {
46 // Get the layer selection mode from the second byte
47 return (shortcut >> 8) & 0xFF;
48 }
49
51 {
52 // Get the selection override mode from the first byte
53 return shortcut & 0xFF;
54 }
55
56 void selectNodes(const KisNodeList &nodesToSelect, int selectionOverrideMode, bool includeGroups) const
57 {
58 KisNodeManager *nodeManager = q->inputManager()->canvas()->viewManager()->nodeManager();
59 KisNodeSP activeNode = nodeManager->activeNode();
60 KisNodeList finalSelectedNodes;
61
62 // Make the final list of nodes to select, excluding the group layers,
63 // if needed
64 if (includeGroups) {
65 finalSelectedNodes = nodesToSelect;
66 } else {
67 Q_FOREACH(KisNodeSP node, nodesToSelect) {
68 if (!dynamic_cast<KisGroupLayer*>(node.data())) {
69 finalSelectedNodes.append(node);
70 }
71 }
72 }
73
74 // Expand the group layers that contain newly selected nodes
75 Q_FOREACH(KisNodeSP node, finalSelectedNodes) {
76 KisNodeSP tmpNode = node->parent();
77 while (tmpNode) {
78 if (dynamic_cast<KisGroupLayer*>(tmpNode.data())) {
79 tmpNode->setCollapsed(false);
80 }
81 tmpNode = tmpNode->parent();
82 }
83 }
84
85 // Combine the list of nodes with the current selection
87 KisNodeList currentlySelectedNodes = nodeManager->selectedNodes();
88 Q_FOREACH(KisNodeSP node, currentlySelectedNodes) {
89 if (!finalSelectedNodes.contains(node)) {
90 finalSelectedNodes.append(node);
91 }
92 }
93 }
94
95 // Try to retain the previously selected node or select the top one otherwise
96 if (!finalSelectedNodes.contains(activeNode)) {
97 activeNode = finalSelectedNodes.last();
98 }
99
100 // Select
101 nodeManager->slotImageRequestNodeReselection(activeNode, finalSelectedNodes);
102 }
103
105 {
106 KisNodeList nodesToSelect;
107 nodesToSelect.append(node);
108 selectNodes(nodesToSelect, selectionOverrideMode, true);
109 }
110};
111
113 : KisAbstractInputAction("Select Layer")
114 , d(new Private(this))
115{
116 setName(i18n("Select Layer"));
117 setDescription(i18n("Select layers under the cursor position"));
118
119 QHash<QString, int> shortcuts;
120 shortcuts.insert(i18n("Select Top Layer (Replace Selection)"),
122 shortcuts.insert(i18n("Select All Layers (Replace Selection)"),
124 shortcuts.insert(i18n("Select from Menu (Replace Selection)"),
126 shortcuts.insert(i18n("Select Top Layer (Add to Selection)"),
128 shortcuts.insert(i18n("Select All Layers (Add to Selection)"),
130 shortcuts.insert(i18n("Select from Menu (Add to Selection)"),
132 setShortcutIndexes(shortcuts);
133}
134
139
141{
142 return 5;
143}
144
146{
147 Q_UNUSED(shortcut);
148 QApplication::setOverrideCursor(KisCursor::pickLayerCursor());
149}
150
152{
153 Q_UNUSED(shortcut);
154 QApplication::restoreOverrideCursor();
155}
156
157void KisSelectLayerAction::begin(int shortcut, QEvent *event)
158{
159 KisAbstractInputAction::begin(shortcut, event);
160
161 d->shortcut = shortcut;
162 inputEvent(event);
163}
164
166{
167 // Event not recognized
168 if (!event || (event->type() != QEvent::MouseMove && event->type() != QEvent::TabletMove &&
169 event->type() != QTouchEvent::TouchUpdate && event->type() != QEvent::MouseButtonPress &&
170 event->type() != QEvent::TabletPress && event->type() != QTouchEvent::TouchBegin)) {
171 return;
172 }
173
174 const int layerSelectionMode = d->layerSelectionMode(d->shortcut);
175 const int selectionOverrideMode = d->selectionOverrideMode(d->shortcut);
176
177 // Shortcut not recognized
179 (layerSelectionMode == LayerSelectionMode_TopLayer ||
180 layerSelectionMode == LayerSelectionMode_AllLayers ||
181 layerSelectionMode == LayerSelectionMode_Ask) &&
182 (selectionOverrideMode == SelectionOverrideMode_Replace ||
183 selectionOverrideMode == SelectionOverrideMode_Add)
184 );
185
186 QPoint pos =
187 inputManager()->canvas()->
188 coordinatesConverter()->widgetToImage(eventPosF(event)).toPoint();
189
190 // First make a list with the nodes to be selected
191 KisNodeList nodesToSelect;
192
193 if (layerSelectionMode == LayerSelectionMode_TopLayer) {
194 KisNodeSP foundNode = KisToolUtils::findNode(inputManager()->canvas()->image()->root(), pos, false);
195 if (!foundNode) {
196 return;
197 }
198 nodesToSelect.append(foundNode);
199 } else {
200 // Retrieve group nodes only if the mode is LayerSelectionMode_Ask
201 const KisNodeList foundNodes = KisToolUtils::findNodes(
202 inputManager()->canvas()->image()->root()->firstChild(),
203 pos, false, layerSelectionMode == LayerSelectionMode_Ask);
204
205 if (foundNodes.isEmpty()) {
206 return;
207 }
208
209 if (layerSelectionMode == LayerSelectionMode_AllLayers) {
210 nodesToSelect = foundNodes;
211 } else { //LayerSelectionMode_Ask
212 QWidget *canvasWidget = inputManager()->canvas()->canvasWidget();
213 QMenu *menu = new QMenu(canvasWidget);
214 menu->setAttribute(Qt::WA_DeleteOnClose);
215 int numberOfLayers = 0;
216
217 // Traverse the list in reverse order so that the menu entries order
218 // resembles that of the layer stack
219 for (int i = foundNodes.size() - 1; i >= 0; --i) {
220 KisNodeSP node = foundNodes[i];
221 int indentation = -1;
222 {
223 KisNodeSP tempNode = node;
224 while (tempNode->parent()) {
225 ++indentation;
226 tempNode = tempNode->parent();
227 }
228 }
229 QAction *action = menu->addAction(QString(4 * indentation, ' ') + node->name());
230 QObject::connect(action, &QAction::triggered,
231 [this, node, selectionOverrideMode]()
232 {
233 d->selectNode(node, selectionOverrideMode);
234 }
235 );
236 if (!dynamic_cast<KisGroupLayer*>(node.data())) {
237 ++numberOfLayers;
238 }
239 }
240
241 // Add separator
242 menu->addSeparator();
243
244 // Add "select all layers" menu item
245 {
246 QAction *action = menu->addAction(i18nc("Menu entry for the select layer under cursor canvas input action",
247 "Select all layers"));
248 action->setVisible(numberOfLayers > 1);
249 QObject::connect(action, &QAction::triggered,
250 [this, foundNodes, selectionOverrideMode]()
251 {
252 d->selectNodes(foundNodes, selectionOverrideMode, false);
253 }
254 );
255 }
256
257 menu->popup(canvasWidget->mapToGlobal(eventPos(event)));
258 return;
259 }
260 }
261
262 // Now select the nodes
263 d->selectNodes(nodesToSelect, selectionOverrideMode, true);
264}
Abstract base class for input actions.
static KisInputManager * inputManager
void setShortcutIndexes(const QHash< QString, int > &indexes)
QPoint eventPos(const QEvent *event)
QPointF eventPosF(const QEvent *event)
void setName(const QString &name)
void setDescription(const QString &description)
virtual void begin(int shortcut, QEvent *event)
KisViewManager * viewManager() const
KisAbstractCanvasWidget * canvasWidget
static QCursor pickLayerCursor()
KisCanvas2 * canvas() const
KisNodeSP activeNode()
Convenience function to get the active layer or mask.
KisNodeList selectedNodes()
void slotImageRequestNodeReselection(KisNodeSP activeNode, const KisNodeList &selectedNodes)
static int selectionOverrideMode(int shortcut)
static int makeShortcut(LayerSelectionMode layerSelectionMode, SelectionOverrideMode selectionOverrideMode)
static int layerSelectionMode(int shortcut)
void selectNodes(const KisNodeList &nodesToSelect, int selectionOverrideMode, bool includeGroups) const
void selectNode(KisNodeSP node, int selectionOverrideMode) const
Select Layer implementation of KisAbstractInputAction.
void begin(int shortcut, QEvent *event) override
void activate(int shortcut) override
void deactivate(int shortcut) override
void inputEvent(QEvent *event) override
KisNodeManager * nodeManager() const
The node manager handles everything about nodes.
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
KisNodeList findNodes(KisNodeSP node, const QPoint &point, bool wholeGroup, bool includeGroups, bool editableOnly)
KisNodeSP findNode(KisNodeSP node, const QPoint &point, bool wholeGroup, bool editableOnly)
void setCollapsed(bool collapsed)
QString name() const
KisNodeWSP parent
Definition kis_node.cpp:86
KisCanvas2 * canvas