diff --git a/app/node/output/timeline/CMakeLists.txt b/app/node/output/timeline/CMakeLists.txt index 6b7989f64..c37d1a788 100644 --- a/app/node/output/timeline/CMakeLists.txt +++ b/app/node/output/timeline/CMakeLists.txt @@ -20,6 +20,5 @@ set(OLIVE_SOURCES node/output/timeline/timeline.cpp node/output/timeline/tracklist.h node/output/timeline/tracklist.cpp - node/output/timeline/tracktypes.h PARENT_SCOPE ) diff --git a/app/node/output/timeline/timeline.cpp b/app/node/output/timeline/timeline.cpp index 7f0933ac0..eebae2ec1 100644 --- a/app/node/output/timeline/timeline.cpp +++ b/app/node/output/timeline/timeline.cpp @@ -45,6 +45,8 @@ TimelineOutput::TimelineOutput() connect(list, SIGNAL(LengthChanged(const rational &)), this, SLOT(UpdateLength(const rational &))); connect(list, SIGNAL(BlockAdded(Block*, int)), this, SLOT(TrackListAddedBlock(Block*, int))); connect(list, SIGNAL(BlockRemoved(Block*)), this, SIGNAL(BlockRemoved(Block*))); + connect(list, SIGNAL(TrackAdded(TrackOutput*)), this, SLOT(TrackListAddedTrack(TrackOutput*))); + connect(list, SIGNAL(TrackRemoved(TrackOutput*)), this, SIGNAL(TrackRemoved(TrackOutput*))); } length_output_ = new NodeOutput("length_out"); @@ -87,6 +89,11 @@ const rational &TimelineOutput::timeline_length() return length_; } +const rational &TimelineOutput::Timebase() +{ + return timebase_; +} + QVariant TimelineOutput::Value(NodeOutput *output, const rational &time) { if (output == length_output_) { @@ -136,9 +143,9 @@ void TimelineOutput::UpdateLength(const rational &length) void TimelineOutput::SetTimebase(const rational &timebase) { - foreach (TrackList* list, track_lists_) { - list->SetTimebase(timebase); - } + timebase_ = timebase; + + emit TimebaseChanged(timebase_); } NodeInput *TimelineOutput::track_input(TrackType type) @@ -156,3 +163,9 @@ void TimelineOutput::TrackListAddedBlock(Block *block, int index) TrackType type = static_cast(sender())->TrackType(); emit BlockAdded(block, TrackReference(type, index)); } + +void TimelineOutput::TrackListAddedTrack(TrackOutput *track) +{ + TrackType type = static_cast(sender())->TrackType(); + emit TrackAdded(track, type); +} diff --git a/app/node/output/timeline/timeline.h b/app/node/output/timeline/timeline.h index 84ed3317b..d4c385939 100644 --- a/app/node/output/timeline/timeline.h +++ b/app/node/output/timeline/timeline.h @@ -25,8 +25,8 @@ #include "node/block/block.h" #include "node/output/track/track.h" #include "timeline/trackreference.h" +#include "timeline/tracktypes.h" #include "tracklist.h" -#include "tracktypes.h" /** * @brief Node that represents the end of the Timeline as well as a time traversal Node @@ -52,15 +52,20 @@ public: const rational& timeline_length(); + const rational& Timebase(); + void SetTimebase(const rational &timebase); signals: void LengthChanged(const rational& length); + void TimebaseChanged(const rational &timebase); void BlockAdded(Block* block, TrackReference track); - void BlockRemoved(Block* block); + void TrackAdded(TrackOutput* track, TrackType type); + void TrackRemoved(TrackOutput* track); + protected: virtual QVariant Value(NodeOutput* output, const rational& time) override; @@ -75,6 +80,8 @@ private: rational length_; + rational timebase_; + private slots: void UpdateTrackCache(); @@ -82,6 +89,8 @@ private slots: void TrackListAddedBlock(Block* block, int index); + void TrackListAddedTrack(TrackOutput* track); + }; #endif // TIMELINEOUTPUT_H diff --git a/app/node/output/timeline/tracklist.cpp b/app/node/output/timeline/tracklist.cpp index e373d9a6b..4c2c4c6b1 100644 --- a/app/node/output/timeline/tracklist.cpp +++ b/app/node/output/timeline/tracklist.cpp @@ -50,6 +50,7 @@ void TrackList::AttachTrack(TrackOutput *track) connect(current_track, SIGNAL(Refreshed()), this, SLOT(UpdateTotalLength())); current_track->SetIndex(track_cache_.size()); + current_track->set_track_type(type_); track_cache_.append(current_track); emit TrackListChanged(); @@ -73,6 +74,7 @@ void TrackList::DetachTrack(TrackOutput *track) emit TrackRemoved(current_track); current_track->SetIndex(-1); + current_track->set_track_type(kTrackTypeNone); disconnect(current_track, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SLOT(TrackEdgeAdded(NodeEdgePtr))); disconnect(current_track, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SLOT(TrackEdgeRemoved(NodeEdgePtr))); @@ -109,18 +111,6 @@ TrackOutput *TrackList::TrackAt(int index) return track_cache_.at(index); } -const rational &TrackList::Timebase() -{ - return timebase_; -} - -void TrackList::SetTimebase(const rational &timebase) -{ - timebase_ = timebase; - - emit TimebaseChanged(timebase_); -} - const rational &TrackList::TrackLength() { return total_length_; @@ -178,9 +168,6 @@ void TrackList::TrackConnectionAdded(NodeEdgePtr edge) } AttachTrack(attached_track()); - - // FIXME: Is this necessary? - emit TimebaseChanged(timebase_); } void TrackList::TrackConnectionRemoved(NodeEdgePtr edge) @@ -190,8 +177,6 @@ void TrackList::TrackConnectionRemoved(NodeEdgePtr edge) } DetachTrack(Node::ValueToPtr(edge->output()->get_value(0))); - - emit TimelineCleared(); } void TrackList::TrackEdgeAdded(NodeEdgePtr edge) diff --git a/app/node/output/timeline/tracklist.h b/app/node/output/timeline/tracklist.h index 7b0858d13..ee0d20de6 100644 --- a/app/node/output/timeline/tracklist.h +++ b/app/node/output/timeline/tracklist.h @@ -25,7 +25,7 @@ #include "node/graph.h" #include "node/output/track/track.h" -#include "tracktypes.h" +#include "timeline/tracktypes.h" class TimelineOutput; @@ -48,10 +48,6 @@ public: void RemoveTrack(); - const rational& Timebase(); - - void SetTimebase(const rational& timebase); - const rational& TrackLength(); const enum TrackType& TrackType(); @@ -97,10 +93,6 @@ signals: void TrackListChanged(); - void TimelineCleared(); - - void TimebaseChanged(const rational &timebase); - void LengthChanged(const rational &length); private: @@ -111,8 +103,6 @@ private: */ QVector track_cache_; - rational timebase_; - NodeInput* track_input_; rational total_length_; diff --git a/app/node/output/track/track.cpp b/app/node/output/track/track.cpp index 15f8cc6b7..53ee736cd 100644 --- a/app/node/output/track/track.cpp +++ b/app/node/output/track/track.cpp @@ -27,6 +27,7 @@ TrackOutput::TrackOutput() : current_block_(this), + track_type_(kTrackTypeNone), block_invalidate_cache_stack_(0), index_(-1) { @@ -40,6 +41,16 @@ TrackOutput::TrackOutput() : AddParameter(track_output_); } +void TrackOutput::set_track_type(const TrackType &track_type) +{ + track_type_ = track_type; +} + +const TrackType& TrackOutput::track_type() +{ + return track_type_; +} + Block::Type TrackOutput::type() { return kEnd; diff --git a/app/node/output/track/track.h b/app/node/output/track/track.h index 53fe21bf9..e899032ec 100644 --- a/app/node/output/track/track.h +++ b/app/node/output/track/track.h @@ -22,6 +22,7 @@ #define TRACKOUTPUT_H #include "node/block/block.h" +#include "timeline/tracktypes.h" /** * @brief A time traversal Node for sorting through one channel/track of Blocks @@ -32,6 +33,9 @@ class TrackOutput : public Block public: TrackOutput(); + const TrackType& track_type(); + void set_track_type(const TrackType& track_type); + virtual Type type() override; virtual Block* copy() override; @@ -170,6 +174,8 @@ private: NodeOutput* track_output_; + TrackType track_type_; + int block_invalidate_cache_stack_; int index_; diff --git a/app/timeline/CMakeLists.txt b/app/timeline/CMakeLists.txt index c0bd69c9f..a05475736 100644 --- a/app/timeline/CMakeLists.txt +++ b/app/timeline/CMakeLists.txt @@ -20,5 +20,6 @@ set(OLIVE_SOURCES timeline/timelinecoordinate.cpp timeline/trackreference.h timeline/trackreference.cpp + timeline/tracktypes.h PARENT_SCOPE ) diff --git a/app/timeline/trackreference.h b/app/timeline/trackreference.h index 675c7fb51..cf18dfa4d 100644 --- a/app/timeline/trackreference.h +++ b/app/timeline/trackreference.h @@ -21,7 +21,7 @@ #ifndef TRACKREFERENCE_H #define TRACKREFERENCE_H -#include "node/output/timeline/tracktypes.h" +#include "timeline/tracktypes.h" class TrackReference { diff --git a/app/node/output/timeline/tracktypes.h b/app/timeline/tracktypes.h similarity index 100% rename from app/node/output/timeline/tracktypes.h rename to app/timeline/tracktypes.h diff --git a/app/widget/timelineview/timelineview.cpp b/app/widget/timelineview/timelineview.cpp index 4deecdc2e..a11103419 100644 --- a/app/widget/timelineview/timelineview.cpp +++ b/app/widget/timelineview/timelineview.cpp @@ -33,11 +33,10 @@ #include "node/input/media/media.h" #include "project/item/footage/footage.h" -TimelineView::TimelineView(Qt::Alignment vertical_alignment, QWidget *parent) : +TimelineView::TimelineView(const TrackType &type, Qt::Alignment vertical_alignment, QWidget *parent) : QGraphicsView(parent), - timeline_node_(nullptr), playhead_(0), - use_tracklist_length_directly_(true) + type_(type) { Q_ASSERT(vertical_alignment == Qt::AlignTop || vertical_alignment == Qt::AlignBottom); setAlignment(Qt::AlignLeft | vertical_alignment); @@ -57,20 +56,6 @@ TimelineView::TimelineView(Qt::Alignment vertical_alignment, QWidget *parent) : SetScale(1.0); } -void TimelineView::AddTrack(TrackOutput *track) -{ - foreach (Block* b, track->Blocks()) { - AddBlock(b, track->Index()); - } -} - -void TimelineView::RemoveTrack(TrackOutput *track) -{ - foreach (Block* b, track->Blocks()) { - RemoveBlock(b); - } -} - void TimelineView::SetScale(const double &scale) { scale_ = scale; @@ -89,44 +74,6 @@ void TimelineView::SetTimebase(const rational &timebase) viewport()->update(); } -void TimelineView::ConnectTimelineNode(TrackList *node) -{ - if (timeline_node_ != nullptr) { - disconnect(timeline_node_, SIGNAL(TimebaseChanged(const rational&)), this, SIGNAL(TimebaseChanged(const rational&))); - disconnect(timeline_node_, SIGNAL(TimebaseChanged(const rational&)), this, SLOT(SetTimebase(const rational&))); - disconnect(timeline_node_, SIGNAL(TimelineCleared()), this, SLOT(Clear())); - disconnect(timeline_node_, SIGNAL(TrackAdded(TrackOutput*)), this, SLOT(AddTrack(TrackOutput*))); - disconnect(timeline_node_, SIGNAL(TrackRemoved(TrackOutput*)), this, SLOT(RemoveTrack(TrackOutput*))); - disconnect(timeline_node_, SIGNAL(LengthChanged(const rational&)), this, SLOT(UpdateEndTimeFromTrackList(const rational&))); - - Clear(); - } - - timeline_node_ = node; - - if (timeline_node_ != nullptr) { - SetTimebase(timeline_node_->Timebase()); - emit TimebaseChanged(timeline_node_->Timebase()); - - connect(timeline_node_, SIGNAL(TimebaseChanged(const rational&)), this, SIGNAL(TimebaseChanged(const rational&))); - connect(timeline_node_, SIGNAL(TimebaseChanged(const rational&)), this, SLOT(SetTimebase(const rational&))); - connect(timeline_node_, SIGNAL(TimelineCleared()), this, SLOT(Clear())); - connect(timeline_node_, SIGNAL(TrackAdded(TrackOutput*)), this, SLOT(AddTrack(TrackOutput*))); - connect(timeline_node_, SIGNAL(TrackRemoved(TrackOutput*)), this, SLOT(RemoveTrack(TrackOutput*))); - connect(timeline_node_, SIGNAL(LengthChanged(const rational&)), this, SLOT(UpdateEndTimeFromTrackList(const rational&))); - - foreach (TrackOutput* track, timeline_node_->Tracks()) { - // Defer to the track to make all the block UI items necessary - AddTrack(track); - } - } -} - -void TimelineView::DisconnectTimelineNode() -{ - ConnectTimelineNode(nullptr); -} - void TimelineView::SelectAll() { QList all_items = items(); @@ -145,11 +92,6 @@ void TimelineView::DeselectAll() } } -void TimelineView::SetUseTrackListLengthDirectly(bool use) -{ - use_tracklist_length_directly_ = use; -} - void TimelineView::SetTime(const int64_t time) { playhead_ = time; @@ -257,15 +199,6 @@ void TimelineView::drawForeground(QPainter *painter, const QRectF &rect) } } -TrackType TimelineView::ConnectedTrackType() -{ - if (timeline_node_ != nullptr) { - return timeline_node_->TrackType(); - } - - return kTrackTypeNone; -} - Stream::Type TimelineView::TrackTypeToStreamType(TrackType track_type) { switch (track_type) { @@ -290,7 +223,7 @@ TimelineCoordinate TimelineView::ScreenToCoordinate(const QPoint& pt) TimelineCoordinate TimelineView::SceneToCoordinate(const QPointF& pt) { - return TimelineCoordinate(SceneToTime(pt.x()), SceneToTrack(pt.y())); + return TimelineCoordinate(SceneToTime(pt.x()), TrackReference(type_, SceneToTrack(pt.y()))); } int TimelineView::GetTrackY(int track_index) @@ -316,13 +249,6 @@ int TimelineView::GetTrackHeight(int track_index) return fontMetrics().height() * 3; } -void TimelineView::AddGhost(TimelineViewGhostItem *ghost) -{ - ghost->SetScale(scale_); - ghost_items_.append(ghost); - scene_.addItem(ghost); -} - int TimelineView::SceneToTrack(double y) { int track = -1; @@ -351,15 +277,6 @@ rational TimelineView::GetPlayheadTime() return rational(playhead_ * timebase().numerator(), timebase().denominator()); } -void TimelineView::BlockChanged() -{ - TimelineViewRect* rect = block_items_[static_cast(sender())]; - - if (rect != nullptr) { - rect->UpdateRect(); - } -} - void TimelineView::UpdateSceneRect() { QRectF bounding_rect = scene_.itemsBoundingRect(); @@ -395,13 +312,6 @@ void TimelineView::UpdateSceneRect() scene_.setSceneRect(bounding_rect); } -void TimelineView::UpdateEndTimeFromTrackList(const rational &length) -{ - if (use_tracklist_length_directly_) { - SetEndTime(length); - } -} - void TimelineView::SetEndTime(const rational &length) { end_item_->SetEndTime(length); diff --git a/app/widget/timelineview/timelineview.h b/app/widget/timelineview/timelineview.h index 6e4850223..6e69f7b3c 100644 --- a/app/widget/timelineview/timelineview.h +++ b/app/widget/timelineview/timelineview.h @@ -46,20 +46,16 @@ class TimelineView : public QGraphicsView, public TimelineScaledObject { Q_OBJECT public: - TimelineView(Qt::Alignment vertical_alignment = Qt::AlignTop, QWidget* parent = nullptr); + TimelineView(const TrackType& type, + Qt::Alignment vertical_alignment = Qt::AlignTop, + QWidget* parent = nullptr); void SetScale(const double& scale); - void ConnectTimelineNode(TrackList* node); - - void DisconnectTimelineNode(); - void SelectAll(); void DeselectAll(); - void SetUseTrackListLengthDirectly(bool use); - void SetEndTime(const rational& length); int GetTrackY(int track_index); @@ -70,15 +66,9 @@ public slots: void SetTime(const int64_t time); - void AddTrack(TrackOutput* track); - - void RemoveTrack(TrackOutput* track); - signals: void ScaleChanged(double scale); - void TimebaseChanged(const rational& timebase); - void TimeChanged(const int64_t& time); void MousePressed(TimelineViewMouseEvent* event); @@ -113,10 +103,6 @@ private: TimelineCoordinate ScreenToCoordinate(const QPoint& pt); TimelineCoordinate SceneToCoordinate(const QPointF& pt); - TrackList* timeline_node_; - - void AddGhost(TimelineViewGhostItem* ghost); - int SceneToTrack(double y); void UserSetTime(const int64_t& time); @@ -137,27 +123,14 @@ private: QRect playhead_rect_; - bool use_tracklist_length_directly_; + TrackType type_; private slots: - /** - * @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 BlockChanged(); - /** * @brief Slot called whenever the view resizes or the scene contents change to enforce minimum scene sizes */ void UpdateSceneRect(); - /** - * @brief When the attached track list's end frame changes, update the graphical representation here - */ - void UpdateEndTimeFromTrackList(const rational& length); - }; #endif // TIMELINEVIEW_H diff --git a/app/widget/timelineview/timelineviewghostitem.cpp b/app/widget/timelineview/timelineviewghostitem.cpp index c75c83fd6..5e0bf3661 100644 --- a/app/widget/timelineview/timelineviewghostitem.cpp +++ b/app/widget/timelineview/timelineviewghostitem.cpp @@ -172,7 +172,7 @@ rational TimelineViewGhostItem::GetAdjustedMediaIn() const TrackReference TimelineViewGhostItem::GetAdjustedTrack() const { - return track_ + track_adj_; + return TrackReference(track_.type(), track_.index() + track_adj_); } const olive::timeline::MovementMode &TimelineViewGhostItem::mode() const diff --git a/app/widget/timelineview/tool/import.cpp b/app/widget/timelineview/tool/import.cpp index f6f83453d..6b16e5256 100644 --- a/app/widget/timelineview/tool/import.cpp +++ b/app/widget/timelineview/tool/import.cpp @@ -95,6 +95,10 @@ void TimelineWidget::ImportTool::DragEnter(TimelineViewMouseEvent *event) // If the Item is Footage, we can create a Ghost from it Footage* footage = static_cast(item); + // Each stream is offset by one track per track "type", we keep track of them in this vector + QVector track_offsets(kTrackTypeCount); + track_offsets.fill(drag_start_.GetTrack().index()); + rational footage_duration; // Loop through all streams in footage @@ -119,6 +123,10 @@ void TimelineWidget::ImportTool::DragEnter(TimelineViewMouseEvent *event) ghost->SetIn(ghost_start); ghost->SetOut(ghost_start + footage_duration); + ghost->SetTrack(TrackReference(track_type, track_offsets.at(track_type))); + + // Increment track count for this track type + track_offsets[track_type]++; snap_points_.append(ghost->In()); snap_points_.append(ghost->Out()); @@ -145,10 +153,7 @@ void TimelineWidget::ImportTool::DragMove(TimelineViewMouseEvent *event) { if (parent()->HasGhosts()) { rational time_movement = event->GetCoordinates().GetFrame() - drag_start_.GetFrame(); - - const TrackReference& ghost_track = event->GetCoordinates().GetTrack(); - int ghost_y = parent()->GetTrackY(ghost_track); - int ghost_height = parent()->GetTrackHeight(ghost_track); + int track_movement = event->GetCoordinates().GetTrack().index() - drag_start_.GetTrack().index(); // If snapping is enabled, check for snap points if (olive::core.snapping()) { @@ -156,6 +161,7 @@ void TimelineWidget::ImportTool::DragMove(TimelineViewMouseEvent *event) } time_movement = ValidateFrameMovement(time_movement, parent()->ghost_items_); + track_movement = ValidateTrackMovement(track_movement, parent()->ghost_items_); rational earliest_ghost = RATIONAL_MAX; @@ -163,11 +169,11 @@ void TimelineWidget::ImportTool::DragMove(TimelineViewMouseEvent *event) foreach (TimelineViewGhostItem* ghost, parent()->ghost_items_) { ghost->SetInAdjustment(time_movement); ghost->SetOutAdjustment(time_movement); + ghost->SetTrackAdjustment(track_movement); - ghost->SetTrack(ghost_track); - - ghost->SetY(ghost_y); - ghost->SetHeight(ghost_height); + TrackReference adjusted_track = ghost->GetAdjustedTrack(); + ghost->SetY(parent()->GetTrackY(adjusted_track)); + ghost->SetHeight(parent()->GetTrackHeight(adjusted_track)); earliest_ghost = qMin(earliest_ghost, ghost->GetAdjustedIn()); } diff --git a/app/widget/timelineview/tool/pointer.cpp b/app/widget/timelineview/tool/pointer.cpp index e97d20d5b..06e1fd813 100644 --- a/app/widget/timelineview/tool/pointer.cpp +++ b/app/widget/timelineview/tool/pointer.cpp @@ -274,7 +274,7 @@ void TimelineWidget::PointerTool::InitiateGhosts(TimelineViewBlockItem* clicked_ bool allow_gap_trimming) { // Convert selected items list to clips list - QList clips = GetSelectedClips(); + QList clips = parent()->GetSelectedBlocks(); // If trimming multiple clips, we only trim the earliest in each track (trimming in) or the latest in each track // (trimming out). If the current clip is NOT one of these, we only trim it. @@ -351,7 +351,6 @@ TimelineViewGhostItem* TimelineWidget::PointerTool::AddGhostFromNull(const ratio void TimelineWidget::PointerTool::AddGhostInternal(TimelineViewGhostItem* ghost, olive::timeline::MovementMode mode) { - ghost->SetScale(parent()->scale_); ghost->SetMode(mode); // Prepare snap points (optimizes snapping for later) @@ -370,25 +369,7 @@ void TimelineWidget::PointerTool::AddGhostInternal(TimelineViewGhostItem* ghost, break; } - parent()->ghost_items_.append(ghost); - parent()->scene_.addItem(ghost); -} - -QList TimelineWidget::PointerTool::GetSelectedClips() -{ - QList selected_items = parent()->scene_.selectedItems(); - - // Convert selected items list to clips list - QList clips; - foreach (QGraphicsItem* item, selected_items) { - TimelineViewBlockItem* clip_cast = dynamic_cast(item); - - if (clip_cast != nullptr) { - clips.append(clip_cast); - } - } - - return clips; + parent()->AddGhost(ghost); } bool TimelineWidget::PointerTool::IsClipTrimmable(TimelineViewBlockItem* clip, diff --git a/app/widget/timelineview/tool/ripple.cpp b/app/widget/timelineview/tool/ripple.cpp index c1214c2d7..f65a4a01e 100644 --- a/app/widget/timelineview/tool/ripple.cpp +++ b/app/widget/timelineview/tool/ripple.cpp @@ -85,8 +85,8 @@ rational TimelineWidget::RippleTool::FrameValidateInternal(rational time_movemen } void TimelineWidget::RippleTool::InitiateGhosts(TimelineViewBlockItem *clicked_item, - olive::timeline::MovementMode trim_mode, - bool allow_gap_trimming) + olive::timeline::MovementMode trim_mode, + bool allow_gap_trimming) { Q_UNUSED(allow_gap_trimming) @@ -134,12 +134,14 @@ void TimelineWidget::RippleTool::InitiateGhosts(TimelineViewBlockItem *clicked_i && block_before_ripple->next()->type() != Block::kEnd) { 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->Index(), trim_mode); + ghost = AddGhostFromBlock(block_before_ripple, track_ref, trim_mode); } else { // If there's no gap here, we'll need to create one - ghost = AddGhostFromNull(block_before_ripple->out(), block_before_ripple->out(), track->Index(), trim_mode); + ghost = AddGhostFromNull(block_before_ripple->out(), block_before_ripple->out(), track_ref, trim_mode); ghost->setData(TimelineViewGhostItem::kReferenceBlock, Node::PtrToValue(block_before_ripple)); } diff --git a/app/widget/timelinewidget/timelinewidget.cpp b/app/widget/timelinewidget/timelinewidget.cpp index 14291f250..232aa1ff7 100644 --- a/app/widget/timelinewidget/timelinewidget.cpp +++ b/app/widget/timelinewidget/timelinewidget.cpp @@ -29,10 +29,10 @@ TimelineWidget::TimelineWidget(QWidget *parent) : layout->addWidget(view_splitter); // Video view - views_.append(new TimelineView(Qt::AlignBottom)); + views_.append(new TimelineView(kTrackTypeVideo, Qt::AlignBottom)); // Audio view - views_.append(new TimelineView(Qt::AlignTop)); + views_.append(new TimelineView(kTrackTypeAudio, Qt::AlignTop)); // Create tools tools_.resize(olive::tool::kCount); @@ -67,13 +67,21 @@ TimelineWidget::TimelineWidget(QWidget *parent) : connect(view->horizontalScrollBar(), SIGNAL(valueChanged(int)), ruler_, SLOT(SetScroll(int))); connect(view, SIGNAL(ScaleChanged(double)), this, SLOT(SetScale(double))); - connect(view, SIGNAL(TimebaseChanged(const rational&)), this, SLOT(SetTimebase(const rational&))); connect(ruler_, SIGNAL(TimeChanged(const int64_t&)), view, SLOT(SetTime(const int64_t&))); connect(view, SIGNAL(TimeChanged(const int64_t&)), ruler_, SLOT(SetTime(const int64_t&))); connect(view, SIGNAL(TimeChanged(const int64_t&)), this, SIGNAL(TimeChanged(const int64_t&))); connect(horizontal_scroll_, SIGNAL(valueChanged(int)), view->horizontalScrollBar(), SLOT(setValue(int))); connect(view->horizontalScrollBar(), SIGNAL(valueChanged(int)), horizontal_scroll_, SLOT(setValue(int))); + connect(view, SIGNAL(MousePressed(TimelineViewMouseEvent*)), this, SLOT(ViewMousePressed(TimelineViewMouseEvent*))); + connect(view, SIGNAL(MouseMoved(TimelineViewMouseEvent*)), this, SLOT(ViewMouseMoved(TimelineViewMouseEvent*))); + connect(view, SIGNAL(MouseReleased(TimelineViewMouseEvent*)), this, SLOT(ViewMouseReleased(TimelineViewMouseEvent*))); + connect(view, SIGNAL(MouseDoubleClicked(TimelineViewMouseEvent*)), this, SLOT(ViewMouseDoubleClicked(TimelineViewMouseEvent*))); + connect(view, SIGNAL(DragEntered(TimelineViewMouseEvent*)), this, SLOT(ViewDragEntered(TimelineViewMouseEvent*))); + connect(view, SIGNAL(DragMoved(TimelineViewMouseEvent*)), this, SLOT(ViewDragMoved(TimelineViewMouseEvent*))); + connect(view, SIGNAL(DragLeft(QDragLeaveEvent*)), this, SLOT(ViewDragLeft(QDragLeaveEvent*))); + connect(view, SIGNAL(DragDropped(TimelineViewMouseEvent*)), this, SLOT(ViewDragDropped(TimelineViewMouseEvent*))); + // Connect each view's scroll to each other foreach (TimelineView* other_view, views_) { if (view != other_view) { @@ -141,32 +149,46 @@ void TimelineWidget::ConnectTimelineNode(TimelineOutput *node) disconnect(timeline_node_, SIGNAL(LengthChanged(const rational&)), this, SLOT(UpdateTimelineLength(const rational&))); disconnect(timeline_node_, SIGNAL(BlockAdded(Block*, TrackReference)), this, SLOT(AddBlock(Block*, TrackReference))); disconnect(timeline_node_, SIGNAL(BlockRemoved(Block*)), this, SLOT(RemoveBlock(Block*))); + disconnect(timeline_node_, SIGNAL(TrackAdded(TrackOutput*)), this, SLOT(AddTrack(TrackOutput*))); + disconnect(timeline_node_, SIGNAL(TrackRemoved(TrackOutput*)), this, SLOT(RemoveTrack(TrackOutput*))); + disconnect(timeline_node_, SIGNAL(TimebaseChanged(const rational&)), this, SLOT(SetTimebase(const rational&))); + disconnect(timeline_node_, SIGNAL(TimelineCleared()), this, SLOT(Clear())); + + SetTimebase(0); + + Clear(); } timeline_node_ = node; - for (int track_type=0;track_typeConnectTimelineNode(node->track_list(static_cast(track_type))); - } - if (timeline_node_ != nullptr) { connect(timeline_node_, SIGNAL(LengthChanged(const rational&)), this, SLOT(UpdateTimelineLength(const rational&))); connect(timeline_node_, SIGNAL(BlockAdded(Block*, TrackReference)), this, SLOT(AddBlock(Block*, TrackReference))); connect(timeline_node_, SIGNAL(BlockRemoved(Block*)), this, SLOT(RemoveBlock(Block*))); + connect(timeline_node_, SIGNAL(TrackAdded(TrackOutput*, TrackType)), this, SLOT(AddTrack(TrackOutput*, TrackType))); + connect(timeline_node_, SIGNAL(TrackRemoved(TrackOutput*)), this, SLOT(RemoveTrack(TrackOutput*))); + connect(timeline_node_, SIGNAL(TimebaseChanged(const rational&)), this, SLOT(SetTimebase(const rational&))); + + SetTimebase(timeline_node_->Timebase()); + + for (int i=0;i(i); + + TimelineView* view = views_.at(i); - foreach (TimelineView* view, views_) { view->SetEndTime(timeline_node_->timeline_length()); + + // Defer to the track to make all the block UI items necessary + foreach (TrackOutput* track, timeline_node_->track_list(track_type)->Tracks()) { + AddTrack(track, track_type); + } } } } void TimelineWidget::DisconnectTimelineNode() { - timeline_node_ = nullptr; - - foreach (TimelineView* view, views_) { - view->DisconnectTimelineNode(); - } + ConnectTimelineNode(nullptr); } void TimelineWidget::ZoomIn() @@ -276,6 +298,25 @@ void TimelineWidget::GoToNextCut() } } +QList TimelineWidget::GetSelectedBlocks() +{ + QList list; + + QMapIterator iterator(block_items_); + + while (iterator.hasNext()) { + iterator.next(); + + TimelineViewBlockItem* item = iterator.value(); + + if (item != nullptr && item->isSelected()) { + list.append(item); + } + } + + return list; +} + void TimelineWidget::RippleEditTo(olive::timeline::MovementMode mode, bool insert_gaps) { rational playhead_time = olive::timestamp_to_time(playhead_, timebase()); @@ -514,3 +555,33 @@ void TimelineWidget::RemoveBlock(Block *block) block_items_.remove(block); } + +void TimelineWidget::AddTrack(TrackOutput *track, TrackType type) +{ + foreach (Block* b, track->Blocks()) { + AddBlock(b, TrackReference(type, track->Index())); + } +} + +void TimelineWidget::RemoveTrack(TrackOutput *track) +{ + foreach (Block* b, track->Blocks()) { + RemoveBlock(b); + } +} + +void TimelineWidget::BlockChanged() +{ + TimelineViewRect* rect = block_items_[static_cast(sender())]; + + if (rect != nullptr) { + rect->UpdateRect(); + } +} + +void TimelineWidget::AddGhost(TimelineViewGhostItem *ghost) +{ + ghost->SetScale(scale_); + ghost_items_.append(ghost); + views_.at(ghost->Track().type())->scene()->addItem(ghost); +} diff --git a/app/widget/timelinewidget/timelinewidget.h b/app/widget/timelinewidget/timelinewidget.h index c75a7045e..00ba170c4 100644 --- a/app/widget/timelinewidget/timelinewidget.h +++ b/app/widget/timelinewidget/timelinewidget.h @@ -47,6 +47,8 @@ public: void GoToNextCut(); + QList GetSelectedBlocks(); + public slots: void SetTimebase(const rational& timebase); @@ -180,8 +182,6 @@ private: void AddGhostInternal(TimelineViewGhostItem* ghost, olive::timeline::MovementMode mode); - QList GetSelectedClips(); - bool IsClipTrimmable(TimelineViewBlockItem* clip, const QList& items, const olive::timeline::MovementMode& mode); @@ -325,6 +325,8 @@ private: void CenterOn(qreal scene_pos); + void AddGhost(TimelineViewGhostItem* ghost); + private slots: void SetScale(double scale); @@ -345,6 +347,17 @@ private slots: void AddBlock(Block* block, TrackReference track); void RemoveBlock(Block* block); + void AddTrack(TrackOutput* track, TrackType type); + void RemoveTrack(TrackOutput* track); + + /** + * @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 BlockChanged(); + }; #endif // TIMELINEWIDGET_H