began some rewrites to timeline drawing

This commit is contained in:
itsmattkc
2021-01-14 10:30:20 +11:00
parent fbdda3d6d4
commit f7883bd02c
60 changed files with 3134 additions and 951 deletions
+4 -71
View File
@@ -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
View File
@@ -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_;
+24 -31
View File
@@ -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)
-4
View File
@@ -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;
+73 -61
View File
@@ -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);
}
}
+66 -5
View File
@@ -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
+2 -43
View File
@@ -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);
}
}
+19 -28
View File
@@ -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);
};
}
+1 -21
View File
@@ -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);
}
}
+2 -14
View File
@@ -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);
};
}
+3 -3
View File
@@ -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;
+2 -2
View File
@@ -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) {
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -29,7 +29,7 @@ namespace olive {
class FootageManagementPanel {
public:
virtual QList<Footage*> GetSelectedFootage() const = 0;
virtual QVector<Footage*> GetSelectedFootage() const = 0;
};
}
+4 -4
View File
@@ -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) {
+2 -2
View File
@@ -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;
+2 -2
View File
@@ -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);
}
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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;
+41 -37
View File
@@ -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);
+15 -19
View File
@@ -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();
+1 -1
View File
@@ -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>();
-2
View File
@@ -25,7 +25,5 @@ set(OLIVE_SOURCES
timeline/timelinepoints.cpp
timeline/timelineworkarea.h
timeline/timelineworkarea.cpp
timeline/trackreference.h
timeline/trackreference.cpp
PARENT_SCOPE
)
+3 -3
View File
@@ -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;
}
+5 -5
View File
@@ -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_;
};
-65
View File
@@ -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);
}
}
-57
View File
@@ -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;
+2 -2
View File
@@ -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);
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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;
+2 -2
View File
@@ -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_;
+1
View File
@@ -28,6 +28,7 @@
#include "config/config.h"
#include "core.h"
#include "project/item/sequence/sequence.h"
#include "widget/timelinewidget/timelineundo.h"
namespace olive {
+4 -3
View File
@@ -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
+725
View File
@@ -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
+158 -244
View File
@@ -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> &times)
void TimelineWidget::ShowSnap(const QVector<rational> &times)
{
foreach (TimelineAndTrackView* tview, views_) {
tview->view()->EnableSnap(times);
@@ -1366,7 +1266,7 @@ void TimelineWidget::ShowSnap(const QList<rational> &times)
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);
+17 -37
View File
@@ -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;
+3 -5
View File
@@ -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()) {
+1 -1
View File
@@ -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);
}
}
+8 -22
View File
@@ -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));
+5 -5
View File
@@ -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_;
+64 -69
View File
@@ -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)
+3 -3
View File
@@ -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_;
+2 -2
View File
@@ -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()) {
+1 -1
View File
@@ -35,7 +35,7 @@ public:
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
private:
QVector<TrackReference> split_tracks_;
QVector<Track::Reference> split_tracks_;
};
}
+4 -6
View File
@@ -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();
-1
View File
@@ -21,7 +21,6 @@
#include "widget/timelinewidget/timelinewidget.h"
#include "node/block/transition/transition.h"
#include "widget/nodeview/nodeviewundo.h"
namespace olive {
+3 -1
View File
@@ -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());
}
+60 -17
View File
@@ -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_;
+1 -1
View File
@@ -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