From 323718bc115f0c5970d19503d0d74f27cb0daa7b Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sat, 14 Dec 2019 00:04:57 +1100 Subject: [PATCH] moved timeline undoable commands to using the new NodeAddCommand Previous iteration used some "magic code" that added clips automatically to the timeline. This was functional but ultimately outside of the undo commands' control meaning nodes could be infinitely added and abandoned. This makes the add process part of the undo command which means it's all undoable as the user would expect. --- app/node/graph.cpp | 27 ------------------- app/node/graph.h | 20 -------------- app/node/node.cpp | 10 +++++++ app/node/node.h | 10 +++++++ app/node/output/track/track.cpp | 27 ++++--------------- app/node/output/track/track.h | 12 --------- app/node/param.cpp | 5 +--- app/widget/nodeview/nodeviewitem.cpp | 14 ++++++++-- app/widget/nodeview/nodeviewitem.h | 2 ++ app/widget/nodeview/nodeviewundo.cpp | 4 +-- app/widget/nodeview/nodeviewundo.h | 5 +++- app/widget/timelinewidget/timelinewidget.cpp | 22 +++++++++++++-- app/widget/timelinewidget/timelinewidget.h | 2 ++ app/widget/timelinewidget/tool/add.cpp | 18 ++++++++++--- app/widget/timelinewidget/tool/import.cpp | 12 ++++++--- app/widget/timelinewidget/tool/pointer.cpp | 10 +++---- app/widget/timelinewidget/tool/ripple.cpp | 7 ++++- app/widget/timelinewidget/tool/rolling.cpp | 4 +++ app/widget/timelinewidget/tool/slide.cpp | 2 ++ app/widget/timelinewidget/tool/transition.cpp | 3 +++ app/widget/timelinewidget/undo/undo.cpp | 18 ++++++------- 21 files changed, 120 insertions(+), 114 deletions(-) diff --git a/app/node/graph.cpp b/app/node/graph.cpp index e6f1187ac..1023f2619 100644 --- a/app/node/graph.cpp +++ b/app/node/graph.cpp @@ -49,18 +49,6 @@ void NodeGraph::AddNode(Node *node) emit NodeAdded(node); } -void NodeGraph::AddNodeWithDependencies(Node *node) -{ - // Add node and its connected nodes to graph - AddNode(node); - - // Add all of Block's dependencies - QList node_dependencies = node->GetDependencies(); - foreach (Node* dep, node_dependencies) { - AddNode(dep); - } -} - void NodeGraph::TakeNode(Node *node, QObject* new_parent) { if (!ContainsNode(node)) { @@ -84,21 +72,6 @@ void NodeGraph::TakeNode(Node *node, QObject* new_parent) emit NodeRemoved(node); } -QList NodeGraph::TakeNodeWithItsDependencies(Node *node, QObject *new_parent) -{ - if (!ContainsNode(node)) { - return QList(); - } - - QList deps = node->GetExclusiveDependencies(); - - foreach (Node* d, deps) { - TakeNode(d, new_parent); - } - - return deps; -} - const QList &NodeGraph::nodes() { return node_children_; diff --git a/app/node/graph.h b/app/node/graph.h index df3613648..c006f0508 100644 --- a/app/node/graph.h +++ b/app/node/graph.h @@ -50,31 +50,11 @@ public: */ void AddNode(Node* node); - /** - * @brief Adds a node to this graph and all nodes connected to its inputs - * - * Adds the Node to the graph and runs through its inputs adding all of its dependencies (and all of their - * dependencies and so forth). The graph takes ownershi of all Nodes added through this process. - */ - void AddNodeWithDependencies(Node* node); - /** * @brief Removes a Node from the graph BUT doesn't destroy it. Ownership is passed to `new_parent`. */ void TakeNode(Node* node, QObject* new_parent = nullptr); - /** - * @brief Removes a Node from the graph and its dependencies (ONLY if the dependencies are exclusive to this Node). - * - * Returns a list of all Nodes that were removed in this process (except the Node used as a parameter) - * - * Only dependencies that are exclusively dependencies of this Node are removed. If a dependency Node is also - * used as the dependency of another Node, it is not removed and not returned in the list. - * - * Ownership of all Nodes is passed to `new_parent`. - */ - QList TakeNodeWithItsDependencies(Node* node, QObject* new_parent = nullptr); - /** * @brief Retrieve a complete list of the nodes belonging to this graph */ diff --git a/app/node/node.cpp b/app/node/node.cpp index 2521aa22e..e0c6955e9 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -468,6 +468,16 @@ QVariant Node::InputValueFromTable(NodeInput *input, const NodeValueTable &table return table.Get(find_data_type); } +const QPointF &Node::GetPosition() +{ + return position_; +} + +void Node::SetPosition(const QPointF &pos) +{ + position_ = pos; +} + void Node::AddInput(NodeInput *input) { AddParameter(input); diff --git a/app/node/node.h b/app/node/node.h index 8a6646130..39e896f4c 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -24,6 +24,7 @@ #include #include #include +#include #include "common/rational.h" #include "node/dependency.h" @@ -270,6 +271,10 @@ public: virtual QVariant InputValueFromTable(NodeInput* input, const NodeValueTable& table) const; + const QPointF& GetPosition(); + + void SetPosition(const QPointF& pos); + protected: void AddInput(NodeInput* input); @@ -339,6 +344,11 @@ private: */ NodeOutput* output_; + /** + * @brief UI position for NodeViews + */ + QPointF position_; + private slots: void InputChanged(rational start, rational end); diff --git a/app/node/output/track/track.cpp b/app/node/output/track/track.cpp index 47a39bb43..5e4559b4c 100644 --- a/app/node/output/track/track.cpp +++ b/app/node/output/track/track.cpp @@ -231,17 +231,19 @@ void TrackOutput::PrependBlock(Block *block) void TrackOutput::InsertBlockAtIndex(Block *block, int index) { - AddBlockToGraph(block); + BlockInvalidateCache(); block_input_->InsertAt(index); NodeParam::ConnectEdge(block->output(), block_input_->At(index)); + + UnblockInvalidateCache(); + + InvalidateCache(block->in(), track_length()); } void TrackOutput::AppendBlock(Block *block) { - AddBlockToGraph(block); - BlockInvalidateCache(); int last_index = block_input_->GetSize(); @@ -255,13 +257,6 @@ void TrackOutput::AppendBlock(Block *block) InvalidateCache(block->in(), track_length()); } -void TrackOutput::AddBlockToGraph(Block *block) -{ - // Find the parent graph - NodeGraph* graph = static_cast(parent()); - graph->AddNodeWithDependencies(block); -} - void TrackOutput::BlockInvalidateCache() { block_invalidate_cache_stack_++; @@ -272,14 +267,6 @@ void TrackOutput::UnblockInvalidateCache() block_invalidate_cache_stack_--; } -void TrackOutput::RemoveBlock(Block *block) -{ - GapBlock* gap = new GapBlock(); - gap->set_length(block->length()); - - ReplaceBlock(block, gap); -} - void TrackOutput::RippleRemoveBlock(Block *block) { BlockInvalidateCache(); @@ -293,8 +280,6 @@ void TrackOutput::RippleRemoveBlock(Block *block) UnblockInvalidateCache(); InvalidateCache(remove_in, track_length()); - - // FIXME: Should there be removing the Blocks from the graph? } void TrackOutput::ReplaceBlock(Block *old, Block *replace) @@ -303,8 +288,6 @@ void TrackOutput::ReplaceBlock(Block *old, Block *replace) BlockInvalidateCache(); - AddBlockToGraph(replace); - int index_of_old_block = block_cache_.indexOf(old); NodeParam::DisconnectEdge(old->output(), diff --git a/app/node/output/track/track.h b/app/node/output/track/track.h index 667a01fe7..cd65ce3c2 100644 --- a/app/node/output/track/track.h +++ b/app/node/output/track/track.h @@ -98,11 +98,6 @@ public: */ void AppendBlock(Block* block); - /** - * @brief Removes a Block and places a Gap in its place - */ - void RemoveBlock(Block* block); - /** * @brief Removes a Block pushing all subsequent Blocks earlier to take up the space */ @@ -119,13 +114,6 @@ public: void UnblockInvalidateCache(); - /** - * @brief Adds a Block to the parent graph so it can be connected to other Nodes - * - * Also runs through Node's dependencies (the Nodes whose outputs are connected to this Node's inputs) - */ - void AddBlockToGraph(Block* block); - static TrackOutput* TrackFromBlock(Block* block); const rational& track_length() const; diff --git a/app/node/param.cpp b/app/node/param.cpp index 09a9d07d0..8f5f3d7aa 100644 --- a/app/node/param.cpp +++ b/app/node/param.cpp @@ -116,10 +116,7 @@ NodeEdgePtr NodeParam::ConnectEdge(NodeOutput *output, NodeInput *input, bool lo } // Ensure both nodes are in the same graph - if (output->parentNode()->parent() != input->parentNode()->parent()) { - qWarning() << "Tried to connect two nodes that aren't part of the same graph"; - return nullptr; - } + Q_ASSERT(output->parentNode()->parent() == input->parentNode()->parent()); NodeEdgePtr edge = std::make_shared(output, input); diff --git a/app/widget/nodeview/nodeviewitem.cpp b/app/widget/nodeview/nodeviewitem.cpp index b0d283c1a..a08a7d91c 100644 --- a/app/widget/nodeview/nodeviewitem.cpp +++ b/app/widget/nodeview/nodeviewitem.cpp @@ -47,6 +47,7 @@ NodeViewItem::NodeViewItem(QGraphicsItem *parent) : // Set flags for this widget setFlag(QGraphicsItem::ItemIsMovable); setFlag(QGraphicsItem::ItemIsSelectable); + setFlag(QGraphicsItem::ItemSendsGeometryChanges); // // We use font metrics to set all the UI measurements for DPI-awareness @@ -77,6 +78,8 @@ void NodeViewItem::SetNode(Node *n) { node_ = n; + setPos(node_->GetPosition()); + update(); } @@ -256,8 +259,6 @@ void NodeViewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti } } -#include "node/block/block.h" - void NodeViewItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { // We override standard mouse behavior in some cases. In these cases, we don't want the standard "move" and "release" @@ -470,3 +471,12 @@ void NodeViewItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) QGraphicsRectItem::mouseReleaseEvent(event); } } + +QVariant NodeViewItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) +{ + if (change == ItemPositionHasChanged && node_) { + node_->SetPosition(value.toPointF()); + } + + return QGraphicsItem::itemChange(change, value); +} diff --git a/app/widget/nodeview/nodeviewitem.h b/app/widget/nodeview/nodeviewitem.h index 4fa76c716..1c0c629f7 100644 --- a/app/widget/nodeview/nodeviewitem.h +++ b/app/widget/nodeview/nodeviewitem.h @@ -82,6 +82,8 @@ protected: virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; + virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override; + private: /** * @brief Get the relative position to draw text for a parameter at a certain index diff --git a/app/widget/nodeview/nodeviewundo.cpp b/app/widget/nodeview/nodeviewundo.cpp index 7d522cdd0..a7cf98898 100644 --- a/app/widget/nodeview/nodeviewundo.cpp +++ b/app/widget/nodeview/nodeviewundo.cpp @@ -70,8 +70,8 @@ NodeAddCommand::NodeAddCommand(NodeGraph *graph, Node *node, QUndoCommand *paren graph_(graph), node_(node) { - // Ensures that when this command is destroyed, if redo() hasn't been called, the node will be destroyed too - node->setParent(&memory_manager_); + // Ensures that when this command is destroyed, if redo() is never called again, the node will be destroyed too + node_->setParent(&memory_manager_); } void NodeAddCommand::redo() diff --git a/app/widget/nodeview/nodeviewundo.h b/app/widget/nodeview/nodeviewundo.h index 77457da5c..72dcfaffc 100644 --- a/app/widget/nodeview/nodeviewundo.h +++ b/app/widget/nodeview/nodeviewundo.h @@ -5,6 +5,7 @@ #include "node/graph.h" #include "node/node.h" +#include "nodeviewitem.h" /** * @brief An undoable commnd for connecting two NodeParams together @@ -62,7 +63,9 @@ private: class NodeRemoveCommand : public QUndoCommand { public: - NodeRemoveCommand(NodeGraph* graph, const QList& nodes, QUndoCommand* parent = nullptr); + NodeRemoveCommand(NodeGraph* graph, + const QList& nodes, + QUndoCommand* parent = nullptr); virtual void redo() override; virtual void undo() override; diff --git a/app/widget/timelinewidget/timelinewidget.cpp b/app/widget/timelinewidget/timelinewidget.cpp index 673cf315c..5dc1047e2 100644 --- a/app/widget/timelinewidget/timelinewidget.cpp +++ b/app/widget/timelinewidget/timelinewidget.cpp @@ -8,6 +8,7 @@ #include "common/timecodefunctions.h" #include "tool/tool.h" #include "trackview/trackview.h" +#include "widget/nodeview/nodeviewundo.h" TimelineWidget::TimelineWidget(QWidget *parent) : QWidget(parent), @@ -382,6 +383,18 @@ void TimelineWidget::SplitAtPlayhead() } } +void TimelineWidget::DeleteSelected() +{ + QList list = GetSelectedBlocks(); + + // No-op if nothing is selected + if (list.isEmpty()) { + return; + } + + +} + QList TimelineWidget::GetSelectedBlocks() { QList list; @@ -440,14 +453,19 @@ void TimelineWidget::RippleEditTo(olive::timeline::MovementMode mode, bool inser rational ripple_length = out_ripple - in_ripple; foreach (TrackOutput* track, timeline_node_->Tracks()) { + GapBlock* gap = nullptr; + if (insert_gaps) { + gap = new GapBlock(); + gap->set_length(ripple_length); + new NodeAddCommand(static_cast(track->parent()), gap, command); + } + TrackRippleRemoveAreaCommand* ripple_command = new TrackRippleRemoveAreaCommand(track, in_ripple, out_ripple, command); if (insert_gaps) { - GapBlock* gap = new GapBlock(); - gap->set_length(ripple_length); ripple_command->SetInsert(gap); } } diff --git a/app/widget/timelinewidget/timelinewidget.h b/app/widget/timelinewidget/timelinewidget.h index 3fe8bd47a..caa0649e7 100644 --- a/app/widget/timelinewidget/timelinewidget.h +++ b/app/widget/timelinewidget/timelinewidget.h @@ -51,6 +51,8 @@ public: void SplitAtPlayhead(); + void DeleteSelected(); + QList GetSelectedBlocks(); public slots: diff --git a/app/widget/timelinewidget/tool/add.cpp b/app/widget/timelinewidget/tool/add.cpp index b9b9ef538..11cd20bae 100644 --- a/app/widget/timelinewidget/tool/add.cpp +++ b/app/widget/timelinewidget/tool/add.cpp @@ -1,6 +1,7 @@ #include "widget/timelinewidget/timelinewidget.h" #include "core.h" +#include "widget/nodeview/nodeviewundo.h" TimelineWidget::AddTool::AddTool(TimelineWidget *parent) : Tool(parent), @@ -46,12 +47,21 @@ void TimelineWidget::AddTool::MouseRelease(TimelineViewMouseEvent *event) if (ghost_) { if (!ghost_->AdjustedLength().isNull()) { + QUndoCommand* command = new QUndoCommand(); + ClipBlock* clip = new ClipBlock(); clip->set_length(ghost_->AdjustedLength()); - olive::undo_stack.push(new TrackPlaceBlockCommand(parent()->timeline_node_->track_list(track.type()), - track.index(), - clip, - ghost_->GetAdjustedIn())); + new NodeAddCommand(static_cast(parent()->timeline_node_->parent()), + clip, + command); + + new TrackPlaceBlockCommand(parent()->timeline_node_->track_list(track.type()), + track.index(), + clip, + ghost_->GetAdjustedIn(), + command); + + olive::undo_stack.push(command); } parent()->ClearGhosts(); diff --git a/app/widget/timelinewidget/tool/import.cpp b/app/widget/timelinewidget/tool/import.cpp index 1a4b4ad53..fa4cb3e5b 100644 --- a/app/widget/timelinewidget/tool/import.cpp +++ b/app/widget/timelinewidget/tool/import.cpp @@ -30,6 +30,7 @@ #include "node/color/opacity/opacity.h" #include "node/input/media/audio/audio.h" #include "node/input/media/video/video.h" +#include "widget/nodeview/nodeviewundo.h" TrackType TrackTypeFromStreamType(Stream::Type stream_type) { @@ -207,6 +208,7 @@ void TimelineWidget::ImportTool::DragDrop(TimelineViewMouseEvent *event) { if (parent()->HasGhosts()) { QUndoCommand* command = new QUndoCommand(); + NodeGraph* dst_graph = static_cast(parent()->timeline_node_->parent()); QVector block_items(parent()->ghost_items_.size()); @@ -218,6 +220,7 @@ void TimelineWidget::ImportTool::DragDrop(TimelineViewMouseEvent *event) ClipBlock* clip = new ClipBlock(); clip->set_length(ghost->Length()); clip->set_block_name(footage_stream->footage()->name()); + new NodeAddCommand(dst_graph, clip, command); switch (footage_stream->type()) { case Stream::kVideo: @@ -225,10 +228,12 @@ void TimelineWidget::ImportTool::DragDrop(TimelineViewMouseEvent *event) { VideoInput* video_input = new VideoInput(); video_input->SetFootage(footage_stream); - NodeParam::ConnectEdge(video_input->output(), clip->texture_input()); + new NodeAddCommand(dst_graph, video_input, command); + new NodeEdgeAddCommand(video_input->output(), clip->texture_input(), command); TransformDistort* transform = new TransformDistort(); - NodeParam::ConnectEdge(transform->output(), video_input->matrix_input()); + new NodeAddCommand(dst_graph, transform, command); + new NodeEdgeAddCommand(transform->output(), video_input->matrix_input(), command); //OpacityNode* opacity = new OpacityNode(); //NodeParam::ConnectEdge(opacity->texture_output(), clip->texture_input()); @@ -239,7 +244,8 @@ void TimelineWidget::ImportTool::DragDrop(TimelineViewMouseEvent *event) { AudioInput* audio_input = new AudioInput(); audio_input->SetFootage(footage_stream); - NodeParam::ConnectEdge(audio_input->output(), clip->texture_input()); + new NodeAddCommand(dst_graph, audio_input, command); + new NodeEdgeAddCommand(audio_input->output(), clip->texture_input(), command); break; } default: diff --git a/app/widget/timelinewidget/tool/pointer.cpp b/app/widget/timelinewidget/tool/pointer.cpp index 98952deee..6b3a38fb0 100644 --- a/app/widget/timelinewidget/tool/pointer.cpp +++ b/app/widget/timelinewidget/tool/pointer.cpp @@ -30,6 +30,7 @@ #include "config/config.h" #include "core.h" #include "node/block/gap/gap.h" +#include "widget/nodeview/nodeviewundo.h" TimelineWidget::PointerTool::PointerTool(TimelineWidget *parent) : Tool(parent), @@ -158,10 +159,6 @@ void TimelineWidget::PointerTool::MouseReleaseInternal(TimelineViewMouseEvent *e { Q_UNUSED(event) - // We create a QObject on the stack so that when we allocate objects on the heap, they aren't parent-less and will - // get cleaned up if they aren't re-parented by the attached NodeGraph - QObject block_memory_manager; - QUndoCommand* command = new QUndoCommand(); // Since all the ghosts will be leaving their old position in some way, we replace all of them with gaps here so the @@ -171,9 +168,12 @@ void TimelineWidget::PointerTool::MouseReleaseInternal(TimelineViewMouseEvent *e // Replace old Block with a new Gap GapBlock* gap = new GapBlock(); - gap->setParent(&block_memory_manager); gap->set_length(b->length()); + new NodeAddCommand(static_cast(b->parent()), + gap, + command); + new TrackReplaceBlockCommand(parent()->GetTrackFromReference(ghost->Track()), b, gap, diff --git a/app/widget/timelinewidget/tool/ripple.cpp b/app/widget/timelinewidget/tool/ripple.cpp index 3d9f5f2cc..9bc3148b7 100644 --- a/app/widget/timelinewidget/tool/ripple.cpp +++ b/app/widget/timelinewidget/tool/ripple.cpp @@ -21,6 +21,7 @@ #include "widget/timelinewidget/timelinewidget.h" #include "node/block/gap/gap.h" +#include "widget/nodeview/nodeviewundo.h" TimelineWidget::RippleTool::RippleTool(TimelineWidget* parent) : PointerTool(parent) @@ -48,13 +49,15 @@ void TimelineWidget::RippleTool::MouseReleaseInternal(TimelineViewMouseEvent *ev if (ghost->AdjustedLength() > 0) { GapBlock* gap = new GapBlock(); gap->set_length(ghost->AdjustedLength()); + new NodeAddCommand(static_cast(parent()->timeline_node_->parent()), gap, command); Block* block_to_append_gap_to = Node::ValueToPtr(ghost->data(TimelineViewGhostItem::kReferenceBlock)); new TrackInsertBlockBetweenBlocksCommand(parent()->GetTrackFromReference(ghost->Track()), gap, block_to_append_gap_to, - block_to_append_gap_to->next()); + block_to_append_gap_to->next(), + command); } } else { // This was a Block that already existed @@ -68,6 +71,8 @@ void TimelineWidget::RippleTool::MouseReleaseInternal(TimelineViewMouseEvent *ev } else { // Assumed the Block was a Gap and it was reduced to zero length, remove it here new TrackRippleRemoveBlockCommand(parent()->GetTrackFromReference(ghost->Track()), b, command); + + new NodeRemoveCommand(static_cast(b->parent()), {b}, command); } } } diff --git a/app/widget/timelinewidget/tool/rolling.cpp b/app/widget/timelinewidget/tool/rolling.cpp index 4e51f9454..1435c0d4f 100644 --- a/app/widget/timelinewidget/tool/rolling.cpp +++ b/app/widget/timelinewidget/tool/rolling.cpp @@ -21,6 +21,7 @@ #include "widget/timelinewidget/timelinewidget.h" #include "node/block/gap/gap.h" +#include "widget/nodeview/nodeviewundo.h" TimelineWidget::RollingTool::RollingTool(TimelineWidget* parent) : PointerTool(parent) @@ -43,6 +44,9 @@ void TimelineWidget::RollingTool::MouseReleaseInternal(TimelineViewMouseEvent *e // We'll need to insert a gap here, so we'll do a Place command instead GapBlock* gap = new GapBlock(); gap->set_length(ghost->Length()); + new NodeAddCommand(static_cast(b->parent()), + gap, + command); new TrackReplaceBlockCommand(parent()->GetTrackFromReference(ghost->Track()), b, gap, command); } diff --git a/app/widget/timelinewidget/tool/slide.cpp b/app/widget/timelinewidget/tool/slide.cpp index 55c7db3e6..cc2b38e62 100644 --- a/app/widget/timelinewidget/tool/slide.cpp +++ b/app/widget/timelinewidget/tool/slide.cpp @@ -21,6 +21,7 @@ #include "widget/timelinewidget/timelinewidget.h" #include "node/block/gap/gap.h" +#include "widget/nodeview/nodeviewundo.h" TimelineWidget::SlideTool::SlideTool(TimelineWidget* parent) : PointerTool(parent) @@ -46,6 +47,7 @@ void TimelineWidget::SlideTool::MouseReleaseInternal(TimelineViewMouseEvent *eve } else if (ghost->mode() == olive::timeline::kMove && b->previous() == nullptr) { GapBlock* gap = new GapBlock(); gap->set_length(ghost->InAdjustment()); + new NodeAddCommand(static_cast(b->parent()), gap, command); new TrackPrependBlockCommand(parent()->GetTrackFromReference(ghost->Track()), gap, command); } } diff --git a/app/widget/timelinewidget/tool/transition.cpp b/app/widget/timelinewidget/tool/transition.cpp index c32790fe8..2699821c2 100644 --- a/app/widget/timelinewidget/tool/transition.cpp +++ b/app/widget/timelinewidget/tool/transition.cpp @@ -94,6 +94,9 @@ void TimelineWidget::TransitionTool::MouseRelease(TimelineViewMouseEvent *event) QUndoCommand* command = new QUndoCommand(); // Place transition in place + new NodeAddCommand(static_cast(parent()->timeline_node_->parent()), + transition, + command); new TrackPlaceBlockCommand(parent()->timeline_node_->track_list(track.type()), track.index(), transition, diff --git a/app/widget/timelinewidget/undo/undo.cpp b/app/widget/timelinewidget/undo/undo.cpp index 79a1c16d4..2314ad1d7 100644 --- a/app/widget/timelinewidget/undo/undo.cpp +++ b/app/widget/timelinewidget/undo/undo.cpp @@ -183,7 +183,7 @@ void TrackRippleRemoveAreaCommand::redo() splice_original_length_ = splice_->length(); splice_->set_length(out_ - splice_->in()); - track_->AddBlockToGraph(copy); + static_cast(track_->parent())->AddNode(copy); Node::CopyInputs(splice_, copy); track_->InsertBlockAfter(copy, splice_); @@ -213,6 +213,8 @@ void TrackRippleRemoveAreaCommand::redo() // Remove all blocks that are flagged for removal foreach (Block* remove_block, removed_blocks_) { track_->RippleRemoveBlock(remove_block); + + // FIXME: Delete blocks from graph and restore them in undo } // If we picked up a block to trim the out point of @@ -221,13 +223,12 @@ void TrackRippleRemoveAreaCommand::redo() } // If we were given a block to insert, insert it here - if (insert_ != nullptr) { - track_->AddBlockToGraph(insert_); - - if (trim_out_ == nullptr) { + if (insert_) { + qDebug() << "Insert is" << insert_ << ", parent is" << insert_->parent(); + if (!trim_out_) { // This is the start of the Sequence track_->PrependBlock(insert_); - } else if (trim_in_ == nullptr) { + } else if (!trim_in_) { // This is the end of the Sequence track_->AppendBlock(insert_); } else { @@ -291,7 +292,6 @@ TrackPlaceBlockCommand::TrackPlaceBlockCommand(TrackList *timeline, int track, B gap_(nullptr) { insert_ = block; - insert_->setParent(&memory_manager_); } void TrackPlaceBlockCommand::redo() @@ -315,6 +315,7 @@ void TrackPlaceBlockCommand::redo() // If so, insert a gap here gap_ = new GapBlock(); gap_->set_length(in_ - track_->track_length()); + static_cast(track_->parent())->AddNode(gap_); track_->AppendBlock(gap_); } @@ -331,7 +332,6 @@ void TrackPlaceBlockCommand::undo() { if (append_) { track_->RippleRemoveBlock(insert_); - TakeNodeFromParentGraph(insert_, &memory_manager_); if (gap_ != nullptr) { track_->RippleRemoveBlock(gap_); @@ -365,7 +365,7 @@ void BlockSplitCommand::redo() block_->set_length(new_length_); - track_->AddBlockToGraph(new_block_); + static_cast(block_->parent())->AddNode(new_block_); Node::CopyInputs(block_, new_block_); // Will re-parent new_block_ to the track's graph