From dc37389d02cedfa608ef67cdcd6dc688c749ce24 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 8 Mar 2020 01:06:45 +1100 Subject: [PATCH] timeline: implemented in/out points --- app/common/rational.h | 1 + app/panel/timebased/timebased.cpp | 25 +++++ app/panel/timebased/timebased.h | 10 ++ app/project/item/footage/footage.h | 3 +- app/project/item/sequence/sequence.h | 3 +- app/timeline/CMakeLists.txt | 6 ++ app/timeline/timelinemarker.cpp | 61 +++++++++++ app/timeline/timelinemarker.h | 56 ++++++++++ app/timeline/timelinepoints.cpp | 21 ++++ app/timeline/timelinepoints.h | 25 +++++ app/timeline/timelineworkarea.cpp | 41 ++++++++ app/timeline/timelineworkarea.h | 37 +++++++ app/widget/menu/menushared.cpp | 47 +++++++-- app/widget/menu/menushared.h | 16 ++- app/widget/panel/panel.h | 10 ++ app/widget/timebased/timebased.cpp | 105 +++++++++++++++++++ app/widget/timebased/timebased.h | 31 ++++++ app/widget/timelinewidget/timelinewidget.cpp | 4 +- app/widget/timelinewidget/timelinewidget.h | 2 +- app/widget/timelinewidget/undo/undo.cpp | 42 +++++++- app/widget/timelinewidget/undo/undo.h | 39 ++++++- app/widget/timeruler/timeruler.cpp | 41 +++++++- app/widget/timeruler/timeruler.h | 8 ++ 23 files changed, 609 insertions(+), 25 deletions(-) create mode 100644 app/timeline/timelinemarker.cpp create mode 100644 app/timeline/timelinemarker.h create mode 100644 app/timeline/timelinepoints.cpp create mode 100644 app/timeline/timelinepoints.h create mode 100644 app/timeline/timelineworkarea.cpp create mode 100644 app/timeline/timelineworkarea.h diff --git a/app/common/rational.h b/app/common/rational.h index 59ed8775e..505ac313f 100644 --- a/app/common/rational.h +++ b/app/common/rational.h @@ -118,6 +118,7 @@ private: QDebug operator<<(QDebug debug, const rational& r); +// We define these limits at 32-bit to try avoiding integer overflow #define RATIONAL_MIN rational(INT32_MIN, 1) #define RATIONAL_MAX rational(INT32_MAX, 1) diff --git a/app/panel/timebased/timebased.cpp b/app/panel/timebased/timebased.cpp index 2e76ae10f..d74b1cd61 100644 --- a/app/panel/timebased/timebased.cpp +++ b/app/panel/timebased/timebased.cpp @@ -134,3 +134,28 @@ void TimeBasedPanel::Retranslate() SetSubtitle(tr("(none)")); } } + +void TimeBasedPanel::SetIn() +{ + GetTimeBasedWidget()->SetInAtPlayhead(); +} + +void TimeBasedPanel::SetOut() +{ + GetTimeBasedWidget()->SetOutAtPlayhead(); +} + +void TimeBasedPanel::ResetIn() +{ + GetTimeBasedWidget()->ResetIn(); +} + +void TimeBasedPanel::ResetOut() +{ + GetTimeBasedWidget()->ResetOut(); +} + +void TimeBasedPanel::ClearInOut() +{ + GetTimeBasedWidget()->ClearInOutPoints(); +} diff --git a/app/panel/timebased/timebased.h b/app/panel/timebased/timebased.h index 59a4ec84e..555821539 100644 --- a/app/panel/timebased/timebased.h +++ b/app/panel/timebased/timebased.h @@ -44,6 +44,16 @@ public: virtual void ShuttleRight() override; + virtual void SetIn() override; + + virtual void SetOut() override; + + virtual void ResetIn() override; + + virtual void ResetOut() override; + + virtual void ClearInOut() override; + public slots: void SetTimebase(const rational& timebase); diff --git a/app/project/item/footage/footage.h b/app/project/item/footage/footage.h index 42226d64d..0e5f31ee9 100644 --- a/app/project/item/footage/footage.h +++ b/app/project/item/footage/footage.h @@ -30,6 +30,7 @@ #include "project/item/footage/audiostream.h" #include "project/item/footage/imagestream.h" #include "project/item/footage/videostream.h" +#include "timeline/timelinepoints.h" /** * @brief A reference to an external media file with metadata in a project structure @@ -38,7 +39,7 @@ * Footage objects store a list of Stream objects which store the majority of video/audio metadata. These streams * are identical to the stream data in the files. */ -class Footage : public Item +class Footage : public Item, public TimelinePoints { public: enum Status { diff --git a/app/project/item/sequence/sequence.h b/app/project/item/sequence/sequence.h index c9311cd40..dd91dc2f4 100644 --- a/app/project/item/sequence/sequence.h +++ b/app/project/item/sequence/sequence.h @@ -27,6 +27,7 @@ #include "render/videoparams.h" #include "project/item/footage/stream.h" #include "project/item/item.h" +#include "timeline/timelinepoints.h" class Sequence; using SequencePtr = std::shared_ptr; @@ -34,7 +35,7 @@ using SequencePtr = std::shared_ptr; /** * @brief The main timeline object, an graph of edited clips that forms a complete edit */ -class Sequence : public Item, public NodeGraph +class Sequence : public Item, public NodeGraph, public TimelinePoints { public: Sequence(); diff --git a/app/timeline/CMakeLists.txt b/app/timeline/CMakeLists.txt index c0bd69c9f..000775dcc 100644 --- a/app/timeline/CMakeLists.txt +++ b/app/timeline/CMakeLists.txt @@ -18,6 +18,12 @@ set(OLIVE_SOURCES ${OLIVE_SOURCES} timeline/timelinecoordinate.h timeline/timelinecoordinate.cpp + timeline/timelinemarker.h + timeline/timelinemarker.cpp + timeline/timelinepoints.h + timeline/timelinepoints.cpp + timeline/timelineworkarea.h + timeline/timelineworkarea.cpp timeline/trackreference.h timeline/trackreference.cpp PARENT_SCOPE diff --git a/app/timeline/timelinemarker.cpp b/app/timeline/timelinemarker.cpp new file mode 100644 index 000000000..83a136c7b --- /dev/null +++ b/app/timeline/timelinemarker.cpp @@ -0,0 +1,61 @@ +#include "timelinemarker.h" + +TimelineMarker::TimelineMarker(const TimeRange &time, const QString &name, QObject *parent) : + QObject(parent), + time_(time), + name_(name) +{ +} + +const TimeRange &TimelineMarker::time() const +{ + return time_; +} + +void TimelineMarker::set_time(const TimeRange &time) +{ + time_ = time; + emit TimeChanged(time_); +} + +const QString &TimelineMarker::name() const +{ + return name_; +} + +void TimelineMarker::set_name(const QString &name) +{ + name_ = name; + emit NameChanged(name_); +} + +TimelineMarkerList::~TimelineMarkerList() +{ + qDeleteAll(markers_); +} + +void TimelineMarkerList::AddMarker(const TimeRange &time, const QString &name) +{ + TimelineMarker* m = new TimelineMarker(time, name); + markers_.append(m); + emit MarkerAdded(m); +} + +void TimelineMarkerList::RemoveMarker(TimelineMarker *marker) +{ + for (int i=0;i &TimelineMarkerList::list() const +{ + return markers_; +} diff --git a/app/timeline/timelinemarker.h b/app/timeline/timelinemarker.h new file mode 100644 index 000000000..998f27585 --- /dev/null +++ b/app/timeline/timelinemarker.h @@ -0,0 +1,56 @@ +#ifndef TIMELINEMARKER_H +#define TIMELINEMARKER_H + +#include + +#include "common/timerange.h" + +class TimelineMarker : public QObject +{ + Q_OBJECT +public: + TimelineMarker(const TimeRange& time = TimeRange(), const QString& name = QString(), QObject* parent = nullptr); + + const TimeRange &time() const; + void set_time(const TimeRange& time); + + const QString& name() const; + void set_name(const QString& name); + +signals: + void TimeChanged(const TimeRange& time); + + void NameChanged(const QString& name); + +private: + TimeRange time_; + + QString name_; + +}; + +class TimelineMarkerList : public QObject +{ + Q_OBJECT +public: + TimelineMarkerList() = default; + + virtual ~TimelineMarkerList() override; + + void AddMarker(const TimeRange& time = TimeRange(), const QString& name = QString()); + + void RemoveMarker(TimelineMarker* marker); + + const QList &list() const; + +signals: + void MarkerAdded(TimelineMarker* marker); + + void MarkerRemoved(TimelineMarker* marker); + +private: + QList markers_; + +}; + +#endif // TIMELINEMARKER_H diff --git a/app/timeline/timelinepoints.cpp b/app/timeline/timelinepoints.cpp new file mode 100644 index 000000000..b3aae146c --- /dev/null +++ b/app/timeline/timelinepoints.cpp @@ -0,0 +1,21 @@ +#include "timelinepoints.h" + +TimelineMarkerList *TimelinePoints::markers() +{ + return &markers_; +} + +const TimelineMarkerList *TimelinePoints::markers() const +{ + return &markers_; +} + +const TimelineWorkArea *TimelinePoints::workarea() const +{ + return &workarea_; +} + +TimelineWorkArea *TimelinePoints::workarea() +{ + return &workarea_; +} diff --git a/app/timeline/timelinepoints.h b/app/timeline/timelinepoints.h new file mode 100644 index 000000000..ed2570f1c --- /dev/null +++ b/app/timeline/timelinepoints.h @@ -0,0 +1,25 @@ +#ifndef TIMELINEPOINTS_H +#define TIMELINEPOINTS_H + +#include "timelinemarker.h" +#include "timelineworkarea.h" + +class TimelinePoints +{ +public: + TimelinePoints() = default; + + TimelineMarkerList* markers(); + const TimelineMarkerList* markers() const; + + TimelineWorkArea* workarea(); + const TimelineWorkArea* workarea() const; + +private: + TimelineMarkerList markers_; + + TimelineWorkArea workarea_; + +}; + +#endif // TIMELINEPOINTS_H diff --git a/app/timeline/timelineworkarea.cpp b/app/timeline/timelineworkarea.cpp new file mode 100644 index 000000000..57b29364a --- /dev/null +++ b/app/timeline/timelineworkarea.cpp @@ -0,0 +1,41 @@ +#include "timelineworkarea.h" + +const rational TimelineWorkArea::kResetIn = 0; +const rational TimelineWorkArea::kResetOut = RATIONAL_MAX; + +TimelineWorkArea::TimelineWorkArea(QObject *parent) : + QObject(parent) +{ +} + +bool TimelineWorkArea::enabled() const +{ + return workarea_enabled_; +} + +void TimelineWorkArea::set_enabled(bool e) +{ + workarea_enabled_ = e; + emit EnabledChanged(workarea_enabled_); +} + +const TimeRange &TimelineWorkArea::range() const +{ + return workarea_range_; +} + +void TimelineWorkArea::set_range(const TimeRange &range) +{ + workarea_range_ = range; + emit RangeChanged(workarea_range_); +} + +const rational &TimelineWorkArea::in() const +{ + return workarea_range_.in(); +} + +const rational &TimelineWorkArea::out() const +{ + return workarea_range_.out(); +} diff --git a/app/timeline/timelineworkarea.h b/app/timeline/timelineworkarea.h new file mode 100644 index 000000000..bad23bc82 --- /dev/null +++ b/app/timeline/timelineworkarea.h @@ -0,0 +1,37 @@ +#ifndef TIMELINEWORKAREA_H +#define TIMELINEWORKAREA_H + +#include + +#include "common/timerange.h" + +class TimelineWorkArea : public QObject +{ + Q_OBJECT +public: + TimelineWorkArea(QObject* parent = nullptr); + + bool enabled() const; + void set_enabled(bool e); + + const rational& in() const; + const rational& out() const; + const TimeRange& range() const; + void set_range(const TimeRange& range); + + static const rational kResetIn; + static const rational kResetOut; + +signals: + void EnabledChanged(bool e); + + void RangeChanged(const TimeRange& r); + +private: + bool workarea_enabled_; + + TimeRange workarea_range_; + +}; + +#endif // TIMELINEWORKAREA_H diff --git a/app/widget/menu/menushared.cpp b/app/widget/menu/menushared.cpp index 6cd1df5f4..84419b8cc 100644 --- a/app/widget/menu/menushared.cpp +++ b/app/widget/menu/menushared.cpp @@ -39,16 +39,16 @@ MenuShared::MenuShared() edit_paste_item_ = Menu::CreateItem(this, "paste", nullptr, nullptr, "Ctrl+V"); edit_paste_insert_item_ = Menu::CreateItem(this, "pasteinsert", nullptr, nullptr, "Ctrl+Shift+V"); edit_duplicate_item_ = Menu::CreateItem(this, "duplicate", nullptr, nullptr, "Ctrl+D"); - edit_delete_item_ = Menu::CreateItem(this, "delete", this, SLOT(DeleteSelected()), "Del"); - edit_ripple_delete_item_ = Menu::CreateItem(this, "rippledelete", this, SLOT(RippleDelete()), "Shift+Del"); - edit_split_item_ = Menu::CreateItem(this, "split", this, SLOT(SplitAtPlayhead()), "Ctrl+K"); + edit_delete_item_ = Menu::CreateItem(this, "delete", this, SLOT(DeleteSelectedTriggered()), "Del"); + edit_ripple_delete_item_ = Menu::CreateItem(this, "rippledelete", this, SLOT(RippleDeleteTriggered()), "Shift+Del"); + edit_split_item_ = Menu::CreateItem(this, "split", this, SLOT(SplitAtPlayheadTriggered()), "Ctrl+K"); // "In/Out" menu shared items - inout_set_in_item_ = Menu::CreateItem(this, "setinpoint", nullptr, nullptr, "I"); - inout_set_out_item_ = Menu::CreateItem(this, "setoutpoint", nullptr, nullptr, "O"); - inout_reset_in_item_ = Menu::CreateItem(this, "resetin", nullptr, nullptr); - inout_reset_out_item_ = Menu::CreateItem(this, "resetout", nullptr, nullptr); - inout_clear_inout_item_ = Menu::CreateItem(this, "clearinout", nullptr, nullptr, "G"); + inout_set_in_item_ = Menu::CreateItem(this, "setinpoint", this, SLOT(SetInTriggered()), "I"); + inout_set_out_item_ = Menu::CreateItem(this, "setoutpoint", this, SLOT(SetOutTriggered()), "O"); + inout_reset_in_item_ = Menu::CreateItem(this, "resetin", this, SLOT(ResetInTriggered())); + inout_reset_out_item_ = Menu::CreateItem(this, "resetout", this, SLOT(ResetOutTriggered())); + inout_clear_inout_item_ = Menu::CreateItem(this, "clearinout", this, SLOT(ClearInOutTriggered()), "G"); // "Clip Edit" menu shared items clip_add_default_transition_item_ = Menu::CreateItem(this, "deftransition", nullptr, nullptr, "Ctrl+Shift+D"); @@ -112,7 +112,7 @@ MenuShared *MenuShared::instance() return instance_; } -void MenuShared::SplitAtPlayhead() +void MenuShared::SplitAtPlayheadTriggered() { TimelinePanel* timeline = PanelManager::instance()->MostRecentlyFocused(); @@ -121,16 +121,41 @@ void MenuShared::SplitAtPlayhead() } } -void MenuShared::DeleteSelected() +void MenuShared::DeleteSelectedTriggered() { PanelManager::instance()->CurrentlyFocused()->DeleteSelected(); } -void MenuShared::RippleDelete() +void MenuShared::RippleDeleteTriggered() { PanelManager::instance()->CurrentlyFocused()->RippleDelete(); } +void MenuShared::SetInTriggered() +{ + PanelManager::instance()->CurrentlyFocused()->SetIn(); +} + +void MenuShared::SetOutTriggered() +{ + PanelManager::instance()->CurrentlyFocused()->SetOut(); +} + +void MenuShared::ResetInTriggered() +{ + PanelManager::instance()->CurrentlyFocused()->ResetIn(); +} + +void MenuShared::ResetOutTriggered() +{ + PanelManager::instance()->CurrentlyFocused()->ResetOut(); +} + +void MenuShared::ClearInOutTriggered() +{ + PanelManager::instance()->CurrentlyFocused()->ClearInOut(); +} + void MenuShared::Retranslate() { // "New" menu shared items diff --git a/app/widget/menu/menushared.h b/app/widget/menu/menushared.h index 2cee72066..6269aa2bb 100644 --- a/app/widget/menu/menushared.h +++ b/app/widget/menu/menushared.h @@ -75,11 +75,21 @@ private: static MenuShared* instance_; private slots: - void SplitAtPlayhead(); + void SplitAtPlayheadTriggered(); - void DeleteSelected(); + void DeleteSelectedTriggered(); - void RippleDelete(); + void RippleDeleteTriggered(); + + void SetInTriggered(); + + void SetOutTriggered(); + + void ResetInTriggered(); + + void ResetOutTriggered(); + + void ClearInOutTriggered(); }; diff --git a/app/widget/panel/panel.h b/app/widget/panel/panel.h index e324c149f..d81df1be8 100644 --- a/app/widget/panel/panel.h +++ b/app/widget/panel/panel.h @@ -118,6 +118,16 @@ public: virtual void DecreaseTrackHeight(){} + virtual void SetIn(){} + + virtual void SetOut(){} + + virtual void ResetIn(){} + + virtual void ResetOut(){} + + virtual void ClearInOut(){} + protected: /** * @brief paintEvent diff --git a/app/widget/timebased/timebased.cpp b/app/widget/timebased/timebased.cpp index b7feb9bb6..f75d657ec 100644 --- a/app/widget/timebased/timebased.cpp +++ b/app/widget/timebased/timebased.cpp @@ -1,6 +1,11 @@ #include "timebased.h" +#include + #include "common/timecodefunctions.h" +#include "core.h" +#include "project/item/sequence/sequence.h" +#include "widget/timelinewidget/undo/undo.h" TimeBasedWidget::TimeBasedWidget(bool ruler_text_visible, bool ruler_cache_status_visible, QWidget *parent) : QWidget(parent), @@ -44,6 +49,8 @@ void TimeBasedWidget::ConnectViewerNode(ViewerOutput *node) DisconnectNodeInternal(viewer_node_); disconnect(viewer_node_, &ViewerOutput::LengthChanged, this, &TimeBasedWidget::UpdateMaximumScroll); + + ruler()->ConnectTimelinePoints(nullptr); } viewer_node_ = node; @@ -54,6 +61,8 @@ void TimeBasedWidget::ConnectViewerNode(ViewerOutput *node) ConnectNodeInternal(viewer_node_); connect(viewer_node_, &ViewerOutput::LengthChanged, this, &TimeBasedWidget::UpdateMaximumScroll); + + ruler()->ConnectTimelinePoints(static_cast(viewer_node_->parent())); } } @@ -242,3 +251,99 @@ void TimeBasedWidget::CenterScrollOnPlayhead() { scrollbar_->setValue(qRound(TimeToScene(Timecode::timestamp_to_time(ruler_->GetTime(), timebase()))) - scrollbar_->width()/2); } + +void TimeBasedWidget::SetPoint(Timeline::MovementMode m, const rational& time) +{ + if (!GetConnectedNode()) { + return; + } + + QUndoCommand* command = new QUndoCommand(); + + Sequence* s = static_cast(GetConnectedNode()->parent()); + + // Enable workarea if it isn't already enabled + if (!s->workarea()->enabled()) { + new WorkareaSetEnabledCommand(s, true, command); + } + + // Determine our new range + rational in_point, out_point; + + if (m == Timeline::kTrimIn) { + in_point = time; + + if (!s->workarea()->enabled() || s->workarea()->out() < in_point) { + out_point = TimelineWorkArea::kResetOut; + } else { + out_point = s->workarea()->out(); + } + } else { + out_point = time; + + if (!s->workarea()->enabled() || s->workarea()->in() > out_point) { + in_point = TimelineWorkArea::kResetIn; + } else { + in_point = s->workarea()->in(); + } + } + + // Set workarea + new WorkareaSetRangeCommand(s, TimeRange(in_point, out_point), command); + + Core::instance()->undo_stack()->push(command); +} + +void TimeBasedWidget::ResetPoint(Timeline::MovementMode m) +{ + if (!GetConnectedNode()) { + return; + } + + Sequence* s = static_cast(GetConnectedNode()->parent()); + + if (!s->workarea()->enabled()) { + return; + } + + TimeRange r = s->workarea()->range(); + + if (m == Timeline::kTrimIn) { + r.set_in(TimelineWorkArea::kResetIn); + } else { + r.set_out(TimelineWorkArea::kResetOut); + } + + Core::instance()->undo_stack()->push(new WorkareaSetRangeCommand(s, r)); +} + +void TimeBasedWidget::SetInAtPlayhead() +{ + SetPoint(Timeline::kTrimIn, GetTime()); +} + +void TimeBasedWidget::SetOutAtPlayhead() +{ + SetPoint(Timeline::kTrimOut, GetTime()); +} + +void TimeBasedWidget::ResetIn() +{ + ResetPoint(Timeline::kTrimIn); +} + +void TimeBasedWidget::ResetOut() +{ + ResetPoint(Timeline::kTrimOut); +} + +void TimeBasedWidget::ClearInOutPoints() +{ + if (!GetConnectedNode()) { + return; + } + + Sequence* s = static_cast(GetConnectedNode()->parent()); + + Core::instance()->undo_stack()->push(new WorkareaSetEnabledCommand(s, false)); +} diff --git a/app/widget/timebased/timebased.h b/app/widget/timebased/timebased.h index 50b0f4882..7b341a4b3 100644 --- a/app/widget/timebased/timebased.h +++ b/app/widget/timebased/timebased.h @@ -3,6 +3,7 @@ #include +#include "common/timelinecommon.h" #include "node/output/viewer/viewer.h" #include "widget/resizablescrollbar/resizablescrollbar.h" #include "widget/timelinewidget/timelinescaledobject.h" @@ -48,6 +49,16 @@ public slots: void GoToNextCut(); + void SetInAtPlayhead(); + + void SetOutAtPlayhead(); + + void ResetIn(); + + void ResetOut(); + + void ClearInOutPoints(); + TimeRuler* ruler() const; protected slots: @@ -84,6 +95,26 @@ signals: void TimebaseChanged(const rational&); private: + /** + * @brief Set either in or out point to the current playhead + * + * @param m + * + * Set to kTrimIn or kTrimOut for setting the in point or out point respectively. + */ + void SetPoint(Timeline::MovementMode m, const rational &time); + + /** + * @brief Reset either the in or out point + * + * Sets either the in point to 0 or the out point to `RATIONAL_MAX`. + * + * @param m + * + * Set to kTrimIn or kTrimOut for setting the in point or out point respectively. + */ + void ResetPoint(Timeline::MovementMode m); + ViewerOutput* viewer_node_; TimeRuler* ruler_; diff --git a/app/widget/timelinewidget/timelinewidget.cpp b/app/widget/timelinewidget/timelinewidget.cpp index 6173d9df2..2385b9289 100644 --- a/app/widget/timelinewidget/timelinewidget.cpp +++ b/app/widget/timelinewidget/timelinewidget.cpp @@ -335,7 +335,7 @@ void TimelineWidget::SplitAtPlayhead() } } -void TimelineWidget::DeleteSelectedInternal(QList blocks, +void TimelineWidget::DeleteSelectedInternal(const QList &blocks, bool transition_aware, bool remove_from_graph, QUndoCommand *command) @@ -426,7 +426,7 @@ void TimelineWidget::DeleteSelected(bool ripple) range_list.InsertTimeRange(TimeRange(b->in(), b->out())); } - new TimelineRippleDeleteGapsAtRegions(GetConnectedNode(), range_list, command); + new TimelineRippleDeleteGapsAtRegionsCommand(GetConnectedNode(), range_list, command); } Core::instance()->undo_stack()->pushIfHasChildren(command); diff --git a/app/widget/timelinewidget/timelinewidget.h b/app/widget/timelinewidget/timelinewidget.h index 2dd6bd758..ca51db637 100644 --- a/app/widget/timelinewidget/timelinewidget.h +++ b/app/widget/timelinewidget/timelinewidget.h @@ -349,7 +349,7 @@ private: bool dual_transition_; }; - void DeleteSelectedInternal(QList blocks, bool transition_aware, bool remove_from_graph, QUndoCommand* command); + void DeleteSelectedInternal(const QList& blocks, bool transition_aware, bool remove_from_graph, QUndoCommand* command); void SetBlockLinksSelected(Block *block, bool selected); diff --git a/app/widget/timelinewidget/undo/undo.cpp b/app/widget/timelinewidget/undo/undo.cpp index 09a9d2db8..2a7dfae1b 100644 --- a/app/widget/timelinewidget/undo/undo.cpp +++ b/app/widget/timelinewidget/undo/undo.cpp @@ -623,14 +623,14 @@ void BlockSetSpeedCommand::undo_internal() block_->set_speed(old_speed_); } -TimelineRippleDeleteGapsAtRegions::TimelineRippleDeleteGapsAtRegions(ViewerOutput *vo, const TimeRangeList ®ions, QUndoCommand *parent) : +TimelineRippleDeleteGapsAtRegionsCommand::TimelineRippleDeleteGapsAtRegionsCommand(ViewerOutput *vo, const TimeRangeList ®ions, QUndoCommand *parent) : UndoCommand(parent), timeline_(vo), regions_(regions) { } -void TimelineRippleDeleteGapsAtRegions::redo_internal() +void TimelineRippleDeleteGapsAtRegionsCommand::redo_internal() { foreach (const TimeRange& range, regions_) { rational max_ripple_length = range.length(); @@ -671,7 +671,7 @@ void TimelineRippleDeleteGapsAtRegions::redo_internal() } } -void TimelineRippleDeleteGapsAtRegions::undo_internal() +void TimelineRippleDeleteGapsAtRegionsCommand::undo_internal() { for (int i=commands_.size()-1;i>=0;i--) { commands_.at(i)->undo(); @@ -679,3 +679,39 @@ void TimelineRippleDeleteGapsAtRegions::undo_internal() } commands_.empty(); } + +WorkareaSetEnabledCommand::WorkareaSetEnabledCommand(TimelinePoints *points, bool enabled, QUndoCommand *parent) : + UndoCommand(parent), + points_(points), + old_enabled_(points_->workarea()->enabled()), + new_enabled_(enabled) +{ +} + +void WorkareaSetEnabledCommand::redo_internal() +{ + points_->workarea()->set_enabled(new_enabled_); +} + +void WorkareaSetEnabledCommand::undo_internal() +{ + points_->workarea()->set_enabled(old_enabled_); +} + +WorkareaSetRangeCommand::WorkareaSetRangeCommand(TimelinePoints *points, const TimeRange &range, QUndoCommand *parent) : + UndoCommand(parent), + points_(points), + old_range_(points_->workarea()->range()), + new_range_(range) +{ +} + +void WorkareaSetRangeCommand::redo_internal() +{ + points_->workarea()->set_range(new_range_); +} + +void WorkareaSetRangeCommand::undo_internal() +{ + points_->workarea()->set_range(old_range_); +} diff --git a/app/widget/timelinewidget/undo/undo.h b/app/widget/timelinewidget/undo/undo.h index 8e4d81b9c..d8afe6d60 100644 --- a/app/widget/timelinewidget/undo/undo.h +++ b/app/widget/timelinewidget/undo/undo.h @@ -27,6 +27,7 @@ #include "node/block/gap/gap.h" #include "node/output/track/track.h" #include "node/output/track/tracklist.h" +#include "timeline/timelinepoints.h" #include "undo/undocommand.h" class BlockResizeCommand : public UndoCommand { @@ -280,9 +281,9 @@ private: }; -class TimelineRippleDeleteGapsAtRegions : public UndoCommand { +class TimelineRippleDeleteGapsAtRegionsCommand : public UndoCommand { public: - TimelineRippleDeleteGapsAtRegions(ViewerOutput* vo, const TimeRangeList& regions, QUndoCommand* parent = nullptr); + TimelineRippleDeleteGapsAtRegionsCommand(ViewerOutput* vo, const TimeRangeList& regions, QUndoCommand* parent = nullptr); protected: virtual void redo_internal() override; @@ -296,4 +297,38 @@ private: }; +class WorkareaSetEnabledCommand : public UndoCommand { +public: + WorkareaSetEnabledCommand(TimelinePoints* points, bool enabled, QUndoCommand* parent = nullptr); + +protected: + virtual void redo_internal() override; + virtual void undo_internal() override; + +private: + TimelinePoints* points_; + + bool old_enabled_; + + bool new_enabled_; + +}; + +class WorkareaSetRangeCommand : public UndoCommand { +public: + WorkareaSetRangeCommand(TimelinePoints* points, const TimeRange& range, QUndoCommand* parent = nullptr); + +protected: + virtual void redo_internal() override; + virtual void undo_internal() override; + +private: + TimelinePoints* points_; + + TimeRange old_range_; + + TimeRange new_range_; + +}; + #endif // TIMELINEUNDOABLE_H diff --git a/app/widget/timeruler/timeruler.cpp b/app/widget/timeruler/timeruler.cpp index a5ef88a9a..15a90b6ab 100644 --- a/app/widget/timeruler/timeruler.cpp +++ b/app/widget/timeruler/timeruler.cpp @@ -37,7 +37,8 @@ TimeRuler::TimeRuler(bool text_visible, bool cache_status_visible, QWidget* pare centered_text_(true), scale_(1.0), time_(0), - show_cache_status_(cache_status_visible) + show_cache_status_(cache_status_visible), + timeline_points_(nullptr) { QFontMetrics fm = fontMetrics(); @@ -81,6 +82,23 @@ void TimeRuler::SetTimebase(const rational &r) update(); } +void TimeRuler::ConnectTimelinePoints(TimelinePoints *points) +{ + if (timeline_points_) { + disconnect(timeline_points_->workarea(), &TimelineWorkArea::RangeChanged, this, &TimeRuler::TimelineWorkareaChanged); + disconnect(timeline_points_->workarea(), &TimelineWorkArea::EnabledChanged, this, &TimeRuler::TimelineWorkareaChanged); + } + + timeline_points_ = points; + + if (timeline_points_) { + connect(timeline_points_->workarea(), &TimelineWorkArea::RangeChanged, this, &TimeRuler::TimelineWorkareaChanged); + connect(timeline_points_->workarea(), &TimelineWorkArea::EnabledChanged, this, &TimeRuler::TimelineWorkareaChanged); + } + + update(); +} + const int64_t &TimeRuler::GetTime() { return time_; @@ -138,6 +156,22 @@ void TimeRuler::paintEvent(QPaintEvent *) QPainter p(this); + // Draw timeline points if connected + if (timeline_points_) { + if (timeline_points_->workarea()->enabled()) { + int workarea_left = qMax(0, TimeToScreen(timeline_points_->workarea()->in())); + int workarea_right; + + if (timeline_points_->workarea()->out() == TimelineWorkArea::kResetOut) { + workarea_right = width(); + } else { + workarea_right = qMin(width(), TimeToScreen(timeline_points_->workarea()->out())); + } + + p.fillRect(workarea_left, 0, workarea_right - workarea_left, height(), palette().highlight()); + } + } + double width_of_frame = timebase_dbl_ * scale_; double width_of_second = 0; do { @@ -381,6 +415,11 @@ void TimeRuler::SeekToScreenPoint(int screen) emit TimeChanged(timestamp); } +void TimeRuler::TimelineWorkareaChanged() +{ + update(); +} + void TimeRuler::UpdateHeight() { int height = text_height_; diff --git a/app/widget/timeruler/timeruler.h b/app/widget/timeruler/timeruler.h index a43b81edd..bb1c5f290 100644 --- a/app/widget/timeruler/timeruler.h +++ b/app/widget/timeruler/timeruler.h @@ -26,6 +26,7 @@ #include "common/rational.h" #include "common/timerange.h" +#include "timeline/timelinepoints.h" #include "widget/timelinewidget/view/timelineplayhead.h" class TimeRuler : public QWidget @@ -41,6 +42,8 @@ public: void SetCenteredText(bool c); + void ConnectTimelinePoints(TimelinePoints* points); + const int64_t& GetTime(); public slots: @@ -115,6 +118,11 @@ private: TimeRangeList dirty_cache_ranges_; + TimelinePoints* timeline_points_; + +private slots: + void TimelineWorkareaChanged(); + }; #endif // TIMERULER_H