File indexing completed on 2024-05-19 04:28:59
0001 /* 0002 * SPDX-FileCopyrightText: 2011 Boudewijn Rempt <boud@valdyas.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #include "kis_mimedata.h" 0008 #include "kis_config.h" 0009 #include "kis_node.h" 0010 #include "kis_paint_device.h" 0011 #include "kis_shared_ptr.h" 0012 #include "kis_image.h" 0013 #include "kis_layer.h" 0014 #include "kis_shape_layer.h" 0015 #include "kis_paint_layer.h" 0016 #include "kis_clone_layer.h" 0017 #include "KisDocument.h" 0018 #include "kis_shape_controller.h" 0019 #include "KisPart.h" 0020 #include "kis_layer_utils.h" 0021 #include "kis_generator_registry.h" 0022 #include "KisGlobalResourcesInterface.h" 0023 #include "kis_filter_configuration.h" 0024 #include "kis_generator_layer.h" 0025 #include "kis_selection.h" 0026 #include "kis_node_insertion_adapter.h" 0027 #include "kis_dummies_facade_base.h" 0028 #include "kis_node_dummies_graph.h" 0029 #include "KisImportExportManager.h" 0030 #include "KisImageBarrierLock.h" 0031 0032 #include <KoProperties.h> 0033 #include <KoStore.h> 0034 #include <KoColorProfile.h> 0035 #include <KoColorSpaceRegistry.h> 0036 0037 #include <QApplication> 0038 #include <QImage> 0039 #include <QByteArray> 0040 #include <QBuffer> 0041 #include <QDomDocument> 0042 #include <QDomElement> 0043 #include <QDesktopWidget> 0044 #include <QDir> 0045 0046 namespace { 0047 KisNodeSP safeCopyNode(KisNodeSP node, bool detachClones = true) { 0048 KisCloneLayerSP cloneLayer = dynamic_cast<KisCloneLayer*>(node.data()); 0049 return cloneLayer && detachClones ? 0050 KisNodeSP(cloneLayer->reincarnateAsPaintLayer()) : node->clone(); 0051 } 0052 } 0053 0054 0055 KisMimeData::KisMimeData(QList<KisNodeSP> nodes, KisImageSP image, bool forceCopy) 0056 : QMimeData() 0057 , m_nodes(nodes) 0058 , m_forceCopy(forceCopy) 0059 , m_image(image) 0060 { 0061 Q_ASSERT(m_nodes.size() > 0); 0062 0063 KIS_SAFE_ASSERT_RECOVER_RETURN(image); 0064 0065 Q_FOREACH (KisNodeSP node, nodes) { 0066 m_copiedBounds |= KisLayerUtils::recursiveTightNodeVisibleBounds(node); 0067 } 0068 } 0069 0070 void KisMimeData::deepCopyNodes() 0071 { 0072 KisNodeList newNodes; 0073 0074 { 0075 KisImageReadOnlyBarrierLock lock(m_image, std::defer_lock); 0076 if (m_image) { 0077 lock.lock(); 0078 } 0079 0080 Q_FOREACH (KisNodeSP node, m_nodes) { 0081 KisNodeSP newNode = safeCopyNode(node); 0082 newNode->setImage(nullptr); 0083 0084 newNodes << newNode; 0085 } 0086 } 0087 0088 m_nodes = newNodes; 0089 m_image = 0; 0090 } 0091 0092 QList<KisNodeSP> KisMimeData::nodes() const 0093 { 0094 return m_nodes; 0095 } 0096 0097 QStringList KisMimeData::formats () const 0098 { 0099 QStringList f = QMimeData::formats(); 0100 if (m_nodes.size() > 0) { 0101 f << "application/x-qt-image" 0102 << "application/zip" 0103 << "application/x-krita-node-internal-pointer"; 0104 } 0105 return f; 0106 } 0107 0108 KisDocument *createDocument(QList<KisNodeSP> nodes, KisImageSP srcImage, const QRect &copiedBounds) 0109 { 0110 KisDocument *doc = KisPart::instance()->createTemporaryDocument(); 0111 QRect rc = copiedBounds; 0112 0113 QRect offset(0, 0, rc.width(), rc.height()); 0114 rc |= offset; 0115 0116 if (rc.isEmpty() && srcImage) { 0117 rc = srcImage->bounds(); 0118 } 0119 0120 KisImageSP image = new KisImage(0, rc.width(), rc.height(), nodes.first()->colorSpace(), nodes.first()->name()); 0121 image->setAllowMasksOnRootNode(true); 0122 0123 if (srcImage) { 0124 image->setResolution(srcImage->xRes(), srcImage->yRes()); 0125 } 0126 0127 { 0128 KisImageReadOnlyBarrierLock lock(srcImage, std::defer_lock); 0129 if (srcImage) { 0130 lock.lock(); 0131 } 0132 0133 Q_FOREACH (KisNodeSP node, nodes) { 0134 KisNodeSP clonedNode = safeCopyNode(node); 0135 /// HACK ALERT: here we just initialize parent image link 0136 /// and skip initializing shapeController! 0137 /// Ideally, we should call initializeExternalNode() 0138 /// instead. 0139 image->addNode(clonedNode); 0140 KIS_SAFE_ASSERT_RECOVER(clonedNode->image() == KisImageWSP(image)) { 0141 clonedNode->setImage(image); 0142 } 0143 } 0144 } 0145 0146 doc->setCurrentImage(image); 0147 0148 return doc; 0149 } 0150 0151 QByteArray serializeToByteArray(QList<KisNodeSP> nodes, KisImageSP srcImage, const QRect &copiedBounds) 0152 { 0153 QScopedPointer<KisDocument> doc(createDocument(nodes, srcImage, copiedBounds)); 0154 QByteArray result = doc->serializeToNativeByteArray(); 0155 0156 // avoid a sanity check failure caused by the fact that the image outlives 0157 // the document (and it does) 0158 doc->setCurrentImage(0); 0159 0160 return result; 0161 } 0162 0163 QVariant KisMimeData::retrieveData(const QString &mimetype, QVariant::Type preferredType) const 0164 { 0165 /** 0166 * HACK ALERT: 0167 * 0168 * Sometimes Qt requests the data *after* destruction of Krita, 0169 * we cannot load the nodes in that case, because we need signals 0170 * and timers. So we just skip serializing. 0171 */ 0172 if (!QApplication::instance()) return QVariant(); 0173 0174 0175 Q_ASSERT(m_nodes.size() > 0); 0176 0177 if (mimetype == "application/x-qt-image") { 0178 KisConfig cfg(true); 0179 0180 QScopedPointer<KisDocument> doc(createDocument(m_nodes, m_image, m_copiedBounds)); 0181 0182 return doc->image()->projection()->convertToQImage(cfg.displayProfile(QApplication::desktop()->screenNumber(QApplication::activeWindow())), 0183 KoColorConversionTransformation::internalRenderingIntent(), 0184 KoColorConversionTransformation::internalConversionFlags()); 0185 } 0186 else if (mimetype == "application/zip") { 0187 0188 QByteArray ba = serializeToByteArray(m_nodes, m_image, m_copiedBounds); 0189 return ba; 0190 0191 } 0192 else if (mimetype == "application/x-krita-node-internal-pointer") { 0193 0194 QDomDocument doc("krita_internal_node_pointer"); 0195 QDomElement root = doc.createElement("pointer"); 0196 root.setAttribute("application_pid", (qint64)QApplication::applicationPid()); 0197 root.setAttribute("force_copy", m_forceCopy); 0198 root.setAttribute("image_pointer_value", (qint64)m_image.data()); 0199 doc.appendChild(root); 0200 0201 Q_FOREACH (KisNodeSP node, m_nodes) { 0202 QDomElement element = doc.createElement("node"); 0203 element.setAttribute("pointer_value", (qint64)node.data()); 0204 root.appendChild(element); 0205 } 0206 0207 return doc.toByteArray(); 0208 0209 } 0210 else { 0211 return QMimeData::retrieveData(mimetype, preferredType); 0212 } 0213 } 0214 0215 void KisMimeData::initializeExternalNode(KisNodeSP *node, 0216 KisImageSP srcImage, 0217 KisImageSP dstImage, 0218 KisShapeController *shapeController) 0219 { 0220 KisShapeLayer *shapeLayer = dynamic_cast<KisShapeLayer*>(node->data()); 0221 if (shapeLayer) { 0222 // attach the layer to a new shape controller 0223 KisShapeLayer *shapeLayer2 = new KisShapeLayer(*shapeLayer, shapeController); 0224 0225 if (srcImage 0226 && (!qFuzzyCompare(dstImage->xRes(), srcImage->xRes()) 0227 || !qFuzzyCompare(dstImage->yRes(), srcImage->yRes()))) { 0228 0229 const QTransform t = QTransform::fromScale(srcImage->xRes() / dstImage->xRes(), 0230 srcImage->yRes() / dstImage->yRes()); 0231 0232 shapeLayer2->setTransformation(shapeLayer2->transformation() * t); 0233 } 0234 0235 *node = shapeLayer2; 0236 } 0237 } 0238 0239 QList<KisNodeSP> KisMimeData::tryLoadInternalNodes(const QMimeData *data, 0240 KisImageSP image, 0241 KisShapeController *shapeController, 0242 bool /* IN-OUT */ ©Node) 0243 { 0244 QList<KisNodeSP> nodes; 0245 bool forceCopy = false; 0246 KisImageSP sourceImage; 0247 0248 // Qt 4.7 and Qt 5.5 way 0249 const KisMimeData *mimedata = qobject_cast<const KisMimeData*>(data); 0250 if (mimedata) { 0251 nodes = mimedata->nodes(); 0252 forceCopy = mimedata->m_forceCopy; 0253 sourceImage = mimedata->m_image; 0254 } 0255 0256 // Qt 4.8 way 0257 if (nodes.isEmpty() && data->hasFormat("application/x-krita-node-internal-pointer")) { 0258 QByteArray nodeXml = data->data("application/x-krita-node-internal-pointer"); 0259 0260 QDomDocument doc; 0261 doc.setContent(nodeXml); 0262 0263 QDomElement root = doc.documentElement(); 0264 qint64 pid = root.attribute("application_pid").toLongLong(); 0265 forceCopy = root.attribute("force_copy").toInt(); 0266 qint64 imagePointerValue = root.attribute("image_pointer_value").toLongLong(); 0267 sourceImage = reinterpret_cast<KisImage*>(imagePointerValue); 0268 0269 if (pid == QApplication::applicationPid()) { 0270 QDomElement e; 0271 for (e = root.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) { 0272 qint64 pointerValue = e.attribute("pointer_value").toLongLong(); 0273 if (pointerValue) { 0274 nodes << reinterpret_cast<KisNode*>(pointerValue); 0275 } 0276 } 0277 } 0278 } 0279 0280 if (!nodes.isEmpty() && (forceCopy || copyNode || sourceImage != image)) { 0281 KisImageReadOnlyBarrierLock lock(sourceImage, std::defer_lock); 0282 if (sourceImage) { 0283 lock.lock(); 0284 } 0285 0286 QList<KisNodeSP> clones; 0287 Q_FOREACH (KisNodeSP node, nodes) { 0288 node = safeCopyNode(node, sourceImage != image); 0289 if ((forceCopy || copyNode) && sourceImage == image) { 0290 KisLayerUtils::addCopyOfNameTag(node); 0291 } 0292 initializeExternalNode(&node, sourceImage, image, shapeController); 0293 clones << node; 0294 } 0295 nodes = clones; 0296 copyNode = true; 0297 } 0298 return nodes; 0299 } 0300 0301 QList<KisNodeSP> KisMimeData::loadNonNativeNodes(const QMimeData *data, 0302 KisImageWSP image) 0303 { 0304 bool doRecenter = false; 0305 QList<KisNodeSP> nodes; 0306 0307 if (nodes.isEmpty() && (data->hasFormat("application/x-color") || data->hasFormat("krita/x-colorsetentry"))) { 0308 QColor color = data->hasColor() ? qvariant_cast<QColor>(data->colorData()) : QColor(255, 0, 255); 0309 if (!data->hasColor() && data->hasFormat("krita/x-colorsetentry")) { 0310 QByteArray byteData = data->data("krita/x-colorsetentry"); 0311 KisSwatch s = KisSwatch::fromByteArray(byteData); 0312 color = s.color().toQColor(); 0313 } 0314 KisGeneratorSP generator = KisGeneratorRegistry::instance()->value("color"); 0315 KisFilterConfigurationSP defaultConfig = generator->factoryConfiguration(KisGlobalResourcesInterface::instance()); 0316 defaultConfig->setProperty("color", color); 0317 defaultConfig->createLocalResourcesSnapshot(KisGlobalResourcesInterface::instance()); 0318 0319 if (image) { 0320 KisGeneratorLayerSP fillLayer = new KisGeneratorLayer(image, image->nextLayerName(i18n("Fill Layer")), 0321 defaultConfig, image->globalSelection()); 0322 nodes << fillLayer; 0323 } 0324 } 0325 0326 if (nodes.isEmpty() && data->hasImage()) { 0327 QImage qimage = qvariant_cast<QImage>(data->imageData()); 0328 0329 KisPaintDeviceSP device = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb8()); 0330 device->convertFromQImage(qimage, 0); 0331 0332 if (image) { 0333 nodes << new KisPaintLayer(image.data(), image->nextLayerName(), OPACITY_OPAQUE_U8, device); 0334 } 0335 0336 doRecenter = true; 0337 } 0338 0339 if (!nodes.isEmpty() && doRecenter) { 0340 const QRect imageBounds = image->bounds(); 0341 0342 Q_FOREACH (KisNodeSP node, nodes) { 0343 const QRect layerBounds = node->projection()->exactBounds(); 0344 if (doRecenter) { 0345 QPoint pt = imageBounds.center() - layerBounds.center(); 0346 node->setX(pt.x()); 0347 node->setY(pt.y()); 0348 } 0349 } 0350 } 0351 0352 return nodes; 0353 } 0354 0355 QMimeData* KisMimeData::mimeForLayers(const KisNodeList &nodes, KisImageSP image, bool forceCopy) 0356 { 0357 KisNodeList inputNodes = nodes; 0358 KisNodeList sortedNodes; 0359 KisLayerUtils::sortMergeableNodes(image->root(), inputNodes, sortedNodes); 0360 if (sortedNodes.isEmpty()) return 0; 0361 0362 KisMimeData* data = new KisMimeData(sortedNodes, image, forceCopy); 0363 return data; 0364 } 0365 0366 QMimeData* KisMimeData::mimeForLayersDeepCopy(const KisNodeList &nodes, KisImageSP image, bool forceCopy) 0367 { 0368 KisNodeList inputNodes = nodes; 0369 KisNodeList sortedNodes; 0370 KisLayerUtils::sortMergeableNodes(image->root(), inputNodes, sortedNodes); 0371 if (sortedNodes.isEmpty()) return 0; 0372 0373 KisMimeData* data = new KisMimeData(sortedNodes, image, forceCopy); 0374 data->deepCopyNodes(); 0375 return data; 0376 } 0377 0378 bool nodeAllowsAsChild(KisNodeSP parent, KisNodeList nodes) 0379 { 0380 bool result = true; 0381 Q_FOREACH (KisNodeSP node, nodes) { 0382 if (!parent->allowAsChild(node) || !parent->isEditable(false)) { 0383 result = false; 0384 break; 0385 } 0386 } 0387 return result; 0388 } 0389 0390 bool correctNewNodeLocation(KisNodeList nodes, 0391 KisNodeDummy* &parentDummy, 0392 KisNodeDummy* &aboveThisDummy) 0393 { 0394 KisNodeSP parentNode = parentDummy->node(); 0395 bool result = true; 0396 0397 if(!nodeAllowsAsChild(parentDummy->node(), nodes) || 0398 (parentDummy->node()->inherits("KisGroupLayer") && parentDummy->node()->collapsed())) { 0399 aboveThisDummy = parentDummy; 0400 parentDummy = parentDummy->parent(); 0401 0402 result = (!parentDummy) ? false : 0403 correctNewNodeLocation(nodes, parentDummy, aboveThisDummy); 0404 } 0405 0406 return result; 0407 } 0408 0409 KisNodeList KisMimeData::loadNodesFast( 0410 const QMimeData *data, 0411 KisImageSP image, 0412 KisShapeController *shapeController, 0413 bool ©Node) 0414 { 0415 QList<KisNodeSP> nodes = 0416 KisMimeData::tryLoadInternalNodes(data, 0417 image, 0418 shapeController, 0419 copyNode /* IN-OUT */); 0420 0421 if (nodes.isEmpty()) { 0422 nodes = KisMimeData::loadNonNativeNodes(data, image); 0423 /** 0424 * Don't try to move a node originating from another image, 0425 * just copy it. 0426 */ 0427 copyNode = true; 0428 } 0429 0430 return nodes; 0431 } 0432 0433 KisNodeList KisMimeData::loadNodesFastAndRecenter(const QPoint &preferredCenter, const QMimeData *data, KisImageSP image, KisShapeController *shapeController, bool ©Node) 0434 { 0435 KisNodeList nodes = loadNodesFast(data, image, shapeController, copyNode); 0436 0437 Q_FOREACH (KisNodeSP node, nodes) { 0438 const QRect layerBounds = node->exactBounds(); 0439 const QPoint offset = preferredCenter - layerBounds.center(); 0440 0441 node->setX(node->x() + offset.x()); 0442 node->setY(node->y() + offset.y()); 0443 } 0444 0445 return nodes; 0446 } 0447 0448 bool KisMimeData::insertMimeLayers(const QMimeData *data, 0449 KisImageSP image, 0450 KisShapeController *shapeController, 0451 KisNodeDummy *parentDummy, 0452 KisNodeDummy *aboveThisDummy, 0453 bool copyNode, 0454 KisNodeInsertionAdapter *nodeInsertionAdapter, 0455 bool changeOffset, 0456 QPointF offset) 0457 { 0458 QList<KisNodeSP> nodes = loadNodesFast(data, image, shapeController, copyNode /* IN-OUT */); 0459 0460 if (changeOffset) { 0461 Q_FOREACH (KisNodeSP node, nodes) { 0462 KisLayerUtils::recursiveApplyNodes(node, [offset] (KisNodeSP node){ 0463 if (node->hasEditablePaintDevice()) { 0464 KisPaintDeviceSP dev = node->paintDevice(); 0465 dev->moveTo(offset.x(), offset.y()); 0466 } 0467 }); 0468 } 0469 } 0470 0471 if (nodes.isEmpty()) return false; 0472 0473 bool result = true; 0474 0475 if (!correctNewNodeLocation(nodes, parentDummy, aboveThisDummy)) { 0476 return false; 0477 } 0478 0479 KIS_ASSERT_RECOVER(nodeInsertionAdapter) { return false; } 0480 0481 Q_ASSERT(parentDummy); 0482 KisNodeSP aboveThisNode = aboveThisDummy ? aboveThisDummy->node() : 0; 0483 if (copyNode) { 0484 nodeInsertionAdapter->addNodes(nodes, parentDummy->node(), aboveThisNode); 0485 } 0486 else { 0487 Q_ASSERT(nodes.first()->graphListener() == image.data()); 0488 nodeInsertionAdapter->moveNodes(nodes, parentDummy->node(), aboveThisNode); 0489 } 0490 0491 const bool hasDelayedNodes = 0492 std::find_if(nodes.begin(), nodes.end(), 0493 [] (KisNodeSP node) { 0494 return bool(dynamic_cast<KisDelayedUpdateNodeInterface*>(node.data())); 0495 }) != nodes.end(); 0496 0497 if (hasDelayedNodes) { 0498 /** 0499 * We have the node juggler running, so it will delay the update of the 0500 * generator layers that might be included into the paste. To avoid 0501 * that we should forcefully to make it stop 0502 */ 0503 image->requestStrokeEnd(); 0504 } 0505 0506 return result; 0507 }