1 /*
2  *  Copyright (C) 2007 Boudewijn Rempt <boud@valdyas.org>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include "kis_node_manager.h"
20 
21 #include <QStandardPaths>
22 #include <QMessageBox>
23 #include <KisSignalMapper.h>
24 #include <QApplication>
25 
26 #include <kactioncollection.h>
27 
28 #include <QKeySequence>
29 
30 #include <kis_icon.h>
31 #include <KoSelection.h>
32 #include <KoShapeManager.h>
33 #include <KoShape.h>
34 #include <KoShapeLayer.h>
35 #include <KisImportExportManager.h>
36 #include <KoFileDialog.h>
37 #include <KoToolManager.h>
38 #include <KoProperties.h>
39 
40 #include <KoColorSpace.h>
41 #include <KoColorSpaceRegistry.h>
42 #include <KoColorModelStandardIds.h>
43 
44 #include <kis_types.h>
45 #include <kis_node.h>
46 #include <kis_selection.h>
47 #include <kis_selection_mask.h>
48 #include <kis_layer.h>
49 #include <kis_mask.h>
50 #include <kis_image.h>
51 #include <kis_painter.h>
52 #include <kis_paint_layer.h>
53 #include <KisMimeDatabase.h>
54 #include <KisReferenceImagesLayer.h>
55 
56 #include "KisPart.h"
57 #include "canvas/kis_canvas2.h"
58 #include "kis_shape_controller.h"
59 #include "kis_canvas_resource_provider.h"
60 #include "KisViewManager.h"
61 #include "KisDocument.h"
62 #include "kis_mask_manager.h"
63 #include "kis_group_layer.h"
64 #include "kis_layer_manager.h"
65 #include "kis_selection_manager.h"
66 #include "kis_node_commands_adapter.h"
67 #include "kis_action.h"
68 #include "kis_action_manager.h"
69 #include "kis_processing_applicator.h"
70 #include "kis_sequential_iterator.h"
71 #include "kis_transaction.h"
72 #include "kis_node_selection_adapter.h"
73 #include "kis_node_insertion_adapter.h"
74 #include "kis_node_juggler_compressed.h"
75 #include "KisNodeDisplayModeAdapter.h"
76 #include "kis_clipboard.h"
77 #include "kis_node_dummies_graph.h"
78 #include "kis_mimedata.h"
79 #include "kis_layer_utils.h"
80 #include "krita_utils.h"
81 #include "kis_shape_layer.h"
82 
83 #include "processing/kis_mirror_processing_visitor.h"
84 #include "KisView.h"
85 
86 #include <kis_signals_blocker.h>
87 #include <libs/image/kis_layer_properties_icons.h>
88 #include <libs/image/commands/kis_node_property_list_command.h>
89 
90 struct KisNodeManager::Private {
91 
PrivateKisNodeManager::Private92     Private(KisNodeManager *_q, KisViewManager *v)
93         : q(_q)
94         , view(v)
95         , imageView(0)
96         , layerManager(v)
97         , maskManager(v)
98         , commandsAdapter(v)
99         , nodeSelectionAdapter(new KisNodeSelectionAdapter(q))
100         , nodeInsertionAdapter(new KisNodeInsertionAdapter(q))
101         , nodeDisplayModeAdapter(new KisNodeDisplayModeAdapter())
102         , lastRequestedIsolatedModeStatus(false)
103     {
104     }
105 
106     KisNodeManager * q;
107     KisViewManager * view;
108     QPointer<KisView>imageView;
109     KisLayerManager layerManager;
110     KisMaskManager maskManager;
111     KisNodeCommandsAdapter commandsAdapter;
112     QScopedPointer<KisNodeSelectionAdapter> nodeSelectionAdapter;
113     QScopedPointer<KisNodeInsertionAdapter> nodeInsertionAdapter;
114     QScopedPointer<KisNodeDisplayModeAdapter> nodeDisplayModeAdapter;
115 
116     KisAction *showInTimeline;
117 
118     KisNodeList selectedNodes;
119     QPointer<KisNodeJugglerCompressed> nodeJuggler;
120 
121     KisNodeWSP previouslyActiveNode;
122 
123     bool activateNodeImpl(KisNodeSP node);
124 
125     KisSignalMapper nodeCreationSignalMapper;
126     KisSignalMapper nodeConversionSignalMapper;
127 
128     bool lastRequestedIsolatedModeStatus;
129 
130     void saveDeviceAsImage(KisPaintDeviceSP device,
131                            const QString &defaultName,
132                            const QRect &bounds,
133                            qreal xRes,
134                            qreal yRes,
135                            quint8 opacity);
136 
137     void mergeTransparencyMaskAsAlpha(bool writeToLayers);
138     KisNodeJugglerCompressed* lazyGetJuggler(const KUndo2MagicString &actionName);
139 };
140 
activateNodeImpl(KisNodeSP node)141 bool KisNodeManager::Private::activateNodeImpl(KisNodeSP node)
142 {
143     Q_ASSERT(view);
144     Q_ASSERT(view->canvasBase());
145     Q_ASSERT(view->canvasBase()->globalShapeManager());
146     Q_ASSERT(imageView);
147     if (node && node == q->activeNode()) {
148         return false;
149     }
150 
151     // Set the selection on the shape manager to the active layer
152     // and set call KoSelection::setActiveLayer( KoShapeLayer* layer )
153     // with the parent of the active layer.
154     KoSelection *selection = view->canvasBase()->globalShapeManager()->selection();
155     Q_ASSERT(selection);
156     selection->deselectAll();
157 
158     if (!node) {
159         selection->setActiveLayer(0);
160         imageView->setCurrentNode(0);
161         maskManager.activateMask(0);
162         layerManager.activateLayer(0);
163         previouslyActiveNode = q->activeNode();
164     } else {
165 
166         previouslyActiveNode = q->activeNode();
167 
168         KoShape * shape = view->document()->shapeForNode(node);
169 
170         //if (!shape) return false;
171         KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(shape, false);
172 
173         selection->select(shape);
174         KoShapeLayer * shapeLayer = dynamic_cast<KoShapeLayer*>(shape);
175 
176         //if (!shapeLayer) return false;
177         KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(shapeLayer, false);
178 
179         //         shapeLayer->setGeometryProtected(node->userLocked());
180         //         shapeLayer->setVisible(node->visible());
181         selection->setActiveLayer(shapeLayer);
182 
183         imageView->setCurrentNode(node);
184         if (KisLayerSP layer = qobject_cast<KisLayer*>(node.data())) {
185             maskManager.activateMask(0);
186             layerManager.activateLayer(layer);
187         } else if (KisMaskSP mask = dynamic_cast<KisMask*>(node.data())) {
188             maskManager.activateMask(mask);
189             // XXX_NODE: for now, masks cannot be nested.
190             layerManager.activateLayer(static_cast<KisLayer*>(node->parent().data()));
191         }
192     }
193     return true;
194 }
195 
KisNodeManager(KisViewManager * view)196 KisNodeManager::KisNodeManager(KisViewManager *view)
197     : m_d(new Private(this, view))
198 {
199 }
200 
~KisNodeManager()201 KisNodeManager::~KisNodeManager()
202 {
203     delete m_d;
204 }
205 
setView(QPointer<KisView> imageView)206 void KisNodeManager::setView(QPointer<KisView>imageView)
207 {
208     m_d->maskManager.setView(imageView);
209     m_d->layerManager.setView(imageView);
210 
211     if (m_d->imageView) {
212         KisShapeController *shapeController = dynamic_cast<KisShapeController*>(m_d->imageView->document()->shapeController());
213         Q_ASSERT(shapeController);
214         shapeController->disconnect(SIGNAL(sigActivateNode(KisNodeSP)), this);
215         m_d->imageView->image()->disconnect(this);
216     }
217 
218     m_d->imageView = imageView;
219 
220     if (m_d->imageView) {
221         KisShapeController *shapeController = dynamic_cast<KisShapeController*>(m_d->imageView->document()->shapeController());
222         Q_ASSERT(shapeController);
223         connect(shapeController, SIGNAL(sigActivateNode(KisNodeSP)), SLOT(slotNonUiActivatedNode(KisNodeSP)));
224         connect(m_d->imageView->image(), SIGNAL(sigIsolatedModeChanged()),this, SLOT(slotUpdateIsolateModeActionImageStatusChange()));
225         connect(m_d->imageView->image(), SIGNAL(sigRequestNodeReselection(KisNodeSP,KisNodeList)),this, SLOT(slotImageRequestNodeReselection(KisNodeSP,KisNodeList)));
226         m_d->imageView->resourceProvider()->slotNodeActivated(m_d->imageView->currentNode());
227     }
228 
229 }
230 
231 #define NEW_LAYER_ACTION(id, layerType)                                 \
232 {                                                                   \
233     action = actionManager->createAction(id);                       \
234     m_d->nodeCreationSignalMapper.setMapping(action, layerType);    \
235     connect(action, SIGNAL(triggered()),                            \
236     &m_d->nodeCreationSignalMapper, SLOT(map()));           \
237     }
238 
239 #define CONVERT_NODE_ACTION_2(id, layerType, exclude)                   \
240 {                                                                   \
241     action = actionManager->createAction(id);                       \
242     action->setExcludedNodeTypes(QStringList(exclude));             \
243     actionManager->addAction(id, action);                           \
244     m_d->nodeConversionSignalMapper.setMapping(action, layerType);  \
245     connect(action, SIGNAL(triggered()),                            \
246     &m_d->nodeConversionSignalMapper, SLOT(map()));         \
247     }
248 
249 #define CONVERT_NODE_ACTION(id, layerType)              \
250     CONVERT_NODE_ACTION_2(id, layerType, layerType)
251 
setup(KActionCollection * actionCollection,KisActionManager * actionManager)252 void KisNodeManager::setup(KActionCollection * actionCollection, KisActionManager* actionManager)
253 {
254     m_d->layerManager.setup(actionManager);
255     m_d->maskManager.setup(actionCollection, actionManager);
256 
257     KisAction * action = 0;
258 
259     action = actionManager->createAction("mirrorNodeX");
260     connect(action, SIGNAL(triggered()), this, SLOT(mirrorNodeX()));
261 
262     action  = actionManager->createAction("mirrorNodeY");
263     connect(action, SIGNAL(triggered()), this, SLOT(mirrorNodeY()));
264 
265     action = actionManager->createAction("mirrorAllNodesX");
266     connect(action, SIGNAL(triggered()), this, SLOT(mirrorAllNodesX()));
267 
268     action  = actionManager->createAction("mirrorAllNodesY");
269     connect(action, SIGNAL(triggered()), this, SLOT(mirrorAllNodesY()));
270 
271     action = actionManager->createAction("activateNextLayer");
272     connect(action, SIGNAL(triggered()), this, SLOT(activateNextNode()));
273 
274     action = actionManager->createAction("activateNextSiblingLayer");
275     connect(action, SIGNAL(triggered()), this, SLOT(activateNextSiblingNode()));
276 
277     action = actionManager->createAction("activatePreviousLayer");
278     connect(action, SIGNAL(triggered()), this, SLOT(activatePreviousNode()));
279 
280     action = actionManager->createAction("activatePreviousSiblingLayer");
281     connect(action, SIGNAL(triggered()), this, SLOT(activatePreviousSiblingNode()));
282 
283     action = actionManager->createAction("switchToPreviouslyActiveNode");
284     connect(action, SIGNAL(triggered()), this, SLOT(switchToPreviouslyActiveNode()));
285 
286     action  = actionManager->createAction("save_node_as_image");
287     connect(action, SIGNAL(triggered()), this, SLOT(saveNodeAsImage()));
288 
289     action  = actionManager->createAction("save_vector_node_to_svg");
290     connect(action, SIGNAL(triggered()), this, SLOT(saveVectorLayerAsImage()));
291     action->setActivationFlags(KisAction::ACTIVE_SHAPE_LAYER);
292 
293     action = actionManager->createAction("duplicatelayer");
294     connect(action, SIGNAL(triggered()), this, SLOT(duplicateActiveNode()));
295 
296     action = actionManager->createAction("copy_layer_clipboard");
297     connect(action, SIGNAL(triggered()), this, SLOT(copyLayersToClipboard()));
298 
299     action = actionManager->createAction("cut_layer_clipboard");
300     connect(action, SIGNAL(triggered()), this, SLOT(cutLayersToClipboard()));
301 
302     action = actionManager->createAction("paste_layer_from_clipboard");
303     connect(action, SIGNAL(triggered()), this, SLOT(pasteLayersFromClipboard()));
304 
305     action = actionManager->createAction("create_quick_group");
306     connect(action, SIGNAL(triggered()), this, SLOT(createQuickGroup()));
307 
308     action = actionManager->createAction("create_quick_clipping_group");
309     connect(action, SIGNAL(triggered()), this, SLOT(createQuickClippingGroup()));
310 
311     action = actionManager->createAction("quick_ungroup");
312     connect(action, SIGNAL(triggered()), this, SLOT(quickUngroup()));
313 
314     action = actionManager->createAction("select_all_layers");
315     connect(action, SIGNAL(triggered()), this, SLOT(selectAllNodes()));
316 
317     action = actionManager->createAction("select_visible_layers");
318     connect(action, SIGNAL(triggered()), this, SLOT(selectVisibleNodes()));
319 
320     action = actionManager->createAction("select_locked_layers");
321     connect(action, SIGNAL(triggered()), this, SLOT(selectLockedNodes()));
322 
323     action = actionManager->createAction("select_invisible_layers");
324     connect(action, SIGNAL(triggered()), this, SLOT(selectInvisibleNodes()));
325 
326     action = actionManager->createAction("select_unlocked_layers");
327     connect(action, SIGNAL(triggered()), this, SLOT(selectUnlockedNodes()));
328 
329     action = actionManager->createAction("new_from_visible");
330     connect(action, SIGNAL(triggered()), this, SLOT(createFromVisible()));
331 
332     action = actionManager->createAction("show_in_timeline");
333     action->setCheckable(true);
334     connect(action, SIGNAL(toggled(bool)), this, SLOT(slotShowHideTimeline(bool)));
335     m_d->showInTimeline = action;
336 
337     NEW_LAYER_ACTION("add_new_paint_layer", "KisPaintLayer");
338 
339     NEW_LAYER_ACTION("add_new_group_layer", "KisGroupLayer");
340 
341     NEW_LAYER_ACTION("add_new_clone_layer", "KisCloneLayer");
342 
343     NEW_LAYER_ACTION("add_new_shape_layer", "KisShapeLayer");
344 
345     NEW_LAYER_ACTION("add_new_adjustment_layer", "KisAdjustmentLayer");
346 
347     NEW_LAYER_ACTION("add_new_fill_layer", "KisGeneratorLayer");
348 
349     NEW_LAYER_ACTION("add_new_file_layer", "KisFileLayer");
350 
351     NEW_LAYER_ACTION("add_new_transparency_mask", "KisTransparencyMask");
352 
353     NEW_LAYER_ACTION("add_new_filter_mask", "KisFilterMask");
354 
355     NEW_LAYER_ACTION("add_new_colorize_mask", "KisColorizeMask");
356 
357     NEW_LAYER_ACTION("add_new_transform_mask", "KisTransformMask");
358 
359     NEW_LAYER_ACTION("add_new_selection_mask", "KisSelectionMask");
360 
361     connect(&m_d->nodeCreationSignalMapper, SIGNAL(mapped(QString)),
362             this, SLOT(createNode(QString)));
363 
364     CONVERT_NODE_ACTION("convert_to_paint_layer", "KisPaintLayer");
365 
366     CONVERT_NODE_ACTION_2("convert_to_selection_mask", "KisSelectionMask", QStringList() << "KisSelectionMask" << "KisColorizeMask");
367 
368     CONVERT_NODE_ACTION_2("convert_to_filter_mask", "KisFilterMask", QStringList() << "KisFilterMask" << "KisColorizeMask");
369 
370     CONVERT_NODE_ACTION_2("convert_to_transparency_mask", "KisTransparencyMask", QStringList() << "KisTransparencyMask" << "KisColorizeMask");
371 
372     CONVERT_NODE_ACTION("convert_to_animated", "animated");
373 
374     CONVERT_NODE_ACTION_2("convert_to_file_layer", "KisFileLayer", QStringList() << "KisFileLayer" << "KisCloneLayer");
375 
376     connect(&m_d->nodeConversionSignalMapper, SIGNAL(mapped(QString)),
377             this, SLOT(convertNode(QString)));
378 
379     action = actionManager->createAction("isolate_active_layer");
380     connect(action, SIGNAL(triggered(bool)), this, SLOT(toggleIsolateMode(bool)));
381 
382     action = actionManager->createAction("toggle_layer_visibility");
383     connect(action, SIGNAL(triggered()), this, SLOT(toggleVisibility()));
384 
385     action = actionManager->createAction("toggle_layer_lock");
386     connect(action, SIGNAL(triggered()), this, SLOT(toggleLock()));
387 
388     action = actionManager->createAction("toggle_layer_inherit_alpha");
389     connect(action, SIGNAL(triggered()), this, SLOT(toggleInheritAlpha()));
390 
391     action = actionManager->createAction("toggle_layer_alpha_lock");
392     connect(action, SIGNAL(triggered()), this, SLOT(toggleAlphaLock()));
393 
394     action  = actionManager->createAction("split_alpha_into_mask");
395     connect(action, SIGNAL(triggered()), this, SLOT(slotSplitAlphaIntoMask()));
396 
397     action  = actionManager->createAction("split_alpha_write");
398     connect(action, SIGNAL(triggered()), this, SLOT(slotSplitAlphaWrite()));
399 
400     // HINT: we can save even when the nodes are not editable
401     action  = actionManager->createAction("split_alpha_save_merged");
402     connect(action, SIGNAL(triggered()), this, SLOT(slotSplitAlphaSaveMerged()));
403 
404     connect(this, SIGNAL(sigNodeActivated(KisNodeSP)), SLOT(slotUpdateIsolateModeAction()));
405     connect(this, SIGNAL(sigNodeActivated(KisNodeSP)), SLOT(slotTryRestartIsolatedMode()));
406 }
407 
updateGUI()408 void KisNodeManager::updateGUI()
409 {
410     // enable/disable all relevant actions
411     m_d->layerManager.updateGUI();
412     m_d->maskManager.updateGUI();
413 }
414 
activeNode()415 KisNodeSP KisNodeManager::activeNode()
416 {
417     if (m_d->imageView) {
418         return m_d->imageView->currentNode();
419     }
420     return 0;
421 }
422 
activeLayer()423 KisLayerSP KisNodeManager::activeLayer()
424 {
425     return m_d->layerManager.activeLayer();
426 }
427 
activeColorSpace()428 const KoColorSpace* KisNodeManager::activeColorSpace()
429 {
430     if (m_d->maskManager.activeDevice()) {
431         return m_d->maskManager.activeDevice()->colorSpace();
432     } else {
433         Q_ASSERT(m_d->layerManager.activeLayer());
434         if (m_d->layerManager.activeLayer()->parentLayer())
435             return m_d->layerManager.activeLayer()->parentLayer()->colorSpace();
436         else
437             return m_d->view->image()->colorSpace();
438     }
439 }
440 
canModifyLayers(KisNodeList nodes,bool showWarning)441 bool KisNodeManager::canModifyLayers(KisNodeList nodes, bool showWarning)
442 {
443     KisNodeSP lockedNode;
444     Q_FOREACH (KisNodeSP node, nodes) {
445         if (!node->isEditable(false)) {
446             lockedNode = node;
447             break;
448         }
449     }
450 
451     if (lockedNode && showWarning) {
452         QString errorMessage;
453 
454         if (nodes.size() <= 1) {
455             errorMessage = i18n("Layer is locked");
456         } else {
457             errorMessage = i18n("Layer \"%1\" is locked", lockedNode->name());
458         }
459 
460         m_d->view->showFloatingMessage(errorMessage, QIcon());
461     }
462 
463     return !lockedNode;
464 }
465 
canModifyLayer(KisNodeSP node,bool showWarning)466 bool KisNodeManager::canModifyLayer(KisNodeSP node, bool showWarning)
467 {
468     return canModifyLayers({node}, showWarning);
469 }
470 
canMoveLayers(KisNodeList nodes,bool showWarning)471 bool KisNodeManager::canMoveLayers(KisNodeList nodes, bool showWarning)
472 {
473     KisNodeSP lockedNode;
474     Q_FOREACH (KisNodeSP node, nodes) {
475         if (node->parent() && !node->parent()->isEditable(false)) {
476             lockedNode = node->parent();
477             break;
478         }
479     }
480 
481     if (lockedNode && showWarning) {
482         QString errorMessage = i18n("Layer \"%1\" is locked", lockedNode->name());
483         m_d->view->showFloatingMessage(errorMessage, QIcon());
484     }
485 
486     return !lockedNode;
487 }
488 
canMoveLayer(KisNodeSP node,bool showWarning)489 bool KisNodeManager::canMoveLayer(KisNodeSP node, bool showWarning)
490 {
491     return canMoveLayers({node}, showWarning);
492 }
493 
moveNodeAt(KisNodeSP node,KisNodeSP parent,int index)494 void KisNodeManager::moveNodeAt(KisNodeSP node, KisNodeSP parent, int index)
495 {
496     if (parent->allowAsChild(node)) {
497         if (node->inherits("KisSelectionMask") && parent->inherits("KisLayer")) {
498             KisSelectionMask *m = dynamic_cast<KisSelectionMask*>(node.data());
499             KisLayer *l = qobject_cast<KisLayer*>(parent.data());
500             if (m && m->active() && l && l->selectionMask()) {
501                 l->selectionMask()->setActive(false);
502             }
503         }
504         m_d->commandsAdapter.moveNode(node, parent, index);
505     }
506 }
507 
moveNodesDirect(KisNodeList nodes,KisNodeSP parent,KisNodeSP aboveThis)508 void KisNodeManager::moveNodesDirect(KisNodeList nodes, KisNodeSP parent, KisNodeSP aboveThis)
509 {
510     KUndo2MagicString actionName = kundo2_i18n("Move Nodes");
511     KisNodeJugglerCompressed *juggler = m_d->lazyGetJuggler(actionName);
512     juggler->moveNode(nodes, parent, aboveThis);
513 }
514 
copyNodesDirect(KisNodeList nodes,KisNodeSP parent,KisNodeSP aboveThis)515 void KisNodeManager::copyNodesDirect(KisNodeList nodes, KisNodeSP parent, KisNodeSP aboveThis)
516 {
517     KUndo2MagicString actionName = kundo2_i18n("Copy Nodes");
518     KisNodeJugglerCompressed *juggler = m_d->lazyGetJuggler(actionName);
519     juggler->copyNode(nodes, parent, aboveThis);
520 }
521 
addNodesDirect(KisNodeList nodes,KisNodeSP parent,KisNodeSP aboveThis)522 void KisNodeManager::addNodesDirect(KisNodeList nodes, KisNodeSP parent, KisNodeSP aboveThis)
523 {
524     KUndo2MagicString actionName = kundo2_i18n("Add Nodes");
525     KisNodeJugglerCompressed *juggler = m_d->lazyGetJuggler(actionName);
526     juggler->addNode(nodes, parent, aboveThis);
527 }
528 
toggleIsolateActiveNode()529 void KisNodeManager::toggleIsolateActiveNode()
530 {
531     KisImageWSP image = m_d->view->image();
532     KisNodeSP activeNode = this->activeNode();
533     KIS_ASSERT_RECOVER_RETURN(activeNode);
534 
535     if (activeNode == image->isolatedModeRoot()) {
536         toggleIsolateMode(false);
537     } else {
538         toggleIsolateMode(true);
539     }
540 }
541 
toggleIsolateMode(bool checked)542 void KisNodeManager::toggleIsolateMode(bool checked)
543 {
544     KisImageWSP image = m_d->view->image();
545 
546     KisNodeSP activeNode = this->activeNode();
547     if (checked && activeNode) {
548 
549         // Transform and colorize masks don't have pixel data...
550         if (activeNode->inherits("KisTransformMask") ||
551                 activeNode->inherits("KisColorizeMask")) return;
552 
553         if (!image->startIsolatedMode(activeNode)) {
554             KisAction *action = m_d->view->actionManager()->actionByName("isolate_active_layer");
555             action->setChecked(false);
556         }
557     } else {
558         image->stopIsolatedMode();
559     }
560 
561     m_d->lastRequestedIsolatedModeStatus = checked;
562 }
563 
slotUpdateIsolateModeActionImageStatusChange()564 void KisNodeManager::slotUpdateIsolateModeActionImageStatusChange()
565 {
566     slotUpdateIsolateModeAction();
567 
568     KisNodeSP isolatedRootNode = m_d->view->image()->isolatedModeRoot();
569     if (this->activeNode() &&
570             bool(isolatedRootNode) != m_d->lastRequestedIsolatedModeStatus) {
571 
572         slotTryRestartIsolatedMode();
573     }
574 }
575 
slotUpdateIsolateModeAction()576 void KisNodeManager::slotUpdateIsolateModeAction()
577 {
578     KisAction *action = m_d->view->actionManager()->actionByName("isolate_active_layer");
579     Q_ASSERT(action);
580 
581     KisNodeSP activeNode = this->activeNode();
582     KisNodeSP isolatedRootNode = m_d->view->image()->isolatedModeRoot();
583 
584     action->setChecked(isolatedRootNode && isolatedRootNode == activeNode);
585 }
586 
slotTryRestartIsolatedMode()587 void KisNodeManager::slotTryRestartIsolatedMode()
588 {
589     /**
590      * It might be that we have multiple Krita windows open. In such a case
591      * only the currently active one should restart isolated mode
592      */
593     if (!m_d->view->mainWindow()->isActiveWindow()) return;
594 
595     KisNodeSP isolatedRootNode = m_d->view->image()->isolatedModeRoot();
596     if (!isolatedRootNode && !m_d->lastRequestedIsolatedModeStatus) return;
597 
598     this->toggleIsolateMode(true);
599 }
600 
createNode(const QString & nodeType,bool quiet,KisPaintDeviceSP copyFrom)601 KisNodeSP  KisNodeManager::createNode(const QString & nodeType, bool quiet, KisPaintDeviceSP copyFrom)
602 {
603     if (!m_d->view->blockUntilOperationsFinished(m_d->view->image())) {
604         return 0;
605     }
606 
607     KisNodeSP activeNode = this->activeNode();
608     if (!activeNode) {
609         activeNode = m_d->view->image()->root();
610     }
611 
612     KIS_ASSERT_RECOVER_RETURN_VALUE(activeNode, 0);
613 
614     /// the check for editability happens inside the functions
615     /// themselves, because layers can be created anyway (in a
616     /// different position), but masks cannot.
617 
618     // XXX: make factories for this kind of stuff,
619     //      with a registry
620 
621     if (nodeType == "KisPaintLayer") {
622         return m_d->layerManager.addPaintLayer(activeNode);
623     } else if (nodeType == "KisGroupLayer") {
624         return m_d->layerManager.addGroupLayer(activeNode);
625     } else if (nodeType == "KisAdjustmentLayer") {
626         return m_d->layerManager.addAdjustmentLayer(activeNode);
627     } else if (nodeType == "KisGeneratorLayer") {
628         return m_d->layerManager.addGeneratorLayer(activeNode);
629     } else if (nodeType == "KisShapeLayer") {
630         return m_d->layerManager.addShapeLayer(activeNode);
631     } else if (nodeType == "KisCloneLayer") {
632         KisNodeList nodes = selectedNodes();
633         if (nodes.isEmpty()) {
634             nodes.append(activeNode);
635         }
636 
637         return m_d->layerManager.addCloneLayer(nodes);
638     } else if (nodeType == "KisTransparencyMask") {
639         return m_d->maskManager.createTransparencyMask(activeNode, copyFrom, false);
640     } else if (nodeType == "KisFilterMask") {
641         return m_d->maskManager.createFilterMask(activeNode, copyFrom, quiet, false);
642     } else if (nodeType == "KisColorizeMask") {
643         return m_d->maskManager.createColorizeMask(activeNode);
644     } else if (nodeType == "KisTransformMask") {
645         return m_d->maskManager.createTransformMask(activeNode);
646     } else if (nodeType == "KisSelectionMask") {
647         return m_d->maskManager.createSelectionMask(activeNode, copyFrom, false);
648     } else if (nodeType == "KisFileLayer") {
649         return m_d->layerManager.addFileLayer(activeNode);
650     }
651     return 0;
652 }
653 
createFromVisible()654 void KisNodeManager::createFromVisible()
655 {
656     KisLayerUtils::newLayerFromVisible(m_d->view->image(), m_d->view->image()->root()->lastChild());
657 }
658 
slotShowHideTimeline(bool value)659 void KisNodeManager::slotShowHideTimeline(bool value)
660 {
661     Q_FOREACH (KisNodeSP node, selectedNodes()) {
662         node->setUseInTimeline(value);
663     }
664 }
665 
createPaintLayer()666 KisLayerSP KisNodeManager::createPaintLayer()
667 {
668     KisNodeSP node = createNode("KisPaintLayer");
669     return dynamic_cast<KisLayer*>(node.data());
670 }
671 
convertNode(const QString & nodeType)672 void KisNodeManager::convertNode(const QString &nodeType)
673 {
674     if (!m_d->view->blockUntilOperationsFinished(m_d->view->image())) {
675         return;
676     }
677 
678     KisNodeSP activeNode = this->activeNode();
679     if (!activeNode) return;
680 
681     if (!canModifyLayer(activeNode)) return;
682 
683     if (nodeType == "KisPaintLayer") {
684         m_d->layerManager.convertNodeToPaintLayer(activeNode);
685     } else if (nodeType == "KisSelectionMask" ||
686                nodeType == "KisFilterMask" ||
687                nodeType == "KisTransparencyMask") {
688 
689         KisPaintDeviceSP copyFrom = activeNode->paintDevice() ?
690                     activeNode->paintDevice() : activeNode->projection();
691 
692         m_d->commandsAdapter.beginMacro(kundo2_i18n("Convert to a Selection Mask"));
693 
694         bool result = false;
695 
696         if (nodeType == "KisSelectionMask") {
697             result = !m_d->maskManager.createSelectionMask(activeNode, copyFrom, true).isNull();
698         } else if (nodeType == "KisFilterMask") {
699             result = !m_d->maskManager.createFilterMask(activeNode, copyFrom, false, true).isNull();
700         } else if (nodeType == "KisTransparencyMask") {
701             result = !m_d->maskManager.createTransparencyMask(activeNode, copyFrom, true).isNull();
702         }
703 
704         m_d->commandsAdapter.endMacro();
705 
706         if (!result) {
707             m_d->view->blockUntilOperationsFinishedForced(m_d->imageView->image());
708             m_d->commandsAdapter.undoLastCommand();
709         }
710 
711     } else if (nodeType == "KisFileLayer") {
712         m_d->layerManager.convertLayerToFileLayer(activeNode);
713     } else {
714         warnKrita << "Unsupported node conversion type:" << nodeType;
715     }
716 }
717 
slotSomethingActivatedNodeImpl(KisNodeSP node)718 void KisNodeManager::slotSomethingActivatedNodeImpl(KisNodeSP node)
719 {
720     KisDummiesFacadeBase *dummiesFacade = dynamic_cast<KisDummiesFacadeBase*>(m_d->imageView->document()->shapeController());
721     KIS_SAFE_ASSERT_RECOVER_RETURN(dummiesFacade);
722 
723     const bool nodeVisible = !isNodeHidden(node, !m_d->nodeDisplayModeAdapter->showGlobalSelectionMask());
724     if (!nodeVisible) {
725         return;
726     }
727 
728     KIS_ASSERT_RECOVER_RETURN(node != activeNode());
729     if (m_d->activateNodeImpl(node)) {
730         emit sigUiNeedChangeActiveNode(node);
731         emit sigNodeActivated(node);
732         nodesUpdated();
733         if (node) {
734             bool toggled =  m_d->view->actionCollection()->action("view_show_canvas_only")->isChecked();
735             if (toggled) {
736                 m_d->view->showFloatingMessage( activeLayer()->name(), QIcon(), 1600, KisFloatingMessage::Medium, Qt::TextSingleLine);
737             }
738         }
739     }
740 }
741 
slotNonUiActivatedNode(KisNodeSP node)742 void KisNodeManager::slotNonUiActivatedNode(KisNodeSP node)
743 {
744     // the node must still be in the graph, some asynchronous
745     // signals may easily break this requirement
746     if (node && !node->graphListener()) {
747         node = 0;
748     }
749 
750     if (node == activeNode()) return;
751 
752     slotSomethingActivatedNodeImpl(node);
753 
754     if (node) {
755         bool toggled =  m_d->view->actionCollection()->action("view_show_canvas_only")->isChecked();
756         if (toggled) {
757             m_d->view->showFloatingMessage( activeLayer()->name(), QIcon(), 1600, KisFloatingMessage::Medium, Qt::TextSingleLine);
758         }
759     }
760 }
761 
slotUiActivatedNode(KisNodeSP node)762 void KisNodeManager::slotUiActivatedNode(KisNodeSP node)
763 {
764     // the node must still be in the graph, some asynchronous
765     // signals may easily break this requirement
766     if (node && !node->graphListener()) {
767         node = 0;
768     }
769 
770     if (node) {
771         QStringList vectorTools = QStringList()
772                 << "InteractionTool"
773                 << "KarbonGradientTool"
774                 << "KarbonCalligraphyTool"
775                 << "PathTool";
776 
777         QStringList pixelTools = QStringList()
778                 << "KritaShape/KisToolBrush"
779                 << "KritaShape/KisToolDyna"
780                 << "KritaShape/KisToolMultiBrush"
781                 << "KritaFill/KisToolFill"
782                 << "KritaFill/KisToolGradient";
783 
784 
785         KisSelectionMask *selectionMask = dynamic_cast<KisSelectionMask*>(node.data());
786         const bool nodeHasVectorAbilities = node->inherits("KisShapeLayer") ||
787                 (selectionMask && selectionMask->selection()->hasShapeSelection());
788 
789         if (nodeHasVectorAbilities) {
790             if (pixelTools.contains(KoToolManager::instance()->activeToolId())) {
791                 KoToolManager::instance()->switchToolRequested("InteractionTool");
792             }
793         }
794         else {
795             if (vectorTools.contains(KoToolManager::instance()->activeToolId())) {
796                 KoToolManager::instance()->switchToolRequested("KritaShape/KisToolBrush");
797             }
798         }
799     }
800 
801     if (node == activeNode()) return;
802 
803     slotSomethingActivatedNodeImpl(node);
804 }
805 
nodesUpdated()806 void KisNodeManager::nodesUpdated()
807 {
808     KisNodeSP node = activeNode();
809     if (!node) return;
810 
811     m_d->layerManager.layersUpdated();
812     m_d->maskManager.masksUpdated();
813 
814     m_d->view->updateGUI();
815     m_d->view->selectionManager()->selectionChanged();
816 
817     {
818         KisSignalsBlocker b(m_d->showInTimeline);
819         m_d->showInTimeline->setChecked(node->useInTimeline());
820     }
821 }
822 
activePaintDevice()823 KisPaintDeviceSP KisNodeManager::activePaintDevice()
824 {
825     return m_d->maskManager.activeMask() ?
826                 m_d->maskManager.activeDevice() :
827                 m_d->layerManager.activeDevice();
828 }
829 
nodeProperties(KisNodeSP node)830 void KisNodeManager::nodeProperties(KisNodeSP node)
831 {
832     if ((selectedNodes().size() > 1 && node->inherits("KisLayer")) || node->inherits("KisLayer")) {
833         m_d->layerManager.layerProperties();
834     }
835     else if (node->inherits("KisMask")) {
836         m_d->maskManager.maskProperties();
837     }
838 }
839 
changeCloneSource()840 void KisNodeManager::changeCloneSource()
841 {
842     m_d->layerManager.changeCloneSource();
843 }
844 
convertOpacityToInt(qreal opacity)845 qint32 KisNodeManager::convertOpacityToInt(qreal opacity)
846 {
847     /**
848      * Scales opacity from the range 0...100
849      * to the integer range 0...255
850      */
851 
852     return qMin(255, int(opacity * 2.55 + 0.5));
853 }
854 
setNodeName(KisNodeSP node,const QString & name)855 void KisNodeManager::setNodeName(KisNodeSP node, const QString &name)
856 {
857     if (!node) return;
858     if (node->name() == name) return;
859 
860     m_d->commandsAdapter.setNodeName(node, name);
861 
862 }
863 
setNodeOpacity(KisNodeSP node,qint32 opacity)864 void KisNodeManager::setNodeOpacity(KisNodeSP node, qint32 opacity)
865 {
866     if (!node) return;
867     if (node->opacity() == opacity) return;
868 
869     m_d->commandsAdapter.setOpacity(node, opacity);
870 }
871 
setNodeCompositeOp(KisNodeSP node,const KoCompositeOp * compositeOp)872 void KisNodeManager::setNodeCompositeOp(KisNodeSP node,
873                                         const KoCompositeOp* compositeOp)
874 {
875     if (!node) return;
876     if (node->compositeOp() == compositeOp) return;
877 
878     m_d->commandsAdapter.setCompositeOp(node, compositeOp);
879 }
880 
slotImageRequestNodeReselection(KisNodeSP activeNode,const KisNodeList & selectedNodes)881 void KisNodeManager::slotImageRequestNodeReselection(KisNodeSP activeNode, const KisNodeList &selectedNodes)
882 {
883     if (activeNode) {
884         slotNonUiActivatedNode(activeNode);
885     }
886     if (!selectedNodes.isEmpty()) {
887         slotSetSelectedNodes(selectedNodes);
888     }
889 }
890 
slotSetSelectedNodes(const KisNodeList & nodes)891 void KisNodeManager::slotSetSelectedNodes(const KisNodeList &nodes)
892 {
893     m_d->selectedNodes = nodes;
894     emit sigUiNeedChangeSelectedNodes(nodes);
895 }
896 
selectedNodes()897 KisNodeList KisNodeManager::selectedNodes()
898 {
899     return m_d->selectedNodes;
900 }
901 
nodeSelectionAdapter() const902 KisNodeSelectionAdapter* KisNodeManager::nodeSelectionAdapter() const
903 {
904     return m_d->nodeSelectionAdapter.data();
905 }
906 
nodeInsertionAdapter() const907 KisNodeInsertionAdapter* KisNodeManager::nodeInsertionAdapter() const
908 {
909     return m_d->nodeInsertionAdapter.data();
910 }
911 
nodeDisplayModeAdapter() const912 KisNodeDisplayModeAdapter *KisNodeManager::nodeDisplayModeAdapter() const
913 {
914     return m_d->nodeDisplayModeAdapter.data();
915 }
916 
isNodeHidden(KisNodeSP node,bool isGlobalSelectionHidden)917 bool KisNodeManager::isNodeHidden(KisNodeSP node, bool isGlobalSelectionHidden)
918 {
919     if (node && node->isFakeNode()) {
920         return true;
921     }
922 
923     if (isGlobalSelectionHidden && dynamic_cast<KisSelectionMask *>(node.data()) &&
924             (!node->parent() || !node->parent()->parent())) {
925         return true;
926     }
927 
928     return false;
929 }
930 
trySetNodeProperties(KisNodeSP node,KisImageSP image,KisBaseNode::PropertyList properties) const931 bool KisNodeManager::trySetNodeProperties(KisNodeSP node, KisImageSP image, KisBaseNode::PropertyList properties) const
932 {
933     const KisPaintLayer *paintLayer = dynamic_cast<KisPaintLayer*>(node.data());
934     if (paintLayer) {
935         const auto onionSkinOn = KisLayerPropertiesIcons::getProperty(KisLayerPropertiesIcons::onionSkins, true);
936 
937         if (properties.contains(onionSkinOn)) {
938             const KisPaintDeviceSP &paintDevice = paintLayer->paintDevice();
939             if (paintDevice && paintDevice->defaultPixel().opacityU8() == 255) {
940                 m_d->view->showFloatingMessage(i18n("Onion skins require a layer with transparent background."), QIcon());
941                 return false;
942             }
943         }
944     }
945 
946     KisNodePropertyListCommand::setNodePropertiesAutoUndo(node, image, properties);
947 
948     return true;
949 }
950 
nodeOpacityChanged(qreal opacity)951 void KisNodeManager::nodeOpacityChanged(qreal opacity)
952 {
953     KisNodeSP node = activeNode();
954 
955     setNodeOpacity(node, convertOpacityToInt(opacity));
956 }
957 
nodeCompositeOpChanged(const KoCompositeOp * op)958 void KisNodeManager::nodeCompositeOpChanged(const KoCompositeOp* op)
959 {
960     KisNodeSP node = activeNode();
961 
962     setNodeCompositeOp(node, op);
963 }
964 
duplicateActiveNode()965 void KisNodeManager::duplicateActiveNode()
966 {
967     KUndo2MagicString actionName = kundo2_i18n("Duplicate Nodes");
968     KisNodeJugglerCompressed *juggler = m_d->lazyGetJuggler(actionName);
969     juggler->duplicateNode(selectedNodes());
970 }
971 
lazyGetJuggler(const KUndo2MagicString & actionName)972 KisNodeJugglerCompressed* KisNodeManager::Private::lazyGetJuggler(const KUndo2MagicString &actionName)
973 {
974     KisImageWSP image = view->image();
975 
976     if (!nodeJuggler ||
977             (nodeJuggler &&
978              (nodeJuggler->isEnded() ||
979               !nodeJuggler->canMergeAction(actionName)))) {
980 
981         nodeJuggler = new KisNodeJugglerCompressed(actionName, image, q, 750);
982         nodeJuggler->setAutoDelete(true);
983     }
984 
985     return nodeJuggler;
986 }
987 
raiseNode()988 void KisNodeManager::raiseNode()
989 {
990     if (!canMoveLayers(selectedNodes())) return;
991 
992     KUndo2MagicString actionName = kundo2_i18n("Raise Nodes");
993     KisNodeJugglerCompressed *juggler = m_d->lazyGetJuggler(actionName);
994     juggler->raiseNode(selectedNodes());
995 }
996 
lowerNode()997 void KisNodeManager::lowerNode()
998 {
999     if (!canMoveLayers(selectedNodes())) return;
1000 
1001     KUndo2MagicString actionName = kundo2_i18n("Lower Nodes");
1002     KisNodeJugglerCompressed *juggler = m_d->lazyGetJuggler(actionName);
1003     juggler->lowerNode(selectedNodes());
1004 }
1005 
removeSingleNode(KisNodeSP node)1006 void KisNodeManager::removeSingleNode(KisNodeSP node)
1007 {
1008     if (!node || !node->parent()) {
1009         return;
1010     }
1011 
1012     KisNodeList nodes;
1013     nodes << node;
1014     removeSelectedNodes(nodes);
1015 }
1016 
removeSelectedNodes(KisNodeList nodes)1017 void KisNodeManager::removeSelectedNodes(KisNodeList nodes)
1018 {
1019     if (!canModifyLayers(nodes)) return;
1020 
1021     KUndo2MagicString actionName = kundo2_i18n("Remove Nodes");
1022     KisNodeJugglerCompressed *juggler = m_d->lazyGetJuggler(actionName);
1023     juggler->removeNode(nodes);
1024 }
1025 
removeNode()1026 void KisNodeManager::removeNode()
1027 {
1028     removeSelectedNodes(selectedNodes());
1029 }
1030 
mirrorNodeX()1031 void KisNodeManager::mirrorNodeX()
1032 {
1033     KisNodeSP node = activeNode();
1034 
1035     KUndo2MagicString commandName;
1036     if (node->inherits("KisLayer")) {
1037         commandName = kundo2_i18n("Mirror Layer X");
1038     } else if (node->inherits("KisMask")) {
1039         commandName = kundo2_i18n("Mirror Mask X");
1040     }
1041     mirrorNode(node, commandName, Qt::Horizontal, m_d->view->selection());
1042 }
1043 
mirrorNodeY()1044 void KisNodeManager::mirrorNodeY()
1045 {
1046     KisNodeSP node = activeNode();
1047 
1048     KUndo2MagicString commandName;
1049     if (node->inherits("KisLayer")) {
1050         commandName = kundo2_i18n("Mirror Layer Y");
1051     } else if (node->inherits("KisMask")) {
1052         commandName = kundo2_i18n("Mirror Mask Y");
1053     }
1054     mirrorNode(node, commandName, Qt::Vertical, m_d->view->selection());
1055 }
1056 
mirrorAllNodesX()1057 void KisNodeManager::mirrorAllNodesX()
1058 {
1059     KisNodeSP node = m_d->view->image()->root();
1060     mirrorNode(node, kundo2_i18n("Mirror All Layers X"),
1061                Qt::Horizontal, m_d->view->selection());
1062 }
1063 
mirrorAllNodesY()1064 void KisNodeManager::mirrorAllNodesY()
1065 {
1066     KisNodeSP node = m_d->view->image()->root();
1067     mirrorNode(node, kundo2_i18n("Mirror All Layers Y"),
1068                Qt::Vertical, m_d->view->selection());
1069 }
1070 
activateNextNode(bool siblingsOnly)1071 void KisNodeManager::activateNextNode(bool siblingsOnly)
1072 {
1073     KisNodeSP activeNode = this->activeNode();
1074     if (!activeNode) return;
1075 
1076     KisNodeSP nextNode = activeNode->nextSibling();
1077 
1078     if (!siblingsOnly) {
1079         // Recurse groups...
1080         while (nextNode && nextNode->childCount() > 0) {
1081             nextNode = nextNode->firstChild();
1082         }
1083 
1084         // Out of nodes? Back out of group...
1085         if (!nextNode && activeNode->parent()) {
1086             nextNode = activeNode->parent();
1087         }
1088     }
1089 
1090     // Skip nodes hidden from tree view..
1091     while (nextNode && isNodeHidden(nextNode, m_d->nodeDisplayModeAdapter->showGlobalSelectionMask())) {
1092         nextNode = nextNode->nextSibling();
1093     }
1094 
1095     // Select node, unless root..
1096     if (nextNode && nextNode->parent()) {
1097         slotNonUiActivatedNode(nextNode);
1098     }
1099 }
1100 
activateNextSiblingNode()1101 void KisNodeManager::activateNextSiblingNode()
1102 {
1103     activateNextNode(true);
1104 }
1105 
activatePreviousNode(bool siblingsOnly)1106 void KisNodeManager::activatePreviousNode(bool siblingsOnly)
1107 {
1108     KisNodeSP activeNode = this->activeNode();
1109     if (!activeNode) return;
1110 
1111     KisNodeSP nextNode = activeNode->prevSibling();
1112 
1113     if (!siblingsOnly) {
1114         // Enter groups..
1115         if (activeNode->childCount() > 0) {
1116             nextNode = activeNode->lastChild();
1117         }
1118 
1119         // Out of nodes? Back out of group...
1120         if (!nextNode && activeNode->parent()) {
1121             nextNode = activeNode->parent()->prevSibling();
1122         }
1123     }
1124 
1125     // Skip nodes hidden from tree view..
1126     while (nextNode && isNodeHidden(nextNode, m_d->nodeDisplayModeAdapter->showGlobalSelectionMask())) {
1127         nextNode = nextNode->prevSibling();
1128     }
1129 
1130     // Select node, unless root..
1131     if (nextNode && nextNode->parent()) {
1132         slotNonUiActivatedNode(nextNode);
1133     }
1134 }
1135 
activatePreviousSiblingNode()1136 void KisNodeManager::activatePreviousSiblingNode()
1137 {
1138     activatePreviousNode(true);
1139 }
1140 
switchToPreviouslyActiveNode()1141 void KisNodeManager::switchToPreviouslyActiveNode()
1142 {
1143     if (m_d->previouslyActiveNode && m_d->previouslyActiveNode->parent()) {
1144         slotNonUiActivatedNode(m_d->previouslyActiveNode);
1145     }
1146 }
1147 
mirrorNode(KisNodeSP node,const KUndo2MagicString & actionName,Qt::Orientation orientation,KisSelectionSP selection)1148 void KisNodeManager::mirrorNode(KisNodeSP node,
1149                                 const KUndo2MagicString& actionName,
1150                                 Qt::Orientation orientation,
1151                                 KisSelectionSP selection)
1152 {
1153     if (!canModifyLayer(node)) return;
1154 
1155     KisImageSignalVector emitSignals;
1156     emitSignals << ModifiedSignal;
1157 
1158     KisProcessingApplicator applicator(m_d->view->image(), node,
1159                                        KisProcessingApplicator::RECURSIVE,
1160                                        emitSignals, actionName);
1161 
1162     KisProcessingVisitorSP visitor;
1163 
1164     if (selection) {
1165         visitor = new KisMirrorProcessingVisitor(selection, orientation);
1166     } else {
1167         visitor = new KisMirrorProcessingVisitor(m_d->view->image()->bounds(), orientation);
1168     }
1169 
1170     if (!selection) {
1171         applicator.applyVisitorAllFrames(visitor, KisStrokeJobData::CONCURRENT);
1172     } else {
1173         applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT);
1174     }
1175 
1176     applicator.end();
1177 
1178     nodesUpdated();
1179 }
1180 
saveDeviceAsImage(KisPaintDeviceSP device,const QString & defaultName,const QRect & bounds,qreal xRes,qreal yRes,quint8 opacity)1181 void KisNodeManager::Private::saveDeviceAsImage(KisPaintDeviceSP device,
1182                                                 const QString &defaultName,
1183                                                 const QRect &bounds,
1184                                                 qreal xRes,
1185                                                 qreal yRes,
1186                                                 quint8 opacity)
1187 {
1188     KoFileDialog dialog(view->mainWindow(), KoFileDialog::SaveFile, "savenodeasimage");
1189     dialog.setCaption(i18n("Export \"%1\"", defaultName));
1190     dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
1191     dialog.setMimeTypeFilters(KisImportExportManager::supportedMimeTypes(KisImportExportManager::Export));
1192     QString filename = dialog.filename();
1193 
1194     if (filename.isEmpty()) return;
1195 
1196     QUrl url = QUrl::fromLocalFile(filename);
1197 
1198     if (url.isEmpty()) return;
1199 
1200     QString mimefilter = KisMimeDatabase::mimeTypeForFile(filename, false);
1201 
1202     QScopedPointer<KisDocument> doc(KisPart::instance()->createDocument());
1203 
1204     KisImageSP dst = new KisImage(doc->createUndoStore(),
1205                                   bounds.width(),
1206                                   bounds.height(),
1207                                   device->compositionSourceColorSpace(),
1208                                   defaultName);
1209     dst->setResolution(xRes, yRes);
1210     doc->setCurrentImage(dst);
1211     KisPaintLayer* paintLayer = new KisPaintLayer(dst, "paint device", opacity);
1212     paintLayer->paintDevice()->makeCloneFrom(device, bounds);
1213     dst->addNode(paintLayer, dst->rootLayer(), KisLayerSP(0));
1214 
1215     dst->initialRefreshGraph();
1216 
1217     if (!doc->exportDocumentSync(url, mimefilter.toLatin1())) {
1218         QMessageBox::warning(0,
1219                              i18nc("@title:window", "Krita"),
1220                              i18n("Could not save the layer. %1", doc->errorMessage().toUtf8().data()),
1221                              QMessageBox::Ok);
1222 
1223     }
1224 }
1225 
saveNodeAsImage()1226 void KisNodeManager::saveNodeAsImage()
1227 {
1228     KisNodeSP node = activeNode();
1229 
1230     if (!node) {
1231         warnKrita << "BUG: Save Node As Image was called without any node selected";
1232         return;
1233     }
1234 
1235     KisPaintDeviceSP saveDevice = node->projection();
1236 
1237     if (!saveDevice) {
1238         return;
1239     }
1240 
1241     KisImageSP image = m_d->view->image();
1242     QRect saveRect = image->bounds() | node->exactBounds();
1243 
1244     m_d->saveDeviceAsImage(saveDevice,
1245                            node->name(),
1246                            saveRect,
1247                            image->xRes(), image->yRes(),
1248                            node->opacity());
1249 }
1250 
1251 #include "SvgWriter.h"
1252 
saveVectorLayerAsImage()1253 void KisNodeManager::saveVectorLayerAsImage()
1254 {
1255     KisShapeLayerSP shapeLayer = qobject_cast<KisShapeLayer*>(activeNode().data());
1256     if (!shapeLayer) {
1257         return;
1258     }
1259 
1260     KoFileDialog dialog(m_d->view->mainWindow(), KoFileDialog::SaveFile, "savenodeasimage");
1261     dialog.setCaption(i18nc("@title:window", "Export to SVG"));
1262     dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
1263     dialog.setMimeTypeFilters(QStringList() << "image/svg+xml", "image/svg+xml");
1264     QString filename = dialog.filename();
1265 
1266     if (filename.isEmpty()) return;
1267 
1268     QUrl url = QUrl::fromLocalFile(filename);
1269 
1270     if (url.isEmpty()) return;
1271 
1272     const QSizeF sizeInPx = m_d->view->image()->bounds().size();
1273     const QSizeF sizeInPt(sizeInPx.width() / m_d->view->image()->xRes(),
1274                           sizeInPx.height() / m_d->view->image()->yRes());
1275 
1276     QList<KoShape*> shapes = shapeLayer->shapes();
1277     std::sort(shapes.begin(), shapes.end(), KoShape::compareShapeZIndex);
1278 
1279     SvgWriter writer(shapes);
1280     if (!writer.save(filename, sizeInPt, true)) {
1281         QMessageBox::warning(qApp->activeWindow(), i18nc("@title:window", "Krita"), i18n("Could not save to svg: %1", filename));
1282     }
1283 }
1284 
slotSplitAlphaIntoMask()1285 void KisNodeManager::slotSplitAlphaIntoMask()
1286 {
1287     KisNodeSP node = activeNode();
1288     if (!canModifyLayer(node)) return;
1289 
1290     // guaranteed by KisActionManager
1291     KIS_ASSERT_RECOVER_RETURN(node->hasEditablePaintDevice());
1292 
1293     KisPaintDeviceSP srcDevice = node->paintDevice();
1294     const KoColorSpace *srcCS = srcDevice->colorSpace();
1295     const QRect processRect =
1296             srcDevice->exactBounds() |
1297             srcDevice->defaultBounds()->bounds();
1298 
1299     KisPaintDeviceSP selectionDevice =
1300             new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8());
1301 
1302     m_d->commandsAdapter.beginMacro(kundo2_i18n("Split Alpha into a Mask"));
1303     KisTransaction transaction(kundo2_noi18n("__split_alpha_channel__"), srcDevice);
1304 
1305     KisSequentialIterator srcIt(srcDevice, processRect);
1306     KisSequentialIterator dstIt(selectionDevice, processRect);
1307 
1308     while (srcIt.nextPixel() && dstIt.nextPixel()) {
1309         quint8 *srcPtr = srcIt.rawData();
1310         quint8 *alpha8Ptr = dstIt.rawData();
1311 
1312         *alpha8Ptr = srcCS->opacityU8(srcPtr);
1313         srcCS->setOpacity(srcPtr, OPACITY_OPAQUE_U8, 1);
1314     }
1315 
1316     m_d->commandsAdapter.addExtraCommand(transaction.endAndTake());
1317 
1318     createNode("KisTransparencyMask", false, selectionDevice);
1319     m_d->commandsAdapter.endMacro();
1320 }
1321 
mergeTransparencyMaskAsAlpha(bool writeToLayers)1322 void KisNodeManager::Private::mergeTransparencyMaskAsAlpha(bool writeToLayers)
1323 {
1324     KisNodeSP node = q->activeNode();
1325     KisNodeSP parentNode = node->parent();
1326 
1327     // guaranteed by KisActionManager
1328     KIS_ASSERT_RECOVER_RETURN(node->inherits("KisTransparencyMask"));
1329 
1330     if (writeToLayers && (!parentNode->hasEditablePaintDevice() || !node->isEditable(false))) {
1331         QMessageBox::information(view->mainWindow(),
1332                                  i18nc("@title:window", "Layer %1 is not editable", parentNode->name()),
1333                                  i18n("Cannot write alpha channel of "
1334                                       "the parent layer \"%1\".\n"
1335                                       "The operation will be cancelled.", parentNode->name()));
1336         return;
1337     }
1338 
1339     KisPaintDeviceSP dstDevice;
1340     if (writeToLayers) {
1341         KIS_ASSERT_RECOVER_RETURN(parentNode->paintDevice());
1342         dstDevice = parentNode->paintDevice();
1343     } else {
1344         KisPaintDeviceSP copyDevice = parentNode->paintDevice();
1345         if (!copyDevice) {
1346             copyDevice = parentNode->original();
1347         }
1348         dstDevice = new KisPaintDevice(*copyDevice);
1349     }
1350 
1351     const KoColorSpace *dstCS = dstDevice->colorSpace();
1352 
1353     KisPaintDeviceSP selectionDevice = node->paintDevice();
1354     KIS_ASSERT_RECOVER_RETURN(selectionDevice->colorSpace()->pixelSize() == 1);
1355 
1356     const QRect processRect =
1357             selectionDevice->exactBounds() |
1358             dstDevice->exactBounds() |
1359             selectionDevice->defaultBounds()->bounds();
1360 
1361     QScopedPointer<KisTransaction> transaction;
1362 
1363     if (writeToLayers) {
1364         commandsAdapter.beginMacro(kundo2_i18n("Write Alpha into a Layer"));
1365         transaction.reset(new KisTransaction(kundo2_noi18n("__write_alpha_channel__"), dstDevice));
1366     }
1367 
1368     KisSequentialIterator srcIt(selectionDevice, processRect);
1369     KisSequentialIterator dstIt(dstDevice, processRect);
1370 
1371     while (srcIt.nextPixel() && dstIt.nextPixel()) {
1372         quint8 *alpha8Ptr = srcIt.rawData();
1373         quint8 *dstPtr = dstIt.rawData();
1374 
1375         dstCS->setOpacity(dstPtr, *alpha8Ptr, 1);
1376     }
1377 
1378     if (writeToLayers) {
1379         commandsAdapter.addExtraCommand(transaction->endAndTake());
1380         commandsAdapter.removeNode(node);
1381         commandsAdapter.endMacro();
1382     } else {
1383         KisImageWSP image = view->image();
1384         QRect saveRect = image->bounds();
1385 
1386         saveDeviceAsImage(dstDevice, parentNode->name(),
1387                           saveRect,
1388                           image->xRes(), image->yRes(),
1389                           OPACITY_OPAQUE_U8);
1390     }
1391 }
1392 
1393 
slotSplitAlphaWrite()1394 void KisNodeManager::slotSplitAlphaWrite()
1395 {
1396     m_d->mergeTransparencyMaskAsAlpha(true);
1397 }
1398 
slotSplitAlphaSaveMerged()1399 void KisNodeManager::slotSplitAlphaSaveMerged()
1400 {
1401     m_d->mergeTransparencyMaskAsAlpha(false);
1402 }
1403 
toggleLock()1404 void KisNodeManager::toggleLock()
1405 {
1406     KisNodeList nodes = this->selectedNodes();
1407     KisNodeSP active = activeNode();
1408     if (nodes.isEmpty() || !active) return;
1409 
1410     bool isLocked = active->userLocked();
1411 
1412     for (auto &node : nodes) {
1413         KisLayerPropertiesIcons::setNodePropertyAutoUndo(node, KisLayerPropertiesIcons::locked, !isLocked, m_d->view->image());
1414     }
1415 }
1416 
toggleVisibility()1417 void KisNodeManager::toggleVisibility()
1418 {
1419     KisNodeList nodes = this->selectedNodes();
1420     KisNodeSP active = activeNode();
1421     if (nodes.isEmpty() || !active) return;
1422 
1423     bool isVisible = active->visible();
1424 
1425     for (auto &node : nodes) {
1426         KisLayerPropertiesIcons::setNodePropertyAutoUndo(node, KisLayerPropertiesIcons::visible, !isVisible, m_d->view->image());
1427     }
1428 }
1429 
toggleAlphaLock()1430 void KisNodeManager::toggleAlphaLock()
1431 {
1432     KisNodeList nodes = this->selectedNodes();
1433     KisNodeSP active = activeNode();
1434     if (nodes.isEmpty() || !active) return;
1435 
1436     auto layer = qobject_cast<KisPaintLayer*>(active.data());
1437     if (!layer) {
1438         return;
1439     }
1440 
1441     bool isAlphaLocked = layer->alphaLocked();
1442     for (auto &node : nodes) {
1443         auto layer = qobject_cast<KisPaintLayer*>(node.data());
1444         if (layer) {
1445             KisLayerPropertiesIcons::setNodePropertyAutoUndo(node, KisLayerPropertiesIcons::alphaLocked, !isAlphaLocked, m_d->view->image());
1446         }
1447     }
1448 }
1449 
toggleInheritAlpha()1450 void KisNodeManager::toggleInheritAlpha()
1451 {
1452     KisNodeList nodes = this->selectedNodes();
1453     KisNodeSP active = activeNode();
1454     if (nodes.isEmpty() || !active) return;
1455 
1456     auto layer = qobject_cast<KisLayer*>(active.data());
1457     if (!layer) {
1458         return;
1459     }
1460 
1461     bool isAlphaDisabled = layer->alphaChannelDisabled();
1462     for (auto &node : nodes) {
1463         auto layer = qobject_cast<KisLayer*>(node.data());
1464         if (layer) {
1465             KisLayerPropertiesIcons::setNodePropertyAutoUndo(node, KisLayerPropertiesIcons::inheritAlpha, !isAlphaDisabled, m_d->view->image());
1466         }
1467     }
1468 }
1469 
cutLayersToClipboard()1470 void KisNodeManager::cutLayersToClipboard()
1471 {
1472     KisNodeList nodes = this->selectedNodes();
1473     if (nodes.isEmpty()) return;
1474 
1475     KisClipboard::instance()->setLayers(nodes, m_d->view->image(), false);
1476 
1477     if (canModifyLayers(nodes)) {
1478         KUndo2MagicString actionName = kundo2_i18n("Cut Nodes");
1479         KisNodeJugglerCompressed *juggler = m_d->lazyGetJuggler(actionName);
1480         juggler->removeNode(nodes);
1481     }
1482 }
1483 
copyLayersToClipboard()1484 void KisNodeManager::copyLayersToClipboard()
1485 {
1486     KisNodeList nodes = this->selectedNodes();
1487     KisClipboard::instance()->setLayers(nodes, m_d->view->image(), true);
1488 }
1489 
pasteLayersFromClipboard()1490 void KisNodeManager::pasteLayersFromClipboard()
1491 {
1492     const QMimeData *data = KisClipboard::instance()->layersMimeData();
1493     if (!data) return;
1494 
1495     KisNodeSP activeNode = this->activeNode();
1496 
1497     KisShapeController *shapeController = dynamic_cast<KisShapeController*>(m_d->imageView->document()->shapeController());
1498     Q_ASSERT(shapeController);
1499 
1500     KisDummiesFacadeBase *dummiesFacade = dynamic_cast<KisDummiesFacadeBase*>(m_d->imageView->document()->shapeController());
1501     Q_ASSERT(dummiesFacade);
1502 
1503     const bool copyNode = false;
1504     KisImageSP image = m_d->view->image();
1505     KisNodeDummy *parentDummy = dummiesFacade->dummyForNode(activeNode);
1506     KisNodeDummy *aboveThisDummy = parentDummy ? parentDummy->lastChild() : 0;
1507 
1508     KisMimeData::insertMimeLayers(data,
1509                                   image,
1510                                   shapeController,
1511                                   parentDummy,
1512                                   aboveThisDummy,
1513                                   copyNode,
1514                                   nodeInsertionAdapter());
1515 }
1516 
createQuickGroupImpl(KisNodeJugglerCompressed * juggler,const QString & overrideGroupName,KisNodeSP * newGroup,KisNodeSP * newLastChild)1517 bool KisNodeManager::createQuickGroupImpl(KisNodeJugglerCompressed *juggler,
1518                                           const QString &overrideGroupName,
1519                                           KisNodeSP *newGroup,
1520                                           KisNodeSP *newLastChild)
1521 {
1522     KisNodeSP active = activeNode();
1523     if (!active) return false;
1524 
1525     if (!canMoveLayer(active)) return false;
1526 
1527     KisImageSP image = m_d->view->image();
1528     QString groupName = !overrideGroupName.isEmpty() ? overrideGroupName : image->nextLayerName(i18n("Group"));
1529     KisGroupLayerSP group = new KisGroupLayer(image.data(), groupName, OPACITY_OPAQUE_U8);
1530 
1531     KisNodeList nodes1;
1532     nodes1 << group;
1533 
1534     KisNodeList nodes2;
1535     nodes2 = KisLayerUtils::sortMergableNodes(image->root(), selectedNodes());
1536     KisLayerUtils::filterMergableNodes(nodes2);
1537 
1538     if (nodes2.size() == 0) return false;
1539 
1540     if (KisLayerUtils::checkIsChildOf(active, nodes2)) {
1541         active = nodes2.first();
1542     }
1543 
1544     KisNodeSP parent = active->parent();
1545     KisNodeSP aboveThis = active;
1546 
1547     juggler->addNode(nodes1, parent, aboveThis);
1548     juggler->moveNode(nodes2, group, 0);
1549 
1550     *newGroup = group;
1551     *newLastChild = nodes2.last();
1552 
1553     return true;
1554 }
1555 
createQuickGroup()1556 void KisNodeManager::createQuickGroup()
1557 {
1558     KUndo2MagicString actionName = kundo2_i18n("Quick Group");
1559     KisNodeJugglerCompressed *juggler = m_d->lazyGetJuggler(actionName);
1560 
1561     KisNodeSP parent;
1562     KisNodeSP above;
1563 
1564     createQuickGroupImpl(juggler, "", &parent, &above);
1565 }
1566 
createQuickClippingGroup()1567 void KisNodeManager::createQuickClippingGroup()
1568 {
1569     KUndo2MagicString actionName = kundo2_i18n("Quick Clipping Group");
1570     KisNodeJugglerCompressed *juggler = m_d->lazyGetJuggler(actionName);
1571 
1572     KisNodeSP parent;
1573     KisNodeSP above;
1574 
1575     KisImageSP image = m_d->view->image();
1576     if (createQuickGroupImpl(juggler, image->nextLayerName(i18nc("default name for a clipping group layer", "Clipping Group")), &parent, &above)) {
1577         KisPaintLayerSP maskLayer = new KisPaintLayer(image.data(), i18nc("default name for quick clip group mask layer", "Mask Layer"), OPACITY_OPAQUE_U8, image->colorSpace());
1578         maskLayer->disableAlphaChannel(true);
1579 
1580         juggler->addNode(KisNodeList() << maskLayer, parent, above);
1581     }
1582 }
1583 
quickUngroup()1584 void KisNodeManager::quickUngroup()
1585 {
1586     KisNodeSP active = activeNode();
1587     if (!active) return;
1588 
1589     if (!canModifyLayer(active)) return;
1590 
1591     KisNodeSP parent = active->parent();
1592     KisNodeSP aboveThis = active;
1593 
1594     KUndo2MagicString actionName = kundo2_i18n("Quick Ungroup");
1595 
1596     if (parent && dynamic_cast<KisGroupLayer*>(active.data())) {
1597         KisNodeList nodes = active->childNodes(QStringList(), KoProperties());
1598 
1599         KisNodeJugglerCompressed *juggler = m_d->lazyGetJuggler(actionName);
1600         juggler->moveNode(nodes, parent, active);
1601         juggler->removeNode(KisNodeList() << active);
1602     } else if (parent && parent->parent()) {
1603         KisNodeSP grandParent = parent->parent();
1604 
1605         KisNodeList allChildNodes = parent->childNodes(QStringList(), KoProperties());
1606         KisNodeList allSelectedNodes = selectedNodes();
1607 
1608         const bool removeParent = KritaUtils::compareListsUnordered(allChildNodes, allSelectedNodes);
1609 
1610         KisNodeJugglerCompressed *juggler = m_d->lazyGetJuggler(actionName);
1611         juggler->moveNode(allSelectedNodes, grandParent, parent);
1612         if (removeParent) {
1613             juggler->removeNode(KisNodeList() << parent);
1614         }
1615     }
1616 }
1617 
selectLayersImpl(const KoProperties & props,const KoProperties & invertedProps)1618 void KisNodeManager::selectLayersImpl(const KoProperties &props, const KoProperties &invertedProps)
1619 {
1620     KisImageSP image = m_d->view->image();
1621     KisNodeList nodes = KisLayerUtils::findNodesWithProps(image->root(), props, true);
1622 
1623     KisNodeList selectedNodes = this->selectedNodes();
1624 
1625     if (KritaUtils::compareListsUnordered(nodes, selectedNodes)) {
1626         nodes = KisLayerUtils::findNodesWithProps(image->root(), invertedProps, true);
1627     }
1628 
1629     if (!nodes.isEmpty()) {
1630         slotImageRequestNodeReselection(nodes.last(), nodes);
1631     }
1632 }
1633 
selectAllNodes()1634 void KisNodeManager::selectAllNodes()
1635 {
1636     KoProperties props;
1637     selectLayersImpl(props, props);
1638 }
1639 
selectVisibleNodes()1640 void KisNodeManager::selectVisibleNodes()
1641 {
1642     KoProperties props;
1643     props.setProperty("visible", true);
1644 
1645     KoProperties invertedProps;
1646     invertedProps.setProperty("visible", false);
1647 
1648     selectLayersImpl(props, invertedProps);
1649 }
1650 
selectLockedNodes()1651 void KisNodeManager::selectLockedNodes()
1652 {
1653     KoProperties props;
1654     props.setProperty("locked", true);
1655 
1656     KoProperties invertedProps;
1657     invertedProps.setProperty("locked", false);
1658 
1659     selectLayersImpl(props, invertedProps);
1660 }
1661 
selectInvisibleNodes()1662 void KisNodeManager::selectInvisibleNodes()
1663 {
1664     KoProperties props;
1665     props.setProperty("visible", false);
1666 
1667     KoProperties invertedProps;
1668     invertedProps.setProperty("visible", true);
1669 
1670     selectLayersImpl(props, invertedProps);
1671 }
1672 
selectUnlockedNodes()1673 void KisNodeManager::selectUnlockedNodes()
1674 {
1675     KoProperties props;
1676     props.setProperty("locked", false);
1677 
1678     KoProperties invertedProps;
1679     invertedProps.setProperty("locked", true);
1680 
1681     selectLayersImpl(props, invertedProps);
1682 }
1683