File indexing completed on 2024-05-19 04:28:58

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         QString scalingFilterOld = fileLayer->scalingFilter();
0305         KisDlgFileLayer dlg(basePath, fileLayer->name(), m_view->mainWindow());
0306         dlg.setCaption(i18n("File Layer Properties"));
0307         dlg.setFileName(fileNameOld);
0308         dlg.setScalingMethod(scalingMethodOld);
0309         dlg.setScalingFilter(scalingFilterOld);
0310 
0311         if (dlg.exec() == QDialog::Accepted) {
0312             const QString fileNameNew = dlg.fileName();
0313             KisFileLayer::ScalingMethod scalingMethodNew = dlg.scaleToImageResolution();
0314             QString scalingFilterNew = dlg.scalingFilter();
0315 
0316             if(fileNameNew.isEmpty()){
0317                 QMessageBox::critical(m_view->mainWindow(), i18nc("@title:window", "Krita"), i18n("No file name specified"));
0318                 return;
0319             }
0320             fileLayer->setName(dlg.layerName());
0321 
0322             if (fileNameOld!= fileNameNew || scalingMethodOld != scalingMethodNew || scalingFilterOld != scalingFilterNew) {
0323                 KisChangeFileLayerCmd *cmd
0324                         = new KisChangeFileLayerCmd(fileLayer,
0325                                                     basePath,
0326                                                     fileNameOld,
0327                                                     scalingMethodOld,
0328                                                     scalingFilterOld,
0329                                                     basePath,
0330                                                     fileNameNew,
0331                                                     scalingMethodNew,
0332                                                     scalingFilterNew);
0333                 m_view->undoAdapter()->addCommand(cmd);
0334             }
0335         }
0336     } else { // If layer == normal painting layer, vector layer, or group layer
0337         QList<KisNodeSP> selectedNodes = m_view->nodeManager()->selectedNodes();
0338 
0339         KisDlgLayerProperties *dialog = new KisDlgLayerProperties(selectedNodes, m_view, m_view->canvas());
0340         dialog->resize(dialog->minimumSizeHint());
0341         dialog->setAttribute(Qt::WA_DeleteOnClose);
0342         Qt::WindowFlags flags = dialog->windowFlags();
0343 #ifdef Q_OS_ANDROID
0344         // a Qt::Tool window seems incapable of receiving keyboard focus
0345         dialog->setWindowFlags(flags | Qt::Dialog);
0346 #else
0347         dialog->setWindowFlags(flags | Qt::Tool | Qt::Dialog);
0348 #endif
0349         dialog->show();
0350         dialog->activateWindow();
0351     }
0352 }
0353 
0354 void KisLayerManager::changeCloneSource()
0355 {
0356     QList<KisNodeSP> selectedNodes = m_view->nodeManager()->selectedNodes();
0357     if (selectedNodes.isEmpty()) {
0358         return;
0359     }
0360 
0361     QList<KisCloneLayerSP> cloneLayers;
0362     KisNodeSP node;
0363     Q_FOREACH (node, selectedNodes) {
0364         KisCloneLayerSP cloneLayer(qobject_cast<KisCloneLayer *>(node.data()));
0365         if (cloneLayer) {
0366             cloneLayers << cloneLayer;
0367         }
0368     }
0369 
0370     if (cloneLayers.isEmpty()) {
0371         return;
0372     }
0373 
0374     if (!m_view->nodeManager()->canModifyLayers(implicitCastList<KisNodeSP>(cloneLayers))) return;
0375 
0376     KisDlgChangeCloneSource *dialog = new KisDlgChangeCloneSource(cloneLayers, m_view);
0377     dialog->setCaption(i18n("Change Clone Layer"));
0378     dialog->resize(dialog->minimumSizeHint());
0379     dialog->setAttribute(Qt::WA_DeleteOnClose);
0380     Qt::WindowFlags flags = dialog->windowFlags();
0381     dialog->setWindowFlags(flags | Qt::Tool | Qt::Dialog);
0382     dialog->show();
0383     dialog->activateWindow();
0384 }
0385 
0386 void KisLayerManager::copyLayerStyle()
0387 {
0388     KisImageSP image = m_view->image();
0389     if (!image) return;
0390 
0391     KisLayerSP layer = activeLayer();
0392     if (!layer) return;
0393 
0394     KisPSDLayerStyleSP layerStyle = layer->layerStyle();
0395     if (!layerStyle) return;
0396 
0397     KisAslLayerStyleSerializer serializer;
0398     serializer.setStyles(QVector<KisPSDLayerStyleSP>() << layerStyle);
0399     QString psdxml = serializer.formPsdXmlDocument().toString();
0400 
0401     if (!psdxml.isEmpty()) {
0402         QMimeData *mimeData = new QMimeData;
0403 
0404         mimeData->setText(psdxml);
0405         mimeData->setData("application/x-krita-layer-style", psdxml.toUtf8());
0406 
0407         QGuiApplication::clipboard()->setMimeData(mimeData);
0408     }
0409 }
0410 
0411 void KisLayerManager::pasteLayerStyle()
0412 {
0413     KisImageSP image = m_view->image();
0414     if (!image) return;
0415 
0416     KisLayerSP layer = activeLayer();
0417     if (!layer) return;
0418 
0419     QString aslXml;
0420 
0421     if (KisClipboard::instance()->hasLayerStyles()) {
0422         aslXml = QString::fromUtf8(QGuiApplication::clipboard()->mimeData()->data("application/x-krita-layer-style"));
0423     } else {
0424         aslXml = QGuiApplication::clipboard()->text();
0425     }
0426 
0427     if (aslXml.isEmpty()) return;
0428 
0429     QDomDocument aslDoc;
0430     if (!aslDoc.setContent(aslXml)) return;
0431 
0432     KisAslLayerStyleSerializer serializer;
0433     serializer.registerPSDPattern(aslDoc);
0434     serializer.readFromPSDXML(aslDoc);
0435 
0436     if (serializer.styles().size() != 1) return;
0437 
0438     KisPSDLayerStyleSP newStyle = serializer.styles().first()->cloneWithResourcesSnapshot(
0439         KisGlobalResourcesInterface::instance(),
0440         m_view->canvasBase()->resourceManager()->canvasResourcesInterface());
0441     KUndo2Command *cmd = new KisSetLayerStyleCommand(layer, layer->layerStyle(), newStyle);
0442 
0443     KisProcessingApplicator::runSingleCommandStroke(image, cmd);
0444     image->waitForDone();
0445 }
0446 
0447 void KisLayerManager::convertNodeToPaintLayer(KisNodeSP source)
0448 {
0449     KisImageWSP image = m_view->image();
0450     if (!image) return;
0451 
0452     // this precondition must be checked at higher level
0453     KIS_SAFE_ASSERT_RECOVER_RETURN(source->isEditable(false));
0454 
0455     KisLayer *srcLayer = qobject_cast<KisLayer*>(source.data());
0456     if (srcLayer && (srcLayer->inherits("KisGroupLayer") || srcLayer->layerStyle() || srcLayer->childCount() > 0)) {
0457         image->flattenLayer(srcLayer);
0458         return;
0459     }
0460 
0461     (void) KisLayerUtils::convertToPaintLayer(image, source);
0462 }
0463 
0464 void KisLayerManager::convertGroupToAnimated()
0465 {
0466     KisGroupLayerSP group = dynamic_cast<KisGroupLayer*>(activeLayer().data());
0467     if (group.isNull()) return;
0468 
0469     if (!m_view->nodeManager()->canModifyLayer(group)) return;
0470 
0471     KisPaintLayerSP animatedLayer = new KisPaintLayer(m_view->image(), group->name(), OPACITY_OPAQUE_U8);
0472     animatedLayer->enableAnimation();
0473     KisRasterKeyframeChannel *contentChannel = dynamic_cast<KisRasterKeyframeChannel*>(
0474                 animatedLayer->getKeyframeChannel(KisKeyframeChannel::Raster.id(), true));
0475     KIS_ASSERT_RECOVER_RETURN(contentChannel);
0476 
0477     KisNodeSP child = group->firstChild();
0478     int time = 0;
0479     while (child) {
0480         contentChannel->importFrame(time, child->projection(), NULL);
0481         time++;
0482 
0483         child = child->nextSibling();
0484     }
0485 
0486     m_commandsAdapter->beginMacro(kundo2_i18n("Convert to an animated layer"));
0487     m_commandsAdapter->addNode(animatedLayer, group->parent(), group);
0488     m_commandsAdapter->removeNode(group);
0489     m_commandsAdapter->endMacro();
0490 }
0491 
0492 void KisLayerManager::convertLayerToFileLayer(KisNodeSP source)
0493 {
0494     KisImageSP image = m_view->image();
0495     if (!image) return;
0496 
0497     // this precondition must be checked at higher level
0498     KIS_SAFE_ASSERT_RECOVER_RETURN(source->isEditable(false));
0499 
0500     QStringList listMimeFilter = KisImportExportManager::supportedMimeTypes(KisImportExportManager::Export);
0501 
0502     KoDialog dlg;
0503     QWidget *page = new QWidget(&dlg);
0504     dlg.setMainWidget(page);
0505     QBoxLayout *layout = new QVBoxLayout(page);
0506     dlg.setWindowTitle(i18n("Save layers to..."));
0507     QLabel *lbl = new QLabel(i18n("Choose the location where the layer will be saved to. The new file layer will then reference this location."));
0508     lbl->setWordWrap(true);
0509     layout->addWidget(lbl);
0510     KisFileNameRequester *urlRequester = new KisFileNameRequester(page);
0511     urlRequester->setMode(KoFileDialog::SaveFile);
0512     urlRequester->setMimeTypeFilters(listMimeFilter);
0513     urlRequester->setFileName(m_view->document()->path());
0514     if (!m_view->document()->path().isEmpty()) {
0515         QFileInfo location = QFileInfo(m_view->document()->path()).completeBaseName();
0516         location.setFile(location.dir(), location.completeBaseName() + "_" + source->name() + ".png");
0517         urlRequester->setFileName(location.absoluteFilePath());
0518     }
0519     else {
0520         const QFileInfo location = QFileInfo(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
0521         const QString proposedFileName = QDir(location.absoluteFilePath()).absoluteFilePath(source->name() + ".png");
0522         urlRequester->setFileName(proposedFileName);
0523     }
0524 
0525     layout->addWidget(urlRequester);
0526     if (!dlg.exec()) return;
0527 
0528     QString path = urlRequester->fileName();
0529 
0530     if (path.isEmpty()) return;
0531 
0532     QFileInfo f(path);
0533 
0534     QString mimeType= KisMimeDatabase::mimeTypeForFile(f.fileName());
0535     if (mimeType.isEmpty()) {
0536         mimeType = "image/png";
0537     }
0538     QScopedPointer<KisDocument> doc(KisPart::instance()->createDocument());
0539 
0540     QRect bounds = source->exactBounds();
0541     if (bounds.isEmpty()) {
0542         bounds = image->bounds();
0543     }
0544     KisImageSP dst = new KisImage(doc->createUndoStore(),
0545                                   image->width(),
0546                                   image->height(),
0547                                   image->projection()->compositionSourceColorSpace(),
0548                                   source->name());
0549     dst->setResolution(image->xRes(), image->yRes());
0550     doc->setFileBatchMode(false);
0551     doc->setCurrentImage(dst);
0552     KisNodeSP node = source->clone();
0553     dst->addNode(node);
0554     dst->initialRefreshGraph();
0555     dst->cropImage(bounds);
0556     dst->waitForDone();
0557 
0558     bool r = doc->exportDocumentSync(path, mimeType.toLatin1());
0559     if (!r) {
0560 
0561         qWarning() << "Converting layer to file layer. path:"<< path << "gave errors" << doc->errorMessage();
0562     } else {
0563         QString basePath = QFileInfo(m_view->document()->path()).absolutePath();
0564         QString relativePath = QDir(basePath).relativeFilePath(path);
0565         KisFileLayer *fileLayer = new KisFileLayer(image, basePath, relativePath, KisFileLayer::None, "Bicubic", source->name(), OPACITY_OPAQUE_U8);
0566         fileLayer->setX(bounds.x());
0567         fileLayer->setY(bounds.y());
0568         KisNodeSP dstParent = source->parent();
0569         KisNodeSP dstAboveThis = source->prevSibling();
0570         m_commandsAdapter->beginMacro(kundo2_i18n("Convert to a file layer"));
0571         m_commandsAdapter->removeNode(source);
0572         m_commandsAdapter->addNode(fileLayer, dstParent, dstAboveThis);
0573         m_commandsAdapter->endMacro();
0574     }
0575     doc->closePath(false);
0576 }
0577 
0578 void KisLayerManager::adjustLayerPosition(KisNodeSP node, KisNodeSP activeNode, KisNodeSP &parent, KisNodeSP &above)
0579 {
0580     Q_ASSERT(activeNode);
0581 
0582     parent = activeNode;
0583     above = parent->lastChild();
0584 
0585     if (parent->inherits("KisGroupLayer") && parent->collapsed()) {
0586         above = parent;
0587         parent = parent->parent();
0588         return;
0589     }
0590 
0591     while (parent &&
0592            (!parent->allowAsChild(node) || !parent->isEditable(false))) {
0593 
0594         above = parent;
0595         parent = parent->parent();
0596     }
0597 
0598     if (!parent) {
0599         warnKrita << "KisLayerManager::adjustLayerPosition:"
0600                   << "No node accepted newly created node";
0601 
0602         parent = m_view->image()->root();
0603         above = parent->lastChild();
0604     }
0605 }
0606 
0607 void KisLayerManager::addLayerCommon(KisNodeSP activeNode, KisNodeSP layer, bool updateImage, KisProcessingApplicator *applicator)
0608 {
0609     KisNodeSP parent;
0610     KisNodeSP above;
0611     adjustLayerPosition(layer, activeNode, parent, above);
0612 
0613     KisGroupLayer *group = dynamic_cast<KisGroupLayer*>(parent.data());
0614     const bool parentForceUpdate = group && !group->projectionIsValid();
0615     updateImage |= parentForceUpdate;
0616 
0617     m_commandsAdapter->addNodeAsync(layer, parent, above, updateImage, updateImage, applicator);
0618 }
0619 
0620 KisLayerSP KisLayerManager::addPaintLayer(KisNodeSP activeNode)
0621 {
0622     KisImageWSP image = m_view->image();    
0623     KisLayerSP layer = new KisPaintLayer(image.data(),  image->nextLayerName( i18n("Paint Layer") ), OPACITY_OPAQUE_U8, image->colorSpace());
0624 
0625     KisConfig cfg(true);
0626     layer->setPinnedToTimeline(cfg.autoPinLayersToTimeline());
0627 
0628     addLayerCommon(activeNode, layer, false, 0);
0629 
0630     return layer;
0631 }
0632 
0633 KisNodeSP KisLayerManager::addGroupLayer(KisNodeSP activeNode)
0634 {
0635     KisImageWSP image = m_view->image();
0636     KisGroupLayerSP group = new KisGroupLayer(image.data(), image->nextLayerName( i18nc("A group of layers", "Group") ), OPACITY_OPAQUE_U8);
0637     addLayerCommon(activeNode, group, false, 0);
0638     return group;
0639 }
0640 
0641 KisNodeSP KisLayerManager::addCloneLayer(KisNodeList nodes)
0642 {
0643     KisImageWSP image = m_view->image();
0644 
0645     KisNodeList filteredNodes = KisLayerUtils::sortAndFilterMergeableInternalNodes(nodes, false);
0646     if (filteredNodes.isEmpty()) return KisNodeSP();
0647 
0648     KisNodeSP newAbove = filteredNodes.last();
0649 
0650     KisNodeSP node, lastClonedNode;
0651     Q_FOREACH (node, filteredNodes) {
0652         lastClonedNode = new KisCloneLayer(qobject_cast<KisLayer*>(node.data()), image.data(), image->nextLayerName( i18n("Clone Layer") ), OPACITY_OPAQUE_U8);
0653         addLayerCommon(newAbove, lastClonedNode, true, 0 );
0654     }
0655 
0656     return lastClonedNode;
0657 }
0658 
0659 KisNodeSP KisLayerManager::addShapeLayer(KisNodeSP activeNode)
0660 {
0661     if (!m_view) return 0;
0662     if (!m_view->document()) return 0;
0663 
0664     KisImageWSP image = m_view->image();
0665     KisShapeLayerSP layer = new KisShapeLayer(m_view->document()->shapeController(), image.data(), image->nextLayerName(i18n("Vector Layer")), OPACITY_OPAQUE_U8);
0666 
0667     addLayerCommon(activeNode, layer, false, 0);
0668 
0669     return layer;
0670 }
0671 
0672 KisNodeSP KisLayerManager::addAdjustmentLayer(KisNodeSP activeNode)
0673 {
0674     KisImageWSP image = m_view->image();
0675 
0676     KisSelectionSP selection = m_view->selection();
0677 
0678     KisProcessingApplicator applicator(image, 0, KisProcessingApplicator::NONE,
0679                                        KisImageSignalVector(),
0680                                        kundo2_i18n("Add Layer"));
0681 
0682 
0683     KisAdjustmentLayerSP adjl = addAdjustmentLayer(activeNode, QString(), 0, selection, &applicator);
0684 
0685     KisPaintDeviceSP previewDevice = new KisPaintDevice(*adjl->original());
0686 
0687     KisDlgAdjustmentLayer dlg(adjl, adjl.data(), previewDevice, image->nextLayerName(i18n("Filter Layer")), i18n("New Filter Layer"), m_view, qApp->activeWindow());
0688     dlg.resize(dlg.minimumSizeHint());
0689 
0690     // ensure that the device may be free'd by the dialog
0691     // when it is not needed anymore
0692     previewDevice = 0;
0693 
0694     if (dlg.exec() != QDialog::Accepted || adjl->filter().isNull()) {
0695         // XXX: add messagebox warning if there's no filter set!
0696         applicator.cancel();
0697     } else {
0698         applicator.applyCommand(new KisNodeRenameCommand(adjl, adjl->name(), dlg.layerName()));
0699         applicator.end();
0700     }
0701 
0702     return adjl;
0703 }
0704 
0705 KisAdjustmentLayerSP KisLayerManager::addAdjustmentLayer(KisNodeSP activeNode, const QString & name,
0706                                                          KisFilterConfigurationSP  filter,
0707                                                          KisSelectionSP selection,
0708                                                          KisProcessingApplicator *applicator)
0709 {
0710     KisImageWSP image = m_view->image();
0711     KisAdjustmentLayerSP layer = new KisAdjustmentLayer(image, name, filter ? filter->cloneWithResourcesSnapshot() : 0, selection);
0712     addLayerCommon(activeNode, layer, true, applicator);
0713 
0714     return layer;
0715 }
0716 
0717 KisGeneratorLayerSP KisLayerManager::addGeneratorLayer(KisNodeSP activeNode, const QString &name, KisFilterConfigurationSP filter, KisSelectionSP selection, KisProcessingApplicator *applicator)
0718 {
0719     KisImageWSP image = m_view->image();
0720     auto layer = new KisGeneratorLayer(image, name, filter, selection);
0721     addLayerCommon(activeNode, layer, true, applicator);
0722 
0723     return layer;
0724 }
0725 
0726 KisNodeSP KisLayerManager::addGeneratorLayer(KisNodeSP activeNode)
0727 {
0728     KisImageWSP image = m_view->image();
0729     KisSelectionSP selection = m_view->selection();
0730     QColor currentForeground = m_view->canvasResourceProvider()->fgColor().toQColor();
0731 
0732     KisProcessingApplicator applicator(image, 0, KisProcessingApplicator::NONE, KisImageSignalVector(), kundo2_i18n("Add Layer"));
0733 
0734     KisGeneratorLayerSP node = addGeneratorLayer(activeNode, QString(), nullptr, selection, &applicator);
0735 
0736     KisDlgGeneratorLayer dlg(image->nextLayerName(i18n("Fill Layer")), m_view, m_view->mainWindow(), node, nullptr, applicator.getStroke());
0737     KisFilterConfigurationSP defaultConfig = dlg.configuration();
0738     defaultConfig->setProperty("color", currentForeground);
0739     dlg.setConfiguration(defaultConfig);
0740 
0741     if (dlg.exec() == QDialog::Accepted) {
0742         applicator.applyCommand(new KisNodeRenameCommand(node, node->name(), dlg.layerName()));
0743         applicator.end();
0744         return node;
0745     }
0746     else {
0747         applicator.cancel();
0748         return nullptr;
0749     }
0750 }
0751 
0752 void KisLayerManager::flattenImage()
0753 {
0754     KisImageSP image = m_view->image();
0755 
0756     if (!m_view->blockUntilOperationsFinished(image)) return;
0757 
0758     if (image) {
0759         bool doIt = true;
0760 
0761         if (image->nHiddenLayers() > 0) {
0762             int answer = QMessageBox::warning(m_view->mainWindow(),
0763                                               i18nc("@title:window", "Flatten Image"),
0764                                               i18n("The image contains hidden layers that will be lost. Do you want to flatten the image?"),
0765                                               QMessageBox::Yes | QMessageBox::No,
0766                                               QMessageBox::No);
0767 
0768             if (answer != QMessageBox::Yes) {
0769                 doIt = false;
0770             }
0771         }
0772 
0773         if (doIt) {
0774             image->flatten(m_view->activeNode());
0775         }
0776     }
0777 }
0778 
0779 inline bool isSelectionMask(KisNodeSP node) {
0780     return dynamic_cast<KisSelectionMask*>(node.data());
0781 }
0782 
0783 bool tryMergeSelectionMasks(KisNodeSP currentNode, KisImageSP image)
0784 {
0785     bool result = false;
0786 
0787     KisNodeSP prevNode = currentNode->prevSibling();
0788     if (isSelectionMask(currentNode) &&
0789             prevNode && isSelectionMask(prevNode)) {
0790 
0791         QList<KisNodeSP> mergedNodes;
0792         mergedNodes.append(currentNode);
0793         mergedNodes.append(prevNode);
0794 
0795         image->mergeMultipleLayers(mergedNodes, currentNode);
0796 
0797         result = true;
0798     }
0799 
0800     return result;
0801 }
0802 
0803 bool tryFlattenGroupLayer(KisNodeSP currentNode, KisImageSP image)
0804 {
0805     bool result = false;
0806 
0807     if (currentNode->inherits("KisGroupLayer")) {
0808         KisGroupLayer *layer = qobject_cast<KisGroupLayer*>(currentNode.data());
0809         KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(layer, false);
0810 
0811         image->flattenLayer(layer);
0812         result = true;
0813     }
0814 
0815     return result;
0816 }
0817 
0818 void KisLayerManager::mergeLayer()
0819 {
0820     KisImageSP image = m_view->image();
0821     if (!image) return;
0822 
0823     KisLayerSP layer = activeLayer();
0824     if (!layer) return;
0825 
0826     if (!m_view->blockUntilOperationsFinished(image)) return;
0827 
0828     QList<KisNodeSP> selectedNodes = m_view->nodeManager()->selectedNodes();
0829 
0830     // check if all the layers are a part of a locked group
0831     bool hasEditableLayer = false;
0832     Q_FOREACH (KisNodeSP node, selectedNodes) {
0833         if (node->isEditable(false)) {
0834             hasEditableLayer = true;
0835             break;
0836         }
0837     }
0838 
0839     if (!hasEditableLayer) {
0840         m_view->showFloatingMessage(
0841                     i18ncp("floating message in layer manager",
0842                           "Layer is locked", "Layers are locked", selectedNodes.size()),
0843                     QIcon(), 2000, KisFloatingMessage::Low);
0844         return;
0845     }
0846 
0847     if (selectedNodes.size() > 1) {
0848         image->mergeMultipleLayers(selectedNodes, m_view->activeNode());
0849     }
0850 
0851     else if (tryMergeSelectionMasks(m_view->activeNode(), image)) {
0852         // already done!
0853     } else if (tryFlattenGroupLayer(m_view->activeNode(), image)) {
0854         // already done!
0855     } else {
0856 
0857         if (!layer->prevSibling()) return;
0858         KisLayer *prevLayer = qobject_cast<KisLayer*>(layer->prevSibling().data());
0859         if (!prevLayer) return;
0860 
0861         if (prevLayer->userLocked()) {
0862             m_view->showFloatingMessage(
0863                         i18nc("floating message in layer manager when previous layer is locked",
0864                               "Layer is locked"),
0865                         QIcon(), 2000, KisFloatingMessage::Low);
0866         } else {
0867             const KisMetaData::MergeStrategy* strategy = nullptr;
0868 
0869             if (layer->metaData()->isEmpty() && prevLayer->metaData()->isEmpty()) {
0870                 strategy = KisMetaData::MergeStrategyRegistry::instance()->get("Drop");
0871             }
0872             else {
0873                 strategy = KisMetaDataMergeStrategyChooserWidget::showDialog(m_view->mainWindow());
0874             }
0875 
0876             if (!strategy) return;
0877 
0878             if (!layer->isAnimated() && prevLayer->isAnimated()) {
0879                 m_view->showFloatingMessage(
0880                             i18nc("floating message in layer manager when trying to merge a non-animated layer into an animated one",
0881                                   "Non-animated layer is merged into the current frame. To merge it into the whole clip, create at least one frame"),
0882                             QIcon(), 5000, KisFloatingMessage::Medium);
0883             }
0884             image->mergeDown(layer, strategy);
0885         }
0886     }
0887 
0888     m_view->updateGUI();
0889 }
0890 
0891 void KisLayerManager::flattenLayer()
0892 {
0893     KisImageSP image = m_view->image();
0894     if (!image) return;
0895 
0896     KisLayerSP layer = activeLayer();
0897     if (!layer) return;
0898 
0899     if (!m_view->blockUntilOperationsFinished(image)) return;
0900     if (!m_view->nodeManager()->canModifyLayer(layer)) return;
0901 
0902     convertNodeToPaintLayer(layer);
0903     m_view->updateGUI();
0904 }
0905 
0906 void KisLayerManager::layersUpdated()
0907 {
0908     KisLayerSP layer = activeLayer();
0909     if (!layer) return;
0910 
0911     m_view->updateGUI();
0912 }
0913 
0914 void KisLayerManager::saveGroupLayers()
0915 {
0916     QStringList listMimeFilter = KisImportExportManager::supportedMimeTypes(KisImportExportManager::Export);
0917 
0918     KoDialog dlg;
0919     QWidget *page = new QWidget(&dlg);
0920     dlg.setMainWidget(page);
0921     QBoxLayout *layout = new QVBoxLayout(page);
0922 
0923     KisFileNameRequester *urlRequester = new KisFileNameRequester(page);
0924     urlRequester->setMode(KoFileDialog::SaveFile);
0925     urlRequester->setStartDir(QFileInfo(m_view->document()->path()).absolutePath());
0926     urlRequester->setMimeTypeFilters(listMimeFilter);
0927     urlRequester->setFileName(m_view->document()->path());
0928     layout->addWidget(urlRequester);
0929 
0930     QCheckBox *chkInvisible = new QCheckBox(i18n("Convert Invisible Groups"), page);
0931     chkInvisible->setChecked(false);
0932     layout->addWidget(chkInvisible);
0933     QCheckBox *chkDepth = new QCheckBox(i18n("Export Only Toplevel Groups"), page);
0934     chkDepth->setChecked(true);
0935     layout->addWidget(chkDepth);
0936 
0937     if (!dlg.exec()) return;
0938 
0939     QString path = urlRequester->fileName();
0940 
0941     if (path.isEmpty()) return;
0942 
0943     QFileInfo f(path);
0944 
0945     QString mimeType= KisMimeDatabase::mimeTypeForFile(f.fileName(), false);
0946     if (mimeType.isEmpty()) {
0947         mimeType = "image/png";
0948     }
0949     QString extension = KisMimeDatabase::suffixesForMimeType(mimeType).first();
0950     QString basename = f.completeBaseName();
0951 
0952     KisImageSP image = m_view->image();
0953     if (!image) return;
0954 
0955     KisSaveGroupVisitor v(image, chkInvisible->isChecked(), chkDepth->isChecked(), f.absolutePath(), basename, extension, mimeType);
0956     image->rootLayer()->accept(v);
0957 
0958 }
0959 
0960 bool KisLayerManager::activeLayerHasSelection()
0961 {
0962     return (activeLayer()->selection() != 0);
0963 }
0964 
0965 KisNodeSP KisLayerManager::addFileLayer(KisNodeSP activeNode)
0966 {
0967     QString basePath;
0968     QString path = m_view->document()->path();
0969     basePath = QFileInfo(path).absolutePath();
0970     KisImageWSP image = m_view->image();
0971 
0972     KisDlgFileLayer dlg(basePath, image->nextLayerName(i18n("File Layer")), m_view->mainWindow());
0973     dlg.resize(dlg.minimumSizeHint());
0974 
0975     if (dlg.exec() == QDialog::Accepted) {
0976         QString name = dlg.layerName();
0977         QString fileName = dlg.fileName();
0978 
0979         if(fileName.isEmpty()){
0980             QMessageBox::critical(m_view->mainWindow(), i18nc("@title:window", "Krita"), i18n("No file name specified"));
0981             return 0;
0982         }
0983 
0984         KisFileLayer::ScalingMethod scalingMethod = dlg.scaleToImageResolution();
0985         QString scalingFilter = dlg.scalingFilter();
0986         KisNodeSP node = new KisFileLayer(image, basePath, fileName, scalingMethod, scalingFilter, name, OPACITY_OPAQUE_U8);
0987         addLayerCommon(activeNode, node, true, 0);
0988         return node;
0989     }
0990     return 0;
0991 }
0992 
0993 void updateLayerStyles(KisLayerSP layer, KisDlgLayerStyle *dlg, KoCanvasResourcesInterfaceSP canvasResourcesInterface)
0994 {
0995     KisSetLayerStyleCommand::updateLayerStyle(layer,
0996                                               dlg->style()->cloneWithResourcesSnapshot(
0997                                                   KisGlobalResourcesInterface::instance(),
0998                                                   canvasResourcesInterface));
0999 }
1000 
1001 void KisLayerManager::layerStyle()
1002 {
1003     KisImageWSP image = m_view->image();
1004     if (!image) return;
1005 
1006     KisLayerSP layer = activeLayer();
1007     if (!layer) return;
1008 
1009     if (!m_view->blockUntilOperationsFinished(image)) return;
1010     if (!m_view->nodeManager()->canModifyLayer(layer)) return;
1011 
1012     KoCanvasResourcesInterfaceSP canvasResourcesInterface = m_view->canvasBase()->resourceManager()->canvasResourcesInterface();
1013 
1014     KisPSDLayerStyleSP oldStyle;
1015     if (layer->layerStyle()) {
1016         oldStyle = layer->layerStyle()->clone().dynamicCast<KisPSDLayerStyle>();
1017 
1018     } else {
1019         oldStyle = toQShared(new KisPSDLayerStyle("", KisGlobalResourcesInterface::instance()))
1020                 ->cloneWithResourcesSnapshot(KisGlobalResourcesInterface::instance(),
1021                                              canvasResourcesInterface);
1022     }
1023 
1024     KisPSDLayerStyleSP newStyle = oldStyle->clone().dynamicCast<KisPSDLayerStyle>();
1025     // We want to also change the UUID, else it might be considered the same style after save and won't load correctly
1026     newStyle->setUuid(QUuid::createUuid());
1027     newStyle->setResourcesInterface(KisGlobalResourcesInterface::instance());
1028 
1029     KisDlgLayerStyle dlg(newStyle, m_view->canvasResourceProvider());
1030 
1031     std::function<void ()> updateCall(std::bind(updateLayerStyles, layer, &dlg, canvasResourcesInterface));
1032     SignalToFunctionProxy proxy(updateCall);
1033     connect(&dlg, SIGNAL(configChanged()), &proxy, SLOT(start()));
1034 
1035     if (dlg.exec() == QDialog::Accepted) {
1036         KisPSDLayerStyleSP newStyle =
1037             dlg.style()->cloneWithResourcesSnapshot(KisGlobalResourcesInterface::instance(),
1038                                                     canvasResourcesInterface);
1039 
1040         KUndo2CommandSP command = toQShared(
1041                     new KisSetLayerStyleCommand(layer, oldStyle, newStyle));
1042 
1043         image->postExecutionUndoAdapter()->addCommand(command);
1044     }
1045 }
1046