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