File indexing completed on 2024-05-12 16:01:33

0001 /*
0002  *  SPDX-FileCopyrightText: 2006 Boudewijn Rempt <boud@valdyas.org>
0003  *  SPDX-FileCopyrightText: 2020 L. E. Segovia <amy@amyspark.me>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #include "kis_layer_manager.h"
0009 
0010 #include <QRect>
0011 #include <QApplication>
0012 #include <QCursor>
0013 #include <QString>
0014 #include <QDialog>
0015 #include <QVBoxLayout>
0016 #include <QFileInfo>
0017 #include <QStandardPaths>
0018 #include <QClipboard>
0019 #include <QMimeData>
0020 
0021 #include <kactioncollection.h>
0022 #include <klocalizedstring.h>
0023 #include <QMessageBox>
0024 #include <QUrl>
0025 
0026 #include <kis_file_name_requester.h>
0027 #include <kis_icon.h>
0028 #include <KisImportExportManager.h>
0029 #include <KisDocument.h>
0030 #include <KoColorSpace.h>
0031 #include <KoCompositeOpRegistry.h>
0032 #include <KoPointerEvent.h>
0033 #include <KoColorProfile.h>
0034 #include <KoSelection.h>
0035 #include <KisPart.h>
0036 #include <KisMainWindow.h>
0037 
0038 #include <filter/kis_filter_configuration.h>
0039 #include <filter/kis_filter.h>
0040 #include <kis_filter_strategy.h>
0041 #include <generator/kis_generator_layer.h>
0042 #include <kis_file_layer.h>
0043 #include <kis_adjustment_layer.h>
0044 #include <kis_mask.h>
0045 #include <kis_clone_layer.h>
0046 #include <kis_group_layer.h>
0047 #include <kis_image.h>
0048 #include <kis_layer.h>
0049 #include <kis_paint_device.h>
0050 #include <kis_selection.h>
0051 #include <flake/kis_shape_layer.h>
0052 #include <kis_undo_adapter.h>
0053 #include <kis_painter.h>
0054 #include <kis_meta_data_store.h>
0055 #include <kis_meta_data_merge_strategy_registry.h>
0056 #include <kis_psd_layer_style.h>
0057 #include <KisMimeDatabase.h>
0058 #include <kis_clipboard.h>
0059 
0060 #include "kis_config.h"
0061 #include "kis_cursor.h"
0062 #include "dialogs/kis_dlg_adj_layer_props.h"
0063 #include "dialogs/kis_dlg_adjustment_layer.h"
0064 #include "dialogs/kis_dlg_layer_properties.h"
0065 #include "dialogs/kis_dlg_generator_layer.h"
0066 #include "dialogs/kis_dlg_file_layer.h"
0067 #include "dialogs/kis_dlg_layer_style.h"
0068 #include "dialogs/KisDlgChangeCloneSource.h"
0069 #include "kis_filter_manager.h"
0070 #include "kis_node_visitor.h"
0071 #include "kis_paint_layer.h"
0072 #include "commands/kis_image_commands.h"
0073 #include "commands/kis_node_commands.h"
0074 #include <commands/KisNodeRenameCommand.h>
0075 #include "kis_change_file_layer_command.h"
0076 #include "kis_canvas_resource_provider.h"
0077 #include "kis_selection_manager.h"
0078 #include "kis_statusbar.h"
0079 #include "KisViewManager.h"
0080 #include "kis_zoom_manager.h"
0081 #include "canvas/kis_canvas2.h"
0082 #include "widgets/kis_meta_data_merge_strategy_chooser_widget.h"
0083 #include "widgets/kis_wdg_generator.h"
0084 #include "kis_progress_widget.h"
0085 #include "kis_node_commands_adapter.h"
0086 #include "kis_node_manager.h"
0087 #include "kis_action.h"
0088 #include "kis_action_manager.h"
0089 #include "kis_raster_keyframe_channel.h"
0090 #include "kis_signal_compressor_with_param.h"
0091 #include "kis_abstract_projection_plane.h"
0092 #include "commands_new/kis_set_layer_style_command.h"
0093 #include "kis_post_execution_undo_adapter.h"
0094 #include "kis_selection_mask.h"
0095 #include "kis_layer_utils.h"
0096 #include "lazybrush/kis_colorize_mask.h"
0097 #include "kis_processing_applicator.h"
0098 #include "kis_projection_leaf.h"
0099 #include "KisGlobalResourcesInterface.h"
0100 
0101 #include "KisSaveGroupVisitor.h"
0102 #include <kis_asl_layer_style_serializer.h>
0103 
0104 
0105 KisLayerManager::KisLayerManager(KisViewManager * view)
0106     : m_view(view)
0107     , m_commandsAdapter(new KisNodeCommandsAdapter(m_view))
0108 
0109 {
0110 }
0111 
0112 KisLayerManager::~KisLayerManager()
0113 {
0114     delete m_commandsAdapter;
0115 }
0116 
0117 void KisLayerManager::setView(QPointer<KisView>view)
0118 {
0119     m_imageView = view;
0120 }
0121 
0122 KisLayerSP KisLayerManager::activeLayer()
0123 {
0124     if (m_imageView) {
0125         return m_imageView->currentLayer();
0126     }
0127     return 0;
0128 }
0129 
0130 KisPaintDeviceSP KisLayerManager::activeDevice()
0131 {
0132     if (activeLayer()) {
0133         return activeLayer()->paintDevice();
0134     }
0135     return 0;
0136 }
0137 
0138 void KisLayerManager::activateLayer(KisLayerSP layer)
0139 {
0140     if (m_imageView) {
0141         layersUpdated();
0142         if (layer) {
0143             m_view->canvasResourceProvider()->slotNodeActivated(layer.data());
0144         }
0145     }
0146 }
0147 
0148 
0149 void KisLayerManager::setup(KisActionManager* actionManager)
0150 {
0151     m_imageFlatten = actionManager->createAction("flatten_image");
0152     connect(m_imageFlatten, SIGNAL(triggered()), this, SLOT(flattenImage()));
0153 
0154     m_imageMergeLayer = actionManager->createAction("merge_layer");
0155     connect(m_imageMergeLayer, SIGNAL(triggered()), this, SLOT(mergeLayer()));
0156 
0157     m_flattenLayer = actionManager->createAction("flatten_layer");
0158     connect(m_flattenLayer, SIGNAL(triggered()), this, SLOT(flattenLayer()));
0159 
0160     m_groupLayersSave = actionManager->createAction("save_groups_as_images");
0161     connect(m_groupLayersSave, SIGNAL(triggered()), this, SLOT(saveGroupLayers()));
0162 
0163     m_convertGroupAnimated = actionManager->createAction("convert_group_to_animated");
0164     connect(m_convertGroupAnimated, SIGNAL(triggered()), this, SLOT(convertGroupToAnimated()));
0165 
0166     m_imageResizeToLayer = actionManager->createAction("resizeimagetolayer");
0167     connect(m_imageResizeToLayer, SIGNAL(triggered()), this, SLOT(imageResizeToActiveLayer()));
0168 
0169     KisAction *action = actionManager->createAction("trim_to_image");
0170     connect(action, SIGNAL(triggered()), this, SLOT(trimToImage()));
0171 
0172     m_layerStyle  = actionManager->createAction("layer_style");
0173     connect(m_layerStyle, SIGNAL(triggered()), this, SLOT(layerStyle()));
0174 
0175     m_copyLayerStyle = actionManager->createAction("copy_layer_style");
0176     connect(m_copyLayerStyle, SIGNAL(triggered()), this, SLOT(copyLayerStyle()));
0177 
0178     m_pasteLayerStyle = actionManager->createAction("paste_layer_style");
0179     connect(m_pasteLayerStyle, SIGNAL(triggered()), this, SLOT(pasteLayerStyle()));
0180 }
0181 
0182 void KisLayerManager::updateGUI()
0183 {
0184     KisImageSP image = m_view->image();
0185     KisLayerSP layer = activeLayer();
0186 
0187     const bool isGroupLayer = layer && layer->inherits("KisGroupLayer");
0188 
0189     m_imageMergeLayer->setText(
0190                 isGroupLayer ?
0191                     i18nc("@action:inmenu", "Merge Group") :
0192                     i18nc("@action:inmenu", "Merge with Layer Below"));
0193     m_flattenLayer->setVisible(!isGroupLayer);
0194 
0195     if (m_view->statusBar())
0196         m_view->statusBar()->setProfile(image);
0197 }
0198 
0199 void KisLayerManager::imageResizeToActiveLayer()
0200 {
0201     KisLayerSP layer;
0202     KisImageWSP image = m_view->image();
0203 
0204     if (image && (layer = activeLayer())) {
0205         QRect cropRect = layer->projection()->nonDefaultPixelArea();
0206         if (!cropRect.isEmpty()) {
0207             image->cropImage(cropRect);
0208         } else {
0209             m_view->showFloatingMessage(
0210                         i18nc("floating message in layer manager",
0211                               "Layer is empty "),
0212                         QIcon(), 2000, KisFloatingMessage::Low);
0213         }
0214     }
0215 }
0216 
0217 void KisLayerManager::trimToImage()
0218 {
0219     KisImageWSP image = m_view->image();
0220     if (image) {
0221         image->cropImage(image->bounds());
0222     }
0223 }
0224 
0225 void KisLayerManager::layerProperties()
0226 {
0227     if (!m_view) return;
0228     if (!m_view->document()) return;
0229 
0230     KisLayerSP layer = activeLayer();
0231     if (!layer) return;
0232 
0233     QList<KisNodeSP> selectedNodes = m_view->nodeManager()->selectedNodes();
0234     const bool multipleLayersSelected = selectedNodes.size() > 1;
0235 
0236     if (!m_view->nodeManager()->canModifyLayers(selectedNodes)) return;
0237 
0238     KisAdjustmentLayerSP adjustmentLayer = KisAdjustmentLayerSP(dynamic_cast<KisAdjustmentLayer*>(layer.data()));
0239     KisGeneratorLayerSP generatorLayer = KisGeneratorLayerSP(dynamic_cast<KisGeneratorLayer*>(layer.data()));
0240     KisFileLayerSP fileLayer = KisFileLayerSP(dynamic_cast<KisFileLayer*>(layer.data()));
0241 
0242     if (adjustmentLayer && !multipleLayersSelected) {
0243 
0244         KisPaintDeviceSP dev = adjustmentLayer->projection();
0245 
0246         KisDlgAdjLayerProps dlg(adjustmentLayer, adjustmentLayer.data(), dev, m_view, adjustmentLayer->filter().data(), adjustmentLayer->name(), i18n("Filter Layer Properties"), m_view->mainWindow(), "dlgadjlayerprops");
0247         dlg.resize(dlg.minimumSizeHint());
0248 
0249 
0250         KisFilterConfigurationSP configBefore(adjustmentLayer->filter());
0251         KIS_ASSERT_RECOVER_RETURN(configBefore);
0252         QString xmlBefore = configBefore->toXML();
0253 
0254 
0255         if (dlg.exec() == QDialog::Accepted) {
0256 
0257             adjustmentLayer->setName(dlg.layerName());
0258 
0259             KisFilterConfigurationSP configAfter(dlg.filterConfiguration());
0260             Q_ASSERT(configAfter);
0261             QString xmlAfter = configAfter->toXML();
0262 
0263             if(xmlBefore != xmlAfter) {
0264                 KisChangeFilterCmd *cmd
0265                         = new KisChangeFilterCmd(adjustmentLayer,
0266                                                  configBefore->cloneWithResourcesSnapshot(),
0267                                                  configAfter->cloneWithResourcesSnapshot());
0268                 // FIXME: check whether is needed
0269                 cmd->redo();
0270                 m_view->undoAdapter()->addCommand(cmd);
0271                 m_view->document()->setModified(true);
0272             }
0273         }
0274         else {
0275             KisFilterConfigurationSP configAfter(dlg.filterConfiguration());
0276             Q_ASSERT(configAfter);
0277             QString xmlAfter = configAfter->toXML();
0278 
0279             if(xmlBefore != xmlAfter) {
0280                 adjustmentLayer->setFilter(configBefore->cloneWithResourcesSnapshot());
0281                 adjustmentLayer->setDirty();
0282             }
0283         }
0284     }
0285     else if (generatorLayer && !multipleLayersSelected) {
0286         KisFilterConfigurationSP configBefore(generatorLayer->filter());
0287         Q_ASSERT(configBefore);
0288 
0289         KisDlgGeneratorLayer *dlg = new KisDlgGeneratorLayer(generatorLayer->name(), m_view, m_view->mainWindow(), generatorLayer, configBefore, KisStrokeId());
0290         dlg->setWindowTitle(i18n("Fill Layer Properties"));
0291         dlg->setAttribute(Qt::WA_DeleteOnClose);
0292 
0293         dlg->setConfiguration(configBefore.data());
0294 
0295         Qt::WindowFlags flags = dlg->windowFlags();
0296         dlg->setWindowFlags(flags | Qt::Tool | Qt::Dialog);
0297         dlg->show();
0298 
0299     }
0300     else if (fileLayer && !multipleLayersSelected){
0301         QString basePath = QFileInfo(m_view->document()->path()).absolutePath();
0302         QString fileNameOld = fileLayer->fileName();
0303         KisFileLayer::ScalingMethod scalingMethodOld = fileLayer->scalingMethod();
0304         KisDlgFileLayer dlg(basePath, fileLayer->name(), m_view->mainWindow());
0305         dlg.setCaption(i18n("File Layer Properties"));
0306         dlg.setFileName(fileNameOld);
0307         dlg.setScalingMethod(scalingMethodOld);
0308 
0309         if (dlg.exec() == QDialog::Accepted) {
0310             const QString fileNameNew = dlg.fileName();
0311             KisFileLayer::ScalingMethod scalingMethodNew = dlg.scaleToImageResolution();
0312 
0313             if(fileNameNew.isEmpty()){
0314                 QMessageBox::critical(m_view->mainWindow(), i18nc("@title:window", "Krita"), i18n("No file name specified"));
0315                 return;
0316             }
0317             fileLayer->setName(dlg.layerName());
0318 
0319             if (fileNameOld!= fileNameNew || scalingMethodOld != scalingMethodNew) {
0320                 KisChangeFileLayerCmd *cmd
0321                         = new KisChangeFileLayerCmd(fileLayer,
0322                                                     basePath,
0323                                                     fileNameOld,
0324                                                     scalingMethodOld,
0325                                                     basePath,
0326                                                     fileNameNew,
0327                                                     scalingMethodNew);
0328                 m_view->undoAdapter()->addCommand(cmd);
0329             }
0330         }
0331     } else { // If layer == normal painting layer, vector layer, or group layer
0332         QList<KisNodeSP> selectedNodes = m_view->nodeManager()->selectedNodes();
0333 
0334         KisDlgLayerProperties *dialog = new KisDlgLayerProperties(selectedNodes, m_view, m_view->canvas());
0335         dialog->resize(dialog->minimumSizeHint());
0336         dialog->setAttribute(Qt::WA_DeleteOnClose);
0337         Qt::WindowFlags flags = dialog->windowFlags();
0338 #ifdef Q_OS_ANDROID
0339         // a Qt::Tool window seems incapable of receiving keyboard focus
0340         dialog->setWindowFlags(flags | Qt::Dialog);
0341 #else
0342         dialog->setWindowFlags(flags | Qt::Tool | Qt::Dialog);
0343 #endif
0344         dialog->show();
0345         dialog->activateWindow();
0346     }
0347 }
0348 
0349 void KisLayerManager::changeCloneSource()
0350 {
0351     QList<KisNodeSP> selectedNodes = m_view->nodeManager()->selectedNodes();
0352     if (selectedNodes.isEmpty()) {
0353         return;
0354     }
0355 
0356     QList<KisCloneLayerSP> cloneLayers;
0357     KisNodeSP node;
0358     Q_FOREACH (node, selectedNodes) {
0359         KisCloneLayerSP cloneLayer(qobject_cast<KisCloneLayer *>(node.data()));
0360         if (cloneLayer) {
0361             cloneLayers << cloneLayer;
0362         }
0363     }
0364 
0365     if (cloneLayers.isEmpty()) {
0366         return;
0367     }
0368 
0369     if (!m_view->nodeManager()->canModifyLayers(implicitCastList<KisNodeSP>(cloneLayers))) return;
0370 
0371     KisDlgChangeCloneSource *dialog = new KisDlgChangeCloneSource(cloneLayers, m_view);
0372     dialog->setCaption(i18n("Change Clone Layer"));
0373     dialog->resize(dialog->minimumSizeHint());
0374     dialog->setAttribute(Qt::WA_DeleteOnClose);
0375     Qt::WindowFlags flags = dialog->windowFlags();
0376     dialog->setWindowFlags(flags | Qt::Tool | Qt::Dialog);
0377     dialog->show();
0378     dialog->activateWindow();
0379 }
0380 
0381 void KisLayerManager::copyLayerStyle()
0382 {
0383     KisImageSP image = m_view->image();
0384     if (!image) return;
0385 
0386     KisLayerSP layer = activeLayer();
0387     if (!layer) return;
0388 
0389     KisPSDLayerStyleSP layerStyle = layer->layerStyle();
0390     if (!layerStyle) return;
0391 
0392     KisAslLayerStyleSerializer serializer;
0393     serializer.setStyles(QVector<KisPSDLayerStyleSP>() << layerStyle);
0394     QString psdxml = serializer.formPsdXmlDocument().toString();
0395 
0396     if (!psdxml.isEmpty()) {
0397         QMimeData *mimeData = new QMimeData;
0398 
0399         mimeData->setText(psdxml);
0400         mimeData->setData("application/x-krita-layer-style", psdxml.toUtf8());
0401 
0402         QGuiApplication::clipboard()->setMimeData(mimeData);
0403     }
0404 }
0405 
0406 void KisLayerManager::pasteLayerStyle()
0407 {
0408     KisImageSP image = m_view->image();
0409     if (!image) return;
0410 
0411     KisLayerSP layer = activeLayer();
0412     if (!layer) return;
0413 
0414     QString aslXml;
0415 
0416     if (KisClipboard::instance()->hasLayerStyles()) {
0417         aslXml = QString::fromUtf8(QGuiApplication::clipboard()->mimeData()->data("application/x-krita-layer-style"));
0418     } else {
0419         aslXml = QGuiApplication::clipboard()->text();
0420     }
0421 
0422     if (aslXml.isEmpty()) return;
0423 
0424     QDomDocument aslDoc;
0425     if (!aslDoc.setContent(aslXml)) return;
0426 
0427     KisAslLayerStyleSerializer serializer;
0428     serializer.registerPSDPattern(aslDoc);
0429     serializer.readFromPSDXML(aslDoc);
0430 
0431     if (serializer.styles().size() != 1) return;
0432 
0433     KisPSDLayerStyleSP newStyle = serializer.styles().first()->cloneWithResourcesSnapshot(
0434         KisGlobalResourcesInterface::instance(),
0435         m_view->canvasBase()->resourceManager()->canvasResourcesInterface());
0436     KUndo2Command *cmd = new KisSetLayerStyleCommand(layer, layer->layerStyle(), newStyle);
0437 
0438     KisProcessingApplicator::runSingleCommandStroke(image, cmd);
0439     image->waitForDone();
0440 }
0441 
0442 void KisLayerManager::convertNodeToPaintLayer(KisNodeSP source)
0443 {
0444     KisImageWSP image = m_view->image();
0445     if (!image) return;
0446 
0447     // this precondition must be checked at higher level
0448     KIS_SAFE_ASSERT_RECOVER_RETURN(source->isEditable(false));
0449 
0450     KisLayer *srcLayer = qobject_cast<KisLayer*>(source.data());
0451     if (srcLayer && (srcLayer->inherits("KisGroupLayer") || srcLayer->layerStyle() || srcLayer->childCount() > 0)) {
0452         image->flattenLayer(srcLayer);
0453         return;
0454     }
0455 
0456     KisLayerUtils::convertToPaintLayer(image, source);
0457 }
0458 
0459 void KisLayerManager::convertGroupToAnimated()
0460 {
0461     KisGroupLayerSP group = dynamic_cast<KisGroupLayer*>(activeLayer().data());
0462     if (group.isNull()) return;
0463 
0464     if (!m_view->nodeManager()->canModifyLayer(group)) return;
0465 
0466     KisPaintLayerSP animatedLayer = new KisPaintLayer(m_view->image(), group->name(), OPACITY_OPAQUE_U8);
0467     animatedLayer->enableAnimation();
0468     KisRasterKeyframeChannel *contentChannel = dynamic_cast<KisRasterKeyframeChannel*>(
0469                 animatedLayer->getKeyframeChannel(KisKeyframeChannel::Raster.id(), true));
0470     KIS_ASSERT_RECOVER_RETURN(contentChannel);
0471 
0472     KisNodeSP child = group->firstChild();
0473     int time = 0;
0474     while (child) {
0475         contentChannel->importFrame(time, child->projection(), NULL);
0476         time++;
0477 
0478         child = child->nextSibling();
0479     }
0480 
0481     m_commandsAdapter->beginMacro(kundo2_i18n("Convert to an animated layer"));
0482     m_commandsAdapter->addNode(animatedLayer, group->parent(), group);
0483     m_commandsAdapter->removeNode(group);
0484     m_commandsAdapter->endMacro();
0485 }
0486 
0487 void KisLayerManager::convertLayerToFileLayer(KisNodeSP source)
0488 {
0489     KisImageSP image = m_view->image();
0490     if (!image) return;
0491 
0492     // this precondition must be checked at higher level
0493     KIS_SAFE_ASSERT_RECOVER_RETURN(source->isEditable(false));
0494 
0495     QStringList listMimeFilter = KisImportExportManager::supportedMimeTypes(KisImportExportManager::Export);
0496 
0497     KoDialog dlg;
0498     QWidget *page = new QWidget(&dlg);
0499     dlg.setMainWidget(page);
0500     QBoxLayout *layout = new QVBoxLayout(page);
0501     dlg.setWindowTitle(i18n("Save layers to..."));
0502     QLabel *lbl = new QLabel(i18n("Choose the location where the layer will be saved to. The new file layer will then reference this location."));
0503     lbl->setWordWrap(true);
0504     layout->addWidget(lbl);
0505     KisFileNameRequester *urlRequester = new KisFileNameRequester(page);
0506     urlRequester->setMode(KoFileDialog::SaveFile);
0507     urlRequester->setMimeTypeFilters(listMimeFilter);
0508     urlRequester->setFileName(m_view->document()->path());
0509     if (!m_view->document()->path().isEmpty()) {
0510         QFileInfo location = QFileInfo(m_view->document()->path()).completeBaseName();
0511         location.setFile(location.dir(), location.completeBaseName() + "_" + source->name() + ".png");
0512         urlRequester->setFileName(location.absoluteFilePath());
0513     }
0514     else {
0515         const QFileInfo location = QFileInfo(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
0516         const QString proposedFileName = QDir(location.absoluteFilePath()).absoluteFilePath(source->name() + ".png");
0517         urlRequester->setFileName(proposedFileName);
0518     }
0519 
0520     layout->addWidget(urlRequester);
0521     if (!dlg.exec()) return;
0522 
0523     QString path = urlRequester->fileName();
0524 
0525     if (path.isEmpty()) return;
0526 
0527     QFileInfo f(path);
0528 
0529     QString mimeType= KisMimeDatabase::mimeTypeForFile(f.fileName());
0530     if (mimeType.isEmpty()) {
0531         mimeType = "image/png";
0532     }
0533     QScopedPointer<KisDocument> doc(KisPart::instance()->createDocument());
0534 
0535     QRect bounds = source->exactBounds();
0536     if (bounds.isEmpty()) {
0537         bounds = image->bounds();
0538     }
0539     KisImageSP dst = new KisImage(doc->createUndoStore(),
0540                                   image->width(),
0541                                   image->height(),
0542                                   image->projection()->compositionSourceColorSpace(),
0543                                   source->name());
0544     dst->setResolution(image->xRes(), image->yRes());
0545     doc->setFileBatchMode(false);
0546     doc->setCurrentImage(dst);
0547     KisNodeSP node = source->clone();
0548     dst->addNode(node);
0549     dst->initialRefreshGraph();
0550     dst->cropImage(bounds);
0551     dst->waitForDone();
0552 
0553     bool r = doc->exportDocumentSync(path, mimeType.toLatin1());
0554     if (!r) {
0555 
0556         qWarning() << "Converting layer to file layer. path:"<< path << "gave errors" << doc->errorMessage();
0557     } else {
0558         QString basePath = QFileInfo(m_view->document()->path()).absolutePath();
0559         QString relativePath = QDir(basePath).relativeFilePath(path);
0560         KisFileLayer *fileLayer = new KisFileLayer(image, basePath, relativePath, KisFileLayer::None, source->name(), OPACITY_OPAQUE_U8);
0561         fileLayer->setX(bounds.x());
0562         fileLayer->setY(bounds.y());
0563         KisNodeSP dstParent = source->parent();
0564         KisNodeSP dstAboveThis = source->prevSibling();
0565         m_commandsAdapter->beginMacro(kundo2_i18n("Convert to a file layer"));
0566         m_commandsAdapter->removeNode(source);
0567         m_commandsAdapter->addNode(fileLayer, dstParent, dstAboveThis);
0568         m_commandsAdapter->endMacro();
0569     }
0570     doc->closePath(false);
0571 }
0572 
0573 void KisLayerManager::adjustLayerPosition(KisNodeSP node, KisNodeSP activeNode, KisNodeSP &parent, KisNodeSP &above)
0574 {
0575     Q_ASSERT(activeNode);
0576 
0577     parent = activeNode;
0578     above = parent->lastChild();
0579 
0580     if (parent->inherits("KisGroupLayer") && parent->collapsed()) {
0581         above = parent;
0582         parent = parent->parent();
0583         return;
0584     }
0585 
0586     while (parent &&
0587            (!parent->allowAsChild(node) || !parent->isEditable(false))) {
0588 
0589         above = parent;
0590         parent = parent->parent();
0591     }
0592 
0593     if (!parent) {
0594         warnKrita << "KisLayerManager::adjustLayerPosition:"
0595                   << "No node accepted newly created node";
0596 
0597         parent = m_view->image()->root();
0598         above = parent->lastChild();
0599     }
0600 }
0601 
0602 void KisLayerManager::addLayerCommon(KisNodeSP activeNode, KisNodeSP layer, bool updateImage, KisProcessingApplicator *applicator)
0603 {
0604     KisNodeSP parent;
0605     KisNodeSP above;
0606     adjustLayerPosition(layer, activeNode, parent, above);
0607 
0608     KisGroupLayer *group = dynamic_cast<KisGroupLayer*>(parent.data());
0609     const bool parentForceUpdate = group && !group->projectionIsValid();
0610     updateImage |= parentForceUpdate;
0611 
0612     m_commandsAdapter->addNodeAsync(layer, parent, above, updateImage, updateImage, applicator);
0613 }
0614 
0615 KisLayerSP KisLayerManager::addPaintLayer(KisNodeSP activeNode)
0616 {
0617     KisImageWSP image = m_view->image();    
0618     KisLayerSP layer = new KisPaintLayer(image.data(),  image->nextLayerName( i18n("Paint Layer") ), OPACITY_OPAQUE_U8, image->colorSpace());
0619 
0620     KisConfig cfg(true);
0621     layer->setPinnedToTimeline(cfg.autoPinLayersToTimeline());
0622 
0623     addLayerCommon(activeNode, layer, false, 0);
0624 
0625     return layer;
0626 }
0627 
0628 KisNodeSP KisLayerManager::addGroupLayer(KisNodeSP activeNode)
0629 {
0630     KisImageWSP image = m_view->image();
0631     KisGroupLayerSP group = new KisGroupLayer(image.data(), image->nextLayerName( i18nc("A group of layers", "Group") ), OPACITY_OPAQUE_U8);
0632     addLayerCommon(activeNode, group, false, 0);
0633     return group;
0634 }
0635 
0636 KisNodeSP KisLayerManager::addCloneLayer(KisNodeList nodes)
0637 {
0638     KisImageWSP image = m_view->image();
0639 
0640     KisNodeList filteredNodes = KisLayerUtils::sortAndFilterMergableInternalNodes(nodes, false);
0641     if (filteredNodes.isEmpty()) return KisNodeSP();
0642 
0643     KisNodeSP newAbove = filteredNodes.last();
0644 
0645     KisNodeSP node, lastClonedNode;
0646     Q_FOREACH (node, filteredNodes) {
0647         lastClonedNode = new KisCloneLayer(qobject_cast<KisLayer*>(node.data()), image.data(), image->nextLayerName( i18n("Clone Layer") ), OPACITY_OPAQUE_U8);
0648         addLayerCommon(newAbove, lastClonedNode, true, 0 );
0649     }
0650 
0651     return lastClonedNode;
0652 }
0653 
0654 KisNodeSP KisLayerManager::addShapeLayer(KisNodeSP activeNode)
0655 {
0656     if (!m_view) return 0;
0657     if (!m_view->document()) return 0;
0658 
0659     KisImageWSP image = m_view->image();
0660     KisShapeLayerSP layer = new KisShapeLayer(m_view->document()->shapeController(), image.data(), image->nextLayerName(i18n("Vector Layer")), OPACITY_OPAQUE_U8);
0661 
0662     addLayerCommon(activeNode, layer, false, 0);
0663 
0664     return layer;
0665 }
0666 
0667 KisNodeSP KisLayerManager::addAdjustmentLayer(KisNodeSP activeNode)
0668 {
0669     KisImageWSP image = m_view->image();
0670 
0671     KisSelectionSP selection = m_view->selection();
0672 
0673     KisProcessingApplicator applicator(image, 0, KisProcessingApplicator::NONE,
0674                                        KisImageSignalVector(),
0675                                        kundo2_i18n("Add Layer"));
0676 
0677 
0678     KisAdjustmentLayerSP adjl = addAdjustmentLayer(activeNode, QString(), 0, selection, &applicator);
0679 
0680     KisPaintDeviceSP previewDevice = new KisPaintDevice(*adjl->original());
0681 
0682     KisDlgAdjustmentLayer dlg(adjl, adjl.data(), previewDevice, image->nextLayerName(i18n("Filter Layer")), i18n("New Filter Layer"), m_view, qApp->activeWindow());
0683     dlg.resize(dlg.minimumSizeHint());
0684 
0685     // ensure that the device may be free'd by the dialog
0686     // when it is not needed anymore
0687     previewDevice = 0;
0688 
0689     if (dlg.exec() != QDialog::Accepted || adjl->filter().isNull()) {
0690         // XXX: add messagebox warning if there's no filter set!
0691         applicator.cancel();
0692     } else {
0693         applicator.applyCommand(new KisNodeRenameCommand(adjl, adjl->name(), dlg.layerName()));
0694         applicator.end();
0695     }
0696 
0697     return adjl;
0698 }
0699 
0700 KisAdjustmentLayerSP KisLayerManager::addAdjustmentLayer(KisNodeSP activeNode, const QString & name,
0701                                                          KisFilterConfigurationSP  filter,
0702                                                          KisSelectionSP selection,
0703                                                          KisProcessingApplicator *applicator)
0704 {
0705     KisImageWSP image = m_view->image();
0706     KisAdjustmentLayerSP layer = new KisAdjustmentLayer(image, name, filter ? filter->cloneWithResourcesSnapshot() : 0, selection);
0707     addLayerCommon(activeNode, layer, true, applicator);
0708 
0709     return layer;
0710 }
0711 
0712 KisGeneratorLayerSP KisLayerManager::addGeneratorLayer(KisNodeSP activeNode, const QString &name, KisFilterConfigurationSP filter, KisSelectionSP selection, KisProcessingApplicator *applicator)
0713 {
0714     KisImageWSP image = m_view->image();
0715     auto layer = new KisGeneratorLayer(image, name, filter, selection);
0716     addLayerCommon(activeNode, layer, true, applicator);
0717 
0718     return layer;
0719 }
0720 
0721 KisNodeSP KisLayerManager::addGeneratorLayer(KisNodeSP activeNode)
0722 {
0723     KisImageWSP image = m_view->image();
0724     KisSelectionSP selection = m_view->selection();
0725     QColor currentForeground = m_view->canvasResourceProvider()->fgColor().toQColor();
0726 
0727     KisProcessingApplicator applicator(image, 0, KisProcessingApplicator::NONE, KisImageSignalVector(), kundo2_i18n("Add Layer"));
0728 
0729     KisGeneratorLayerSP node = addGeneratorLayer(activeNode, QString(), nullptr, selection, &applicator);
0730 
0731     KisDlgGeneratorLayer dlg(image->nextLayerName(i18n("Fill Layer")), m_view, m_view->mainWindow(), node, nullptr, applicator.getStroke());
0732     KisFilterConfigurationSP defaultConfig = dlg.configuration();
0733     defaultConfig->setProperty("color", currentForeground);
0734     dlg.setConfiguration(defaultConfig);
0735 
0736     if (dlg.exec() == QDialog::Accepted) {
0737         applicator.applyCommand(new KisNodeRenameCommand(node, node->name(), dlg.layerName()));
0738         applicator.end();
0739         return node;
0740     }
0741     else {
0742         applicator.cancel();
0743         return nullptr;
0744     }
0745 }
0746 
0747 void KisLayerManager::flattenImage()
0748 {
0749     KisImageSP image = m_view->image();
0750 
0751     if (!m_view->blockUntilOperationsFinished(image)) return;
0752 
0753     if (image) {
0754         bool doIt = true;
0755 
0756         if (image->nHiddenLayers() > 0) {
0757             int answer = QMessageBox::warning(m_view->mainWindow(),
0758                                               i18nc("@title:window", "Flatten Image"),
0759                                               i18n("The image contains hidden layers that will be lost. Do you want to flatten the image?"),
0760                                               QMessageBox::Yes | QMessageBox::No,
0761                                               QMessageBox::No);
0762 
0763             if (answer != QMessageBox::Yes) {
0764                 doIt = false;
0765             }
0766         }
0767 
0768         if (doIt) {
0769             image->flatten(m_view->activeNode());
0770         }
0771     }
0772 }
0773 
0774 inline bool isSelectionMask(KisNodeSP node) {
0775     return dynamic_cast<KisSelectionMask*>(node.data());
0776 }
0777 
0778 bool tryMergeSelectionMasks(KisNodeSP currentNode, KisImageSP image)
0779 {
0780     bool result = false;
0781 
0782     KisNodeSP prevNode = currentNode->prevSibling();
0783     if (isSelectionMask(currentNode) &&
0784             prevNode && isSelectionMask(prevNode)) {
0785 
0786         QList<KisNodeSP> mergedNodes;
0787         mergedNodes.append(currentNode);
0788         mergedNodes.append(prevNode);
0789 
0790         image->mergeMultipleLayers(mergedNodes, currentNode);
0791 
0792         result = true;
0793     }
0794 
0795     return result;
0796 }
0797 
0798 bool tryFlattenGroupLayer(KisNodeSP currentNode, KisImageSP image)
0799 {
0800     bool result = false;
0801 
0802     if (currentNode->inherits("KisGroupLayer")) {
0803         KisGroupLayer *layer = qobject_cast<KisGroupLayer*>(currentNode.data());
0804         KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(layer, false);
0805 
0806         image->flattenLayer(layer);
0807         result = true;
0808     }
0809 
0810     return result;
0811 }
0812 
0813 void KisLayerManager::mergeLayer()
0814 {
0815     KisImageSP image = m_view->image();
0816     if (!image) return;
0817 
0818     KisLayerSP layer = activeLayer();
0819     if (!layer) return;
0820 
0821     if (!m_view->blockUntilOperationsFinished(image)) return;
0822 
0823     QList<KisNodeSP> selectedNodes = m_view->nodeManager()->selectedNodes();
0824 
0825     // check if all the layers are a part of a locked group
0826     bool hasEditableLayer = false;
0827     Q_FOREACH (KisNodeSP node, selectedNodes) {
0828         if (node->isEditable(false)) {
0829             hasEditableLayer = true;
0830             break;
0831         }
0832     }
0833 
0834     if (!hasEditableLayer) {
0835         m_view->showFloatingMessage(
0836                     i18ncp("floating message in layer manager",
0837                           "Layer is locked", "Layers are locked", selectedNodes.size()),
0838                     QIcon(), 2000, KisFloatingMessage::Low);
0839         return;
0840     }
0841 
0842     if (selectedNodes.size() > 1) {
0843         image->mergeMultipleLayers(selectedNodes, m_view->activeNode());
0844     }
0845 
0846     else if (tryMergeSelectionMasks(m_view->activeNode(), image)) {
0847         // already done!
0848     } else if (tryFlattenGroupLayer(m_view->activeNode(), image)) {
0849         // already done!
0850     } else {
0851 
0852         if (!layer->prevSibling()) return;
0853         KisLayer *prevLayer = qobject_cast<KisLayer*>(layer->prevSibling().data());
0854         if (!prevLayer) return;
0855         if (prevLayer->userLocked()) {
0856             m_view->showFloatingMessage(
0857                         i18nc("floating message in layer manager when previous layer is locked",
0858                               "Layer is locked"),
0859                         QIcon(), 2000, KisFloatingMessage::Low);
0860         }
0861 
0862         else if (layer->metaData()->isEmpty() && prevLayer->metaData()->isEmpty()) {
0863             image->mergeDown(layer, KisMetaData::MergeStrategyRegistry::instance()->get("Drop"));
0864         }
0865         else {
0866             const KisMetaData::MergeStrategy* strategy = KisMetaDataMergeStrategyChooserWidget::showDialog(m_view->mainWindow());
0867             if (!strategy) return;
0868             image->mergeDown(layer, strategy);
0869         }
0870     }
0871 
0872     m_view->updateGUI();
0873 }
0874 
0875 void KisLayerManager::flattenLayer()
0876 {
0877     KisImageSP image = m_view->image();
0878     if (!image) return;
0879 
0880     KisLayerSP layer = activeLayer();
0881     if (!layer) return;
0882 
0883     if (!m_view->blockUntilOperationsFinished(image)) return;
0884     if (!m_view->nodeManager()->canModifyLayer(layer)) return;
0885 
0886     convertNodeToPaintLayer(layer);
0887     m_view->updateGUI();
0888 }
0889 
0890 void KisLayerManager::layersUpdated()
0891 {
0892     KisLayerSP layer = activeLayer();
0893     if (!layer) return;
0894 
0895     m_view->updateGUI();
0896 }
0897 
0898 void KisLayerManager::saveGroupLayers()
0899 {
0900     QStringList listMimeFilter = KisImportExportManager::supportedMimeTypes(KisImportExportManager::Export);
0901 
0902     KoDialog dlg;
0903     QWidget *page = new QWidget(&dlg);
0904     dlg.setMainWidget(page);
0905     QBoxLayout *layout = new QVBoxLayout(page);
0906 
0907     KisFileNameRequester *urlRequester = new KisFileNameRequester(page);
0908     urlRequester->setMode(KoFileDialog::SaveFile);
0909     urlRequester->setStartDir(QFileInfo(m_view->document()->path()).absolutePath());
0910     urlRequester->setMimeTypeFilters(listMimeFilter);
0911     urlRequester->setFileName(m_view->document()->path());
0912     layout->addWidget(urlRequester);
0913 
0914     QCheckBox *chkInvisible = new QCheckBox(i18n("Convert Invisible Groups"), page);
0915     chkInvisible->setChecked(false);
0916     layout->addWidget(chkInvisible);
0917     QCheckBox *chkDepth = new QCheckBox(i18n("Export Only Toplevel Groups"), page);
0918     chkDepth->setChecked(true);
0919     layout->addWidget(chkDepth);
0920 
0921     if (!dlg.exec()) return;
0922 
0923     QString path = urlRequester->fileName();
0924 
0925     if (path.isEmpty()) return;
0926 
0927     QFileInfo f(path);
0928 
0929     QString mimeType= KisMimeDatabase::mimeTypeForFile(f.fileName(), false);
0930     if (mimeType.isEmpty()) {
0931         mimeType = "image/png";
0932     }
0933     QString extension = KisMimeDatabase::suffixesForMimeType(mimeType).first();
0934     QString basename = f.completeBaseName();
0935 
0936     KisImageSP image = m_view->image();
0937     if (!image) return;
0938 
0939     KisSaveGroupVisitor v(image, chkInvisible->isChecked(), chkDepth->isChecked(), f.absolutePath(), basename, extension, mimeType);
0940     image->rootLayer()->accept(v);
0941 
0942 }
0943 
0944 bool KisLayerManager::activeLayerHasSelection()
0945 {
0946     return (activeLayer()->selection() != 0);
0947 }
0948 
0949 KisNodeSP KisLayerManager::addFileLayer(KisNodeSP activeNode)
0950 {
0951     QString basePath;
0952     QString path = m_view->document()->path();
0953     basePath = QFileInfo(path).absolutePath();
0954     KisImageWSP image = m_view->image();
0955 
0956     KisDlgFileLayer dlg(basePath, image->nextLayerName(i18n("File Layer")), m_view->mainWindow());
0957     dlg.resize(dlg.minimumSizeHint());
0958 
0959     if (dlg.exec() == QDialog::Accepted) {
0960         QString name = dlg.layerName();
0961         QString fileName = dlg.fileName();
0962 
0963         if(fileName.isEmpty()){
0964             QMessageBox::critical(m_view->mainWindow(), i18nc("@title:window", "Krita"), i18n("No file name specified"));
0965             return 0;
0966         }
0967 
0968         KisFileLayer::ScalingMethod scalingMethod = dlg.scaleToImageResolution();
0969         KisNodeSP node = new KisFileLayer(image, basePath, fileName, scalingMethod, name, OPACITY_OPAQUE_U8);
0970         addLayerCommon(activeNode, node, true, 0);
0971         return node;
0972     }
0973     return 0;
0974 }
0975 
0976 void updateLayerStyles(KisLayerSP layer, KisDlgLayerStyle *dlg, KoCanvasResourcesInterfaceSP canvasResroucesInterface)
0977 {
0978     KisSetLayerStyleCommand::updateLayerStyle(layer,
0979                                               dlg->style()->cloneWithResourcesSnapshot(
0980                                                   KisGlobalResourcesInterface::instance(),
0981                                                   canvasResroucesInterface));
0982 }
0983 
0984 void KisLayerManager::layerStyle()
0985 {
0986     KisImageWSP image = m_view->image();
0987     if (!image) return;
0988 
0989     KisLayerSP layer = activeLayer();
0990     if (!layer) return;
0991 
0992     if (!m_view->blockUntilOperationsFinished(image)) return;
0993     if (!m_view->nodeManager()->canModifyLayer(layer)) return;
0994 
0995     KoCanvasResourcesInterfaceSP canvasResroucesInterface = m_view->canvasBase()->resourceManager()->canvasResourcesInterface();
0996 
0997     KisPSDLayerStyleSP oldStyle;
0998     if (layer->layerStyle()) {
0999         oldStyle = layer->layerStyle()->clone().dynamicCast<KisPSDLayerStyle>();
1000 
1001     } else {
1002         oldStyle = toQShared(new KisPSDLayerStyle("", KisGlobalResourcesInterface::instance()))
1003                 ->cloneWithResourcesSnapshot(KisGlobalResourcesInterface::instance(),
1004                                              canvasResroucesInterface);
1005     }
1006 
1007     KisPSDLayerStyleSP newStyle = oldStyle->clone().dynamicCast<KisPSDLayerStyle>();
1008     newStyle->setResourcesInterface(KisGlobalResourcesInterface::instance());
1009 
1010     KisDlgLayerStyle dlg(newStyle, m_view->canvasResourceProvider());
1011 
1012     std::function<void ()> updateCall(std::bind(updateLayerStyles, layer, &dlg, canvasResroucesInterface));
1013     SignalToFunctionProxy proxy(updateCall);
1014     connect(&dlg, SIGNAL(configChanged()), &proxy, SLOT(start()));
1015 
1016     if (dlg.exec() == QDialog::Accepted) {
1017         KisPSDLayerStyleSP newStyle =
1018             dlg.style()->cloneWithResourcesSnapshot(KisGlobalResourcesInterface::instance(),
1019                                                     canvasResroucesInterface);
1020 
1021         KUndo2CommandSP command = toQShared(
1022                     new KisSetLayerStyleCommand(layer, oldStyle, newStyle));
1023 
1024         image->postExecutionUndoAdapter()->addCommand(command);
1025     }
1026 }
1027