Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/QtNodes/internal/DagGraphicsScene.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <QFileInfo>
#include <QDir>

#include "BasicGraphicsScene.hpp"
#include "DirectedAcyclicGraphModel.hpp"
Expand All @@ -23,6 +24,8 @@ class NODE_EDITOR_PUBLIC DagGraphicsScene : public BasicGraphicsScene
QMenu *createSceneMenu(QPointF const scenePos) override;
bool isEmpty() const { return _graphModel.isEmpty(); }
bool isBlank() const { return _graphModel.isEmpty(); }
QDir getDataDir() const;
void setDataDir(QDir const &dir);

public Q_SLOTS:
bool save(const QString &filePath, const QJsonObject &metadata = {}) const;
Expand All @@ -34,6 +37,7 @@ public Q_SLOTS:

private:
DirectedAcyclicGraphModel &_graphModel;
QDir _dataDir; // store current tab's data dir
};

} // namespace QtNodes
7 changes: 6 additions & 1 deletion include/QtNodes/internal/UndoCommands.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
#include "Definitions.hpp"
#include "Export.hpp"

#include <QDir>
#include <QUndoCommand>
#include <QtCore/QJsonObject>
#include <QtCore/QPointF>
#include <QUndoCommand>

#include <unordered_set>

Expand Down Expand Up @@ -61,11 +62,15 @@ class NODE_EDITOR_PUBLIC PasteCommand : public QUndoCommand
private:
QJsonObject takeSceneJsonFromClipboard();
QJsonObject makeNewNodeIdsInScene(QJsonObject const &sceneJson);
void copyNodeDataFiles(const QJsonObject &sceneJson,
const QDir &sourceDir,
BasicGraphicsScene *scene);

private:
BasicGraphicsScene *_scene;
QPointF const &_mouseScenePos;
QJsonObject _newSceneJson;
QDir _sourceDataDir; // source data dir for paste operation
};

class NODE_EDITOR_PUBLIC DisconnectCommand : public QUndoCommand
Expand Down
12 changes: 12 additions & 0 deletions src/DagGraphicsScene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,4 +202,16 @@ void DagGraphicsScene::createNodeAt(const QString &name, const QPointF &pos)
this->undoStack().push(new CreateCommand(this, name, pos));
}

QDir DagGraphicsScene::getDataDir() const
{
if (_dataDir.exists())
return _dataDir;
return QDir();
}

void DagGraphicsScene::setDataDir(QDir const &dir)
{
_dataDir = dir;
}

} // namespace QtNodes
53 changes: 50 additions & 3 deletions src/UndoCommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "BasicGraphicsScene.hpp"
#include "ConnectionGraphicsObject.hpp"
#include "ConnectionIdUtils.hpp"
#include "DagGraphicsScene.hpp"
#include "Definitions.hpp"
#include "NodeGraphicsObject.hpp"

Expand All @@ -13,7 +14,6 @@
#include <QtWidgets/QApplication>
#include <QtWidgets/QGraphicsObject>


namespace QtNodes {

static QJsonObject serializeSelectedItems(BasicGraphicsScene *scene)
Expand Down Expand Up @@ -240,10 +240,17 @@ CopyCommand::CopyCommand(BasicGraphicsScene *scene)
setObsolete(true);
return;
}
// For copy-paste data: include the data path (sourceDir) in the scene
QJsonObject wrapper;
wrapper["scene"] = sceneJson;
if (auto dagScene = dynamic_cast<DagGraphicsScene *>(scene)) {
if (auto srcDir = dagScene->getDataDir(); srcDir.exists())
wrapper["sourceDir"] = srcDir.absolutePath();
}

QClipboard *clipboard = QApplication::clipboard();

QByteArray const data = QJsonDocument(sceneJson).toJson();
QByteArray const data = QJsonDocument(wrapper).toJson();

QMimeData *mimeData = new QMimeData();
mimeData->setData("application/qt-nodes-graph", data);
Expand All @@ -263,7 +270,12 @@ PasteCommand::PasteCommand(BasicGraphicsScene *scene, QPointF const &mouseSceneP
: _scene(scene)
, _mouseScenePos(mouseScenePos)
{
_newSceneJson = takeSceneJsonFromClipboard();
QJsonObject wrapper = takeSceneJsonFromClipboard();
// check if sourcDir key exists in wrapper
_sourceDataDir = QDir();
if (wrapper.contains("sourceDir"))
_sourceDataDir = QDir(wrapper["sourceDir"].toString());
_newSceneJson = wrapper["scene"].toObject();

if (_newSceneJson.empty() || _newSceneJson["nodes"].toArray().empty()) {
setObsolete(true);
Expand All @@ -288,6 +300,7 @@ void PasteCommand::redo()

// Ignore if pasted in content does not generate nodes.
try {
copyNodeDataFiles(_newSceneJson, _sourceDataDir, _scene);
insertSerializedItems(_newSceneJson, _scene);
} catch (...) {
// If the paste does not work, delete all selected nodes and connections
Expand All @@ -305,6 +318,40 @@ void PasteCommand::redo()
}
}

void PasteCommand::copyNodeDataFiles(const QJsonObject &sceneJson,
const QDir &sourceDir,
BasicGraphicsScene *scene)
{
QDir targetDir;
if (auto dagScene = dynamic_cast<DagGraphicsScene *>(scene)) {
targetDir = dagScene->getDataDir();
}

QJsonArray nodesJsonArray = sceneJson["nodes"].toArray();
for (const auto &nodeVal : nodesJsonArray) {
QJsonObject obj = nodeVal.toObject();
QJsonObject internalData = obj["internal-data"].toObject();

// check if data/function source model exists in the scene, to copy the files
QString fileName;
if (internalData.contains("data-name"))
fileName = internalData["data-name"].toString();
else if (internalData.contains("saved_function"))
fileName = internalData["saved_function"].toString();

if (!fileName.isEmpty()) {
QString srcPath = sourceDir.filePath(fileName);
QString targetPath = targetDir.filePath(fileName);

if (QFile::exists(srcPath) && !QFile::exists(targetPath)) {
QFile::copy(srcPath, targetPath);
} else {
qWarning() << "Failed to copy file from" << srcPath << "to" << targetPath;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

else {
warning("Cannot copy file {srcPath} to {targetPath}")
}

}
}
}

QJsonObject PasteCommand::takeSceneJsonFromClipboard()
{
QClipboard const *clipboard = QApplication::clipboard();
Expand Down
Loading