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
+16 -5
View File
@@ -29,7 +29,7 @@
namespace olive {
void NodeCopyPasteService::CopyNodesToClipboard(const QVector<Node *> &nodes, void *userdata)
void NodeCopyPasteService::CopyNodesToClipboard(QVector<Node *> nodes, void *userdata)
{
QString copy_str;
@@ -42,11 +42,22 @@ void NodeCopyPasteService::CopyNodesToClipboard(const QVector<Node *> &nodes, vo
writer.writeTextElement(QStringLiteral("version"), QString::number(Core::kProjectVersion));
writer.writeStartElement(QStringLiteral("nodes"));
foreach (Node* n, nodes) {
for (int i=0; i<nodes.size(); i++) {
Node *n = nodes.at(i);
writer.writeStartElement(QStringLiteral("node"));
writer.writeAttribute(QStringLiteral("id"), n->id());
n->Save(&writer);
writer.writeEndElement(); // node
// If this is a group, add the child nodes too
if (NodeGroup *g = dynamic_cast<NodeGroup*>(n)) {
for (auto it=g->GetContextPositions().cbegin(); it!=g->GetContextPositions().cend(); it++) {
if (!nodes.contains(it.key())) {
nodes.append(it.key());
}
}
}
}
writer.writeEndElement(); // nodes
@@ -208,9 +219,6 @@ QVector<Node *> NodeCopyPasteService::PasteNodesFromClipboard(NodeGraph *graph,
}
}
// Make connections
xml_node_data.PostConnect(data_version, command);
// Process contexts
for (auto it=pasted_contexts.cbegin(); it!=pasted_contexts.cend(); it++) {
Node *context = xml_node_data.node_ptrs.value(it.key());
@@ -229,6 +237,9 @@ QVector<Node *> NodeCopyPasteService::PasteNodesFromClipboard(NodeGraph *graph,
}
}
// Make connections
xml_node_data.PostConnect(data_version, command);
return pasted_nodes;
}
+1 -1
View File
@@ -35,7 +35,7 @@ public:
NodeCopyPasteService() = default;
protected:
void CopyNodesToClipboard(const QVector<Node *> &nodes, void* userdata = nullptr);
void CopyNodesToClipboard(QVector<Node *> nodes, void* userdata = nullptr);
QVector<Node*> PasteNodesFromClipboard(NodeGraph *graph, MultiUndoCommand *command, void* userdata = nullptr);
+5
View File
@@ -38,6 +38,11 @@ public:
return static_cast<NodeParamView *>(GetTimeBasedWidget());
}
const QVector<Node*> &GetContexts() const
{
return GetParamView()->GetContexts();
}
void SetCreateCheckBoxes(NodeParamViewCheckBoxBehavior e)
{
GetParamView()->SetCreateCheckBoxes(e);
@@ -238,6 +238,7 @@ void NodeParamView::SetContexts(const QVector<Node *> &contexts)
ctx->Clear();
ctx->setVisible(false);
}
contexts_ = contexts;
if (keyframe_view_) {
keyframe_view_->Clear();
+7
View File
@@ -77,6 +77,11 @@ public:
void SelectNodes(const QVector<Node*> &nodes);
void DeselectNodes(const QVector<Node*> &nodes);
const QVector<Node*> &GetContexts() const
{
return contexts_;
}
public slots:
void SetInputChecked(const NodeInput &input, bool e);
@@ -133,6 +138,8 @@ private:
bool ignore_flags_;
QVector<Node*> contexts_;
private slots:
void UpdateGlobalScrollBar();
@@ -52,7 +52,7 @@ NodeParamViewItemBase::NodeParamViewItemBase(QWidget *parent) :
bool NodeParamViewItemBase::IsExpanded() const
{
return body_->isVisible();
return title_bar_->IsExpanded();
}
QString NodeParamViewItemBase::GetTitleBarTextFromNode(Node *n)
+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()));
}
}
+5 -6
View File
@@ -133,9 +133,7 @@ protected:
virtual void changeEvent(QEvent *e) override;
private:
void AttachItemsToCursor(const QVector<NodeViewItem *> &items);
void DetachItemsFromCursor();
void DetachItemsFromCursor(bool delete_nodes_too = true);
void SetFlowDirection(NodeViewCommon::FlowDirection dir);
@@ -150,6 +148,7 @@ private:
QPointF GetEstimatedPositionForContext(NodeViewItem *item, Node *context) const;
NodeViewItem *GetAssumedItemForSelectedNode(Node *node);
Node::Position GetAssumedPositionForSelectedNode(Node *node);
Menu *CreateAddMenu(Menu *parent);
@@ -172,10 +171,12 @@ private:
struct AttachedItem {
NodeViewItem* item;
Node *node;
QPointF original_pos;
};
QList<AttachedItem> attached_items_;
void SetAttachedItems(const QVector<AttachedItem> &items);
QVector<AttachedItem> attached_items_;
NodeViewEdge* drop_edge_;
NodeInput drop_input_;
@@ -191,8 +192,6 @@ private:
NodeViewScene scene_;
MultiUndoCommand* paste_command_;
QVector<Node*> selected_nodes_;
QVector<Node*> contexts_;
+5
View File
@@ -97,6 +97,11 @@ NodeViewItem::~NodeViewItem()
Q_ASSERT(edges_.isEmpty());
}
Node::Position NodeViewItem::GetNodePositionData() const
{
return Node::Position(GetNodePosition(), IsExpanded());
}
QPointF NodeViewItem::GetNodePosition() const
{
return ScreenToNodePoint(pos(), flow_dir_);
+1
View File
@@ -54,6 +54,7 @@ public:
virtual ~NodeViewItem() override;
Node::Position GetNodePositionData() const;
QPointF GetNodePosition() const;
void SetNodePosition(const QPointF& pos);
void SetNodePosition(const Node::Position& pos);
+8 -4
View File
@@ -737,10 +737,14 @@ void MainWindow::FocusedPanelChanged(PanelWidget *panel)
if (NodePanel *node_panel = dynamic_cast<NodePanel*>(panel)) {
// Set param view contexts to these
bool is_default_node_panel = node_panel == node_panel_;
param_panel_->SetIgnoreNodeFlags(!is_default_node_panel);
param_panel_->SetCreateCheckBoxes(is_default_node_panel ? kNoCheckBoxes : kCheckBoxesOnNonConnected);
param_panel_->SetContexts(node_panel->GetContexts());
const QVector<Node*> &new_ctxs = node_panel->GetContexts();
if (new_ctxs != param_panel_->GetContexts()) {
bool is_default_node_panel = node_panel == node_panel_;
param_panel_->SetIgnoreNodeFlags(!is_default_node_panel);
param_panel_->SetCreateCheckBoxes(is_default_node_panel ? kNoCheckBoxes : kCheckBoxesOnNonConnected);
param_panel_->SetContexts(node_panel->GetContexts());
}
} else if (TimelinePanel* timeline = dynamic_cast<TimelinePanel*>(panel)) {
// Signal timeline focus
TimelineFocused(timeline->GetConnectedViewer());