From a0719701cfd8833698c1386559f896b4847e358f Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Tue, 20 Jul 2021 13:00:00 -0700 Subject: [PATCH] nodes: include contexts in copy data Fixes #1683 --- app/node/nodecopypaste.cpp | 103 ++++++++++++++++++++++++++++++----- app/node/project/project.cpp | 82 ++++++++++++++++------------ app/node/project/project.h | 3 + 3 files changed, 141 insertions(+), 47 deletions(-) diff --git a/app/node/nodecopypaste.cpp b/app/node/nodecopypaste.cpp index c89967b79..61799b0f8 100644 --- a/app/node/nodecopypaste.cpp +++ b/app/node/nodecopypaste.cpp @@ -41,12 +41,33 @@ void NodeCopyPasteService::CopyNodesToClipboard(const QVector &nodes, vo writer.writeTextElement(QStringLiteral("version"), QString::number(Core::kProjectVersion)); + writer.writeStartElement(QStringLiteral("nodes")); foreach (Node* n, nodes) { writer.writeStartElement(QStringLiteral("node")); writer.writeAttribute(QStringLiteral("id"), n->id()); n->Save(&writer); writer.writeEndElement(); // node } + writer.writeEndElement(); // nodes + + writer.writeStartElement(QStringLiteral("contexts")); + foreach (Node* n, nodes) { + // Determine if this node is a context + if (n->parent()->GetPositionMap().contains(n)) { + writer.writeStartElement(QStringLiteral("context")); + writer.writeAttribute(QStringLiteral("ptr"), QString::number(reinterpret_cast(n))); + + const NodeGraph::PositionMap &map = n->parent()->GetNodesForContext(n); + for (auto it=map.cbegin(); it!=map.cend(); it++) { + writer.writeStartElement(QStringLiteral("node")); + Project::SavePosition(&writer, it.key(), it.value()); + writer.writeEndElement(); // node + } + + writer.writeEndElement(); // context + } + } + writer.writeEndElement(); // contexts writer.writeStartElement(QStringLiteral("custom")); CopyNodesToClipboardInternal(&writer, userdata); @@ -71,6 +92,7 @@ QVector NodeCopyPasteService::PasteNodesFromClipboard(NodeGraph *graph, QVector pasted_nodes; XMLNodeData xml_node_data; + QMap > pasted_contexts; while (XMLReadNextStartElement(&reader)) { if (reader.name() == QStringLiteral("olive")) { @@ -79,25 +101,66 @@ QVector NodeCopyPasteService::PasteNodesFromClipboard(NodeGraph *graph, while (XMLReadNextStartElement(&reader)) { if (reader.name() == QStringLiteral("version")) { data_version = reader.readElementText().toUInt(); - } else if (reader.name() == QStringLiteral("node")) { - if (data_version == 0) { - // Refuse to create any nodes if we didn't get a version string - return QVector(); - } + } else if (reader.name() == QStringLiteral("nodes")) { + while (XMLReadNextStartElement(&reader)) { + if (reader.name() == QStringLiteral("node")) { + if (data_version == 0) { + // Refuse to create any nodes if we didn't get a version string + return QVector(); + } - Node* node = nullptr; + Node* node = nullptr; - XMLAttributeLoop((&reader), attr) { - if (attr.name() == QStringLiteral("id")) { - node = NodeFactory::CreateFromID(attr.value().toString()); - break; + XMLAttributeLoop((&reader), attr) { + if (attr.name() == QStringLiteral("id")) { + node = NodeFactory::CreateFromID(attr.value().toString()); + break; + } + } + + if (node) { + node->Load(&reader, xml_node_data, data_version, nullptr); + + pasted_nodes.append(node); + } + } else { + reader.skipCurrentElement(); } } + } else if (reader.name() == QStringLiteral("contexts")) { + while (XMLReadNextStartElement(&reader)) { + if (reader.name() == QStringLiteral("context")) { + // Get context ptr + QMap map; + quintptr context_ptr = 0; + XMLAttributeLoop((&reader), attr) { + if (attr.name() == QStringLiteral("ptr")) { + context_ptr = attr.value().toULongLong(); + break; + } + } - if (node) { - node->Load(&reader, xml_node_data, data_version, nullptr); + // Find nodes section + while (XMLReadNextStartElement(&reader)) { + if (reader.name() == QStringLiteral("node")) { + quintptr node_ptr; + QPointF node_pos; - pasted_nodes.append(node); + if (Project::LoadPosition(&reader, &node_ptr, &node_pos)) { + map.insert(node_ptr, node_pos); + } + } else { + reader.skipCurrentElement(); + } + } + + // Insert + if (!map.isEmpty()) { + pasted_contexts.insert(context_ptr, map); + } + } else { + reader.skipCurrentElement(); + } } } else if (reader.name() == QStringLiteral("custom")) { if (data_version == 0) { @@ -149,6 +212,20 @@ QVector NodeCopyPasteService::PasteNodesFromClipboard(NodeGraph *graph, // Link blocks XMLLinkBlocks(xml_node_data); + // Process contexts + for (auto it=pasted_contexts.cbegin(); it!=pasted_contexts.cend(); it++) { + Node *context = xml_node_data.node_ptrs.value(it.key()); + if (context) { + const QMap &map = it.value(); + for (auto jt=map.cbegin(); jt!=map.cend(); jt++) { + Node *subnode = xml_node_data.node_ptrs.value(jt.key()); + if (subnode) { + command->add_child(new NodeSetPositionCommand(subnode, context, jt.value(), false)); + } + } + } + } + return pasted_nodes; } diff --git a/app/node/project/project.cpp b/app/node/project/project.cpp index 5cc50d274..26f0336c1 100644 --- a/app/node/project/project.cpp +++ b/app/node/project/project.cpp @@ -158,35 +158,18 @@ void Project::Load(QXmlStreamReader *reader, MainWindowLayoutInfo* layout, uint } else { while (XMLReadNextStartElement(reader)) { if (reader->name() == QStringLiteral("node")) { - quintptr node_ptr = 0; - XMLAttributeLoop(reader, attr) { - if (attr.name() == QStringLiteral("ptr")) { - node_ptr = attr.value().toULongLong(); - break; + quintptr node_ptr; + QPointF node_pos; + + if (LoadPosition(reader, &node_ptr, &node_pos)) { + Node *node = xml_node_data.node_ptrs.value(node_ptr); + + if (node) { + SetNodePosition(node, context, node_pos); + } else { + qWarning() << "Failed to find pointer for node position"; } } - - Node *node = xml_node_data.node_ptrs.value(node_ptr); - - if (!node) { - qWarning() << "Failed to find pointer for node position"; - reader->skipCurrentElement(); - } else { - QPointF pos; - - while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("x")) { - pos.setX(reader->readElementText().toDouble()); - } else if (reader->name() == QStringLiteral("y")) { - pos.setY(reader->readElementText().toDouble()); - } else { - reader->skipCurrentElement(); - } - } - - SetNodePosition(node, context, pos); - } - } else { reader->skipCurrentElement(); } @@ -253,13 +236,7 @@ void Project::Save(QXmlStreamWriter *writer) const for (auto jt=map.cbegin(); jt!=map.cend(); jt++) { writer->writeStartElement(QStringLiteral("node")); - - writer->writeAttribute(QStringLiteral("ptr"), QString::number(reinterpret_cast(jt.key()))); - - const QPointF &pos = jt.value(); - writer->writeTextElement(QStringLiteral("x"), QString::number(pos.x())); - writer->writeTextElement(QStringLiteral("y"), QString::number(pos.y())); - + SavePosition(writer, jt.key(), jt.value()); writer->writeEndElement(); // node } @@ -371,6 +348,43 @@ void Project::RegenerateUuid() uuid_ = QUuid::createUuid(); } +bool Project::LoadPosition(QXmlStreamReader *reader, quintptr *node_ptr, QPointF *pos) +{ + bool got_node_ptr = false; + bool got_pos_x = false; + bool got_pos_y = false; + + XMLAttributeLoop(reader, attr) { + if (attr.name() == QStringLiteral("ptr")) { + *node_ptr = attr.value().toULongLong(); + got_node_ptr = true; + break; + } + } + + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("x")) { + pos->setX(reader->readElementText().toDouble()); + got_pos_x = true; + } else if (reader->name() == QStringLiteral("y")) { + pos->setY(reader->readElementText().toDouble()); + got_pos_y = true; + } else { + reader->skipCurrentElement(); + } + } + + return got_node_ptr && got_pos_x && got_pos_y; +} + +void Project::SavePosition(QXmlStreamWriter *writer, Node *node, const QPointF &pos) +{ + writer->writeAttribute(QStringLiteral("ptr"), QString::number(reinterpret_cast(node))); + + writer->writeTextElement(QStringLiteral("x"), QString::number(pos.x())); + writer->writeTextElement(QStringLiteral("y"), QString::number(pos.y())); +} + void Project::ColorManagerValueChanged(const NodeInput &input, const TimeRange &range) { Q_UNUSED(input) diff --git a/app/node/project/project.h b/app/node/project/project.h index 0c4d5e5ea..3dbceb2bf 100644 --- a/app/node/project/project.h +++ b/app/node/project/project.h @@ -82,6 +82,9 @@ public: void RegenerateUuid(); + static bool LoadPosition(QXmlStreamReader *reader, quintptr *node_ptr, QPointF *pos); + static void SavePosition(QXmlStreamWriter *writer, Node *node, const QPointF &pos); + signals: void NameChanged();