change: change code style to Linux style except indent.
This commit is contained in:
@@ -23,54 +23,60 @@
|
||||
#include <QHBoxLayout>
|
||||
#include <QScrollBar>
|
||||
|
||||
namespace olive {
|
||||
|
||||
TimelineAndTrackView::TimelineAndTrackView(Qt::Alignment vertical_alignment, QWidget *parent) :
|
||||
QWidget(parent)
|
||||
namespace olive
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
layout->setSpacing(0);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
splitter_ = new QSplitter(Qt::Horizontal);
|
||||
splitter_->setChildrenCollapsible(false);
|
||||
layout->addWidget(splitter_);
|
||||
TimelineAndTrackView::TimelineAndTrackView(Qt::Alignment vertical_alignment,
|
||||
QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->setSpacing(0);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
track_view_ = new TrackView(vertical_alignment);
|
||||
splitter_->addWidget(track_view_);
|
||||
splitter_ = new QSplitter(Qt::Horizontal);
|
||||
splitter_->setChildrenCollapsible(false);
|
||||
layout->addWidget(splitter_);
|
||||
|
||||
view_ = new TimelineView(vertical_alignment);
|
||||
splitter_->addWidget(view_);
|
||||
track_view_ = new TrackView(vertical_alignment);
|
||||
splitter_->addWidget(track_view_);
|
||||
|
||||
connect(view_->verticalScrollBar(), &QScrollBar::valueChanged, this, &TimelineAndTrackView::ViewValueChanged);
|
||||
connect(track_view_->verticalScrollBar(), &QScrollBar::valueChanged, this, &TimelineAndTrackView::TracksValueChanged);
|
||||
view_ = new TimelineView(vertical_alignment);
|
||||
splitter_->addWidget(view_);
|
||||
|
||||
splitter_->setSizes({1, width()});
|
||||
connect(view_->verticalScrollBar(), &QScrollBar::valueChanged, this,
|
||||
&TimelineAndTrackView::ViewValueChanged);
|
||||
connect(track_view_->verticalScrollBar(), &QScrollBar::valueChanged, this,
|
||||
&TimelineAndTrackView::TracksValueChanged);
|
||||
|
||||
splitter_->setSizes({ 1, width() });
|
||||
}
|
||||
|
||||
QSplitter *TimelineAndTrackView::splitter() const
|
||||
{
|
||||
return splitter_;
|
||||
return splitter_;
|
||||
}
|
||||
|
||||
TimelineView *TimelineAndTrackView::view() const
|
||||
{
|
||||
return view_;
|
||||
return view_;
|
||||
}
|
||||
|
||||
TrackView *TimelineAndTrackView::track_view() const
|
||||
{
|
||||
return track_view_;
|
||||
return track_view_;
|
||||
}
|
||||
|
||||
void TimelineAndTrackView::ViewValueChanged(int v)
|
||||
{
|
||||
track_view_->verticalScrollBar()->setValue(v - view_->verticalScrollBar()->minimum());
|
||||
track_view_->verticalScrollBar()->setValue(
|
||||
v - view_->verticalScrollBar()->minimum());
|
||||
}
|
||||
|
||||
void TimelineAndTrackView::TracksValueChanged(int v)
|
||||
{
|
||||
view_->verticalScrollBar()->setValue(view_->verticalScrollBar()->minimum() + v);
|
||||
view_->verticalScrollBar()->setValue(view_->verticalScrollBar()->minimum() +
|
||||
v);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,32 +27,31 @@
|
||||
#include "view/timelineview.h"
|
||||
#include "trackview/trackview.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class TimelineAndTrackView : public QWidget
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class TimelineAndTrackView : public QWidget {
|
||||
public:
|
||||
TimelineAndTrackView(Qt::Alignment vertical_alignment = Qt::AlignTop,
|
||||
QWidget* parent = nullptr);
|
||||
TimelineAndTrackView(Qt::Alignment vertical_alignment = Qt::AlignTop,
|
||||
QWidget *parent = nullptr);
|
||||
|
||||
QSplitter* splitter() const;
|
||||
QSplitter *splitter() const;
|
||||
|
||||
TimelineView* view() const;
|
||||
TimelineView *view() const;
|
||||
|
||||
TrackView* track_view() const;
|
||||
TrackView *track_view() const;
|
||||
|
||||
private:
|
||||
QSplitter* splitter_;
|
||||
QSplitter *splitter_;
|
||||
|
||||
TimelineView* view_;
|
||||
TimelineView *view_;
|
||||
|
||||
TrackView* track_view_;
|
||||
TrackView *track_view_;
|
||||
|
||||
private slots:
|
||||
void ViewValueChanged(int v);
|
||||
|
||||
void TracksValueChanged(int v);
|
||||
void ViewValueChanged(int v);
|
||||
|
||||
void TracksValueChanged(int v);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,167 +37,173 @@
|
||||
#include "widget/timelinewidget/tool/import.h"
|
||||
#include "widget/timelinewidget/tool/tool.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Full widget for working with TimelineOutput nodes
|
||||
*
|
||||
* Encapsulates TimelineViews, TimeRulers, and scrollbars for a complete widget to manipulate Timelines
|
||||
*/
|
||||
class TimelineWidget : public TimeBasedWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
class TimelineWidget : public TimeBasedWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
TimelineWidget(QWidget* parent = nullptr);
|
||||
TimelineWidget(QWidget *parent = nullptr);
|
||||
|
||||
virtual ~TimelineWidget() override;
|
||||
virtual ~TimelineWidget() override;
|
||||
|
||||
void Clear();
|
||||
void Clear();
|
||||
|
||||
void SelectAll();
|
||||
void SelectAll();
|
||||
|
||||
void DeselectAll();
|
||||
void DeselectAll();
|
||||
|
||||
void RippleToIn();
|
||||
void RippleToIn();
|
||||
|
||||
void RippleToOut();
|
||||
void RippleToOut();
|
||||
|
||||
void EditToIn();
|
||||
void EditToIn();
|
||||
|
||||
void EditToOut();
|
||||
void EditToOut();
|
||||
|
||||
void SplitAtPlayhead();
|
||||
void SplitAtPlayhead();
|
||||
|
||||
void DeleteSelected(bool ripple = false);
|
||||
void DeleteSelected(bool ripple = false);
|
||||
|
||||
void IncreaseTrackHeight();
|
||||
void IncreaseTrackHeight();
|
||||
|
||||
void DecreaseTrackHeight();
|
||||
void DecreaseTrackHeight();
|
||||
|
||||
void InsertFootageAtPlayhead(const QVector<ViewerOutput *> &footage);
|
||||
void InsertFootageAtPlayhead(const QVector<ViewerOutput *> &footage);
|
||||
|
||||
void OverwriteFootageAtPlayhead(const QVector<ViewerOutput *> &footage);
|
||||
void OverwriteFootageAtPlayhead(const QVector<ViewerOutput *> &footage);
|
||||
|
||||
void ToggleLinksOnSelected();
|
||||
void ToggleLinksOnSelected();
|
||||
|
||||
void AddDefaultTransitionsToSelected();
|
||||
void AddDefaultTransitionsToSelected();
|
||||
|
||||
virtual bool CopySelected(bool cut) override;
|
||||
virtual bool CopySelected(bool cut) override;
|
||||
|
||||
virtual bool Paste() override;
|
||||
virtual bool Paste() override;
|
||||
|
||||
void PasteInsert();
|
||||
void PasteInsert();
|
||||
|
||||
void DeleteInToOut(bool ripple);
|
||||
void DeleteInToOut(bool ripple);
|
||||
|
||||
void ToggleSelectedEnabled();
|
||||
void ToggleSelectedEnabled();
|
||||
|
||||
void SetColorLabel(int index);
|
||||
void SetColorLabel(int index);
|
||||
|
||||
void NudgeLeft();
|
||||
void NudgeLeft();
|
||||
|
||||
void NudgeRight();
|
||||
void NudgeRight();
|
||||
|
||||
void MoveInToPlayhead();
|
||||
void MoveInToPlayhead();
|
||||
|
||||
void MoveOutToPlayhead();
|
||||
void MoveOutToPlayhead();
|
||||
|
||||
void ShowSpeedDurationDialogForSelectedClips();
|
||||
void ShowSpeedDurationDialogForSelectedClips();
|
||||
|
||||
void RecordingCallback(const QString &filename, const TimeRange &time, const Track::Reference &track);
|
||||
void RecordingCallback(const QString &filename, const TimeRange &time,
|
||||
const Track::Reference &track);
|
||||
|
||||
void EnableRecordingOverlay(const TimelineCoordinate &coord);
|
||||
void EnableRecordingOverlay(const TimelineCoordinate &coord);
|
||||
|
||||
void DisableRecordingOverlay();
|
||||
void DisableRecordingOverlay();
|
||||
|
||||
void AddTentativeSubtitleTrack();
|
||||
void AddTentativeSubtitleTrack();
|
||||
|
||||
void NestSelectedClips();
|
||||
void NestSelectedClips();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Timelines should always be connected to sequences
|
||||
*/
|
||||
Sequence* sequence() const
|
||||
{
|
||||
return static_cast<Sequence*>(GetConnectedNode());
|
||||
}
|
||||
Sequence *sequence() const
|
||||
{
|
||||
return static_cast<Sequence *>(GetConnectedNode());
|
||||
}
|
||||
|
||||
const QVector<Block*>& GetSelectedBlocks() const
|
||||
{
|
||||
return selected_blocks_;
|
||||
}
|
||||
const QVector<Block *> &GetSelectedBlocks() const
|
||||
{
|
||||
return selected_blocks_;
|
||||
}
|
||||
|
||||
QByteArray SaveSplitterState() const;
|
||||
QByteArray SaveSplitterState() const;
|
||||
|
||||
void RestoreSplitterState(const QByteArray& state);
|
||||
void RestoreSplitterState(const QByteArray &state);
|
||||
|
||||
static void ReplaceBlocksWithGaps(const QVector<Block *> &blocks, bool remove_from_graph, MultiUndoCommand *command, bool handle_transitions = true);
|
||||
static void ReplaceBlocksWithGaps(const QVector<Block *> &blocks,
|
||||
bool remove_from_graph,
|
||||
MultiUndoCommand *command,
|
||||
bool handle_transitions = true);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Retrieve the QGraphicsItem at a particular scene position
|
||||
*
|
||||
* Requires a float-based scene position. If you have a screen position, use GetScenePos() first to convert it to a
|
||||
* scene position
|
||||
*/
|
||||
Block* GetItemAtScenePos(const TimelineCoordinate &coord);
|
||||
Block *GetItemAtScenePos(const TimelineCoordinate &coord);
|
||||
|
||||
void AddSelection(const TimeRange& time, const Track::Reference& track);
|
||||
void AddSelection(Block* item);
|
||||
void AddSelection(const TimeRange &time, const Track::Reference &track);
|
||||
void AddSelection(Block *item);
|
||||
|
||||
void RemoveSelection(const TimeRange& time, const Track::Reference& track);
|
||||
void RemoveSelection(Block* item);
|
||||
void RemoveSelection(const TimeRange &time, const Track::Reference &track);
|
||||
void RemoveSelection(Block *item);
|
||||
|
||||
const TimelineWidgetSelections& GetSelections() const
|
||||
{
|
||||
return selections_;
|
||||
}
|
||||
const TimelineWidgetSelections &GetSelections() const
|
||||
{
|
||||
return selections_;
|
||||
}
|
||||
|
||||
void SetSelections(const TimelineWidgetSelections &s, bool process_block_changes);
|
||||
void SetSelections(const TimelineWidgetSelections &s,
|
||||
bool process_block_changes);
|
||||
|
||||
Track* GetTrackFromReference(const Track::Reference& ref) const;
|
||||
Track *GetTrackFromReference(const Track::Reference &ref) const;
|
||||
|
||||
void SetViewBeamCursor(const TimelineCoordinate& coord);
|
||||
void SetViewTransitionOverlay(ClipBlock *out, ClipBlock *in);
|
||||
void SetViewBeamCursor(const TimelineCoordinate &coord);
|
||||
void SetViewTransitionOverlay(ClipBlock *out, ClipBlock *in);
|
||||
|
||||
const QVector<TimelineViewGhostItem*>& GetGhostItems() const
|
||||
{
|
||||
return ghost_items_;
|
||||
}
|
||||
const QVector<TimelineViewGhostItem *> &GetGhostItems() const
|
||||
{
|
||||
return ghost_items_;
|
||||
}
|
||||
|
||||
void InsertGapsAt(const rational& time, const rational& length, MultiUndoCommand *command);
|
||||
void InsertGapsAt(const rational &time, const rational &length,
|
||||
MultiUndoCommand *command);
|
||||
|
||||
void StartRubberBandSelect(const QPoint& global_cursor_start);
|
||||
void MoveRubberBandSelect(bool enable_selecting, bool select_links);
|
||||
void EndRubberBandSelect();
|
||||
void StartRubberBandSelect(const QPoint &global_cursor_start);
|
||||
void MoveRubberBandSelect(bool enable_selecting, bool select_links);
|
||||
void EndRubberBandSelect();
|
||||
|
||||
int GetTrackY(const Track::Reference& ref);
|
||||
int GetTrackHeight(const Track::Reference& ref);
|
||||
int GetTrackY(const Track::Reference &ref);
|
||||
int GetTrackHeight(const Track::Reference &ref);
|
||||
|
||||
void AddGhost(TimelineViewGhostItem* ghost);
|
||||
void AddGhost(TimelineViewGhostItem *ghost);
|
||||
|
||||
void ClearGhosts();
|
||||
void ClearGhosts();
|
||||
|
||||
bool HasGhosts() const
|
||||
{
|
||||
return !ghost_items_.isEmpty();
|
||||
}
|
||||
bool HasGhosts() const
|
||||
{
|
||||
return !ghost_items_.isEmpty();
|
||||
}
|
||||
|
||||
bool IsBlockSelected(Block* b) const
|
||||
{
|
||||
return selected_blocks_.contains(b);
|
||||
}
|
||||
bool IsBlockSelected(Block *b) const
|
||||
{
|
||||
return selected_blocks_.contains(b);
|
||||
}
|
||||
|
||||
void SetBlockLinksSelected(ClipBlock *block, bool selected);
|
||||
void SetBlockLinksSelected(ClipBlock *block, bool selected);
|
||||
|
||||
void QueueScroll(int value);
|
||||
void QueueScroll(int value);
|
||||
|
||||
TimelineView* GetFirstTimelineView();
|
||||
TimelineView *GetFirstTimelineView();
|
||||
|
||||
rational GetTimebaseForTrackType(Track::Type type);
|
||||
rational GetTimebaseForTrackType(Track::Type type);
|
||||
|
||||
const QRect &GetRubberBandGeometry() const;
|
||||
const QRect &GetRubberBandGeometry() const;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Track blocks that have newly been selected (this is preferred over emitting BlocksSelected directly)
|
||||
*
|
||||
* TimelineWidget keeps track of which blocks are selected internally. Calling this function will
|
||||
@@ -213,243 +219,253 @@ public:
|
||||
* this is preferable and should only be set to FALSE if the list is guaranteed not to contain
|
||||
* already selected blocks (and therefore filtering can be skipped to save time).
|
||||
*/
|
||||
void SignalSelectedBlocks(QVector<Block *> selected_blocks, bool filter = true);
|
||||
void SignalSelectedBlocks(QVector<Block *> selected_blocks,
|
||||
bool filter = true);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Track blocks that have been newly deselected
|
||||
*/
|
||||
void SignalDeselectedBlocks(const QVector<Block *> &deselected_blocks);
|
||||
void SignalDeselectedBlocks(const QVector<Block *> &deselected_blocks);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Convenience function to deselect all blocks and signal them
|
||||
*/
|
||||
void SignalDeselectedAllBlocks();
|
||||
void SignalDeselectedAllBlocks();
|
||||
|
||||
void Refresh()
|
||||
{
|
||||
UpdateViewports();
|
||||
}
|
||||
void Refresh()
|
||||
{
|
||||
UpdateViewports();
|
||||
}
|
||||
|
||||
MultiUndoCommand *TakeSubtitleSectionCommand()
|
||||
{
|
||||
// Copy pointer
|
||||
MultiUndoCommand *c = subtitle_show_command_;
|
||||
MultiUndoCommand *TakeSubtitleSectionCommand()
|
||||
{
|
||||
// Copy pointer
|
||||
MultiUndoCommand *c = subtitle_show_command_;
|
||||
|
||||
// Set to null
|
||||
subtitle_show_command_ = nullptr;
|
||||
subtitle_tentative_track_ = nullptr;
|
||||
// Set to null
|
||||
subtitle_show_command_ = nullptr;
|
||||
subtitle_tentative_track_ = nullptr;
|
||||
|
||||
// Return command
|
||||
return c;
|
||||
}
|
||||
// Return command
|
||||
return c;
|
||||
}
|
||||
|
||||
class SetSelectionsCommand : public UndoCommand {
|
||||
public:
|
||||
SetSelectionsCommand(TimelineWidget* timeline, const TimelineWidgetSelections& now, const TimelineWidgetSelections& old, bool process_block_changes = true) :
|
||||
timeline_(timeline),
|
||||
old_(old),
|
||||
now_(now),
|
||||
process_block_changes_(process_block_changes)
|
||||
{
|
||||
}
|
||||
class SetSelectionsCommand : public UndoCommand {
|
||||
public:
|
||||
SetSelectionsCommand(TimelineWidget *timeline,
|
||||
const TimelineWidgetSelections &now,
|
||||
const TimelineWidgetSelections &old,
|
||||
bool process_block_changes = true)
|
||||
: timeline_(timeline)
|
||||
, old_(old)
|
||||
, now_(now)
|
||||
, process_block_changes_(process_block_changes)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override {return nullptr;}
|
||||
virtual Project *GetRelevantProject() const override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo() override
|
||||
{
|
||||
timeline_->SetSelections(now_, process_block_changes_);
|
||||
}
|
||||
protected:
|
||||
virtual void redo() override
|
||||
{
|
||||
timeline_->SetSelections(now_, process_block_changes_);
|
||||
}
|
||||
|
||||
virtual void undo() override
|
||||
{
|
||||
timeline_->SetSelections(old_, process_block_changes_);
|
||||
}
|
||||
virtual void undo() override
|
||||
{
|
||||
timeline_->SetSelections(old_, process_block_changes_);
|
||||
}
|
||||
|
||||
private:
|
||||
TimelineWidget* timeline_;
|
||||
TimelineWidgetSelections old_;
|
||||
TimelineWidgetSelections now_;
|
||||
bool process_block_changes_;
|
||||
|
||||
};
|
||||
private:
|
||||
TimelineWidget *timeline_;
|
||||
TimelineWidgetSelections old_;
|
||||
TimelineWidgetSelections now_;
|
||||
bool process_block_changes_;
|
||||
};
|
||||
|
||||
public slots:
|
||||
void ClearTentativeSubtitleTrack();
|
||||
void ClearTentativeSubtitleTrack();
|
||||
|
||||
void RenameSelectedBlocks();
|
||||
void RenameSelectedBlocks();
|
||||
|
||||
signals:
|
||||
void BlockSelectionChanged(const QVector<Block*>& selected_blocks);
|
||||
void BlockSelectionChanged(const QVector<Block *> &selected_blocks);
|
||||
|
||||
void RequestCaptureStart(const TimeRange &time, const Track::Reference &track);
|
||||
void RequestCaptureStart(const TimeRange &time,
|
||||
const Track::Reference &track);
|
||||
|
||||
void RevealViewerInFootageViewer(ViewerOutput *r, const TimeRange &range);
|
||||
void RevealViewerInProject(ViewerOutput *r);
|
||||
void RevealViewerInFootageViewer(ViewerOutput *r, const TimeRange &range);
|
||||
void RevealViewerInProject(ViewerOutput *r);
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
virtual void TimeChangedEvent(const rational &) override;
|
||||
virtual void TimebaseChangedEvent(const rational &) override;
|
||||
virtual void ScaleChangedEvent(const double &) override;
|
||||
virtual void TimeChangedEvent(const rational &) override;
|
||||
virtual void TimebaseChangedEvent(const rational &) override;
|
||||
virtual void ScaleChangedEvent(const double &) override;
|
||||
|
||||
virtual void ConnectNodeEvent(ViewerOutput* n) override;
|
||||
virtual void DisconnectNodeEvent(ViewerOutput* n) override;
|
||||
virtual void ConnectNodeEvent(ViewerOutput *n) override;
|
||||
virtual void DisconnectNodeEvent(ViewerOutput *n) override;
|
||||
|
||||
virtual const QVector<Block*> *GetSnapBlocks() const override { return &added_blocks_; }
|
||||
virtual const QVector<Block *> *GetSnapBlocks() const override
|
||||
{
|
||||
return &added_blocks_;
|
||||
}
|
||||
|
||||
protected slots:
|
||||
virtual void SendCatchUpScrollEvent() override;
|
||||
virtual void SendCatchUpScrollEvent() override;
|
||||
|
||||
private:
|
||||
QVector<Timeline::EditToInfo> GetEditToInfo(const rational &playhead_time, Timeline::MovementMode mode);
|
||||
QVector<Timeline::EditToInfo> GetEditToInfo(const rational &playhead_time,
|
||||
Timeline::MovementMode mode);
|
||||
|
||||
void RippleTo(Timeline::MovementMode mode);
|
||||
void RippleTo(Timeline::MovementMode mode);
|
||||
|
||||
void EditTo(Timeline::MovementMode mode);
|
||||
void EditTo(Timeline::MovementMode mode);
|
||||
|
||||
void UpdateViewports(const Track::Type& type = Track::kNone);
|
||||
void UpdateViewports(const Track::Type &type = Track::kNone);
|
||||
|
||||
bool PasteInternal(bool insert);
|
||||
bool PasteInternal(bool insert);
|
||||
|
||||
TimelineAndTrackView *AddTimelineAndTrackView(Qt::Alignment alignment);
|
||||
TimelineAndTrackView *AddTimelineAndTrackView(Qt::Alignment alignment);
|
||||
|
||||
QHash<Node*, Node*> GenerateExistingPasteMap(const ProjectSerializer::Result &r);
|
||||
QHash<Node *, Node *>
|
||||
GenerateExistingPasteMap(const ProjectSerializer::Result &r);
|
||||
|
||||
QRubberBand rubberband_;
|
||||
QVector<QPointF> rubberband_scene_pos_;
|
||||
TimelineWidgetSelections rubberband_old_selections_;
|
||||
QVector<Block*> rubberband_now_selected_;
|
||||
bool rubberband_enable_selecting_;
|
||||
bool rubberband_select_links_;
|
||||
QRubberBand rubberband_;
|
||||
QVector<QPointF> rubberband_scene_pos_;
|
||||
TimelineWidgetSelections rubberband_old_selections_;
|
||||
QVector<Block *> rubberband_now_selected_;
|
||||
bool rubberband_enable_selecting_;
|
||||
bool rubberband_select_links_;
|
||||
|
||||
TimelineWidgetSelections selections_;
|
||||
TimelineWidgetSelections selections_;
|
||||
|
||||
TimelineTool* GetActiveTool();
|
||||
TimelineTool *GetActiveTool();
|
||||
|
||||
QVector<TimelineTool*> tools_;
|
||||
QVector<TimelineTool *> tools_;
|
||||
|
||||
ImportTool* import_tool_;
|
||||
ImportTool *import_tool_;
|
||||
|
||||
TimelineTool* active_tool_;
|
||||
TimelineTool *active_tool_;
|
||||
|
||||
QVector<TimelineViewGhostItem*> ghost_items_;
|
||||
QVector<TimelineViewGhostItem *> ghost_items_;
|
||||
|
||||
QVector<TimelineAndTrackView*> views_;
|
||||
QVector<TimelineAndTrackView *> views_;
|
||||
|
||||
RationalSlider* timecode_label_;
|
||||
RationalSlider *timecode_label_;
|
||||
|
||||
QVector<Block*> selected_blocks_;
|
||||
QVector<Block *> selected_blocks_;
|
||||
|
||||
QVector<Block*> added_blocks_;
|
||||
QVector<Block *> added_blocks_;
|
||||
|
||||
int deferred_scroll_value_;
|
||||
int deferred_scroll_value_;
|
||||
|
||||
bool use_audio_time_units_;
|
||||
bool use_audio_time_units_;
|
||||
|
||||
QSplitter* view_splitter_;
|
||||
QSplitter *view_splitter_;
|
||||
|
||||
MultiUndoCommand *subtitle_show_command_;
|
||||
Track *subtitle_tentative_track_;
|
||||
MultiUndoCommand *subtitle_show_command_;
|
||||
Track *subtitle_tentative_track_;
|
||||
|
||||
QTimer *signal_block_change_timer_;
|
||||
QTimer *signal_block_change_timer_;
|
||||
|
||||
class SetSplitterSizesCommand : public UndoCommand
|
||||
{
|
||||
public:
|
||||
SetSplitterSizesCommand(QSplitter *splitter, const QList<int> &sizes) :
|
||||
splitter_(splitter),
|
||||
new_sizes_(sizes)
|
||||
{}
|
||||
class SetSplitterSizesCommand : public UndoCommand {
|
||||
public:
|
||||
SetSplitterSizesCommand(QSplitter *splitter, const QList<int> &sizes)
|
||||
: splitter_(splitter)
|
||||
, new_sizes_(sizes)
|
||||
{
|
||||
}
|
||||
|
||||
virtual Project* GetRelevantProject() const override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
virtual Project *GetRelevantProject() const override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
QSplitter *splitter_;
|
||||
QList<int> new_sizes_;
|
||||
QList<int> old_sizes_;
|
||||
private:
|
||||
QSplitter *splitter_;
|
||||
QList<int> new_sizes_;
|
||||
QList<int> old_sizes_;
|
||||
};
|
||||
|
||||
};
|
||||
void CenterOn(qreal scene_pos);
|
||||
|
||||
void CenterOn(qreal scene_pos);
|
||||
void UpdateViewTimebases();
|
||||
|
||||
void UpdateViewTimebases();
|
||||
void NudgeInternal(rational amount);
|
||||
|
||||
void NudgeInternal(rational amount);
|
||||
|
||||
void MoveToPlayheadInternal(bool out);
|
||||
void MoveToPlayheadInternal(bool out);
|
||||
|
||||
private slots:
|
||||
void ViewMousePressed(TimelineViewMouseEvent* event);
|
||||
void ViewMouseMoved(TimelineViewMouseEvent* event);
|
||||
void ViewMouseReleased(TimelineViewMouseEvent* event);
|
||||
void ViewMouseDoubleClicked(TimelineViewMouseEvent* event);
|
||||
void ViewMousePressed(TimelineViewMouseEvent *event);
|
||||
void ViewMouseMoved(TimelineViewMouseEvent *event);
|
||||
void ViewMouseReleased(TimelineViewMouseEvent *event);
|
||||
void ViewMouseDoubleClicked(TimelineViewMouseEvent *event);
|
||||
|
||||
void ViewDragEntered(TimelineViewMouseEvent* event);
|
||||
void ViewDragMoved(TimelineViewMouseEvent* event);
|
||||
void ViewDragLeft(QDragLeaveEvent* event);
|
||||
void ViewDragDropped(TimelineViewMouseEvent* event);
|
||||
void ViewDragEntered(TimelineViewMouseEvent *event);
|
||||
void ViewDragMoved(TimelineViewMouseEvent *event);
|
||||
void ViewDragLeft(QDragLeaveEvent *event);
|
||||
void ViewDragDropped(TimelineViewMouseEvent *event);
|
||||
|
||||
void AddBlock(Block* block);
|
||||
void RemoveBlock(Block *blocks);
|
||||
void AddBlock(Block *block);
|
||||
void RemoveBlock(Block *blocks);
|
||||
|
||||
void AddTrack(Track* track);
|
||||
void RemoveTrack(Track* track);
|
||||
void TrackUpdated();
|
||||
void AddTrack(Track *track);
|
||||
void RemoveTrack(Track *track);
|
||||
void TrackUpdated();
|
||||
|
||||
void BlockUpdated();
|
||||
void BlockUpdated();
|
||||
|
||||
void UpdateHorizontalSplitters();
|
||||
void UpdateHorizontalSplitters();
|
||||
|
||||
void UpdateTimecodeWidthFromSplitters(QSplitter *s);
|
||||
void UpdateTimecodeWidthFromSplitters(QSplitter *s);
|
||||
|
||||
void ShowContextMenu();
|
||||
void ShowContextMenu();
|
||||
|
||||
void DeferredScrollAction();
|
||||
void DeferredScrollAction();
|
||||
|
||||
void ShowSequenceDialog();
|
||||
void ShowSequenceDialog();
|
||||
|
||||
void SetUseAudioTimeUnits(bool use);
|
||||
void SetUseAudioTimeUnits(bool use);
|
||||
|
||||
void ToolChanged();
|
||||
void ToolChanged();
|
||||
|
||||
void AddableObjectChanged();
|
||||
void AddableObjectChanged();
|
||||
|
||||
void SetViewWaveformsEnabled(bool e);
|
||||
void SetViewWaveformsEnabled(bool e);
|
||||
|
||||
void SetViewThumbnailsEnabled(QAction *action);
|
||||
void SetViewThumbnailsEnabled(QAction *action);
|
||||
|
||||
void FrameRateChanged();
|
||||
void FrameRateChanged();
|
||||
|
||||
void SampleRateChanged();
|
||||
void SampleRateChanged();
|
||||
|
||||
void TrackIndexChanged(int old, int now);
|
||||
void TrackIndexChanged(int old, int now);
|
||||
|
||||
void SignalBlockSelectionChange();
|
||||
void SignalBlockSelectionChange();
|
||||
|
||||
void RevealInFootageViewer();
|
||||
void RevealInProject();
|
||||
void RevealInFootageViewer();
|
||||
void RevealInProject();
|
||||
|
||||
void TrackAboutToBeDeleted(Track *track);
|
||||
void TrackAboutToBeDeleted(Track *track);
|
||||
|
||||
void SetSelectedClipsAutocaching(bool e);
|
||||
void SetSelectedClipsAutocaching(bool e);
|
||||
|
||||
void CacheClips();
|
||||
void CacheClipsInOut();
|
||||
void CacheDiscard();
|
||||
void CacheClips();
|
||||
void CacheClipsInOut();
|
||||
void CacheDiscard();
|
||||
|
||||
void MulticamEnabledTriggered(bool e);
|
||||
|
||||
void ForceUpdateRubberBand();
|
||||
void MulticamEnabledTriggered(bool e);
|
||||
|
||||
void ForceUpdateRubberBand();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -20,65 +20,68 @@
|
||||
|
||||
#include "timelinewidgetselections.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
void TimelineWidgetSelections::ShiftTime(const rational &diff)
|
||||
{
|
||||
for (auto it=this->begin(); it!=this->end(); it++) {
|
||||
it.value().shift(diff);
|
||||
}
|
||||
for (auto it = this->begin(); it != this->end(); it++) {
|
||||
it.value().shift(diff);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidgetSelections::ShiftTracks(Track::Type type, int diff)
|
||||
{
|
||||
TimelineWidgetSelections cached_selections;
|
||||
TimelineWidgetSelections cached_selections;
|
||||
|
||||
{
|
||||
// Take all selections of this track type
|
||||
auto it = this->begin();
|
||||
while (it != this->end()) {
|
||||
if (it.key().type() == type) {
|
||||
cached_selections.insert(it.key(), it.value());
|
||||
it = this->erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
// Take all selections of this track type
|
||||
auto it = this->begin();
|
||||
while (it != this->end()) {
|
||||
if (it.key().type() == type) {
|
||||
cached_selections.insert(it.key(), it.value());
|
||||
it = this->erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then re-insert them with the diff applied
|
||||
for (auto it=cached_selections.cbegin(); it!=cached_selections.cend(); it++) {
|
||||
Track::Reference ref(it.key().type(), it.key().index() + diff);
|
||||
// Then re-insert them with the diff applied
|
||||
for (auto it = cached_selections.cbegin(); it != cached_selections.cend();
|
||||
it++) {
|
||||
Track::Reference ref(it.key().type(), it.key().index() + diff);
|
||||
|
||||
this->insert(ref, it.value());
|
||||
}
|
||||
this->insert(ref, it.value());
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidgetSelections::TrimIn(const rational &diff)
|
||||
{
|
||||
for (auto it=this->begin(); it!=this->end(); it++) {
|
||||
it.value().trim_in(diff);
|
||||
}
|
||||
for (auto it = this->begin(); it != this->end(); it++) {
|
||||
it.value().trim_in(diff);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidgetSelections::TrimOut(const rational &diff)
|
||||
{
|
||||
for (auto it=this->begin(); it!=this->end(); it++) {
|
||||
it.value().trim_out(diff);
|
||||
}
|
||||
for (auto it = this->begin(); it != this->end(); it++) {
|
||||
it.value().trim_out(diff);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidgetSelections::Subtract(const TimelineWidgetSelections &selections)
|
||||
void TimelineWidgetSelections::Subtract(
|
||||
const TimelineWidgetSelections &selections)
|
||||
{
|
||||
for (auto it=selections.cbegin(); it!=selections.cend(); it++) {
|
||||
const Track::Reference &track = it.key();
|
||||
const TimeRangeList &their_list = it.value();
|
||||
for (auto it = selections.cbegin(); it != selections.cend(); it++) {
|
||||
const Track::Reference &track = it.key();
|
||||
const TimeRangeList &their_list = it.value();
|
||||
|
||||
if (this->contains(track)) {
|
||||
TimeRangeList &our_list = (*this)[it.key()];
|
||||
our_list.remove(their_list);
|
||||
}
|
||||
}
|
||||
if (this->contains(track)) {
|
||||
TimeRangeList &our_list = (*this)[it.key()];
|
||||
our_list.remove(their_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,30 +25,30 @@
|
||||
|
||||
#include "node/output/track/track.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class TimelineWidgetSelections : public QHash<Track::Reference, TimeRangeList>
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class TimelineWidgetSelections : public QHash<Track::Reference, TimeRangeList> {
|
||||
public:
|
||||
TimelineWidgetSelections() = default;
|
||||
TimelineWidgetSelections() = default;
|
||||
|
||||
void ShiftTime(const rational& diff);
|
||||
void ShiftTime(const rational &diff);
|
||||
|
||||
void ShiftTracks(Track::Type type, int diff);
|
||||
void ShiftTracks(Track::Type type, int diff);
|
||||
|
||||
void TrimIn(const rational& diff);
|
||||
void TrimIn(const rational &diff);
|
||||
|
||||
void TrimOut(const rational& diff);
|
||||
void TrimOut(const rational &diff);
|
||||
|
||||
void Subtract(const TimelineWidgetSelections &selections);
|
||||
|
||||
TimelineWidgetSelections Subtracted(const TimelineWidgetSelections &selections) const
|
||||
{
|
||||
TimelineWidgetSelections copy = *this;
|
||||
copy.Subtract(selections);
|
||||
return copy;
|
||||
}
|
||||
void Subtract(const TimelineWidgetSelections &selections);
|
||||
|
||||
TimelineWidgetSelections
|
||||
Subtracted(const TimelineWidgetSelections &selections) const
|
||||
{
|
||||
TimelineWidgetSelections copy = *this;
|
||||
copy.Subtract(selections);
|
||||
return copy;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -29,202 +29,218 @@
|
||||
#include "timeline/timelineundopointer.h"
|
||||
#include "widget/timelinewidget/timelinewidget.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
AddTool::AddTool(TimelineWidget *parent) :
|
||||
BeamTool(parent),
|
||||
ghost_(nullptr)
|
||||
AddTool::AddTool(TimelineWidget *parent)
|
||||
: BeamTool(parent)
|
||||
, ghost_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void AddTool::MousePress(TimelineViewMouseEvent *event)
|
||||
{
|
||||
const Track::Reference& track = event->GetTrack();
|
||||
const Track::Reference &track = event->GetTrack();
|
||||
|
||||
// Check if track is locked
|
||||
Track* t = parent()->GetTrackFromReference(track);
|
||||
if (t && t->IsLocked()) {
|
||||
return;
|
||||
}
|
||||
// Check if track is locked
|
||||
Track *t = parent()->GetTrackFromReference(track);
|
||||
if (t && t->IsLocked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Track::Type add_type = Track::kNone;
|
||||
Track::Type add_type = Track::kNone;
|
||||
|
||||
switch (Core::instance()->GetSelectedAddableObject()) {
|
||||
case Tool::kAddableBars:
|
||||
case Tool::kAddableSolid:
|
||||
case Tool::kAddableTitle:
|
||||
case Tool::kAddableShape:
|
||||
add_type = Track::kVideo;
|
||||
break;
|
||||
case Tool::kAddableTone:
|
||||
add_type = Track::kAudio;
|
||||
break;
|
||||
case Tool::kAddableSubtitle:
|
||||
add_type = Track::kSubtitle;
|
||||
break;
|
||||
case Tool::kAddableEmpty:
|
||||
// Leave as "none", which means this block can be placed on any track
|
||||
break;
|
||||
case Tool::kAddableCount:
|
||||
// Return so we do nothing
|
||||
return;
|
||||
}
|
||||
switch (Core::instance()->GetSelectedAddableObject()) {
|
||||
case Tool::kAddableBars:
|
||||
case Tool::kAddableSolid:
|
||||
case Tool::kAddableTitle:
|
||||
case Tool::kAddableShape:
|
||||
add_type = Track::kVideo;
|
||||
break;
|
||||
case Tool::kAddableTone:
|
||||
add_type = Track::kAudio;
|
||||
break;
|
||||
case Tool::kAddableSubtitle:
|
||||
add_type = Track::kSubtitle;
|
||||
break;
|
||||
case Tool::kAddableEmpty:
|
||||
// Leave as "none", which means this block can be placed on any track
|
||||
break;
|
||||
case Tool::kAddableCount:
|
||||
// Return so we do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
if (add_type == Track::kNone
|
||||
|| add_type == track.type()) {
|
||||
drag_start_point_ = ValidatedCoordinate(event->GetCoordinates(true)).GetFrame();
|
||||
if (add_type == Track::kNone || add_type == track.type()) {
|
||||
drag_start_point_ =
|
||||
ValidatedCoordinate(event->GetCoordinates(true)).GetFrame();
|
||||
|
||||
ghost_ = new TimelineViewGhostItem();
|
||||
ghost_->SetIn(drag_start_point_);
|
||||
ghost_->SetOut(drag_start_point_);
|
||||
ghost_->SetTrack(track);
|
||||
parent()->AddGhost(ghost_);
|
||||
ghost_ = new TimelineViewGhostItem();
|
||||
ghost_->SetIn(drag_start_point_);
|
||||
ghost_->SetOut(drag_start_point_);
|
||||
ghost_->SetTrack(track);
|
||||
parent()->AddGhost(ghost_);
|
||||
|
||||
snap_points_.push_back(drag_start_point_);
|
||||
}
|
||||
snap_points_.push_back(drag_start_point_);
|
||||
}
|
||||
}
|
||||
|
||||
void AddTool::MouseMove(TimelineViewMouseEvent *event)
|
||||
{
|
||||
if (!ghost_) {
|
||||
return;
|
||||
}
|
||||
if (!ghost_) {
|
||||
return;
|
||||
}
|
||||
|
||||
MouseMoveInternal(event->GetFrame(), event->GetModifiers() & Qt::AltModifier);
|
||||
MouseMoveInternal(event->GetFrame(),
|
||||
event->GetModifiers() & Qt::AltModifier);
|
||||
}
|
||||
|
||||
void AddTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
{
|
||||
if (ghost_) {
|
||||
if (!ghost_->GetAdjustedLength().isNull()) {
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
if (ghost_) {
|
||||
if (!ghost_->GetAdjustedLength().isNull()) {
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
if (MultiUndoCommand *subtitle_section_command = parent()->TakeSubtitleSectionCommand()) {
|
||||
command->add_child(subtitle_section_command);
|
||||
}
|
||||
if (MultiUndoCommand *subtitle_section_command =
|
||||
parent()->TakeSubtitleSectionCommand()) {
|
||||
command->add_child(subtitle_section_command);
|
||||
}
|
||||
|
||||
Sequence *s = parent()->sequence();
|
||||
Sequence *s = parent()->sequence();
|
||||
|
||||
QRectF r;
|
||||
if (Core::instance()->GetSelectedAddableObject() == Tool::kAddableTitle) {
|
||||
VideoParams svp = s->GetVideoParams();
|
||||
r = QRectF(0, 0, svp.width(), svp.height());
|
||||
r.adjust(svp.width()/10, svp.height()/10, -svp.width()/10, -svp.height()/10);
|
||||
}
|
||||
QRectF r;
|
||||
if (Core::instance()->GetSelectedAddableObject() ==
|
||||
Tool::kAddableTitle) {
|
||||
VideoParams svp = s->GetVideoParams();
|
||||
r = QRectF(0, 0, svp.width(), svp.height());
|
||||
r.adjust(svp.width() / 10, svp.height() / 10, -svp.width() / 10,
|
||||
-svp.height() / 10);
|
||||
}
|
||||
|
||||
CreateAddableClip(command, s, ghost_->GetTrack(), ghost_->GetAdjustedIn(), ghost_->GetAdjustedLength(), r);
|
||||
CreateAddableClip(command, s, ghost_->GetTrack(),
|
||||
ghost_->GetAdjustedIn(),
|
||||
ghost_->GetAdjustedLength(), r);
|
||||
|
||||
Core::instance()->undo_stack()->push(command, qApp->translate("AddTool", "Added Clip"));
|
||||
}
|
||||
Core::instance()->undo_stack()->push(
|
||||
command, qApp->translate("AddTool", "Added Clip"));
|
||||
}
|
||||
|
||||
parent()->ClearGhosts();
|
||||
snap_points_.clear();
|
||||
ghost_ = nullptr;
|
||||
}
|
||||
parent()->ClearGhosts();
|
||||
snap_points_.clear();
|
||||
ghost_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Node *AddTool::CreateAddableClip(MultiUndoCommand *command, Sequence *sequence, const Track::Reference &track, const rational &in, const rational &length, const QRectF &rect)
|
||||
Node *AddTool::CreateAddableClip(MultiUndoCommand *command, Sequence *sequence,
|
||||
const Track::Reference &track,
|
||||
const rational &in, const rational &length,
|
||||
const QRectF &rect)
|
||||
{
|
||||
ClipBlock* clip;
|
||||
if (Core::instance()->GetSelectedAddableObject() == Tool::kAddableSubtitle) {
|
||||
clip = new SubtitleBlock();
|
||||
} else {
|
||||
clip = new ClipBlock();
|
||||
clip->SetLabel(olive::Tool::GetAddableObjectName(Core::instance()->GetSelectedAddableObject()));
|
||||
}
|
||||
clip->set_length_and_media_out(length);
|
||||
ClipBlock *clip;
|
||||
if (Core::instance()->GetSelectedAddableObject() ==
|
||||
Tool::kAddableSubtitle) {
|
||||
clip = new SubtitleBlock();
|
||||
} else {
|
||||
clip = new ClipBlock();
|
||||
clip->SetLabel(olive::Tool::GetAddableObjectName(
|
||||
Core::instance()->GetSelectedAddableObject()));
|
||||
}
|
||||
clip->set_length_and_media_out(length);
|
||||
|
||||
Project* graph = sequence->parent();
|
||||
Project *graph = sequence->parent();
|
||||
|
||||
command->add_child(new NodeAddCommand(graph, clip));
|
||||
command->add_child(new NodeSetPositionCommand(clip, clip, QPointF(0, 0)));
|
||||
command->add_child(new TrackPlaceBlockCommand(sequence->track_list(track.type()),
|
||||
track.index(),
|
||||
clip,
|
||||
in));
|
||||
command->add_child(new NodeAddCommand(graph, clip));
|
||||
command->add_child(new NodeSetPositionCommand(clip, clip, QPointF(0, 0)));
|
||||
command->add_child(new TrackPlaceBlockCommand(
|
||||
sequence->track_list(track.type()), track.index(), clip, in));
|
||||
|
||||
Node *node_to_add = nullptr;
|
||||
Node *node_to_add = nullptr;
|
||||
|
||||
switch (Core::instance()->GetSelectedAddableObject()) {
|
||||
case Tool::kAddableEmpty:
|
||||
// Empty, nothing to be done
|
||||
break;
|
||||
case Tool::kAddableSolid:
|
||||
node_to_add = new SolidGenerator();
|
||||
break;
|
||||
case Tool::kAddableShape:
|
||||
node_to_add = new ShapeNode();
|
||||
break;
|
||||
case Tool::kAddableTitle:
|
||||
node_to_add = new TextGeneratorV3();
|
||||
break;
|
||||
case Tool::kAddableBars:
|
||||
case Tool::kAddableTone:
|
||||
// Not implemented yet
|
||||
qWarning() << "Unimplemented add object:" << Core::instance()->GetSelectedAddableObject();
|
||||
break;
|
||||
case Tool::kAddableSubtitle:
|
||||
// The block itself is the node we want
|
||||
break;
|
||||
case Tool::kAddableCount:
|
||||
// Invalid value, do nothing
|
||||
break;
|
||||
}
|
||||
switch (Core::instance()->GetSelectedAddableObject()) {
|
||||
case Tool::kAddableEmpty:
|
||||
// Empty, nothing to be done
|
||||
break;
|
||||
case Tool::kAddableSolid:
|
||||
node_to_add = new SolidGenerator();
|
||||
break;
|
||||
case Tool::kAddableShape:
|
||||
node_to_add = new ShapeNode();
|
||||
break;
|
||||
case Tool::kAddableTitle:
|
||||
node_to_add = new TextGeneratorV3();
|
||||
break;
|
||||
case Tool::kAddableBars:
|
||||
case Tool::kAddableTone:
|
||||
// Not implemented yet
|
||||
qWarning() << "Unimplemented add object:"
|
||||
<< Core::instance()->GetSelectedAddableObject();
|
||||
break;
|
||||
case Tool::kAddableSubtitle:
|
||||
// The block itself is the node we want
|
||||
break;
|
||||
case Tool::kAddableCount:
|
||||
// Invalid value, do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
if (node_to_add) {
|
||||
QPointF extra_node_offset(kDefaultDistanceFromOutput, 0);
|
||||
command->add_child(new NodeAddCommand(graph, node_to_add));
|
||||
command->add_child(new NodeEdgeAddCommand(node_to_add, NodeInput(clip, ClipBlock::kBufferIn)));
|
||||
command->add_child(new NodeSetPositionCommand(node_to_add, clip, extra_node_offset));
|
||||
if (node_to_add) {
|
||||
QPointF extra_node_offset(kDefaultDistanceFromOutput, 0);
|
||||
command->add_child(new NodeAddCommand(graph, node_to_add));
|
||||
command->add_child(new NodeEdgeAddCommand(
|
||||
node_to_add, NodeInput(clip, ClipBlock::kBufferIn)));
|
||||
command->add_child(
|
||||
new NodeSetPositionCommand(node_to_add, clip, extra_node_offset));
|
||||
|
||||
if (!rect.isNull()) {
|
||||
if (ShapeNodeBase *shape = dynamic_cast<ShapeNodeBase*>(node_to_add)) {
|
||||
shape->SetRect(rect, sequence->GetVideoParams(), command);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!rect.isNull()) {
|
||||
if (ShapeNodeBase *shape =
|
||||
dynamic_cast<ShapeNodeBase *>(node_to_add)) {
|
||||
shape->SetRect(rect, sequence->GetVideoParams(), command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return node_to_add;
|
||||
return node_to_add;
|
||||
}
|
||||
|
||||
void AddTool::MouseMoveInternal(const rational &cursor_frame, bool outwards)
|
||||
{
|
||||
// Calculate movement
|
||||
rational movement = cursor_frame - drag_start_point_;
|
||||
// Calculate movement
|
||||
rational movement = cursor_frame - drag_start_point_;
|
||||
|
||||
// Validation: Ensure in point never goes below 0
|
||||
if (movement < -ghost_->GetIn() || (outwards && -movement < -ghost_->GetIn())) {
|
||||
movement = -ghost_->GetIn();
|
||||
}
|
||||
// Validation: Ensure in point never goes below 0
|
||||
if (movement < -ghost_->GetIn() ||
|
||||
(outwards && -movement < -ghost_->GetIn())) {
|
||||
movement = -ghost_->GetIn();
|
||||
}
|
||||
|
||||
// Snap movement
|
||||
bool snapped;
|
||||
// Snap movement
|
||||
bool snapped;
|
||||
|
||||
if (Core::instance()->snapping()) {
|
||||
snapped = parent()->SnapPoint(snap_points_, &movement);
|
||||
} else {
|
||||
snapped = false;
|
||||
}
|
||||
if (Core::instance()->snapping()) {
|
||||
snapped = parent()->SnapPoint(snap_points_, &movement);
|
||||
} else {
|
||||
snapped = false;
|
||||
}
|
||||
|
||||
// If alt is held, our movement goes both ways (outwards)
|
||||
if (!snapped && outwards) {
|
||||
// Snap backwards too
|
||||
movement = -movement;
|
||||
parent()->SnapPoint(snap_points_, &movement);
|
||||
// We don't need to un-neg here because outwards means all future processing will be done both pos and neg
|
||||
}
|
||||
// If alt is held, our movement goes both ways (outwards)
|
||||
if (!snapped && outwards) {
|
||||
// Snap backwards too
|
||||
movement = -movement;
|
||||
parent()->SnapPoint(snap_points_, &movement);
|
||||
// We don't need to un-neg here because outwards means all future processing will be done both pos and neg
|
||||
}
|
||||
|
||||
// Make adjustment
|
||||
if (!movement) {
|
||||
ghost_->SetInAdjustment(0);
|
||||
ghost_->SetOutAdjustment(0);
|
||||
} else if (movement > 0) {
|
||||
ghost_->SetInAdjustment(outwards ? -movement : 0);
|
||||
ghost_->SetOutAdjustment(movement);
|
||||
} else if (movement < 0) {
|
||||
ghost_->SetInAdjustment(movement);
|
||||
ghost_->SetOutAdjustment(outwards ? -movement : 0);
|
||||
}
|
||||
// Make adjustment
|
||||
if (!movement) {
|
||||
ghost_->SetInAdjustment(0);
|
||||
ghost_->SetOutAdjustment(0);
|
||||
} else if (movement > 0) {
|
||||
ghost_->SetInAdjustment(outwards ? -movement : 0);
|
||||
ghost_->SetOutAdjustment(movement);
|
||||
} else if (movement < 0) {
|
||||
ghost_->SetInAdjustment(movement);
|
||||
ghost_->SetOutAdjustment(outwards ? -movement : 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,25 +23,29 @@
|
||||
|
||||
#include "beam.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class AddTool : public BeamTool
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class AddTool : public BeamTool {
|
||||
public:
|
||||
AddTool(TimelineWidget* parent);
|
||||
AddTool(TimelineWidget *parent);
|
||||
|
||||
virtual void MousePress(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
|
||||
virtual void MousePress(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
|
||||
|
||||
static Node *CreateAddableClip(MultiUndoCommand *command, Sequence *sequence, const Track::Reference &track, const rational &in, const rational &length, const QRectF &rect = QRectF());
|
||||
static Node *CreateAddableClip(MultiUndoCommand *command,
|
||||
Sequence *sequence,
|
||||
const Track::Reference &track,
|
||||
const rational &in, const rational &length,
|
||||
const QRectF &rect = QRectF());
|
||||
|
||||
protected:
|
||||
void MouseMoveInternal(const rational& cursor_frame, bool outwards);
|
||||
void MouseMoveInternal(const rational &cursor_frame, bool outwards);
|
||||
|
||||
TimelineViewGhostItem* ghost_;
|
||||
TimelineViewGhostItem *ghost_;
|
||||
|
||||
rational drag_start_point_;
|
||||
rational drag_start_point_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -21,29 +21,31 @@
|
||||
#include "beam.h"
|
||||
#include "widget/timelinewidget/timelinewidget.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
BeamTool::BeamTool(TimelineWidget *parent) :
|
||||
TimelineTool(parent)
|
||||
BeamTool::BeamTool(TimelineWidget *parent)
|
||||
: TimelineTool(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void BeamTool::HoverMove(TimelineViewMouseEvent *event)
|
||||
{
|
||||
parent()->SetViewBeamCursor(ValidatedCoordinate(event->GetCoordinates(true)));
|
||||
parent()->SetViewBeamCursor(
|
||||
ValidatedCoordinate(event->GetCoordinates(true)));
|
||||
}
|
||||
|
||||
TimelineCoordinate BeamTool::ValidatedCoordinate(TimelineCoordinate coord)
|
||||
{
|
||||
if (Core::instance()->snapping()) {
|
||||
rational movement;
|
||||
parent()->SnapPoint({coord.GetFrame()}, &movement);
|
||||
if (!movement.isNull()) {
|
||||
coord.SetFrame(coord.GetFrame() + movement);
|
||||
}
|
||||
}
|
||||
if (Core::instance()->snapping()) {
|
||||
rational movement;
|
||||
parent()->SnapPoint({ coord.GetFrame() }, &movement);
|
||||
if (!movement.isNull()) {
|
||||
coord.SetFrame(coord.GetFrame() + movement);
|
||||
}
|
||||
}
|
||||
|
||||
return coord;
|
||||
return coord;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,18 +23,17 @@
|
||||
|
||||
#include "tool.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class BeamTool : public TimelineTool
|
||||
namespace olive
|
||||
{
|
||||
public:
|
||||
BeamTool(TimelineWidget *parent);
|
||||
|
||||
virtual void HoverMove(TimelineViewMouseEvent *event) override;
|
||||
class BeamTool : public TimelineTool {
|
||||
public:
|
||||
BeamTool(TimelineWidget *parent);
|
||||
|
||||
virtual void HoverMove(TimelineViewMouseEvent *event) override;
|
||||
|
||||
protected:
|
||||
TimelineCoordinate ValidatedCoordinate(TimelineCoordinate coord);
|
||||
|
||||
TimelineCoordinate ValidatedCoordinate(TimelineCoordinate coord);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -21,72 +21,73 @@
|
||||
#include "edit.h"
|
||||
#include "widget/timelinewidget/timelinewidget.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
EditTool::EditTool(TimelineWidget* parent) :
|
||||
BeamTool(parent)
|
||||
EditTool::EditTool(TimelineWidget *parent)
|
||||
: BeamTool(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void EditTool::MousePress(TimelineViewMouseEvent *event)
|
||||
{
|
||||
if (!(event->GetModifiers() & Qt::ShiftModifier)) {
|
||||
parent()->DeselectAll();
|
||||
}
|
||||
if (!(event->GetModifiers() & Qt::ShiftModifier)) {
|
||||
parent()->DeselectAll();
|
||||
}
|
||||
}
|
||||
|
||||
void EditTool::MouseMove(TimelineViewMouseEvent *event)
|
||||
{
|
||||
if (dragging_) {
|
||||
rational end_frame = event->GetFrame(true);
|
||||
if (dragging_) {
|
||||
rational end_frame = event->GetFrame(true);
|
||||
|
||||
if (Core::instance()->snapping()) {
|
||||
rational movement;
|
||||
parent()->SnapPoint({end_frame}, &movement);
|
||||
if (!movement.isNull()) {
|
||||
end_frame += movement;
|
||||
}
|
||||
}
|
||||
if (Core::instance()->snapping()) {
|
||||
rational movement;
|
||||
parent()->SnapPoint({ end_frame }, &movement);
|
||||
if (!movement.isNull()) {
|
||||
end_frame += movement;
|
||||
}
|
||||
}
|
||||
|
||||
parent()->SetSelections(start_selections_, false);
|
||||
parent()->AddSelection(TimeRange(start_coord_.GetFrame(), end_frame),
|
||||
start_coord_.GetTrack());
|
||||
} else {
|
||||
start_selections_ = parent()->GetSelections();
|
||||
parent()->SetSelections(start_selections_, false);
|
||||
parent()->AddSelection(TimeRange(start_coord_.GetFrame(), end_frame),
|
||||
start_coord_.GetTrack());
|
||||
} else {
|
||||
start_selections_ = parent()->GetSelections();
|
||||
|
||||
dragging_ = true;
|
||||
dragging_ = true;
|
||||
|
||||
start_coord_ = event->GetCoordinates(true);
|
||||
start_coord_ = event->GetCoordinates(true);
|
||||
|
||||
// Snap if we're snapping
|
||||
if (Core::instance()->snapping()) {
|
||||
rational movement;
|
||||
parent()->SnapPoint({start_coord_.GetFrame()}, &movement);
|
||||
if (!movement.isNull()) {
|
||||
start_coord_.SetFrame(start_coord_.GetFrame() + movement);
|
||||
}
|
||||
}
|
||||
// Snap if we're snapping
|
||||
if (Core::instance()->snapping()) {
|
||||
rational movement;
|
||||
parent()->SnapPoint({ start_coord_.GetFrame() }, &movement);
|
||||
if (!movement.isNull()) {
|
||||
start_coord_.SetFrame(start_coord_.GetFrame() + movement);
|
||||
}
|
||||
}
|
||||
|
||||
dragging_ = true;
|
||||
}
|
||||
dragging_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void EditTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
{
|
||||
auto current_sel = parent()->GetSelections();
|
||||
parent()->SetSelections(start_selections_, false);
|
||||
parent()->SetSelections(current_sel, true);
|
||||
auto current_sel = parent()->GetSelections();
|
||||
parent()->SetSelections(start_selections_, false);
|
||||
parent()->SetSelections(current_sel, true);
|
||||
|
||||
dragging_ = false;
|
||||
dragging_ = false;
|
||||
}
|
||||
|
||||
void EditTool::MouseDoubleClick(TimelineViewMouseEvent *event)
|
||||
{
|
||||
Block* item = parent()->GetItemAtScenePos(event->GetCoordinates());
|
||||
Block *item = parent()->GetItemAtScenePos(event->GetCoordinates());
|
||||
|
||||
if (item && !item->track()->IsLocked()) {
|
||||
parent()->AddSelection(item);
|
||||
}
|
||||
if (item && !item->track()->IsLocked()) {
|
||||
parent()->AddSelection(item);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,23 +25,22 @@
|
||||
#include "tool.h"
|
||||
#include "widget/timelinewidget/timelinewidgetselections.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class EditTool : public BeamTool
|
||||
namespace olive
|
||||
{
|
||||
public:
|
||||
EditTool(TimelineWidget* parent);
|
||||
|
||||
virtual void MousePress(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseDoubleClick(TimelineViewMouseEvent *event) override;
|
||||
class EditTool : public BeamTool {
|
||||
public:
|
||||
EditTool(TimelineWidget *parent);
|
||||
|
||||
virtual void MousePress(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseDoubleClick(TimelineViewMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
TimelineWidgetSelections start_selections_;
|
||||
|
||||
TimelineCoordinate start_coord_;
|
||||
TimelineWidgetSelections start_selections_;
|
||||
|
||||
TimelineCoordinate start_coord_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -40,509 +40,588 @@
|
||||
#include "window/mainwindow/mainwindow.h"
|
||||
#include "window/mainwindow/mainwindowundo.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
ImportTool::ImportTool(TimelineWidget *parent) :
|
||||
TimelineTool(parent)
|
||||
namespace olive
|
||||
{
|
||||
// Calculate width used for importing to give ghosts a slight lead-in so the ghosts aren't right on the cursor
|
||||
import_pre_buffer_ = QtUtils::QFontMetricsWidth(parent->fontMetrics(), "HHHHHHHH");
|
||||
|
||||
ImportTool::ImportTool(TimelineWidget *parent)
|
||||
: TimelineTool(parent)
|
||||
{
|
||||
// Calculate width used for importing to give ghosts a slight lead-in so the ghosts aren't right on the cursor
|
||||
import_pre_buffer_ =
|
||||
QtUtils::QFontMetricsWidth(parent->fontMetrics(), "HHHHHHHH");
|
||||
}
|
||||
|
||||
void ImportTool::DragEnter(TimelineViewMouseEvent *event)
|
||||
{
|
||||
QStringList mime_formats = event->GetMimeData()->formats();
|
||||
QStringList mime_formats = event->GetMimeData()->formats();
|
||||
|
||||
// Listen for MIME data from a ProjectViewModel
|
||||
if (mime_formats.contains(Project::kItemMimeType)) {
|
||||
// Listen for MIME data from a ProjectViewModel
|
||||
if (mime_formats.contains(Project::kItemMimeType)) {
|
||||
// Data is drag/drop data from a ProjectViewModel
|
||||
QByteArray model_data =
|
||||
event->GetMimeData()->data(Project::kItemMimeType);
|
||||
|
||||
// Data is drag/drop data from a ProjectViewModel
|
||||
QByteArray model_data = event->GetMimeData()->data(Project::kItemMimeType);
|
||||
// Use QDataStream to deserialize the data
|
||||
QDataStream stream(&model_data, QIODevice::ReadOnly);
|
||||
|
||||
// Use QDataStream to deserialize the data
|
||||
QDataStream stream(&model_data, QIODevice::ReadOnly);
|
||||
// Variables to deserialize into
|
||||
quintptr item_ptr;
|
||||
QVector<Track::Reference> enabled_streams;
|
||||
|
||||
// Variables to deserialize into
|
||||
quintptr item_ptr;
|
||||
QVector<Track::Reference> enabled_streams;
|
||||
// Set drag start position
|
||||
drag_start_ = event->GetCoordinates();
|
||||
|
||||
// Set drag start position
|
||||
drag_start_ = event->GetCoordinates();
|
||||
snap_points_.clear();
|
||||
|
||||
snap_points_.clear();
|
||||
while (!stream.atEnd()) {
|
||||
stream >> enabled_streams >> item_ptr;
|
||||
|
||||
while (!stream.atEnd()) {
|
||||
stream >> enabled_streams >> item_ptr;
|
||||
// Get Item object
|
||||
Node *item = reinterpret_cast<Node *>(item_ptr);
|
||||
|
||||
// Get Item object
|
||||
Node* item = reinterpret_cast<Node*>(item_ptr);
|
||||
// Check if Item is Footage
|
||||
ViewerOutput *f = dynamic_cast<ViewerOutput *>(item);
|
||||
|
||||
// Check if Item is Footage
|
||||
ViewerOutput* f = dynamic_cast<ViewerOutput*>(item);
|
||||
if (f && f->GetTotalStreamCount()) {
|
||||
// If the Item is Footage, we can create a Ghost from it
|
||||
dragged_footage_.append({ f, enabled_streams });
|
||||
}
|
||||
}
|
||||
|
||||
if (f && f->GetTotalStreamCount()) {
|
||||
// If the Item is Footage, we can create a Ghost from it
|
||||
dragged_footage_.append({f, enabled_streams});
|
||||
}
|
||||
}
|
||||
// Create a reasonable amount of space to inset the cursor by when importing
|
||||
ghost_offset_ = drag_start_.GetFrame();
|
||||
|
||||
// Create a reasonable amount of space to inset the cursor by when importing
|
||||
ghost_offset_ = drag_start_.GetFrame();
|
||||
if (!event->GetBypassImportBuffer()) {
|
||||
ghost_offset_ -= parent()->SceneToTime(import_pre_buffer_);
|
||||
}
|
||||
|
||||
if (!event->GetBypassImportBuffer()) {
|
||||
ghost_offset_ -= parent()->SceneToTime(import_pre_buffer_);
|
||||
}
|
||||
PrepGhosts(ghost_offset_, drag_start_.GetTrack().index());
|
||||
|
||||
PrepGhosts(ghost_offset_, drag_start_.GetTrack().index());
|
||||
if (parent()->HasGhosts() || !parent()->GetConnectedNode()) {
|
||||
// We only clear the tentative track if the mimedata is about to be destroyed (i.e. the drag
|
||||
// is cancelled). If we do this in DragLeave, it leads to undesirable behavior if the cursor
|
||||
// is going between views (subtitle track rapidly appearing and disappearing)
|
||||
QObject::connect(event->GetMimeData(), &QObject::destroyed,
|
||||
parent(),
|
||||
&TimelineWidget::ClearTentativeSubtitleTrack);
|
||||
|
||||
if (parent()->HasGhosts() || !parent()->GetConnectedNode()) {
|
||||
// We only clear the tentative track if the mimedata is about to be destroyed (i.e. the drag
|
||||
// is cancelled). If we do this in DragLeave, it leads to undesirable behavior if the cursor
|
||||
// is going between views (subtitle track rapidly appearing and disappearing)
|
||||
QObject::connect(event->GetMimeData(), &QObject::destroyed, parent(), &TimelineWidget::ClearTentativeSubtitleTrack);
|
||||
|
||||
event->accept();
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
} else {
|
||||
// FIXME: Implement dropping from file
|
||||
event->ignore();
|
||||
}
|
||||
event->accept();
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
} else {
|
||||
// FIXME: Implement dropping from file
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void ImportTool::DragMove(TimelineViewMouseEvent *event)
|
||||
{
|
||||
if (!dragged_footage_.isEmpty()) {
|
||||
if (!dragged_footage_.isEmpty()) {
|
||||
if (parent()->HasGhosts()) {
|
||||
rational time_movement = event->GetFrame() - drag_start_.GetFrame();
|
||||
|
||||
if (parent()->HasGhosts()) {
|
||||
rational time_movement = event->GetFrame() - drag_start_.GetFrame();
|
||||
// Keep ghost offset no lower than 0
|
||||
if (ghost_offset_ + time_movement < 0) {
|
||||
time_movement = -ghost_offset_;
|
||||
}
|
||||
|
||||
// Keep ghost offset no lower than 0
|
||||
if (ghost_offset_ + time_movement < 0) {
|
||||
time_movement = -ghost_offset_;
|
||||
}
|
||||
int track_movement =
|
||||
event->GetTrack().index() - drag_start_.GetTrack().index();
|
||||
|
||||
int track_movement = event->GetTrack().index() - drag_start_.GetTrack().index();
|
||||
time_movement = ValidateTimeMovement(time_movement);
|
||||
track_movement = ValidateTrackMovement(track_movement,
|
||||
parent()->GetGhostItems());
|
||||
|
||||
time_movement = ValidateTimeMovement(time_movement);
|
||||
track_movement = ValidateTrackMovement(track_movement, parent()->GetGhostItems());
|
||||
// If snapping is enabled, check for snap points
|
||||
if (Core::instance()->snapping()) {
|
||||
parent()->SnapPoint(snap_points_, &time_movement);
|
||||
|
||||
// If snapping is enabled, check for snap points
|
||||
if (Core::instance()->snapping()) {
|
||||
parent()->SnapPoint(snap_points_, &time_movement);
|
||||
time_movement = ValidateTimeMovement(time_movement);
|
||||
track_movement = ValidateTrackMovement(
|
||||
track_movement, parent()->GetGhostItems());
|
||||
}
|
||||
|
||||
time_movement = ValidateTimeMovement(time_movement);
|
||||
track_movement = ValidateTrackMovement(track_movement, parent()->GetGhostItems());
|
||||
}
|
||||
rational earliest_ghost = RATIONAL_MAX;
|
||||
|
||||
rational earliest_ghost = RATIONAL_MAX;
|
||||
// Move ghosts to the mouse cursor
|
||||
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
|
||||
ghost->SetInAdjustment(time_movement);
|
||||
ghost->SetOutAdjustment(time_movement);
|
||||
ghost->SetTrackAdjustment(track_movement);
|
||||
|
||||
// Move ghosts to the mouse cursor
|
||||
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
|
||||
ghost->SetInAdjustment(time_movement);
|
||||
ghost->SetOutAdjustment(time_movement);
|
||||
ghost->SetTrackAdjustment(track_movement);
|
||||
earliest_ghost = qMin(earliest_ghost, ghost->GetAdjustedIn());
|
||||
}
|
||||
|
||||
earliest_ghost = qMin(earliest_ghost, ghost->GetAdjustedIn());
|
||||
}
|
||||
// Generate tooltip (showing earliest in point of imported clip)
|
||||
rational tooltip_timebase =
|
||||
parent()->GetTimebaseForTrackType(event->GetTrack().type());
|
||||
QString tooltip_text =
|
||||
QString::fromStdString(Timecode::time_to_timecode(
|
||||
earliest_ghost, tooltip_timebase,
|
||||
Core::instance()->GetTimecodeDisplay()));
|
||||
|
||||
// Generate tooltip (showing earliest in point of imported clip)
|
||||
rational tooltip_timebase = parent()->GetTimebaseForTrackType(event->GetTrack().type());
|
||||
QString tooltip_text = QString::fromStdString(Timecode::time_to_timecode(earliest_ghost,
|
||||
tooltip_timebase,
|
||||
Core::instance()->GetTimecodeDisplay()));
|
||||
// Force tooltip to update (otherwise the tooltip won't move as written in the documentation, and could get in the way
|
||||
// of the cursor)
|
||||
QToolTip::hideText();
|
||||
QToolTip::showText(QCursor::pos(), tooltip_text, parent());
|
||||
}
|
||||
|
||||
// Force tooltip to update (otherwise the tooltip won't move as written in the documentation, and could get in the way
|
||||
// of the cursor)
|
||||
QToolTip::hideText();
|
||||
QToolTip::showText(QCursor::pos(),
|
||||
tooltip_text,
|
||||
parent());
|
||||
}
|
||||
|
||||
event->accept();
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
event->accept();
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void ImportTool::DragLeave(QDragLeaveEvent* event)
|
||||
void ImportTool::DragLeave(QDragLeaveEvent *event)
|
||||
{
|
||||
if (!dragged_footage_.isEmpty()) {
|
||||
parent()->ClearGhosts();
|
||||
dragged_footage_.clear();
|
||||
if (!dragged_footage_.isEmpty()) {
|
||||
parent()->ClearGhosts();
|
||||
dragged_footage_.clear();
|
||||
|
||||
event->accept();
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
event->accept();
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void ImportTool::DragDrop(TimelineViewMouseEvent *event)
|
||||
{
|
||||
if (!dragged_footage_.isEmpty()) {
|
||||
auto command = new MultiUndoCommand();
|
||||
DropGhosts(event->GetModifiers() & Qt::ControlModifier, command);
|
||||
Core::instance()->undo_stack()->push(command, qApp->translate("ImportTool", "Dropped Footage Into Sequence"));
|
||||
if (!dragged_footage_.isEmpty()) {
|
||||
auto command = new MultiUndoCommand();
|
||||
DropGhosts(event->GetModifiers() & Qt::ControlModifier, command);
|
||||
Core::instance()->undo_stack()->push(
|
||||
command,
|
||||
qApp->translate("ImportTool", "Dropped Footage Into Sequence"));
|
||||
|
||||
event->accept();
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
event->accept();
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void ImportTool::PlaceAt(const QVector<ViewerOutput *> &footage, const rational &start, bool insert, MultiUndoCommand *command, int track_offset, bool jump_to_end)
|
||||
void ImportTool::PlaceAt(const QVector<ViewerOutput *> &footage,
|
||||
const rational &start, bool insert,
|
||||
MultiUndoCommand *command, int track_offset,
|
||||
bool jump_to_end)
|
||||
{
|
||||
DraggedFootageData refs;
|
||||
DraggedFootageData refs;
|
||||
|
||||
foreach (ViewerOutput* f, footage) {
|
||||
refs.append({f, f->GetEnabledStreamsAsReferences()});
|
||||
}
|
||||
foreach (ViewerOutput *f, footage) {
|
||||
refs.append({ f, f->GetEnabledStreamsAsReferences() });
|
||||
}
|
||||
|
||||
PlaceAt(refs, start, insert, command, track_offset, jump_to_end);
|
||||
PlaceAt(refs, start, insert, command, track_offset, jump_to_end);
|
||||
}
|
||||
|
||||
void ImportTool::PlaceAt(const DraggedFootageData &footage, const rational &start, bool insert, MultiUndoCommand *command, int track_offset, bool jump_to_end)
|
||||
void ImportTool::PlaceAt(const DraggedFootageData &footage,
|
||||
const rational &start, bool insert,
|
||||
MultiUndoCommand *command, int track_offset,
|
||||
bool jump_to_end)
|
||||
{
|
||||
dragged_footage_ = footage;
|
||||
dragged_footage_ = footage;
|
||||
|
||||
if (dragged_footage_.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (dragged_footage_.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PrepGhosts(start, track_offset);
|
||||
PrepGhosts(start, track_offset);
|
||||
|
||||
rational max(0);
|
||||
if (jump_to_end) {
|
||||
for (TimelineViewGhostItem* ghost : parent()->GetGhostItems()) {
|
||||
max = std::max(max, ghost->GetAdjustedOut());
|
||||
}
|
||||
}
|
||||
rational max(0);
|
||||
if (jump_to_end) {
|
||||
for (TimelineViewGhostItem *ghost : parent()->GetGhostItems()) {
|
||||
max = std::max(max, ghost->GetAdjustedOut());
|
||||
}
|
||||
}
|
||||
|
||||
DropGhosts(insert, command);
|
||||
DropGhosts(insert, command);
|
||||
|
||||
if (jump_to_end) {
|
||||
this->sequence()->SetPlayhead(max);
|
||||
}
|
||||
if (jump_to_end) {
|
||||
this->sequence()->SetPlayhead(max);
|
||||
}
|
||||
}
|
||||
|
||||
void ImportTool::FootageToGhosts(rational ghost_start, const DraggedFootageData &sorted, const rational& dest_tb, const int& track_start)
|
||||
void ImportTool::FootageToGhosts(rational ghost_start,
|
||||
const DraggedFootageData &sorted,
|
||||
const rational &dest_tb,
|
||||
const int &track_start)
|
||||
{
|
||||
for (auto it=sorted.cbegin(); it!=sorted.cend(); it++) {
|
||||
ViewerOutput* footage = it->first;
|
||||
for (auto it = sorted.cbegin(); it != sorted.cend(); it++) {
|
||||
ViewerOutput *footage = it->first;
|
||||
|
||||
if (footage == sequence() || (sequence() && footage->InputsFrom(sequence(), true))) {
|
||||
// Prevent cyclical dependency
|
||||
continue;
|
||||
}
|
||||
if (footage == sequence() ||
|
||||
(sequence() && footage->InputsFrom(sequence(), true))) {
|
||||
// Prevent cyclical dependency
|
||||
continue;
|
||||
}
|
||||
|
||||
// Each stream is offset by one track per track "type", we keep track of them in this vector
|
||||
QVector<int> track_offsets(Track::kCount);
|
||||
track_offsets.fill(track_start);
|
||||
// Each stream is offset by one track per track "type", we keep track of them in this vector
|
||||
QVector<int> track_offsets(Track::kCount);
|
||||
track_offsets.fill(track_start);
|
||||
|
||||
rational footage_duration;
|
||||
rational ghost_in;
|
||||
rational footage_duration;
|
||||
rational ghost_in;
|
||||
|
||||
TimelineWorkArea* wk = footage->GetWorkArea();
|
||||
if (wk->enabled()) {
|
||||
footage_duration = wk->length();
|
||||
ghost_in = wk->in();
|
||||
} else {
|
||||
footage_duration = footage->GetLength();
|
||||
TimelineWorkArea *wk = footage->GetWorkArea();
|
||||
if (wk->enabled()) {
|
||||
footage_duration = wk->length();
|
||||
ghost_in = wk->in();
|
||||
} else {
|
||||
footage_duration = footage->GetLength();
|
||||
|
||||
if (footage_duration.isNull()) {
|
||||
// Fallback to still length if legngth was 0
|
||||
footage_duration = OLIVE_CONFIG("DefaultStillLength").value<rational>();
|
||||
}
|
||||
}
|
||||
if (footage_duration.isNull()) {
|
||||
// Fallback to still length if legngth was 0
|
||||
footage_duration =
|
||||
OLIVE_CONFIG("DefaultStillLength").value<rational>();
|
||||
}
|
||||
}
|
||||
|
||||
// Snap footage duration to timebase
|
||||
rational snap_mvmt = SnapMovementToTimebase(footage_duration, 0, dest_tb);
|
||||
if (!snap_mvmt.isNull()) {
|
||||
footage_duration += snap_mvmt;
|
||||
}
|
||||
// Snap footage duration to timebase
|
||||
rational snap_mvmt =
|
||||
SnapMovementToTimebase(footage_duration, 0, dest_tb);
|
||||
if (!snap_mvmt.isNull()) {
|
||||
footage_duration += snap_mvmt;
|
||||
}
|
||||
|
||||
// Create ghosts
|
||||
foreach (const Track::Reference& ref, it->second) {
|
||||
Track::Type track_type = ref.type();
|
||||
Track::Reference dest_track(track_type, track_offsets.at(track_type));
|
||||
// Create ghosts
|
||||
foreach (const Track::Reference &ref, it->second) {
|
||||
Track::Type track_type = ref.type();
|
||||
Track::Reference dest_track(track_type,
|
||||
track_offsets.at(track_type));
|
||||
|
||||
if (track_type == Track::kVideo || track_type == Track::kAudio) {
|
||||
auto ghost = CreateGhost(TimeRange(ghost_start, ghost_start + footage_duration), ghost_in, dest_track);
|
||||
if (track_type == Track::kVideo || track_type == Track::kAudio) {
|
||||
auto ghost = CreateGhost(
|
||||
TimeRange(ghost_start, ghost_start + footage_duration),
|
||||
ghost_in, dest_track);
|
||||
|
||||
// Increment track count for this track type
|
||||
track_offsets[track_type]++;
|
||||
// Increment track count for this track type
|
||||
track_offsets[track_type]++;
|
||||
|
||||
TimelineViewGhostItem::AttachedFootage af = {it->first, ref.ToString()};
|
||||
ghost->SetData(TimelineViewGhostItem::kAttachedFootage, QVariant::fromValue(af));
|
||||
} else if (track_type == Track::kSubtitle) {
|
||||
SubtitleParams sp = footage->GetSubtitleParams(ref.index());
|
||||
TimelineViewGhostItem::AttachedFootage af = { it->first,
|
||||
ref.ToString() };
|
||||
ghost->SetData(TimelineViewGhostItem::kAttachedFootage,
|
||||
QVariant::fromValue(af));
|
||||
} else if (track_type == Track::kSubtitle) {
|
||||
SubtitleParams sp = footage->GetSubtitleParams(ref.index());
|
||||
|
||||
for (const Subtitle &sub : sp) {
|
||||
auto ghost = CreateGhost(sub.time() + ghost_start, 0, dest_track);
|
||||
for (const Subtitle &sub : sp) {
|
||||
auto ghost =
|
||||
CreateGhost(sub.time() + ghost_start, 0, dest_track);
|
||||
|
||||
ghost->SetData(TimelineViewGhostItem::kAttachedFootage, QVariant::fromValue(sub));
|
||||
}
|
||||
ghost->SetData(TimelineViewGhostItem::kAttachedFootage,
|
||||
QVariant::fromValue(sub));
|
||||
}
|
||||
|
||||
parent()->AddTentativeSubtitleTrack();
|
||||
}
|
||||
}
|
||||
parent()->AddTentativeSubtitleTrack();
|
||||
}
|
||||
}
|
||||
|
||||
// Stack each ghost one after the other
|
||||
ghost_start += footage_duration;
|
||||
|
||||
}
|
||||
// Stack each ghost one after the other
|
||||
ghost_start += footage_duration;
|
||||
}
|
||||
}
|
||||
|
||||
void ImportTool::PrepGhosts(const rational& frame, const int& track_index)
|
||||
void ImportTool::PrepGhosts(const rational &frame, const int &track_index)
|
||||
{
|
||||
if (parent()->GetConnectedNode()) {
|
||||
FootageToGhosts(frame,
|
||||
dragged_footage_,
|
||||
parent()->GetConnectedNode()->GetVideoParams().time_base(),
|
||||
track_index);
|
||||
}
|
||||
if (parent()->GetConnectedNode()) {
|
||||
FootageToGhosts(
|
||||
frame, dragged_footage_,
|
||||
parent()->GetConnectedNode()->GetVideoParams().time_base(),
|
||||
track_index);
|
||||
}
|
||||
}
|
||||
|
||||
void ImportTool::DropGhosts(bool insert, MultiUndoCommand *parent_command)
|
||||
{
|
||||
auto command = new MultiUndoCommand();
|
||||
auto command = new MultiUndoCommand();
|
||||
|
||||
if (MultiUndoCommand *c = parent()->TakeSubtitleSectionCommand()) {
|
||||
command->add_child(c);
|
||||
}
|
||||
if (MultiUndoCommand *c = parent()->TakeSubtitleSectionCommand()) {
|
||||
command->add_child(c);
|
||||
}
|
||||
|
||||
Project* dst_graph = nullptr;
|
||||
Sequence* sequence = this->sequence();
|
||||
bool open_sequence = false;
|
||||
Project *dst_graph = nullptr;
|
||||
Sequence *sequence = this->sequence();
|
||||
bool open_sequence = false;
|
||||
|
||||
if (sequence) {
|
||||
dst_graph = sequence->parent();
|
||||
} else {
|
||||
// There's no active timeline here, ask the user what to do
|
||||
if (sequence) {
|
||||
dst_graph = sequence->parent();
|
||||
} else {
|
||||
// There's no active timeline here, ask the user what to do
|
||||
|
||||
DropWithoutSequenceBehavior behavior = static_cast<DropWithoutSequenceBehavior>(OLIVE_CONFIG("DropWithoutSequenceBehavior").toInt());
|
||||
DropWithoutSequenceBehavior behavior =
|
||||
static_cast<DropWithoutSequenceBehavior>(
|
||||
OLIVE_CONFIG("DropWithoutSequenceBehavior").toInt());
|
||||
|
||||
if (behavior == kDWSAsk) {
|
||||
QCheckBox* dont_ask_again_box = new QCheckBox(QCoreApplication::translate("ImportTool", "Don't ask me again"));
|
||||
if (behavior == kDWSAsk) {
|
||||
QCheckBox *dont_ask_again_box = new QCheckBox(
|
||||
QCoreApplication::translate("ImportTool",
|
||||
"Don't ask me again"));
|
||||
|
||||
QMessageBox mbox(parent());
|
||||
QMessageBox mbox(parent());
|
||||
|
||||
mbox.setIcon(QMessageBox::Question);
|
||||
mbox.setWindowTitle(QCoreApplication::translate("ImportTool", "No Active Sequence"));
|
||||
mbox.setText(QCoreApplication::translate("ImportTool", "No sequence is currently open. Would you like to create one?"));
|
||||
mbox.setCheckBox(dont_ask_again_box);
|
||||
mbox.setIcon(QMessageBox::Question);
|
||||
mbox.setWindowTitle(QCoreApplication::translate(
|
||||
"ImportTool", "No Active Sequence"));
|
||||
mbox.setText(QCoreApplication::translate(
|
||||
"ImportTool",
|
||||
"No sequence is currently open. Would you like to create one?"));
|
||||
mbox.setCheckBox(dont_ask_again_box);
|
||||
|
||||
QPushButton* auto_params_btn = mbox.addButton(QCoreApplication::translate("ImportTool", "Automatically Detect Parameters From Footage"), QMessageBox::YesRole);
|
||||
QPushButton* manual_params_btn = mbox.addButton(QCoreApplication::translate("ImportTool", "Set Parameters Manually"), QMessageBox::NoRole);
|
||||
mbox.addButton(QMessageBox::Cancel);
|
||||
QPushButton *auto_params_btn = mbox.addButton(
|
||||
QCoreApplication::translate(
|
||||
"ImportTool",
|
||||
"Automatically Detect Parameters From Footage"),
|
||||
QMessageBox::YesRole);
|
||||
QPushButton *manual_params_btn =
|
||||
mbox.addButton(QCoreApplication::translate(
|
||||
"ImportTool", "Set Parameters Manually"),
|
||||
QMessageBox::NoRole);
|
||||
mbox.addButton(QMessageBox::Cancel);
|
||||
|
||||
mbox.exec();
|
||||
mbox.exec();
|
||||
|
||||
if (mbox.clickedButton() == auto_params_btn) {
|
||||
behavior = kDWSAuto;
|
||||
} else if (mbox.clickedButton() == manual_params_btn) {
|
||||
behavior = kDWSManual;
|
||||
} else {
|
||||
behavior = kDWSDisable;
|
||||
}
|
||||
if (mbox.clickedButton() == auto_params_btn) {
|
||||
behavior = kDWSAuto;
|
||||
} else if (mbox.clickedButton() == manual_params_btn) {
|
||||
behavior = kDWSManual;
|
||||
} else {
|
||||
behavior = kDWSDisable;
|
||||
}
|
||||
|
||||
if (behavior != kDWSDisable && dont_ask_again_box->isChecked()) {
|
||||
OLIVE_CONFIG("DropWithoutSequenceBehavior") = behavior;
|
||||
}
|
||||
}
|
||||
if (behavior != kDWSDisable && dont_ask_again_box->isChecked()) {
|
||||
OLIVE_CONFIG("DropWithoutSequenceBehavior") = behavior;
|
||||
}
|
||||
}
|
||||
|
||||
if (behavior != kDWSDisable) {
|
||||
Project* active_project = Core::instance()->GetActiveProject();
|
||||
if (behavior != kDWSDisable) {
|
||||
Project *active_project = Core::instance()->GetActiveProject();
|
||||
|
||||
if (active_project) {
|
||||
Sequence* new_sequence = Core::instance()->CreateNewSequenceForProject(active_project);
|
||||
if (active_project) {
|
||||
Sequence *new_sequence =
|
||||
Core::instance()->CreateNewSequenceForProject(
|
||||
active_project);
|
||||
|
||||
new_sequence->set_default_parameters();
|
||||
new_sequence->set_default_parameters();
|
||||
|
||||
bool sequence_is_valid = true;
|
||||
bool sequence_is_valid = true;
|
||||
|
||||
// Even if the user selected manual, set from footage anyway so the user has a useful
|
||||
// starting point
|
||||
QVector<ViewerOutput*> footage_only;
|
||||
// Even if the user selected manual, set from footage anyway so the user has a useful
|
||||
// starting point
|
||||
QVector<ViewerOutput *> footage_only;
|
||||
|
||||
for (auto it=dragged_footage_.cbegin(); it!=dragged_footage_.cend(); it++) {
|
||||
if (!footage_only.contains(it->first)) {
|
||||
footage_only.append(it->first);
|
||||
}
|
||||
}
|
||||
for (auto it = dragged_footage_.cbegin();
|
||||
it != dragged_footage_.cend(); it++) {
|
||||
if (!footage_only.contains(it->first)) {
|
||||
footage_only.append(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
new_sequence->set_parameters_from_footage(footage_only);
|
||||
new_sequence->set_parameters_from_footage(footage_only);
|
||||
|
||||
// If the user selected manual, show them a dialog with parameters
|
||||
if (behavior == kDWSManual) {
|
||||
// If the user selected manual, show them a dialog with parameters
|
||||
if (behavior == kDWSManual) {
|
||||
SequenceDialog sd(new_sequence, SequenceDialog::kNew,
|
||||
parent());
|
||||
sd.SetUndoable(false);
|
||||
|
||||
SequenceDialog sd(new_sequence, SequenceDialog::kNew, parent());
|
||||
sd.SetUndoable(false);
|
||||
if (sd.exec() != QDialog::Accepted) {
|
||||
sequence_is_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (sd.exec() != QDialog::Accepted) {
|
||||
sequence_is_valid = false;
|
||||
}
|
||||
if (sequence_is_valid) {
|
||||
dst_graph = Core::instance()->GetActiveProject();
|
||||
|
||||
}
|
||||
command->add_child(
|
||||
new NodeAddCommand(dst_graph, new_sequence));
|
||||
command->add_child(new FolderAddChild(
|
||||
Core::instance()->GetSelectedFolderInActiveProject(),
|
||||
new_sequence));
|
||||
command->add_child(new NodeSetPositionCommand(
|
||||
new_sequence, new_sequence, QPointF(0, 0)));
|
||||
new_sequence->add_default_nodes(command);
|
||||
|
||||
if (sequence_is_valid) {
|
||||
dst_graph = Core::instance()->GetActiveProject();
|
||||
FootageToGhosts(0, dragged_footage_,
|
||||
new_sequence->GetVideoParams().time_base(),
|
||||
0);
|
||||
|
||||
command->add_child(new NodeAddCommand(dst_graph, new_sequence));
|
||||
command->add_child(new FolderAddChild(Core::instance()->GetSelectedFolderInActiveProject(), new_sequence));
|
||||
command->add_child(new NodeSetPositionCommand(new_sequence, new_sequence, QPointF(0, 0)));
|
||||
new_sequence->add_default_nodes(command);
|
||||
if (MultiUndoCommand *c =
|
||||
parent()->TakeSubtitleSectionCommand()) {
|
||||
command->add_child(c);
|
||||
}
|
||||
|
||||
FootageToGhosts(0, dragged_footage_, new_sequence->GetVideoParams().time_base(), 0);
|
||||
sequence = new_sequence;
|
||||
|
||||
if (MultiUndoCommand *c = parent()->TakeSubtitleSectionCommand()) {
|
||||
command->add_child(c);
|
||||
}
|
||||
// Set this as the sequence to open
|
||||
open_sequence = true;
|
||||
} else {
|
||||
// If the sequence is valid, ownership is passed to AddItemCommand.
|
||||
// Otherwise, we're responsible for deleting it.
|
||||
delete new_sequence;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sequence = new_sequence;
|
||||
std::list<ClipBlock *> imported_clips;
|
||||
|
||||
// Set this as the sequence to open
|
||||
open_sequence = true;
|
||||
} else {
|
||||
// If the sequence is valid, ownership is passed to AddItemCommand.
|
||||
// Otherwise, we're responsible for deleting it.
|
||||
delete new_sequence;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dst_graph) {
|
||||
QVector<Block *> block_items(parent()->GetGhostItems().size());
|
||||
|
||||
std::list<ClipBlock*> imported_clips;
|
||||
// Check if we're inserting (only valid if we're not creating this sequence ourselves)
|
||||
if (insert && !open_sequence) {
|
||||
InsertGapsAtGhostDestination(command);
|
||||
}
|
||||
|
||||
if (dst_graph) {
|
||||
for (int i = 0; i < parent()->GetGhostItems().size(); i++) {
|
||||
TimelineViewGhostItem *ghost = parent()->GetGhostItems().at(i);
|
||||
Block *block = nullptr;
|
||||
|
||||
QVector<Block*> block_items(parent()->GetGhostItems().size());
|
||||
Track::Type track_type = ghost->GetAdjustedTrack().type();
|
||||
if (track_type == Track::kVideo || track_type == Track::kAudio) {
|
||||
TimelineViewGhostItem::AttachedFootage footage_stream =
|
||||
ghost->GetData(TimelineViewGhostItem::kAttachedFootage)
|
||||
.value<TimelineViewGhostItem::AttachedFootage>();
|
||||
|
||||
// Check if we're inserting (only valid if we're not creating this sequence ourselves)
|
||||
if (insert && !open_sequence) {
|
||||
InsertGapsAtGhostDestination(command);
|
||||
}
|
||||
ClipBlock *clip = new ClipBlock();
|
||||
block = clip;
|
||||
clip->set_media_in(ghost->GetMediaIn());
|
||||
command->add_child(new NodeAddCommand(dst_graph, clip));
|
||||
|
||||
for (int i=0;i<parent()->GetGhostItems().size();i++) {
|
||||
TimelineViewGhostItem* ghost = parent()->GetGhostItems().at(i);
|
||||
Block* block = nullptr;
|
||||
// Position clip in its own context
|
||||
command->add_child(
|
||||
new NodeSetPositionCommand(clip, clip, QPointF(0, 0)));
|
||||
|
||||
Track::Type track_type = ghost->GetAdjustedTrack().type();
|
||||
if (track_type == Track::kVideo || track_type == Track::kAudio) {
|
||||
TimelineViewGhostItem::AttachedFootage footage_stream = ghost->GetData(TimelineViewGhostItem::kAttachedFootage).value<TimelineViewGhostItem::AttachedFootage>();
|
||||
int dep_pos = kDefaultDistanceFromOutput;
|
||||
|
||||
ClipBlock* clip = new ClipBlock();
|
||||
block = clip;
|
||||
clip->set_media_in(ghost->GetMediaIn());
|
||||
command->add_child(new NodeAddCommand(dst_graph, clip));
|
||||
// Position footage in its context
|
||||
command->add_child(new NodeSetPositionCommand(
|
||||
footage_stream.footage, clip, QPointF(dep_pos, 0)));
|
||||
|
||||
// Position clip in its own context
|
||||
command->add_child(new NodeSetPositionCommand(clip, clip, QPointF(0, 0)));
|
||||
dep_pos++;
|
||||
|
||||
int dep_pos = kDefaultDistanceFromOutput;
|
||||
switch (
|
||||
Track::Reference::TypeFromString(footage_stream.output)) {
|
||||
case Track::kVideo: {
|
||||
TransformDistortNode *transform =
|
||||
new TransformDistortNode();
|
||||
command->add_child(
|
||||
new NodeAddCommand(dst_graph, transform));
|
||||
|
||||
// Position footage in its context
|
||||
command->add_child(new NodeSetPositionCommand(footage_stream.footage, clip, QPointF(dep_pos, 0)));
|
||||
command->add_child(new NodeSetValueHintCommand(
|
||||
transform, TransformDistortNode::kTextureInput, -1,
|
||||
Node::ValueHint({ NodeValue::kTexture },
|
||||
footage_stream.output)));
|
||||
|
||||
dep_pos++;
|
||||
command->add_child(new NodeEdgeAddCommand(
|
||||
footage_stream.footage,
|
||||
NodeInput(transform,
|
||||
TransformDistortNode::kTextureInput)));
|
||||
command->add_child(new NodeEdgeAddCommand(
|
||||
transform, NodeInput(clip, ClipBlock::kBufferIn)));
|
||||
command->add_child(new NodeSetPositionCommand(
|
||||
transform, clip, QPointF(dep_pos, 0)));
|
||||
break;
|
||||
}
|
||||
case Track::kAudio: {
|
||||
VolumeNode *volume_node = new VolumeNode();
|
||||
command->add_child(
|
||||
new NodeAddCommand(dst_graph, volume_node));
|
||||
|
||||
switch (Track::Reference::TypeFromString(footage_stream.output)) {
|
||||
case Track::kVideo:
|
||||
{
|
||||
TransformDistortNode* transform = new TransformDistortNode();
|
||||
command->add_child(new NodeAddCommand(dst_graph, transform));
|
||||
command->add_child(new NodeSetValueHintCommand(
|
||||
volume_node, VolumeNode::kSamplesInput, -1,
|
||||
Node::ValueHint({ NodeValue::kSamples },
|
||||
footage_stream.output)));
|
||||
|
||||
command->add_child(new NodeSetValueHintCommand(transform, TransformDistortNode::kTextureInput, -1, Node::ValueHint({NodeValue::kTexture}, footage_stream.output)));
|
||||
command->add_child(new NodeEdgeAddCommand(
|
||||
footage_stream.footage,
|
||||
NodeInput(volume_node, VolumeNode::kSamplesInput)));
|
||||
command->add_child(new NodeEdgeAddCommand(
|
||||
volume_node, NodeInput(clip, ClipBlock::kBufferIn)));
|
||||
command->add_child(new NodeSetPositionCommand(
|
||||
volume_node, clip, QPointF(dep_pos, 0)));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
command->add_child(new NodeEdgeAddCommand(footage_stream.footage, NodeInput(transform, TransformDistortNode::kTextureInput)));
|
||||
command->add_child(new NodeEdgeAddCommand(transform, NodeInput(clip, ClipBlock::kBufferIn)));
|
||||
command->add_child(new NodeSetPositionCommand(transform, clip, QPointF(dep_pos, 0)));
|
||||
break;
|
||||
}
|
||||
case Track::kAudio:
|
||||
{
|
||||
VolumeNode* volume_node = new VolumeNode();
|
||||
command->add_child(new NodeAddCommand(dst_graph, volume_node));
|
||||
// Link any clips so far that share the same Footage with this one
|
||||
for (int j = 0; j < i; j++) {
|
||||
TimelineViewGhostItem::AttachedFootage footage_compare =
|
||||
parent()
|
||||
->GetGhostItems()
|
||||
.at(j)
|
||||
->GetData(TimelineViewGhostItem::kAttachedFootage)
|
||||
.value<TimelineViewGhostItem::AttachedFootage>();
|
||||
|
||||
command->add_child(new NodeSetValueHintCommand(volume_node, VolumeNode::kSamplesInput, -1, Node::ValueHint({NodeValue::kSamples}, footage_stream.output)));
|
||||
if (footage_compare.footage == footage_stream.footage) {
|
||||
Block::Link(block_items.at(j), clip);
|
||||
}
|
||||
}
|
||||
|
||||
command->add_child(new NodeEdgeAddCommand(footage_stream.footage, NodeInput(volume_node, VolumeNode::kSamplesInput)));
|
||||
command->add_child(new NodeEdgeAddCommand(volume_node, NodeInput(clip, ClipBlock::kBufferIn)));
|
||||
command->add_child(new NodeSetPositionCommand(volume_node, clip, QPointF(dep_pos, 0)));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
imported_clips.push_back(clip);
|
||||
} else if (track_type == Track::kSubtitle) {
|
||||
Subtitle src =
|
||||
ghost->GetData(TimelineViewGhostItem::kAttachedFootage)
|
||||
.value<Subtitle>();
|
||||
SubtitleBlock *sub = new SubtitleBlock();
|
||||
sub->SetText(src.text());
|
||||
block = sub;
|
||||
|
||||
// Link any clips so far that share the same Footage with this one
|
||||
for (int j=0;j<i;j++) {
|
||||
TimelineViewGhostItem::AttachedFootage footage_compare = parent()->GetGhostItems().at(j)->GetData(TimelineViewGhostItem::kAttachedFootage).value<TimelineViewGhostItem::AttachedFootage>();
|
||||
command->add_child(new NodeAddCommand(dst_graph, sub));
|
||||
command->add_child(
|
||||
new NodeSetPositionCommand(sub, sub, QPointF(0, 0)));
|
||||
}
|
||||
|
||||
if (footage_compare.footage == footage_stream.footage) {
|
||||
Block::Link(block_items.at(j), clip);
|
||||
}
|
||||
}
|
||||
block->set_length_and_media_out(ghost->GetLength());
|
||||
|
||||
imported_clips.push_back(clip);
|
||||
} else if (track_type == Track::kSubtitle) {
|
||||
Subtitle src = ghost->GetData(TimelineViewGhostItem::kAttachedFootage).value<Subtitle>();
|
||||
SubtitleBlock *sub = new SubtitleBlock();
|
||||
sub->SetText(src.text());
|
||||
block = sub;
|
||||
command->add_child(new TrackPlaceBlockCommand(
|
||||
sequence->track_list(ghost->GetAdjustedTrack().type()),
|
||||
ghost->GetAdjustedTrack().index(), block,
|
||||
ghost->GetAdjustedIn()));
|
||||
|
||||
command->add_child(new NodeAddCommand(dst_graph, sub));
|
||||
command->add_child(new NodeSetPositionCommand(sub, sub, QPointF(0, 0)));
|
||||
}
|
||||
block_items.replace(i, block);
|
||||
}
|
||||
}
|
||||
|
||||
block->set_length_and_media_out(ghost->GetLength());
|
||||
if (open_sequence) {
|
||||
command->add_child(new OpenSequenceCommand(sequence));
|
||||
}
|
||||
|
||||
command->add_child(new TrackPlaceBlockCommand(sequence->track_list(ghost->GetAdjustedTrack().type()),
|
||||
ghost->GetAdjustedTrack().index(),
|
||||
block,
|
||||
ghost->GetAdjustedIn()));
|
||||
// Do command now because RequestInvalidatedFromConnected relies on track type, which will be
|
||||
// "none" before this command is done because it won't be connected to any track
|
||||
command->redo_now();
|
||||
parent_command->add_child(command);
|
||||
|
||||
block_items.replace(i, block);
|
||||
}
|
||||
}
|
||||
while (!imported_clips.empty()) {
|
||||
imported_clips.front()->RequestInvalidatedFromConnected();
|
||||
imported_clips.pop_front();
|
||||
}
|
||||
|
||||
if (open_sequence) {
|
||||
command->add_child(new OpenSequenceCommand(sequence));
|
||||
}
|
||||
|
||||
// Do command now because RequestInvalidatedFromConnected relies on track type, which will be
|
||||
// "none" before this command is done because it won't be connected to any track
|
||||
command->redo_now();
|
||||
parent_command->add_child(command);
|
||||
|
||||
while (!imported_clips.empty()) {
|
||||
imported_clips.front()->RequestInvalidatedFromConnected();
|
||||
imported_clips.pop_front();
|
||||
}
|
||||
|
||||
parent()->ClearGhosts();
|
||||
dragged_footage_.clear();
|
||||
parent()->ClearGhosts();
|
||||
dragged_footage_.clear();
|
||||
}
|
||||
|
||||
TimelineViewGhostItem* ImportTool::CreateGhost(const TimeRange &range, const rational &media_in, const Track::Reference &track)
|
||||
TimelineViewGhostItem *ImportTool::CreateGhost(const TimeRange &range,
|
||||
const rational &media_in,
|
||||
const Track::Reference &track)
|
||||
{
|
||||
TimelineViewGhostItem* ghost = new TimelineViewGhostItem();
|
||||
TimelineViewGhostItem *ghost = new TimelineViewGhostItem();
|
||||
|
||||
ghost->SetIn(range.in());
|
||||
ghost->SetOut(range.out());
|
||||
ghost->SetMediaIn(media_in);
|
||||
ghost->SetTrack(track);
|
||||
ghost->SetIn(range.in());
|
||||
ghost->SetOut(range.out());
|
||||
ghost->SetMediaIn(media_in);
|
||||
ghost->SetTrack(track);
|
||||
|
||||
snap_points_.push_back(ghost->GetIn());
|
||||
snap_points_.push_back(ghost->GetOut());
|
||||
snap_points_.push_back(ghost->GetIn());
|
||||
snap_points_.push_back(ghost->GetOut());
|
||||
|
||||
ghost->SetMode(Timeline::kMove);
|
||||
ghost->SetMode(Timeline::kMove);
|
||||
|
||||
parent()->AddGhost(ghost);
|
||||
parent()->AddGhost(ghost);
|
||||
|
||||
return ghost;
|
||||
return ghost;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,45 +23,53 @@
|
||||
|
||||
#include "tool.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class ImportTool : public TimelineTool
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class ImportTool : public TimelineTool {
|
||||
public:
|
||||
ImportTool(TimelineWidget* parent);
|
||||
ImportTool(TimelineWidget *parent);
|
||||
|
||||
virtual void DragEnter(TimelineViewMouseEvent *event) override;
|
||||
virtual void DragMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void DragLeave(QDragLeaveEvent *event) override;
|
||||
virtual void DragDrop(TimelineViewMouseEvent *event) override;
|
||||
virtual void DragEnter(TimelineViewMouseEvent *event) override;
|
||||
virtual void DragMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void DragLeave(QDragLeaveEvent *event) override;
|
||||
virtual void DragDrop(TimelineViewMouseEvent *event) override;
|
||||
|
||||
using DraggedFootageData = QVector<QPair<ViewerOutput*, QVector<Track::Reference> > >;
|
||||
using DraggedFootageData =
|
||||
QVector<QPair<ViewerOutput *, QVector<Track::Reference>>>;
|
||||
|
||||
void PlaceAt(const QVector<ViewerOutput *> &footage, const rational& start, bool insert, MultiUndoCommand *command, int track_offset = 0, bool jump_to_end = false);
|
||||
void PlaceAt(const DraggedFootageData &footage, const rational& start, bool insert, MultiUndoCommand *command, int track_offset = 0, bool jump_to_end = false);
|
||||
void PlaceAt(const QVector<ViewerOutput *> &footage, const rational &start,
|
||||
bool insert, MultiUndoCommand *command, int track_offset = 0,
|
||||
bool jump_to_end = false);
|
||||
void PlaceAt(const DraggedFootageData &footage, const rational &start,
|
||||
bool insert, MultiUndoCommand *command, int track_offset = 0,
|
||||
bool jump_to_end = false);
|
||||
|
||||
enum DropWithoutSequenceBehavior {
|
||||
kDWSAsk,
|
||||
kDWSAuto,
|
||||
kDWSManual,
|
||||
kDWSDisable
|
||||
};
|
||||
enum DropWithoutSequenceBehavior {
|
||||
kDWSAsk,
|
||||
kDWSAuto,
|
||||
kDWSManual,
|
||||
kDWSDisable
|
||||
};
|
||||
|
||||
private:
|
||||
void FootageToGhosts(rational ghost_start, const DraggedFootageData &footage, const rational &dest_tb, const int &track_start);
|
||||
void FootageToGhosts(rational ghost_start,
|
||||
const DraggedFootageData &footage,
|
||||
const rational &dest_tb, const int &track_start);
|
||||
|
||||
void PrepGhosts(const rational &frame, const int &track_index);
|
||||
void PrepGhosts(const rational &frame, const int &track_index);
|
||||
|
||||
void DropGhosts(bool insert, MultiUndoCommand *parent_command);
|
||||
void DropGhosts(bool insert, MultiUndoCommand *parent_command);
|
||||
|
||||
TimelineViewGhostItem* CreateGhost(const TimeRange &range, const rational &media_in, const Track::Reference &track);
|
||||
TimelineViewGhostItem *CreateGhost(const TimeRange &range,
|
||||
const rational &media_in,
|
||||
const Track::Reference &track);
|
||||
|
||||
DraggedFootageData dragged_footage_;
|
||||
DraggedFootageData dragged_footage_;
|
||||
|
||||
int import_pre_buffer_;
|
||||
|
||||
rational ghost_offset_;
|
||||
int import_pre_buffer_;
|
||||
|
||||
rational ghost_offset_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,111 +23,124 @@
|
||||
|
||||
#include "tool.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class PointerTool : public TimelineTool
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class PointerTool : public TimelineTool {
|
||||
public:
|
||||
PointerTool(TimelineWidget* parent);
|
||||
PointerTool(TimelineWidget *parent);
|
||||
|
||||
virtual void MousePress(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
|
||||
virtual void MousePress(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
|
||||
|
||||
virtual void HoverMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void HoverMove(TimelineViewMouseEvent *event) override;
|
||||
|
||||
protected:
|
||||
virtual void FinishDrag(TimelineViewMouseEvent *event);
|
||||
virtual void FinishDrag(TimelineViewMouseEvent *event);
|
||||
|
||||
virtual void InitiateDrag(Block* clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers);
|
||||
virtual void InitiateDrag(Block *clicked_item,
|
||||
Timeline::MovementMode trim_mode,
|
||||
Qt::KeyboardModifiers modifiers);
|
||||
|
||||
TimelineViewGhostItem *GetExistingGhostFromBlock(Block *block);
|
||||
TimelineViewGhostItem *GetExistingGhostFromBlock(Block *block);
|
||||
|
||||
TimelineViewGhostItem* AddGhostFromBlock(Block *block, 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 Track::Reference& 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
|
||||
*
|
||||
* Assumes ghost->data() is a Block. Ensures no Ghost's in point becomes a negative timecode. Also ensures no
|
||||
* Ghost's length becomes 0 or negative.
|
||||
*/
|
||||
rational ValidateInTrimming(rational movement);
|
||||
rational ValidateInTrimming(rational movement);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Validates Ghosts that are getting their out points trimmed
|
||||
*
|
||||
* Assumes ghost->data() is a Block. Ensures no Ghost's in point becomes a negative timecode. Also ensures no
|
||||
* Ghost's length becomes 0 or negative.
|
||||
*/
|
||||
rational ValidateOutTrimming(rational movement);
|
||||
rational ValidateOutTrimming(rational movement);
|
||||
|
||||
virtual void ProcessDrag(const TimelineCoordinate &mouse_pos);
|
||||
virtual void ProcessDrag(const TimelineCoordinate &mouse_pos);
|
||||
|
||||
void InitiateDragInternal(Block* clicked_item,
|
||||
Timeline::MovementMode trim_mode,
|
||||
Qt::KeyboardModifiers modifiers,
|
||||
bool dont_roll_trims,
|
||||
bool allow_nongap_rolling, bool slide_instead_of_moving);
|
||||
void InitiateDragInternal(Block *clicked_item,
|
||||
Timeline::MovementMode trim_mode,
|
||||
Qt::KeyboardModifiers modifiers,
|
||||
bool dont_roll_trims, bool allow_nongap_rolling,
|
||||
bool slide_instead_of_moving);
|
||||
|
||||
const Timeline::MovementMode& drag_movement_mode() const { return drag_movement_mode_; }
|
||||
void set_drag_movement_mode(const Timeline::MovementMode &d) { drag_movement_mode_ = d; }
|
||||
const Timeline::MovementMode &drag_movement_mode() const
|
||||
{
|
||||
return drag_movement_mode_;
|
||||
}
|
||||
void set_drag_movement_mode(const Timeline::MovementMode &d)
|
||||
{
|
||||
drag_movement_mode_ = d;
|
||||
}
|
||||
|
||||
static bool CanTransitionMove(TransitionBlock *transit, const QVector<Block*> &clips);
|
||||
static bool CanTransitionMove(TransitionBlock *transit,
|
||||
const QVector<Block *> &clips);
|
||||
|
||||
void SetMovementAllowed(bool e)
|
||||
{
|
||||
movement_allowed_ = e;
|
||||
}
|
||||
void SetMovementAllowed(bool e)
|
||||
{
|
||||
movement_allowed_ = e;
|
||||
}
|
||||
|
||||
void SetTrimmingAllowed(bool e)
|
||||
{
|
||||
trimming_allowed_ = e;
|
||||
}
|
||||
void SetTrimmingAllowed(bool e)
|
||||
{
|
||||
trimming_allowed_ = e;
|
||||
}
|
||||
|
||||
void SetTrackMovementAllowed(bool e)
|
||||
{
|
||||
track_movement_allowed_ = e;
|
||||
}
|
||||
void SetTrackMovementAllowed(bool e)
|
||||
{
|
||||
track_movement_allowed_ = e;
|
||||
}
|
||||
|
||||
void SetGapTrimmingAllowed(bool e)
|
||||
{
|
||||
gap_trimming_allowed_ = e;
|
||||
}
|
||||
void SetGapTrimmingAllowed(bool e)
|
||||
{
|
||||
gap_trimming_allowed_ = e;
|
||||
}
|
||||
|
||||
void SetClickedItem(Block *b)
|
||||
{
|
||||
clicked_item_ = b;
|
||||
}
|
||||
void SetClickedItem(Block *b)
|
||||
{
|
||||
clicked_item_ = b;
|
||||
}
|
||||
|
||||
private:
|
||||
Timeline::MovementMode IsCursorInTrimHandle(Block* block, qreal cursor_x);
|
||||
Timeline::MovementMode IsCursorInTrimHandle(Block *block, qreal cursor_x);
|
||||
|
||||
void AddGhostInternal(TimelineViewGhostItem* ghost, Timeline::MovementMode mode);
|
||||
void AddGhostInternal(TimelineViewGhostItem *ghost,
|
||||
Timeline::MovementMode mode);
|
||||
|
||||
bool IsClipTrimmable(Block* clip,
|
||||
const QVector<Block*> &items,
|
||||
const Timeline::MovementMode& mode);
|
||||
bool IsClipTrimmable(Block *clip, const QVector<Block *> &items,
|
||||
const Timeline::MovementMode &mode);
|
||||
|
||||
void ProcessGhostsForSliding();
|
||||
void ProcessGhostsForSliding();
|
||||
|
||||
void ProcessGhostsForRolling();
|
||||
void ProcessGhostsForRolling();
|
||||
|
||||
bool movement_allowed_;
|
||||
bool trimming_allowed_;
|
||||
bool track_movement_allowed_;
|
||||
bool gap_trimming_allowed_;
|
||||
bool can_rubberband_select_;
|
||||
bool rubberband_selecting_;
|
||||
bool movement_allowed_;
|
||||
bool trimming_allowed_;
|
||||
bool track_movement_allowed_;
|
||||
bool gap_trimming_allowed_;
|
||||
bool can_rubberband_select_;
|
||||
bool rubberband_selecting_;
|
||||
|
||||
Track::Type drag_track_type_;
|
||||
Timeline::MovementMode drag_movement_mode_;
|
||||
Track::Type drag_track_type_;
|
||||
Timeline::MovementMode drag_movement_mode_;
|
||||
|
||||
Block* clicked_item_;
|
||||
|
||||
QPoint drag_global_start_;
|
||||
Block *clicked_item_;
|
||||
|
||||
QPoint drag_global_start_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -24,79 +24,82 @@
|
||||
#include "timeline/timelineundosplit.h"
|
||||
#include "widget/timelinewidget/timelinewidget.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
RazorTool::RazorTool(TimelineWidget* parent) :
|
||||
BeamTool(parent)
|
||||
RazorTool::RazorTool(TimelineWidget *parent)
|
||||
: BeamTool(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void RazorTool::MousePress(TimelineViewMouseEvent *event)
|
||||
{
|
||||
split_tracks_.clear();
|
||||
split_tracks_.clear();
|
||||
|
||||
MouseMove(event);
|
||||
MouseMove(event);
|
||||
}
|
||||
|
||||
void RazorTool::MouseMove(TimelineViewMouseEvent *event)
|
||||
{
|
||||
if (!dragging_) {
|
||||
drag_start_ = ValidatedCoordinate(event->GetCoordinates(true));
|
||||
dragging_ = true;
|
||||
}
|
||||
if (!dragging_) {
|
||||
drag_start_ = ValidatedCoordinate(event->GetCoordinates(true));
|
||||
dragging_ = true;
|
||||
}
|
||||
|
||||
// Split at the current cursor track
|
||||
Track::Reference split_track = event->GetTrack();
|
||||
// Split at the current cursor track
|
||||
Track::Reference split_track = event->GetTrack();
|
||||
|
||||
if (!split_tracks_.contains(split_track)) {
|
||||
split_tracks_.append(split_track);
|
||||
}
|
||||
if (!split_tracks_.contains(split_track)) {
|
||||
split_tracks_.append(split_track);
|
||||
}
|
||||
}
|
||||
|
||||
void RazorTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
Q_UNUSED(event)
|
||||
|
||||
// Always split at the same time
|
||||
rational split_time = drag_start_.GetFrame();
|
||||
// Always split at the same time
|
||||
rational split_time = drag_start_.GetFrame();
|
||||
|
||||
QVector<Block*> blocks_to_split;
|
||||
QVector<Block *> blocks_to_split;
|
||||
|
||||
foreach (const Track::Reference& track_ref, split_tracks_) {
|
||||
Track* track = parent()->GetTrackFromReference(track_ref);
|
||||
foreach (const Track::Reference &track_ref, split_tracks_) {
|
||||
Track *track = parent()->GetTrackFromReference(track_ref);
|
||||
|
||||
if (track == nullptr || track->IsLocked()) {
|
||||
continue;
|
||||
}
|
||||
if (track == nullptr || track->IsLocked()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Block* block_at_time = track->NearestBlockBefore(split_time);
|
||||
Block *block_at_time = track->NearestBlockBefore(split_time);
|
||||
|
||||
// Ensure there's a valid block here
|
||||
ClipBlock *clip_at_time;
|
||||
if (block_at_time
|
||||
&& block_at_time->out() != split_time
|
||||
&& (clip_at_time = dynamic_cast<ClipBlock*>(block_at_time))
|
||||
&& !blocks_to_split.contains(block_at_time)) {
|
||||
blocks_to_split.append(block_at_time);
|
||||
// Ensure there's a valid block here
|
||||
ClipBlock *clip_at_time;
|
||||
if (block_at_time && block_at_time->out() != split_time &&
|
||||
(clip_at_time = dynamic_cast<ClipBlock *>(block_at_time)) &&
|
||||
!blocks_to_split.contains(block_at_time)) {
|
||||
blocks_to_split.append(block_at_time);
|
||||
|
||||
// Add links if no alt is held
|
||||
if (!(event->GetModifiers() & Qt::AltModifier)) {
|
||||
foreach (Block* link, clip_at_time->block_links()) {
|
||||
if (!blocks_to_split.contains(link)) {
|
||||
blocks_to_split.append(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add links if no alt is held
|
||||
if (!(event->GetModifiers() & Qt::AltModifier)) {
|
||||
foreach (Block *link, clip_at_time->block_links()) {
|
||||
if (!blocks_to_split.contains(link)) {
|
||||
blocks_to_split.append(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
split_tracks_.clear();
|
||||
split_tracks_.clear();
|
||||
|
||||
if (!blocks_to_split.isEmpty()) {
|
||||
Core::instance()->undo_stack()->push(new BlockSplitPreservingLinksCommand(blocks_to_split, {split_time}), qApp->translate("RazorTool", "Split Clips"));
|
||||
}
|
||||
if (!blocks_to_split.isEmpty()) {
|
||||
Core::instance()->undo_stack()->push(
|
||||
new BlockSplitPreservingLinksCommand(blocks_to_split,
|
||||
{ split_time }),
|
||||
qApp->translate("RazorTool", "Split Clips"));
|
||||
}
|
||||
|
||||
dragging_ = false;
|
||||
dragging_ = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,19 +23,19 @@
|
||||
|
||||
#include "beam.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class RazorTool : public BeamTool
|
||||
namespace olive
|
||||
{
|
||||
public:
|
||||
RazorTool(TimelineWidget* parent);
|
||||
|
||||
virtual void MousePress(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
|
||||
class RazorTool : public BeamTool {
|
||||
public:
|
||||
RazorTool(TimelineWidget *parent);
|
||||
|
||||
virtual void MousePress(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
QVector<Track::Reference> split_tracks_;
|
||||
QVector<Track::Reference> split_tracks_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -2,87 +2,90 @@
|
||||
|
||||
#include "widget/timelinewidget/timelinewidget.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
RecordTool::RecordTool(TimelineWidget *parent) :
|
||||
BeamTool(parent),
|
||||
ghost_(nullptr)
|
||||
namespace olive
|
||||
{
|
||||
|
||||
RecordTool::RecordTool(TimelineWidget *parent)
|
||||
: BeamTool(parent)
|
||||
, ghost_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void RecordTool::MousePress(TimelineViewMouseEvent *event)
|
||||
{
|
||||
const Track::Reference& track = event->GetTrack();
|
||||
const Track::Reference &track = event->GetTrack();
|
||||
|
||||
// Check if track is locked
|
||||
Track* t = parent()->GetTrackFromReference(track);
|
||||
if (t && t->IsLocked()) {
|
||||
return;
|
||||
}
|
||||
// Check if track is locked
|
||||
Track *t = parent()->GetTrackFromReference(track);
|
||||
if (t && t->IsLocked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (t && t->type() != Track::kAudio) {
|
||||
// We only support audio tracks here
|
||||
return;
|
||||
}
|
||||
if (t && t->type() != Track::kAudio) {
|
||||
// We only support audio tracks here
|
||||
return;
|
||||
}
|
||||
|
||||
drag_start_point_ = ValidatedCoordinate(event->GetCoordinates(true)).GetFrame();
|
||||
drag_start_point_ =
|
||||
ValidatedCoordinate(event->GetCoordinates(true)).GetFrame();
|
||||
|
||||
ghost_ = new TimelineViewGhostItem();
|
||||
ghost_->SetIn(drag_start_point_);
|
||||
ghost_->SetOut(drag_start_point_);
|
||||
ghost_->SetTrack(track);
|
||||
parent()->AddGhost(ghost_);
|
||||
ghost_ = new TimelineViewGhostItem();
|
||||
ghost_->SetIn(drag_start_point_);
|
||||
ghost_->SetOut(drag_start_point_);
|
||||
ghost_->SetTrack(track);
|
||||
parent()->AddGhost(ghost_);
|
||||
|
||||
snap_points_.push_back(drag_start_point_);
|
||||
snap_points_.push_back(drag_start_point_);
|
||||
}
|
||||
|
||||
void RecordTool::MouseMove(TimelineViewMouseEvent *event)
|
||||
{
|
||||
if (!ghost_) {
|
||||
return;
|
||||
}
|
||||
if (!ghost_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate movement
|
||||
rational movement = event->GetFrame() - drag_start_point_;
|
||||
// Calculate movement
|
||||
rational movement = event->GetFrame() - drag_start_point_;
|
||||
|
||||
// Validation: Ensure in point never goes below 0
|
||||
if (movement < -ghost_->GetIn()) {
|
||||
movement = -ghost_->GetIn();
|
||||
}
|
||||
// Validation: Ensure in point never goes below 0
|
||||
if (movement < -ghost_->GetIn()) {
|
||||
movement = -ghost_->GetIn();
|
||||
}
|
||||
|
||||
// Snap movement
|
||||
bool snapped;
|
||||
// Snap movement
|
||||
bool snapped;
|
||||
|
||||
if (Core::instance()->snapping()) {
|
||||
snapped = parent()->SnapPoint(snap_points_, &movement);
|
||||
} else {
|
||||
snapped = false;
|
||||
}
|
||||
if (Core::instance()->snapping()) {
|
||||
snapped = parent()->SnapPoint(snap_points_, &movement);
|
||||
} else {
|
||||
snapped = false;
|
||||
}
|
||||
|
||||
// Make adjustment
|
||||
if (!movement) {
|
||||
ghost_->SetInAdjustment(0);
|
||||
ghost_->SetOutAdjustment(0);
|
||||
} else if (movement > 0) {
|
||||
ghost_->SetInAdjustment(0);
|
||||
ghost_->SetOutAdjustment(movement);
|
||||
} else if (movement < 0) {
|
||||
ghost_->SetInAdjustment(movement);
|
||||
ghost_->SetOutAdjustment(0);
|
||||
}
|
||||
// Make adjustment
|
||||
if (!movement) {
|
||||
ghost_->SetInAdjustment(0);
|
||||
ghost_->SetOutAdjustment(0);
|
||||
} else if (movement > 0) {
|
||||
ghost_->SetInAdjustment(0);
|
||||
ghost_->SetOutAdjustment(movement);
|
||||
} else if (movement < 0) {
|
||||
ghost_->SetInAdjustment(movement);
|
||||
ghost_->SetOutAdjustment(0);
|
||||
}
|
||||
|
||||
Q_UNUSED(snapped)
|
||||
Q_UNUSED(snapped)
|
||||
}
|
||||
|
||||
void RecordTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
{
|
||||
if (ghost_) {
|
||||
emit parent()->RequestCaptureStart(TimeRange(ghost_->GetAdjustedIn(), ghost_->GetAdjustedOut()), ghost_->GetTrack());
|
||||
parent()->ClearGhosts();
|
||||
snap_points_.clear();
|
||||
ghost_ = nullptr;
|
||||
}
|
||||
if (ghost_) {
|
||||
emit parent() -> RequestCaptureStart(
|
||||
TimeRange(ghost_->GetAdjustedIn(), ghost_->GetAdjustedOut()),
|
||||
ghost_->GetTrack());
|
||||
parent()->ClearGhosts();
|
||||
snap_points_.clear();
|
||||
ghost_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,24 +23,23 @@
|
||||
|
||||
#include "beam.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class RecordTool : public BeamTool
|
||||
namespace olive
|
||||
{
|
||||
public:
|
||||
RecordTool(TimelineWidget* parent);
|
||||
|
||||
virtual void MousePress(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
|
||||
class RecordTool : public BeamTool {
|
||||
public:
|
||||
RecordTool(TimelineWidget *parent);
|
||||
|
||||
virtual void MousePress(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
|
||||
|
||||
protected:
|
||||
void MouseMoveInternal(const rational& cursor_frame, bool outwards);
|
||||
void MouseMoveInternal(const rational &cursor_frame, bool outwards);
|
||||
|
||||
TimelineViewGhostItem* ghost_;
|
||||
|
||||
rational drag_start_point_;
|
||||
TimelineViewGhostItem *ghost_;
|
||||
|
||||
rational drag_start_point_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -24,156 +24,170 @@
|
||||
#include "timeline/timelineundoripple.h"
|
||||
#include "ripple.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
RippleTool::RippleTool(TimelineWidget* parent) :
|
||||
PointerTool(parent)
|
||||
namespace olive
|
||||
{
|
||||
SetMovementAllowed(false);
|
||||
SetGapTrimmingAllowed(true);
|
||||
|
||||
RippleTool::RippleTool(TimelineWidget *parent)
|
||||
: PointerTool(parent)
|
||||
{
|
||||
SetMovementAllowed(false);
|
||||
SetGapTrimmingAllowed(true);
|
||||
}
|
||||
|
||||
void RippleTool::InitiateDrag(Block *clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers)
|
||||
void RippleTool::InitiateDrag(Block *clicked_item,
|
||||
Timeline::MovementMode trim_mode,
|
||||
Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
InitiateDragInternal(clicked_item, trim_mode, modifiers, true, true, false);
|
||||
InitiateDragInternal(clicked_item, trim_mode, modifiers, true, true, false);
|
||||
|
||||
if (!parent()->HasGhosts()) {
|
||||
return;
|
||||
}
|
||||
if (!parent()->HasGhosts()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the earliest ripple
|
||||
rational earliest_ripple = RATIONAL_MAX;
|
||||
// Find the earliest ripple
|
||||
rational earliest_ripple = RATIONAL_MAX;
|
||||
|
||||
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
|
||||
rational ghost_ripple_point;
|
||||
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
|
||||
rational ghost_ripple_point;
|
||||
|
||||
if (trim_mode == Timeline::kTrimIn) {
|
||||
ghost_ripple_point = ghost->GetIn();
|
||||
} else {
|
||||
ghost_ripple_point = ghost->GetOut();
|
||||
}
|
||||
if (trim_mode == Timeline::kTrimIn) {
|
||||
ghost_ripple_point = ghost->GetIn();
|
||||
} else {
|
||||
ghost_ripple_point = ghost->GetOut();
|
||||
}
|
||||
|
||||
earliest_ripple = qMin(earliest_ripple, ghost_ripple_point);
|
||||
}
|
||||
earliest_ripple = qMin(earliest_ripple, ghost_ripple_point);
|
||||
}
|
||||
|
||||
// For each track that does NOT have a ghost, we need to make one for Gaps
|
||||
foreach (Track* track, sequence()->GetTracks()) {
|
||||
if (track->IsLocked()) {
|
||||
continue;
|
||||
}
|
||||
// For each track that does NOT have a ghost, we need to make one for Gaps
|
||||
foreach (Track *track, sequence()->GetTracks()) {
|
||||
if (track->IsLocked()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Determine if we've already created a ghost on this track
|
||||
bool ghost_on_this_track_exists = false;
|
||||
// Determine if we've already created a ghost on this track
|
||||
bool ghost_on_this_track_exists = false;
|
||||
|
||||
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
|
||||
if (parent()->GetTrackFromReference(ghost->GetTrack()) == track) {
|
||||
ghost_on_this_track_exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
|
||||
if (parent()->GetTrackFromReference(ghost->GetTrack()) == track) {
|
||||
ghost_on_this_track_exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If there's no ghost on this track, create one
|
||||
if (!ghost_on_this_track_exists) {
|
||||
// Find the block that starts just after or at the ripple point
|
||||
Block* block_after_ripple = track->NearestBlockAfterOrAt(earliest_ripple);
|
||||
// If there's no ghost on this track, create one
|
||||
if (!ghost_on_this_track_exists) {
|
||||
// Find the block that starts just after or at the ripple point
|
||||
Block *block_after_ripple =
|
||||
track->NearestBlockAfterOrAt(earliest_ripple);
|
||||
|
||||
// Exception for out-transitions, do not create a gap between them
|
||||
if (block_after_ripple) {
|
||||
if (ClipBlock *prev_clip = dynamic_cast<ClipBlock*>(block_after_ripple->previous())) {
|
||||
if (prev_clip->out_transition() == block_after_ripple) {
|
||||
block_after_ripple = block_after_ripple->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Exception for out-transitions, do not create a gap between them
|
||||
if (block_after_ripple) {
|
||||
if (ClipBlock *prev_clip = dynamic_cast<ClipBlock *>(
|
||||
block_after_ripple->previous())) {
|
||||
if (prev_clip->out_transition() == block_after_ripple) {
|
||||
block_after_ripple = block_after_ripple->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If block is null, there will be no blocks after to ripple
|
||||
if (block_after_ripple) {
|
||||
TimelineViewGhostItem* ghost;
|
||||
// If block is null, there will be no blocks after to ripple
|
||||
if (block_after_ripple) {
|
||||
TimelineViewGhostItem *ghost;
|
||||
|
||||
if (dynamic_cast<GapBlock*>(block_after_ripple)) {
|
||||
// If this Block is already a Gap, ghost it now
|
||||
ghost = AddGhostFromBlock(block_after_ripple, trim_mode);
|
||||
} else {
|
||||
// Well we need to ripple SOMETHING, it'll either be the previous block if it's a gap
|
||||
// or we'll have to create a new gap ourselves
|
||||
Block* previous = block_after_ripple->previous();
|
||||
if (dynamic_cast<GapBlock *>(block_after_ripple)) {
|
||||
// If this Block is already a Gap, ghost it now
|
||||
ghost = AddGhostFromBlock(block_after_ripple, trim_mode);
|
||||
} else {
|
||||
// Well we need to ripple SOMETHING, it'll either be the previous block if it's a gap
|
||||
// or we'll have to create a new gap ourselves
|
||||
Block *previous = block_after_ripple->previous();
|
||||
|
||||
if (dynamic_cast<GapBlock*>(previous)) {
|
||||
// Previous is a gap, that'll make a fine substitute
|
||||
ghost = AddGhostFromBlock(previous, trim_mode);
|
||||
} else {
|
||||
// Previous is not a gap, we'll have to insert one there ourselves
|
||||
ghost = AddGhostFromNull(block_after_ripple->in(), block_after_ripple->in(), track->ToReference(), trim_mode);
|
||||
ghost->SetData(TimelineViewGhostItem::kReferenceBlock, QtUtils::PtrToValue(block_after_ripple));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dynamic_cast<GapBlock *>(previous)) {
|
||||
// Previous is a gap, that'll make a fine substitute
|
||||
ghost = AddGhostFromBlock(previous, trim_mode);
|
||||
} else {
|
||||
// Previous is not a gap, we'll have to insert one there ourselves
|
||||
ghost = AddGhostFromNull(block_after_ripple->in(),
|
||||
block_after_ripple->in(),
|
||||
track->ToReference(),
|
||||
trim_mode);
|
||||
ghost->SetData(TimelineViewGhostItem::kReferenceBlock,
|
||||
QtUtils::PtrToValue(block_after_ripple));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RippleTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
Q_UNUSED(event)
|
||||
|
||||
if (parent()->HasGhosts()) {
|
||||
QVector< QHash<Track*, TrackListRippleToolCommand::RippleInfo> > info_list(Track::kCount);
|
||||
if (parent()->HasGhosts()) {
|
||||
QVector<QHash<Track *, TrackListRippleToolCommand::RippleInfo>>
|
||||
info_list(Track::kCount);
|
||||
|
||||
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
|
||||
if (!ghost->HasBeenAdjusted()) {
|
||||
continue;
|
||||
}
|
||||
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
|
||||
if (!ghost->HasBeenAdjusted()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Track* track = parent()->GetTrackFromReference(ghost->GetTrack());
|
||||
Track *track = parent()->GetTrackFromReference(ghost->GetTrack());
|
||||
|
||||
TrackListRippleToolCommand::RippleInfo info;
|
||||
Block* b = QtUtils::ValueToPtr<Block>(ghost->GetData(TimelineViewGhostItem::kAttachedBlock));
|
||||
TrackListRippleToolCommand::RippleInfo info;
|
||||
Block *b = QtUtils::ValueToPtr<Block>(
|
||||
ghost->GetData(TimelineViewGhostItem::kAttachedBlock));
|
||||
|
||||
if (b) {
|
||||
info.block = b;
|
||||
info.append_gap = false;
|
||||
} else {
|
||||
info.block = QtUtils::ValueToPtr<Block>(ghost->GetData(TimelineViewGhostItem::kReferenceBlock));
|
||||
info.append_gap = true;
|
||||
}
|
||||
if (b) {
|
||||
info.block = b;
|
||||
info.append_gap = false;
|
||||
} else {
|
||||
info.block = QtUtils::ValueToPtr<Block>(
|
||||
ghost->GetData(TimelineViewGhostItem::kReferenceBlock));
|
||||
info.append_gap = true;
|
||||
}
|
||||
|
||||
info_list[track->type()].insert(track, info);
|
||||
}
|
||||
info_list[track->type()].insert(track, info);
|
||||
}
|
||||
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
rational movement;
|
||||
rational movement;
|
||||
|
||||
if (drag_movement_mode() == Timeline::kTrimOut) {
|
||||
movement = parent()->GetGhostItems().first()->GetOutAdjustment();
|
||||
} else {
|
||||
movement = parent()->GetGhostItems().first()->GetInAdjustment();
|
||||
}
|
||||
if (drag_movement_mode() == Timeline::kTrimOut) {
|
||||
movement = parent()->GetGhostItems().first()->GetOutAdjustment();
|
||||
} else {
|
||||
movement = parent()->GetGhostItems().first()->GetInAdjustment();
|
||||
}
|
||||
|
||||
for (int i=0;i<info_list.size();i++) {
|
||||
if (!info_list.at(i).isEmpty()) {
|
||||
command->add_child(new TrackListRippleToolCommand(sequence()->track_list(static_cast<Track::Type>(i)),
|
||||
info_list.at(i),
|
||||
movement,
|
||||
drag_movement_mode()));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < info_list.size(); i++) {
|
||||
if (!info_list.at(i).isEmpty()) {
|
||||
command->add_child(new TrackListRippleToolCommand(
|
||||
sequence()->track_list(static_cast<Track::Type>(i)),
|
||||
info_list.at(i), movement, drag_movement_mode()));
|
||||
}
|
||||
}
|
||||
|
||||
if (command->child_count() > 0) {
|
||||
TimelineWidgetSelections new_sel = parent()->GetSelections();
|
||||
TimelineViewGhostItem* reference_ghost = parent()->GetGhostItems().first();
|
||||
if (drag_movement_mode() == Timeline::kTrimIn) {
|
||||
new_sel.TrimOut(-reference_ghost->GetInAdjustment());
|
||||
} else {
|
||||
new_sel.TrimOut(reference_ghost->GetOutAdjustment());
|
||||
}
|
||||
command->add_child(new TimelineWidget::SetSelectionsCommand(parent(), new_sel, parent()->GetSelections(), false));
|
||||
if (command->child_count() > 0) {
|
||||
TimelineWidgetSelections new_sel = parent()->GetSelections();
|
||||
TimelineViewGhostItem *reference_ghost =
|
||||
parent()->GetGhostItems().first();
|
||||
if (drag_movement_mode() == Timeline::kTrimIn) {
|
||||
new_sel.TrimOut(-reference_ghost->GetInAdjustment());
|
||||
} else {
|
||||
new_sel.TrimOut(reference_ghost->GetOutAdjustment());
|
||||
}
|
||||
command->add_child(new TimelineWidget::SetSelectionsCommand(
|
||||
parent(), new_sel, parent()->GetSelections(), false));
|
||||
|
||||
Core::instance()->undo_stack()->push(command, qApp->translate("RippleTool", "Rippled Clips"));
|
||||
} else {
|
||||
delete command;
|
||||
}
|
||||
}
|
||||
Core::instance()->undo_stack()->push(
|
||||
command, qApp->translate("RippleTool", "Rippled Clips"));
|
||||
} else {
|
||||
delete command;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,16 +23,19 @@
|
||||
|
||||
#include "pointer.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class RippleTool : public PointerTool
|
||||
namespace olive
|
||||
{
|
||||
public:
|
||||
RippleTool(TimelineWidget* parent);
|
||||
protected:
|
||||
virtual void FinishDrag(TimelineViewMouseEvent *event) override;
|
||||
|
||||
virtual void InitiateDrag(Block* clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers) override;
|
||||
class RippleTool : public PointerTool {
|
||||
public:
|
||||
RippleTool(TimelineWidget *parent);
|
||||
|
||||
protected:
|
||||
virtual void FinishDrag(TimelineViewMouseEvent *event) override;
|
||||
|
||||
virtual void InitiateDrag(Block *clicked_item,
|
||||
Timeline::MovementMode trim_mode,
|
||||
Qt::KeyboardModifiers modifiers) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -24,18 +24,22 @@
|
||||
#include "node/nodeundo.h"
|
||||
#include "rolling.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
RollingTool::RollingTool(TimelineWidget* parent) :
|
||||
PointerTool(parent)
|
||||
namespace olive
|
||||
{
|
||||
SetMovementAllowed(false);
|
||||
SetGapTrimmingAllowed(true);
|
||||
}
|
||||
|
||||
void RollingTool::InitiateDrag(Block *clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers)
|
||||
RollingTool::RollingTool(TimelineWidget *parent)
|
||||
: PointerTool(parent)
|
||||
{
|
||||
InitiateDragInternal(clicked_item, trim_mode, modifiers, false, true, false);
|
||||
SetMovementAllowed(false);
|
||||
SetGapTrimmingAllowed(true);
|
||||
}
|
||||
|
||||
void RollingTool::InitiateDrag(Block *clicked_item,
|
||||
Timeline::MovementMode trim_mode,
|
||||
Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
InitiateDragInternal(clicked_item, trim_mode, modifiers, false, true,
|
||||
false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,15 +23,17 @@
|
||||
|
||||
#include "pointer.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class RollingTool : public PointerTool
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class RollingTool : public PointerTool {
|
||||
public:
|
||||
RollingTool(TimelineWidget* parent);
|
||||
RollingTool(TimelineWidget *parent);
|
||||
|
||||
protected:
|
||||
virtual void InitiateDrag(Block* clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers) override;
|
||||
virtual void InitiateDrag(Block *clicked_item,
|
||||
Timeline::MovementMode trim_mode,
|
||||
Qt::KeyboardModifiers modifiers) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -24,19 +24,22 @@
|
||||
#include "node/nodeundo.h"
|
||||
#include "slide.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
SlideTool::SlideTool(TimelineWidget* parent) :
|
||||
PointerTool(parent)
|
||||
namespace olive
|
||||
{
|
||||
SetTrimmingAllowed(false);
|
||||
SetTrackMovementAllowed(false);
|
||||
SetGapTrimmingAllowed(true);
|
||||
}
|
||||
|
||||
void SlideTool::InitiateDrag(Block *clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers)
|
||||
SlideTool::SlideTool(TimelineWidget *parent)
|
||||
: PointerTool(parent)
|
||||
{
|
||||
InitiateDragInternal(clicked_item, trim_mode, modifiers, false, true, true);
|
||||
SetTrimmingAllowed(false);
|
||||
SetTrackMovementAllowed(false);
|
||||
SetGapTrimmingAllowed(true);
|
||||
}
|
||||
|
||||
void SlideTool::InitiateDrag(Block *clicked_item,
|
||||
Timeline::MovementMode trim_mode,
|
||||
Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
InitiateDragInternal(clicked_item, trim_mode, modifiers, false, true, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,16 +23,17 @@
|
||||
|
||||
#include "pointer.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class SlideTool : public PointerTool
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class SlideTool : public PointerTool {
|
||||
public:
|
||||
SlideTool(TimelineWidget* parent);
|
||||
SlideTool(TimelineWidget *parent);
|
||||
|
||||
protected:
|
||||
virtual void InitiateDrag(Block* clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers) override;
|
||||
|
||||
virtual void InitiateDrag(Block *clicked_item,
|
||||
Timeline::MovementMode trim_mode,
|
||||
Qt::KeyboardModifiers modifiers) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -26,61 +26,66 @@
|
||||
#include "timeline/timelineundogeneral.h"
|
||||
#include "widget/timelinewidget/timelinewidget.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
SlipTool::SlipTool(TimelineWidget *parent) :
|
||||
PointerTool(parent)
|
||||
namespace olive
|
||||
{
|
||||
SetTrimmingAllowed(false);
|
||||
SetTrackMovementAllowed(false);
|
||||
|
||||
SlipTool::SlipTool(TimelineWidget *parent)
|
||||
: PointerTool(parent)
|
||||
{
|
||||
SetTrimmingAllowed(false);
|
||||
SetTrackMovementAllowed(false);
|
||||
}
|
||||
|
||||
void SlipTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
|
||||
{
|
||||
// Determine frame movement
|
||||
rational time_movement = drag_start_.GetFrame() - mouse_pos.GetFrame();
|
||||
// Determine frame movement
|
||||
rational time_movement = drag_start_.GetFrame() - mouse_pos.GetFrame();
|
||||
|
||||
// Validate slip (enforce all ghosts moving in legal ways)
|
||||
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
|
||||
if (ghost->GetMediaIn() + time_movement < 0) {
|
||||
time_movement = -ghost->GetMediaIn();
|
||||
}
|
||||
}
|
||||
// Validate slip (enforce all ghosts moving in legal ways)
|
||||
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
|
||||
if (ghost->GetMediaIn() + time_movement < 0) {
|
||||
time_movement = -ghost->GetMediaIn();
|
||||
}
|
||||
}
|
||||
|
||||
// Perform slip
|
||||
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
|
||||
ghost->SetMediaInAdjustment(time_movement);
|
||||
}
|
||||
// Perform slip
|
||||
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
|
||||
ghost->SetMediaInAdjustment(time_movement);
|
||||
}
|
||||
|
||||
// Generate tooltip and force it to to update (otherwise the tooltip won't move as written in the
|
||||
// documentation, and could get in the way of the cursor)
|
||||
rational tooltip_timebase = parent()->GetTimebaseForTrackType(drag_start_.GetTrack().type());
|
||||
QToolTip::hideText();
|
||||
QToolTip::showText(QCursor::pos(),
|
||||
QString::fromStdString(Timecode::time_to_timecode(time_movement,
|
||||
tooltip_timebase,
|
||||
Core::instance()->GetTimecodeDisplay(),
|
||||
true)),
|
||||
parent());
|
||||
// Generate tooltip and force it to to update (otherwise the tooltip won't move as written in the
|
||||
// documentation, and could get in the way of the cursor)
|
||||
rational tooltip_timebase =
|
||||
parent()->GetTimebaseForTrackType(drag_start_.GetTrack().type());
|
||||
QToolTip::hideText();
|
||||
QToolTip::showText(QCursor::pos(),
|
||||
QString::fromStdString(Timecode::time_to_timecode(
|
||||
time_movement, tooltip_timebase,
|
||||
Core::instance()->GetTimecodeDisplay(), true)),
|
||||
parent());
|
||||
}
|
||||
|
||||
void SlipTool::FinishDrag(TimelineViewMouseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
Q_UNUSED(event)
|
||||
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
// Find earliest point to ripple around
|
||||
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
|
||||
Block* b = QtUtils::ValueToPtr<Block>(ghost->GetData(TimelineViewGhostItem::kAttachedBlock));
|
||||
// Find earliest point to ripple around
|
||||
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
|
||||
Block *b = QtUtils::ValueToPtr<Block>(
|
||||
ghost->GetData(TimelineViewGhostItem::kAttachedBlock));
|
||||
|
||||
ClipBlock *cb = dynamic_cast<ClipBlock*>(b);
|
||||
if (cb) {
|
||||
command->add_child(new BlockSetMediaInCommand(cb, ghost->GetAdjustedMediaIn()));
|
||||
}
|
||||
}
|
||||
ClipBlock *cb = dynamic_cast<ClipBlock *>(b);
|
||||
if (cb) {
|
||||
command->add_child(
|
||||
new BlockSetMediaInCommand(cb, ghost->GetAdjustedMediaIn()));
|
||||
}
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(command, qApp->translate("SlipTool", "Slipped %1 Clip(s)").arg(parent()->GetGhostItems().size()));
|
||||
Core::instance()->undo_stack()->push(
|
||||
command, qApp->translate("SlipTool", "Slipped %1 Clip(s)")
|
||||
.arg(parent()->GetGhostItems().size()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,16 +23,16 @@
|
||||
|
||||
#include "pointer.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class SlipTool : public PointerTool
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class SlipTool : public PointerTool {
|
||||
public:
|
||||
SlipTool(TimelineWidget* parent);
|
||||
SlipTool(TimelineWidget *parent);
|
||||
|
||||
protected:
|
||||
virtual void ProcessDrag(const TimelineCoordinate &mouse_pos) override;
|
||||
virtual void FinishDrag(TimelineViewMouseEvent *event) override;
|
||||
virtual void ProcessDrag(const TimelineCoordinate &mouse_pos) override;
|
||||
virtual void FinishDrag(TimelineViewMouseEvent *event) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -22,13 +22,14 @@
|
||||
|
||||
#include "node/block/transition/transition.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
const int TimelineTool::kDefaultDistanceFromOutput = -4;
|
||||
|
||||
TimelineTool::TimelineTool(TimelineWidget *parent) :
|
||||
dragging_(false),
|
||||
parent_(parent)
|
||||
TimelineTool::TimelineTool(TimelineWidget *parent)
|
||||
: dragging_(false)
|
||||
, parent_(parent)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -38,110 +39,116 @@ TimelineTool::~TimelineTool()
|
||||
|
||||
TimelineWidget *TimelineTool::parent()
|
||||
{
|
||||
return parent_;
|
||||
return parent_;
|
||||
}
|
||||
|
||||
Sequence *TimelineTool::sequence()
|
||||
{
|
||||
return parent_->sequence();
|
||||
return parent_->sequence();
|
||||
}
|
||||
|
||||
Timeline::MovementMode TimelineTool::FlipTrimMode(const Timeline::MovementMode &trim_mode)
|
||||
Timeline::MovementMode
|
||||
TimelineTool::FlipTrimMode(const Timeline::MovementMode &trim_mode)
|
||||
{
|
||||
if (trim_mode == Timeline::kTrimIn) {
|
||||
return Timeline::kTrimOut;
|
||||
}
|
||||
if (trim_mode == Timeline::kTrimIn) {
|
||||
return Timeline::kTrimOut;
|
||||
}
|
||||
|
||||
if (trim_mode == Timeline::kTrimOut) {
|
||||
return Timeline::kTrimIn;
|
||||
}
|
||||
if (trim_mode == Timeline::kTrimOut) {
|
||||
return Timeline::kTrimIn;
|
||||
}
|
||||
|
||||
return trim_mode;
|
||||
return trim_mode;
|
||||
}
|
||||
|
||||
rational TimelineTool::SnapMovementToTimebase(const rational &start, rational movement, const rational &timebase)
|
||||
rational TimelineTool::SnapMovementToTimebase(const rational &start,
|
||||
rational movement,
|
||||
const rational &timebase)
|
||||
{
|
||||
rational proposed_position = start + movement;
|
||||
rational snapped = Timecode::snap_time_to_timebase(proposed_position, timebase);
|
||||
rational proposed_position = start + movement;
|
||||
rational snapped =
|
||||
Timecode::snap_time_to_timebase(proposed_position, timebase);
|
||||
|
||||
if (proposed_position != snapped) {
|
||||
movement += snapped - proposed_position;
|
||||
}
|
||||
if (proposed_position != snapped) {
|
||||
movement += snapped - proposed_position;
|
||||
}
|
||||
|
||||
return movement;
|
||||
return movement;
|
||||
}
|
||||
|
||||
rational TimelineTool::ValidateTimeMovement(rational movement)
|
||||
{
|
||||
bool first_ghost = true;
|
||||
bool first_ghost = true;
|
||||
|
||||
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
|
||||
if (ghost->GetMode() != Timeline::kMove) {
|
||||
continue;
|
||||
}
|
||||
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
|
||||
if (ghost->GetMode() != Timeline::kMove) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prevents any ghosts from going below 0:00:00 time
|
||||
if (ghost->GetIn() + movement < 0) {
|
||||
movement = -ghost->GetIn();
|
||||
} else if (first_ghost) {
|
||||
// Ensure ghost is snapped to a grid
|
||||
movement = SnapMovementToTimebase(ghost->GetIn(), movement, parent()->GetTimebaseForTrackType(ghost->GetTrack().type()));
|
||||
// Prevents any ghosts from going below 0:00:00 time
|
||||
if (ghost->GetIn() + movement < 0) {
|
||||
movement = -ghost->GetIn();
|
||||
} else if (first_ghost) {
|
||||
// Ensure ghost is snapped to a grid
|
||||
movement = SnapMovementToTimebase(
|
||||
ghost->GetIn(), movement,
|
||||
parent()->GetTimebaseForTrackType(ghost->GetTrack().type()));
|
||||
|
||||
first_ghost = false;
|
||||
}
|
||||
}
|
||||
first_ghost = false;
|
||||
}
|
||||
}
|
||||
|
||||
return movement;
|
||||
return movement;
|
||||
}
|
||||
|
||||
int TimelineTool::ValidateTrackMovement(int movement, const QVector<TimelineViewGhostItem*>& ghosts)
|
||||
int TimelineTool::ValidateTrackMovement(
|
||||
int movement, const QVector<TimelineViewGhostItem *> &ghosts)
|
||||
{
|
||||
foreach (TimelineViewGhostItem* ghost, ghosts) {
|
||||
if (ghost->GetMode() != Timeline::kMove) {
|
||||
continue;
|
||||
}
|
||||
foreach (TimelineViewGhostItem *ghost, ghosts) {
|
||||
if (ghost->GetMode() != Timeline::kMove) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ghost->GetCanMoveTracks()) {
|
||||
if (!ghost->GetCanMoveTracks()) {
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
} else if (ghost->GetTrack().index() + movement < 0) {
|
||||
// Prevents any ghosts from going to a non-existent negative track
|
||||
movement = -ghost->GetTrack().index();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (ghost->GetTrack().index() + movement < 0) {
|
||||
|
||||
// Prevents any ghosts from going to a non-existent negative track
|
||||
movement = -ghost->GetTrack().index();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return movement;
|
||||
return movement;
|
||||
}
|
||||
|
||||
void TimelineTool::GetGhostData(rational *earliest_point, rational *latest_point)
|
||||
void TimelineTool::GetGhostData(rational *earliest_point,
|
||||
rational *latest_point)
|
||||
{
|
||||
rational ep = RATIONAL_MAX;
|
||||
rational lp = RATIONAL_MIN;
|
||||
rational ep = RATIONAL_MAX;
|
||||
rational lp = RATIONAL_MIN;
|
||||
|
||||
foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) {
|
||||
ep = qMin(ep, ghost->GetAdjustedIn());
|
||||
lp = qMax(lp, ghost->GetAdjustedOut());
|
||||
}
|
||||
foreach (TimelineViewGhostItem *ghost, parent()->GetGhostItems()) {
|
||||
ep = qMin(ep, ghost->GetAdjustedIn());
|
||||
lp = qMax(lp, ghost->GetAdjustedOut());
|
||||
}
|
||||
|
||||
if (earliest_point) {
|
||||
*earliest_point = ep;
|
||||
}
|
||||
if (earliest_point) {
|
||||
*earliest_point = ep;
|
||||
}
|
||||
|
||||
if (latest_point) {
|
||||
*latest_point = lp;
|
||||
}
|
||||
if (latest_point) {
|
||||
*latest_point = lp;
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineTool::InsertGapsAtGhostDestination(olive::MultiUndoCommand *command)
|
||||
{
|
||||
rational earliest_point, latest_point;
|
||||
rational earliest_point, latest_point;
|
||||
|
||||
GetGhostData(&earliest_point, &latest_point);
|
||||
GetGhostData(&earliest_point, &latest_point);
|
||||
|
||||
parent()->InsertGapsAt(earliest_point, latest_point - earliest_point, command);
|
||||
parent()->InsertGapsAt(earliest_point, latest_point - earliest_point,
|
||||
command);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,67 +26,88 @@
|
||||
#include "widget/timelinewidget/view/timelineviewghostitem.h"
|
||||
#include "widget/timelinewidget/view/timelineviewmouseevent.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class TimelineWidget;
|
||||
|
||||
class TimelineTool
|
||||
{
|
||||
class TimelineTool {
|
||||
public:
|
||||
TimelineTool(TimelineWidget* parent);
|
||||
virtual ~TimelineTool();
|
||||
TimelineTool(TimelineWidget *parent);
|
||||
virtual ~TimelineTool();
|
||||
|
||||
virtual void MousePress(TimelineViewMouseEvent *){}
|
||||
virtual void MouseMove(TimelineViewMouseEvent *){}
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *){}
|
||||
virtual void MouseDoubleClick(TimelineViewMouseEvent *){}
|
||||
virtual void MousePress(TimelineViewMouseEvent *)
|
||||
{
|
||||
}
|
||||
virtual void MouseMove(TimelineViewMouseEvent *)
|
||||
{
|
||||
}
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *)
|
||||
{
|
||||
}
|
||||
virtual void MouseDoubleClick(TimelineViewMouseEvent *)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void HoverMove(TimelineViewMouseEvent *){}
|
||||
virtual void HoverMove(TimelineViewMouseEvent *)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void DragEnter(TimelineViewMouseEvent *){}
|
||||
virtual void DragMove(TimelineViewMouseEvent *){}
|
||||
virtual void DragLeave(QDragLeaveEvent *){}
|
||||
virtual void DragDrop(TimelineViewMouseEvent *){}
|
||||
virtual void DragEnter(TimelineViewMouseEvent *)
|
||||
{
|
||||
}
|
||||
virtual void DragMove(TimelineViewMouseEvent *)
|
||||
{
|
||||
}
|
||||
virtual void DragLeave(QDragLeaveEvent *)
|
||||
{
|
||||
}
|
||||
virtual void DragDrop(TimelineViewMouseEvent *)
|
||||
{
|
||||
}
|
||||
|
||||
TimelineWidget* parent();
|
||||
TimelineWidget *parent();
|
||||
|
||||
Sequence* sequence();
|
||||
Sequence *sequence();
|
||||
|
||||
static Timeline::MovementMode FlipTrimMode(const Timeline::MovementMode& trim_mode);
|
||||
static Timeline::MovementMode
|
||||
FlipTrimMode(const Timeline::MovementMode &trim_mode);
|
||||
|
||||
static rational SnapMovementToTimebase(const rational& start, rational movement, const rational& timebase);
|
||||
static rational SnapMovementToTimebase(const rational &start,
|
||||
rational movement,
|
||||
const rational &timebase);
|
||||
|
||||
protected:
|
||||
/**
|
||||
/**
|
||||
* @brief Validates Ghosts that are moving horizontally (time-based)
|
||||
*
|
||||
* Validation is the process of ensuring that whatever movements the user is making are "valid" and "legal". This
|
||||
* function's validation ensures that no Ghost's in point ends up in a negative timecode.
|
||||
*/
|
||||
rational ValidateTimeMovement(rational movement);
|
||||
rational ValidateTimeMovement(rational movement);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Validates Ghosts that are moving vertically (track-based)
|
||||
*
|
||||
* This function's validation ensures that no Ghost's track ends up in a negative (non-existent) track.
|
||||
*/
|
||||
int ValidateTrackMovement(int movement, const QVector<TimelineViewGhostItem *> &ghosts);
|
||||
int ValidateTrackMovement(int movement,
|
||||
const QVector<TimelineViewGhostItem *> &ghosts);
|
||||
|
||||
void GetGhostData(rational *earliest_point, rational *latest_point);
|
||||
void GetGhostData(rational *earliest_point, rational *latest_point);
|
||||
|
||||
void InsertGapsAtGhostDestination(MultiUndoCommand* command);
|
||||
void InsertGapsAtGhostDestination(MultiUndoCommand *command);
|
||||
|
||||
std::vector<rational> snap_points_;
|
||||
std::vector<rational> snap_points_;
|
||||
|
||||
bool dragging_;
|
||||
bool dragging_;
|
||||
|
||||
TimelineCoordinate drag_start_;
|
||||
TimelineCoordinate drag_start_;
|
||||
|
||||
static const int kDefaultDistanceFromOutput;
|
||||
static const int kDefaultDistanceFromOutput;
|
||||
|
||||
private:
|
||||
TimelineWidget* parent_;
|
||||
|
||||
TimelineWidget *parent_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -24,73 +24,77 @@
|
||||
#include "node/output/track/track.h"
|
||||
#include "widget/timelinewidget/timelinewidget.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
TrackSelectTool::TrackSelectTool(TimelineWidget *parent) :
|
||||
PointerTool(parent)
|
||||
TrackSelectTool::TrackSelectTool(TimelineWidget *parent)
|
||||
: PointerTool(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void TrackSelectTool::MousePress(TimelineViewMouseEvent *event)
|
||||
{
|
||||
QVector<Block*> blocks;
|
||||
bool forward = !(event->GetModifiers() & Qt::ControlModifier);
|
||||
QVector<Block *> blocks;
|
||||
bool forward = !(event->GetModifiers() & Qt::ControlModifier);
|
||||
|
||||
parent()->DeselectAll();
|
||||
parent()->DeselectAll();
|
||||
|
||||
if (event->GetModifiers() & Qt::ShiftModifier) {
|
||||
// Track only
|
||||
Track *track = parent()->GetTrackFromReference(event->GetTrack());
|
||||
if (track) {
|
||||
SelectBlocksOnTrack(track, event, &blocks, forward);
|
||||
}
|
||||
} else {
|
||||
// All tracks
|
||||
foreach (Track *track, parent()->sequence()->GetTracks()) {
|
||||
SelectBlocksOnTrack(track, event, &blocks, forward);
|
||||
}
|
||||
}
|
||||
if (event->GetModifiers() & Qt::ShiftModifier) {
|
||||
// Track only
|
||||
Track *track = parent()->GetTrackFromReference(event->GetTrack());
|
||||
if (track) {
|
||||
SelectBlocksOnTrack(track, event, &blocks, forward);
|
||||
}
|
||||
} else {
|
||||
// All tracks
|
||||
foreach (Track *track, parent()->sequence()->GetTracks()) {
|
||||
SelectBlocksOnTrack(track, event, &blocks, forward);
|
||||
}
|
||||
}
|
||||
|
||||
if (!blocks.isEmpty()) {
|
||||
parent()->SignalSelectedBlocks(blocks);
|
||||
set_drag_movement_mode(Timeline::kMove);
|
||||
SetClickedItem(blocks.first());
|
||||
drag_start_ = event->GetCoordinates();
|
||||
} else {
|
||||
set_drag_movement_mode(Timeline::kNone);
|
||||
}
|
||||
if (!blocks.isEmpty()) {
|
||||
parent()->SignalSelectedBlocks(blocks);
|
||||
set_drag_movement_mode(Timeline::kMove);
|
||||
SetClickedItem(blocks.first());
|
||||
drag_start_ = event->GetCoordinates();
|
||||
} else {
|
||||
set_drag_movement_mode(Timeline::kNone);
|
||||
}
|
||||
}
|
||||
|
||||
void TrackSelectTool::SelectBlocksOnTrack(Track *track, TimelineViewMouseEvent *event, QVector<Block*> *blocks, bool forward)
|
||||
void TrackSelectTool::SelectBlocksOnTrack(Track *track,
|
||||
TimelineViewMouseEvent *event,
|
||||
QVector<Block *> *blocks,
|
||||
bool forward)
|
||||
{
|
||||
Block *b = track->NearestBlockBeforeOrAt(event->GetFrame());
|
||||
Block *b = track->NearestBlockBeforeOrAt(event->GetFrame());
|
||||
|
||||
if (!b && !track->Blocks().isEmpty() && !forward) {
|
||||
// Fallback to first or last block in track
|
||||
b = track->Blocks().last();
|
||||
}
|
||||
if (!b && !track->Blocks().isEmpty() && !forward) {
|
||||
// Fallback to first or last block in track
|
||||
b = track->Blocks().last();
|
||||
}
|
||||
|
||||
while (b) {
|
||||
if (!dynamic_cast<GapBlock*>(b)) {
|
||||
if (!blocks->contains(b)) {
|
||||
parent()->AddSelection(b);
|
||||
blocks->append(b);
|
||||
}
|
||||
while (b) {
|
||||
if (!dynamic_cast<GapBlock *>(b)) {
|
||||
if (!blocks->contains(b)) {
|
||||
parent()->AddSelection(b);
|
||||
blocks->append(b);
|
||||
}
|
||||
|
||||
if (!(event->GetModifiers() & Qt::AltModifier)) {
|
||||
if (ClipBlock *clip = dynamic_cast<ClipBlock*>(b)) {
|
||||
foreach (Block *link, clip->block_links()) {
|
||||
if (!blocks->contains(link)) {
|
||||
parent()->AddSelection(link);
|
||||
blocks->append(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!(event->GetModifiers() & Qt::AltModifier)) {
|
||||
if (ClipBlock *clip = dynamic_cast<ClipBlock *>(b)) {
|
||||
foreach (Block *link, clip->block_links()) {
|
||||
if (!blocks->contains(link)) {
|
||||
parent()->AddSelection(link);
|
||||
blocks->append(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b = forward ? b->next() : b->previous();
|
||||
}
|
||||
b = forward ? b->next() : b->previous();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,18 +23,18 @@
|
||||
|
||||
#include "pointer.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class TrackSelectTool : public PointerTool
|
||||
namespace olive
|
||||
{
|
||||
public:
|
||||
TrackSelectTool(TimelineWidget *parent);
|
||||
|
||||
virtual void MousePress(TimelineViewMouseEvent *event) override;
|
||||
class TrackSelectTool : public PointerTool {
|
||||
public:
|
||||
TrackSelectTool(TimelineWidget *parent);
|
||||
|
||||
virtual void MousePress(TimelineViewMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
void SelectBlocksOnTrack(Track *track, TimelineViewMouseEvent *event, QVector<Block *> *blocks, bool forward);
|
||||
|
||||
void SelectBlocksOnTrack(Track *track, TimelineViewMouseEvent *event,
|
||||
QVector<Block *> *blocks, bool forward);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -27,209 +27,238 @@
|
||||
#include "timeline/timelineundopointer.h"
|
||||
#include "transition.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
TransitionTool::TransitionTool(TimelineWidget *parent) :
|
||||
AddTool(parent)
|
||||
TransitionTool::TransitionTool(TimelineWidget *parent)
|
||||
: AddTool(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void TransitionTool::HoverMove(TimelineViewMouseEvent *event)
|
||||
{
|
||||
ClipBlock *primary = nullptr;
|
||||
ClipBlock *secondary = nullptr;
|
||||
Timeline::MovementMode trim_mode = Timeline::kNone;
|
||||
rational transition_start_point;
|
||||
ClipBlock *primary = nullptr;
|
||||
ClipBlock *secondary = nullptr;
|
||||
Timeline::MovementMode trim_mode = Timeline::kNone;
|
||||
rational transition_start_point;
|
||||
|
||||
GetBlocksAtCoord(event->GetCoordinates(), &primary, &secondary, &trim_mode, &transition_start_point);
|
||||
GetBlocksAtCoord(event->GetCoordinates(), &primary, &secondary, &trim_mode,
|
||||
&transition_start_point);
|
||||
|
||||
if (trim_mode == Timeline::kTrimIn) {
|
||||
std::swap(primary, secondary);
|
||||
}
|
||||
if (trim_mode == Timeline::kTrimIn) {
|
||||
std::swap(primary, secondary);
|
||||
}
|
||||
|
||||
parent()->SetViewTransitionOverlay(primary, secondary);
|
||||
parent()->SetViewTransitionOverlay(primary, secondary);
|
||||
}
|
||||
|
||||
void TransitionTool::MousePress(TimelineViewMouseEvent *event)
|
||||
{
|
||||
ClipBlock *primary, *secondary;
|
||||
Timeline::MovementMode trim_mode;
|
||||
rational transition_start_point;
|
||||
if (!GetBlocksAtCoord(event->GetCoordinates(), &primary, &secondary, &trim_mode, &transition_start_point)) {
|
||||
return;
|
||||
}
|
||||
ClipBlock *primary, *secondary;
|
||||
Timeline::MovementMode trim_mode;
|
||||
rational transition_start_point;
|
||||
if (!GetBlocksAtCoord(event->GetCoordinates(), &primary, &secondary,
|
||||
&trim_mode, &transition_start_point)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create ghost
|
||||
ghost_ = new TimelineViewGhostItem();
|
||||
ghost_->SetTrack(event->GetTrack());
|
||||
ghost_->SetIn(transition_start_point);
|
||||
ghost_->SetOut(transition_start_point);
|
||||
ghost_->SetMode(trim_mode);
|
||||
ghost_->SetData(TimelineViewGhostItem::kAttachedBlock, QtUtils::PtrToValue(primary));
|
||||
// Create ghost
|
||||
ghost_ = new TimelineViewGhostItem();
|
||||
ghost_->SetTrack(event->GetTrack());
|
||||
ghost_->SetIn(transition_start_point);
|
||||
ghost_->SetOut(transition_start_point);
|
||||
ghost_->SetMode(trim_mode);
|
||||
ghost_->SetData(TimelineViewGhostItem::kAttachedBlock,
|
||||
QtUtils::PtrToValue(primary));
|
||||
|
||||
dual_transition_ = (secondary);
|
||||
if (secondary)
|
||||
ghost_->SetData(TimelineViewGhostItem::kReferenceBlock, QtUtils::PtrToValue(secondary));
|
||||
dual_transition_ = (secondary);
|
||||
if (secondary)
|
||||
ghost_->SetData(TimelineViewGhostItem::kReferenceBlock,
|
||||
QtUtils::PtrToValue(secondary));
|
||||
|
||||
parent()->AddGhost(ghost_);
|
||||
parent()->AddGhost(ghost_);
|
||||
|
||||
snap_points_.push_back(transition_start_point);
|
||||
snap_points_.push_back(transition_start_point);
|
||||
|
||||
// Set the drag start point
|
||||
drag_start_point_ = event->GetFrame();
|
||||
// Set the drag start point
|
||||
drag_start_point_ = event->GetFrame();
|
||||
}
|
||||
|
||||
void TransitionTool::MouseMove(TimelineViewMouseEvent *event)
|
||||
{
|
||||
if (!ghost_) {
|
||||
return;
|
||||
}
|
||||
if (!ghost_) {
|
||||
return;
|
||||
}
|
||||
|
||||
MouseMoveInternal(event->GetFrame(), dual_transition_);
|
||||
MouseMoveInternal(event->GetFrame(), dual_transition_);
|
||||
}
|
||||
|
||||
void TransitionTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
{
|
||||
const Track::Reference& track = ghost_->GetTrack();
|
||||
const Track::Reference &track = ghost_->GetTrack();
|
||||
|
||||
if (ghost_) {
|
||||
if (!ghost_->GetAdjustedLength().isNull()) {
|
||||
TransitionBlock* transition;
|
||||
if (ghost_) {
|
||||
if (!ghost_->GetAdjustedLength().isNull()) {
|
||||
TransitionBlock *transition;
|
||||
|
||||
if (Core::instance()->GetSelectedTransition().isEmpty()) {
|
||||
// Fallback if the user hasn't selected one yet
|
||||
transition = new CrossDissolveTransition();
|
||||
} else {
|
||||
transition = static_cast<TransitionBlock*>(NodeFactory::CreateFromID(Core::instance()->GetSelectedTransition()));
|
||||
}
|
||||
if (Core::instance()->GetSelectedTransition().isEmpty()) {
|
||||
// Fallback if the user hasn't selected one yet
|
||||
transition = new CrossDissolveTransition();
|
||||
} else {
|
||||
transition =
|
||||
static_cast<TransitionBlock *>(NodeFactory::CreateFromID(
|
||||
Core::instance()->GetSelectedTransition()));
|
||||
}
|
||||
|
||||
// Set transition length
|
||||
rational len = ghost_->GetAdjustedLength();
|
||||
transition->set_length_and_media_out(len);
|
||||
// Set transition length
|
||||
rational len = ghost_->GetAdjustedLength();
|
||||
transition->set_length_and_media_out(len);
|
||||
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
// Place transition in place
|
||||
command->add_child(new NodeAddCommand(parent()->GetConnectedNode()->parent(),
|
||||
transition));
|
||||
// Place transition in place
|
||||
command->add_child(new NodeAddCommand(
|
||||
parent()->GetConnectedNode()->parent(), transition));
|
||||
|
||||
command->add_child(new NodeSetPositionCommand(transition, transition, QPointF(0, 0)));
|
||||
command->add_child(new NodeSetPositionCommand(
|
||||
transition, transition, QPointF(0, 0)));
|
||||
|
||||
command->add_child(new TrackPlaceBlockCommand(sequence()->track_list(track.type()),
|
||||
track.index(),
|
||||
transition,
|
||||
ghost_->GetAdjustedIn()));
|
||||
command->add_child(new TrackPlaceBlockCommand(
|
||||
sequence()->track_list(track.type()), track.index(), transition,
|
||||
ghost_->GetAdjustedIn()));
|
||||
|
||||
if (dual_transition_) {
|
||||
// Block mouse is hovering over
|
||||
Block* active_block = QtUtils::ValueToPtr<Block>(ghost_->GetData(TimelineViewGhostItem::kAttachedBlock));
|
||||
if (dual_transition_) {
|
||||
// Block mouse is hovering over
|
||||
Block *active_block = QtUtils::ValueToPtr<Block>(
|
||||
ghost_->GetData(TimelineViewGhostItem::kAttachedBlock));
|
||||
|
||||
// Block mouse is next to
|
||||
Block* friend_block = QtUtils::ValueToPtr<Block>(ghost_->GetData(TimelineViewGhostItem::kReferenceBlock));
|
||||
// Block mouse is next to
|
||||
Block *friend_block = QtUtils::ValueToPtr<Block>(
|
||||
ghost_->GetData(TimelineViewGhostItem::kReferenceBlock));
|
||||
|
||||
// Use ghost mode to determine which block is which
|
||||
Block* out_block = (ghost_->GetMode() == Timeline::kTrimIn) ? friend_block : active_block;
|
||||
Block* in_block = (ghost_->GetMode() == Timeline::kTrimIn) ? active_block : friend_block;
|
||||
// Use ghost mode to determine which block is which
|
||||
Block *out_block = (ghost_->GetMode() == Timeline::kTrimIn) ?
|
||||
friend_block :
|
||||
active_block;
|
||||
Block *in_block = (ghost_->GetMode() == Timeline::kTrimIn) ?
|
||||
active_block :
|
||||
friend_block;
|
||||
|
||||
// Connect block to transition
|
||||
command->add_child(new NodeEdgeAddCommand(out_block,
|
||||
NodeInput(transition, TransitionBlock::kOutBlockInput)));
|
||||
// Connect block to transition
|
||||
command->add_child(new NodeEdgeAddCommand(
|
||||
out_block,
|
||||
NodeInput(transition, TransitionBlock::kOutBlockInput)));
|
||||
|
||||
command->add_child(new NodeEdgeAddCommand(in_block,
|
||||
NodeInput(transition, TransitionBlock::kInBlockInput)));
|
||||
command->add_child(new NodeEdgeAddCommand(
|
||||
in_block,
|
||||
NodeInput(transition, TransitionBlock::kInBlockInput)));
|
||||
|
||||
command->add_child(new NodeSetPositionCommand(out_block, transition, QPointF(-1, -0.5)));
|
||||
command->add_child(new NodeSetPositionCommand(in_block, transition, QPointF(-1, 0.5)));
|
||||
} else {
|
||||
Block* block_to_transition = QtUtils::ValueToPtr<Block>(ghost_->GetData(TimelineViewGhostItem::kAttachedBlock));
|
||||
QString transition_input_to_connect;
|
||||
command->add_child(new NodeSetPositionCommand(
|
||||
out_block, transition, QPointF(-1, -0.5)));
|
||||
command->add_child(new NodeSetPositionCommand(
|
||||
in_block, transition, QPointF(-1, 0.5)));
|
||||
} else {
|
||||
Block *block_to_transition = QtUtils::ValueToPtr<Block>(
|
||||
ghost_->GetData(TimelineViewGhostItem::kAttachedBlock));
|
||||
QString transition_input_to_connect;
|
||||
|
||||
if (ghost_->GetMode() == Timeline::kTrimIn) {
|
||||
transition_input_to_connect = TransitionBlock::kInBlockInput;
|
||||
} else {
|
||||
transition_input_to_connect = TransitionBlock::kOutBlockInput;
|
||||
}
|
||||
if (ghost_->GetMode() == Timeline::kTrimIn) {
|
||||
transition_input_to_connect =
|
||||
TransitionBlock::kInBlockInput;
|
||||
} else {
|
||||
transition_input_to_connect =
|
||||
TransitionBlock::kOutBlockInput;
|
||||
}
|
||||
|
||||
// Connect block to transition
|
||||
command->add_child(new NodeEdgeAddCommand(block_to_transition,
|
||||
NodeInput(transition, transition_input_to_connect)));
|
||||
// Connect block to transition
|
||||
command->add_child(new NodeEdgeAddCommand(
|
||||
block_to_transition,
|
||||
NodeInput(transition, transition_input_to_connect)));
|
||||
|
||||
command->add_child(new NodeSetPositionCommand(block_to_transition, transition, QPointF(-1, 0)));
|
||||
}
|
||||
command->add_child(new NodeSetPositionCommand(
|
||||
block_to_transition, transition, QPointF(-1, 0)));
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(command, qApp->translate("TransitionTool", "Created Transition"));
|
||||
Core::instance()->undo_stack()->push(
|
||||
command,
|
||||
qApp->translate("TransitionTool", "Created Transition"));
|
||||
|
||||
parent()->SetViewTransitionOverlay(nullptr, nullptr);
|
||||
}
|
||||
parent()->SetViewTransitionOverlay(nullptr, nullptr);
|
||||
}
|
||||
|
||||
parent()->ClearGhosts();
|
||||
snap_points_.clear();
|
||||
ghost_ = nullptr;
|
||||
}
|
||||
parent()->ClearGhosts();
|
||||
snap_points_.clear();
|
||||
ghost_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool TransitionTool::GetBlocksAtCoord(const TimelineCoordinate &coord, ClipBlock **primary, ClipBlock **secondary, Timeline::MovementMode *ptrim_mode, rational *start_point)
|
||||
bool TransitionTool::GetBlocksAtCoord(const TimelineCoordinate &coord,
|
||||
ClipBlock **primary,
|
||||
ClipBlock **secondary,
|
||||
Timeline::MovementMode *ptrim_mode,
|
||||
rational *start_point)
|
||||
{
|
||||
const Track::Reference& track = coord.GetTrack();
|
||||
Track* t = parent()->GetTrackFromReference(track);
|
||||
rational cursor_frame = coord.GetFrame();
|
||||
const Track::Reference &track = coord.GetTrack();
|
||||
Track *t = parent()->GetTrackFromReference(track);
|
||||
rational cursor_frame = coord.GetFrame();
|
||||
|
||||
if (!t || t->IsLocked()) {
|
||||
return false;
|
||||
}
|
||||
if (!t || t->IsLocked()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Block* block_at_time = t->NearestBlockBeforeOrAt(coord.GetFrame());
|
||||
if (!dynamic_cast<ClipBlock*>(block_at_time)) {
|
||||
return false;
|
||||
}
|
||||
Block *block_at_time = t->NearestBlockBeforeOrAt(coord.GetFrame());
|
||||
if (!dynamic_cast<ClipBlock *>(block_at_time)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Determine which side of the clip the transition belongs to
|
||||
rational transition_start_point;
|
||||
Timeline::MovementMode trim_mode;
|
||||
rational tenth_point = block_at_time->length() / 10;
|
||||
Block* other_block = nullptr;
|
||||
if (cursor_frame < (block_at_time->in() + block_at_time->length() / 2)) {
|
||||
if (static_cast<ClipBlock*>(block_at_time)->in_transition()) {
|
||||
// This clip already has a transition here
|
||||
return false;
|
||||
}
|
||||
// Determine which side of the clip the transition belongs to
|
||||
rational transition_start_point;
|
||||
Timeline::MovementMode trim_mode;
|
||||
rational tenth_point = block_at_time->length() / 10;
|
||||
Block *other_block = nullptr;
|
||||
if (cursor_frame < (block_at_time->in() + block_at_time->length() / 2)) {
|
||||
if (static_cast<ClipBlock *>(block_at_time)->in_transition()) {
|
||||
// This clip already has a transition here
|
||||
return false;
|
||||
}
|
||||
|
||||
ClipBlock *adjacent = dynamic_cast<ClipBlock*>(block_at_time->previous());
|
||||
if (adjacent) {
|
||||
tenth_point = std::min(tenth_point, adjacent->length()/10);
|
||||
}
|
||||
ClipBlock *adjacent =
|
||||
dynamic_cast<ClipBlock *>(block_at_time->previous());
|
||||
if (adjacent) {
|
||||
tenth_point = std::min(tenth_point, adjacent->length() / 10);
|
||||
}
|
||||
|
||||
transition_start_point = block_at_time->in();
|
||||
trim_mode = Timeline::kTrimIn;
|
||||
transition_start_point = block_at_time->in();
|
||||
trim_mode = Timeline::kTrimIn;
|
||||
|
||||
if (cursor_frame < (block_at_time->in() + tenth_point) && adjacent) {
|
||||
other_block = adjacent;
|
||||
}
|
||||
} else {
|
||||
if (static_cast<ClipBlock*>(block_at_time)->out_transition()) {
|
||||
// This clip already has a transition here
|
||||
return false;
|
||||
}
|
||||
if (cursor_frame < (block_at_time->in() + tenth_point) && adjacent) {
|
||||
other_block = adjacent;
|
||||
}
|
||||
} else {
|
||||
if (static_cast<ClipBlock *>(block_at_time)->out_transition()) {
|
||||
// This clip already has a transition here
|
||||
return false;
|
||||
}
|
||||
|
||||
ClipBlock *adjacent = dynamic_cast<ClipBlock*>(block_at_time->next());
|
||||
if (adjacent) {
|
||||
tenth_point = std::min(tenth_point, adjacent->length()/10);
|
||||
}
|
||||
ClipBlock *adjacent = dynamic_cast<ClipBlock *>(block_at_time->next());
|
||||
if (adjacent) {
|
||||
tenth_point = std::min(tenth_point, adjacent->length() / 10);
|
||||
}
|
||||
|
||||
transition_start_point = block_at_time->out();
|
||||
trim_mode = Timeline::kTrimOut;
|
||||
transition_start_point = block_at_time->out();
|
||||
trim_mode = Timeline::kTrimOut;
|
||||
|
||||
if (cursor_frame > block_at_time->out() - tenth_point && adjacent) {
|
||||
other_block = block_at_time->next();
|
||||
}
|
||||
}
|
||||
if (cursor_frame > block_at_time->out() - tenth_point && adjacent) {
|
||||
other_block = block_at_time->next();
|
||||
}
|
||||
}
|
||||
|
||||
*primary = static_cast<ClipBlock*>(block_at_time);
|
||||
*secondary = static_cast<ClipBlock*>(other_block);
|
||||
*ptrim_mode = trim_mode;
|
||||
*start_point = transition_start_point;
|
||||
*primary = static_cast<ClipBlock *>(block_at_time);
|
||||
*secondary = static_cast<ClipBlock *>(other_block);
|
||||
*ptrim_mode = trim_mode;
|
||||
*start_point = transition_start_point;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,24 +23,26 @@
|
||||
|
||||
#include "add.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class TransitionTool : public AddTool
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class TransitionTool : public AddTool {
|
||||
public:
|
||||
TransitionTool(TimelineWidget* parent);
|
||||
TransitionTool(TimelineWidget *parent);
|
||||
|
||||
virtual void HoverMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void HoverMove(TimelineViewMouseEvent *event) override;
|
||||
|
||||
virtual void MousePress(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
|
||||
virtual void MousePress(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
bool GetBlocksAtCoord(const TimelineCoordinate &coord, ClipBlock **primary, ClipBlock **secondary, Timeline::MovementMode *trim_mode, rational *start_point);
|
||||
|
||||
bool dual_transition_;
|
||||
bool GetBlocksAtCoord(const TimelineCoordinate &coord, ClipBlock **primary,
|
||||
ClipBlock **secondary,
|
||||
Timeline::MovementMode *trim_mode,
|
||||
rational *start_point);
|
||||
|
||||
bool dual_transition_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -21,81 +21,91 @@
|
||||
#include "widget/timelinewidget/timelinewidget.h"
|
||||
#include "zoom.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
ZoomTool::ZoomTool(TimelineWidget *parent) :
|
||||
TimelineTool(parent)
|
||||
ZoomTool::ZoomTool(TimelineWidget *parent)
|
||||
: TimelineTool(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void ZoomTool::MousePress(TimelineViewMouseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
Q_UNUSED(event)
|
||||
|
||||
drag_global_start_ = QCursor::pos();
|
||||
drag_global_start_ = QCursor::pos();
|
||||
}
|
||||
|
||||
void ZoomTool::MouseMove(TimelineViewMouseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
Q_UNUSED(event)
|
||||
|
||||
if (!dragging_) {
|
||||
parent()->StartRubberBandSelect(drag_global_start_);
|
||||
if (!dragging_) {
|
||||
parent()->StartRubberBandSelect(drag_global_start_);
|
||||
|
||||
dragging_ = true;
|
||||
}
|
||||
dragging_ = true;
|
||||
}
|
||||
|
||||
parent()->MoveRubberBandSelect(false, false);
|
||||
parent()->MoveRubberBandSelect(false, false);
|
||||
}
|
||||
|
||||
void ZoomTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
{
|
||||
int scroll_value;
|
||||
int scroll_value;
|
||||
|
||||
if (dragging_) {
|
||||
// Zoom into the rubberband selection
|
||||
QRect screen_coords = parent()->GetRubberBandGeometry();
|
||||
if (dragging_) {
|
||||
// Zoom into the rubberband selection
|
||||
QRect screen_coords = parent()->GetRubberBandGeometry();
|
||||
|
||||
parent()->EndRubberBandSelect();
|
||||
parent()->EndRubberBandSelect();
|
||||
|
||||
TimelineView* reference_view = parent()->GetFirstTimelineView();
|
||||
QPointF scene_topleft = reference_view->mapToScene(reference_view->mapFrom(parent(), screen_coords.topLeft()));
|
||||
QPointF scene_bottomright = reference_view->mapToScene(reference_view->mapFrom(parent(), screen_coords.bottomRight()));
|
||||
TimelineView *reference_view = parent()->GetFirstTimelineView();
|
||||
QPointF scene_topleft = reference_view->mapToScene(
|
||||
reference_view->mapFrom(parent(), screen_coords.topLeft()));
|
||||
QPointF scene_bottomright = reference_view->mapToScene(
|
||||
reference_view->mapFrom(parent(), screen_coords.bottomRight()));
|
||||
|
||||
double scene_left = scene_topleft.x();
|
||||
double scene_right = scene_bottomright.x();
|
||||
double scene_left = scene_topleft.x();
|
||||
double scene_right = scene_bottomright.x();
|
||||
|
||||
// Normalize scale to 1.0 scale
|
||||
double scene_width = (scene_right - scene_left) / parent()->GetScale();
|
||||
// Normalize scale to 1.0 scale
|
||||
double scene_width = (scene_right - scene_left) / parent()->GetScale();
|
||||
|
||||
double new_scale = qMin(parent()->GetFirstTimelineView()->GetMaximumScale(), static_cast<double>(reference_view->viewport()->width()) / scene_width);
|
||||
double new_scale =
|
||||
qMin(parent()->GetFirstTimelineView()->GetMaximumScale(),
|
||||
static_cast<double>(reference_view->viewport()->width()) /
|
||||
scene_width);
|
||||
|
||||
parent()->SetScale(new_scale);
|
||||
parent()->SetScale(new_scale);
|
||||
|
||||
scroll_value = qMax(0, qRound(scene_left / parent()->GetScale() * new_scale));
|
||||
scroll_value =
|
||||
qMax(0, qRound(scene_left / parent()->GetScale() * new_scale));
|
||||
|
||||
dragging_ = false;
|
||||
} else {
|
||||
// Simple zoom in/out at the cursor position
|
||||
double scale = parent()->GetScale();
|
||||
dragging_ = false;
|
||||
} else {
|
||||
// Simple zoom in/out at the cursor position
|
||||
double scale = parent()->GetScale();
|
||||
|
||||
if (event->GetModifiers() & Qt::AltModifier) {
|
||||
// Zoom out if the user clicks while holding Alt
|
||||
scale *= 0.5;
|
||||
} else {
|
||||
// Otherwise zoom in
|
||||
scale *= 2.0;
|
||||
}
|
||||
if (event->GetModifiers() & Qt::AltModifier) {
|
||||
// Zoom out if the user clicks while holding Alt
|
||||
scale *= 0.5;
|
||||
} else {
|
||||
// Otherwise zoom in
|
||||
scale *= 2.0;
|
||||
}
|
||||
|
||||
parent()->SetScale(scale);
|
||||
parent()->SetScale(scale);
|
||||
|
||||
// Adjust scroll location for new scale
|
||||
double frame_x = event->GetFrame().toDouble() * scale;
|
||||
// Adjust scroll location for new scale
|
||||
double frame_x = event->GetFrame().toDouble() * scale;
|
||||
|
||||
scroll_value = qMax(0, qRound(frame_x - parent()->GetFirstTimelineView()->viewport()->width()/2));
|
||||
}
|
||||
scroll_value = qMax(
|
||||
0,
|
||||
qRound(frame_x -
|
||||
parent()->GetFirstTimelineView()->viewport()->width() / 2));
|
||||
}
|
||||
|
||||
parent()->QueueScroll(scroll_value);
|
||||
parent()->QueueScroll(scroll_value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,20 +23,19 @@
|
||||
|
||||
#include "tool.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class ZoomTool : public TimelineTool
|
||||
namespace olive
|
||||
{
|
||||
public:
|
||||
ZoomTool(TimelineWidget* parent);
|
||||
|
||||
virtual void MousePress(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
|
||||
class ZoomTool : public TimelineTool {
|
||||
public:
|
||||
ZoomTool(TimelineWidget *parent);
|
||||
|
||||
virtual void MousePress(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseMove(TimelineViewMouseEvent *event) override;
|
||||
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
QPoint drag_global_start_;
|
||||
|
||||
QPoint drag_global_start_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -28,111 +28,115 @@
|
||||
|
||||
#include "trackviewitem.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
TrackView::TrackView(Qt::Alignment vertical_alignment, QWidget *parent) :
|
||||
QScrollArea(parent),
|
||||
list_(nullptr),
|
||||
alignment_(vertical_alignment)
|
||||
namespace olive
|
||||
{
|
||||
setAlignment(Qt::AlignLeft | alignment_);
|
||||
|
||||
QWidget* central = new QWidget();
|
||||
setWidget(central);
|
||||
setWidgetResizable(true);
|
||||
TrackView::TrackView(Qt::Alignment vertical_alignment, QWidget *parent)
|
||||
: QScrollArea(parent)
|
||||
, list_(nullptr)
|
||||
, alignment_(vertical_alignment)
|
||||
{
|
||||
setAlignment(Qt::AlignLeft | alignment_);
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout(central);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(0);
|
||||
QWidget *central = new QWidget();
|
||||
setWidget(central);
|
||||
setWidgetResizable(true);
|
||||
|
||||
if (alignment_ == Qt::AlignBottom) {
|
||||
layout->addStretch();
|
||||
QVBoxLayout *layout = new QVBoxLayout(central);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(0);
|
||||
|
||||
connect(verticalScrollBar(), &QScrollBar::rangeChanged, this, &TrackView::ScrollbarRangeChanged);
|
||||
last_scrollbar_max_ = verticalScrollBar()->maximum();
|
||||
}
|
||||
if (alignment_ == Qt::AlignBottom) {
|
||||
layout->addStretch();
|
||||
|
||||
splitter_ = new TrackViewSplitter(alignment_);
|
||||
splitter_->setChildrenCollapsible(false);
|
||||
layout->addWidget(splitter_);
|
||||
connect(verticalScrollBar(), &QScrollBar::rangeChanged, this,
|
||||
&TrackView::ScrollbarRangeChanged);
|
||||
last_scrollbar_max_ = verticalScrollBar()->maximum();
|
||||
}
|
||||
|
||||
if (alignment_ == Qt::AlignTop) {
|
||||
layout->addStretch();
|
||||
}
|
||||
splitter_ = new TrackViewSplitter(alignment_);
|
||||
splitter_->setChildrenCollapsible(false);
|
||||
layout->addWidget(splitter_);
|
||||
|
||||
connect(splitter_, &TrackViewSplitter::TrackHeightChanged, this, &TrackView::TrackHeightChanged);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
if (alignment_ == Qt::AlignTop) {
|
||||
layout->addStretch();
|
||||
}
|
||||
|
||||
connect(splitter_, &TrackViewSplitter::TrackHeightChanged, this,
|
||||
&TrackView::TrackHeightChanged);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
}
|
||||
|
||||
void TrackView::ConnectTrackList(TrackList *list)
|
||||
{
|
||||
if (list_ != nullptr) {
|
||||
// Remove tracks
|
||||
for (int i=0; i<list_->GetTrackCount(); i++) {
|
||||
splitter_->Remove(0);
|
||||
}
|
||||
if (list_ != nullptr) {
|
||||
// Remove tracks
|
||||
for (int i = 0; i < list_->GetTrackCount(); i++) {
|
||||
splitter_->Remove(0);
|
||||
}
|
||||
|
||||
disconnect(list_, &TrackList::TrackAdded, this, &TrackView::InsertTrack);
|
||||
disconnect(list_, &TrackList::TrackRemoved, this, &TrackView::RemoveTrack);
|
||||
}
|
||||
disconnect(list_, &TrackList::TrackAdded, this,
|
||||
&TrackView::InsertTrack);
|
||||
disconnect(list_, &TrackList::TrackRemoved, this,
|
||||
&TrackView::RemoveTrack);
|
||||
}
|
||||
|
||||
list_ = list;
|
||||
list_ = list;
|
||||
|
||||
if (list_ != nullptr) {
|
||||
foreach (Track* track, list_->GetTracks()) {
|
||||
InsertTrack(track);
|
||||
}
|
||||
if (list_ != nullptr) {
|
||||
foreach (Track *track, list_->GetTracks()) {
|
||||
InsertTrack(track);
|
||||
}
|
||||
|
||||
connect(list_, &TrackList::TrackAdded, this, &TrackView::InsertTrack);
|
||||
connect(list_, &TrackList::TrackRemoved, this, &TrackView::RemoveTrack);
|
||||
}
|
||||
connect(list_, &TrackList::TrackAdded, this, &TrackView::InsertTrack);
|
||||
connect(list_, &TrackList::TrackRemoved, this, &TrackView::RemoveTrack);
|
||||
}
|
||||
}
|
||||
|
||||
void TrackView::DisconnectTrackList()
|
||||
{
|
||||
ConnectTrackList(nullptr);
|
||||
ConnectTrackList(nullptr);
|
||||
}
|
||||
|
||||
void TrackView::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
QScrollArea::resizeEvent(e);
|
||||
QScrollArea::resizeEvent(e);
|
||||
|
||||
splitter_->SetSpacerHeight(height()/2);
|
||||
splitter_->SetSpacerHeight(height() / 2);
|
||||
}
|
||||
|
||||
void TrackView::ScrollbarRangeChanged(int, int max)
|
||||
{
|
||||
if (max != last_scrollbar_max_) {
|
||||
int ba_val = last_scrollbar_max_ - verticalScrollBar()->value();
|
||||
int new_val = max - ba_val;
|
||||
if (max != last_scrollbar_max_) {
|
||||
int ba_val = last_scrollbar_max_ - verticalScrollBar()->value();
|
||||
int new_val = max - ba_val;
|
||||
|
||||
verticalScrollBar()->setValue(new_val);
|
||||
emit verticalScrollBar()->valueChanged(new_val);
|
||||
verticalScrollBar()->setValue(new_val);
|
||||
emit verticalScrollBar() -> valueChanged(new_val);
|
||||
|
||||
last_scrollbar_max_ = max;
|
||||
}
|
||||
last_scrollbar_max_ = max;
|
||||
}
|
||||
}
|
||||
|
||||
void TrackView::TrackHeightChanged(int index, int height)
|
||||
{
|
||||
list_->GetTrackAt(index)->SetTrackHeightInPixels(height);
|
||||
list_->GetTrackAt(index)->SetTrackHeightInPixels(height);
|
||||
}
|
||||
|
||||
void TrackView::InsertTrack(Track *track)
|
||||
{
|
||||
TrackViewItem *tvi = new TrackViewItem(track);
|
||||
TrackViewItem *tvi = new TrackViewItem(track);
|
||||
|
||||
connect(tvi, &TrackViewItem::AboutToDeleteTrack, this, &TrackView::AboutToDeleteTrack);
|
||||
connect(tvi, &TrackViewItem::AboutToDeleteTrack, this,
|
||||
&TrackView::AboutToDeleteTrack);
|
||||
|
||||
splitter_->Insert(track->Index(),
|
||||
track->GetTrackHeightInPixels(),
|
||||
tvi);
|
||||
splitter_->Insert(track->Index(), track->GetTrackHeightInPixels(), tvi);
|
||||
}
|
||||
|
||||
void TrackView::RemoveTrack(Track *track)
|
||||
{
|
||||
splitter_->Remove(track->Index());
|
||||
splitter_->Remove(track->Index());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,42 +28,41 @@
|
||||
#include "trackviewitem.h"
|
||||
#include "trackviewsplitter.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class TrackView : public QScrollArea
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TrackView(Qt::Alignment vertical_alignment = Qt::AlignTop,
|
||||
QWidget* parent = nullptr);
|
||||
|
||||
void ConnectTrackList(TrackList* list);
|
||||
void DisconnectTrackList();
|
||||
class TrackView : public QScrollArea {
|
||||
Q_OBJECT
|
||||
public:
|
||||
TrackView(Qt::Alignment vertical_alignment = Qt::AlignTop,
|
||||
QWidget *parent = nullptr);
|
||||
|
||||
void ConnectTrackList(TrackList *list);
|
||||
void DisconnectTrackList();
|
||||
|
||||
signals:
|
||||
void AboutToDeleteTrack(Track *track);
|
||||
void AboutToDeleteTrack(Track *track);
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent *e) override;
|
||||
virtual void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
private:
|
||||
TrackList* list_;
|
||||
TrackList *list_;
|
||||
|
||||
TrackViewSplitter* splitter_;
|
||||
TrackViewSplitter *splitter_;
|
||||
|
||||
Qt::Alignment alignment_;
|
||||
Qt::Alignment alignment_;
|
||||
|
||||
int last_scrollbar_max_;
|
||||
int last_scrollbar_max_;
|
||||
|
||||
private slots:
|
||||
void ScrollbarRangeChanged(int min, int max);
|
||||
void ScrollbarRangeChanged(int min, int max);
|
||||
|
||||
void TrackHeightChanged(int index, int height);
|
||||
void TrackHeightChanged(int index, int height);
|
||||
|
||||
void InsertTrack(Track* track);
|
||||
|
||||
void RemoveTrack(Track* track);
|
||||
void InsertTrack(Track *track);
|
||||
|
||||
void RemoveTrack(Track *track);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -32,159 +32,177 @@
|
||||
#include "ui/icons/icons.h"
|
||||
#include "widget/menu/menu.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
TrackViewItem::TrackViewItem(Track* track, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
track_(track)
|
||||
namespace olive
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
layout->setSpacing(0);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
stack_ = new QStackedWidget();
|
||||
layout->addWidget(stack_);
|
||||
TrackViewItem::TrackViewItem(Track *track, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, track_(track)
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->setSpacing(0);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
label_ = new ClickableLabel();
|
||||
connect(label_, &ClickableLabel::MouseDoubleClicked, this, &TrackViewItem::LabelClicked);
|
||||
connect(track_, &Track::LabelChanged, this, &TrackViewItem::UpdateLabel);
|
||||
connect(track_, &Track::IndexChanged, this, &TrackViewItem::UpdateLabel);
|
||||
UpdateLabel();
|
||||
stack_->addWidget(label_);
|
||||
stack_ = new QStackedWidget();
|
||||
layout->addWidget(stack_);
|
||||
|
||||
line_edit_ = new FocusableLineEdit();
|
||||
connect(line_edit_, &FocusableLineEdit::Confirmed, this, &TrackViewItem::LineEditConfirmed);
|
||||
connect(line_edit_, &FocusableLineEdit::Cancelled, this, &TrackViewItem::LineEditCancelled);
|
||||
stack_->addWidget(line_edit_);
|
||||
label_ = new ClickableLabel();
|
||||
connect(label_, &ClickableLabel::MouseDoubleClicked, this,
|
||||
&TrackViewItem::LabelClicked);
|
||||
connect(track_, &Track::LabelChanged, this, &TrackViewItem::UpdateLabel);
|
||||
connect(track_, &Track::IndexChanged, this, &TrackViewItem::UpdateLabel);
|
||||
UpdateLabel();
|
||||
stack_->addWidget(label_);
|
||||
|
||||
mute_button_ = CreateMSLButton(Qt::red);
|
||||
mute_button_->setChecked(track->IsMuted());
|
||||
UpdateMuteButton(track->IsMuted());
|
||||
connect(mute_button_, &QPushButton::toggled, track_, &Track::SetMuted);
|
||||
connect(mute_button_, &QPushButton::toggled, this, &TrackViewItem::UpdateMuteButton);
|
||||
layout->addWidget(mute_button_);
|
||||
line_edit_ = new FocusableLineEdit();
|
||||
connect(line_edit_, &FocusableLineEdit::Confirmed, this,
|
||||
&TrackViewItem::LineEditConfirmed);
|
||||
connect(line_edit_, &FocusableLineEdit::Cancelled, this,
|
||||
&TrackViewItem::LineEditCancelled);
|
||||
stack_->addWidget(line_edit_);
|
||||
|
||||
/*solo_button_ = CreateMSLButton(tr("S"), Qt::yellow);
|
||||
mute_button_ = CreateMSLButton(Qt::red);
|
||||
mute_button_->setChecked(track->IsMuted());
|
||||
UpdateMuteButton(track->IsMuted());
|
||||
connect(mute_button_, &QPushButton::toggled, track_, &Track::SetMuted);
|
||||
connect(mute_button_, &QPushButton::toggled, this,
|
||||
&TrackViewItem::UpdateMuteButton);
|
||||
layout->addWidget(mute_button_);
|
||||
|
||||
/*solo_button_ = CreateMSLButton(tr("S"), Qt::yellow);
|
||||
layout->addWidget(solo_button_);*/
|
||||
|
||||
lock_button_ = CreateMSLButton(Qt::gray);
|
||||
lock_button_->setChecked(track->IsLocked());
|
||||
UpdateLockButton(track->IsLocked());
|
||||
connect(lock_button_, &QPushButton::toggled, track_, &Track::SetLocked);
|
||||
connect(lock_button_, &QPushButton::toggled, this, &TrackViewItem::UpdateLockButton);
|
||||
layout->addWidget(lock_button_);
|
||||
lock_button_ = CreateMSLButton(Qt::gray);
|
||||
lock_button_->setChecked(track->IsLocked());
|
||||
UpdateLockButton(track->IsLocked());
|
||||
connect(lock_button_, &QPushButton::toggled, track_, &Track::SetLocked);
|
||||
connect(lock_button_, &QPushButton::toggled, this,
|
||||
&TrackViewItem::UpdateLockButton);
|
||||
layout->addWidget(lock_button_);
|
||||
|
||||
setMinimumHeight(mute_button_->height());
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
setMinimumHeight(mute_button_->height());
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
connect(track, &Track::MutedChanged, mute_button_, &QPushButton::setChecked);
|
||||
connect(this, &QWidget::customContextMenuRequested, this, &TrackViewItem::ShowContextMenu);
|
||||
connect(track, &Track::MutedChanged, mute_button_,
|
||||
&QPushButton::setChecked);
|
||||
connect(this, &QWidget::customContextMenuRequested, this,
|
||||
&TrackViewItem::ShowContextMenu);
|
||||
}
|
||||
|
||||
QPushButton *TrackViewItem::CreateMSLButton(const QColor& checked_color) const
|
||||
QPushButton *TrackViewItem::CreateMSLButton(const QColor &checked_color) const
|
||||
{
|
||||
QPushButton* button = new QPushButton();
|
||||
button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
||||
button->setCheckable(true);
|
||||
button->setStyleSheet(QStringLiteral("QPushButton::checked { background: %1; }").arg(checked_color.name()));
|
||||
QPushButton *button = new QPushButton();
|
||||
button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
||||
button->setCheckable(true);
|
||||
button->setStyleSheet(
|
||||
QStringLiteral("QPushButton::checked { background: %1; }")
|
||||
.arg(checked_color.name()));
|
||||
|
||||
int size = button->sizeHint().height();
|
||||
size = qRound(size * 0.75);
|
||||
button->setFixedSize(size, size);
|
||||
int size = button->sizeHint().height();
|
||||
size = qRound(size * 0.75);
|
||||
button->setFixedSize(size, size);
|
||||
|
||||
return button;
|
||||
return button;
|
||||
}
|
||||
|
||||
void TrackViewItem::LabelClicked()
|
||||
{
|
||||
stack_->setCurrentWidget(line_edit_);
|
||||
line_edit_->setFocus();
|
||||
line_edit_->selectAll();
|
||||
stack_->setCurrentWidget(line_edit_);
|
||||
line_edit_->setFocus();
|
||||
line_edit_->selectAll();
|
||||
}
|
||||
|
||||
void TrackViewItem::LineEditConfirmed()
|
||||
{
|
||||
line_edit_->blockSignals(true);
|
||||
line_edit_->blockSignals(true);
|
||||
|
||||
track_->SetLabel(line_edit_->text());
|
||||
UpdateLabel();
|
||||
track_->SetLabel(line_edit_->text());
|
||||
UpdateLabel();
|
||||
|
||||
stack_->setCurrentWidget(label_);
|
||||
stack_->setCurrentWidget(label_);
|
||||
|
||||
line_edit_->blockSignals(false);
|
||||
line_edit_->blockSignals(false);
|
||||
}
|
||||
|
||||
void TrackViewItem::LineEditCancelled()
|
||||
{
|
||||
line_edit_->blockSignals(true);
|
||||
line_edit_->blockSignals(true);
|
||||
|
||||
stack_->setCurrentWidget(label_);
|
||||
stack_->setCurrentWidget(label_);
|
||||
|
||||
line_edit_->blockSignals(false);
|
||||
line_edit_->blockSignals(false);
|
||||
}
|
||||
|
||||
void TrackViewItem::UpdateLabel()
|
||||
{
|
||||
label_->setText(track_->GetLabelOrName());
|
||||
label_->setText(track_->GetLabelOrName());
|
||||
}
|
||||
|
||||
void TrackViewItem::ShowContextMenu(const QPoint &p)
|
||||
{
|
||||
Menu m(this);
|
||||
Menu m(this);
|
||||
|
||||
QAction *delete_action = m.addAction(tr("&Delete"));
|
||||
connect(delete_action, &QAction::triggered, this, &TrackViewItem::DeleteTrack, Qt::QueuedConnection);
|
||||
QAction *delete_action = m.addAction(tr("&Delete"));
|
||||
connect(delete_action, &QAction::triggered, this,
|
||||
&TrackViewItem::DeleteTrack, Qt::QueuedConnection);
|
||||
|
||||
m.addSeparator();
|
||||
m.addSeparator();
|
||||
|
||||
QAction *delete_unused_action = m.addAction(tr("Delete All &Empty"));
|
||||
connect(delete_unused_action, &QAction::triggered, this, &TrackViewItem::DeleteAllEmptyTracks, Qt::QueuedConnection);
|
||||
QAction *delete_unused_action = m.addAction(tr("Delete All &Empty"));
|
||||
connect(delete_unused_action, &QAction::triggered, this,
|
||||
&TrackViewItem::DeleteAllEmptyTracks, Qt::QueuedConnection);
|
||||
|
||||
m.exec(mapToGlobal(p));
|
||||
m.exec(mapToGlobal(p));
|
||||
}
|
||||
|
||||
void TrackViewItem::DeleteTrack()
|
||||
{
|
||||
emit AboutToDeleteTrack(track_);
|
||||
Core::instance()->undo_stack()->push(new TimelineRemoveTrackCommand(track_), tr("Deleted Track \"%1\"").arg(track_->GetLabelOrName()));
|
||||
emit AboutToDeleteTrack(track_);
|
||||
Core::instance()->undo_stack()->push(
|
||||
new TimelineRemoveTrackCommand(track_),
|
||||
tr("Deleted Track \"%1\"").arg(track_->GetLabelOrName()));
|
||||
}
|
||||
|
||||
void TrackViewItem::DeleteAllEmptyTracks()
|
||||
{
|
||||
Sequence *sequence = track_->sequence();
|
||||
QVector<Track*> tracks_to_remove;
|
||||
QStringList track_names_to_remove;
|
||||
Sequence *sequence = track_->sequence();
|
||||
QVector<Track *> tracks_to_remove;
|
||||
QStringList track_names_to_remove;
|
||||
|
||||
foreach (Track *t, sequence->GetTracks()) {
|
||||
if (t->Blocks().isEmpty()) {
|
||||
tracks_to_remove.append(t);
|
||||
track_names_to_remove.append(t->GetLabelOrName());
|
||||
}
|
||||
}
|
||||
foreach (Track *t, sequence->GetTracks()) {
|
||||
if (t->Blocks().isEmpty()) {
|
||||
tracks_to_remove.append(t);
|
||||
track_names_to_remove.append(t->GetLabelOrName());
|
||||
}
|
||||
}
|
||||
|
||||
if (tracks_to_remove.isEmpty()) {
|
||||
QMessageBox::information(this, tr("Delete All Empty"), tr("No tracks are currently empty"));
|
||||
} else {
|
||||
if (QMessageBox::question(this, tr("Delete All Empty"),
|
||||
tr("This will delete the following tracks:\n\n%1\n\nDo you wish to continue?").arg(track_names_to_remove.join('\n')),
|
||||
QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
foreach (Track *track, tracks_to_remove) {
|
||||
command->add_child(new TimelineRemoveTrackCommand(track));
|
||||
}
|
||||
Core::instance()->undo_stack()->push(command, tr("Deleted All Empty Tracks"));
|
||||
}
|
||||
}
|
||||
if (tracks_to_remove.isEmpty()) {
|
||||
QMessageBox::information(this, tr("Delete All Empty"),
|
||||
tr("No tracks are currently empty"));
|
||||
} else {
|
||||
if (QMessageBox::question(
|
||||
this, tr("Delete All Empty"),
|
||||
tr("This will delete the following tracks:\n\n%1\n\nDo you wish to continue?")
|
||||
.arg(track_names_to_remove.join('\n')),
|
||||
QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
foreach (Track *track, tracks_to_remove) {
|
||||
command->add_child(new TimelineRemoveTrackCommand(track));
|
||||
}
|
||||
Core::instance()->undo_stack()->push(
|
||||
command, tr("Deleted All Empty Tracks"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TrackViewItem::UpdateMuteButton(bool e)
|
||||
{
|
||||
mute_button_->setIcon(e ? icon::EyeClosed : icon::EyeOpened);
|
||||
mute_button_->setIcon(e ? icon::EyeClosed : icon::EyeOpened);
|
||||
}
|
||||
|
||||
void TrackViewItem::UpdateLockButton(bool e)
|
||||
{
|
||||
lock_button_->setIcon(e ? icon::LockClosed : icon::LockOpened);
|
||||
lock_button_->setIcon(e ? icon::LockClosed : icon::LockOpened);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,51 +30,49 @@
|
||||
#include "widget/focusablelineedit/focusablelineedit.h"
|
||||
#include "widget/timelinewidget/view/timelineviewmouseevent.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class TrackViewItem : public QWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class TrackViewItem : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
TrackViewItem(Track* track,
|
||||
QWidget* parent = nullptr);
|
||||
TrackViewItem(Track *track, QWidget *parent = nullptr);
|
||||
|
||||
signals:
|
||||
void AboutToDeleteTrack(Track *track);
|
||||
void AboutToDeleteTrack(Track *track);
|
||||
|
||||
private:
|
||||
QPushButton* CreateMSLButton(const QColor &checked_color) const;
|
||||
QPushButton *CreateMSLButton(const QColor &checked_color) const;
|
||||
|
||||
QStackedWidget* stack_;
|
||||
QStackedWidget *stack_;
|
||||
|
||||
ClickableLabel* label_;
|
||||
FocusableLineEdit* line_edit_;
|
||||
ClickableLabel *label_;
|
||||
FocusableLineEdit *line_edit_;
|
||||
|
||||
QPushButton* mute_button_;
|
||||
QPushButton* solo_button_;
|
||||
QPushButton* lock_button_;
|
||||
QPushButton *mute_button_;
|
||||
QPushButton *solo_button_;
|
||||
QPushButton *lock_button_;
|
||||
|
||||
Track* track_;
|
||||
Track *track_;
|
||||
|
||||
private slots:
|
||||
void LabelClicked();
|
||||
void LabelClicked();
|
||||
|
||||
void LineEditConfirmed();
|
||||
void LineEditConfirmed();
|
||||
|
||||
void LineEditCancelled();
|
||||
void LineEditCancelled();
|
||||
|
||||
void UpdateLabel();
|
||||
void UpdateLabel();
|
||||
|
||||
void ShowContextMenu(const QPoint &p);
|
||||
void ShowContextMenu(const QPoint &p);
|
||||
|
||||
void DeleteTrack();
|
||||
void DeleteTrack();
|
||||
|
||||
void DeleteAllEmptyTracks();
|
||||
void DeleteAllEmptyTracks();
|
||||
|
||||
void UpdateMuteButton(bool e);
|
||||
|
||||
void UpdateLockButton(bool e);
|
||||
void UpdateMuteButton(bool e);
|
||||
|
||||
void UpdateLockButton(bool e);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -25,145 +25,148 @@
|
||||
|
||||
#include "node/output/track/track.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
TrackViewSplitter::TrackViewSplitter(Qt::Alignment vertical_alignment, QWidget* parent) :
|
||||
QSplitter(Qt::Vertical, parent),
|
||||
alignment_(vertical_alignment),
|
||||
spacer_height_(0)
|
||||
namespace olive
|
||||
{
|
||||
setHandleWidth(1);
|
||||
|
||||
int initial_height = 0;
|
||||
TrackViewSplitter::TrackViewSplitter(Qt::Alignment vertical_alignment,
|
||||
QWidget *parent)
|
||||
: QSplitter(Qt::Vertical, parent)
|
||||
, alignment_(vertical_alignment)
|
||||
, spacer_height_(0)
|
||||
{
|
||||
setHandleWidth(1);
|
||||
|
||||
// Add empty spacer so we get a splitter handle after the last element
|
||||
QWidget* spacer = new QWidget();
|
||||
addWidget(spacer);
|
||||
int initial_height = 0;
|
||||
|
||||
setFixedHeight(initial_height);
|
||||
// Add empty spacer so we get a splitter handle after the last element
|
||||
QWidget *spacer = new QWidget();
|
||||
addWidget(spacer);
|
||||
|
||||
setFixedHeight(initial_height);
|
||||
}
|
||||
|
||||
void TrackViewSplitter::HandleReceiver(TrackViewSplitterHandle *h, int diff)
|
||||
{
|
||||
int ele_id = -1;
|
||||
int ele_id = -1;
|
||||
|
||||
for (int i=0;i<count();i++) {
|
||||
if (handle(i) == h) {
|
||||
ele_id = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < count(); i++) {
|
||||
if (handle(i) == h) {
|
||||
ele_id = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// The handle index is actually always one above the element index
|
||||
if (alignment_ == Qt::AlignTop) {
|
||||
ele_id--;
|
||||
} else if (alignment_ == Qt::AlignBottom) {
|
||||
diff = -diff;
|
||||
}
|
||||
// The handle index is actually always one above the element index
|
||||
if (alignment_ == Qt::AlignTop) {
|
||||
ele_id--;
|
||||
} else if (alignment_ == Qt::AlignBottom) {
|
||||
diff = -diff;
|
||||
}
|
||||
|
||||
QList<int> element_sizes = sizes();
|
||||
QList<int> element_sizes = sizes();
|
||||
|
||||
int old_ele_sz = element_sizes.at(ele_id);
|
||||
int old_ele_sz = element_sizes.at(ele_id);
|
||||
|
||||
// Transform element size by diff
|
||||
int new_ele_sz = old_ele_sz + diff;
|
||||
// Transform element size by diff
|
||||
int new_ele_sz = old_ele_sz + diff;
|
||||
|
||||
// Limit by track minimum height
|
||||
new_ele_sz = qMax(new_ele_sz, Track::GetMinimumTrackHeightInPixels());
|
||||
// Limit by track minimum height
|
||||
new_ele_sz = qMax(new_ele_sz, Track::GetMinimumTrackHeightInPixels());
|
||||
|
||||
if (alignment_ == Qt::AlignBottom) {
|
||||
ele_id = count() - ele_id - 1;
|
||||
}
|
||||
if (alignment_ == Qt::AlignBottom) {
|
||||
ele_id = count() - ele_id - 1;
|
||||
}
|
||||
|
||||
SetTrackHeight(ele_id, new_ele_sz);
|
||||
SetTrackHeight(ele_id, new_ele_sz);
|
||||
|
||||
emit TrackHeightChanged(ele_id, new_ele_sz);
|
||||
emit TrackHeightChanged(ele_id, new_ele_sz);
|
||||
}
|
||||
|
||||
void TrackViewSplitter::SetTrackHeight(int index, int h)
|
||||
{
|
||||
QList<int> element_sizes = sizes();
|
||||
QList<int> element_sizes = sizes();
|
||||
|
||||
if (alignment_ == Qt::AlignBottom) {
|
||||
index = count() - index - 1;
|
||||
}
|
||||
if (alignment_ == Qt::AlignBottom) {
|
||||
index = count() - index - 1;
|
||||
}
|
||||
|
||||
int old_ele_sz = element_sizes.at(index);
|
||||
int old_ele_sz = element_sizes.at(index);
|
||||
|
||||
int diff = h - old_ele_sz;
|
||||
int diff = h - old_ele_sz;
|
||||
|
||||
// Set new size on element
|
||||
element_sizes.replace(index, h);
|
||||
setSizes(element_sizes);
|
||||
// Set new size on element
|
||||
element_sizes.replace(index, h);
|
||||
setSizes(element_sizes);
|
||||
|
||||
// Increase height by the difference
|
||||
setFixedHeight(height() + diff);
|
||||
// Increase height by the difference
|
||||
setFixedHeight(height() + diff);
|
||||
}
|
||||
|
||||
void TrackViewSplitter::SetHeightWithSizes(QList<int> sizes)
|
||||
{
|
||||
int start_height = 0;
|
||||
int start_height = 0;
|
||||
|
||||
// Add spacer height too
|
||||
if (alignment_ == Qt::AlignBottom) {
|
||||
sizes.replace(0, spacer_height_);
|
||||
} else {
|
||||
sizes.replace(sizes.size() - 1, spacer_height_);
|
||||
}
|
||||
// Add spacer height too
|
||||
if (alignment_ == Qt::AlignBottom) {
|
||||
sizes.replace(0, spacer_height_);
|
||||
} else {
|
||||
sizes.replace(sizes.size() - 1, spacer_height_);
|
||||
}
|
||||
|
||||
foreach (int s, sizes) {
|
||||
start_height += s + handleWidth();
|
||||
}
|
||||
foreach (int s, sizes) {
|
||||
start_height += s + handleWidth();
|
||||
}
|
||||
|
||||
// The spacer doesn't need a handle width
|
||||
start_height -= handleWidth();
|
||||
// The spacer doesn't need a handle width
|
||||
start_height -= handleWidth();
|
||||
|
||||
setFixedHeight(start_height);
|
||||
setSizes(sizes);
|
||||
setFixedHeight(start_height);
|
||||
setSizes(sizes);
|
||||
}
|
||||
|
||||
void TrackViewSplitter::Insert(int index, int height, QWidget *item)
|
||||
{
|
||||
QList<int> sz = sizes();
|
||||
QList<int> sz = sizes();
|
||||
|
||||
if (alignment_ == Qt::AlignBottom) {
|
||||
index = count() - index;
|
||||
}
|
||||
if (alignment_ == Qt::AlignBottom) {
|
||||
index = count() - index;
|
||||
}
|
||||
|
||||
sz.insert(index, height);
|
||||
insertWidget(index, item);
|
||||
sz.insert(index, height);
|
||||
insertWidget(index, item);
|
||||
|
||||
SetHeightWithSizes(sz);
|
||||
SetHeightWithSizes(sz);
|
||||
}
|
||||
|
||||
void TrackViewSplitter::Remove(int index)
|
||||
{
|
||||
QList<int> sz = sizes();
|
||||
QList<int> sz = sizes();
|
||||
|
||||
if (alignment_ == Qt::AlignBottom) {
|
||||
index = count() - 1 - index;
|
||||
}
|
||||
if (alignment_ == Qt::AlignBottom) {
|
||||
index = count() - 1 - index;
|
||||
}
|
||||
|
||||
sz.removeAt(index);
|
||||
delete widget(index);
|
||||
sz.removeAt(index);
|
||||
delete widget(index);
|
||||
|
||||
SetHeightWithSizes(sz);
|
||||
SetHeightWithSizes(sz);
|
||||
}
|
||||
|
||||
void TrackViewSplitter::SetSpacerHeight(int height)
|
||||
{
|
||||
spacer_height_ = height;
|
||||
SetHeightWithSizes(sizes());
|
||||
spacer_height_ = height;
|
||||
SetHeightWithSizes(sizes());
|
||||
}
|
||||
|
||||
QSplitterHandle *TrackViewSplitter::createHandle()
|
||||
{
|
||||
return new TrackViewSplitterHandle(orientation(), this);
|
||||
return new TrackViewSplitterHandle(orientation(), this);
|
||||
}
|
||||
|
||||
TrackViewSplitterHandle::TrackViewSplitterHandle(Qt::Orientation orientation, QSplitter *parent) :
|
||||
QSplitterHandle(orientation, parent),
|
||||
dragging_(false)
|
||||
TrackViewSplitterHandle::TrackViewSplitterHandle(Qt::Orientation orientation,
|
||||
QSplitter *parent)
|
||||
: QSplitterHandle(orientation, parent)
|
||||
, dragging_(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -173,23 +176,24 @@ void TrackViewSplitterHandle::mousePressEvent(QMouseEvent *)
|
||||
|
||||
void TrackViewSplitterHandle::mouseMoveEvent(QMouseEvent *)
|
||||
{
|
||||
if (dragging_) {
|
||||
static_cast<TrackViewSplitter*>(parent())->HandleReceiver(this, QCursor::pos().y() - drag_y_);
|
||||
}
|
||||
if (dragging_) {
|
||||
static_cast<TrackViewSplitter *>(parent())->HandleReceiver(
|
||||
this, QCursor::pos().y() - drag_y_);
|
||||
}
|
||||
|
||||
drag_y_ = QCursor::pos().y();
|
||||
dragging_ = true;
|
||||
drag_y_ = QCursor::pos().y();
|
||||
dragging_ = true;
|
||||
}
|
||||
|
||||
void TrackViewSplitterHandle::mouseReleaseEvent(QMouseEvent *)
|
||||
{
|
||||
dragging_ = false;
|
||||
dragging_ = false;
|
||||
}
|
||||
|
||||
void TrackViewSplitterHandle::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter p(this);
|
||||
p.fillRect(rect(), palette().base());
|
||||
QPainter p(this);
|
||||
p.fillRect(rect(), palette().base());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,56 +25,55 @@
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class TrackViewSplitterHandle : public QSplitterHandle
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class TrackViewSplitterHandle : public QSplitterHandle {
|
||||
Q_OBJECT
|
||||
public:
|
||||
TrackViewSplitterHandle(Qt::Orientation orientation, QSplitter *parent);
|
||||
TrackViewSplitterHandle(Qt::Orientation orientation, QSplitter *parent);
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent *e) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *e) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
virtual void mousePressEvent(QMouseEvent *e) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *e) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
|
||||
virtual void paintEvent(QPaintEvent *e) override;
|
||||
virtual void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
int drag_y_;
|
||||
int drag_y_;
|
||||
|
||||
bool dragging_;
|
||||
bool dragging_;
|
||||
};
|
||||
|
||||
class TrackViewSplitter : public QSplitter
|
||||
{
|
||||
Q_OBJECT
|
||||
class TrackViewSplitter : public QSplitter {
|
||||
Q_OBJECT
|
||||
public:
|
||||
TrackViewSplitter(Qt::Alignment vertical_alignment, QWidget* parent = nullptr);
|
||||
TrackViewSplitter(Qt::Alignment vertical_alignment,
|
||||
QWidget *parent = nullptr);
|
||||
|
||||
void HandleReceiver(TrackViewSplitterHandle* h, int diff);
|
||||
void HandleReceiver(TrackViewSplitterHandle *h, int diff);
|
||||
|
||||
void SetHeightWithSizes(QList<int> sizes);
|
||||
void SetHeightWithSizes(QList<int> sizes);
|
||||
|
||||
void Insert(int index, int height, QWidget* item);
|
||||
void Remove(int index);
|
||||
void Insert(int index, int height, QWidget *item);
|
||||
void Remove(int index);
|
||||
|
||||
void SetSpacerHeight(int height);
|
||||
void SetSpacerHeight(int height);
|
||||
|
||||
public slots:
|
||||
void SetTrackHeight(int index, int h);
|
||||
void SetTrackHeight(int index, int h);
|
||||
|
||||
signals:
|
||||
void TrackHeightChanged(int index, int height);
|
||||
void TrackHeightChanged(int index, int height);
|
||||
|
||||
protected:
|
||||
virtual QSplitterHandle *createHandle() override;
|
||||
virtual QSplitterHandle *createHandle() override;
|
||||
|
||||
private:
|
||||
Qt::Alignment alignment_;
|
||||
|
||||
int spacer_height_;
|
||||
Qt::Alignment alignment_;
|
||||
|
||||
int spacer_height_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -32,129 +32,136 @@
|
||||
#include "timelineviewghostitem.h"
|
||||
#include "widget/timebased/timebasedview.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A widget for viewing and interacting Sequences
|
||||
*
|
||||
* This widget primarily exposes users to viewing and modifying Block nodes, usually through a TimelineOutput node.
|
||||
*/
|
||||
class TimelineView : public TimeBasedView
|
||||
{
|
||||
Q_OBJECT
|
||||
class TimelineView : public TimeBasedView {
|
||||
Q_OBJECT
|
||||
public:
|
||||
TimelineView(Qt::Alignment vertical_alignment = Qt::AlignTop,
|
||||
QWidget* parent = nullptr);
|
||||
TimelineView(Qt::Alignment vertical_alignment = Qt::AlignTop,
|
||||
QWidget *parent = nullptr);
|
||||
|
||||
int GetTrackY(int track_index) const;
|
||||
int GetTrackHeight(int track_index) const;
|
||||
int GetTrackY(int track_index) const;
|
||||
int GetTrackHeight(int track_index) const;
|
||||
|
||||
QPoint GetScrollCoordinates() const;
|
||||
void SetScrollCoordinates(const QPoint& pt);
|
||||
QPoint GetScrollCoordinates() const;
|
||||
void SetScrollCoordinates(const QPoint &pt);
|
||||
|
||||
void ConnectTrackList(TrackList* list);
|
||||
void ConnectTrackList(TrackList *list);
|
||||
|
||||
void SetBeamCursor(const TimelineCoordinate& coord);
|
||||
void SetTransitionOverlay(ClipBlock *out, ClipBlock *in);
|
||||
void EnableRecordingOverlay(const TimelineCoordinate &coord);
|
||||
void DisableRecordingOverlay();
|
||||
void SetBeamCursor(const TimelineCoordinate &coord);
|
||||
void SetTransitionOverlay(ClipBlock *out, ClipBlock *in);
|
||||
void EnableRecordingOverlay(const TimelineCoordinate &coord);
|
||||
void DisableRecordingOverlay();
|
||||
|
||||
void SetSelectionList(QHash<Track::Reference, TimeRangeList>* s)
|
||||
{
|
||||
selections_ = s;
|
||||
}
|
||||
void SetSelectionList(QHash<Track::Reference, TimeRangeList> *s)
|
||||
{
|
||||
selections_ = s;
|
||||
}
|
||||
|
||||
void SetGhostList(QVector<TimelineViewGhostItem*>* ghosts)
|
||||
{
|
||||
ghosts_ = ghosts;
|
||||
}
|
||||
void SetGhostList(QVector<TimelineViewGhostItem *> *ghosts)
|
||||
{
|
||||
ghosts_ = ghosts;
|
||||
}
|
||||
|
||||
int SceneToTrack(double y);
|
||||
int SceneToTrack(double y);
|
||||
|
||||
Block* GetItemAtScenePos(const rational& time, int track_index) const;
|
||||
Block *GetItemAtScenePos(const rational &time, int track_index) const;
|
||||
|
||||
QVector<Block*> GetItemsAtSceneRect(const QRectF &rect) const;
|
||||
QVector<Block *> GetItemsAtSceneRect(const QRectF &rect) const;
|
||||
|
||||
signals:
|
||||
void MousePressed(TimelineViewMouseEvent* event);
|
||||
void MouseMoved(TimelineViewMouseEvent* event);
|
||||
void MouseReleased(TimelineViewMouseEvent* event);
|
||||
void MouseDoubleClicked(TimelineViewMouseEvent* event);
|
||||
void MousePressed(TimelineViewMouseEvent *event);
|
||||
void MouseMoved(TimelineViewMouseEvent *event);
|
||||
void MouseReleased(TimelineViewMouseEvent *event);
|
||||
void MouseDoubleClicked(TimelineViewMouseEvent *event);
|
||||
|
||||
void DragEntered(TimelineViewMouseEvent* event);
|
||||
void DragMoved(TimelineViewMouseEvent* event);
|
||||
void DragLeft(QDragLeaveEvent* event);
|
||||
void DragDropped(TimelineViewMouseEvent* event);
|
||||
void DragEntered(TimelineViewMouseEvent *event);
|
||||
void DragMoved(TimelineViewMouseEvent *event);
|
||||
void DragLeft(QDragLeaveEvent *event);
|
||||
void DragDropped(TimelineViewMouseEvent *event);
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
|
||||
virtual void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
virtual void dragMoveEvent(QDragMoveEvent *event) override;
|
||||
virtual void dragLeaveEvent(QDragLeaveEvent *event) override;
|
||||
virtual void dropEvent(QDropEvent *event) override;
|
||||
virtual void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
virtual void dragMoveEvent(QDragMoveEvent *event) override;
|
||||
virtual void dragLeaveEvent(QDragLeaveEvent *event) override;
|
||||
virtual void dropEvent(QDropEvent *event) override;
|
||||
|
||||
virtual void drawBackground(QPainter *painter, const QRectF &rect) override;
|
||||
virtual void drawForeground(QPainter *painter, const QRectF &rect) override;
|
||||
virtual void drawBackground(QPainter *painter, const QRectF &rect) override;
|
||||
virtual void drawForeground(QPainter *painter, const QRectF &rect) override;
|
||||
|
||||
virtual void ToolChangedEvent(Tool::Item tool) override;
|
||||
virtual void ToolChangedEvent(Tool::Item tool) override;
|
||||
|
||||
virtual void SceneRectUpdateEvent(QRectF& rect) override;
|
||||
virtual void SceneRectUpdateEvent(QRectF &rect) override;
|
||||
|
||||
private:
|
||||
Track::Type ConnectedTrackType();
|
||||
Track::Type ConnectedTrackType();
|
||||
|
||||
TimelineCoordinate ScreenToCoordinate(const QPoint& pt);
|
||||
TimelineCoordinate SceneToCoordinate(const QPointF& pt);
|
||||
TimelineCoordinate ScreenToCoordinate(const QPoint &pt);
|
||||
TimelineCoordinate SceneToCoordinate(const QPointF &pt);
|
||||
|
||||
TimelineViewMouseEvent CreateMouseEvent(QMouseEvent* event);
|
||||
TimelineViewMouseEvent CreateMouseEvent(const QPoint &pos, Qt::MouseButton button, Qt::KeyboardModifiers modifiers);
|
||||
TimelineViewMouseEvent CreateMouseEvent(QMouseEvent *event);
|
||||
TimelineViewMouseEvent CreateMouseEvent(const QPoint &pos,
|
||||
Qt::MouseButton button,
|
||||
Qt::KeyboardModifiers modifiers);
|
||||
|
||||
void DrawBlocks(QPainter* painter, bool foreground);
|
||||
void DrawBlocks(QPainter *painter, bool foreground);
|
||||
|
||||
void DrawBlock(QPainter *painter, bool foreground, Block *block, qreal top, qreal height, const rational &in, const rational &out, const rational &media_in);
|
||||
void DrawBlock(QPainter *painter, bool foreground, Block *block, qreal top, qreal height)
|
||||
{
|
||||
ClipBlock *cb = dynamic_cast<ClipBlock*>(block);
|
||||
return DrawBlock(painter, foreground, block, top, height, block->in(), block->out(), cb ? cb->media_in() : 0);
|
||||
}
|
||||
void DrawBlock(QPainter *painter, bool foreground, Block *block, qreal top,
|
||||
qreal height, const rational &in, const rational &out,
|
||||
const rational &media_in);
|
||||
void DrawBlock(QPainter *painter, bool foreground, Block *block, qreal top,
|
||||
qreal height)
|
||||
{
|
||||
ClipBlock *cb = dynamic_cast<ClipBlock *>(block);
|
||||
return DrawBlock(painter, foreground, block, top, height, block->in(),
|
||||
block->out(), cb ? cb->media_in() : 0);
|
||||
}
|
||||
|
||||
void DrawZebraStripes(QPainter *painter, const QRectF &r);
|
||||
void DrawZebraStripes(QPainter *painter, const QRectF &r);
|
||||
|
||||
int GetHeightOfAllTracks() const;
|
||||
int GetHeightOfAllTracks() const;
|
||||
|
||||
void UpdatePlayheadRect();
|
||||
void UpdatePlayheadRect();
|
||||
|
||||
qreal GetTimelineLeftBound() const;
|
||||
qreal GetTimelineLeftBound() const;
|
||||
|
||||
qreal GetTimelineRightBound() const;
|
||||
qreal GetTimelineRightBound() const;
|
||||
|
||||
void DrawThumbnail(QPainter *painter, const FrameHashCache *thumbs, const rational &time, int x, const QRect &preview_rect, QRect *thumb_rect) const;
|
||||
void DrawThumbnail(QPainter *painter, const FrameHashCache *thumbs,
|
||||
const rational &time, int x, const QRect &preview_rect,
|
||||
QRect *thumb_rect) const;
|
||||
|
||||
QHash<Track::Reference, TimeRangeList>* selections_;
|
||||
QHash<Track::Reference, TimeRangeList> *selections_;
|
||||
|
||||
QVector<TimelineViewGhostItem*>* ghosts_;
|
||||
QVector<TimelineViewGhostItem *> *ghosts_;
|
||||
|
||||
bool show_beam_cursor_;
|
||||
bool show_beam_cursor_;
|
||||
|
||||
TimelineCoordinate cursor_coord_;
|
||||
TimelineCoordinate cursor_coord_;
|
||||
|
||||
TrackList* connected_track_list_;
|
||||
TrackList *connected_track_list_;
|
||||
|
||||
ClipBlock *transition_overlay_out_;
|
||||
ClipBlock *transition_overlay_in_;
|
||||
ClipBlock *transition_overlay_out_;
|
||||
ClipBlock *transition_overlay_in_;
|
||||
|
||||
QMap<TimelineMarker*, QRectF> clip_marker_rects_;
|
||||
QMap<TimelineMarker *, QRectF> clip_marker_rects_;
|
||||
|
||||
bool recording_overlay_;
|
||||
TimelineCoordinate recording_coord_;
|
||||
bool recording_overlay_;
|
||||
TimelineCoordinate recording_coord_;
|
||||
|
||||
private slots:
|
||||
void TrackListChanged();
|
||||
|
||||
void TrackListChanged();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -29,244 +29,240 @@
|
||||
#include "node/project/footage/footage.h"
|
||||
#include "timeline/timelinecommon.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
/**
|
||||
* @brief A graphical representation of changes the user is making before they apply it
|
||||
*/
|
||||
class TimelineViewGhostItem
|
||||
{
|
||||
class TimelineViewGhostItem {
|
||||
public:
|
||||
enum DataType {
|
||||
kAttachedBlock,
|
||||
kReferenceBlock,
|
||||
kAttachedFootage,
|
||||
kGhostIsSliding,
|
||||
kTrimIsARollEdit,
|
||||
kTrimShouldBeIgnored
|
||||
};
|
||||
enum DataType {
|
||||
kAttachedBlock,
|
||||
kReferenceBlock,
|
||||
kAttachedFootage,
|
||||
kGhostIsSliding,
|
||||
kTrimIsARollEdit,
|
||||
kTrimShouldBeIgnored
|
||||
};
|
||||
|
||||
struct AttachedFootage {
|
||||
ViewerOutput* footage;
|
||||
QString output;
|
||||
};
|
||||
struct AttachedFootage {
|
||||
ViewerOutput *footage;
|
||||
QString output;
|
||||
};
|
||||
|
||||
TimelineViewGhostItem() :
|
||||
track_adj_(0),
|
||||
mode_(Timeline::kNone),
|
||||
can_have_zero_length_(true),
|
||||
can_move_tracks_(true),
|
||||
invisible_(false)
|
||||
{
|
||||
}
|
||||
TimelineViewGhostItem()
|
||||
: track_adj_(0)
|
||||
, mode_(Timeline::kNone)
|
||||
, can_have_zero_length_(true)
|
||||
, can_move_tracks_(true)
|
||||
, invisible_(false)
|
||||
{
|
||||
}
|
||||
|
||||
static TimelineViewGhostItem* FromBlock(Block *block)
|
||||
{
|
||||
TimelineViewGhostItem* ghost = new TimelineViewGhostItem();
|
||||
static TimelineViewGhostItem *FromBlock(Block *block)
|
||||
{
|
||||
TimelineViewGhostItem *ghost = new TimelineViewGhostItem();
|
||||
|
||||
ghost->SetIn(block->in());
|
||||
ghost->SetOut(block->out());
|
||||
if (dynamic_cast<ClipBlock*>(block)) {
|
||||
ghost->SetMediaIn(static_cast<ClipBlock*>(block)->media_in());
|
||||
}
|
||||
ghost->SetTrack(block->track()->ToReference());
|
||||
ghost->SetData(kAttachedBlock, QtUtils::PtrToValue(block));
|
||||
ghost->SetIn(block->in());
|
||||
ghost->SetOut(block->out());
|
||||
if (dynamic_cast<ClipBlock *>(block)) {
|
||||
ghost->SetMediaIn(static_cast<ClipBlock *>(block)->media_in());
|
||||
}
|
||||
ghost->SetTrack(block->track()->ToReference());
|
||||
ghost->SetData(kAttachedBlock, QtUtils::PtrToValue(block));
|
||||
|
||||
if (dynamic_cast<ClipBlock*>(block)) {
|
||||
ghost->can_have_zero_length_ = false;
|
||||
} else if (dynamic_cast<TransitionBlock*>(block)) {
|
||||
ghost->can_have_zero_length_ = false;
|
||||
}
|
||||
if (dynamic_cast<ClipBlock *>(block)) {
|
||||
ghost->can_have_zero_length_ = false;
|
||||
} else if (dynamic_cast<TransitionBlock *>(block)) {
|
||||
ghost->can_have_zero_length_ = false;
|
||||
}
|
||||
|
||||
return ghost;
|
||||
}
|
||||
return ghost;
|
||||
}
|
||||
|
||||
bool CanHaveZeroLength() const
|
||||
{
|
||||
return can_have_zero_length_;
|
||||
}
|
||||
bool CanHaveZeroLength() const
|
||||
{
|
||||
return can_have_zero_length_;
|
||||
}
|
||||
|
||||
bool GetCanMoveTracks() const
|
||||
{
|
||||
return can_move_tracks_;
|
||||
}
|
||||
bool GetCanMoveTracks() const
|
||||
{
|
||||
return can_move_tracks_;
|
||||
}
|
||||
|
||||
void SetCanMoveTracks(bool e)
|
||||
{
|
||||
can_move_tracks_ = e;
|
||||
}
|
||||
void SetCanMoveTracks(bool e)
|
||||
{
|
||||
can_move_tracks_ = e;
|
||||
}
|
||||
|
||||
const rational& GetIn() const
|
||||
{
|
||||
return in_;
|
||||
}
|
||||
const rational &GetIn() const
|
||||
{
|
||||
return in_;
|
||||
}
|
||||
|
||||
const rational& GetOut() const
|
||||
{
|
||||
return out_;
|
||||
}
|
||||
const rational &GetOut() const
|
||||
{
|
||||
return out_;
|
||||
}
|
||||
|
||||
const rational& GetMediaIn() const
|
||||
{
|
||||
return media_in_;
|
||||
}
|
||||
const rational &GetMediaIn() const
|
||||
{
|
||||
return media_in_;
|
||||
}
|
||||
|
||||
rational GetLength() const
|
||||
{
|
||||
return out_ - in_;
|
||||
}
|
||||
rational GetLength() const
|
||||
{
|
||||
return out_ - in_;
|
||||
}
|
||||
|
||||
rational GetAdjustedLength() const
|
||||
{
|
||||
return GetAdjustedOut() - GetAdjustedIn();
|
||||
}
|
||||
rational GetAdjustedLength() const
|
||||
{
|
||||
return GetAdjustedOut() - GetAdjustedIn();
|
||||
}
|
||||
|
||||
void SetIn(const rational& in)
|
||||
{
|
||||
in_ = in;
|
||||
}
|
||||
void SetIn(const rational &in)
|
||||
{
|
||||
in_ = in;
|
||||
}
|
||||
|
||||
void SetOut(const rational& out)
|
||||
{
|
||||
out_ = out;
|
||||
}
|
||||
void SetOut(const rational &out)
|
||||
{
|
||||
out_ = out;
|
||||
}
|
||||
|
||||
void SetMediaIn(const rational& media_in)
|
||||
{
|
||||
media_in_ = media_in;
|
||||
}
|
||||
void SetMediaIn(const rational &media_in)
|
||||
{
|
||||
media_in_ = media_in;
|
||||
}
|
||||
|
||||
void SetInAdjustment(const rational& in_adj)
|
||||
{
|
||||
in_adj_ = in_adj;
|
||||
}
|
||||
void SetInAdjustment(const rational &in_adj)
|
||||
{
|
||||
in_adj_ = in_adj;
|
||||
}
|
||||
|
||||
void SetOutAdjustment(const rational& out_adj)
|
||||
{
|
||||
out_adj_ = out_adj;
|
||||
}
|
||||
void SetOutAdjustment(const rational &out_adj)
|
||||
{
|
||||
out_adj_ = out_adj;
|
||||
}
|
||||
|
||||
void SetTrackAdjustment(const int& track_adj)
|
||||
{
|
||||
track_adj_ = track_adj;
|
||||
}
|
||||
void SetTrackAdjustment(const int &track_adj)
|
||||
{
|
||||
track_adj_ = track_adj;
|
||||
}
|
||||
|
||||
void SetMediaInAdjustment(const rational& media_in_adj)
|
||||
{
|
||||
media_in_adj_ = media_in_adj;
|
||||
}
|
||||
void SetMediaInAdjustment(const rational &media_in_adj)
|
||||
{
|
||||
media_in_adj_ = media_in_adj;
|
||||
}
|
||||
|
||||
const rational& GetInAdjustment() const
|
||||
{
|
||||
return in_adj_;
|
||||
}
|
||||
const rational &GetInAdjustment() const
|
||||
{
|
||||
return in_adj_;
|
||||
}
|
||||
|
||||
const rational& GetOutAdjustment() const
|
||||
{
|
||||
return out_adj_;
|
||||
}
|
||||
const rational &GetOutAdjustment() const
|
||||
{
|
||||
return out_adj_;
|
||||
}
|
||||
|
||||
const rational& GetMediaInAdjustment() const
|
||||
{
|
||||
return media_in_adj_;
|
||||
}
|
||||
const rational &GetMediaInAdjustment() const
|
||||
{
|
||||
return media_in_adj_;
|
||||
}
|
||||
|
||||
const int& GetTrackAdjustment() const
|
||||
{
|
||||
return track_adj_;
|
||||
}
|
||||
const int &GetTrackAdjustment() const
|
||||
{
|
||||
return track_adj_;
|
||||
}
|
||||
|
||||
rational GetAdjustedIn() const
|
||||
{
|
||||
return in_ + in_adj_;
|
||||
}
|
||||
rational GetAdjustedIn() const
|
||||
{
|
||||
return in_ + in_adj_;
|
||||
}
|
||||
|
||||
rational GetAdjustedOut() const
|
||||
{
|
||||
return out_ + out_adj_;
|
||||
}
|
||||
rational GetAdjustedOut() const
|
||||
{
|
||||
return out_ + out_adj_;
|
||||
}
|
||||
|
||||
rational GetAdjustedMediaIn() const
|
||||
{
|
||||
return media_in_ + media_in_adj_;
|
||||
}
|
||||
rational GetAdjustedMediaIn() const
|
||||
{
|
||||
return media_in_ + media_in_adj_;
|
||||
}
|
||||
|
||||
Track::Reference GetAdjustedTrack() const
|
||||
{
|
||||
return Track::Reference(track_.type(), track_.index() + track_adj_);
|
||||
}
|
||||
Track::Reference GetAdjustedTrack() const
|
||||
{
|
||||
return Track::Reference(track_.type(), track_.index() + track_adj_);
|
||||
}
|
||||
|
||||
const Timeline::MovementMode& GetMode() const
|
||||
{
|
||||
return mode_;
|
||||
}
|
||||
const Timeline::MovementMode &GetMode() const
|
||||
{
|
||||
return mode_;
|
||||
}
|
||||
|
||||
void SetMode(const Timeline::MovementMode& mode)
|
||||
{
|
||||
mode_ = mode;
|
||||
}
|
||||
void SetMode(const Timeline::MovementMode &mode)
|
||||
{
|
||||
mode_ = mode;
|
||||
}
|
||||
|
||||
bool HasBeenAdjusted() const
|
||||
{
|
||||
return GetInAdjustment() != 0
|
||||
|| GetOutAdjustment() != 0
|
||||
|| GetMediaInAdjustment() != 0
|
||||
|| GetTrackAdjustment() != 0;
|
||||
}
|
||||
bool HasBeenAdjusted() const
|
||||
{
|
||||
return GetInAdjustment() != 0 || GetOutAdjustment() != 0 ||
|
||||
GetMediaInAdjustment() != 0 || GetTrackAdjustment() != 0;
|
||||
}
|
||||
|
||||
QVariant GetData(int key) const
|
||||
{
|
||||
return data_.value(key);
|
||||
}
|
||||
QVariant GetData(int key) const
|
||||
{
|
||||
return data_.value(key);
|
||||
}
|
||||
|
||||
void SetData(int key, const QVariant& value)
|
||||
{
|
||||
data_.insert(key, value);
|
||||
}
|
||||
void SetData(int key, const QVariant &value)
|
||||
{
|
||||
data_.insert(key, value);
|
||||
}
|
||||
|
||||
const Track::Reference& GetTrack() const
|
||||
{
|
||||
return track_;
|
||||
}
|
||||
const Track::Reference &GetTrack() const
|
||||
{
|
||||
return track_;
|
||||
}
|
||||
|
||||
void SetTrack(const Track::Reference& track)
|
||||
{
|
||||
track_ = track;
|
||||
}
|
||||
void SetTrack(const Track::Reference &track)
|
||||
{
|
||||
track_ = track;
|
||||
}
|
||||
|
||||
bool IsInvisible() const
|
||||
{
|
||||
return invisible_;
|
||||
}
|
||||
bool IsInvisible() const
|
||||
{
|
||||
return invisible_;
|
||||
}
|
||||
|
||||
void SetInvisible(bool e)
|
||||
{
|
||||
invisible_ = e;
|
||||
}
|
||||
void SetInvisible(bool e)
|
||||
{
|
||||
invisible_ = e;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
rational in_;
|
||||
rational out_;
|
||||
rational media_in_;
|
||||
rational in_;
|
||||
rational out_;
|
||||
rational media_in_;
|
||||
|
||||
rational in_adj_;
|
||||
rational out_adj_;
|
||||
rational media_in_adj_;
|
||||
rational in_adj_;
|
||||
rational out_adj_;
|
||||
rational media_in_adj_;
|
||||
|
||||
int track_adj_;
|
||||
int track_adj_;
|
||||
|
||||
Timeline::MovementMode mode_;
|
||||
Timeline::MovementMode mode_;
|
||||
|
||||
bool can_have_zero_length_;
|
||||
bool can_move_tracks_;
|
||||
bool can_have_zero_length_;
|
||||
bool can_move_tracks_;
|
||||
|
||||
Track::Reference track_;
|
||||
Track::Reference track_;
|
||||
|
||||
QHash<int, QVariant> data_;
|
||||
|
||||
bool invisible_;
|
||||
QHash<int, QVariant> data_;
|
||||
|
||||
bool invisible_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -29,42 +29,40 @@
|
||||
#include "timeline/timelinecoordinate.h"
|
||||
#include "widget/timebased/timescaledobject.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class TimelineViewMouseEvent
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class TimelineViewMouseEvent {
|
||||
public:
|
||||
TimelineViewMouseEvent(const QPointF& scene_pos,
|
||||
const QPoint &screen_pos,
|
||||
const double& scale_x,
|
||||
const rational& timebase,
|
||||
const Track::Reference &track,
|
||||
const Qt::MouseButton &button,
|
||||
const Qt::KeyboardModifiers& modifiers = Qt::NoModifier) :
|
||||
scene_pos_(scene_pos),
|
||||
screen_pos_(screen_pos),
|
||||
scale_x_(scale_x),
|
||||
timebase_(timebase),
|
||||
track_(track),
|
||||
button_(button),
|
||||
modifiers_(modifiers),
|
||||
source_event_(nullptr),
|
||||
mime_data_(nullptr),
|
||||
bypass_import_buffer_(false)
|
||||
{
|
||||
}
|
||||
TimelineViewMouseEvent(
|
||||
const QPointF &scene_pos, const QPoint &screen_pos,
|
||||
const double &scale_x, const rational &timebase,
|
||||
const Track::Reference &track, const Qt::MouseButton &button,
|
||||
const Qt::KeyboardModifiers &modifiers = Qt::NoModifier)
|
||||
: scene_pos_(scene_pos)
|
||||
, screen_pos_(screen_pos)
|
||||
, scale_x_(scale_x)
|
||||
, timebase_(timebase)
|
||||
, track_(track)
|
||||
, button_(button)
|
||||
, modifiers_(modifiers)
|
||||
, source_event_(nullptr)
|
||||
, mime_data_(nullptr)
|
||||
, bypass_import_buffer_(false)
|
||||
{
|
||||
}
|
||||
|
||||
TimelineCoordinate GetCoordinates(bool round_time = false) const
|
||||
{
|
||||
return TimelineCoordinate(GetFrame(round_time), track_);
|
||||
}
|
||||
TimelineCoordinate GetCoordinates(bool round_time = false) const
|
||||
{
|
||||
return TimelineCoordinate(GetFrame(round_time), track_);
|
||||
}
|
||||
|
||||
const Qt::KeyboardModifiers& GetModifiers() const
|
||||
{
|
||||
return modifiers_;
|
||||
}
|
||||
const Qt::KeyboardModifiers &GetModifiers() const
|
||||
{
|
||||
return modifiers_;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Gets the time at this cursor point
|
||||
*
|
||||
* @param round
|
||||
@@ -73,77 +71,89 @@ public:
|
||||
* always to the left of the cursor. The former behavior is better for clicking between frames (e.g. razor tool) and
|
||||
* the latter is better for clicking directly on frames (e.g. pointer tool).
|
||||
*/
|
||||
rational GetFrame(bool round = false) const
|
||||
{
|
||||
return TimeScaledObject::SceneToTime(GetSceneX(), scale_x_, timebase_, round);
|
||||
}
|
||||
rational GetFrame(bool round = false) const
|
||||
{
|
||||
return TimeScaledObject::SceneToTime(GetSceneX(), scale_x_, timebase_,
|
||||
round);
|
||||
}
|
||||
|
||||
const Track::Reference& GetTrack() const
|
||||
{
|
||||
return track_;
|
||||
}
|
||||
const Track::Reference &GetTrack() const
|
||||
{
|
||||
return track_;
|
||||
}
|
||||
|
||||
const QMimeData *GetMimeData()
|
||||
{
|
||||
return mime_data_;
|
||||
}
|
||||
const QMimeData *GetMimeData()
|
||||
{
|
||||
return mime_data_;
|
||||
}
|
||||
|
||||
void SetMimeData(const QMimeData *data)
|
||||
{
|
||||
mime_data_ = data;
|
||||
}
|
||||
void SetMimeData(const QMimeData *data)
|
||||
{
|
||||
mime_data_ = data;
|
||||
}
|
||||
|
||||
void SetEvent(QEvent* event)
|
||||
{
|
||||
source_event_ = event;
|
||||
}
|
||||
void SetEvent(QEvent *event)
|
||||
{
|
||||
source_event_ = event;
|
||||
}
|
||||
|
||||
qreal GetSceneX() const
|
||||
{
|
||||
return scene_pos_.x();
|
||||
}
|
||||
qreal GetSceneX() const
|
||||
{
|
||||
return scene_pos_.x();
|
||||
}
|
||||
|
||||
const QPointF &GetScenePos() const { return scene_pos_; }
|
||||
const QPoint &GetScreenPos() const { return screen_pos_; }
|
||||
const QPointF &GetScenePos() const
|
||||
{
|
||||
return scene_pos_;
|
||||
}
|
||||
const QPoint &GetScreenPos() const
|
||||
{
|
||||
return screen_pos_;
|
||||
}
|
||||
|
||||
const Qt::MouseButton& GetButton() const
|
||||
{
|
||||
return button_;
|
||||
}
|
||||
const Qt::MouseButton &GetButton() const
|
||||
{
|
||||
return button_;
|
||||
}
|
||||
|
||||
void accept()
|
||||
{
|
||||
if (source_event_ != nullptr)
|
||||
source_event_->accept();
|
||||
}
|
||||
void accept()
|
||||
{
|
||||
if (source_event_ != nullptr)
|
||||
source_event_->accept();
|
||||
}
|
||||
|
||||
void ignore()
|
||||
{
|
||||
if (source_event_ != nullptr)
|
||||
source_event_->ignore();
|
||||
}
|
||||
void ignore()
|
||||
{
|
||||
if (source_event_ != nullptr)
|
||||
source_event_->ignore();
|
||||
}
|
||||
|
||||
bool GetBypassImportBuffer() const { return bypass_import_buffer_; }
|
||||
void SetBypassImportBuffer(bool e) { bypass_import_buffer_ = e; }
|
||||
bool GetBypassImportBuffer() const
|
||||
{
|
||||
return bypass_import_buffer_;
|
||||
}
|
||||
void SetBypassImportBuffer(bool e)
|
||||
{
|
||||
bypass_import_buffer_ = e;
|
||||
}
|
||||
|
||||
private:
|
||||
QPointF scene_pos_;
|
||||
QPoint screen_pos_;
|
||||
double scale_x_;
|
||||
rational timebase_;
|
||||
QPointF scene_pos_;
|
||||
QPoint screen_pos_;
|
||||
double scale_x_;
|
||||
rational timebase_;
|
||||
|
||||
Track::Reference track_;
|
||||
Track::Reference track_;
|
||||
|
||||
Qt::MouseButton button_;
|
||||
Qt::MouseButton button_;
|
||||
|
||||
Qt::KeyboardModifiers modifiers_;
|
||||
Qt::KeyboardModifiers modifiers_;
|
||||
|
||||
QEvent* source_event_;
|
||||
QEvent *source_event_;
|
||||
|
||||
const QMimeData* mime_data_;
|
||||
|
||||
bool bypass_import_buffer_;
|
||||
const QMimeData *mime_data_;
|
||||
|
||||
bool bypass_import_buffer_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user