began some rewrites to timeline drawing
This commit is contained in:
@@ -29,7 +29,10 @@ namespace olive {
|
||||
|
||||
Block::Block() :
|
||||
previous_(nullptr),
|
||||
next_(nullptr)
|
||||
next_(nullptr),
|
||||
track_(nullptr),
|
||||
in_transition_(nullptr),
|
||||
out_transition_(nullptr)
|
||||
{
|
||||
length_input_ = new NodeInput(this, QStringLiteral("length_in"), NodeValue::kRational);
|
||||
length_input_->SetConnectable(false);
|
||||
@@ -59,26 +62,6 @@ QVector<Node::CategoryID> Block::Category() const
|
||||
return {kCategoryTimeline};
|
||||
}
|
||||
|
||||
const rational &Block::in() const
|
||||
{
|
||||
return in_point_;
|
||||
}
|
||||
|
||||
const rational &Block::out() const
|
||||
{
|
||||
return out_point_;
|
||||
}
|
||||
|
||||
void Block::set_in(const rational &in)
|
||||
{
|
||||
in_point_ = in;
|
||||
}
|
||||
|
||||
void Block::set_out(const rational &out)
|
||||
{
|
||||
out_point_ = out;
|
||||
}
|
||||
|
||||
rational Block::length() const
|
||||
{
|
||||
return length_input_->GetStandardValue().value<rational>();
|
||||
@@ -110,31 +93,6 @@ void Block::set_length_and_media_in(const rational &length)
|
||||
set_length_internal(length);
|
||||
}
|
||||
|
||||
TimeRange Block::range() const
|
||||
{
|
||||
return TimeRange(in(), out());
|
||||
}
|
||||
|
||||
Block *Block::previous()
|
||||
{
|
||||
return previous_;
|
||||
}
|
||||
|
||||
Block *Block::next()
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
void Block::set_previous(Block *previous)
|
||||
{
|
||||
previous_ = previous;
|
||||
}
|
||||
|
||||
void Block::set_next(Block *next)
|
||||
{
|
||||
next_ = next;
|
||||
}
|
||||
|
||||
rational Block::media_in() const
|
||||
{
|
||||
return media_in_input_->GetStandardValue().value<rational>();
|
||||
@@ -309,16 +267,6 @@ bool Block::AreLinked(Block *a, Block *b)
|
||||
return a->linked_clips_.contains(b);
|
||||
}
|
||||
|
||||
const QVector<Block*> &Block::linked_clips()
|
||||
{
|
||||
return linked_clips_;
|
||||
}
|
||||
|
||||
bool Block::HasLinks()
|
||||
{
|
||||
return !linked_clips_.isEmpty();
|
||||
}
|
||||
|
||||
void Block::Retranslate()
|
||||
{
|
||||
Node::Retranslate();
|
||||
@@ -329,21 +277,6 @@ void Block::Retranslate()
|
||||
speed_input_->set_name(tr("Speed"));
|
||||
}
|
||||
|
||||
NodeInput *Block::length_input() const
|
||||
{
|
||||
return length_input_;
|
||||
}
|
||||
|
||||
NodeInput *Block::media_in_input() const
|
||||
{
|
||||
return media_in_input_;
|
||||
}
|
||||
|
||||
NodeInput *Block::speed_input() const
|
||||
{
|
||||
return speed_input_;
|
||||
}
|
||||
|
||||
void Block::Hash(QCryptographicHash &, const rational &) const
|
||||
{
|
||||
// A block does nothing by default, so we hash nothing
|
||||
|
||||
+102
-14
@@ -26,6 +26,8 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
class TransitionBlock;
|
||||
|
||||
/**
|
||||
* @brief A Node that represents a block of time, also displayable on a Timeline
|
||||
*/
|
||||
@@ -45,25 +47,68 @@ public:
|
||||
|
||||
virtual QVector<CategoryID> Category() const override;
|
||||
|
||||
const rational& in() const;
|
||||
const rational& out() const;
|
||||
void set_in(const rational& in);
|
||||
void set_out(const rational& out);
|
||||
const rational& in() const
|
||||
{
|
||||
return in_point_;
|
||||
}
|
||||
|
||||
const rational& out() const
|
||||
{
|
||||
return out_point_;
|
||||
}
|
||||
|
||||
void set_in(const rational& in)
|
||||
{
|
||||
in_point_ = in;
|
||||
}
|
||||
|
||||
void set_out(const rational& out)
|
||||
{
|
||||
out_point_ = out;
|
||||
}
|
||||
|
||||
rational length() const;
|
||||
void set_length_and_media_out(const rational &length);
|
||||
void set_length_and_media_in(const rational &length);
|
||||
|
||||
TimeRange range() const;
|
||||
TimeRange range() const
|
||||
{
|
||||
return TimeRange(in(), out());
|
||||
}
|
||||
|
||||
Block* previous();
|
||||
Block* next();
|
||||
void set_previous(Block* previous);
|
||||
void set_next(Block* next);
|
||||
Block* previous() const
|
||||
{
|
||||
return previous_;
|
||||
}
|
||||
|
||||
Block* next() const
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
void set_previous(Block* previous)
|
||||
{
|
||||
previous_ = previous;
|
||||
}
|
||||
|
||||
void set_next(Block* next)
|
||||
{
|
||||
next_ = next;
|
||||
}
|
||||
|
||||
rational media_in() const;
|
||||
void set_media_in(const rational& media_in);
|
||||
|
||||
Track* track() const
|
||||
{
|
||||
return track_;
|
||||
}
|
||||
|
||||
void set_track(Track* track)
|
||||
{
|
||||
track_ = track;
|
||||
}
|
||||
|
||||
bool is_enabled() const;
|
||||
void set_enabled(bool e);
|
||||
|
||||
@@ -72,14 +117,53 @@ public:
|
||||
static bool Unlink(Block* a, Block* b);
|
||||
static void Unlink(const QList<Block*>& blocks);
|
||||
static bool AreLinked(Block* a, Block* b);
|
||||
const QVector<Block*>& linked_clips();
|
||||
bool HasLinks();
|
||||
|
||||
const QVector<Block*>& linked_clips() const
|
||||
{
|
||||
return linked_clips_;
|
||||
}
|
||||
|
||||
bool HasLinks() const
|
||||
{
|
||||
return !linked_clips_.isEmpty();
|
||||
}
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
NodeInput* length_input() const;
|
||||
NodeInput* media_in_input() const;
|
||||
NodeInput* speed_input() const;
|
||||
NodeInput* length_input() const
|
||||
{
|
||||
return length_input_;
|
||||
}
|
||||
|
||||
NodeInput* media_in_input() const
|
||||
{
|
||||
return media_in_input_;
|
||||
}
|
||||
|
||||
NodeInput* speed_input() const
|
||||
{
|
||||
return speed_input_;
|
||||
}
|
||||
|
||||
TransitionBlock* in_transition()
|
||||
{
|
||||
return in_transition_;
|
||||
}
|
||||
|
||||
void set_in_transition(TransitionBlock* t)
|
||||
{
|
||||
in_transition_ = t;
|
||||
}
|
||||
|
||||
TransitionBlock* out_transition()
|
||||
{
|
||||
return out_transition_;
|
||||
}
|
||||
|
||||
void set_out_transition(TransitionBlock* t)
|
||||
{
|
||||
out_transition_ = t;
|
||||
}
|
||||
|
||||
virtual void Hash(QCryptographicHash &hash, const rational &time) const override;
|
||||
|
||||
@@ -116,6 +200,10 @@ private:
|
||||
|
||||
rational in_point_;
|
||||
rational out_point_;
|
||||
Track* track_;
|
||||
|
||||
TransitionBlock* in_transition_;
|
||||
TransitionBlock* out_transition_;
|
||||
|
||||
QVector<Block*> linked_clips_;
|
||||
|
||||
|
||||
@@ -172,23 +172,43 @@ void TransitionBlock::InsertTransitionTimes(AcceleratedJob *job, const double &t
|
||||
void TransitionBlock::OutBlockConnected(Node *node)
|
||||
{
|
||||
// If node is not a block, this will just be null
|
||||
connected_out_block_ = dynamic_cast<Block*>(node);
|
||||
if ((connected_out_block_ = dynamic_cast<Block*>(node))) {
|
||||
|
||||
Q_ASSERT(connected_out_block_->type() != Block::kTransition
|
||||
&& !connected_out_block_->out_transition()
|
||||
&& connected_out_block_ == this->previous());
|
||||
|
||||
connected_out_block_->set_out_transition(this);
|
||||
}
|
||||
}
|
||||
|
||||
void TransitionBlock::OutBlockDisconnected()
|
||||
{
|
||||
connected_out_block_ = nullptr;
|
||||
if (connected_out_block_) {
|
||||
connected_out_block_->set_in_transition(nullptr);
|
||||
connected_out_block_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void TransitionBlock::InBlockConnected(Node *node)
|
||||
{
|
||||
// If node is not a block, this will just be null
|
||||
connected_in_block_ = dynamic_cast<Block*>(node);
|
||||
if ((connected_in_block_ = dynamic_cast<Block*>(node))) {
|
||||
|
||||
Q_ASSERT(connected_in_block_->type() != Block::kTransition
|
||||
&& !connected_in_block_->in_transition()
|
||||
&& connected_in_block_ == this->next());
|
||||
|
||||
connected_in_block_->set_in_transition(this);
|
||||
}
|
||||
}
|
||||
|
||||
void TransitionBlock::InBlockDisconnected()
|
||||
{
|
||||
connected_in_block_ = nullptr;
|
||||
if (connected_in_block_) {
|
||||
connected_in_block_->set_in_transition(nullptr);
|
||||
connected_in_block_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NodeValueTable TransitionBlock::Value(NodeValueDatabase &value) const
|
||||
@@ -251,33 +271,6 @@ NodeValueTable TransitionBlock::Value(NodeValueDatabase &value) const
|
||||
return table;
|
||||
}
|
||||
|
||||
TransitionBlock *GetBlockTransitionInternal(Block *block, Timeline::MovementMode mode)
|
||||
{
|
||||
// See if this block outputs to a transition
|
||||
foreach (const NodeConnectable::InputConnection& conn, block->edges()) {
|
||||
TransitionBlock* transition = dynamic_cast<TransitionBlock*>(conn.input->parent());
|
||||
|
||||
if (transition) {
|
||||
if ((mode == Timeline::kTrimIn && conn.input == transition->in_block_input())
|
||||
|| (mode == Timeline::kTrimOut && conn.input == transition->out_block_input())) {
|
||||
return transition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TransitionBlock *TransitionBlock::GetBlockInTransition(Block *block)
|
||||
{
|
||||
return GetBlockTransitionInternal(block, Timeline::kTrimIn);
|
||||
}
|
||||
|
||||
TransitionBlock *TransitionBlock::GetBlockOutTransition(Block *block)
|
||||
{
|
||||
return GetBlockTransitionInternal(block, Timeline::kTrimOut);
|
||||
}
|
||||
|
||||
void TransitionBlock::ShaderJobEvent(NodeValueDatabase &value, ShaderJob &job) const
|
||||
{
|
||||
Q_UNUSED(value)
|
||||
|
||||
@@ -52,10 +52,6 @@ public:
|
||||
|
||||
virtual NodeValueTable Value(NodeValueDatabase &value) const override;
|
||||
|
||||
static TransitionBlock* GetBlockInTransition(Block* block);
|
||||
|
||||
static TransitionBlock* GetBlockOutTransition(Block* block);
|
||||
|
||||
protected:
|
||||
virtual void ShaderJobEvent(NodeValueDatabase &value, ShaderJob& job) const;
|
||||
|
||||
|
||||
@@ -60,12 +60,12 @@ Track::~Track()
|
||||
DisconnectAll();
|
||||
}
|
||||
|
||||
void Track::set_track_type(const Type &track_type)
|
||||
void Track::set_type(const Type &track_type)
|
||||
{
|
||||
track_type_ = track_type;
|
||||
}
|
||||
|
||||
const Track::Type& Track::track_type() const
|
||||
const Track::Type& Track::type() const
|
||||
{
|
||||
return track_type_;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ TimeRange Track::InputTimeAdjustment(NodeInput *input, int element, const TimeRa
|
||||
{
|
||||
if (input == block_input_ && element >= 0) {
|
||||
int cache_index = GetCacheIndexFromArrayIndex(element);
|
||||
const rational& block_in = blocks_.at(cache_index).range.in();
|
||||
const rational& block_in = blocks_.at(cache_index)->in();
|
||||
|
||||
return input_time - block_in;
|
||||
}
|
||||
@@ -112,7 +112,7 @@ TimeRange Track::OutputTimeAdjustment(NodeInput *input, int element, const TimeR
|
||||
{
|
||||
if (input == block_input_ && element >= 0) {
|
||||
int cache_index = GetCacheIndexFromArrayIndex(element);
|
||||
const rational& block_in = blocks_.at(cache_index).range.in();
|
||||
const rational& block_in = blocks_.at(cache_index)->in();
|
||||
|
||||
return input_time + block_in;
|
||||
}
|
||||
@@ -155,11 +155,6 @@ void Track::Retranslate()
|
||||
muted_input_->set_name(tr("Muted"));
|
||||
}
|
||||
|
||||
const int &Track::Index()
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
void Track::SetIndex(const int &index)
|
||||
{
|
||||
index_ = index;
|
||||
@@ -169,7 +164,7 @@ void Track::SetIndex(const int &index)
|
||||
|
||||
Block *Track::BlockContainingTime(const rational &time) const
|
||||
{
|
||||
foreach (Block* block, block_cache_) {
|
||||
foreach (Block* block, blocks_) {
|
||||
if (block->in() < time && block->out() > time) {
|
||||
return block;
|
||||
} else if (block->out() == time) {
|
||||
@@ -182,7 +177,7 @@ Block *Track::BlockContainingTime(const rational &time) const
|
||||
|
||||
Block *Track::NearestBlockBefore(const rational &time) const
|
||||
{
|
||||
foreach (Block* block, block_cache_) {
|
||||
foreach (Block* block, blocks_) {
|
||||
// Blocks are sorted by time, so the first Block who's out point is at/after this time is the correct Block
|
||||
if (block->out() >= time) {
|
||||
return block;
|
||||
@@ -194,7 +189,7 @@ Block *Track::NearestBlockBefore(const rational &time) const
|
||||
|
||||
Block *Track::NearestBlockBeforeOrAt(const rational &time) const
|
||||
{
|
||||
foreach (Block* block, block_cache_) {
|
||||
foreach (Block* block, blocks_) {
|
||||
// Blocks are sorted by time, so the first Block who's out point is at/after this time is the correct Block
|
||||
if (block->out() > time) {
|
||||
return block;
|
||||
@@ -206,7 +201,7 @@ Block *Track::NearestBlockBeforeOrAt(const rational &time) const
|
||||
|
||||
Block *Track::NearestBlockAfterOrAt(const rational &time) const
|
||||
{
|
||||
foreach (Block* block, block_cache_) {
|
||||
foreach (Block* block, blocks_) {
|
||||
// Blocks are sorted by time, so the first Block after this time is the correct Block
|
||||
if (block->in() >= time) {
|
||||
return block;
|
||||
@@ -218,7 +213,7 @@ Block *Track::NearestBlockAfterOrAt(const rational &time) const
|
||||
|
||||
Block *Track::NearestBlockAfter(const rational &time) const
|
||||
{
|
||||
foreach (Block* block, block_cache_) {
|
||||
foreach (Block* block, blocks_) {
|
||||
// Blocks are sorted by time, so the first Block after this time is the correct Block
|
||||
if (block->in() > time) {
|
||||
return block;
|
||||
@@ -234,7 +229,7 @@ Block *Track::BlockAtTime(const rational &time) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
foreach (Block* block, block_cache_) {
|
||||
foreach (Block* block, blocks_) {
|
||||
if (block
|
||||
&& block->in() <= time
|
||||
&& block->out() > time) {
|
||||
@@ -257,7 +252,7 @@ QVector<Block *> Track::BlocksAtTimeRange(const TimeRange &range) const
|
||||
return list;
|
||||
}
|
||||
|
||||
foreach (Block* block, block_cache_) {
|
||||
foreach (Block* block, blocks_) {
|
||||
if (block
|
||||
&& block->is_enabled()
|
||||
&& block->out() > range.in()
|
||||
@@ -293,16 +288,16 @@ void Track::InvalidateCache(const TimeRange& range, const InputConnection& from)
|
||||
|
||||
void Track::InsertBlockBefore(Block* block, Block* after)
|
||||
{
|
||||
InsertBlockAtIndex(block, block_cache_.indexOf(after));
|
||||
InsertBlockAtIndex(block, blocks_.indexOf(after));
|
||||
}
|
||||
|
||||
void Track::InsertBlockAfter(Block *block, Block *before)
|
||||
{
|
||||
int before_index = block_cache_.indexOf(before);
|
||||
int before_index = blocks_.indexOf(before);
|
||||
|
||||
Q_ASSERT(before_index >= 0);
|
||||
|
||||
if (before_index == block_cache_.size() - 1) {
|
||||
if (before_index == blocks_.size() - 1) {
|
||||
AppendBlock(block);
|
||||
} else {
|
||||
InsertBlockAtIndex(block, before_index + 1);
|
||||
@@ -326,7 +321,7 @@ void Track::InsertBlockAtIndex(Block *block, int index)
|
||||
{
|
||||
BeginOperation();
|
||||
|
||||
int insert_index = GetInputIndexFromCacheIndex(index);
|
||||
int insert_index = GetArrayIndexFromCacheIndex(index);
|
||||
block_input_->ArrayInsert(insert_index);
|
||||
Node::ConnectEdge(block, block_input_, insert_index);
|
||||
|
||||
@@ -355,7 +350,7 @@ void Track::RippleRemoveBlock(Block *block)
|
||||
rational remove_in = block->in();
|
||||
rational remove_out = block->out();
|
||||
|
||||
block_input_->ArrayRemove(GetInputIndexFromCacheIndex(block));
|
||||
block_input_->ArrayRemove(GetArrayIndexFromBlock(block));
|
||||
|
||||
EndOperation();
|
||||
|
||||
@@ -366,7 +361,7 @@ void Track::ReplaceBlock(Block *old, Block *replace)
|
||||
{
|
||||
BeginOperation();
|
||||
|
||||
int index_of_old_block = GetInputIndexFromCacheIndex(old);
|
||||
int index_of_old_block = GetArrayIndexFromBlock(old);
|
||||
|
||||
DisconnectEdge(old, block_input_, index_of_old_block);
|
||||
|
||||
@@ -442,11 +437,11 @@ void Track::SetLocked(bool e)
|
||||
void Track::UpdateInOutFrom(int index)
|
||||
{
|
||||
// Find block just before this one to find the last out point
|
||||
rational last_out = (index == 0) ? 0 : block_cache_.at(index - 1)->out();
|
||||
rational last_out = (index == 0) ? 0 : blocks_.at(index - 1)->out();
|
||||
|
||||
// Iterate through all blocks updating their in/outs
|
||||
for (int i=index; i<block_cache_.size(); i++) {
|
||||
Block* b = block_cache_.at(i);
|
||||
for (int i=index; i<blocks_.size(); i++) {
|
||||
Block* b = blocks_.at(i);
|
||||
|
||||
b->set_in(last_out);
|
||||
|
||||
@@ -455,24 +450,25 @@ void Track::UpdateInOutFrom(int index)
|
||||
b->set_out(last_out);
|
||||
}
|
||||
|
||||
emit BlocksRefreshed();
|
||||
|
||||
// Update track length
|
||||
SetLengthInternal(last_out);
|
||||
}
|
||||
|
||||
int Track::GetArrayIndexFromBlock(Block *block) const
|
||||
{
|
||||
return block_array_indexes_.at(blocks_.indexOf(block));
|
||||
}
|
||||
|
||||
int Track::GetArrayIndexFromCacheIndex(int index) const
|
||||
{
|
||||
return blocks_.at(index).array_index;
|
||||
return block_array_indexes_.at(index);
|
||||
}
|
||||
|
||||
int Track::GetCacheIndexFromArrayIndex(int index) const
|
||||
{
|
||||
for (int i=0; i<blocks_.size(); i++) {
|
||||
if (blocks_.at(i).array_index == index) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return block_array_indexes_.indexOf(index);
|
||||
}
|
||||
|
||||
void Track::SetLengthInternal(const rational &r, bool invalidate)
|
||||
@@ -504,36 +500,36 @@ void Track::BlockConnected(Node *node, int element)
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine where in the cache this block will be
|
||||
int cache_index = -1;
|
||||
Block *previous = nullptr, *next = nullptr;
|
||||
|
||||
for (int i=element-1; i>=0; i--) {
|
||||
// Find previous block
|
||||
previous = dynamic_cast<Block*>(block_input_->GetConnectedNode(i));
|
||||
for (int i=element+1; i<block_input_->ArraySize(); i++) {
|
||||
// Find next block because this will be the index that we want to insert at
|
||||
cache_index = GetCacheIndexFromArrayIndex(i);
|
||||
|
||||
if (previous) {
|
||||
if (cache_index >= 0) {
|
||||
next = blocks_.at(cache_index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find cache index
|
||||
int cache_index;
|
||||
if (previous) {
|
||||
// Insert block just after the previous block we found
|
||||
cache_index = block_cache_.indexOf(previous) + 1;
|
||||
// If there was no next, this will be inserted at the end
|
||||
if (cache_index == -1) {
|
||||
cache_index = blocks_.size();
|
||||
}
|
||||
|
||||
// Use current previous' next as our next
|
||||
next = previous->next();
|
||||
} else {
|
||||
// Didn't find a previous, so insert block at 0 (prepend it)
|
||||
cache_index = 0;
|
||||
|
||||
if (!block_cache_.isEmpty()) {
|
||||
next = block_cache_.first();
|
||||
}
|
||||
// Determine previous block, either by using next's previous or the last block if there was no
|
||||
// next. If there are neither, they'll both remain null
|
||||
if (next) {
|
||||
previous = next->previous();
|
||||
} else if (!blocks_.isEmpty()) {
|
||||
previous = blocks_.last();
|
||||
}
|
||||
|
||||
// Insert at index
|
||||
block_cache_.insert(cache_index, block);
|
||||
blocks_.insert(cache_index, block);
|
||||
block_array_indexes_.insert(cache_index, element);
|
||||
|
||||
// Update previous/next
|
||||
if (previous) {
|
||||
@@ -546,6 +542,8 @@ void Track::BlockConnected(Node *node, int element)
|
||||
next->set_previous(block);
|
||||
}
|
||||
|
||||
block->set_track(this);
|
||||
|
||||
// Update ins/outs
|
||||
UpdateInOutFrom(cache_index);
|
||||
|
||||
@@ -575,10 +573,16 @@ void Track::BlockDisconnected(Node* node, int element)
|
||||
|
||||
TimeRange invalidate_range(b->in(), track_length());
|
||||
|
||||
// FIXME: What happens if a user connects the same block twice? This must be addressed in the
|
||||
// upcoming timeline rewrite.
|
||||
block_cache_.removeOne(b);
|
||||
// Get cache index
|
||||
int cache_index = GetCacheIndexFromArrayIndex(element);
|
||||
|
||||
// Remove block here
|
||||
blocks_.removeAt(cache_index);
|
||||
block_array_indexes_.removeAt(cache_index);
|
||||
|
||||
emit BlockRemoved(b);
|
||||
|
||||
// Update previous/nexts
|
||||
Block* previous = b->previous();
|
||||
Block* next = b->next();
|
||||
|
||||
@@ -592,19 +596,19 @@ void Track::BlockDisconnected(Node* node, int element)
|
||||
|
||||
b->set_previous(nullptr);
|
||||
b->set_next(nullptr);
|
||||
b->set_track(nullptr);
|
||||
|
||||
// Update lengths
|
||||
if (next) {
|
||||
UpdateInOutFrom(block_cache_.indexOf(next));
|
||||
} else if (block_cache_.isEmpty()) {
|
||||
UpdateInOutFrom(blocks_.indexOf(next));
|
||||
} else if (blocks_.isEmpty()) {
|
||||
SetLengthInternal(rational());
|
||||
} else {
|
||||
SetLengthInternal(block_cache_.last()->out());
|
||||
SetLengthInternal(blocks_.last()->out());
|
||||
}
|
||||
|
||||
disconnect(b, &Block::LengthChanged, this, &Track::BlockLengthChanged);
|
||||
|
||||
emit BlockRemoved(b);
|
||||
|
||||
Node::InvalidateCache(invalidate_range);
|
||||
}
|
||||
|
||||
@@ -615,7 +619,7 @@ void Track::BlockLengthChanged()
|
||||
|
||||
rational old_out = b->out();
|
||||
|
||||
UpdateInOutFrom(block_cache_.indexOf(b));
|
||||
UpdateInOutFrom(blocks_.indexOf(b));
|
||||
|
||||
rational new_out = b->out();
|
||||
|
||||
@@ -629,4 +633,12 @@ void Track::MutedInputValueChanged()
|
||||
emit MutedChanged(IsMuted());
|
||||
}
|
||||
|
||||
uint qHash(const Track::Reference &r, uint seed)
|
||||
{
|
||||
// Not super efficient, but couldn't think of any better way to ensure a different hash each time
|
||||
return ::qHash(QStringLiteral("%1:%2").arg(QString::number(r.type()),
|
||||
QString::number(r.index())),
|
||||
seed);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -46,8 +46,8 @@ public:
|
||||
|
||||
virtual ~Track() override;
|
||||
|
||||
const Track::Type& track_type() const;
|
||||
void set_track_type(const Track::Type& track_type);
|
||||
const Track::Type& type() const;
|
||||
void set_type(const Track::Type& track_type);
|
||||
|
||||
virtual Node* copy() const override;
|
||||
|
||||
@@ -95,7 +95,58 @@ public:
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
const int& Index();
|
||||
class Reference
|
||||
{
|
||||
public:
|
||||
Reference() :
|
||||
type_(kNone),
|
||||
index_(-1)
|
||||
{
|
||||
}
|
||||
|
||||
Reference(const Track::Type& type, const int& index) :
|
||||
type_(type),
|
||||
index_(index)
|
||||
{
|
||||
}
|
||||
|
||||
const Track::Type& type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
const int& index() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
bool operator==(const Reference& ref) const
|
||||
{
|
||||
return type_ == ref.type_ && index_ == ref.index_;
|
||||
}
|
||||
|
||||
bool operator!=(const Reference& ref) const
|
||||
{
|
||||
return !(*this == ref);
|
||||
}
|
||||
|
||||
private:
|
||||
Track::Type type_;
|
||||
|
||||
int index_;
|
||||
|
||||
};
|
||||
|
||||
Reference ToReference() const
|
||||
{
|
||||
return Reference(type(), Index());
|
||||
}
|
||||
|
||||
const int& Index() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
void SetIndex(const int& index);
|
||||
|
||||
/**
|
||||
@@ -164,7 +215,7 @@ public:
|
||||
|
||||
const QVector<Block *> &Blocks() const
|
||||
{
|
||||
return block_cache_;
|
||||
return blocks_;
|
||||
}
|
||||
|
||||
virtual void InvalidateCache(const TimeRange& range, const InputConnection& from) override;
|
||||
@@ -273,6 +324,11 @@ signals:
|
||||
*/
|
||||
void PreviewChanged();
|
||||
|
||||
/**
|
||||
* @brief Emitted when a block changes length and all the subsequent blocks had to update
|
||||
*/
|
||||
void BlocksRefreshed();
|
||||
|
||||
protected:
|
||||
virtual void LoadInternal(QXmlStreamReader* reader, XMLNodeData& xml_node_data) override;
|
||||
|
||||
@@ -281,13 +337,16 @@ protected:
|
||||
private:
|
||||
void UpdateInOutFrom(int index);
|
||||
|
||||
int GetArrayIndexFromBlock(Block* block) const;
|
||||
|
||||
int GetArrayIndexFromCacheIndex(int index) const;
|
||||
|
||||
int GetCacheIndexFromArrayIndex(int index) const;
|
||||
|
||||
void SetLengthInternal(const rational& r, bool invalidate = true);
|
||||
|
||||
QVector<Block*> block_cache_;
|
||||
QVector<Block*> blocks_;
|
||||
QVector<int> block_array_indexes_;
|
||||
|
||||
NodeInput* block_input_;
|
||||
|
||||
@@ -316,6 +375,8 @@ private slots:
|
||||
|
||||
};
|
||||
|
||||
uint qHash(const Track::Reference& r, uint seed = 0);
|
||||
|
||||
}
|
||||
|
||||
#endif // TRACK_H
|
||||
|
||||
@@ -36,26 +36,6 @@ TrackList::TrackList(ViewerOutput *parent, const Track::Type &type, NodeInput *t
|
||||
connect(track_input_, &NodeInput::InputDisconnected, this, &TrackList::TrackDisconnected);
|
||||
}
|
||||
|
||||
const Track::Type &TrackList::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
void TrackList::TrackAddedBlock(Block *block)
|
||||
{
|
||||
emit BlockAdded(block, static_cast<Track*>(sender())->Index());
|
||||
}
|
||||
|
||||
void TrackList::TrackRemovedBlock(Block *block)
|
||||
{
|
||||
emit BlockRemoved(block);
|
||||
}
|
||||
|
||||
const QVector<Track *> &TrackList::GetTracks() const
|
||||
{
|
||||
return track_cache_;
|
||||
}
|
||||
|
||||
Track *TrackList::GetTrackAt(int index) const
|
||||
{
|
||||
if (index < track_cache_.size()) {
|
||||
@@ -65,16 +45,6 @@ Track *TrackList::GetTrackAt(int index) const
|
||||
}
|
||||
}
|
||||
|
||||
const rational &TrackList::GetTotalLength() const
|
||||
{
|
||||
return total_length_;
|
||||
}
|
||||
|
||||
int TrackList::GetTrackCount() const
|
||||
{
|
||||
return track_cache_.size();
|
||||
}
|
||||
|
||||
void TrackList::TrackConnected(Node *node, int element)
|
||||
{
|
||||
if (element == -1) {
|
||||
@@ -114,12 +84,9 @@ void TrackList::TrackConnected(Node *node, int element)
|
||||
// Update track indexes in the list (including this track)
|
||||
UpdateTrackIndexesFrom(track_index);
|
||||
|
||||
connect(track, &Track::BlockAdded, this, &TrackList::TrackAddedBlock);
|
||||
connect(track, &Track::BlockRemoved, this, &TrackList::TrackRemovedBlock);
|
||||
connect(track, &Track::TrackLengthChanged, this, &TrackList::UpdateTotalLength);
|
||||
connect(track, &Track::TrackHeightChangedInPixels, this, &TrackList::TrackHeightChangedSlot);
|
||||
|
||||
track->set_track_type(type_);
|
||||
track->set_type(type_);
|
||||
|
||||
emit TrackListChanged();
|
||||
|
||||
@@ -150,12 +117,9 @@ void TrackList::TrackDisconnected(Node *node, int element)
|
||||
emit TrackRemoved(track);
|
||||
|
||||
track->SetIndex(-1);
|
||||
track->set_track_type(Track::kNone);
|
||||
track->set_type(Track::kNone);
|
||||
|
||||
disconnect(track, &Track::BlockAdded, this, &TrackList::TrackAddedBlock);
|
||||
disconnect(track, &Track::BlockRemoved, this, &TrackList::TrackRemovedBlock);
|
||||
disconnect(track, &Track::TrackLengthChanged, this, &TrackList::UpdateTotalLength);
|
||||
disconnect(track, &Track::TrackHeightChangedInPixels, this, &TrackList::TrackHeightChangedSlot);
|
||||
|
||||
emit TrackListChanged();
|
||||
|
||||
@@ -187,9 +151,4 @@ void TrackList::UpdateTotalLength()
|
||||
emit LengthChanged(total_length_);
|
||||
}
|
||||
|
||||
void TrackList::TrackHeightChangedSlot(int height)
|
||||
{
|
||||
emit TrackHeightChanged(static_cast<Track*>(sender())->Index(), height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,15 +37,27 @@ class TrackList : public QObject
|
||||
public:
|
||||
TrackList(ViewerOutput *parent, const Track::Type& type, NodeInput* track_input);
|
||||
|
||||
const Track::Type& type() const;
|
||||
const Track::Type& type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
const QVector<Track*>& GetTracks() const;
|
||||
const QVector<Track*>& GetTracks() const
|
||||
{
|
||||
return track_cache_;
|
||||
}
|
||||
|
||||
Track* GetTrackAt(int index) const;
|
||||
|
||||
const rational& GetTotalLength() const;
|
||||
const rational& GetTotalLength() const
|
||||
{
|
||||
return total_length_;
|
||||
}
|
||||
|
||||
int GetTrackCount() const;
|
||||
int GetTrackCount() const
|
||||
{
|
||||
return track_cache_.size();
|
||||
}
|
||||
|
||||
NodeGraph* GetParentGraph() const;
|
||||
|
||||
@@ -55,19 +67,13 @@ public:
|
||||
}
|
||||
|
||||
signals:
|
||||
void BlockAdded(Block* block, int index);
|
||||
|
||||
void BlockRemoved(Block* block);
|
||||
|
||||
void TrackAdded(Track* track);
|
||||
|
||||
void TrackRemoved(Track* track);
|
||||
|
||||
void TrackListChanged();
|
||||
|
||||
void LengthChanged(const rational &length);
|
||||
|
||||
void TrackHeightChanged(int index, int height);
|
||||
void TrackAdded(Track* track);
|
||||
|
||||
void TrackRemoved(Track* track);
|
||||
|
||||
private:
|
||||
void UpdateTrackIndexesFrom(int index);
|
||||
@@ -94,26 +100,11 @@ private slots:
|
||||
*/
|
||||
void TrackDisconnected(Node* node, int element);
|
||||
|
||||
/**
|
||||
* @brief Slot for when a connected Track has added a Block so we can update the UI
|
||||
*/
|
||||
void TrackAddedBlock(Block* block);
|
||||
|
||||
/**
|
||||
* @brief Slot for when a connected Track has added a Block so we can update the UI
|
||||
*/
|
||||
void TrackRemovedBlock(Block* block);
|
||||
|
||||
/**
|
||||
* @brief Slot for when any of the track's length changes so we can update the length of the tracklist
|
||||
*/
|
||||
void UpdateTotalLength();
|
||||
|
||||
/**
|
||||
* @brief Slot when a track height changes, transforms to the TrackHeightChanged signal which includes a track index
|
||||
*/
|
||||
void TrackHeightChangedSlot(int height);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -47,11 +47,8 @@ ViewerOutput::ViewerOutput() :
|
||||
track_lists_.replace(i, list);
|
||||
connect(list, &TrackList::TrackListChanged, this, &ViewerOutput::UpdateTrackCache);
|
||||
connect(list, &TrackList::LengthChanged, this, &ViewerOutput::VerifyLength);
|
||||
connect(list, &TrackList::BlockAdded, this, &ViewerOutput::TrackListAddedBlock);
|
||||
connect(list, &TrackList::BlockRemoved, this, &ViewerOutput::BlockRemoved);
|
||||
connect(list, &TrackList::TrackAdded, this, &ViewerOutput::TrackListAddedTrack);
|
||||
connect(list, &TrackList::TrackAdded, this, &ViewerOutput::TrackAdded);
|
||||
connect(list, &TrackList::TrackRemoved, this, &ViewerOutput::TrackRemoved);
|
||||
connect(list, &TrackList::TrackHeightChanged, this, &ViewerOutput::TrackHeightChangedSlot);
|
||||
}
|
||||
|
||||
// Create UUID for this node
|
||||
@@ -291,21 +288,4 @@ void ViewerOutput::EndOperation()
|
||||
Node::EndOperation();
|
||||
}
|
||||
|
||||
void ViewerOutput::TrackListAddedBlock(Block *block, int index)
|
||||
{
|
||||
Track::Type type = static_cast<TrackList*>(sender())->type();
|
||||
emit BlockAdded(block, TrackReference(type, index));
|
||||
}
|
||||
|
||||
void ViewerOutput::TrackListAddedTrack(Track *track)
|
||||
{
|
||||
Track::Type type = static_cast<TrackList*>(sender())->type();
|
||||
emit TrackAdded(track, type);
|
||||
}
|
||||
|
||||
void ViewerOutput::TrackHeightChangedSlot(int index, int height)
|
||||
{
|
||||
emit TrackHeightChanged(static_cast<TrackList*>(sender())->type(), index, height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "render/framehashcache.h"
|
||||
#include "render/videoparams.h"
|
||||
#include "timeline/timelinecommon.h"
|
||||
#include "timeline/trackreference.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -97,7 +96,7 @@ public:
|
||||
return track_cache_;
|
||||
}
|
||||
|
||||
Track* GetTrackFromReference(const TrackReference& track_ref) const
|
||||
Track* GetTrackFromReference(const Track::Reference& track_ref) const
|
||||
{
|
||||
return track_lists_.at(track_ref.type())->GetTrackAt(track_ref.index());
|
||||
}
|
||||
@@ -147,14 +146,9 @@ signals:
|
||||
void VideoParamsChanged();
|
||||
void AudioParamsChanged();
|
||||
|
||||
void BlockAdded(Block* block, TrackReference track);
|
||||
void BlockRemoved(Block* block);
|
||||
|
||||
void TrackAdded(Track* track, Track::Type type);
|
||||
void TrackAdded(Track* track);
|
||||
void TrackRemoved(Track* track);
|
||||
|
||||
void TrackHeightChanged(Track::Type type, int index, int height);
|
||||
|
||||
private:
|
||||
QUuid uuid_;
|
||||
|
||||
@@ -185,12 +179,6 @@ private slots:
|
||||
|
||||
void VerifyLength();
|
||||
|
||||
void TrackListAddedBlock(Block* block, int index);
|
||||
|
||||
void TrackListAddedTrack(Track* track);
|
||||
|
||||
void TrackHeightChangedSlot(int index, int height);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -123,12 +123,12 @@ NodeValueTable NodeTraverser::GenerateTable(const Node *n, const rational &in, c
|
||||
NodeValueTable NodeTraverser::GenerateBlockTable(const Track *track, const TimeRange &range)
|
||||
{
|
||||
// By default, just follow the in point
|
||||
int active_block = track->BlockAtTime(range.in());
|
||||
Block* active_block = track->BlockAtTime(range.in());
|
||||
|
||||
NodeValueTable table;
|
||||
|
||||
if (active_block >= 0) {
|
||||
table = GenerateTable(track->Blocks().at(active_block).block, range);
|
||||
if (active_block) {
|
||||
table = GenerateTable(active_block, range);
|
||||
}
|
||||
|
||||
return table;
|
||||
|
||||
@@ -37,9 +37,9 @@ FootageViewerPanel::FootageViewerPanel(QWidget *parent) :
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
QList<Footage *> FootageViewerPanel::GetSelectedFootage() const
|
||||
QVector<Footage *> FootageViewerPanel::GetSelectedFootage() const
|
||||
{
|
||||
QList<Footage *> list;
|
||||
QVector<Footage *> list;
|
||||
Footage* f = static_cast<FootageViewerWidget*>(GetTimeBasedWidget())->GetFootage();
|
||||
|
||||
if (f) {
|
||||
|
||||
@@ -36,7 +36,7 @@ class FootageViewerPanel : public ViewerPanelBase, public FootageManagementPanel
|
||||
public:
|
||||
FootageViewerPanel(QWidget* parent);
|
||||
|
||||
virtual QList<Footage*> GetSelectedFootage() const override;
|
||||
virtual QVector<Footage *> GetSelectedFootage() const override;
|
||||
|
||||
void SetFootage(Footage* f);
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace olive {
|
||||
|
||||
class FootageManagementPanel {
|
||||
public:
|
||||
virtual QList<Footage*> GetSelectedFootage() const = 0;
|
||||
virtual QVector<Footage*> GetSelectedFootage() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ void ProjectPanel::set_root(Item *item)
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
QList<Item *> ProjectPanel::SelectedItems() const
|
||||
QVector<Item *> ProjectPanel::SelectedItems() const
|
||||
{
|
||||
return explorer_->SelectedItems();
|
||||
}
|
||||
@@ -232,10 +232,10 @@ void ProjectPanel::SaveConnectedProject()
|
||||
Core::instance()->SaveProject(this->project());
|
||||
}
|
||||
|
||||
QList<Footage *> ProjectPanel::GetSelectedFootage() const
|
||||
QVector<Footage *> ProjectPanel::GetSelectedFootage() const
|
||||
{
|
||||
QList<Item*> items = SelectedItems();
|
||||
QList<Footage*> footage;
|
||||
QVector<Item*> items = SelectedItems();
|
||||
QVector<Footage*> footage;
|
||||
|
||||
foreach (Item* i, items) {
|
||||
if (i->type() == Item::kFootage) {
|
||||
|
||||
@@ -44,11 +44,11 @@ public:
|
||||
|
||||
void set_root(Item* item);
|
||||
|
||||
QList<Item*> SelectedItems() const;
|
||||
QVector<Item *> SelectedItems() const;
|
||||
|
||||
Folder* GetSelectedFolder() const;
|
||||
|
||||
virtual QList<Footage*> GetSelectedFootage() const override;
|
||||
virtual QVector<Footage *> GetSelectedFootage() const override;
|
||||
|
||||
ProjectViewModel* model() const;
|
||||
|
||||
|
||||
@@ -165,12 +165,12 @@ void TimelinePanel::ToggleSelectedEnabled()
|
||||
static_cast<TimelineWidget*>(GetTimeBasedWidget())->ToggleSelectedEnabled();
|
||||
}
|
||||
|
||||
void TimelinePanel::InsertFootageAtPlayhead(const QList<Footage *> &footage)
|
||||
void TimelinePanel::InsertFootageAtPlayhead(const QVector<Footage *> &footage)
|
||||
{
|
||||
static_cast<TimelineWidget*>(GetTimeBasedWidget())->InsertFootageAtPlayhead(footage);
|
||||
}
|
||||
|
||||
void TimelinePanel::OverwriteFootageAtPlayhead(const QList<Footage *> &footage)
|
||||
void TimelinePanel::OverwriteFootageAtPlayhead(const QVector<Footage *> &footage)
|
||||
{
|
||||
static_cast<TimelineWidget*>(GetTimeBasedWidget())->OverwriteFootageAtPlayhead(footage);
|
||||
}
|
||||
|
||||
@@ -83,9 +83,9 @@ public:
|
||||
|
||||
virtual void ToggleSelectedEnabled() override;
|
||||
|
||||
void InsertFootageAtPlayhead(const QList<Footage *> &footage);
|
||||
void InsertFootageAtPlayhead(const QVector<Footage *> &footage);
|
||||
|
||||
void OverwriteFootageAtPlayhead(const QList<Footage *> &footage);
|
||||
void OverwriteFootageAtPlayhead(const QVector<Footage *> &footage);
|
||||
|
||||
protected:
|
||||
virtual void Retranslate() override;
|
||||
|
||||
@@ -297,7 +297,7 @@ void Sequence::set_default_parameters()
|
||||
AudioParams::kInternalFormat));
|
||||
}
|
||||
|
||||
void Sequence::set_parameters_from_footage(const QList<Footage *> footage)
|
||||
void Sequence::set_parameters_from_footage(const QVector<Footage *> footage)
|
||||
{
|
||||
bool found_video_params = false;
|
||||
bool found_audio_params = false;
|
||||
|
||||
@@ -70,7 +70,7 @@ public:
|
||||
|
||||
void set_default_parameters();
|
||||
|
||||
void set_parameters_from_footage(const QList<Footage*> footage);
|
||||
void set_parameters_from_footage(const QVector<Footage *> footage);
|
||||
|
||||
ViewerOutput* viewer_output() const;
|
||||
|
||||
|
||||
@@ -18,8 +18,6 @@ PreviewAutoCacher::PreviewAutoCacher() :
|
||||
single_frame_render_(nullptr),
|
||||
last_update_time_(0),
|
||||
ignore_next_mouse_button_(false),
|
||||
video_params_changed_(false),
|
||||
audio_params_changed_(false),
|
||||
color_manager_(nullptr)
|
||||
{
|
||||
// Set default autocache range
|
||||
@@ -91,7 +89,7 @@ void PreviewAutoCacher::GenerateHashes(ViewerOutput *viewer, FrameHashCache* cac
|
||||
|
||||
void PreviewAutoCacher::VideoInvalidated(const TimeRange &range)
|
||||
{
|
||||
ClearQueue(false);
|
||||
ClearVideoQueue();
|
||||
|
||||
// Hash these frames since that should be relatively quick.
|
||||
if (ignore_next_mouse_button_ || !(qApp->mouseButtons() & Qt::LeftButton)) {
|
||||
@@ -105,7 +103,7 @@ void PreviewAutoCacher::VideoInvalidated(const TimeRange &range)
|
||||
|
||||
void PreviewAutoCacher::AudioInvalidated(const TimeRange &range)
|
||||
{
|
||||
ClearQueue(false);
|
||||
ClearAudioQueue();
|
||||
|
||||
// Start jobs to re-render the audio at this range, split into 2 second chunks
|
||||
invalidated_audio_.insert(range);
|
||||
@@ -239,23 +237,6 @@ void PreviewAutoCacher::VideoDownloaded()
|
||||
delete watcher;
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::VideoParamsChanged()
|
||||
{
|
||||
// In case the user is pressing the mouse at this exact moment
|
||||
IgnoreNextMouseButton();
|
||||
|
||||
ClearVideoQueue();
|
||||
video_params_changed_ = true;
|
||||
TryRender();
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::AudioParamsChanged()
|
||||
{
|
||||
ClearAudioQueue();
|
||||
audio_params_changed_ = true;
|
||||
TryRender();
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::SingleFrameFinished()
|
||||
{
|
||||
RenderTicketWatcher* watcher = static_cast<RenderTicketWatcher*>(sender());
|
||||
@@ -283,6 +264,12 @@ void PreviewAutoCacher::ProcessUpdateQueue()
|
||||
case QueuedJob::kValueChanged:
|
||||
CopyValue(job.input, job.element);
|
||||
break;
|
||||
case QueuedJob::kVideoParamsChanged:
|
||||
UpdateVideoParams();
|
||||
break;
|
||||
case QueuedJob::kAudioParamsChanged:
|
||||
UpdateAudioParams();
|
||||
break;
|
||||
}
|
||||
}
|
||||
graph_update_queue_.clear();
|
||||
@@ -354,6 +341,16 @@ void PreviewAutoCacher::CopyValue(NodeInput *input, int element)
|
||||
NodeInput::CopyValuesOfElement(input, our_input, element);
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::UpdateVideoParams()
|
||||
{
|
||||
copied_viewer_node_->set_video_params(viewer_node_->video_params());
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::UpdateAudioParams()
|
||||
{
|
||||
copied_viewer_node_->set_audio_params(viewer_node_->audio_params());
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::SetPlayhead(const rational &playhead)
|
||||
{
|
||||
cache_range_ = TimeRange(playhead - Config::Current()["DiskCacheBehind"].value<rational>(),
|
||||
@@ -465,6 +462,23 @@ void PreviewAutoCacher::ValueChanged(const TimeRange &range, int element)
|
||||
graph_update_queue_.append({QueuedJob::kValueChanged, nullptr, static_cast<NodeInput*>(sender()), element});
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::VideoParamsChanged()
|
||||
{
|
||||
// In case the user is pressing the mouse at this exact moment
|
||||
IgnoreNextMouseButton();
|
||||
|
||||
graph_update_queue_.append({QueuedJob::kVideoParamsChanged, nullptr, nullptr, -1});
|
||||
ClearVideoQueue();
|
||||
TryRender();
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::AudioParamsChanged()
|
||||
{
|
||||
graph_update_queue_.append({QueuedJob::kAudioParamsChanged, nullptr, nullptr, -1});
|
||||
ClearAudioQueue();
|
||||
TryRender();
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::TryRender()
|
||||
{
|
||||
if (!graph_update_queue_.isEmpty()) {
|
||||
@@ -475,16 +489,6 @@ void PreviewAutoCacher::TryRender()
|
||||
|
||||
// No jobs are active, we can process the update queue
|
||||
ProcessUpdateQueue();
|
||||
|
||||
if (video_params_changed_) {
|
||||
copied_viewer_node_->set_video_params(viewer_node_->video_params());
|
||||
video_params_changed_ = false;
|
||||
}
|
||||
|
||||
if (audio_params_changed_) {
|
||||
copied_viewer_node_->set_audio_params(viewer_node_->audio_params());
|
||||
audio_params_changed_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
// If we're here, we must be able to render
|
||||
@@ -575,7 +579,8 @@ void PreviewAutoCacher::RequeueFrames()
|
||||
video_tasks_.insert(watcher, hash);
|
||||
watcher->SetTicket(RenderManager::instance()->RenderFrame(copied_viewer_node_,
|
||||
color_manager_,
|
||||
t, RenderMode::kOffline,
|
||||
t,
|
||||
RenderMode::kOffline,
|
||||
viewer_node_->video_frame_cache(),
|
||||
false));
|
||||
}
|
||||
@@ -637,14 +642,11 @@ void PreviewAutoCacher::SetViewerNode(ViewerOutput *viewer_node)
|
||||
copied_viewer_node_ = nullptr;
|
||||
graph_update_queue_.clear();
|
||||
|
||||
video_params_changed_ = false;
|
||||
audio_params_changed_ = false;
|
||||
|
||||
// Disconnect signals for future node additions/deletions
|
||||
NodeGraph* graph = viewer_node_->parent();
|
||||
|
||||
connect(graph, &NodeGraph::NodeAdded, this, &PreviewAutoCacher::NodeAdded);
|
||||
connect(graph, &NodeGraph::NodeRemoved, this, &PreviewAutoCacher::NodeRemoved);
|
||||
disconnect(graph, &NodeGraph::NodeAdded, this, &PreviewAutoCacher::NodeAdded);
|
||||
disconnect(graph, &NodeGraph::NodeRemoved, this, &PreviewAutoCacher::NodeRemoved);
|
||||
|
||||
// Disconnect signal (will be a no-op if the signal was never connected)
|
||||
disconnect(viewer_node_,
|
||||
@@ -695,6 +697,8 @@ void PreviewAutoCacher::SetViewerNode(ViewerOutput *viewer_node)
|
||||
}
|
||||
}
|
||||
|
||||
last_update_time_ = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
// Connect signals for future node additions/deletions
|
||||
connect(graph, &NodeGraph::NodeAdded, this, &PreviewAutoCacher::NodeAdded);
|
||||
connect(graph, &NodeGraph::NodeRemoved, this, &PreviewAutoCacher::NodeRemoved);
|
||||
|
||||
@@ -90,20 +90,6 @@ public:
|
||||
color_manager_ = manager;
|
||||
}
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief Main handler for when the NodeGraph changes
|
||||
*/
|
||||
void NodeAdded(Node* node);
|
||||
|
||||
void NodeRemoved(Node* node);
|
||||
|
||||
void EdgeAdded(Node* output, int element);
|
||||
|
||||
void EdgeRemoved(Node* output, int element);
|
||||
|
||||
void ValueChanged(const TimeRange& range, int element);
|
||||
|
||||
private:
|
||||
static void GenerateHashes(ViewerOutput* viewer, FrameHashCache *cache, const QVector<rational>& times, qint64 job_time);
|
||||
|
||||
@@ -124,6 +110,8 @@ private:
|
||||
void AddEdge(Node* output, NodeInput* input, int element);
|
||||
void RemoveEdge(Node* output, NodeInput* input, int element);
|
||||
void CopyValue(NodeInput* input, int element);
|
||||
void UpdateVideoParams();
|
||||
void UpdateAudioParams();
|
||||
|
||||
class QueuedJob {
|
||||
public:
|
||||
@@ -132,7 +120,9 @@ private:
|
||||
kNodeRemoved,
|
||||
kEdgeAdded,
|
||||
kEdgeRemoved,
|
||||
kValueChanged
|
||||
kValueChanged,
|
||||
kVideoParamsChanged,
|
||||
kAudioParamsChanged
|
||||
};
|
||||
|
||||
Type type;
|
||||
@@ -172,10 +162,6 @@ private:
|
||||
|
||||
bool ignore_next_mouse_button_;
|
||||
|
||||
bool video_params_changed_;
|
||||
|
||||
bool audio_params_changed_;
|
||||
|
||||
ColorManager* color_manager_;
|
||||
|
||||
QTimer delayed_requeue_timer_;
|
||||
@@ -211,6 +197,16 @@ private slots:
|
||||
*/
|
||||
void VideoDownloaded();
|
||||
|
||||
void NodeAdded(Node* node);
|
||||
|
||||
void NodeRemoved(Node* node);
|
||||
|
||||
void EdgeAdded(Node* output, int element);
|
||||
|
||||
void EdgeRemoved(Node* output, int element);
|
||||
|
||||
void ValueChanged(const TimeRange& range, int element);
|
||||
|
||||
void VideoParamsChanged();
|
||||
|
||||
void AudioParamsChanged();
|
||||
|
||||
@@ -188,7 +188,7 @@ void RenderProcessor::Process(RenderTicketPtr ticket, Renderer *render_ctx, Stil
|
||||
|
||||
NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const TimeRange &range)
|
||||
{
|
||||
if (track->track_type() == Track::kAudio) {
|
||||
if (track->type() == Track::kAudio) {
|
||||
|
||||
const AudioParams& audio_params = ticket_->property("aparam").value<AudioParams>();
|
||||
|
||||
|
||||
@@ -25,7 +25,5 @@ set(OLIVE_SOURCES
|
||||
timeline/timelinepoints.cpp
|
||||
timeline/timelineworkarea.h
|
||||
timeline/timelineworkarea.cpp
|
||||
timeline/trackreference.h
|
||||
timeline/trackreference.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
@@ -27,7 +27,7 @@ TimelineCoordinate::TimelineCoordinate() :
|
||||
{
|
||||
}
|
||||
|
||||
TimelineCoordinate::TimelineCoordinate(const rational &frame, const TrackReference &track) :
|
||||
TimelineCoordinate::TimelineCoordinate(const rational &frame, const Track::Reference &track) :
|
||||
frame_(frame),
|
||||
track_(track)
|
||||
{
|
||||
@@ -44,7 +44,7 @@ const rational &TimelineCoordinate::GetFrame() const
|
||||
return frame_;
|
||||
}
|
||||
|
||||
const TrackReference &TimelineCoordinate::GetTrack() const
|
||||
const Track::Reference &TimelineCoordinate::GetTrack() const
|
||||
{
|
||||
return track_;
|
||||
}
|
||||
@@ -54,7 +54,7 @@ void TimelineCoordinate::SetFrame(const rational &frame)
|
||||
frame_ = frame;
|
||||
}
|
||||
|
||||
void TimelineCoordinate::SetTrack(const TrackReference &track)
|
||||
void TimelineCoordinate::SetTrack(const Track::Reference &track)
|
||||
{
|
||||
track_ = track;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define TIMELINECOORDINATE_H
|
||||
|
||||
#include "common/rational.h"
|
||||
#include "trackreference.h"
|
||||
#include "node/output/track/track.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -30,19 +30,19 @@ class TimelineCoordinate
|
||||
{
|
||||
public:
|
||||
TimelineCoordinate();
|
||||
TimelineCoordinate(const rational& frame, const TrackReference& track);
|
||||
TimelineCoordinate(const rational& frame, const Track::Reference& track);
|
||||
TimelineCoordinate(const rational& frame, const Track::Type& track_type, const int& track_index);
|
||||
|
||||
const rational& GetFrame() const;
|
||||
const TrackReference& GetTrack() const;
|
||||
const Track::Reference& GetTrack() const;
|
||||
|
||||
void SetFrame(const rational& frame);
|
||||
void SetTrack(const TrackReference& track);
|
||||
void SetTrack(const Track::Reference& track);
|
||||
|
||||
private:
|
||||
rational frame_;
|
||||
|
||||
TrackReference track_;
|
||||
Track::Reference track_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2020 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "trackreference.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
TrackReference::TrackReference() :
|
||||
type_(Track::kNone),
|
||||
index_(0)
|
||||
{
|
||||
}
|
||||
|
||||
TrackReference::TrackReference(const Track::Type &type, const int &index) :
|
||||
type_(type),
|
||||
index_(index)
|
||||
{
|
||||
}
|
||||
|
||||
const Track::Type &TrackReference::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
const int &TrackReference::index() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
bool TrackReference::operator==(const TrackReference &ref) const
|
||||
{
|
||||
return type_ == ref.type_ && index_ == ref.index_;
|
||||
}
|
||||
|
||||
bool TrackReference::operator!=(const TrackReference &ref) const
|
||||
{
|
||||
return !(*this == ref);
|
||||
}
|
||||
|
||||
uint qHash(const TrackReference &r, uint seed)
|
||||
{
|
||||
// Not super efficient, but couldn't think of any better way to ensure a different hash each time
|
||||
return ::qHash(QStringLiteral("%1:%2").arg(QString::number(r.type()),
|
||||
QString::number(r.index())),
|
||||
seed);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2020 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef TRACKREFERENCE_H
|
||||
#define TRACKREFERENCE_H
|
||||
|
||||
#include "node/output/track/track.h"
|
||||
#include "timeline/timelinecommon.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class TrackReference
|
||||
{
|
||||
public:
|
||||
TrackReference();
|
||||
|
||||
TrackReference(const Track::Type& type, const int& index);
|
||||
|
||||
const Track::Type& type() const;
|
||||
|
||||
const int& index() const;
|
||||
|
||||
bool operator<(const TrackReference& ref) const;
|
||||
|
||||
bool operator==(const TrackReference& ref) const;
|
||||
|
||||
bool operator!=(const TrackReference& ref) const;
|
||||
|
||||
private:
|
||||
Track::Type type_;
|
||||
|
||||
int index_;
|
||||
|
||||
};
|
||||
|
||||
uint qHash(const TrackReference& r, uint seed = 0);
|
||||
|
||||
}
|
||||
|
||||
#endif // TRACKREFERENCE_H
|
||||
@@ -460,13 +460,13 @@ void ProjectExplorer::set_root(Item *item)
|
||||
tree_view_->setRootIndex(index);
|
||||
}
|
||||
|
||||
QList<Item *> ProjectExplorer::SelectedItems() const
|
||||
QVector<Item *> ProjectExplorer::SelectedItems() const
|
||||
{
|
||||
// Determine which view is active and get its selected indexes
|
||||
QModelIndexList index_list = CurrentView()->selectionModel()->selectedRows();
|
||||
|
||||
// Convert indexes to item objects
|
||||
QList<Item*> selected_items;
|
||||
QVector<Item*> selected_items;
|
||||
|
||||
for (int i=0;i<index_list.size();i++) {
|
||||
const QModelIndex& index = index_list.at(i);
|
||||
@@ -488,7 +488,7 @@ Folder *ProjectExplorer::GetSelectedFolder() const
|
||||
Folder* folder = nullptr;
|
||||
|
||||
// Get the selected items from the panel
|
||||
QList<Item*> selected_items = SelectedItems();
|
||||
QVector<Item*> selected_items = SelectedItems();
|
||||
|
||||
// Heuristic for finding the selected folder:
|
||||
//
|
||||
@@ -565,7 +565,7 @@ QVector<MediaInput *> ProjectExplorer::GetMediaNodesUsingFootage(Footage *item)
|
||||
|
||||
void ProjectExplorer::DeleteSelected()
|
||||
{
|
||||
QList<Item*> selected = SelectedItems();
|
||||
QVector<Item*> selected = SelectedItems();
|
||||
|
||||
if (selected.isEmpty()) {
|
||||
return;
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
|
||||
void set_root(Item* item);
|
||||
|
||||
QList<Item*> SelectedItems() const;
|
||||
QVector<Item *> SelectedItems() const;
|
||||
|
||||
/**
|
||||
* @brief Use a heuristic to determine which (if any) folder is selected
|
||||
@@ -157,7 +157,7 @@ private:
|
||||
|
||||
QTimer rename_timer_;
|
||||
|
||||
QList<Item*> context_menu_items_;
|
||||
QVector<Item*> context_menu_items_;
|
||||
|
||||
private slots:
|
||||
void ItemClickedSlot(const QModelIndex& index);
|
||||
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
/**
|
||||
* @brief Snaps point `start_point` that is moving by `movement` to currently existing clips
|
||||
*/
|
||||
virtual bool SnapPoint(QList<rational> start_times, rational *movement, int snap_points = kSnapAll) = 0;
|
||||
virtual bool SnapPoint(QVector<rational> start_times, rational *movement, int snap_points = kSnapAll) = 0;
|
||||
|
||||
virtual void HideSnaps() = 0;
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ void TimeBasedView::TimebaseChangedEvent(const rational &)
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
void TimeBasedView::EnableSnap(const QList<rational> &points)
|
||||
void TimeBasedView::EnableSnap(const QVector<rational> &points)
|
||||
{
|
||||
snapped_ = true;
|
||||
snap_time_ = points;
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
|
||||
static const double kMaximumScale;
|
||||
|
||||
void EnableSnap(const QList<rational>& points);
|
||||
void EnableSnap(const QVector<rational> &points);
|
||||
void DisableSnap();
|
||||
bool IsSnapped() const
|
||||
{
|
||||
@@ -106,7 +106,7 @@ private:
|
||||
QGraphicsScene scene_;
|
||||
|
||||
bool snapped_;
|
||||
QList<rational> snap_time_;
|
||||
QVector<rational> snap_time_;
|
||||
|
||||
rational end_time_;
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "config/config.h"
|
||||
#include "core.h"
|
||||
#include "project/item/sequence/sequence.h"
|
||||
#include "widget/timelinewidget/timelineundo.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
|
||||
@@ -20,12 +20,13 @@ add_subdirectory(view)
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
widget/timelinewidget/timelineandtrackview.h
|
||||
widget/timelinewidget/timelineandtrackview.cpp
|
||||
widget/timelinewidget/timelineandtrackview.h
|
||||
widget/timelinewidget/timelineundo.cpp
|
||||
widget/timelinewidget/timelineundo.h
|
||||
widget/timelinewidget/timelinewidget.h
|
||||
widget/timelinewidget/timelinewidget.cpp
|
||||
widget/timelinewidget/timelinewidgetselections.h
|
||||
widget/timelinewidget/timelinewidget.h
|
||||
widget/timelinewidget/timelinewidgetselections.cpp
|
||||
widget/timelinewidget/timelinewidgetselections.h
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,725 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2020 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef TIMELINEUNDOABLE_H
|
||||
#define TIMELINEUNDOABLE_H
|
||||
|
||||
#include <QUndoCommand>
|
||||
|
||||
#include "node/block/block.h"
|
||||
#include "node/block/gap/gap.h"
|
||||
#include "node/block/transition/transition.h"
|
||||
#include "node/output/track/track.h"
|
||||
#include "node/output/track/tracklist.h"
|
||||
#include "timeline/timelinepoints.h"
|
||||
#include "undo/undocommand.h"
|
||||
#include "widget/timelinewidget/timelinewidgetselections.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class BlockResizeCommand : public UndoCommand {
|
||||
public:
|
||||
BlockResizeCommand(Block* block, rational new_length, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
block_(block),
|
||||
new_length_(new_length)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override
|
||||
{
|
||||
return block_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
{
|
||||
old_length_ = block_->length();
|
||||
block_->set_length_and_media_out(new_length_);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
{
|
||||
block_->set_length_and_media_out(old_length_);
|
||||
}
|
||||
|
||||
private:
|
||||
Block* block_;
|
||||
rational old_length_;
|
||||
rational new_length_;
|
||||
|
||||
};
|
||||
|
||||
class BlockResizeWithMediaInCommand : public UndoCommand {
|
||||
public:
|
||||
BlockResizeWithMediaInCommand(Block* block, rational new_length, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
block_(block),
|
||||
new_length_(new_length)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override
|
||||
{
|
||||
return block_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
{
|
||||
old_length_ = block_->length();
|
||||
block_->set_length_and_media_in(new_length_);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
{
|
||||
block_->set_length_and_media_in(old_length_);
|
||||
}
|
||||
|
||||
private:
|
||||
Block* block_;
|
||||
rational old_length_;
|
||||
rational new_length_;
|
||||
};
|
||||
|
||||
class BlockTrimCommand : public UndoCommand {
|
||||
public:
|
||||
BlockTrimCommand(Track *track, Block* block, rational new_length, Timeline::MovementMode mode, QUndoCommand* command = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
void SetTrimIsARollEdit(bool e)
|
||||
{
|
||||
trim_is_a_roll_edit_ = e;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
Track* track_;
|
||||
Block* block_;
|
||||
rational old_length_;
|
||||
rational new_length_;
|
||||
Timeline::MovementMode mode_;
|
||||
|
||||
Block* adjacent_;
|
||||
bool we_created_adjacent_;
|
||||
bool we_deleted_adjacent_;
|
||||
|
||||
bool trim_is_a_roll_edit_;
|
||||
|
||||
QObject memory_manager_;
|
||||
|
||||
};
|
||||
|
||||
class BlockSetMediaInCommand : public UndoCommand {
|
||||
public:
|
||||
BlockSetMediaInCommand(Block* block, rational new_media_in, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
block_(block),
|
||||
new_media_in_(new_media_in)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override
|
||||
{
|
||||
return block_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
{
|
||||
old_media_in_ = block_->media_in();
|
||||
block_->set_media_in(new_media_in_);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
{
|
||||
block_->set_media_in(old_media_in_);
|
||||
}
|
||||
|
||||
private:
|
||||
Block* block_;
|
||||
rational old_media_in_;
|
||||
rational new_media_in_;
|
||||
};
|
||||
|
||||
class TrackRippleRemoveBlockCommand : public UndoCommand {
|
||||
public:
|
||||
TrackRippleRemoveBlockCommand(Track* track, Block* block, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
track_(track),
|
||||
block_(block)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override
|
||||
{
|
||||
return track_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
{
|
||||
before_ = block_->previous();
|
||||
track_->RippleRemoveBlock(block_);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
{
|
||||
if (before_) {
|
||||
track_->InsertBlockAfter(block_, before_);
|
||||
} else {
|
||||
track_->PrependBlock(block_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Track* track_;
|
||||
|
||||
Block* block_;
|
||||
|
||||
Block* before_;
|
||||
|
||||
};
|
||||
|
||||
class TrackPrependBlockCommand : public UndoCommand {
|
||||
public:
|
||||
TrackPrependBlockCommand(Track* track, Block* block, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
Track* track_;
|
||||
Block* block_;
|
||||
};
|
||||
|
||||
class TrackInsertBlockAfterCommand : public UndoCommand {
|
||||
public:
|
||||
TrackInsertBlockAfterCommand(Track* track, Block* block, Block* before, QUndoCommand* parent = nullptr) :
|
||||
UndoCommand(parent),
|
||||
track_(track),
|
||||
block_(block),
|
||||
before_(before)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override
|
||||
{
|
||||
return block_->parent()->project();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override
|
||||
{
|
||||
track_->InsertBlockAfter(block_, before_);
|
||||
}
|
||||
|
||||
virtual void undo_internal() override
|
||||
{
|
||||
track_->RippleRemoveBlock(block_);
|
||||
}
|
||||
|
||||
private:
|
||||
Track* track_;
|
||||
|
||||
Block* block_;
|
||||
|
||||
Block* before_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Clears the area between in and out
|
||||
*
|
||||
* The area between `in` and `out` is guaranteed to be freed. BLocks are trimmed and removed to free this space.
|
||||
* By default, nothing takes this area meaning all subsequent clips are pushed backward, however you can specify
|
||||
* a block to insert at the `in` point. No checking is done to ensure `insert` is the same length as `in` to `out`.
|
||||
*/
|
||||
class TrackRippleRemoveAreaCommand : public UndoCommand {
|
||||
public:
|
||||
TrackRippleRemoveAreaCommand(Track* track, rational in, rational out, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
void SetInsert(Block* insert);
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
protected:
|
||||
Project* project_;
|
||||
|
||||
Track* track_;
|
||||
rational in_;
|
||||
rational out_;
|
||||
|
||||
bool splice_;
|
||||
QUndoCommand* splice_split_command_;
|
||||
|
||||
Block* trim_out_;
|
||||
Block* trim_in_;
|
||||
QVector<Block*> removed_blocks_;
|
||||
|
||||
rational trim_in_old_length_;
|
||||
rational trim_out_old_length_;
|
||||
|
||||
rational trim_in_new_length_;
|
||||
rational trim_out_new_length_;
|
||||
|
||||
Block* insert_;
|
||||
|
||||
QObject memory_manager_;
|
||||
|
||||
QVector<QUndoCommand*> remove_block_commands_;
|
||||
|
||||
};
|
||||
|
||||
class TrackListRippleRemoveAreaCommand : public UndoCommand {
|
||||
public:
|
||||
TrackListRippleRemoveAreaCommand(TrackList* list, rational in, rational out, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual ~TrackListRippleRemoveAreaCommand() override;
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
TrackList* list_;
|
||||
|
||||
QList<Track*> working_tracks_;
|
||||
|
||||
rational in_;
|
||||
|
||||
rational out_;
|
||||
|
||||
bool all_tracks_unlocked_;
|
||||
|
||||
QVector<TrackRippleRemoveAreaCommand*> commands_;
|
||||
|
||||
};
|
||||
|
||||
class TimelineRippleRemoveAreaCommand : public UndoCommand {
|
||||
public:
|
||||
TimelineRippleRemoveAreaCommand(ViewerOutput* timeline, rational in, rational out, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
private:
|
||||
ViewerOutput* timeline_;
|
||||
|
||||
};
|
||||
|
||||
class TrackListRippleToolCommand : public UndoCommand {
|
||||
public:
|
||||
struct RippleInfo {
|
||||
Block* block;
|
||||
Block* ref_block;
|
||||
Track* track;
|
||||
rational new_length;
|
||||
rational old_length;
|
||||
};
|
||||
|
||||
TrackListRippleToolCommand(TrackList* track_list,
|
||||
const QList<RippleInfo>& info,
|
||||
const Timeline::MovementMode& movement_mode,
|
||||
QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
TrackList* track_list_;
|
||||
|
||||
QList<RippleInfo> info_;
|
||||
Timeline::MovementMode movement_mode_;
|
||||
|
||||
struct WorkingData {
|
||||
GapBlock* created_gap;
|
||||
Block* removed_gap_after;
|
||||
};
|
||||
|
||||
QVector<WorkingData> working_data_;
|
||||
|
||||
QObject memory_manager_;
|
||||
|
||||
bool all_tracks_unlocked_;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Destructively places `block` at the in point `start`
|
||||
*
|
||||
* The Block is guaranteed to be placed at the starting point specified. If there are Blocks in this area, they are
|
||||
* either trimmed or removed to make space for this Block. Additionally, if the Block is placed beyond the end of
|
||||
* the Sequence, a GapBlock is inserted to compensate.
|
||||
*/
|
||||
class TrackPlaceBlockCommand : public TrackRippleRemoveAreaCommand {
|
||||
public:
|
||||
TrackPlaceBlockCommand(TrackList *timeline, int track, Block* block, rational in, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
TrackList* timeline_;
|
||||
int track_index_;
|
||||
bool append_;
|
||||
GapBlock* gap_;
|
||||
QVector<Track*> added_tracks_;
|
||||
|
||||
};
|
||||
|
||||
class BlockSplitCommand : public UndoCommand {
|
||||
public:
|
||||
BlockSplitCommand(Track* track, Block* block, rational point, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
Block* new_block();
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
Track* track_;
|
||||
Block* block_;
|
||||
Block* new_block_;
|
||||
|
||||
rational new_length_;
|
||||
rational old_length_;
|
||||
rational point_;
|
||||
|
||||
QList<NodeInput*> transitions_to_move_;
|
||||
|
||||
QObject memory_manager_;
|
||||
|
||||
QUndoCommand* add_command_;
|
||||
|
||||
};
|
||||
|
||||
class TrackSplitAtTimeCommand : public UndoCommand {
|
||||
public:
|
||||
TrackSplitAtTimeCommand(Track* track, rational point, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
private:
|
||||
Track* track_;
|
||||
|
||||
};
|
||||
|
||||
class BlockSplitPreservingLinksCommand : public UndoCommand {
|
||||
public:
|
||||
BlockSplitPreservingLinksCommand(const QVector<Block *> &blocks, const QList<rational>& times, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
private:
|
||||
QVector<Block *> blocks_;
|
||||
|
||||
QList<rational> times_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Replaces Block `old` with Block `replace`
|
||||
*
|
||||
* Both blocks must have equal lengths.
|
||||
*/
|
||||
class TrackReplaceBlockCommand : public UndoCommand {
|
||||
public:
|
||||
TrackReplaceBlockCommand(Track* track, Block* old, Block* replace, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
Track* track_;
|
||||
Block* old_;
|
||||
Block* replace_;
|
||||
};
|
||||
|
||||
class TrackReplaceBlockWithGapCommand : public UndoCommand {
|
||||
public:
|
||||
TrackReplaceBlockWithGapCommand(Track* track, Block* block, QUndoCommand* command = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
Track* track_;
|
||||
Block* block_;
|
||||
|
||||
GapBlock* existing_gap_;
|
||||
GapBlock* existing_merged_gap_;
|
||||
bool existing_gap_precedes_;
|
||||
GapBlock* our_gap_;
|
||||
|
||||
QObject memory_manager_;
|
||||
|
||||
};
|
||||
|
||||
class TimelineRippleDeleteGapsAtRegionsCommand : public UndoCommand {
|
||||
public:
|
||||
TimelineRippleDeleteGapsAtRegionsCommand(ViewerOutput* vo, const TimeRangeList& regions, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
ViewerOutput* timeline_;
|
||||
TimeRangeList regions_;
|
||||
|
||||
QList<UndoCommand*> commands_;
|
||||
|
||||
};
|
||||
|
||||
class WorkareaSetEnabledCommand : public UndoCommand {
|
||||
public:
|
||||
WorkareaSetEnabledCommand(Project *project, TimelinePoints* points, bool enabled, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
Project* project_;
|
||||
|
||||
TimelinePoints* points_;
|
||||
|
||||
bool old_enabled_;
|
||||
|
||||
bool new_enabled_;
|
||||
|
||||
};
|
||||
|
||||
class WorkareaSetRangeCommand : public UndoCommand {
|
||||
public:
|
||||
WorkareaSetRangeCommand(Project *project, TimelinePoints* points, const TimeRange& range, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
Project* project_;
|
||||
|
||||
TimelinePoints* points_;
|
||||
|
||||
TimeRange old_range_;
|
||||
|
||||
TimeRange new_range_;
|
||||
|
||||
};
|
||||
|
||||
class BlockLinkManyCommand : public UndoCommand {
|
||||
public:
|
||||
BlockLinkManyCommand(const QVector<Block*> blocks, bool link, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
private:
|
||||
QVector<Block*> blocks_;
|
||||
|
||||
};
|
||||
|
||||
class BlockLinkCommand : public UndoCommand {
|
||||
public:
|
||||
BlockLinkCommand(Block* a, Block* b, bool link, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
Block* a_;
|
||||
|
||||
Block* b_;
|
||||
|
||||
bool link_;
|
||||
|
||||
bool done_;
|
||||
|
||||
};
|
||||
|
||||
class BlockUnlinkAllCommand : public UndoCommand {
|
||||
public:
|
||||
BlockUnlinkAllCommand(Block* block, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
Block* block_;
|
||||
|
||||
QVector<Block*> unlinked_;
|
||||
|
||||
};
|
||||
|
||||
class BlockEnableDisableCommand : public UndoCommand {
|
||||
public:
|
||||
BlockEnableDisableCommand(Block* block, bool enabled, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
Block* block_;
|
||||
|
||||
bool old_enabled_;
|
||||
|
||||
bool new_enabled_;
|
||||
|
||||
};
|
||||
|
||||
class TrackSlideCommand : public UndoCommand {
|
||||
public:
|
||||
TrackSlideCommand(Track* track, const QList<Block*>& moving_blocks, Block* in_adjacent, Block* out_adjacent, const rational& movement, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
void slide_internal(bool undo);
|
||||
|
||||
Track* track_;
|
||||
QList<Block*> blocks_;
|
||||
rational movement_;
|
||||
|
||||
bool we_created_in_adjacent_;
|
||||
Block* in_adjacent_;
|
||||
bool we_created_out_adjacent_;
|
||||
Block* out_adjacent_;
|
||||
|
||||
QObject memory_manager_;
|
||||
|
||||
};
|
||||
|
||||
class TrackListInsertGaps : public UndoCommand {
|
||||
public:
|
||||
TrackListInsertGaps(TrackList* track_list, const rational& point, const rational& length, QUndoCommand* parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
TrackList* track_list_;
|
||||
|
||||
rational point_;
|
||||
|
||||
rational length_;
|
||||
|
||||
QList<Track*> working_tracks_;
|
||||
|
||||
bool all_tracks_unlocked_;
|
||||
|
||||
QList<Block*> gaps_to_extend_;
|
||||
|
||||
QList<GapBlock*> gaps_added_;
|
||||
|
||||
BlockSplitPreservingLinksCommand* split_command_;
|
||||
|
||||
QObject memory_manager_;
|
||||
|
||||
};
|
||||
|
||||
class TransitionRemoveCommand : public UndoCommand {
|
||||
public:
|
||||
TransitionRemoveCommand(Track *track, TransitionBlock* block, QUndoCommand *parent = nullptr);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo_internal() override;
|
||||
virtual void undo_internal() override;
|
||||
|
||||
private:
|
||||
Track* track_;
|
||||
|
||||
TransitionBlock* block_;
|
||||
|
||||
Block* out_block_;
|
||||
Block* in_block_;
|
||||
|
||||
};
|
||||
|
||||
class TimelineWidget;
|
||||
|
||||
class TimelineSetSelectionsCommand : public QUndoCommand {
|
||||
public:
|
||||
TimelineSetSelectionsCommand(TimelineWidget* timeline, const TimelineWidgetSelections& now, const TimelineWidgetSelections& old, QUndoCommand* parent = nullptr);
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
TimelineWidget* timeline_;
|
||||
TimelineWidgetSelections old_;
|
||||
TimelineWidgetSelections now_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // TIMELINEUNDOABLE_H
|
||||
@@ -220,12 +220,9 @@ void TimelineWidget::ScaleChangedEvent(const double &scale)
|
||||
|
||||
void TimelineWidget::ConnectNodeInternal(ViewerOutput *n)
|
||||
{
|
||||
connect(n, &ViewerOutput::BlockAdded, this, &TimelineWidget::AddBlock);
|
||||
connect(n, &ViewerOutput::BlockRemoved, this, &TimelineWidget::RemoveBlock);
|
||||
connect(n, &ViewerOutput::TrackAdded, this, &TimelineWidget::AddTrack);
|
||||
connect(n, &ViewerOutput::TrackRemoved, this, &TimelineWidget::RemoveTrack);
|
||||
connect(n, &ViewerOutput::TimebaseChanged, this, &TimelineWidget::SetTimebase);
|
||||
connect(n, &ViewerOutput::TrackHeightChanged, this, &TimelineWidget::TrackHeightChanged);
|
||||
|
||||
ruler()->SetPlaybackCache(n->video_frame_cache());
|
||||
|
||||
@@ -241,20 +238,18 @@ void TimelineWidget::ConnectNodeInternal(ViewerOutput *n)
|
||||
view->ConnectTrackList(track_list);
|
||||
|
||||
// Defer to the track to make all the block UI items necessary
|
||||
foreach (Track* track, n->track_list(track_type)->GetTracks()) {
|
||||
AddTrack(track, track_type);
|
||||
const QVector<Track*> tracks = n->track_list(track_type)->GetTracks();
|
||||
foreach (Track* track, tracks) {
|
||||
AddTrack(track);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::DisconnectNodeInternal(ViewerOutput *n)
|
||||
{
|
||||
disconnect(n, &ViewerOutput::BlockAdded, this, &TimelineWidget::AddBlock);
|
||||
disconnect(n, &ViewerOutput::BlockRemoved, this, &TimelineWidget::RemoveBlock);
|
||||
disconnect(n, &ViewerOutput::TrackAdded, this, &TimelineWidget::AddTrack);
|
||||
disconnect(n, &ViewerOutput::TrackRemoved, this, &TimelineWidget::RemoveTrack);
|
||||
disconnect(n, &ViewerOutput::TimebaseChanged, this, &TimelineWidget::SetTimebase);
|
||||
disconnect(n, &ViewerOutput::TrackHeightChanged, this, &TimelineWidget::TrackHeightChanged);
|
||||
|
||||
DeselectAll();
|
||||
|
||||
@@ -280,9 +275,7 @@ void TimelineWidget::CopyNodesToClipboardInternal(QXmlStreamWriter *writer, void
|
||||
QVector<Block*>& selected = *static_cast<QVector<Block*>*>(userdata);
|
||||
rational earliest_in = RATIONAL_MAX;
|
||||
|
||||
foreach (Block* item, selected) {
|
||||
Block* block = item->block();
|
||||
|
||||
foreach (Block* block, selected) {
|
||||
earliest_in = qMin(earliest_in, block->in());
|
||||
}
|
||||
|
||||
@@ -292,12 +285,9 @@ void TimelineWidget::CopyNodesToClipboardInternal(QXmlStreamWriter *writer, void
|
||||
writer->writeAttribute(QStringLiteral("ptr"), QString::number(reinterpret_cast<quintptr>(block)));
|
||||
writer->writeAttribute(QStringLiteral("in"), (block->in() - earliest_in).toString());
|
||||
|
||||
Track* track = GetTrackFromBlock(block);
|
||||
|
||||
if (track) {
|
||||
writer->writeAttribute(QStringLiteral("tracktype"), QString::number(track->track_type()));
|
||||
writer->writeAttribute(QStringLiteral("trackindex"), QString::number(track->Index()));
|
||||
}
|
||||
Track* track = block->track();
|
||||
writer->writeAttribute(QStringLiteral("tracktype"), QString::number(track->type()));
|
||||
writer->writeAttribute(QStringLiteral("trackindex"), QString::number(track->Index()));
|
||||
|
||||
writer->writeEndElement();
|
||||
}
|
||||
@@ -334,10 +324,10 @@ void TimelineWidget::SelectAll()
|
||||
{
|
||||
QVector<Block*> newly_selected_blocks;
|
||||
|
||||
for (auto it=block_items_.cbegin(); it!=block_items_.cend(); it++) {
|
||||
if (!selected_blocks_.contains(it.key())) {
|
||||
newly_selected_blocks.append(it.key());
|
||||
AddSelection(it.key()->range(), it.value()->Track());
|
||||
foreach (Block* block, added_blocks_) {
|
||||
if (!selected_blocks_.contains(block)) {
|
||||
newly_selected_blocks.append(block);
|
||||
AddSelection(block);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,7 +374,7 @@ void TimelineWidget::SplitAtPlayhead()
|
||||
|
||||
rational playhead_time = Timecode::timestamp_to_time(GetTimestamp(), timebase());
|
||||
|
||||
QVector<TimelineViewBlockItem *> selected_blocks = GetSelectedBlocks();
|
||||
QVector<Block*> selected_blocks = GetSelectedBlocks();
|
||||
|
||||
// Prioritize blocks that are selected and overlap the playhead
|
||||
QVector<Block*> blocks_to_split;
|
||||
@@ -400,8 +390,8 @@ void TimelineWidget::SplitAtPlayhead()
|
||||
bool selected = false;
|
||||
|
||||
// See if this block is selected
|
||||
foreach (TimelineViewBlockItem* item, selected_blocks) {
|
||||
if (item->block() == b) {
|
||||
foreach (Block* item, selected_blocks) {
|
||||
if (item == b) {
|
||||
some_blocks_are_selected = true;
|
||||
selected = true;
|
||||
break;
|
||||
@@ -430,8 +420,8 @@ void TimelineWidget::SplitAtPlayhead()
|
||||
}
|
||||
|
||||
void TimelineWidget::ReplaceBlocksWithGaps(const QVector<Block *> &blocks,
|
||||
bool remove_from_graph,
|
||||
QUndoCommand *command)
|
||||
bool remove_from_graph,
|
||||
QUndoCommand *command)
|
||||
{
|
||||
foreach (Block* b, blocks) {
|
||||
if (b->type() == Block::kGap) {
|
||||
@@ -440,7 +430,7 @@ void TimelineWidget::ReplaceBlocksWithGaps(const QVector<Block *> &blocks,
|
||||
continue;
|
||||
}
|
||||
|
||||
Track* original_track = Track::TrackFromBlock(b);
|
||||
Track* original_track = b->track();
|
||||
|
||||
new TrackReplaceBlockWithGapCommand(original_track, b, command);
|
||||
|
||||
@@ -452,12 +442,10 @@ void TimelineWidget::ReplaceBlocksWithGaps(const QVector<Block *> &blocks,
|
||||
|
||||
void TimelineWidget::DeleteSelected(bool ripple)
|
||||
{
|
||||
QVector<TimelineViewBlockItem *> selected_list = GetSelectedBlocks();
|
||||
QVector<Block*> selected_list = GetSelectedBlocks();
|
||||
QVector<Block*> blocks_to_delete;
|
||||
|
||||
foreach (TimelineViewBlockItem* item, selected_list) {
|
||||
Block* b = item->block();
|
||||
|
||||
foreach (Block* b, selected_list) {
|
||||
blocks_to_delete.append(b);
|
||||
}
|
||||
|
||||
@@ -481,7 +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(Track::TrackFromBlock(transition),
|
||||
new TransitionRemoveCommand(transition->track(),
|
||||
transition,
|
||||
command);
|
||||
|
||||
@@ -536,35 +524,35 @@ void TimelineWidget::DecreaseTrackHeight()
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::InsertFootageAtPlayhead(const QList<Footage*>& footage)
|
||||
void TimelineWidget::InsertFootageAtPlayhead(const QVector<Footage*>& footage)
|
||||
{
|
||||
import_tool_->PlaceAt(footage, GetTime(), true);
|
||||
}
|
||||
|
||||
void TimelineWidget::OverwriteFootageAtPlayhead(const QList<Footage *> &footage)
|
||||
void TimelineWidget::OverwriteFootageAtPlayhead(const QVector<Footage *> &footage)
|
||||
{
|
||||
import_tool_->PlaceAt(footage, GetTime(), false);
|
||||
}
|
||||
|
||||
void TimelineWidget::ToggleLinksOnSelected()
|
||||
{
|
||||
QVector<TimelineViewBlockItem*> sel = GetSelectedBlocks();
|
||||
QVector<Block*> sel = GetSelectedBlocks();
|
||||
|
||||
QVector<Block*> blocks;
|
||||
bool link = true;
|
||||
|
||||
foreach (TimelineViewBlockItem* item, sel) {
|
||||
foreach (Block* item, sel) {
|
||||
// Only clips can be linked
|
||||
if (item->block()->type() != Block::kClip) {
|
||||
if (item->type() != Block::kClip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prioritize unlinking, if any block has links, assume we're unlinking
|
||||
if (link && item->block()->HasLinks()) {
|
||||
if (link && item->HasLinks()) {
|
||||
link = false;
|
||||
}
|
||||
|
||||
blocks.append(item->block());
|
||||
blocks.append(item);
|
||||
}
|
||||
|
||||
if (blocks.isEmpty()) {
|
||||
@@ -580,7 +568,7 @@ void TimelineWidget::CopySelected(bool cut)
|
||||
return;
|
||||
}
|
||||
|
||||
QVector<TimelineViewBlockItem*> selected = GetSelectedBlocks();
|
||||
QVector<Block*> selected = GetSelectedBlocks();
|
||||
|
||||
if (selected.isEmpty()) {
|
||||
return;
|
||||
@@ -588,9 +576,7 @@ void TimelineWidget::CopySelected(bool cut)
|
||||
|
||||
QVector<Node*> selected_nodes;
|
||||
|
||||
foreach (TimelineViewBlockItem* item, selected) {
|
||||
Node* block = item->block();
|
||||
|
||||
foreach (Block* block, selected) {
|
||||
selected_nodes.append(block);
|
||||
|
||||
QVector<Node*> deps = block->GetDependencies();
|
||||
@@ -675,7 +661,7 @@ void TimelineWidget::DeleteInToOut(bool ripple)
|
||||
gap,
|
||||
command);
|
||||
|
||||
new TrackPlaceBlockCommand(GetConnectedNode()->track_list(track->track_type()),
|
||||
new TrackPlaceBlockCommand(GetConnectedNode()->track_list(track->type()),
|
||||
track->Index(),
|
||||
gap,
|
||||
GetConnectedTimelinePoints()->workarea()->in(),
|
||||
@@ -699,7 +685,7 @@ void TimelineWidget::DeleteInToOut(bool ripple)
|
||||
|
||||
void TimelineWidget::ToggleSelectedEnabled()
|
||||
{
|
||||
QVector<TimelineViewBlockItem*> items = GetSelectedBlocks();
|
||||
QVector<Block*> items = GetSelectedBlocks();
|
||||
|
||||
if (items.isEmpty()) {
|
||||
return;
|
||||
@@ -707,29 +693,18 @@ void TimelineWidget::ToggleSelectedEnabled()
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
|
||||
foreach (TimelineViewBlockItem* i, items) {
|
||||
new BlockEnableDisableCommand(i->block(),
|
||||
!i->block()->is_enabled(),
|
||||
foreach (Block* i, items) {
|
||||
new BlockEnableDisableCommand(i,
|
||||
!i->is_enabled(),
|
||||
command);
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
}
|
||||
|
||||
QVector<Block *> TimelineWidget::GetSelectedBlocks()
|
||||
{
|
||||
QVector<Block*> list(selected_blocks_.size());
|
||||
|
||||
for (int i=0; i<selected_blocks_.size(); i++) {
|
||||
list[i] = block_items_.value(selected_blocks_.at(i));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void TimelineWidget::InsertGapsAt(const rational &earliest_point, const rational &insert_length, QUndoCommand *command)
|
||||
{
|
||||
for (int i=0;i<Timeline::kTrackTypeCount;i++) {
|
||||
for (int i=0;i<Track::kCount;i++) {
|
||||
new TrackListInsertGaps(GetConnectedNode()->track_list(static_cast<Track::Type>(i)),
|
||||
earliest_point,
|
||||
insert_length,
|
||||
@@ -737,17 +712,17 @@ void TimelineWidget::InsertGapsAt(const rational &earliest_point, const rational
|
||||
}
|
||||
}
|
||||
|
||||
Track *TimelineWidget::GetTrackFromReference(const TrackReference &ref) const
|
||||
Track *TimelineWidget::GetTrackFromReference(const Track::Reference &ref) const
|
||||
{
|
||||
return GetConnectedNode()->track_list(ref.type())->GetTrackAt(ref.index());
|
||||
}
|
||||
|
||||
int TimelineWidget::GetTrackY(const TrackReference &ref)
|
||||
int TimelineWidget::GetTrackY(const Track::Reference &ref)
|
||||
{
|
||||
return views_.at(ref.type())->view()->GetTrackY(ref.index());
|
||||
}
|
||||
|
||||
int TimelineWidget::GetTrackHeight(const TrackReference &ref)
|
||||
int TimelineWidget::GetTrackHeight(const Track::Reference &ref)
|
||||
{
|
||||
return views_.at(ref.type())->view()->GetTrackHeight(ref.index());
|
||||
}
|
||||
@@ -804,7 +779,6 @@ void TimelineWidget::ViewMouseMoved(TimelineViewMouseEvent *event)
|
||||
|
||||
if (hover_tool) {
|
||||
hover_tool->HoverMove(event);
|
||||
UpdateViewports();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -851,35 +825,15 @@ void TimelineWidget::ViewDragDropped(TimelineViewMouseEvent *event)
|
||||
UpdateViewports();
|
||||
}
|
||||
|
||||
void TimelineWidget::AddBlock(Block *block, TrackReference track)
|
||||
void TimelineWidget::AddBlock(Block *block)
|
||||
{
|
||||
// Set up clip with view parameters (clip item will automatically size its rect accordingly)
|
||||
TimelineViewBlockItem* item = block_items_.value(block);
|
||||
|
||||
if (!item) {
|
||||
|
||||
// Add to list of clip items that can be iterated through
|
||||
item = new TimelineViewBlockItem(block);
|
||||
block_items_.insert(block, item);
|
||||
|
||||
// Set scale parameters
|
||||
item->SetScale(GetScale());
|
||||
item->SetTimebase(timebase());
|
||||
item->SetYCoords(GetTrackY(track), GetTrackHeight(track));
|
||||
item->SetTrack(track);
|
||||
|
||||
// Add item to graphics scene
|
||||
views_.at(track.type())->view()->scene()->addItem(item);
|
||||
|
||||
if (!added_blocks_.contains(block)) {
|
||||
connect(block, &Block::LinksChanged, this, &TimelineWidget::BlockUpdated);
|
||||
connect(block, &Block::LabelChanged, this, &TimelineWidget::BlockUpdated);
|
||||
connect(block, &Block::EnabledChanged, this, &TimelineWidget::BlockUpdated);
|
||||
|
||||
} else if (item->Track() != track) {
|
||||
|
||||
item->SetYCoords(GetTrackY(track), GetTrackHeight(track));
|
||||
item->SetTrack(track);
|
||||
|
||||
added_blocks_.append(block);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -891,84 +845,54 @@ void TimelineWidget::RemoveBlock(Block *b)
|
||||
disconnect(b, &Block::EnabledChanged, this, &TimelineWidget::BlockUpdated);
|
||||
|
||||
// Take item from map
|
||||
TimelineViewBlockItem* item = block_items_.take(b);
|
||||
added_blocks_.removeOne(b);
|
||||
|
||||
// If selected, deselect it
|
||||
int select_index = selected_blocks_.indexOf(b);
|
||||
if (select_index > -1) {
|
||||
selected_blocks_.removeAt(select_index);
|
||||
RemoveSelection(item);
|
||||
RemoveSelection(b);
|
||||
|
||||
emit BlocksDeselected({b});
|
||||
}
|
||||
|
||||
// Finally, delete item
|
||||
delete item;
|
||||
|
||||
emit BlocksDeselected({b});
|
||||
}
|
||||
|
||||
void TimelineWidget::AddTrack(Track *track, Track::Type type)
|
||||
void TimelineWidget::AddTrack(Track *track)
|
||||
{
|
||||
foreach (Block* b, track->Blocks()) {
|
||||
AddBlock(b, TrackReference(type, track->Index()));
|
||||
AddBlock(b);
|
||||
}
|
||||
|
||||
connect(track, &Track::IndexChanged, this, &TimelineWidget::TrackIndexChanged);
|
||||
connect(track, &Track::PreviewChanged, this, &TimelineWidget::TrackPreviewUpdated);
|
||||
connect(track, &Track::IndexChanged, this, &TimelineWidget::TrackUpdated);
|
||||
connect(track, &Track::PreviewChanged, this, &TimelineWidget::TrackUpdated);
|
||||
connect(track, &Track::BlocksRefreshed, this, &TimelineWidget::TrackUpdated);
|
||||
connect(track, &Track::TrackHeightChangedInPixels, this, &TimelineWidget::TrackUpdated);
|
||||
connect(track, &Track::BlockAdded, this, &TimelineWidget::AddBlock);
|
||||
connect(track, &Track::BlockRemoved, this, &TimelineWidget::RemoveBlock);
|
||||
}
|
||||
|
||||
void TimelineWidget::RemoveTrack(Track *track)
|
||||
{
|
||||
disconnect(track, &Track::IndexChanged, this, &TimelineWidget::TrackIndexChanged);
|
||||
disconnect(track, &Track::PreviewChanged, this, &TimelineWidget::TrackPreviewUpdated);
|
||||
disconnect(track, &Track::IndexChanged, this, &TimelineWidget::TrackUpdated);
|
||||
disconnect(track, &Track::PreviewChanged, this, &TimelineWidget::TrackUpdated);
|
||||
disconnect(track, &Track::BlocksRefreshed, this, &TimelineWidget::TrackUpdated);
|
||||
disconnect(track, &Track::TrackHeightChangedInPixels, this, &TimelineWidget::TrackUpdated);
|
||||
disconnect(track, &Track::BlockAdded, this, &TimelineWidget::AddBlock);
|
||||
disconnect(track, &Track::BlockRemoved, this, &TimelineWidget::RemoveBlock);
|
||||
|
||||
foreach (Block* b, track->Blocks()) {
|
||||
RemoveBlock(b);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::TrackIndexChanged()
|
||||
void TimelineWidget::TrackUpdated()
|
||||
{
|
||||
Track* track = static_cast<Track*>(sender());
|
||||
TrackReference ref(track->track_type(), track->Index());
|
||||
|
||||
foreach (Block* b, track->Blocks()) {
|
||||
TimelineViewBlockItem* item = block_items_.value(b);
|
||||
|
||||
item->SetYCoords(GetTrackY(ref), GetTrackHeight(ref));
|
||||
item->SetTrack(ref);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::BlockRefreshed()
|
||||
{
|
||||
TimelineViewRect* rect = block_items_.value(static_cast<Block*>(sender()));
|
||||
|
||||
if (rect) {
|
||||
rect->UpdateRect();
|
||||
}
|
||||
UpdateViewports(static_cast<Track*>(sender())->type());
|
||||
}
|
||||
|
||||
void TimelineWidget::BlockUpdated()
|
||||
{
|
||||
TimelineViewRect* rect = block_items_.value(static_cast<Block*>(sender()));
|
||||
|
||||
if (rect) {
|
||||
rect->update();
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::TrackPreviewUpdated()
|
||||
{
|
||||
QMap<Block*, TimelineViewBlockItem*>::const_iterator i;
|
||||
|
||||
Track* track = static_cast<Track*>(sender());
|
||||
TrackReference track_ref(track->track_type(), track->Index());
|
||||
|
||||
for (i=block_items_.constBegin(); i!=block_items_.constEnd(); i++) {
|
||||
if (i.value()->Track() == track_ref) {
|
||||
i.value()->update();
|
||||
}
|
||||
}
|
||||
UpdateViewports(static_cast<Block*>(sender())->track()->type());
|
||||
}
|
||||
|
||||
void TimelineWidget::UpdateHorizontalSplitters()
|
||||
@@ -993,29 +917,11 @@ void TimelineWidget::UpdateTimecodeWidthFromSplitters(QSplitter* s)
|
||||
timecode_label_->setFixedWidth(s->sizes().first() + s->handleWidth());
|
||||
}
|
||||
|
||||
void TimelineWidget::TrackHeightChanged(Track::Type type, int index, int height)
|
||||
{
|
||||
Q_UNUSED(index)
|
||||
Q_UNUSED(height)
|
||||
|
||||
QMap<Block*, TimelineViewBlockItem*>::const_iterator iterator;
|
||||
TimelineView* view = views_.at(type)->view();
|
||||
|
||||
for (iterator=block_items_.begin();iterator!=block_items_.end();iterator++) {
|
||||
TimelineViewBlockItem* block_item = iterator.value();
|
||||
|
||||
if (block_item->Track().type() == type) {
|
||||
block_item->SetYCoords(view->GetTrackY(block_item->Track().index()),
|
||||
view->GetTrackHeight(block_item->Track().index()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::ShowContextMenu()
|
||||
{
|
||||
Menu menu(this);
|
||||
|
||||
QVector<TimelineViewBlockItem*> selected = GetSelectedBlocks();
|
||||
QVector<Block*> selected = GetSelectedBlocks();
|
||||
|
||||
if (!selected.isEmpty()) {
|
||||
MenuShared::instance()->AddItemsForEditMenu(&menu, true);
|
||||
@@ -1024,11 +930,11 @@ void TimelineWidget::ShowContextMenu()
|
||||
|
||||
QAction* properties_action = menu.addAction(tr("Properties"));
|
||||
connect(properties_action, &QAction::triggered, this, [this](){
|
||||
QVector<TimelineViewBlockItem*> block_items = GetSelectedBlocks();
|
||||
QVector<Block*> block_items = GetSelectedBlocks();
|
||||
QVector<Node*> nodes;
|
||||
|
||||
foreach (TimelineViewBlockItem* i, block_items) {
|
||||
nodes.append(i->block());
|
||||
foreach (Block* i, block_items) {
|
||||
nodes.append(i);
|
||||
}
|
||||
|
||||
Core::instance()->LabelNodes(nodes);
|
||||
@@ -1082,7 +988,7 @@ void TimelineWidget::SetViewTimestamp(const int64_t &ts)
|
||||
for (int i=0;i<views_.size();i++) {
|
||||
TimelineAndTrackView* view = views_.at(i);
|
||||
|
||||
if (use_audio_time_units_ && i == Timeline::kTrackTypeAudio) {
|
||||
if (use_audio_time_units_ && i == Track::kAudio) {
|
||||
view->view()->SetTime(Timecode::rescale_timestamp(ts,
|
||||
timebase(),
|
||||
GetConnectedNode()->audio_params().time_base()));
|
||||
@@ -1094,7 +1000,7 @@ void TimelineWidget::SetViewTimestamp(const int64_t &ts)
|
||||
|
||||
void TimelineWidget::ViewTimestampChanged(int64_t ts)
|
||||
{
|
||||
if (use_audio_time_units_ && sender() == views_.at(Timeline::kTrackTypeAudio)) {
|
||||
if (use_audio_time_units_ && sender() == views_.at(Track::kAudio)) {
|
||||
ts = Timecode::rescale_timestamp(ts,
|
||||
GetConnectedNode()->audio_params().time_base(),
|
||||
timebase());
|
||||
@@ -1124,7 +1030,7 @@ void TimelineWidget::UpdateViewTimebases()
|
||||
for (int i=0;i<views_.size();i++) {
|
||||
TimelineAndTrackView* view = views_.at(i);
|
||||
|
||||
if (use_audio_time_units_ && i == Timeline::kTrackTypeAudio) {
|
||||
if (use_audio_time_units_ && i == Track::kAudio) {
|
||||
view->view()->SetTimebase(GetConnectedNode()->audio_params().time_base());
|
||||
} else {
|
||||
view->view()->SetTimebase(timebase());
|
||||
@@ -1141,17 +1047,11 @@ void TimelineWidget::SetViewBeamCursor(const TimelineCoordinate &coord)
|
||||
|
||||
void TimelineWidget::SetBlockLinksSelected(Block* block, bool selected)
|
||||
{
|
||||
TimelineViewBlockItem* link_item;
|
||||
|
||||
foreach (Block* link, block->linked_clips()) {
|
||||
link_item = block_items_.value(link);
|
||||
|
||||
if (link_item) {
|
||||
if (selected) {
|
||||
AddSelection(link_item);
|
||||
} else {
|
||||
RemoveSelection(link_item);
|
||||
}
|
||||
if (selected) {
|
||||
AddSelection(link);
|
||||
} else {
|
||||
RemoveSelection(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1357,7 +1257,7 @@ void TimelineWidget::EditTo(Timeline::MovementMode mode)
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
}
|
||||
|
||||
void TimelineWidget::ShowSnap(const QList<rational> ×)
|
||||
void TimelineWidget::ShowSnap(const QVector<rational> ×)
|
||||
{
|
||||
foreach (TimelineAndTrackView* tview, views_) {
|
||||
tview->view()->EnableSnap(times);
|
||||
@@ -1366,7 +1266,7 @@ void TimelineWidget::ShowSnap(const QList<rational> ×)
|
||||
|
||||
void TimelineWidget::UpdateViewports(const Track::Type &type)
|
||||
{
|
||||
if (type == Timeline::kTrackTypeNone) {
|
||||
if (type == Track::kNone) {
|
||||
foreach (TimelineAndTrackView* tview, views_) {
|
||||
tview->view()->viewport()->update();
|
||||
}
|
||||
@@ -1375,6 +1275,46 @@ void TimelineWidget::UpdateViewports(const Track::Type &type)
|
||||
}
|
||||
}
|
||||
|
||||
QVector<Block *> TimelineWidget::GetBlocksInGlobalRect(const QPoint &p1, const QPoint& p2)
|
||||
{
|
||||
QVector<Block*> blocks_in_rect;
|
||||
|
||||
// Determine which tracks are in the rect
|
||||
for (int i=0; i<views_.size(); i++) {
|
||||
TimelineView* view = views_.at(i)->view();
|
||||
|
||||
// Map global mouse coordinates to viewport
|
||||
QRectF mapped_rect(view->mapToScene(view->viewport()->mapFromGlobal(p1)),
|
||||
view->mapToScene(view->viewport()->mapFromGlobal(p2)));
|
||||
|
||||
// Normalize
|
||||
mapped_rect = mapped_rect.normalized();
|
||||
|
||||
// Get tracks
|
||||
TrackList* track_list = GetConnectedNode()->track_list(static_cast<Track::Type>(i));
|
||||
|
||||
for (int j=0; j<track_list->GetTrackCount(); j++) {
|
||||
int track_top = view->GetTrackY(j);
|
||||
int track_bottom = track_top + view->GetTrackHeight(j);
|
||||
|
||||
if (!(track_bottom < mapped_rect.top() || track_top > mapped_rect.bottom())) {
|
||||
// This track is in the rect, so we'll iterate through its blocks and see where they start
|
||||
rational left_time = SceneToTime(mapped_rect.left());
|
||||
rational right_time = SceneToTime(mapped_rect.right(), true);
|
||||
|
||||
Track* track = track_list->GetTrackAt(j);
|
||||
foreach (Block* b, track->Blocks()) {
|
||||
if (!(b->out() < left_time || b->in() > right_time)) {
|
||||
blocks_in_rect.append(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blocks_in_rect;
|
||||
}
|
||||
|
||||
void TimelineWidget::HideSnaps()
|
||||
{
|
||||
foreach (TimelineAndTrackView* tview, views_) {
|
||||
@@ -1417,21 +1357,8 @@ void TimelineWidget::MoveRubberBandSelect(bool enable_selecting, bool select_lin
|
||||
return;
|
||||
}
|
||||
|
||||
QList<QGraphicsItem*> items_in_rubberband;
|
||||
|
||||
// Determine all items in the rubberband
|
||||
foreach (TimelineAndTrackView* tview, views_) {
|
||||
TimelineView* view = tview->view();
|
||||
|
||||
// Map global mouse coordinates to viewport
|
||||
QRect mapped_rect(view->viewport()->mapFromGlobal(drag_origin_),
|
||||
view->viewport()->mapFromGlobal(rubberband_now));
|
||||
|
||||
// Normalize and get items in rect
|
||||
QList<QGraphicsItem*> rubberband_items = view->items(mapped_rect.normalized());
|
||||
|
||||
items_in_rubberband.append(rubberband_items);
|
||||
}
|
||||
// Get current items in rubberband
|
||||
QVector<Block*> items_in_rubberband = GetBlocksInGlobalRect(drag_origin_, rubberband_now);
|
||||
|
||||
// Reset selection to whatever it was before
|
||||
SetSelections(rubberband_old_selections_);
|
||||
@@ -1439,32 +1366,26 @@ void TimelineWidget::MoveRubberBandSelect(bool enable_selecting, bool select_lin
|
||||
// Add any blocks in rubberband
|
||||
rubberband_now_selected_.clear();
|
||||
|
||||
foreach (QGraphicsItem* item, items_in_rubberband) {
|
||||
TimelineViewBlockItem* block_item = dynamic_cast<TimelineViewBlockItem*>(item);
|
||||
foreach (Block* b, items_in_rubberband) {
|
||||
if (b->type() == Block::kGap) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (block_item) {
|
||||
Block* b = block_item->block();
|
||||
Track* t = b->track();
|
||||
if (t->IsLocked()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (b->type() == Block::kGap) {
|
||||
continue;
|
||||
}
|
||||
if (!rubberband_now_selected_.contains(b)) {
|
||||
AddSelection(b);
|
||||
rubberband_now_selected_.append(b);
|
||||
}
|
||||
|
||||
Track* t = GetTrackFromReference(block_item->Track());
|
||||
if (t && t->IsLocked()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!rubberband_now_selected_.contains(b)) {
|
||||
AddSelection(block_item);
|
||||
rubberband_now_selected_.append(b);
|
||||
}
|
||||
|
||||
if (select_links) {
|
||||
foreach (Block* link, b->linked_clips()) {
|
||||
if (!rubberband_now_selected_.contains(link)) {
|
||||
AddSelection(block_items_.value(link));
|
||||
rubberband_now_selected_.append(link);
|
||||
}
|
||||
if (select_links) {
|
||||
foreach (Block* link, b->linked_clips()) {
|
||||
if (!rubberband_now_selected_.contains(link)) {
|
||||
AddSelection(link);
|
||||
rubberband_now_selected_.append(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1482,7 +1403,7 @@ void TimelineWidget::EndRubberBandSelect()
|
||||
rubberband_old_selections_.clear();
|
||||
}
|
||||
|
||||
void TimelineWidget::AddSelection(const TimeRange &time, const TrackReference &track)
|
||||
void TimelineWidget::AddSelection(const TimeRange &time, const Track::Reference &track)
|
||||
{
|
||||
selections_[track].insert(time);
|
||||
|
||||
@@ -1491,10 +1412,10 @@ void TimelineWidget::AddSelection(const TimeRange &time, const TrackReference &t
|
||||
|
||||
void TimelineWidget::AddSelection(Block *item)
|
||||
{
|
||||
AddSelection(item->block()->range(), item->Track());
|
||||
AddSelection(item->range(), item->track()->ToReference());
|
||||
}
|
||||
|
||||
void TimelineWidget::RemoveSelection(const TimeRange &time, const TrackReference &track)
|
||||
void TimelineWidget::RemoveSelection(const TimeRange &time, const Track::Reference &track)
|
||||
{
|
||||
selections_[track].remove(time);
|
||||
|
||||
@@ -1503,7 +1424,7 @@ void TimelineWidget::RemoveSelection(const TimeRange &time, const TrackReference
|
||||
|
||||
void TimelineWidget::RemoveSelection(Block *item)
|
||||
{
|
||||
RemoveSelection(item->block()->range(), item->Track());
|
||||
RemoveSelection(item->range(), item->track()->ToReference());
|
||||
}
|
||||
|
||||
void TimelineWidget::SetSelections(const TimelineWidgetSelections &s)
|
||||
@@ -1515,14 +1436,13 @@ void TimelineWidget::SetSelections(const TimelineWidgetSelections &s)
|
||||
|
||||
Block *TimelineWidget::GetItemAtScenePos(const TimelineCoordinate& coord)
|
||||
{
|
||||
for (auto it=block_items_.cbegin(); it!=block_items_.cend(); it++) {
|
||||
Block* b = it.key();
|
||||
TimelineViewBlockItem* item = it.value();
|
||||
Track* track = GetTrackFromReference(coord.GetTrack());
|
||||
|
||||
foreach (Block* b, added_blocks_) {
|
||||
if (b->in() <= coord.GetFrame()
|
||||
&& b->out() > coord.GetFrame()
|
||||
&& item->Track() == coord.GetTrack()) {
|
||||
return item;
|
||||
&& b->track() == track) {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1534,13 +1454,13 @@ struct SnapData {
|
||||
rational movement;
|
||||
};
|
||||
|
||||
QList<SnapData> AttemptSnap(const QList<double>& screen_pt,
|
||||
double compare_pt,
|
||||
const QList<rational>& start_times,
|
||||
const rational& compare_time) {
|
||||
QVector<SnapData> AttemptSnap(const QVector<double>& screen_pt,
|
||||
double compare_pt,
|
||||
const QVector<rational>& start_times,
|
||||
const rational& compare_time) {
|
||||
const qreal kSnapRange = 10; // FIXME: Hardcoded number
|
||||
|
||||
QList<SnapData> snap_data;
|
||||
QVector<SnapData> snap_data;
|
||||
|
||||
for (int i=0;i<screen_pt.size();i++) {
|
||||
// Attempt snapping to clip out point
|
||||
@@ -1552,15 +1472,15 @@ QList<SnapData> AttemptSnap(const QList<double>& screen_pt,
|
||||
return snap_data;
|
||||
}
|
||||
|
||||
bool TimelineWidget::SnapPoint(QList<rational> start_times, rational* movement, int snap_points)
|
||||
bool TimelineWidget::SnapPoint(QVector<rational> start_times, rational* movement, int snap_points)
|
||||
{
|
||||
QList<double> screen_pt;
|
||||
QVector<double> screen_pt;
|
||||
|
||||
foreach (const rational& s, start_times) {
|
||||
screen_pt.append(TimeToScene(s + *movement));
|
||||
}
|
||||
|
||||
QList<SnapData> potential_snaps;
|
||||
QVector<SnapData> potential_snaps;
|
||||
|
||||
if (snap_points & kSnapToPlayhead) {
|
||||
rational playhead_abs_time = GetTime();
|
||||
@@ -1569,21 +1489,15 @@ bool TimelineWidget::SnapPoint(QList<rational> start_times, rational* movement,
|
||||
}
|
||||
|
||||
if (snap_points & kSnapToClips) {
|
||||
QMap<Block*, TimelineViewBlockItem*>::const_iterator i;
|
||||
foreach (Block* b, added_blocks_) {
|
||||
qreal rect_left = TimeToScene(b->in());
|
||||
qreal rect_right = TimeToScene(b->out());
|
||||
|
||||
for (i=block_items_.constBegin(); i!=block_items_.constEnd(); i++) {
|
||||
TimelineViewBlockItem* item = i.value();
|
||||
// Attempt snapping to clip in point
|
||||
potential_snaps.append(AttemptSnap(screen_pt, rect_left, start_times, b->in()));
|
||||
|
||||
if (item) {
|
||||
qreal rect_left = item->x();
|
||||
qreal rect_right = rect_left + item->rect().width();
|
||||
|
||||
// Attempt snapping to clip in point
|
||||
potential_snaps.append(AttemptSnap(screen_pt, rect_left, start_times, item->block()->in()));
|
||||
|
||||
// Attempt snapping to clip out point
|
||||
potential_snaps.append(AttemptSnap(screen_pt, rect_right, start_times, item->block()->out()));
|
||||
}
|
||||
// Attempt snapping to clip out point
|
||||
potential_snaps.append(AttemptSnap(screen_pt, rect_right, start_times, b->out()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1620,7 +1534,7 @@ bool TimelineWidget::SnapPoint(QList<rational> start_times, rational* movement,
|
||||
*movement = potential_snaps.at(closest_snap).movement;
|
||||
|
||||
// Find all points at this movement
|
||||
QList<rational> snap_times;
|
||||
QVector<rational> snap_times;
|
||||
foreach (const SnapData& d, potential_snaps) {
|
||||
if (d.movement == *movement) {
|
||||
snap_times.append(d.time);
|
||||
|
||||
@@ -75,9 +75,9 @@ public:
|
||||
|
||||
void DecreaseTrackHeight();
|
||||
|
||||
void InsertFootageAtPlayhead(const QList<Footage *> &footage);
|
||||
void InsertFootageAtPlayhead(const QVector<Footage *> &footage);
|
||||
|
||||
void OverwriteFootageAtPlayhead(const QList<Footage *> &footage);
|
||||
void OverwriteFootageAtPlayhead(const QVector<Footage *> &footage);
|
||||
|
||||
void ToggleLinksOnSelected();
|
||||
|
||||
@@ -94,17 +94,7 @@ public:
|
||||
return selected_blocks_;
|
||||
}
|
||||
|
||||
Track* GetTrackFromBlock(Block* block) const
|
||||
{
|
||||
return GetTrackFromReference(GetTrackReferenceFromBlock(block));
|
||||
}
|
||||
|
||||
TrackReference GetTrackReferenceFromBlock(Block* block) const
|
||||
{
|
||||
return track_lookup_.value(block);
|
||||
}
|
||||
|
||||
virtual bool SnapPoint(QList<rational> start_times, rational *movement, int snap_points = kSnapAll) override;
|
||||
virtual bool SnapPoint(QVector<rational> start_times, rational *movement, int snap_points = kSnapAll) override;
|
||||
|
||||
virtual void HideSnaps() override;
|
||||
|
||||
@@ -122,10 +112,10 @@ public:
|
||||
*/
|
||||
Block* GetItemAtScenePos(const TimelineCoordinate &coord);
|
||||
|
||||
void AddSelection(const TimeRange& time, const TrackReference& track);
|
||||
void AddSelection(const TimeRange& time, const Track::Reference& track);
|
||||
void AddSelection(Block* item);
|
||||
|
||||
void RemoveSelection(const TimeRange& time, const TrackReference& track);
|
||||
void RemoveSelection(const TimeRange& time, const Track::Reference& track);
|
||||
void RemoveSelection(Block* item);
|
||||
|
||||
const TimelineWidgetSelections& GetSelections() const
|
||||
@@ -135,7 +125,7 @@ public:
|
||||
|
||||
void SetSelections(const TimelineWidgetSelections &s);
|
||||
|
||||
Track* GetTrackFromReference(const TrackReference& ref) const;
|
||||
Track* GetTrackFromReference(const Track::Reference& ref) const;
|
||||
|
||||
void SetViewBeamCursor(const TimelineCoordinate& coord);
|
||||
|
||||
@@ -150,8 +140,8 @@ public:
|
||||
void MoveRubberBandSelect(bool enable_selecting, bool select_links);
|
||||
void EndRubberBandSelect();
|
||||
|
||||
int GetTrackY(const TrackReference& ref);
|
||||
int GetTrackHeight(const TrackReference& ref);
|
||||
int GetTrackY(const Track::Reference& ref);
|
||||
int GetTrackHeight(const Track::Reference& ref);
|
||||
|
||||
void AddGhost(TimelineViewGhostItem* ghost);
|
||||
|
||||
@@ -237,10 +227,12 @@ private:
|
||||
|
||||
void EditTo(Timeline::MovementMode mode);
|
||||
|
||||
void ShowSnap(const QList<rational>& times);
|
||||
void ShowSnap(const QVector<rational>& times);
|
||||
|
||||
void UpdateViewports(const Track::Type& type = Track::kNone);
|
||||
|
||||
QVector<Block*> GetBlocksInGlobalRect(const QPoint &p1, const QPoint &p2);
|
||||
|
||||
QPoint drag_origin_;
|
||||
|
||||
QRubberBand rubberband_;
|
||||
@@ -259,14 +251,14 @@ private:
|
||||
|
||||
QVector<TimelineViewGhostItem*> ghost_items_;
|
||||
|
||||
QHash<Block*, TrackReference> track_lookup_;
|
||||
|
||||
QList<TimelineAndTrackView*> views_;
|
||||
QVector<TimelineAndTrackView*> views_;
|
||||
|
||||
TimeSlider* timecode_label_;
|
||||
|
||||
QVector<Block*> selected_blocks_;
|
||||
|
||||
QVector<Block*> added_blocks_;
|
||||
|
||||
int deferred_scroll_value_;
|
||||
|
||||
bool use_audio_time_units_;
|
||||
@@ -288,31 +280,19 @@ private slots:
|
||||
void ViewDragLeft(QDragLeaveEvent* event);
|
||||
void ViewDragDropped(TimelineViewMouseEvent* event);
|
||||
|
||||
void AddBlock(Block* block, TrackReference track);
|
||||
void AddBlock(Block* block);
|
||||
void RemoveBlock(Block *blocks);
|
||||
|
||||
void AddTrack(Track* track, Track::Type type);
|
||||
void AddTrack(Track* track);
|
||||
void RemoveTrack(Track* track);
|
||||
void TrackIndexChanged();
|
||||
|
||||
/**
|
||||
* @brief Slot for when a Block node changes its parameters and the graphics need to update
|
||||
*
|
||||
* This slot does a static_cast on sender() to Block*, meaning all objects triggering this slot must be Blocks or
|
||||
* derivatives.
|
||||
*/
|
||||
void BlockRefreshed();
|
||||
void TrackUpdated();
|
||||
|
||||
void BlockUpdated();
|
||||
|
||||
void TrackPreviewUpdated();
|
||||
|
||||
void UpdateHorizontalSplitters();
|
||||
|
||||
void UpdateTimecodeWidthFromSplitters(QSplitter *s);
|
||||
|
||||
void TrackHeightChanged(Track::Type type, int index, int height);
|
||||
|
||||
void ShowContextMenu();
|
||||
|
||||
void DeferredScrollAction();
|
||||
|
||||
@@ -48,7 +48,7 @@ void TimelineWidgetSelections::ShiftTracks(Track::Type type, int diff)
|
||||
|
||||
// Then re-insert them with the diff applied
|
||||
for (auto it=cached_selections.cbegin(); it!=cached_selections.cend(); it++) {
|
||||
TrackReference ref(it.key().type(), it.key().index() + diff);
|
||||
Track::Reference ref(it.key().type(), it.key().index() + diff);
|
||||
|
||||
this->insert(ref, it.value());
|
||||
}
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
#include <QHash>
|
||||
|
||||
#include "common/timerange.h"
|
||||
#include "timeline/trackreference.h"
|
||||
#include "node/output/track/track.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class TimelineWidgetSelections : public QHash<TrackReference, TimeRangeList>
|
||||
class TimelineWidgetSelections : public QHash<Track::Reference, TimeRangeList>
|
||||
{
|
||||
public:
|
||||
TimelineWidgetSelections() = default;
|
||||
|
||||
@@ -18,14 +18,12 @@
|
||||
|
||||
***/
|
||||
|
||||
#include "widget/timelinewidget/timelinewidget.h"
|
||||
|
||||
#include "add.h"
|
||||
#include "core.h"
|
||||
#include "node/factory.h"
|
||||
#include "node/generator/solid/solid.h"
|
||||
#include "node/generator/text/text.h"
|
||||
#include "widget/nodeview/nodeviewundo.h"
|
||||
#include "widget/timelinewidget/timelinewidget.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -37,7 +35,7 @@ AddTool::AddTool(TimelineWidget *parent) :
|
||||
|
||||
void AddTool::MousePress(TimelineViewMouseEvent *event)
|
||||
{
|
||||
const TrackReference& track = event->GetTrack();
|
||||
const Track::Reference& track = event->GetTrack();
|
||||
|
||||
// Check if track is locked
|
||||
Track* t = parent()->GetTrackFromReference(track);
|
||||
@@ -89,7 +87,7 @@ void AddTool::MouseMove(TimelineViewMouseEvent *event)
|
||||
|
||||
void AddTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
{
|
||||
const TrackReference& track = ghost_->GetTrack();
|
||||
const Track::Reference& track = ghost_->GetTrack();
|
||||
|
||||
if (ghost_) {
|
||||
if (!ghost_->GetAdjustedLength().isNull()) {
|
||||
|
||||
@@ -80,7 +80,7 @@ void EditTool::MouseDoubleClick(TimelineViewMouseEvent *event)
|
||||
{
|
||||
Block* item = parent()->GetItemAtScenePos(event->GetCoordinates());
|
||||
|
||||
if (item && !parent()->GetTrackFromBlock(item)->IsLocked()) {
|
||||
if (item && !item->track()->IsLocked()) {
|
||||
parent()->AddSelection(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
***/
|
||||
|
||||
#include "widget/timelinewidget/timelinewidget.h"
|
||||
#include "import.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QMessageBox>
|
||||
@@ -192,12 +192,12 @@ void ImportTool::DragDrop(TimelineViewMouseEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
void ImportTool::PlaceAt(const QList<Footage *> &footage, const rational &start, bool insert)
|
||||
void ImportTool::PlaceAt(const QVector<Footage *> &footage, const rational &start, bool insert)
|
||||
{
|
||||
PlaceAt(FootageToDraggedFootage(footage), start, insert);
|
||||
}
|
||||
|
||||
void ImportTool::PlaceAt(const QList<DraggedFootage> &footage, const rational &start, bool insert)
|
||||
void ImportTool::PlaceAt(const QVector<DraggedFootage> &footage, const rational &start, bool insert)
|
||||
{
|
||||
dragged_footage_ = footage;
|
||||
|
||||
@@ -209,7 +209,7 @@ void ImportTool::PlaceAt(const QList<DraggedFootage> &footage, const rational &s
|
||||
DropGhosts(insert);
|
||||
}
|
||||
|
||||
void ImportTool::FootageToGhosts(rational ghost_start, const QList<DraggedFootage> &footage_list, const rational& dest_tb, const int& track_start)
|
||||
void ImportTool::FootageToGhosts(rational ghost_start, const QVector<DraggedFootage> &footage_list, const rational& dest_tb, const int& track_start)
|
||||
{
|
||||
foreach (const DraggedFootage& footage, footage_list) {
|
||||
|
||||
@@ -255,7 +255,7 @@ void ImportTool::FootageToGhosts(rational ghost_start, const QList<DraggedFootag
|
||||
}
|
||||
}
|
||||
|
||||
ghost->SetTrack(TrackReference(track_type, track_offsets.at(track_type)));
|
||||
ghost->SetTrack(Track::Reference(track_type, track_offsets.at(track_type)));
|
||||
|
||||
// Increment track count for this track type
|
||||
track_offsets[track_type]++;
|
||||
@@ -361,7 +361,7 @@ void ImportTool::DropGhosts(bool insert)
|
||||
|
||||
if (behavior == kDWSAuto) {
|
||||
|
||||
QList<Footage*> footage_only;
|
||||
QVector<Footage*> footage_only;
|
||||
|
||||
foreach (const DraggedFootage& df, dragged_footage_) {
|
||||
footage_only.append(df.footage());
|
||||
@@ -431,25 +431,11 @@ void ImportTool::DropGhosts(bool insert)
|
||||
video_input->SetStream(footage_stream);
|
||||
new NodeAddCommand(dst_graph, video_input, command);
|
||||
|
||||
|
||||
TransformDistortNode* transform = new TransformDistortNode();
|
||||
new NodeAddCommand(dst_graph, transform, command);
|
||||
|
||||
new NodeEdgeAddCommand(video_input, transform->texture_input(), -1, command);
|
||||
new NodeEdgeAddCommand(transform, clip->texture_input(), -1, command);
|
||||
|
||||
/*
|
||||
MatrixGenerator* matrix = new MatrixGenerator();
|
||||
new NodeAddCommand(dst_graph, matrix, command);
|
||||
|
||||
MathNode* multiply = new MathNode();
|
||||
multiply->SetOperation(MathNode::kOpMultiply);
|
||||
new NodeAddCommand(dst_graph, multiply, command);
|
||||
|
||||
new NodeEdgeAddCommand(video_input->output(), multiply->param_a_in(), command);
|
||||
new NodeEdgeAddCommand(matrix->output(), multiply->param_b_in(), command);
|
||||
new NodeEdgeAddCommand(multiply->output(), clip->texture_input(), command);
|
||||
*/
|
||||
break;
|
||||
}
|
||||
case Stream::kAudio:
|
||||
@@ -503,9 +489,9 @@ ImportTool::DraggedFootage ImportTool::FootageToDraggedFootage(Footage *f)
|
||||
return DraggedFootage(f, f->get_enabled_stream_flags());
|
||||
}
|
||||
|
||||
QList<ImportTool::DraggedFootage> ImportTool::FootageToDraggedFootage(QList<Footage *> footage)
|
||||
QVector<ImportTool::DraggedFootage> ImportTool::FootageToDraggedFootage(QVector<Footage *> footage)
|
||||
{
|
||||
QList<DraggedFootage> df;
|
||||
QVector<DraggedFootage> df;
|
||||
|
||||
foreach (Footage* f, footage) {
|
||||
df.append(FootageToDraggedFootage(f));
|
||||
|
||||
@@ -58,8 +58,8 @@ public:
|
||||
|
||||
};
|
||||
|
||||
void PlaceAt(const QList<Footage*> &footage, const rational& start, bool insert);
|
||||
void PlaceAt(const QList<DraggedFootage> &footage, const rational& start, bool insert);
|
||||
void PlaceAt(const QVector<Footage*> &footage, const rational& start, bool insert);
|
||||
void PlaceAt(const QVector<DraggedFootage> &footage, const rational& start, bool insert);
|
||||
|
||||
enum DropWithoutSequenceBehavior {
|
||||
kDWSAsk,
|
||||
@@ -70,15 +70,15 @@ public:
|
||||
|
||||
private:
|
||||
static DraggedFootage FootageToDraggedFootage(Footage* f);
|
||||
static QList<DraggedFootage> FootageToDraggedFootage(QList<Footage*> footage);
|
||||
static QVector<DraggedFootage> FootageToDraggedFootage(QVector<Footage*> footage);
|
||||
|
||||
void FootageToGhosts(rational ghost_start, const QList<DraggedFootage>& footage, const rational &dest_tb, const int &track_start);
|
||||
void FootageToGhosts(rational ghost_start, const QVector<DraggedFootage> &footage, const rational &dest_tb, const int &track_start);
|
||||
|
||||
void PrepGhosts(const rational &frame, const int &track_index);
|
||||
|
||||
void DropGhosts(bool insert);
|
||||
|
||||
QList<DraggedFootage> dragged_footage_;
|
||||
QVector<DraggedFootage> dragged_footage_;
|
||||
|
||||
int import_pre_buffer_;
|
||||
|
||||
|
||||
@@ -49,17 +49,19 @@ PointerTool::PointerTool(TimelineWidget *parent) :
|
||||
|
||||
void PointerTool::MousePress(TimelineViewMouseEvent *event)
|
||||
{
|
||||
const Track::Reference& track_ref = event->GetTrack();
|
||||
|
||||
// Determine if item clicked on is selectable
|
||||
clicked_item_ = parent()->GetItemAtScenePos(event->GetCoordinates());
|
||||
|
||||
can_rubberband_select_ = false;
|
||||
|
||||
bool selectable_item = (clicked_item_
|
||||
&& !parent()->GetTrackFromReference(clicked_item_->Track())->IsLocked());
|
||||
&& !parent()->GetTrackFromReference(track_ref)->IsLocked());
|
||||
|
||||
if (selectable_item) {
|
||||
// Cache the clip's type for use later
|
||||
drag_track_type_ = clicked_item_->Track().type();
|
||||
drag_track_type_ = track_ref.type();
|
||||
|
||||
// If we haven't started dragging yet, we'll initiate a drag here
|
||||
// Record where the drag started in timeline coordinates
|
||||
@@ -73,7 +75,7 @@ void PointerTool::MousePress(TimelineViewMouseEvent *event)
|
||||
// the block is not a gap)
|
||||
if (drag_movement_mode_ == Timeline::kNone
|
||||
&& movement_allowed_
|
||||
&& clicked_item_->block()->type() != Block::kGap) {
|
||||
&& clicked_item_->type() != Block::kGap) {
|
||||
drag_movement_mode_ = Timeline::kMove;
|
||||
}
|
||||
|
||||
@@ -86,12 +88,12 @@ void PointerTool::MousePress(TimelineViewMouseEvent *event)
|
||||
// If shift is held, deselect it
|
||||
if (event->GetModifiers() & Qt::ShiftModifier) {
|
||||
parent()->RemoveSelection(clicked_item_);
|
||||
deselected_blocks.append(clicked_item_->block());
|
||||
deselected_blocks.append(clicked_item_);
|
||||
|
||||
// If not holding alt, deselect all links as well
|
||||
if (!(event->GetModifiers() & Qt::AltModifier)) {
|
||||
parent()->SetBlockLinksSelected(clicked_item_->block(), false);
|
||||
deselected_blocks.append(clicked_item_->block()->linked_clips());
|
||||
parent()->SetBlockLinksSelected(clicked_item_, false);
|
||||
deselected_blocks.append(clicked_item_->linked_clips());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,12 +115,12 @@ void PointerTool::MousePress(TimelineViewMouseEvent *event)
|
||||
|
||||
// Select this item
|
||||
parent()->AddSelection(clicked_item_);
|
||||
selected_blocks.append(clicked_item_->block());
|
||||
selected_blocks.append(clicked_item_);
|
||||
|
||||
// If not holding alt, select all links as well
|
||||
if (!(event->GetModifiers() & Qt::AltModifier)) {
|
||||
parent()->SetBlockLinksSelected(clicked_item_->block(), true);
|
||||
selected_blocks.append(clicked_item_->block()->linked_clips());
|
||||
parent()->SetBlockLinksSelected(clicked_item_, true);
|
||||
selected_blocks.append(clicked_item_->linked_clips());
|
||||
}
|
||||
|
||||
parent()->SignalSelectedBlocks(selected_blocks);
|
||||
@@ -142,7 +144,7 @@ void PointerTool::MouseMove(TimelineViewMouseEvent *event)
|
||||
// If we clicked an item but are rubberband selecting anyway, deselect it now
|
||||
if (clicked_item_) {
|
||||
parent()->RemoveSelection(clicked_item_);
|
||||
parent()->SignalDeselectedBlocks({clicked_item_->block()});
|
||||
parent()->SignalDeselectedBlocks({clicked_item_});
|
||||
clicked_item_ = nullptr;
|
||||
}
|
||||
|
||||
@@ -244,13 +246,13 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
||||
bool slide_instead_of_moving)
|
||||
{
|
||||
// Get list of selected blocks
|
||||
QVector<TimelineViewBlockItem*> clips = parent()->GetSelectedBlocks();
|
||||
QVector<Block*> clips = parent()->GetSelectedBlocks();
|
||||
|
||||
if (trim_mode == Timeline::kMove) {
|
||||
|
||||
// Each block type has different behavior, so we determine the type of the block that was
|
||||
// clicked and filter out any others.
|
||||
Block::Type clicked_block_type = clicked_item->block()->type();
|
||||
Block::Type clicked_block_type = clicked_item->type();
|
||||
|
||||
// Gaps are not allowed to move, and since we only allow moving one block type at a time,
|
||||
// dragging a gap is a no-op
|
||||
@@ -269,43 +271,39 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
||||
// For slides to be legal, we make all blocks "contiguous". This means that only one series
|
||||
// of blocks can move at a time and prevents.
|
||||
|
||||
QHash<TrackReference, Block*> earliest_block_on_track;
|
||||
QHash<TrackReference, Block*> latest_block_on_track;
|
||||
QHash<Track*, Block*> earliest_block_on_track;
|
||||
QHash<Track*, Block*> latest_block_on_track;
|
||||
|
||||
foreach (TimelineViewBlockItem* item, clips) {
|
||||
Block* this_block = item->block();
|
||||
const TrackReference& track = item->Track();
|
||||
|
||||
Block* current_earliest = earliest_block_on_track.value(track, nullptr);
|
||||
foreach (Block* this_block, clips) {
|
||||
Block* current_earliest = earliest_block_on_track.value(this_block->track(), nullptr);
|
||||
if (!current_earliest || this_block->in() < current_earliest->in()) {
|
||||
earliest_block_on_track.insert(track, item->block());
|
||||
earliest_block_on_track.insert(this_block->track(), this_block);
|
||||
}
|
||||
|
||||
Block* current_latest = latest_block_on_track.value(track, nullptr);
|
||||
Block* current_latest = latest_block_on_track.value(this_block->track(), nullptr);
|
||||
if (!current_latest || this_block->out() > current_earliest->out()) {
|
||||
latest_block_on_track.insert(track, item->block());
|
||||
latest_block_on_track.insert(this_block->track(), this_block);
|
||||
}
|
||||
}
|
||||
|
||||
QHash<TrackReference, Block*>::const_iterator i;
|
||||
for (i=earliest_block_on_track.constBegin(); i!=earliest_block_on_track.constEnd(); i++) {
|
||||
for (auto i=earliest_block_on_track.constBegin(); i!=earliest_block_on_track.constEnd(); i++) {
|
||||
// Make a contiguous stream
|
||||
const TrackReference& track = i.key();
|
||||
Track* track = i.key();
|
||||
Block* earliest = i.value();
|
||||
Block* latest = latest_block_on_track.value(i.key());
|
||||
|
||||
// First we add the block that's out trimming, the one prior to the earliest
|
||||
TimelineViewGhostItem* earliest_ghost;
|
||||
if (earliest->previous()) {
|
||||
earliest_ghost = AddGhostFromBlock(earliest->previous(), track, Timeline::kTrimOut);
|
||||
earliest_ghost = AddGhostFromBlock(earliest->previous(), Timeline::kTrimOut);
|
||||
} else {
|
||||
earliest_ghost = AddGhostFromNull(earliest->in(), earliest->in(), track, Timeline::kTrimOut);
|
||||
earliest_ghost = AddGhostFromNull(earliest->in(), earliest->in(), track->ToReference(), Timeline::kTrimOut);
|
||||
}
|
||||
SetGhostToSlideMode(earliest_ghost);
|
||||
|
||||
// Then we add the block that's in trimming, the one after the latest
|
||||
if (latest->next()) {
|
||||
TimelineViewGhostItem* latest_ghost = AddGhostFromBlock(latest->next(), track, Timeline::kTrimIn);
|
||||
TimelineViewGhostItem* latest_ghost = AddGhostFromBlock(latest->next(), Timeline::kTrimIn);
|
||||
SetGhostToSlideMode(latest_ghost);
|
||||
}
|
||||
|
||||
@@ -320,15 +318,13 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
||||
b = earliest;
|
||||
}
|
||||
|
||||
TimelineViewGhostItem* between_ghost = AddGhostFromBlock(b, track, Timeline::kMove);
|
||||
TimelineViewGhostItem* between_ghost = AddGhostFromBlock(b, Timeline::kMove);
|
||||
SetGhostToSlideMode(between_ghost);
|
||||
} while (b != latest);
|
||||
}
|
||||
} else {
|
||||
// Prepare for a standard pointer move
|
||||
foreach (TimelineViewBlockItem* clip_item, clips) {
|
||||
Block* block = clip_item->block();
|
||||
|
||||
foreach (Block* block, clips) {
|
||||
if (block->type() == Block::kGap || block->type() == Block::kTransition) {
|
||||
// Gaps cannot move, and we handle transitions further down
|
||||
continue;
|
||||
@@ -336,24 +332,21 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
||||
|
||||
// Create ghost
|
||||
TimelineViewGhostItem* ghost = AddGhostFromBlock(block,
|
||||
clip_item->Track(),
|
||||
trim_mode);
|
||||
Q_UNUSED(ghost)
|
||||
|
||||
// Add transitions if this has any
|
||||
TransitionBlock* opening_transition = TransitionBlock::GetBlockInTransition(block);
|
||||
TransitionBlock* closing_transition = TransitionBlock::GetBlockOutTransition(block);
|
||||
TransitionBlock* opening_transition = block->in_transition();
|
||||
TransitionBlock* closing_transition = block->out_transition();
|
||||
|
||||
if (opening_transition) {
|
||||
TimelineViewGhostItem* ot_ghost = AddGhostFromBlock(opening_transition,
|
||||
clip_item->Track(),
|
||||
trim_mode);
|
||||
Q_UNUSED(ot_ghost)
|
||||
}
|
||||
|
||||
if (closing_transition) {
|
||||
TimelineViewGhostItem* cl_ghost = AddGhostFromBlock(closing_transition,
|
||||
clip_item->Track(),
|
||||
trim_mode);
|
||||
Q_UNUSED(cl_ghost)
|
||||
}
|
||||
@@ -368,7 +361,7 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
||||
bool multitrim_enabled = IsClipTrimmable(clicked_item, clips, trim_mode);
|
||||
|
||||
// Create ghosts for trimming
|
||||
foreach (TimelineViewBlockItem* clip_item, clips) {
|
||||
foreach (Block* clip_item, clips) {
|
||||
if (clip_item != clicked_item
|
||||
&& (!multitrim_enabled || !IsClipTrimmable(clip_item, clips, trim_mode))) {
|
||||
// Either multitrim is disabled or this clip is NOT the earliest/latest in its track. We
|
||||
@@ -376,10 +369,10 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
||||
continue;
|
||||
}
|
||||
|
||||
Block* block = clip_item->block();
|
||||
Block* block = clip_item;
|
||||
|
||||
// Create ghost for this block
|
||||
TimelineViewGhostItem* ghost = AddGhostFromBlock(block, clip_item->Track(), trim_mode);
|
||||
TimelineViewGhostItem* ghost = AddGhostFromBlock(block, trim_mode);
|
||||
|
||||
// If this side of the clip has a transition, we treat it more like a slide for that
|
||||
// transition than a trim/roll
|
||||
@@ -391,14 +384,14 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
||||
|
||||
// Get appropriate transition for the side of the clip
|
||||
if (trim_mode == Timeline::kTrimIn) {
|
||||
connected_transition = TransitionBlock::GetBlockInTransition(block);
|
||||
connected_transition = block->in_transition();
|
||||
} else {
|
||||
connected_transition = TransitionBlock::GetBlockOutTransition(block);
|
||||
connected_transition = block->out_transition();
|
||||
}
|
||||
|
||||
if (connected_transition) {
|
||||
// We found a transition, we'll make this a "slide" action
|
||||
TimelineViewGhostItem* transition_ghost = AddGhostFromBlock(connected_transition, clip_item->Track(), Timeline::kMove);
|
||||
TimelineViewGhostItem* transition_ghost = AddGhostFromBlock(connected_transition, Timeline::kMove);
|
||||
|
||||
// This will in effect be a slide with the transition moving between two other blocks
|
||||
SetGhostToSlideMode(ghost);
|
||||
@@ -435,11 +428,11 @@ void PointerTool::InitiateDragInternal(Block *clicked_item,
|
||||
TimelineViewGhostItem* adjacent_ghost;
|
||||
|
||||
if (adjacent) {
|
||||
adjacent_ghost = AddGhostFromBlock(adjacent, clip_item->Track(), flipped_mode);
|
||||
adjacent_ghost = AddGhostFromBlock(adjacent, flipped_mode);
|
||||
} else if (trim_mode == Timeline::kTrimIn || block->next()) {
|
||||
rational null_ghost_pos = (trim_mode == Timeline::kTrimIn) ? block->in() : block->out();
|
||||
|
||||
adjacent_ghost = AddGhostFromNull(null_ghost_pos, null_ghost_pos, clip_item->Track(), flipped_mode);
|
||||
adjacent_ghost = AddGhostFromNull(null_ghost_pos, null_ghost_pos, clip_item->track()->ToReference(), flipped_mode);
|
||||
} else {
|
||||
adjacent_ghost = nullptr;
|
||||
}
|
||||
@@ -650,7 +643,7 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
block = static_cast<Block*>(copy);
|
||||
}
|
||||
|
||||
const TrackReference& track_ref = p.ghost->GetAdjustedTrack();
|
||||
const Track::Reference& track_ref = p.ghost->GetAdjustedTrack();
|
||||
new TrackPlaceBlockCommand(parent()->GetConnectedNode()->track_list(track_ref.type()),
|
||||
track_ref.index(),
|
||||
block,
|
||||
@@ -669,13 +662,13 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
// Assume that the blocks are contiguous per track as set up in InitiateGhostsInternal()
|
||||
|
||||
// All we need to do is sort them by track and order them
|
||||
QHash<TrackReference, QList<Block*> > slide_info;
|
||||
QHash<TrackReference, Block*> in_adjacents;
|
||||
QHash<TrackReference, Block*> out_adjacents;
|
||||
QHash<Track::Reference, QList<Block*> > slide_info;
|
||||
QHash<Track::Reference, Block*> in_adjacents;
|
||||
QHash<Track::Reference, Block*> out_adjacents;
|
||||
rational movement;
|
||||
|
||||
foreach (const GhostBlockPair& p, blocks_sliding) {
|
||||
const TrackReference& track = p.ghost->GetTrack();
|
||||
const Track::Reference& track = p.ghost->GetTrack();
|
||||
|
||||
switch (p.ghost->GetMode()) {
|
||||
case Timeline::kNone:
|
||||
@@ -711,7 +704,7 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
}
|
||||
|
||||
if (!movement.isNull()) {
|
||||
QHash<TrackReference, QList<Block*> >::const_iterator i;
|
||||
QHash<Track::Reference, QList<Block*> >::const_iterator i;
|
||||
for (i=slide_info.constBegin(); i!=slide_info.constEnd(); i++) {
|
||||
new TrackSlideCommand(parent()->GetTrackFromReference(i.key()),
|
||||
i.value(),
|
||||
@@ -735,14 +728,18 @@ Timeline::MovementMode PointerTool::IsCursorInTrimHandle(Block *block, qreal cur
|
||||
{
|
||||
double kTrimHandle = QtUtils::QFontMetricsWidth(parent()->fontMetrics(), "H");
|
||||
|
||||
double block_left = parent()->TimeToScene(block->in());
|
||||
double block_right = parent()->TimeToScene(block->out());
|
||||
double block_width = block_right - block_left;
|
||||
|
||||
// Block is too narrow, no trimming allowed
|
||||
if (block->rect().width() <= kTrimHandle * 2) {
|
||||
if (block_width <= kTrimHandle * 2) {
|
||||
return Timeline::kNone;
|
||||
}
|
||||
|
||||
if (trimming_allowed_ && cursor_x <= block->x() + kTrimHandle) {
|
||||
if (trimming_allowed_ && cursor_x <= block_left + kTrimHandle) {
|
||||
return Timeline::kTrimIn;
|
||||
} else if (trimming_allowed_ && cursor_x >= block->x() + block->rect().right() - kTrimHandle) {
|
||||
} else if (trimming_allowed_ && cursor_x >= block_left + block_right - kTrimHandle) {
|
||||
return Timeline::kTrimOut;
|
||||
} else {
|
||||
return Timeline::kNone;
|
||||
@@ -757,7 +754,7 @@ void PointerTool::InitiateDrag(Block *clicked_item,
|
||||
|
||||
//#define HIDE_GAP_GHOSTS
|
||||
|
||||
TimelineViewGhostItem* PointerTool::AddGhostFromBlock(Block* block, const TrackReference& track, Timeline::MovementMode mode, bool check_if_exists)
|
||||
TimelineViewGhostItem* PointerTool::AddGhostFromBlock(Block* block, Timeline::MovementMode mode, bool check_if_exists)
|
||||
{
|
||||
if (check_if_exists) {
|
||||
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
|
||||
@@ -767,7 +764,7 @@ TimelineViewGhostItem* PointerTool::AddGhostFromBlock(Block* block, const TrackR
|
||||
}
|
||||
}
|
||||
|
||||
TimelineViewGhostItem* ghost = TimelineViewGhostItem::FromBlock(block, track);
|
||||
TimelineViewGhostItem* ghost = TimelineViewGhostItem::FromBlock(block);
|
||||
|
||||
#ifdef HIDE_GAP_GHOSTS
|
||||
if (block->type() == Block::kGap) {
|
||||
@@ -780,7 +777,7 @@ TimelineViewGhostItem* PointerTool::AddGhostFromBlock(Block* block, const TrackR
|
||||
return ghost;
|
||||
}
|
||||
|
||||
TimelineViewGhostItem* PointerTool::AddGhostFromNull(const rational &in, const rational &out, const TrackReference& track, Timeline::MovementMode mode)
|
||||
TimelineViewGhostItem* PointerTool::AddGhostFromNull(const rational &in, const rational &out, const Track::Reference& track, Timeline::MovementMode mode)
|
||||
{
|
||||
TimelineViewGhostItem* ghost = new TimelineViewGhostItem();
|
||||
|
||||
@@ -821,14 +818,14 @@ void PointerTool::AddGhostInternal(TimelineViewGhostItem* ghost, Timeline::Movem
|
||||
}
|
||||
|
||||
bool PointerTool::IsClipTrimmable(Block *clip,
|
||||
const QVector<TimelineViewBlockItem*>& items,
|
||||
const QVector<Block*>& items,
|
||||
const Timeline::MovementMode& mode)
|
||||
{
|
||||
foreach (TimelineViewBlockItem* compare, items) {
|
||||
if (clip->Track() == compare->Track()
|
||||
foreach (Block* compare, items) {
|
||||
if (clip->track() == compare->track()
|
||||
&& clip != compare
|
||||
&& ((compare->block()->in() < clip->block()->in() && mode == Timeline::kTrimIn)
|
||||
|| (compare->block()->out() > clip->block()->out() && mode == Timeline::kTrimOut))) {
|
||||
&& ((compare->in() < clip->in() && mode == Timeline::kTrimIn)
|
||||
|| (compare->out() > clip->out() && mode == Timeline::kTrimOut))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -837,7 +834,6 @@ bool PointerTool::IsClipTrimmable(Block *clip,
|
||||
}
|
||||
|
||||
bool PointerTool::AddMovingTransitionsToClipGhost(Block* block,
|
||||
const TrackReference& track,
|
||||
Timeline::MovementMode movement,
|
||||
const QVector<Block *> &selected_items)
|
||||
{
|
||||
@@ -845,13 +841,13 @@ bool PointerTool::AddMovingTransitionsToClipGhost(Block* block,
|
||||
TransitionBlock* transitions[2];
|
||||
|
||||
if (movement == Timeline::kMove || movement == Timeline::kTrimOut) {
|
||||
transitions[0] = TransitionBlock::GetBlockOutTransition(block);
|
||||
transitions[0] = block->out_transition();
|
||||
} else {
|
||||
transitions[0] = nullptr;
|
||||
}
|
||||
|
||||
if (movement == Timeline::kMove || movement == Timeline::kTrimIn) {
|
||||
transitions[1] = TransitionBlock::GetBlockInTransition(block);
|
||||
transitions[1] = block->in_transition();
|
||||
} else {
|
||||
transitions[1] = nullptr;
|
||||
}
|
||||
@@ -865,8 +861,8 @@ bool PointerTool::AddMovingTransitionsToClipGhost(Block* block,
|
||||
|
||||
bool found = false;
|
||||
|
||||
foreach (TimelineViewBlockItem* item, selected_items) {
|
||||
if (item->block() == transitions[i]) {
|
||||
foreach (Block* item, selected_items) {
|
||||
if (item == transitions[i]) {
|
||||
// Do nothing
|
||||
found = true;
|
||||
break;
|
||||
@@ -874,8 +870,7 @@ bool PointerTool::AddMovingTransitionsToClipGhost(Block* block,
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
TimelineViewGhostItem* transition_ghost = AddGhostFromBlock(transitions[i], track,
|
||||
Timeline::kMove);
|
||||
TimelineViewGhostItem* transition_ghost = AddGhostFromBlock(transitions[i], Timeline::kMove);
|
||||
|
||||
Q_UNUSED(transition_ghost)
|
||||
|
||||
|
||||
@@ -42,9 +42,9 @@ protected:
|
||||
virtual void InitiateDrag(Block* clicked_item,
|
||||
Timeline::MovementMode trim_mode);
|
||||
|
||||
TimelineViewGhostItem* AddGhostFromBlock(Block *block, const TrackReference& track, Timeline::MovementMode mode, bool check_if_exists = false);
|
||||
TimelineViewGhostItem* AddGhostFromBlock(Block *block, Timeline::MovementMode mode, bool check_if_exists = false);
|
||||
|
||||
TimelineViewGhostItem* AddGhostFromNull(const rational& in, const rational& out, const TrackReference& track, Timeline::MovementMode mode);
|
||||
TimelineViewGhostItem* AddGhostFromNull(const rational& in, const rational& out, const Track::Reference& track, Timeline::MovementMode mode);
|
||||
|
||||
/**
|
||||
* @brief Validates Ghosts that are getting their in points trimmed
|
||||
@@ -107,7 +107,7 @@ private:
|
||||
|
||||
void ProcessGhostsForRolling();
|
||||
|
||||
bool AddMovingTransitionsToClipGhost(Block *block, const TrackReference &track, Timeline::MovementMode movement, const QVector<Block*> &selected_items);
|
||||
bool AddMovingTransitionsToClipGhost(Block *block, Timeline::MovementMode movement, const QVector<Block*> &selected_items);
|
||||
|
||||
bool movement_allowed_;
|
||||
bool trimming_allowed_;
|
||||
|
||||
@@ -43,7 +43,7 @@ void RazorTool::MouseMove(TimelineViewMouseEvent *event)
|
||||
}
|
||||
|
||||
// Split at the current cursor track
|
||||
TrackReference split_track = event->GetTrack();
|
||||
Track::Reference split_track = event->GetTrack();
|
||||
|
||||
if (!split_tracks_.contains(split_track)) {
|
||||
split_tracks_.append(split_track);
|
||||
@@ -59,7 +59,7 @@ void RazorTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
|
||||
QVector<Block*> blocks_to_split;
|
||||
|
||||
foreach (const TrackReference& track_ref, split_tracks_) {
|
||||
foreach (const Track::Reference& track_ref, split_tracks_) {
|
||||
Track* track = parent()->GetTrackFromReference(track_ref);
|
||||
|
||||
if (track == nullptr || track->IsLocked()) {
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
QVector<TrackReference> split_tracks_;
|
||||
QVector<Track::Reference> split_tracks_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -82,20 +82,18 @@ void RippleTool::InitiateDrag(Block *clicked_item,
|
||||
if (block_before_ripple) {
|
||||
TimelineViewGhostItem* ghost;
|
||||
|
||||
TrackReference track_ref(track->track_type(), track->Index());
|
||||
|
||||
if (block_before_ripple->type() == Block::kGap) {
|
||||
// If this Block is already a Gap, ghost it now
|
||||
ghost = AddGhostFromBlock(block_before_ripple, track_ref, trim_mode);
|
||||
ghost = AddGhostFromBlock(block_before_ripple, trim_mode);
|
||||
} else if (block_before_ripple->next()) {
|
||||
// Assuming this block is NOT at the end of the track (i.e. next != null)
|
||||
|
||||
// We're going to create a gap after it. If next is a gap, we can just use that
|
||||
if (block_before_ripple->next()->type() == Block::kGap) {
|
||||
ghost = AddGhostFromBlock(block_before_ripple->next(), track_ref, trim_mode);
|
||||
ghost = AddGhostFromBlock(block_before_ripple->next(), trim_mode);
|
||||
} else {
|
||||
// If next is NOT a gap, we'll need to create one, for which we'll use a null ghost
|
||||
ghost = AddGhostFromNull(block_before_ripple->out(), block_before_ripple->out(), track_ref, trim_mode);
|
||||
ghost = AddGhostFromNull(block_before_ripple->out(), block_before_ripple->out(), track->ToReference(), trim_mode);
|
||||
ghost->SetData(TimelineViewGhostItem::kReferenceBlock, Node::PtrToValue(block_before_ripple));
|
||||
}
|
||||
}
|
||||
@@ -120,7 +118,7 @@ void RippleTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
ghost->GetAdjustedLength(),
|
||||
ghost->GetLength()};
|
||||
|
||||
info_list[track->track_type()].append(i);
|
||||
info_list[track->type()].append(i);
|
||||
}
|
||||
|
||||
QUndoCommand* command = new QUndoCommand();
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "widget/timelinewidget/timelinewidget.h"
|
||||
|
||||
#include "node/block/transition/transition.h"
|
||||
#include "widget/nodeview/nodeviewundo.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include <QDragLeaveEvent>
|
||||
|
||||
#include "common/rational.h"
|
||||
#include "widget/nodeview/nodeviewundo.h"
|
||||
#include "widget/timelinewidget/timelineundo.h"
|
||||
#include "widget/timelinewidget/view/timelineviewghostitem.h"
|
||||
#include "widget/timelinewidget/view/timelineviewmouseevent.h"
|
||||
|
||||
@@ -75,7 +77,7 @@ protected:
|
||||
|
||||
void InsertGapsAtGhostDestination(QUndoCommand* command);
|
||||
|
||||
QList<rational> snap_points_;
|
||||
QVector<rational> snap_points_;
|
||||
|
||||
bool dragging_;
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "node/factory.h"
|
||||
#include "transition.h"
|
||||
#include "widget/nodeview/nodeviewundo.h"
|
||||
#include "widget/timelinewidget/timelineundo.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -35,7 +36,7 @@ TransitionTool::TransitionTool(TimelineWidget *parent) :
|
||||
|
||||
void TransitionTool::MousePress(TimelineViewMouseEvent *event)
|
||||
{
|
||||
const TrackReference& track = event->GetTrack();
|
||||
const Track::Reference& track = event->GetTrack();
|
||||
Track* t = parent()->GetTrackFromReference(track);
|
||||
rational cursor_frame = event->GetFrame();
|
||||
|
||||
@@ -106,7 +107,7 @@ void TransitionTool::MouseMove(TimelineViewMouseEvent *event)
|
||||
|
||||
void TransitionTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
{
|
||||
const TrackReference& track = ghost_->GetTrack();
|
||||
const Track::Reference& track = ghost_->GetTrack();
|
||||
|
||||
if (ghost_) {
|
||||
if (!ghost_->GetAdjustedLength().isNull()) {
|
||||
|
||||
@@ -72,7 +72,6 @@ void TrackView::ConnectTrackList(TrackList *list)
|
||||
RemoveTrack(track);
|
||||
}
|
||||
|
||||
disconnect(list_, &TrackList::TrackHeightChanged, splitter_, &TrackViewSplitter::SetTrackHeight);
|
||||
disconnect(list_, &TrackList::TrackAdded, this, &TrackView::InsertTrack);
|
||||
disconnect(list_, &TrackList::TrackRemoved, this, &TrackView::RemoveTrack);
|
||||
}
|
||||
@@ -84,7 +83,6 @@ void TrackView::ConnectTrackList(TrackList *list)
|
||||
InsertTrack(track);
|
||||
}
|
||||
|
||||
connect(list_, &TrackList::TrackHeightChanged, splitter_, &TrackViewSplitter::SetTrackHeight);
|
||||
connect(list_, &TrackList::TrackAdded, this, &TrackView::InsertTrack);
|
||||
connect(list_, &TrackList::TrackRemoved, this, &TrackView::RemoveTrack);
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ void TrackViewItem::LineEditCancelled()
|
||||
void TrackViewItem::UpdateLabel()
|
||||
{
|
||||
if (track_->GetLabel().isEmpty()) {
|
||||
label_->setText(track_->GetDefaultTrackName(track_->track_type(), track_->Index()));
|
||||
label_->setText(track_->GetDefaultTrackName(track_->type(), track_->Index()));
|
||||
} else {
|
||||
label_->setText(track_->GetLabel());
|
||||
}
|
||||
|
||||
@@ -229,6 +229,13 @@ void TimelineView::drawBackground(QPainter *painter, const QRectF &rect)
|
||||
|
||||
void TimelineView::drawForeground(QPainter *painter, const QRectF &rect)
|
||||
{
|
||||
if (!connected_track_list_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw block backgrounds
|
||||
DrawBlocks(painter, false);
|
||||
|
||||
// Draw selections
|
||||
if (selections_ && !selections_->isEmpty()) {
|
||||
painter->setPen(Qt::NoPen);
|
||||
@@ -248,6 +255,9 @@ void TimelineView::drawForeground(QPainter *painter, const QRectF &rect)
|
||||
}
|
||||
}
|
||||
|
||||
// Draw block foregrounds
|
||||
DrawBlocks(painter, true);
|
||||
|
||||
// Draw ghosts
|
||||
if (ghosts_ && !ghosts_->isEmpty()) {
|
||||
painter->setPen(QPen(Qt::yellow, 2));
|
||||
@@ -268,7 +278,6 @@ void TimelineView::drawForeground(QPainter *painter, const QRectF &rect)
|
||||
|
||||
// Draw beam cursor
|
||||
if (show_beam_cursor_
|
||||
&& connected_track_list_
|
||||
&& cursor_coord_.GetTrack().type() == connected_track_list_->type()) {
|
||||
painter->setPen(Qt::gray);
|
||||
|
||||
@@ -328,20 +337,20 @@ Track::Type TimelineView::ConnectedTrackType()
|
||||
return connected_track_list_->type();
|
||||
}
|
||||
|
||||
return Timeline::kTrackTypeNone;
|
||||
return Track::kNone;
|
||||
}
|
||||
|
||||
Stream::Type TimelineView::TrackTypeToStreamType(Track::Type track_type)
|
||||
{
|
||||
switch (track_type) {
|
||||
case Timeline::kTrackTypeNone:
|
||||
case Timeline::kTrackTypeCount:
|
||||
case Track::kNone:
|
||||
case Track::kCount:
|
||||
break;
|
||||
case Timeline::kTrackTypeVideo:
|
||||
case Track::kVideo:
|
||||
return Stream::kVideo;
|
||||
case Timeline::kTrackTypeAudio:
|
||||
case Track::kAudio:
|
||||
return Stream::kAudio;
|
||||
case Timeline::kTrackTypeSubtitle:
|
||||
case Track::kSubtitle:
|
||||
return Stream::kSubtitle;
|
||||
}
|
||||
|
||||
@@ -355,7 +364,7 @@ TimelineCoordinate TimelineView::ScreenToCoordinate(const QPoint& pt)
|
||||
|
||||
TimelineCoordinate TimelineView::SceneToCoordinate(const QPointF& pt)
|
||||
{
|
||||
return TimelineCoordinate(SceneToTime(pt.x()), TrackReference(ConnectedTrackType(), SceneToTrack(pt.y())));
|
||||
return TimelineCoordinate(SceneToTime(pt.x()), Track::Reference(ConnectedTrackType(), SceneToTrack(pt.y())));
|
||||
}
|
||||
|
||||
TimelineViewMouseEvent TimelineView::CreateMouseEvent(QMouseEvent *event)
|
||||
@@ -370,11 +379,53 @@ TimelineViewMouseEvent TimelineView::CreateMouseEvent(const QPoint& pos, Qt::Mou
|
||||
return TimelineViewMouseEvent(scene_pt.x(),
|
||||
GetScale(),
|
||||
timebase(),
|
||||
TrackReference(ConnectedTrackType(), SceneToTrack(scene_pt.y())),
|
||||
Track::Reference(ConnectedTrackType(), SceneToTrack(scene_pt.y())),
|
||||
button,
|
||||
modifiers);
|
||||
}
|
||||
|
||||
void TimelineView::DrawBlocks(QPainter *painter, bool foreground)
|
||||
{
|
||||
rational start_time = SceneToTime(0);
|
||||
rational end_time = SceneToTime(viewport()->width());
|
||||
|
||||
foreach (Track* track, connected_track_list_->GetTracks()) {
|
||||
// Get first visible block in this track
|
||||
Block* block = track->NearestBlockBeforeOrAt(start_time);
|
||||
|
||||
while (block) {
|
||||
if (block->type() == Block::kClip) {
|
||||
|
||||
qreal block_left = qMax(0.0, TimeToScene(block->in()));
|
||||
qreal block_right = qMin(qreal(viewport()->width()), TimeToScene(block->out()));
|
||||
|
||||
QRectF r(block_left,
|
||||
GetTrackY(track->Index()),
|
||||
block_right - block_left,
|
||||
GetTrackHeight(track->Index()));
|
||||
|
||||
if (foreground) {
|
||||
painter->setPen(Qt::white);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawText(r, block->GetLabel());
|
||||
} else {
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(QColor(128, 128, 192));
|
||||
painter->drawRect(r);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (block->out() >= end_time) {
|
||||
// Rest of the clips are offscreen, can break loop now
|
||||
break;
|
||||
}
|
||||
|
||||
block = block->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int TimelineView::GetHeightOfAllTracks() const
|
||||
{
|
||||
if (connected_track_list_) {
|
||||
@@ -436,15 +487,7 @@ void TimelineView::SetScrollCoordinates(const QPoint &pt)
|
||||
|
||||
void TimelineView::ConnectTrackList(TrackList *list)
|
||||
{
|
||||
if (connected_track_list_) {
|
||||
disconnect(connected_track_list_, SIGNAL(TrackHeightChanged(int, int)), viewport(), SLOT(update()));
|
||||
}
|
||||
|
||||
connected_track_list_ = list;
|
||||
|
||||
if (connected_track_list_) {
|
||||
connect(connected_track_list_, SIGNAL(TrackHeightChanged(int, int)), viewport(), SLOT(update()));
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineView::SetBeamCursor(const TimelineCoordinate &coord)
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
|
||||
void SetBeamCursor(const TimelineCoordinate& coord);
|
||||
|
||||
void SetSelectionList(QHash<TrackReference, TimeRangeList>* s)
|
||||
void SetSelectionList(QHash<Track::Reference, TimeRangeList>* s)
|
||||
{
|
||||
selections_ = s;
|
||||
}
|
||||
@@ -66,6 +66,8 @@ public:
|
||||
ghosts_ = ghosts;
|
||||
}
|
||||
|
||||
int SceneToTrack(double y);
|
||||
|
||||
signals:
|
||||
void MousePressed(TimelineViewMouseEvent* event);
|
||||
void MouseMoved(TimelineViewMouseEvent* event);
|
||||
@@ -107,15 +109,15 @@ private:
|
||||
TimelineViewMouseEvent CreateMouseEvent(QMouseEvent* event);
|
||||
TimelineViewMouseEvent CreateMouseEvent(const QPoint &pos, Qt::MouseButton button, Qt::KeyboardModifiers modifiers);
|
||||
|
||||
int GetHeightOfAllTracks() const;
|
||||
void DrawBlocks(QPainter* painter, bool foreground);
|
||||
|
||||
int SceneToTrack(double y);
|
||||
int GetHeightOfAllTracks() const;
|
||||
|
||||
void UserSetTime(const int64_t& time);
|
||||
|
||||
void UpdatePlayheadRect();
|
||||
|
||||
QHash<TrackReference, TimeRangeList>* selections_;
|
||||
QHash<Track::Reference, TimeRangeList>* selections_;
|
||||
|
||||
QVector<TimelineViewGhostItem*>* ghosts_;
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
#include "project/item/footage/footage.h"
|
||||
#include "timeline/timelinecommon.h"
|
||||
#include "timeline/trackreference.h"
|
||||
|
||||
namespace olive {
|
||||
/**
|
||||
@@ -52,14 +51,14 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
static TimelineViewGhostItem* FromBlock(Block *block, const TrackReference &track)
|
||||
static TimelineViewGhostItem* FromBlock(Block *block)
|
||||
{
|
||||
TimelineViewGhostItem* ghost = new TimelineViewGhostItem();
|
||||
|
||||
ghost->SetIn(block->in());
|
||||
ghost->SetOut(block->out());
|
||||
ghost->SetMediaIn(block->media_in());
|
||||
ghost->SetTrack(track);
|
||||
ghost->SetTrack(block->track()->ToReference());
|
||||
ghost->SetData(kAttachedBlock, Node::PtrToValue(block));
|
||||
|
||||
switch (block->type()) {
|
||||
@@ -187,9 +186,9 @@ public:
|
||||
return media_in_ + media_in_adj_;
|
||||
}
|
||||
|
||||
TrackReference GetAdjustedTrack() const
|
||||
Track::Reference GetAdjustedTrack() const
|
||||
{
|
||||
return TrackReference(track_.type(), track_.index() + track_adj_);
|
||||
return Track::Reference(track_.type(), track_.index() + track_adj_);
|
||||
}
|
||||
|
||||
const Timeline::MovementMode& GetMode() const
|
||||
@@ -220,12 +219,12 @@ public:
|
||||
data_.insert(key, value);
|
||||
}
|
||||
|
||||
const TrackReference& GetTrack() const
|
||||
const Track::Reference& GetTrack() const
|
||||
{
|
||||
return track_;
|
||||
}
|
||||
|
||||
void SetTrack(const TrackReference& track)
|
||||
void SetTrack(const Track::Reference& track)
|
||||
{
|
||||
track_ = track;
|
||||
}
|
||||
@@ -258,7 +257,7 @@ private:
|
||||
bool can_have_zero_length_;
|
||||
bool can_move_tracks_;
|
||||
|
||||
TrackReference track_;
|
||||
Track::Reference track_;
|
||||
|
||||
QHash<int, QVariant> data_;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
TimelineViewMouseEvent(const qreal& scene_x,
|
||||
const double& scale_x,
|
||||
const rational& timebase,
|
||||
const TrackReference &track,
|
||||
const Track::Reference &track,
|
||||
const Qt::MouseButton &button,
|
||||
const Qt::KeyboardModifiers& modifiers = Qt::NoModifier) :
|
||||
scene_x_(scene_x),
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
return TimeScaledObject::SceneToTime(scene_x_, scale_x_, timebase_, round);
|
||||
}
|
||||
|
||||
const TrackReference& GetTrack() const
|
||||
const Track::Reference& GetTrack() const
|
||||
{
|
||||
return track_;
|
||||
}
|
||||
@@ -121,7 +121,7 @@ private:
|
||||
double scale_x_;
|
||||
rational timebase_;
|
||||
|
||||
TrackReference track_;
|
||||
Track::Reference track_;
|
||||
|
||||
Qt::MouseButton button_;
|
||||
|
||||
|
||||
@@ -341,7 +341,7 @@ void MainWindow::ProjectClose(Project *p)
|
||||
|
||||
// Close any open footage in footage viewer
|
||||
QVector<Item*> footage = p->get_items_of_type(Item::kFootage);
|
||||
QList<Footage*> footage_in_viewer = footage_viewer_panel_->GetSelectedFootage();
|
||||
QVector<Footage*> footage_in_viewer = footage_viewer_panel_->GetSelectedFootage();
|
||||
|
||||
if (!footage_in_viewer.isEmpty()) {
|
||||
// FootageViewer only has the one footage item
|
||||
|
||||
Reference in New Issue
Block a user