finished refactoring copy/paste code

This commit is contained in:
itsmattkc
2021-12-30 19:35:52 -08:00
parent 8daa83b682
commit a7be16fec9
11 changed files with 143 additions and 75 deletions
+93 -58
View File
@@ -47,7 +47,6 @@ NodeView::NodeView(QWidget *parent) :
create_edge_(nullptr),
create_edge_output_item_(nullptr),
create_edge_input_item_(nullptr),
paste_command_(nullptr),
scale_(1.0)
{
setScene(&scene_);
@@ -283,14 +282,6 @@ void NodeView::keyPressEvent(QKeyEvent *event)
case Qt::Key_Escape:
if (!attached_items_.isEmpty()) {
DetachItemsFromCursor();
// We undo the last action which SHOULD be adding the node
if (paste_command_) {
paste_command_->undo_now();
delete paste_command_;
paste_command_ = nullptr;
}
break;
}
@@ -573,23 +564,18 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event)
}
if (context) {
if (paste_command_) {
// We've already "done" this command, but MultiUndoCommand prevents "redoing" twice, so we
// add it to this command (which may have extra commands added too) so that it all gets undone
// in the same action
command->add_child(paste_command_);
paste_command_ = nullptr;
}
{
MultiUndoCommand *add_command = new MultiUndoCommand();
foreach (const AttachedItem &ai, attached_items_) {
// Add node to the same graph that the context is in
add_command->add_child(new NodeAddCommand(context->parent(), ai.item->GetNode()));
add_command->add_child(new NodeAddCommand(context->parent(), ai.node));
// Add node to the context
add_command->add_child(new NodeSetPositionCommand(ai.item->GetNode(), context, scene_.context_map().value(context)->MapScenePosToNodePosInContext(ai.item->pos())));
if (ai.item) {
qDebug() << "Placing an item!";
add_command->add_child(new NodeSetPositionCommand(ai.node, context, scene_.context_map().value(context)->MapScenePosToNodePosInContext(ai.item->pos())));
}
}
if (add_command->child_count()) {
@@ -604,9 +590,16 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event)
// Dropped attached item onto an edge, connect it between them
MultiUndoCommand *drop_edge_command = new MultiUndoCommand();
if (attached_items_.size() == 1) {
Node* dropping_node = attached_items_.first().item->GetNode();
Node* dropping_node = nullptr;
if (drop_edge_) {
foreach (const AttachedItem &ai, attached_items_) {
if (ai.item) {
dropping_node = ai.node;
break;
}
}
if (dropping_node && drop_edge_) {
// Remove old edge
drop_edge_command->add_child(new NodeEdgeRemoveCommand(drop_edge_->output(), drop_edge_->input()));
@@ -625,7 +618,7 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event)
}
}
DetachItemsFromCursor();
DetachItemsFromCursor(false);
} else {
QToolTip::showText(QCursor::pos(), tr("Nodes must be placed inside a context."));
}
@@ -809,7 +802,8 @@ void NodeView::CreateNodeSlot(QAction *action)
NodeViewItem *new_item = new NodeViewItem(new_node, nullptr);
new_item->SetFlowDirection(scene_.GetFlowDirection());
scene_.addItem(new_item);
AttachItemsToCursor({new_item});
SetAttachedItems({{new_item, new_node, QPointF(0, 0)}});
}
}
@@ -899,23 +893,14 @@ void NodeView::NodeRemovedFromGraph()
contexts_.removeOne(context);
}
void NodeView::AttachItemsToCursor(const QVector<NodeViewItem*>& items)
{
DetachItemsFromCursor();
if (!items.isEmpty()) {
for (NodeViewItem* i : items) {
attached_items_.append({i, i->pos() - items.first()->pos()});
}
MoveAttachedNodesToCursor(mapFromGlobal(QCursor::pos()));
}
}
void NodeView::DetachItemsFromCursor()
void NodeView::DetachItemsFromCursor(bool delete_nodes_too)
{
foreach (const AttachedItem &ai, attached_items_) {
delete ai.item;
if (delete_nodes_too) {
delete ai.node;
}
}
attached_items_.clear();
@@ -931,7 +916,9 @@ void NodeView::MoveAttachedNodesToCursor(const QPoint& p)
QPointF item_pos = mapToScene(p);
for (const AttachedItem& i : qAsConst(attached_items_)) {
i.item->setPos(item_pos + i.original_pos);
if (i.item) {
i.item->setPos(item_pos + i.original_pos);
}
}
}
@@ -990,14 +977,18 @@ void NodeView::CopyNodesToClipboardInternal(QXmlStreamWriter *writer, const QVec
writer->writeStartElement(QStringLiteral("pos"));
for (Node *n : nodes) {
Node::Position pos = GetAssumedPositionForSelectedNode(n);
NodeViewItem *item = GetAssumedItemForSelectedNode(n);
writer->writeStartElement(QStringLiteral("node"));
writer->writeAttribute(QStringLiteral("ptr"), QString::number(reinterpret_cast<quintptr>(n)));
writer->writeTextElement(QStringLiteral("x"), QString::number(pos.position.x()));
writer->writeTextElement(QStringLiteral("y"), QString::number(pos.position.y()));
writer->writeTextElement(QStringLiteral("expanded"), QString::number(pos.expanded));
writer->writeEndElement(); // node
if (item) {
Node::Position pos = item->GetNodePositionData();
writer->writeStartElement(QStringLiteral("node"));
writer->writeAttribute(QStringLiteral("ptr"), QString::number(reinterpret_cast<quintptr>(n)));
writer->writeTextElement(QStringLiteral("x"), QString::number(pos.position.x()));
writer->writeTextElement(QStringLiteral("y"), QString::number(pos.position.y()));
writer->writeTextElement(QStringLiteral("expanded"), QString::number(pos.expanded));
writer->writeEndElement(); // node
}
}
writer->writeEndElement(); // pos
@@ -1077,19 +1068,27 @@ QPointF NodeView::GetEstimatedPositionForContext(NodeViewItem *item, Node *conte
return item->GetNodePosition() - context_offsets_.value(context);
}
Node::Position NodeView::GetAssumedPositionForSelectedNode(Node *node)
NodeViewItem *NodeView::GetAssumedItemForSelectedNode(Node *node)
{
// Try to find corresponding selected item
foreach (NodeViewContext *ctx, scene_.context_map()) {
NodeViewItem *item = ctx->GetItemFromMap(node);
if (item && item->isSelected()) {
if (item && item->GetNode() == node && item->isSelected()) {
// Good enough
return Node::Position(item->GetNodePosition(), item->IsExpanded());
return item;
}
}
// Fallback
return Node::Position();
return nullptr;
}
Node::Position NodeView::GetAssumedPositionForSelectedNode(Node *node)
{
if (NodeViewItem *item = GetAssumedItemForSelectedNode(node)) {
return item->GetNodePositionData();
} else {
return Node::Position();
}
}
Menu *NodeView::CreateAddMenu(Menu *parent)
@@ -1338,19 +1337,44 @@ void NodeView::PasteNodesInternal(const QVector<Node *> &duplicate_nodes)
// If no nodes were retrieved, do nothing
if (!new_nodes.isEmpty()) {
QVector<NodeViewItem*> items(new_nodes.size());
QVector<AttachedItem> new_attached;
NodeViewItem *first_item = nullptr;
for (int i=0; i<new_nodes.size(); i++) {
Node *node = new_nodes.at(i);
NodeViewItem *new_item = new NodeViewItem(node, nullptr);
new_item->SetFlowDirection(scene_.GetFlowDirection());
new_item->SetNodePosition(map.value(node));
scene_.addItem(new_item);
items[i] = new_item;
// Determine if item had a position, if not don't create an item for it
NodeViewItem *new_item;
if (map.contains(node)) {
new_item = new NodeViewItem(node, nullptr);
new_item->SetFlowDirection(scene_.GetFlowDirection());
new_item->SetNodePosition(map.value(node));
scene_.addItem(new_item);
if (!first_item) {
first_item = new_item;
}
} else {
new_item = nullptr;
}
new_attached.append({new_item, node, QPointF(0, 0)});
}
// Attach nodes to cursor
AttachItemsToCursor(items);
// Correct positions
if (first_item) {
for (int i=0; i<new_attached.size(); i++) {
AttachedItem &ai = new_attached[i];
if (ai.item) {
ai.original_pos = first_item->pos() - ai.item->pos();
}
}
}
SetAttachedItems(new_attached);
}
}
@@ -1389,4 +1413,15 @@ void NodeView::CollapseItem(NodeViewItem *item)
item->setZValue(0);
}
void NodeView::SetAttachedItems(const QVector<AttachedItem> &items)
{
// Detach anything currently attached
DetachItemsFromCursor();
attached_items_ = items;
// Move to cursor
MoveAttachedNodesToCursor(mapFromGlobal(QCursor::pos()));
}
}