reworked all timeline commands
I'll be honest, this stuff probably caused a lot of crashes. Objects were constantly created and destroyed without the foresight that other commands might be using them. This should fix a lot of that.
This commit is contained in:
@@ -31,6 +31,7 @@ Block::Block() :
|
||||
previous_(nullptr),
|
||||
next_(nullptr),
|
||||
track_(nullptr),
|
||||
index_(-1),
|
||||
in_transition_(nullptr),
|
||||
out_transition_(nullptr)
|
||||
{
|
||||
|
||||
@@ -165,6 +165,16 @@ public:
|
||||
out_transition_ = t;
|
||||
}
|
||||
|
||||
int index() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
void set_index(int i)
|
||||
{
|
||||
index_ = i;
|
||||
}
|
||||
|
||||
virtual void Hash(QCryptographicHash &hash, const rational &time) const override;
|
||||
|
||||
public slots:
|
||||
@@ -201,6 +211,7 @@ private:
|
||||
rational in_point_;
|
||||
rational out_point_;
|
||||
Track* track_;
|
||||
int index_;
|
||||
|
||||
TransitionBlock* in_transition_;
|
||||
TransitionBlock* out_transition_;
|
||||
|
||||
@@ -286,7 +286,8 @@ void Track::InvalidateCache(const TimeRange& range, const InputConnection& from)
|
||||
|
||||
limited = TimeRange(qMax(range.in(), b->in()), qMin(range.out(), b->out()));
|
||||
} else {
|
||||
limited = TimeRange(qMax(range.in(), rational(0)), qMin(range.out(), track_length()));
|
||||
limited = TimeRange(qMax(range.in(), rational(0)), qMin(range.out(), last_invalidated_length_));
|
||||
last_invalidated_length_ = track_length();
|
||||
}
|
||||
|
||||
Node::InvalidateCache(limited, from);
|
||||
@@ -294,19 +295,27 @@ void Track::InvalidateCache(const TimeRange& range, const InputConnection& from)
|
||||
|
||||
void Track::InsertBlockBefore(Block* block, Block* after)
|
||||
{
|
||||
InsertBlockAtIndex(block, blocks_.indexOf(after));
|
||||
if (!after) {
|
||||
AppendBlock(block);
|
||||
} else {
|
||||
InsertBlockAtIndex(block, blocks_.indexOf(after));
|
||||
}
|
||||
}
|
||||
|
||||
void Track::InsertBlockAfter(Block *block, Block *before)
|
||||
{
|
||||
int before_index = blocks_.indexOf(before);
|
||||
|
||||
Q_ASSERT(before_index >= 0);
|
||||
|
||||
if (before_index == blocks_.size() - 1) {
|
||||
AppendBlock(block);
|
||||
if (!before) {
|
||||
PrependBlock(block);
|
||||
} else {
|
||||
InsertBlockAtIndex(block, before_index + 1);
|
||||
int before_index = blocks_.indexOf(before);
|
||||
|
||||
Q_ASSERT(before_index >= 0);
|
||||
|
||||
if (before_index == blocks_.size() - 1) {
|
||||
AppendBlock(block);
|
||||
} else {
|
||||
InsertBlockAtIndex(block, before_index + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,7 +329,7 @@ void Track::PrependBlock(Block *block)
|
||||
EndOperation();
|
||||
|
||||
// Everything has shifted at this point
|
||||
Node::InvalidateCache(TimeRange(0, track_length()), InputConnection());
|
||||
InvalidateCache(TimeRange(0, track_length()));
|
||||
}
|
||||
|
||||
void Track::InsertBlockAtIndex(Block *block, int index)
|
||||
@@ -333,7 +342,7 @@ void Track::InsertBlockAtIndex(Block *block, int index)
|
||||
|
||||
EndOperation();
|
||||
|
||||
Node::InvalidateCache(TimeRange(block->in(), track_length()));
|
||||
InvalidateCache(TimeRange(block->in(), track_length()));
|
||||
}
|
||||
|
||||
void Track::AppendBlock(Block *block)
|
||||
@@ -346,7 +355,7 @@ void Track::AppendBlock(Block *block)
|
||||
EndOperation();
|
||||
|
||||
// Invalidate area that block was added to
|
||||
Node::InvalidateCache(TimeRange(block->in(), track_length()));
|
||||
InvalidateCache(TimeRange(block->in(), track_length()));
|
||||
}
|
||||
|
||||
void Track::RippleRemoveBlock(Block *block)
|
||||
@@ -360,7 +369,7 @@ void Track::RippleRemoveBlock(Block *block)
|
||||
|
||||
EndOperation();
|
||||
|
||||
Node::InvalidateCache(TimeRange(remove_in, qMax(track_length(), remove_out)));
|
||||
InvalidateCache(TimeRange(remove_in, qMax(track_length(), remove_out)));
|
||||
}
|
||||
|
||||
void Track::ReplaceBlock(Block *old, Block *replace)
|
||||
@@ -376,9 +385,9 @@ void Track::ReplaceBlock(Block *old, Block *replace)
|
||||
EndOperation();
|
||||
|
||||
if (old->length() == replace->length()) {
|
||||
Node::InvalidateCache(TimeRange(replace->in(), replace->out()));
|
||||
InvalidateCache(TimeRange(replace->in(), replace->out()));
|
||||
} else {
|
||||
Node::InvalidateCache(TimeRange(replace->in(), RATIONAL_MAX));
|
||||
InvalidateCache(TimeRange(replace->in(), RATIONAL_MAX));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,7 +441,7 @@ void Track::Hash(QCryptographicHash &hash, const rational &time) const
|
||||
void Track::SetMuted(bool e)
|
||||
{
|
||||
muted_input_->SetStandardValue(e);
|
||||
Node::InvalidateCache(TimeRange(0, track_length()));
|
||||
InvalidateCache(TimeRange(0, track_length()));
|
||||
}
|
||||
|
||||
void Track::SetLocked(bool e)
|
||||
@@ -454,6 +463,8 @@ void Track::UpdateInOutFrom(int index)
|
||||
last_out += b->length();
|
||||
|
||||
b->set_out(last_out);
|
||||
|
||||
b->set_index(i);
|
||||
}
|
||||
|
||||
emit BlocksRefreshed();
|
||||
@@ -480,13 +491,16 @@ int Track::GetCacheIndexFromArrayIndex(int index) const
|
||||
void Track::SetLengthInternal(const rational &r, bool invalidate)
|
||||
{
|
||||
if (r != track_length_) {
|
||||
// TimeRange will automatically normalize so that the shorter number is the in and the longer
|
||||
// is the out
|
||||
TimeRange invalidate_range(track_length_, r);
|
||||
|
||||
track_length_ = r;
|
||||
last_invalidated_length_ = qMax(last_invalidated_length_, track_length_);
|
||||
emit TrackLengthChanged();
|
||||
|
||||
if (invalidate) {
|
||||
Node::InvalidateCache(invalidate_range);
|
||||
InvalidateCache(invalidate_range);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -557,7 +571,7 @@ void Track::BlockConnected(Node *node, int element)
|
||||
connect(block, &Block::LengthChanged, this, &Track::BlockLengthChanged);
|
||||
|
||||
// Invalidate cache now that block should have an in point
|
||||
Node::InvalidateCache(TimeRange(block->in(), track_length()));
|
||||
InvalidateCache(TimeRange(block->in(), track_length()));
|
||||
|
||||
// Emit block added signal
|
||||
emit BlockAdded(block);
|
||||
@@ -615,7 +629,7 @@ void Track::BlockDisconnected(Node* node, int element)
|
||||
|
||||
disconnect(b, &Block::LengthChanged, this, &Track::BlockLengthChanged);
|
||||
|
||||
Node::InvalidateCache(invalidate_range);
|
||||
InvalidateCache(invalidate_range);
|
||||
}
|
||||
|
||||
void Track::BlockLengthChanged()
|
||||
@@ -631,7 +645,7 @@ void Track::BlockLengthChanged()
|
||||
|
||||
TimeRange invalidate_region(qMin(old_out, new_out), track_length());
|
||||
|
||||
Node::InvalidateCache(invalidate_region);
|
||||
InvalidateCache(invalidate_region);
|
||||
}
|
||||
|
||||
void Track::MutedInputValueChanged()
|
||||
|
||||
@@ -220,7 +220,7 @@ public:
|
||||
return blocks_;
|
||||
}
|
||||
|
||||
virtual void InvalidateCache(const TimeRange& range, const InputConnection& from) override;
|
||||
virtual void InvalidateCache(const TimeRange& range, const InputConnection& from = InputConnection()) override;
|
||||
|
||||
/**
|
||||
* @brief Adds Block `block` at the very beginning of the Sequence before all other clips
|
||||
@@ -358,6 +358,8 @@ private:
|
||||
|
||||
rational track_length_;
|
||||
|
||||
rational last_invalidated_length_;
|
||||
|
||||
double track_height_;
|
||||
|
||||
int index_;
|
||||
|
||||
@@ -22,7 +22,6 @@ set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
widget/timelinewidget/timelineandtrackview.cpp
|
||||
widget/timelinewidget/timelineandtrackview.h
|
||||
widget/timelinewidget/timelineundo.cpp
|
||||
widget/timelinewidget/timelineundo.h
|
||||
widget/timelinewidget/timelinewidget.cpp
|
||||
widget/timelinewidget/timelinewidget.h
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -469,9 +469,7 @@ void TimelineWidget::DeleteSelected(bool ripple)
|
||||
|
||||
// For transitions, remove them but extend their attached blocks to fill their place
|
||||
foreach (TransitionBlock* transition, transitions_to_delete) {
|
||||
new TransitionRemoveCommand(transition->track(),
|
||||
transition,
|
||||
command);
|
||||
new TransitionRemoveCommand(transition, command);
|
||||
|
||||
Node::RemoveNodesAndExclusiveDependencies(transition, command);
|
||||
}
|
||||
@@ -480,7 +478,7 @@ void TimelineWidget::DeleteSelected(bool ripple)
|
||||
ReplaceBlocksWithGaps(clips_to_delete, true, command);
|
||||
|
||||
// Remove all selections
|
||||
new TimelineSetSelectionsCommand(this, TimelineWidgetSelections(), GetSelections(), command);
|
||||
new SetSelectionsCommand(this, TimelineWidgetSelections(), GetSelections(), command);
|
||||
|
||||
// Insert ripple command now that it's all cleaned up gaps
|
||||
if (ripple) {
|
||||
|
||||
@@ -195,6 +195,34 @@ public:
|
||||
*/
|
||||
void SignalDeselectedAllBlocks();
|
||||
|
||||
class SetSelectionsCommand : public QUndoCommand {
|
||||
public:
|
||||
SetSelectionsCommand(TimelineWidget* timeline, const TimelineWidgetSelections& now, const TimelineWidgetSelections& old, QUndoCommand* parent = nullptr) :
|
||||
QUndoCommand(parent),
|
||||
timeline_(timeline),
|
||||
old_(old),
|
||||
now_(now)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo() override
|
||||
{
|
||||
timeline_->SetSelections(now_);
|
||||
}
|
||||
|
||||
virtual void undo() override
|
||||
{
|
||||
timeline_->SetSelections(old_);
|
||||
}
|
||||
|
||||
private:
|
||||
TimelineWidget* timeline_;
|
||||
TimelineWidgetSelections old_;
|
||||
TimelineWidgetSelections now_;
|
||||
|
||||
};
|
||||
|
||||
signals:
|
||||
void BlocksSelected(const QVector<Block*>& selected_blocks);
|
||||
|
||||
|
||||
@@ -590,7 +590,7 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
} else {
|
||||
new_sel.TrimOut(reference_ghost->GetOutAdjustment());
|
||||
}
|
||||
new TimelineSetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), command);
|
||||
new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), command);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -655,7 +655,7 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
TimelineWidgetSelections new_sel = parent()->GetSelections();
|
||||
new_sel.ShiftTime(blocks_moving.first().ghost->GetInAdjustment());
|
||||
new_sel.ShiftTracks(drag_track_type_, blocks_moving.first().ghost->GetTrackAdjustment());
|
||||
new TimelineSetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), command);
|
||||
new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), command);
|
||||
}
|
||||
|
||||
if (!blocks_sliding.isEmpty()) {
|
||||
@@ -717,7 +717,7 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
// Adjust selections
|
||||
TimelineWidgetSelections new_sel = parent()->GetSelections();
|
||||
new_sel.ShiftTime(movement);
|
||||
new TimelineSetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), command);
|
||||
new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), command);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ void RippleTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
} else {
|
||||
new_sel.TrimOut(reference_ghost->GetOutAdjustment());
|
||||
}
|
||||
new TimelineSetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), command);
|
||||
new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), command);
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
|
||||
Reference in New Issue
Block a user