1 /*
2  *  Copyright (C) 2006 Boudewijn Rempt <boud@valdyas.org>
3  *  Copyright (c) 2020 L. E. Segovia <amy@amyspark.me>
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 #include "kis_layer_manager.h"
21 
22 #include <QRect>
23 #include <QApplication>
24 #include <QCursor>
25 #include <QString>
26 #include <QDialog>
27 #include <QVBoxLayout>
28 #include <QFileInfo>
29 #include <QStandardPaths>
30 
31 #include <kactioncollection.h>
32 #include <klocalizedstring.h>
33 #include <QMessageBox>
34 #include <QUrl>
35 
36 #include <kis_file_name_requester.h>
37 #include <kis_icon.h>
38 #include <KisImportExportManager.h>
39 #include <KisDocument.h>
40 #include <KoColorSpace.h>
41 #include <KoCompositeOpRegistry.h>
42 #include <KoPointerEvent.h>
43 #include <KoColorProfile.h>
44 #include <KoSelection.h>
45 #include <KisPart.h>
46 #include <KisMainWindow.h>
47 
48 #include <filter/kis_filter_configuration.h>
49 #include <filter/kis_filter.h>
50 #include <kis_filter_strategy.h>
51 #include <generator/kis_generator_layer.h>
52 #include <kis_file_layer.h>
53 #include <kis_adjustment_layer.h>
54 #include <kis_mask.h>
55 #include <kis_clone_layer.h>
56 #include <kis_group_layer.h>
57 #include <kis_image.h>
58 #include <kis_layer.h>
59 #include <kis_paint_device.h>
60 #include <kis_selection.h>
61 #include <flake/kis_shape_layer.h>
62 #include <kis_undo_adapter.h>
63 #include <kis_painter.h>
64 #include <kis_meta_data_store.h>
65 #include <kis_meta_data_merge_strategy_registry.h>
66 #include <kis_psd_layer_style.h>
67 #include <KisMimeDatabase.h>
68 
69 #include "kis_config.h"
70 #include "kis_cursor.h"
71 #include "dialogs/kis_dlg_adj_layer_props.h"
72 #include "dialogs/kis_dlg_adjustment_layer.h"
73 #include "dialogs/kis_dlg_layer_properties.h"
74 #include "dialogs/kis_dlg_generator_layer.h"
75 #include "dialogs/kis_dlg_file_layer.h"
76 #include "dialogs/kis_dlg_layer_style.h"
77 #include "dialogs/KisDlgChangeCloneSource.h"
78 #include "kis_filter_manager.h"
79 #include "kis_node_visitor.h"
80 #include "kis_paint_layer.h"
81 #include "commands/kis_image_commands.h"
82 #include "commands/kis_node_commands.h"
83 #include "kis_change_file_layer_command.h"
84 #include "kis_canvas_resource_provider.h"
85 #include "kis_selection_manager.h"
86 #include "kis_statusbar.h"
87 #include "KisViewManager.h"
88 #include "kis_zoom_manager.h"
89 #include "canvas/kis_canvas2.h"
90 #include "widgets/kis_meta_data_merge_strategy_chooser_widget.h"
91 #include "widgets/kis_wdg_generator.h"
92 #include "kis_progress_widget.h"
93 #include "kis_node_commands_adapter.h"
94 #include "kis_node_manager.h"
95 #include "kis_action.h"
96 #include "kis_action_manager.h"
97 #include "kis_raster_keyframe_channel.h"
98 #include "kis_signal_compressor_with_param.h"
99 #include "kis_abstract_projection_plane.h"
100 #include "commands_new/kis_set_layer_style_command.h"
101 #include "kis_post_execution_undo_adapter.h"
102 #include "kis_selection_mask.h"
103 #include "kis_layer_utils.h"
104 #include "lazybrush/kis_colorize_mask.h"
105 #include "kis_processing_applicator.h"
106 #include "kis_projection_leaf.h"
107 
108 #include "KisSaveGroupVisitor.h"
109 
KisLayerManager(KisViewManager * view)110 KisLayerManager::KisLayerManager(KisViewManager * view)
111     : m_view(view)
112     , m_commandsAdapter(new KisNodeCommandsAdapter(m_view))
113 
114 {
115 }
116 
~KisLayerManager()117 KisLayerManager::~KisLayerManager()
118 {
119     delete m_commandsAdapter;
120 }
121 
setView(QPointer<KisView> view)122 void KisLayerManager::setView(QPointer<KisView>view)
123 {
124     m_imageView = view;
125 }
126 
activeLayer()127 KisLayerSP KisLayerManager::activeLayer()
128 {
129     if (m_imageView) {
130         return m_imageView->currentLayer();
131     }
132     return 0;
133 }
134 
activeDevice()135 KisPaintDeviceSP KisLayerManager::activeDevice()
136 {
137     if (activeLayer()) {
138         return activeLayer()->paintDevice();
139     }
140     return 0;
141 }
142 
activateLayer(KisLayerSP layer)143 void KisLayerManager::activateLayer(KisLayerSP layer)
144 {
145     if (m_imageView) {
146         layersUpdated();
147         if (layer) {
148             m_view->canvasResourceProvider()->slotNodeActivated(layer.data());
149         }
150     }
151 }
152 
153 
setup(KisActionManager * actionManager)154 void KisLayerManager::setup(KisActionManager* actionManager)
155 {
156     m_imageFlatten = actionManager->createAction("flatten_image");
157     connect(m_imageFlatten, SIGNAL(triggered()), this, SLOT(flattenImage()));
158 
159     m_imageMergeLayer = actionManager->createAction("merge_layer");
160     connect(m_imageMergeLayer, SIGNAL(triggered()), this, SLOT(mergeLayer()));
161 
162     m_flattenLayer = actionManager->createAction("flatten_layer");
163     connect(m_flattenLayer, SIGNAL(triggered()), this, SLOT(flattenLayer()));
164 
165     m_rasterizeLayer = actionManager->createAction("rasterize_layer");
166     connect(m_rasterizeLayer, SIGNAL(triggered()), this, SLOT(rasterizeLayer()));
167 
168     m_groupLayersSave = actionManager->createAction("save_groups_as_images");
169     connect(m_groupLayersSave, SIGNAL(triggered()), this, SLOT(saveGroupLayers()));
170 
171     m_convertGroupAnimated = actionManager->createAction("convert_group_to_animated");
172     connect(m_convertGroupAnimated, SIGNAL(triggered()), this, SLOT(convertGroupToAnimated()));
173 
174     m_imageResizeToLayer = actionManager->createAction("resizeimagetolayer");
175     connect(m_imageResizeToLayer, SIGNAL(triggered()), this, SLOT(imageResizeToActiveLayer()));
176 
177     KisAction *action = actionManager->createAction("trim_to_image");
178     connect(action, SIGNAL(triggered()), this, SLOT(trimToImage()));
179 
180     m_layerStyle  = actionManager->createAction("layer_style");
181     connect(m_layerStyle, SIGNAL(triggered()), this, SLOT(layerStyle()));
182 
183 }
184 
updateGUI()185 void KisLayerManager::updateGUI()
186 {
187     KisImageSP image = m_view->image();
188     KisLayerSP layer = activeLayer();
189 
190     const bool isGroupLayer = layer && layer->inherits("KisGroupLayer");
191 
192     m_imageMergeLayer->setText(
193                 isGroupLayer ?
194                     i18nc("@action:inmenu", "Merge Group") :
195                     i18nc("@action:inmenu", "Merge with Layer Below"));
196     m_flattenLayer->setVisible(!isGroupLayer);
197 
198     if (m_view->statusBar())
199         m_view->statusBar()->setProfile(image);
200 }
201 
imageResizeToActiveLayer()202 void KisLayerManager::imageResizeToActiveLayer()
203 {
204     KisLayerSP layer;
205     KisImageWSP image = m_view->image();
206 
207     if (image && (layer = activeLayer())) {
208         QRect cropRect = layer->projection()->nonDefaultPixelArea();
209         if (!cropRect.isEmpty()) {
210             image->cropImage(cropRect);
211         } else {
212             m_view->showFloatingMessage(
213                         i18nc("floating message in layer manager",
214                               "Layer is empty "),
215                         QIcon(), 2000, KisFloatingMessage::Low);
216         }
217     }
218 }
219 
trimToImage()220 void KisLayerManager::trimToImage()
221 {
222     KisImageWSP image = m_view->image();
223     if (image) {
224         image->cropImage(image->bounds());
225     }
226 }
227 
layerProperties()228 void KisLayerManager::layerProperties()
229 {
230     if (!m_view) return;
231     if (!m_view->document()) return;
232 
233     KisLayerSP layer = activeLayer();
234     if (!layer) return;
235 
236     QList<KisNodeSP> selectedNodes = m_view->nodeManager()->selectedNodes();
237     const bool multipleLayersSelected = selectedNodes.size() > 1;
238 
239     if (!m_view->nodeManager()->canModifyLayers(selectedNodes)) return;
240 
241     KisAdjustmentLayerSP adjustmentLayer = KisAdjustmentLayerSP(dynamic_cast<KisAdjustmentLayer*>(layer.data()));
242     KisGeneratorLayerSP generatorLayer = KisGeneratorLayerSP(dynamic_cast<KisGeneratorLayer*>(layer.data()));
243     KisFileLayerSP fileLayer = KisFileLayerSP(dynamic_cast<KisFileLayer*>(layer.data()));
244 
245     if (adjustmentLayer && !multipleLayersSelected) {
246 
247         KisPaintDeviceSP dev = adjustmentLayer->projection();
248 
249         KisDlgAdjLayerProps dlg(adjustmentLayer, adjustmentLayer.data(), dev, m_view, adjustmentLayer->filter().data(), adjustmentLayer->name(), i18n("Filter Layer Properties"), m_view->mainWindow(), "dlgadjlayerprops");
250         dlg.resize(dlg.minimumSizeHint());
251 
252 
253         KisFilterConfigurationSP configBefore(adjustmentLayer->filter());
254         KIS_ASSERT_RECOVER_RETURN(configBefore);
255         QString xmlBefore = configBefore->toXML();
256 
257 
258         if (dlg.exec() == QDialog::Accepted) {
259 
260             adjustmentLayer->setName(dlg.layerName());
261 
262             KisFilterConfigurationSP configAfter(dlg.filterConfiguration());
263             Q_ASSERT(configAfter);
264             QString xmlAfter = configAfter->toXML();
265 
266             if(xmlBefore != xmlAfter) {
267                 KisChangeFilterCmd *cmd
268                         = new KisChangeFilterCmd(adjustmentLayer,
269                                                  configBefore->name(),
270                                                  xmlBefore,
271                                                  configAfter->name(),
272                                                  xmlAfter,
273                                                  false);
274                 // FIXME: check whether is needed
275                 cmd->redo();
276                 m_view->undoAdapter()->addCommand(cmd);
277                 m_view->document()->setModified(true);
278             }
279         }
280         else {
281             KisFilterConfigurationSP configAfter(dlg.filterConfiguration());
282             Q_ASSERT(configAfter);
283             QString xmlAfter = configAfter->toXML();
284 
285             if(xmlBefore != xmlAfter) {
286                 adjustmentLayer->setFilter(KisFilterRegistry::instance()->cloneConfiguration(configBefore.data()));
287                 adjustmentLayer->setDirty();
288             }
289         }
290     }
291     else if (generatorLayer && !multipleLayersSelected) {
292         KisFilterConfigurationSP configBefore(generatorLayer->filter());
293         Q_ASSERT(configBefore);
294         QString xmlBefore = configBefore->toXML();
295 
296         KisDlgGeneratorLayer *dlg = new KisDlgGeneratorLayer(generatorLayer->name(), m_view, m_view->mainWindow(), generatorLayer, configBefore, KisStrokeId());
297         dlg->setWindowTitle(i18n("Fill Layer Properties"));
298         dlg->setAttribute(Qt::WA_DeleteOnClose);
299 
300         dlg->setConfiguration(configBefore.data());
301 
302         Qt::WindowFlags flags = dlg->windowFlags();
303         dlg->setWindowFlags(flags | Qt::Tool | Qt::Dialog);
304         dlg->show();
305 
306     }
307     else if (fileLayer && !multipleLayersSelected){
308         QString basePath = QFileInfo(m_view->document()->url().toLocalFile()).absolutePath();
309         QString fileNameOld = fileLayer->fileName();
310         KisFileLayer::ScalingMethod scalingMethodOld = fileLayer->scalingMethod();
311         KisDlgFileLayer dlg(basePath, fileLayer->name(), m_view->mainWindow());
312         dlg.setCaption(i18n("File Layer Properties"));
313         dlg.setFileName(fileNameOld);
314         dlg.setScalingMethod(scalingMethodOld);
315 
316         if (dlg.exec() == QDialog::Accepted) {
317             const QString fileNameNew = dlg.fileName();
318             KisFileLayer::ScalingMethod scalingMethodNew = dlg.scaleToImageResolution();
319 
320             if(fileNameNew.isEmpty()){
321                 QMessageBox::critical(m_view->mainWindow(), i18nc("@title:window", "Krita"), i18n("No file name specified"));
322                 return;
323             }
324             fileLayer->setName(dlg.layerName());
325 
326             if (fileNameOld!= fileNameNew || scalingMethodOld != scalingMethodNew) {
327                 KisChangeFileLayerCmd *cmd
328                         = new KisChangeFileLayerCmd(fileLayer,
329                                                     basePath,
330                                                     fileNameOld,
331                                                     scalingMethodOld,
332                                                     basePath,
333                                                     fileNameNew,
334                                                     scalingMethodNew);
335                 m_view->undoAdapter()->addCommand(cmd);
336             }
337         }
338     } else { // If layer == normal painting layer, vector layer, or group layer
339         QList<KisNodeSP> selectedNodes = m_view->nodeManager()->selectedNodes();
340 
341         KisDlgLayerProperties *dialog = new KisDlgLayerProperties(selectedNodes, m_view);
342         dialog->resize(dialog->minimumSizeHint());
343         dialog->setAttribute(Qt::WA_DeleteOnClose);
344         Qt::WindowFlags flags = dialog->windowFlags();
345 #ifdef Q_OS_ANDROID
346         // a Qt::Tool window seems incapable of receiving keyboard focus
347         dialog->setWindowFlags(flags | Qt::Dialog);
348 #else
349         dialog->setWindowFlags(flags | Qt::Tool | Qt::Dialog);
350 #endif
351         dialog->show();
352 
353     }
354 }
355 
changeCloneSource()356 void KisLayerManager::changeCloneSource()
357 {
358     QList<KisNodeSP> selectedNodes = m_view->nodeManager()->selectedNodes();
359     if (selectedNodes.isEmpty()) {
360         return;
361     }
362 
363     QList<KisCloneLayerSP> cloneLayers;
364     KisNodeSP node;
365     Q_FOREACH (node, selectedNodes) {
366         KisCloneLayerSP cloneLayer(qobject_cast<KisCloneLayer *>(node.data()));
367         if (cloneLayer) {
368             cloneLayers << cloneLayer;
369         }
370     }
371 
372     if (cloneLayers.isEmpty()) {
373         return;
374     }
375 
376     if (!m_view->nodeManager()->canModifyLayers(implicitCastList<KisNodeSP>(cloneLayers))) return;
377 
378     KisDlgChangeCloneSource *dialog = new KisDlgChangeCloneSource(cloneLayers, m_view);
379     dialog->setCaption(i18n("Change Clone Layer"));
380     dialog->resize(dialog->minimumSizeHint());
381     dialog->setAttribute(Qt::WA_DeleteOnClose);
382     Qt::WindowFlags flags = dialog->windowFlags();
383     dialog->setWindowFlags(flags | Qt::Tool | Qt::Dialog);
384     dialog->show();
385 }
386 
convertNodeToPaintLayer(KisNodeSP source)387 void KisLayerManager::convertNodeToPaintLayer(KisNodeSP source)
388 {
389     KisImageWSP image = m_view->image();
390     if (!image) return;
391 
392     // this precondition must be checked at higher level
393     KIS_SAFE_ASSERT_RECOVER_RETURN(source->isEditable(false));
394 
395     KisLayer *srcLayer = qobject_cast<KisLayer*>(source.data());
396     if (srcLayer && (srcLayer->inherits("KisGroupLayer") || srcLayer->layerStyle() || srcLayer->childCount() > 0)) {
397         image->flattenLayer(srcLayer);
398         return;
399     }
400 
401     KisPaintDeviceSP srcDevice =
402             source->paintDevice() ? source->projection() : source->original();
403 
404     bool putBehind = false;
405 
406     QString newCompositeOp =
407         source->projectionLeaf()->isLayer() ?
408             source->compositeOpId() : COMPOSITE_OVER;
409 
410     KisColorizeMask *colorizeMask = dynamic_cast<KisColorizeMask*>(source.data());
411     if (colorizeMask) {
412         srcDevice = colorizeMask->coloringProjection();
413         putBehind = colorizeMask->compositeOpId() == COMPOSITE_BEHIND;
414         if (putBehind) {
415             newCompositeOp = COMPOSITE_OVER;
416         }
417     }
418 
419     if (!srcDevice) return;
420 
421     KisPaintDeviceSP clone;
422 
423     if (*srcDevice->colorSpace() !=
424             *srcDevice->compositionSourceColorSpace()) {
425 
426         clone = new KisPaintDevice(srcDevice->compositionSourceColorSpace());
427         clone->setDefaultPixel(
428             srcDevice->defaultPixel().convertedTo(
429                 srcDevice->compositionSourceColorSpace()));
430 
431         QRect rc(srcDevice->extent());
432         KisPainter::copyAreaOptimized(rc.topLeft(), srcDevice, clone, rc);
433     } else {
434         clone = new KisPaintDevice(*srcDevice);
435     }
436 
437     KisLayerSP layer = new KisPaintLayer(image,
438                                          source->name(),
439                                          source->opacity(),
440                                          clone);
441 
442     if (srcDevice->framesInterface()) {
443         KisKeyframeChannel *cloneKeyChannel = layer->getKeyframeChannel(KisKeyframeChannel::Content.id(), true);
444         layer->enableAnimation();
445         KisKeyframeChannel *sourceKeyChannel = srcDevice->keyframeChannel();
446 
447         foreach (const int &index, sourceKeyChannel->allKeyframeIds()) {
448             cloneKeyChannel->copyExternalKeyframe(sourceKeyChannel, index, index);
449         }
450     }
451 
452     layer->setCompositeOpId(newCompositeOp);
453 
454     KisNodeSP parent = source->parent();
455     KisNodeSP above = source->prevSibling();
456 
457     while (parent && !parent->allowAsChild(layer)) {
458         above = above ? above->parent() : source->parent();
459         parent = above ? above->parent() : 0;
460     }
461 
462     if (putBehind && above == source->parent()) {
463         above = above->prevSibling();
464     }
465 
466     m_commandsAdapter->beginMacro(kundo2_i18n("Convert to a Paint Layer"));
467     m_commandsAdapter->removeNode(source);
468     m_commandsAdapter->addNode(layer, parent, above);
469     m_commandsAdapter->endMacro();
470 }
471 
convertGroupToAnimated()472 void KisLayerManager::convertGroupToAnimated()
473 {
474     KisGroupLayerSP group = dynamic_cast<KisGroupLayer*>(activeLayer().data());
475     if (group.isNull()) return;
476 
477     if (!m_view->nodeManager()->canModifyLayer(group)) return;
478 
479     KisPaintLayerSP animatedLayer = new KisPaintLayer(m_view->image(), group->name(), OPACITY_OPAQUE_U8);
480     animatedLayer->enableAnimation();
481     KisRasterKeyframeChannel *contentChannel = dynamic_cast<KisRasterKeyframeChannel*>(
482                 animatedLayer->getKeyframeChannel(KisKeyframeChannel::Content.id(), true));
483     KIS_ASSERT_RECOVER_RETURN(contentChannel);
484 
485     KisNodeSP child = group->firstChild();
486     int time = 0;
487     while (child) {
488         contentChannel->importFrame(time, child->projection(), NULL);
489         time++;
490 
491         child = child->nextSibling();
492     }
493 
494     m_commandsAdapter->beginMacro(kundo2_i18n("Convert to an animated layer"));
495     m_commandsAdapter->addNode(animatedLayer, group->parent(), group);
496     m_commandsAdapter->removeNode(group);
497     m_commandsAdapter->endMacro();
498 }
499 
convertLayerToFileLayer(KisNodeSP source)500 void KisLayerManager::convertLayerToFileLayer(KisNodeSP source)
501 {
502     KisImageSP image = m_view->image();
503     if (!image) return;
504 
505     // this precondition must be checked at higher level
506     KIS_SAFE_ASSERT_RECOVER_RETURN(source->isEditable(false));
507 
508     QStringList listMimeFilter = KisImportExportManager::supportedMimeTypes(KisImportExportManager::Export);
509 
510     KoDialog dlg;
511     QWidget *page = new QWidget(&dlg);
512     dlg.setMainWidget(page);
513     QBoxLayout *layout = new QVBoxLayout(page);
514     dlg.setWindowTitle(i18n("Save layers to..."));
515     QLabel *lbl = new QLabel(i18n("Choose the location where the layer will be saved to. The new file layer will then reference this location."));
516     lbl->setWordWrap(true);
517     layout->addWidget(lbl);
518     KisFileNameRequester *urlRequester = new KisFileNameRequester(page);
519     urlRequester->setMode(KoFileDialog::SaveFile);
520     urlRequester->setMimeTypeFilters(listMimeFilter);
521     urlRequester->setFileName(m_view->document()->url().toLocalFile());
522     if (m_view->document()->url().isLocalFile()) {
523         QFileInfo location = QFileInfo(m_view->document()->url().toLocalFile()).completeBaseName();
524         location.setFile(location.dir(), location.completeBaseName() + "_" + source->name() + ".png");
525         urlRequester->setFileName(location.absoluteFilePath());
526     }
527     else {
528         const QFileInfo location = QFileInfo(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
529         const QString proposedFileName = QDir(location.absoluteFilePath()).absoluteFilePath(source->name() + ".png");
530         urlRequester->setFileName(proposedFileName);
531     }
532 
533     layout->addWidget(urlRequester);
534     if (!dlg.exec()) return;
535 
536     QString path = urlRequester->fileName();
537 
538     if (path.isEmpty()) return;
539 
540     QFileInfo f(path);
541 
542     QString mimeType= KisMimeDatabase::mimeTypeForFile(f.fileName());
543     if (mimeType.isEmpty()) {
544         mimeType = "image/png";
545     }
546     QScopedPointer<KisDocument> doc(KisPart::instance()->createDocument());
547 
548     QRect bounds = source->exactBounds();
549     if (bounds.isEmpty()) {
550         bounds = image->bounds();
551     }
552     KisImageSP dst = new KisImage(doc->createUndoStore(),
553                                   image->width(),
554                                   image->height(),
555                                   image->projection()->compositionSourceColorSpace(),
556                                   source->name());
557     dst->setResolution(image->xRes(), image->yRes());
558     doc->setFileBatchMode(false);
559     doc->setCurrentImage(dst);
560     KisNodeSP node = source->clone();
561     dst->addNode(node);
562     dst->initialRefreshGraph();
563     dst->cropImage(bounds);
564     dst->waitForDone();
565 
566     bool r = doc->exportDocumentSync(QUrl::fromLocalFile(path), mimeType.toLatin1());
567     if (!r) {
568 
569         qWarning() << "Converting layer to file layer. path:"<< path << "gave errors" << doc->errorMessage();
570     } else {
571         QString basePath = QFileInfo(m_view->document()->url().toLocalFile()).absolutePath();
572         QString relativePath = QDir(basePath).relativeFilePath(path);
573         KisFileLayer *fileLayer = new KisFileLayer(image, basePath, relativePath, KisFileLayer::None, source->name(), OPACITY_OPAQUE_U8);
574         fileLayer->setX(bounds.x());
575         fileLayer->setY(bounds.y());
576         KisNodeSP dstParent = source->parent();
577         KisNodeSP dstAboveThis = source->prevSibling();
578         m_commandsAdapter->beginMacro(kundo2_i18n("Convert to a file layer"));
579         m_commandsAdapter->removeNode(source);
580         m_commandsAdapter->addNode(fileLayer, dstParent, dstAboveThis);
581         m_commandsAdapter->endMacro();
582     }
583     doc->closeUrl(false);
584 }
585 
adjustLayerPosition(KisNodeSP node,KisNodeSP activeNode,KisNodeSP & parent,KisNodeSP & above)586 void KisLayerManager::adjustLayerPosition(KisNodeSP node, KisNodeSP activeNode, KisNodeSP &parent, KisNodeSP &above)
587 {
588     Q_ASSERT(activeNode);
589 
590     parent = activeNode;
591     above = parent->lastChild();
592 
593     if (parent->inherits("KisGroupLayer") && parent->collapsed()) {
594         above = parent;
595         parent = parent->parent();
596         return;
597     }
598 
599     while (parent &&
600            (!parent->allowAsChild(node) || !parent->isEditable(false))) {
601 
602         above = parent;
603         parent = parent->parent();
604     }
605 
606     if (!parent) {
607         warnKrita << "KisLayerManager::adjustLayerPosition:"
608                   << "No node accepted newly created node";
609 
610         parent = m_view->image()->root();
611         above = parent->lastChild();
612     }
613 }
614 
addLayerCommon(KisNodeSP activeNode,KisNodeSP layer,bool updateImage,KisProcessingApplicator * applicator)615 void KisLayerManager::addLayerCommon(KisNodeSP activeNode, KisNodeSP layer, bool updateImage, KisProcessingApplicator *applicator)
616 {
617     KisNodeSP parent;
618     KisNodeSP above;
619     adjustLayerPosition(layer, activeNode, parent, above);
620 
621     KisGroupLayer *group = dynamic_cast<KisGroupLayer*>(parent.data());
622     const bool parentForceUpdate = group && !group->projectionIsValid();
623     updateImage |= parentForceUpdate;
624 
625     m_commandsAdapter->addNodeAsync(layer, parent, above, updateImage, updateImage, applicator);
626 }
627 
addPaintLayer(KisNodeSP activeNode)628 KisLayerSP KisLayerManager::addPaintLayer(KisNodeSP activeNode)
629 {
630     KisImageWSP image = m_view->image();
631     KisLayerSP layer = new KisPaintLayer(image.data(),  image->nextLayerName( i18n("Paint Layer") ), OPACITY_OPAQUE_U8, image->colorSpace());
632 
633     addLayerCommon(activeNode, layer, false, 0);
634 
635     return layer;
636 }
637 
addGroupLayer(KisNodeSP activeNode)638 KisNodeSP KisLayerManager::addGroupLayer(KisNodeSP activeNode)
639 {
640     KisImageWSP image = m_view->image();
641     KisGroupLayerSP group = new KisGroupLayer(image.data(), image->nextLayerName( i18n("Group") ), OPACITY_OPAQUE_U8);
642     addLayerCommon(activeNode, group, false, 0);
643     return group;
644 }
645 
addCloneLayer(KisNodeList nodes)646 KisNodeSP KisLayerManager::addCloneLayer(KisNodeList nodes)
647 {
648     KisImageWSP image = m_view->image();
649 
650     KisNodeList filteredNodes = KisLayerUtils::sortAndFilterMergableInternalNodes(nodes, false);
651     if (filteredNodes.isEmpty()) return KisNodeSP();
652 
653     KisNodeSP newAbove = filteredNodes.last();
654 
655     KisNodeSP node, lastClonedNode;
656     Q_FOREACH (node, filteredNodes) {
657         lastClonedNode = new KisCloneLayer(qobject_cast<KisLayer*>(node.data()), image.data(), image->nextLayerName( i18n("Clone Layer") ), OPACITY_OPAQUE_U8);
658         addLayerCommon(newAbove, lastClonedNode, true, 0 );
659     }
660 
661     return lastClonedNode;
662 }
663 
addShapeLayer(KisNodeSP activeNode)664 KisNodeSP KisLayerManager::addShapeLayer(KisNodeSP activeNode)
665 {
666     if (!m_view) return 0;
667     if (!m_view->document()) return 0;
668 
669     KisImageWSP image = m_view->image();
670     KisShapeLayerSP layer = new KisShapeLayer(m_view->document()->shapeController(), image.data(), image->nextLayerName(i18n("Vector Layer")), OPACITY_OPAQUE_U8);
671 
672     addLayerCommon(activeNode, layer, false, 0);
673 
674     return layer;
675 }
676 
addAdjustmentLayer(KisNodeSP activeNode)677 KisNodeSP KisLayerManager::addAdjustmentLayer(KisNodeSP activeNode)
678 {
679     KisImageWSP image = m_view->image();
680 
681     KisSelectionSP selection = m_view->selection();
682 
683     KisProcessingApplicator applicator(image, 0, KisProcessingApplicator::NONE,
684                                        KisImageSignalVector() << ModifiedSignal,
685                                        kundo2_i18n("Add Layer"));
686 
687 
688     KisAdjustmentLayerSP adjl = addAdjustmentLayer(activeNode, QString(), 0, selection, &applicator);
689 
690     KisPaintDeviceSP previewDevice = new KisPaintDevice(*adjl->original());
691 
692     KisDlgAdjustmentLayer dlg(adjl, adjl.data(), previewDevice, image->nextLayerName(i18n("Filter Layer")), i18n("New Filter Layer"), m_view, qApp->activeWindow());
693     dlg.resize(dlg.minimumSizeHint());
694 
695     // ensure that the device may be free'd by the dialog
696     // when it is not needed anymore
697     previewDevice = 0;
698 
699     if (dlg.exec() != QDialog::Accepted || adjl->filter().isNull()) {
700         // XXX: add messagebox warning if there's no filter set!
701         applicator.cancel();
702     } else {
703         adjl->setName(dlg.layerName());
704         applicator.end();
705     }
706 
707     return adjl;
708 }
709 
addAdjustmentLayer(KisNodeSP activeNode,const QString & name,KisFilterConfigurationSP filter,KisSelectionSP selection,KisProcessingApplicator * applicator)710 KisAdjustmentLayerSP KisLayerManager::addAdjustmentLayer(KisNodeSP activeNode, const QString & name,
711                                                          KisFilterConfigurationSP  filter,
712                                                          KisSelectionSP selection,
713                                                          KisProcessingApplicator *applicator)
714 {
715     KisImageWSP image = m_view->image();
716     KisAdjustmentLayerSP layer = new KisAdjustmentLayer(image, name, filter, selection);
717     addLayerCommon(activeNode, layer, true, applicator);
718 
719     return layer;
720 }
721 
addGeneratorLayer(KisNodeSP activeNode,const QString & name,KisFilterConfigurationSP filter,KisSelectionSP selection,KisProcessingApplicator * applicator)722 KisGeneratorLayerSP KisLayerManager::addGeneratorLayer(KisNodeSP activeNode, const QString &name, KisFilterConfigurationSP filter, KisSelectionSP selection, KisProcessingApplicator *applicator)
723 {
724     KisImageWSP image = m_view->image();
725     auto layer = new KisGeneratorLayer(image, name, filter, selection);
726     addLayerCommon(activeNode, layer, true, applicator);
727 
728     return layer;
729 }
730 
addGeneratorLayer(KisNodeSP activeNode)731 KisNodeSP KisLayerManager::addGeneratorLayer(KisNodeSP activeNode)
732 {
733     KisImageWSP image = m_view->image();
734     KisSelectionSP selection = m_view->selection();
735     QColor currentForeground = m_view->canvasResourceProvider()->fgColor().toQColor();
736 
737     KisProcessingApplicator applicator(image, 0, KisProcessingApplicator::NONE, KisImageSignalVector() << ModifiedSignal, kundo2_i18n("Add Layer"));
738 
739     KisGeneratorLayerSP node = addGeneratorLayer(activeNode, QString(), nullptr, selection, &applicator);
740 
741     KisDlgGeneratorLayer dlg(image->nextLayerName(i18n("Fill Layer")), m_view, m_view->mainWindow(), node, nullptr, applicator.getStroke());
742     KisFilterConfigurationSP defaultConfig = dlg.configuration();
743     defaultConfig->setProperty("color", currentForeground);
744     dlg.setConfiguration(defaultConfig);
745 
746     if (dlg.exec() == QDialog::Accepted) {
747         node->setName(dlg.layerName());
748         applicator.end();
749         return node;
750     }
751     else {
752         applicator.cancel();
753         return nullptr;
754     }
755 }
756 
flattenImage()757 void KisLayerManager::flattenImage()
758 {
759     KisImageSP image = m_view->image();
760 
761     if (!m_view->blockUntilOperationsFinished(image)) return;
762 
763     if (image) {
764         bool doIt = true;
765 
766         if (image->nHiddenLayers() > 0) {
767             int answer = QMessageBox::warning(m_view->mainWindow(),
768                                               i18nc("@title:window", "Flatten Image"),
769                                               i18n("The image contains hidden layers that will be lost. Do you want to flatten the image?"),
770                                               QMessageBox::Yes | QMessageBox::No,
771                                               QMessageBox::No);
772 
773             if (answer != QMessageBox::Yes) {
774                 doIt = false;
775             }
776         }
777 
778         if (doIt) {
779             image->flatten(m_view->activeNode());
780         }
781     }
782 }
783 
isSelectionMask(KisNodeSP node)784 inline bool isSelectionMask(KisNodeSP node) {
785     return dynamic_cast<KisSelectionMask*>(node.data());
786 }
787 
tryMergeSelectionMasks(KisNodeSP currentNode,KisImageSP image)788 bool tryMergeSelectionMasks(KisNodeSP currentNode, KisImageSP image)
789 {
790     bool result = false;
791 
792     KisNodeSP prevNode = currentNode->prevSibling();
793     if (isSelectionMask(currentNode) &&
794             prevNode && isSelectionMask(prevNode)) {
795 
796         QList<KisNodeSP> mergedNodes;
797         mergedNodes.append(currentNode);
798         mergedNodes.append(prevNode);
799 
800         image->mergeMultipleLayers(mergedNodes, currentNode);
801 
802         result = true;
803     }
804 
805     return result;
806 }
807 
tryFlattenGroupLayer(KisNodeSP currentNode,KisImageSP image)808 bool tryFlattenGroupLayer(KisNodeSP currentNode, KisImageSP image)
809 {
810     bool result = false;
811 
812     if (currentNode->inherits("KisGroupLayer")) {
813         KisGroupLayer *layer = qobject_cast<KisGroupLayer*>(currentNode.data());
814         KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(layer, false);
815 
816         image->flattenLayer(layer);
817         result = true;
818     }
819 
820     return result;
821 }
822 
mergeLayer()823 void KisLayerManager::mergeLayer()
824 {
825     KisImageSP image = m_view->image();
826     if (!image) return;
827 
828     KisLayerSP layer = activeLayer();
829     if (!layer) return;
830 
831     if (!m_view->blockUntilOperationsFinished(image)) return;
832 
833     QList<KisNodeSP> selectedNodes = m_view->nodeManager()->selectedNodes();
834 
835     // check if all the layers are a part of a locked group
836     bool hasEditableLayer = false;
837     Q_FOREACH (KisNodeSP node, selectedNodes) {
838         if (node->isEditable(false)) {
839             hasEditableLayer = true;
840             break;
841         }
842     }
843 
844     if (!hasEditableLayer) {
845         m_view->showFloatingMessage(
846                     i18ncp("floating message in layer manager",
847                           "Layer is locked ", "Layers are locked", selectedNodes.size()),
848                     QIcon(), 2000, KisFloatingMessage::Low);
849         return;
850     }
851 
852     if (selectedNodes.size() > 1) {
853         image->mergeMultipleLayers(selectedNodes, m_view->activeNode());
854     }
855 
856     else if (tryMergeSelectionMasks(m_view->activeNode(), image)) {
857         // already done!
858     } else if (tryFlattenGroupLayer(m_view->activeNode(), image)) {
859         // already done!
860     } else {
861 
862         if (!layer->prevSibling()) return;
863         KisLayer *prevLayer = qobject_cast<KisLayer*>(layer->prevSibling().data());
864         if (!prevLayer) return;
865         if (prevLayer->userLocked()) {
866             m_view->showFloatingMessage(
867                         i18nc("floating message in layer manager",
868                               "Layer is locked "),
869                         QIcon(), 2000, KisFloatingMessage::Low);
870         }
871 
872         else if (layer->metaData()->isEmpty() && prevLayer->metaData()->isEmpty()) {
873             image->mergeDown(layer, KisMetaData::MergeStrategyRegistry::instance()->get("Drop"));
874         }
875         else {
876             const KisMetaData::MergeStrategy* strategy = KisMetaDataMergeStrategyChooserWidget::showDialog(m_view->mainWindow());
877             if (!strategy) return;
878             image->mergeDown(layer, strategy);
879         }
880     }
881 
882     m_view->updateGUI();
883 }
884 
flattenLayer()885 void KisLayerManager::flattenLayer()
886 {
887     KisImageSP image = m_view->image();
888     if (!image) return;
889 
890     KisLayerSP layer = activeLayer();
891     if (!layer) return;
892 
893     if (!m_view->blockUntilOperationsFinished(image)) return;
894     if (!m_view->nodeManager()->canModifyLayer(layer)) return;
895 
896     convertNodeToPaintLayer(layer);
897     m_view->updateGUI();
898 }
899 
rasterizeLayer()900 void KisLayerManager::rasterizeLayer()
901 {
902     KisImageSP image = m_view->image();
903     if (!image) return;
904 
905     KisLayerSP layer = activeLayer();
906     if (!layer) return;
907 
908     if (!m_view->blockUntilOperationsFinished(image)) return;
909     if (!m_view->nodeManager()->canModifyLayer(layer)) return;
910 
911     KisPaintLayerSP paintLayer = new KisPaintLayer(image, layer->name(), layer->opacity());
912     KisPainter gc(paintLayer->paintDevice());
913     QRect rc = layer->projection()->exactBounds();
914     gc.bitBlt(rc.topLeft(), layer->projection(), rc);
915 
916     m_commandsAdapter->beginMacro(kundo2_i18n("Rasterize Layer"));
917     m_commandsAdapter->addNode(paintLayer.data(), layer->parent().data(), layer.data());
918 
919     int childCount = layer->childCount();
920     for (int i = 0; i < childCount; i++) {
921         m_commandsAdapter->moveNode(layer->firstChild(), paintLayer, paintLayer->lastChild());
922     }
923     m_commandsAdapter->removeNode(layer);
924     m_commandsAdapter->endMacro();
925     updateGUI();
926 }
927 
928 
layersUpdated()929 void KisLayerManager::layersUpdated()
930 {
931     KisLayerSP layer = activeLayer();
932     if (!layer) return;
933 
934     m_view->updateGUI();
935 }
936 
saveGroupLayers()937 void KisLayerManager::saveGroupLayers()
938 {
939     QStringList listMimeFilter = KisImportExportManager::supportedMimeTypes(KisImportExportManager::Export);
940 
941     KoDialog dlg;
942     QWidget *page = new QWidget(&dlg);
943     dlg.setMainWidget(page);
944     QBoxLayout *layout = new QVBoxLayout(page);
945 
946     KisFileNameRequester *urlRequester = new KisFileNameRequester(page);
947     urlRequester->setMode(KoFileDialog::SaveFile);
948     if (m_view->document()->url().isLocalFile()) {
949         urlRequester->setStartDir(QFileInfo(m_view->document()->url().toLocalFile()).absolutePath());
950     }
951     urlRequester->setMimeTypeFilters(listMimeFilter);
952     urlRequester->setFileName(m_view->document()->url().toLocalFile());
953     layout->addWidget(urlRequester);
954 
955     QCheckBox *chkInvisible = new QCheckBox(i18n("Convert Invisible Groups"), page);
956     chkInvisible->setChecked(false);
957     layout->addWidget(chkInvisible);
958     QCheckBox *chkDepth = new QCheckBox(i18n("Export Only Toplevel Groups"), page);
959     chkDepth->setChecked(true);
960     layout->addWidget(chkDepth);
961 
962     if (!dlg.exec()) return;
963 
964     QString path = urlRequester->fileName();
965 
966     if (path.isEmpty()) return;
967 
968     QFileInfo f(path);
969 
970     QString mimeType= KisMimeDatabase::mimeTypeForFile(f.fileName(), false);
971     if (mimeType.isEmpty()) {
972         mimeType = "image/png";
973     }
974     QString extension = KisMimeDatabase::suffixesForMimeType(mimeType).first();
975     QString basename = f.completeBaseName();
976 
977     KisImageSP image = m_view->image();
978     if (!image) return;
979 
980     KisSaveGroupVisitor v(image, chkInvisible->isChecked(), chkDepth->isChecked(), f.absolutePath(), basename, extension, mimeType);
981     image->rootLayer()->accept(v);
982 
983 }
984 
activeLayerHasSelection()985 bool KisLayerManager::activeLayerHasSelection()
986 {
987     return (activeLayer()->selection() != 0);
988 }
989 
addFileLayer(KisNodeSP activeNode)990 KisNodeSP KisLayerManager::addFileLayer(KisNodeSP activeNode)
991 {
992     QString basePath;
993     QUrl url = m_view->document()->url();
994     if (url.isLocalFile()) {
995         basePath = QFileInfo(url.toLocalFile()).absolutePath();
996     }
997     KisImageWSP image = m_view->image();
998 
999     KisDlgFileLayer dlg(basePath, image->nextLayerName(i18n("File Layer")), m_view->mainWindow());
1000     dlg.resize(dlg.minimumSizeHint());
1001 
1002     if (dlg.exec() == QDialog::Accepted) {
1003         QString name = dlg.layerName();
1004         QString fileName = dlg.fileName();
1005 
1006         if(fileName.isEmpty()){
1007             QMessageBox::critical(m_view->mainWindow(), i18nc("@title:window", "Krita"), i18n("No file name specified"));
1008             return 0;
1009         }
1010 
1011         KisFileLayer::ScalingMethod scalingMethod = dlg.scaleToImageResolution();
1012         KisNodeSP node = new KisFileLayer(image, basePath, fileName, scalingMethod, name, OPACITY_OPAQUE_U8);
1013         addLayerCommon(activeNode, node, true, 0);
1014         return node;
1015     }
1016     return 0;
1017 }
1018 
updateLayerStyles(KisLayerSP layer,KisDlgLayerStyle * dlg)1019 void updateLayerStyles(KisLayerSP layer, KisDlgLayerStyle *dlg)
1020 {
1021     KisSetLayerStyleCommand::updateLayerStyle(layer, dlg->style()->clone());
1022 }
1023 
layerStyle()1024 void KisLayerManager::layerStyle()
1025 {
1026     KisImageWSP image = m_view->image();
1027     if (!image) return;
1028 
1029     KisLayerSP layer = activeLayer();
1030     if (!layer) return;
1031 
1032     if (!m_view->blockUntilOperationsFinished(image)) return;
1033     if (!m_view->nodeManager()->canModifyLayer(layer)) return;
1034 
1035     KisPSDLayerStyleSP oldStyle;
1036     if (layer->layerStyle()) {
1037         oldStyle = layer->layerStyle()->clone();
1038     }
1039     else {
1040         oldStyle = toQShared(new KisPSDLayerStyle());
1041     }
1042 
1043     KisDlgLayerStyle dlg(oldStyle->clone(), m_view->canvasResourceProvider());
1044 
1045     std::function<void ()> updateCall(std::bind(updateLayerStyles, layer, &dlg));
1046     SignalToFunctionProxy proxy(updateCall);
1047     connect(&dlg, SIGNAL(configChanged()), &proxy, SLOT(start()));
1048 
1049     if (dlg.exec() == QDialog::Accepted) {
1050         KisPSDLayerStyleSP newStyle = dlg.style();
1051 
1052         KUndo2CommandSP command = toQShared(
1053                     new KisSetLayerStyleCommand(layer, oldStyle, newStyle));
1054 
1055         image->postExecutionUndoAdapter()->addCommand(command);
1056     }
1057 }
1058 
1059