diff --git a/app/node/nodecopypaste.cpp b/app/node/nodecopypaste.cpp index 61799b0f8..21eee76d9 100644 --- a/app/node/nodecopypaste.cpp +++ b/app/node/nodecopypaste.cpp @@ -70,7 +70,7 @@ void NodeCopyPasteService::CopyNodesToClipboard(const QVector &nodes, vo writer.writeEndElement(); // contexts writer.writeStartElement(QStringLiteral("custom")); - CopyNodesToClipboardInternal(&writer, userdata); + CopyNodesToClipboardInternal(&writer, nodes, userdata); writer.writeEndElement(); // custom writer.writeEndElement(); // olive @@ -229,7 +229,7 @@ QVector NodeCopyPasteService::PasteNodesFromClipboard(NodeGraph *graph, return pasted_nodes; } -void NodeCopyPasteService::CopyNodesToClipboardInternal(QXmlStreamWriter*, void*) +void NodeCopyPasteService::CopyNodesToClipboardInternal(QXmlStreamWriter*, const QVector &, void*) { } diff --git a/app/node/nodecopypaste.h b/app/node/nodecopypaste.h index a44e4240b..cc29d281a 100644 --- a/app/node/nodecopypaste.h +++ b/app/node/nodecopypaste.h @@ -39,7 +39,7 @@ protected: QVector PasteNodesFromClipboard(NodeGraph *graph, MultiUndoCommand *command, void* userdata = nullptr); - virtual void CopyNodesToClipboardInternal(QXmlStreamWriter *writer, void* userdata); + virtual void CopyNodesToClipboardInternal(QXmlStreamWriter *writer, const QVector &nodes, void* userdata); virtual void PasteNodesFromClipboardInternal(QXmlStreamReader *reader, XMLNodeData &xml_node_data, void* userdata); diff --git a/app/widget/nodeview/nodeview.cpp b/app/widget/nodeview/nodeview.cpp index b67076a8f..1bfefd9dc 100644 --- a/app/widget/nodeview/nodeview.cpp +++ b/app/widget/nodeview/nodeview.cpp @@ -1264,6 +1264,65 @@ bool NodeView::eventFilter(QObject *object, QEvent *event) return super::eventFilter(object, event); } +void NodeView::CopyNodesToClipboardInternal(QXmlStreamWriter *writer, const QVector &nodes, void *userdata) +{ + writer->writeStartElement(QStringLiteral("pos")); + + for (Node *n : nodes) { + NodeViewItem *item = scene_.item_map().value(n); + QPointF pos = item->GetNodePosition(); + + writer->writeStartElement(QStringLiteral("node")); + writer->writeAttribute(QStringLiteral("ptr"), QString::number(reinterpret_cast(n))); + writer->writeTextElement(QStringLiteral("x"), QString::number(pos.x())); + writer->writeTextElement(QStringLiteral("y"), QString::number(pos.y())); + writer->writeEndElement(); // node + } + + writer->writeEndElement(); // pos +} + +void NodeView::PasteNodesFromClipboardInternal(QXmlStreamReader *reader, XMLNodeData &xml_node_data, void *userdata) +{ + NodeGraph::PositionMap *map = static_cast(userdata); + + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("pos")) { + while (XMLReadNextStartElement(reader)) { + if (reader->name() == QStringLiteral("node")) { + Node *n = nullptr; + QPointF pos; + + XMLAttributeLoop(reader, attr) { + if (attr.name() == QStringLiteral("ptr")) { + n = xml_node_data.node_ptrs.value(attr.value().toULongLong()); + break; + } + } + + 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(); + } + } + + if (n) { + map->insert(n, pos); + } + } else { + reader->skipCurrentElement(); + } + } + } else { + reader->skipCurrentElement(); + } + } +} + void NodeView::ZoomFromKeyboard(double multiplier) { QPoint cursor_pos = mapFromGlobal(QCursor::pos()); @@ -1577,14 +1636,33 @@ void NodeView::PasteNodesInternal(const QVector &duplicate_nodes) // If duplicating nodes, duplicate, otherwise paste QVector new_nodes; + NodeGraph::PositionMap map; if (duplicate_nodes.isEmpty()) { - new_nodes = PasteNodesFromClipboard(graph_, paste_command_); + new_nodes = PasteNodesFromClipboard(graph_, paste_command_, &map); + + for (auto it=new_nodes.cbegin(); it!=new_nodes.cend(); it++) { + for (Node *context : qAsConst(filter_nodes_)) { + paste_command_->add_child(new NodeSetPositionCommand(*it, context, map.value(*it), false)); + } + } } else { new_nodes = Node::CopyDependencyGraph(duplicate_nodes, paste_command_); + + for (int i=0; iGetNodePosition(); + paste_command_->add_child(new NodeSetPositionCommand(copy, context, p, false)); + } + } } // If no nodes were retrieved, do nothing if (new_nodes.isEmpty()) { + delete paste_command_; + paste_command_ = nullptr; return; } diff --git a/app/widget/nodeview/nodeview.h b/app/widget/nodeview/nodeview.h index 24e9d452c..65d1b0438 100644 --- a/app/widget/nodeview/nodeview.h +++ b/app/widget/nodeview/nodeview.h @@ -112,6 +112,9 @@ protected: virtual bool eventFilter(QObject *object, QEvent *event) override; + virtual void CopyNodesToClipboardInternal(QXmlStreamWriter *writer, const QVector &nodes, void* userdata) override; + virtual void PasteNodesFromClipboardInternal(QXmlStreamReader *reader, XMLNodeData &xml_node_data, void* userdata) override; + private: void AttachNodesToCursor(const QVector &nodes); diff --git a/app/widget/timelinewidget/timelinewidget.cpp b/app/widget/timelinewidget/timelinewidget.cpp index 5fa05ab70..6d5d10014 100644 --- a/app/widget/timelinewidget/timelinewidget.cpp +++ b/app/widget/timelinewidget/timelinewidget.cpp @@ -296,7 +296,7 @@ void TimelineWidget::DisconnectNodeEvent(ViewerOutput *n) } } -void TimelineWidget::CopyNodesToClipboardInternal(QXmlStreamWriter *writer, void* userdata) +void TimelineWidget::CopyNodesToClipboardInternal(QXmlStreamWriter *writer, const QVector &nodes, void* userdata) { // Cache the earliest in point so all copied clips have a "relative" in point that can be pasted anywhere QVector& selected = *static_cast*>(userdata); diff --git a/app/widget/timelinewidget/timelinewidget.h b/app/widget/timelinewidget/timelinewidget.h index 502243266..176486f8e 100644 --- a/app/widget/timelinewidget/timelinewidget.h +++ b/app/widget/timelinewidget/timelinewidget.h @@ -248,7 +248,7 @@ protected: virtual void ConnectNodeEvent(ViewerOutput* n) override; virtual void DisconnectNodeEvent(ViewerOutput* n) override; - virtual void CopyNodesToClipboardInternal(QXmlStreamWriter *writer, void* userdata) override; + virtual void CopyNodesToClipboardInternal(QXmlStreamWriter *writer, const QVector &nodes, void* userdata) override; virtual void PasteNodesFromClipboardInternal(QXmlStreamReader *reader, XMLNodeData &xml_node_data, void* userdata) override; struct BlockPasteData {