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

0001 /*
0002  *  SPDX-FileCopyrightText: 2006 Boudewijn Rempt <boud@valdyas.org>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_import_catcher.h"
0008 #include <kis_debug.h>
0009 
0010 #include <klocalizedstring.h>
0011 #include <QFileInfo>
0012 
0013 #include <KisImportExportManager.h>
0014 
0015 #include "kis_node_manager.h"
0016 #include "kis_count_visitor.h"
0017 #include "KisViewManager.h"
0018 #include "KisDocument.h"
0019 #include "kis_image.h"
0020 #include "kis_layer.h"
0021 #include "kis_painter.h"
0022 #include "kis_selection.h"
0023 #include "kis_node_commands_adapter.h"
0024 #include "kis_group_layer.h"
0025 #include "kis_progress_widget.h"
0026 #include "kis_config.h"
0027 #include "KisPart.h"
0028 #include "kis_shape_layer.h"
0029 
0030 struct KisImportCatcher::Private
0031 {
0032 public:
0033     KisDocument* doc;
0034     KisViewManager* view;
0035     QString path;
0036     QString layerType;
0037     int numLayersImported;
0038 
0039     QString prettyLayerName(QString layerName) const;
0040     void importAsPaintLayer(KisPaintDeviceSP device, QString layerName);
0041     void importShapeLayer(KisShapeLayerSP shapeLayer);
0042 };
0043 
0044 QString KisImportCatcher::Private::prettyLayerName(QString layerName) const
0045 {
0046     QString name = QFileInfo(path).fileName();
0047     QString fileName = !name.isEmpty() ? name : path;
0048     return (layerName.isEmpty() || layerName == "Background") ? fileName : layerName;
0049 }
0050 
0051 void KisImportCatcher::Private::importAsPaintLayer(KisPaintDeviceSP device, QString layerName)
0052 {
0053     KisLayerSP newLayer = new KisPaintLayer(view->image(),
0054                                             layerName,
0055                                             OPACITY_OPAQUE_U8,
0056                                             device);
0057 
0058     KisNodeSP parent = nullptr;
0059     KisLayerSP currentActiveLayer = view->activeLayer();
0060 
0061     if (currentActiveLayer) {
0062         parent = currentActiveLayer->parent();
0063     }
0064 
0065     if (parent.isNull()) {
0066         parent = view->image()->rootLayer();
0067     }
0068 
0069     KisNodeCommandsAdapter adapter(view);
0070     adapter.addNode(newLayer, parent, currentActiveLayer);
0071 }
0072 
0073 void KisImportCatcher::Private::importShapeLayer(KisShapeLayerSP shapeLayer)
0074 {
0075     KisNodeSP parent = nullptr;
0076     KisLayerSP currentActiveLayer = view->activeLayer();
0077 
0078     if (currentActiveLayer) {
0079         parent = currentActiveLayer->parent();
0080     }
0081 
0082     if (parent.isNull()) {
0083         parent = view->image()->rootLayer();
0084     }
0085 
0086     KisNodeCommandsAdapter adapter(view);
0087     adapter.addNode(shapeLayer, parent, currentActiveLayer);
0088 }
0089 
0090 KisImportCatcher::KisImportCatcher(const QString &path, KisViewManager *view, const QString &layerType)
0091     : m_d(new Private)
0092 {
0093     m_d->doc = KisPart::instance()->createDocument();
0094     m_d->view = view;
0095     m_d->path = path;
0096     m_d->layerType = layerType;
0097     m_d->numLayersImported = 0;
0098 
0099     connect(m_d->doc, SIGNAL(sigLoadingFinished()), this, SLOT(slotLoadingFinished()));
0100     bool result = m_d->doc->openPath(path, KisDocument::DontAddToRecent);
0101 
0102     if (!result) {
0103         deleteMyself();
0104     }
0105 }
0106 
0107 void KisImportCatcher::slotLoadingFinished()
0108 {
0109     KisImageWSP importedImage = m_d->doc->image();
0110     importedImage->waitForDone();
0111 
0112     if (importedImage && importedImage->bounds().isValid()) {
0113         if (m_d->layerType == "KisPaintLayer") {
0114             QStringList list;
0115             list << "KisLayer";
0116             KoProperties props;
0117 
0118             Q_FOREACH(KisNodeSP node, importedImage->rootLayer()->childNodes(list, props)) {
0119                 // we need to pass a copied device to make sure it is not reset
0120                 // on image's destruction
0121                 KisPaintDeviceSP dev = new KisPaintDevice(*node->projection());
0122                 adaptClipToImageColorSpace(dev, m_d->view->image());
0123                 m_d->importAsPaintLayer(dev, m_d->prettyLayerName(node->name()));
0124                 m_d->numLayersImported++;
0125             }
0126         }
0127         else if (m_d->layerType == "KisShapeLayer") {
0128             KisShapeLayerSP shapeLayer = new KisShapeLayer(m_d->view->document()->shapeController(),
0129                                                            m_d->view->image().data(),
0130                                                            m_d->prettyLayerName(QString()),
0131                                                            OPACITY_OPAQUE_U8);
0132             KisShapeLayerSP imported = dynamic_cast<KisShapeLayer*>(importedImage->rootLayer()->firstChild().data());
0133 
0134             const QTransform thisInvertedTransform = shapeLayer->absoluteTransformation().inverted();
0135 
0136             Q_FOREACH (KoShape *shape, imported->shapes()) {
0137                 KoShape *clonedShape = shape->cloneShape();
0138                 clonedShape->setTransformation(shape->absoluteTransformation() * thisInvertedTransform);
0139                 shapeLayer->addShape(clonedShape);
0140             }
0141             m_d->importShapeLayer(shapeLayer);
0142             m_d->numLayersImported++;
0143         }
0144         else {
0145             KisPaintDeviceSP dev = new KisPaintDevice(*importedImage->projection());
0146             m_d->view->nodeManager()->createNode(m_d->layerType, false, dev);
0147             m_d->numLayersImported++;
0148         }
0149     }
0150 
0151     deleteMyself();
0152 }
0153 
0154 int KisImportCatcher::numLayersImported() const
0155 {
0156     return m_d->numLayersImported;
0157 }
0158 
0159 void KisImportCatcher::deleteMyself()
0160 {
0161     m_d->doc->deleteLater();
0162     deleteLater();
0163 }
0164 
0165 KisImportCatcher::~KisImportCatcher()
0166 {
0167     delete m_d;
0168 }
0169 
0170 void KisImportCatcher::adaptClipToImageColorSpace(KisPaintDeviceSP dev, KisImageSP image)
0171 {
0172     KisConfig cfg(true);
0173     if (cfg.convertToImageColorspaceOnImport() && *dev->colorSpace() != *image->colorSpace()) {
0174         /// XXX: do we need intent here?
0175         dev->convertTo(image->colorSpace());
0176     }
0177 }
0178