added nodes.
This commit is contained in:
209
nodes/services/ntxnodetree.cpp
Normal file
209
nodes/services/ntxnodetree.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include <ntxnodetree.h>
|
||||
#include <ntxnodefactory.h>
|
||||
|
||||
|
||||
namespace ntx
|
||||
{
|
||||
|
||||
NtxNodeTree::NtxNodeTree(NtxClassTypeId id)
|
||||
{
|
||||
//m_ctypeId = id;
|
||||
}
|
||||
|
||||
NtxNodePtr NtxNodeTree::clone() const
|
||||
{
|
||||
/*
|
||||
auto cloned = NtxNodeFactory::makeNode(getClassTypeLabel());
|
||||
qDebug() << "Cloning NtxNodeTree with CTypeLabel: NOT DONE: " << getClassTypeLabel().c_str();
|
||||
|
||||
forEachProperty([&](const NtxString& key, const NtxVariant& value) {
|
||||
cloned->setProperty(key, value);
|
||||
});
|
||||
for (size_t i = 0; i < getChildCount(); ++i)
|
||||
cloned->addChild(getChild(i)->clone());
|
||||
|
||||
|
||||
|
||||
|
||||
return cloned;
|
||||
|
||||
*/
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Command-Ausführung (delegiert an NtxUndoStack)
|
||||
// =========================================================================
|
||||
|
||||
bool NtxNodeTree::execute(NtxCommandUPtr cmd)
|
||||
{
|
||||
if (!cmd || !cmd->canExecute())
|
||||
return false;
|
||||
m_undoStack.push(std::move(cmd));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NtxNodeTree::undo()
|
||||
{
|
||||
if (!canUndo())
|
||||
return false;
|
||||
m_undoStack.undo();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NtxNodeTree::redo()
|
||||
{
|
||||
if (!canRedo())
|
||||
return false;
|
||||
m_undoStack.redo();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NtxNodeTree::canUndo() const { return m_undoStack.canUndo(); }
|
||||
bool NtxNodeTree::canRedo() const { return m_undoStack.canRedo(); }
|
||||
NtxString NtxNodeTree::undoText() const { return m_undoStack.undoText(); }
|
||||
NtxString NtxNodeTree::redoText() const { return m_undoStack.redoText(); }
|
||||
|
||||
void NtxNodeTree::setClean() { m_undoStack.setClean(); }
|
||||
bool NtxNodeTree::isDirty() const { return !m_undoStack.isClean(); }
|
||||
|
||||
// =========================================================================
|
||||
// Einzel-Operationen
|
||||
// =========================================================================
|
||||
|
||||
bool NtxNodeTree::addNode(NtxNodePtr parent, NtxNodePtr node, size_t index)
|
||||
{
|
||||
return execute(std::make_unique<NtxInsertNodeCmd>(
|
||||
std::move(parent), std::move(node), index));
|
||||
}
|
||||
|
||||
bool NtxNodeTree::deleteNode(NtxNodePtr node)
|
||||
{
|
||||
return execute(std::make_unique<NtxRemoveNodeCmd>(std::move(node)));
|
||||
}
|
||||
|
||||
bool NtxNodeTree::moveNode(NtxNodePtr node, NtxNodePtr newParent, size_t newIndex)
|
||||
{
|
||||
// Move = Remove + Insert als Makro
|
||||
auto macro = std::make_unique<NtxMacroCommand>("Move node");
|
||||
macro->add(std::make_unique<NtxRemoveNodeCmd>(node));
|
||||
macro->add(std::make_unique<NtxInsertNodeCmd>(
|
||||
std::move(newParent), std::move(node), newIndex));
|
||||
return execute(std::move(macro));
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Listen-Operationen (Makro-Commands)
|
||||
// =========================================================================
|
||||
|
||||
bool NtxNodeTree::addNodes(NtxNodePtr parent, const NtxNodeList& nodes, size_t index)
|
||||
{
|
||||
std::vector<NtxCommandUPtr> cmds;
|
||||
cmds.reserve(nodes.size());
|
||||
|
||||
for (size_t i = 0; i < nodes.size(); ++i)
|
||||
{
|
||||
cmds.push_back(std::make_unique<NtxInsertNodeCmd>(
|
||||
parent, nodes[i], index + i));
|
||||
}
|
||||
|
||||
return execute(NtxMacroCommand::create(
|
||||
"Insert " + std::to_string(nodes.size()) + " nodes",
|
||||
std::move(cmds)));
|
||||
}
|
||||
|
||||
bool NtxNodeTree::deleteNodes(const NtxNodeList& nodes)
|
||||
{
|
||||
std::vector<NtxCommandUPtr> cmds;
|
||||
cmds.reserve(nodes.size());
|
||||
|
||||
// Rückwärts löschen → Indizes bleiben stabil
|
||||
for (auto it = nodes.rbegin(); it != nodes.rend(); ++it)
|
||||
cmds.push_back(std::make_unique<NtxRemoveNodeCmd>(*it));
|
||||
|
||||
return execute(NtxMacroCommand::create(
|
||||
"Delete " + std::to_string(nodes.size()) + " nodes",
|
||||
std::move(cmds)));
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Clipboard
|
||||
// =========================================================================
|
||||
|
||||
void NtxNodeTree::copyNodes(const NtxNodeList& nodes)
|
||||
{
|
||||
m_clipboard.copyNodes(nodes);
|
||||
m_isCutOperation = false;
|
||||
}
|
||||
|
||||
void NtxNodeTree::cutNodes(const NtxNodeList& nodes)
|
||||
{
|
||||
m_clipboard.copyNodes(nodes);
|
||||
m_isCutOperation = true;
|
||||
}
|
||||
|
||||
NtxNodeList NtxNodeTree::pasteNodes(NtxNodePtr parent, size_t index)
|
||||
{
|
||||
NtxNodeList pasted = m_clipboard.pasteNodes();
|
||||
if (pasted.empty())
|
||||
return {};
|
||||
|
||||
if (m_isCutOperation)
|
||||
{
|
||||
// Cut+Paste = Remove originals + Insert clones (als Makro)
|
||||
auto macro = std::make_unique<NtxMacroCommand>(
|
||||
"Paste " + std::to_string(pasted.size()) + " nodes (cut)");
|
||||
|
||||
// 1. Originale entfernen (rückwärts für stabile Indizes)
|
||||
const auto& entries = m_clipboard.getEntries();
|
||||
for (auto it = entries.rbegin(); it != entries.rend(); ++it)
|
||||
{
|
||||
if (auto origParent = it->originalParent.lock())
|
||||
{
|
||||
if (it->originalPosition < origParent->getChildCount())
|
||||
{
|
||||
auto origNode = origParent->getChild(it->originalPosition);
|
||||
if (origNode)
|
||||
macro->add(std::make_unique<NtxRemoveNodeCmd>(origNode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Clones einfügen
|
||||
for (size_t i = 0; i < pasted.size(); ++i)
|
||||
{
|
||||
macro->add(std::make_unique<NtxInsertNodeCmd>(
|
||||
parent, pasted[i], index + i));
|
||||
}
|
||||
|
||||
if (!execute(std::move(macro)))
|
||||
return {};
|
||||
|
||||
m_isCutOperation = false;
|
||||
m_clipboard.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy+Paste = nur Insert
|
||||
if (!addNodes(parent, pasted, index))
|
||||
return {};
|
||||
}
|
||||
|
||||
return pasted;
|
||||
}
|
||||
|
||||
bool NtxNodeTree::hasClipboard() const
|
||||
{
|
||||
return !m_clipboard.isEmpty();
|
||||
}
|
||||
|
||||
void NtxNodeTree::clearClipboard()
|
||||
{
|
||||
m_clipboard.clear();
|
||||
m_isCutOperation = false;
|
||||
}
|
||||
|
||||
} // namespace ntx
|
||||
Reference in New Issue
Block a user