work towards shifting functions from timelineview to timelinewidget

This commit is contained in:
itsmattkc
2019-10-11 16:57:12 +11:00
parent 79d1f99fa8
commit e9f5d0d248
34 changed files with 895 additions and 704 deletions
+1
View File
@@ -31,6 +31,7 @@ add_subdirectory(panel)
add_subdirectory(project)
add_subdirectory(render)
add_subdirectory(task)
add_subdirectory(timeline)
add_subdirectory(tool)
add_subdirectory(ui)
add_subdirectory(undo)
+1
View File
@@ -20,5 +20,6 @@ set(OLIVE_SOURCES
node/output/timeline/timeline.cpp
node/output/timeline/tracklist.h
node/output/timeline/tracklist.cpp
node/output/timeline/tracktypes.h
PARENT_SCOPE
)
+10 -4
View File
@@ -37,12 +37,14 @@ TimelineOutput::TimelineOutput()
NodeInput* track_input = new NodeInput(QString("track_in_%1").arg(i));
track_input->add_data_input(NodeParam::kTrack);
AddParameter(track_input);
track_inputs_[i] = track_input;
track_inputs_.replace(i, track_input);
TrackList* list = new TrackList(this, static_cast<TrackType>(i), track_input);
track_lists_[i] = list;
track_lists_.replace(i, list);
connect(list, SIGNAL(TrackListChanged()), this, SLOT(UpdateTrackCache()));
connect(list, SIGNAL(LengthChanged(const rational &)), this, SLOT(UpdateLength(const rational &)));
connect(list, SIGNAL(BlockAdded(Block*, int)), this, SLOT(TrackListAddedBlock(Block*, int)));
connect(list, SIGNAL(BlockRemoved(Block*)), this, SIGNAL(BlockRemoved(Block*)));
}
length_output_ = new NodeOutput("length_out");
@@ -107,8 +109,6 @@ void TimelineOutput::UpdateTrackCache()
void TimelineOutput::UpdateLength(const rational &length)
{
qDebug() << "Updating length! Received value:" << length;
// If this length is equal, no-op
if (length == length_) {
return;
@@ -150,3 +150,9 @@ TrackList *TimelineOutput::track_list(TrackType type)
{
return track_lists_.at(type);
}
void TimelineOutput::TrackListAddedBlock(Block *block, int index)
{
TrackType type = static_cast<TrackList*>(sender())->TrackType();
emit BlockAdded(block, TrackReference(type, index));
}
+7
View File
@@ -24,6 +24,7 @@
#include "common/timelinecommon.h"
#include "node/block/block.h"
#include "node/output/track/track.h"
#include "timeline/trackreference.h"
#include "tracklist.h"
#include "tracktypes.h"
@@ -56,6 +57,10 @@ public:
signals:
void LengthChanged(const rational& length);
void BlockAdded(Block* block, TrackReference track);
void BlockRemoved(Block* block);
protected:
virtual QVariant Value(NodeOutput* output, const rational& time) override;
@@ -75,6 +80,8 @@ private slots:
void UpdateLength(const rational &length);
void TrackListAddedBlock(Block* block, int index);
};
#endif // TIMELINEOUTPUT_H
+24
View File
@@ -0,0 +1,24 @@
# Olive - Non-Linear Video Editor
# Copyright (C) 2019 Olive Team
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
set(OLIVE_SOURCES
${OLIVE_SOURCES}
timeline/timelinecoordinate.h
timeline/timelinecoordinate.cpp
timeline/trackreference.h
timeline/trackreference.cpp
PARENT_SCOPE
)
@@ -21,22 +21,28 @@
#include "timelinecoordinate.h"
TimelineCoordinate::TimelineCoordinate() :
track_(0)
track_(kTrackTypeNone, 0)
{
}
TimelineCoordinate::TimelineCoordinate(const rational &frame, const int &track) :
TimelineCoordinate::TimelineCoordinate(const rational &frame, const TrackReference &track) :
frame_(frame),
track_(track)
{
}
TimelineCoordinate::TimelineCoordinate(const rational &frame, const TrackType &track_type, const int &track_index) :
frame_(frame),
track_(track_type, track_index)
{
}
const rational &TimelineCoordinate::GetFrame() const
{
return frame_;
}
const int &TimelineCoordinate::GetTrack() const
const TrackReference &TimelineCoordinate::GetTrack() const
{
return track_;
}
@@ -46,7 +52,7 @@ void TimelineCoordinate::SetFrame(const rational &frame)
frame_ = frame;
}
void TimelineCoordinate::SetTrack(const int &track)
void TimelineCoordinate::SetTrack(const TrackReference &track)
{
track_ = track;
}
@@ -22,23 +22,25 @@
#define TIMELINECOORDINATE_H
#include "common/rational.h"
#include "trackreference.h"
class TimelineCoordinate
{
public:
TimelineCoordinate();
TimelineCoordinate(const rational& frame, const int& track);
TimelineCoordinate(const rational& frame, const TrackReference& track);
TimelineCoordinate(const rational& frame, const TrackType& track_type, const int& track_index);
const rational& GetFrame() const;
const int& GetTrack() const;
const TrackReference& GetTrack() const;
void SetFrame(const rational& frame);
void SetTrack(const int& track);
void SetTrack(const TrackReference& track);
private:
rational frame_;
int track_;
TrackReference track_;
};
+48
View File
@@ -0,0 +1,48 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include "trackreference.h"
TrackReference::TrackReference() :
type_(kTrackTypeNone),
index_(0)
{
}
TrackReference::TrackReference(const TrackType &type, const int &index) :
type_(type),
index_(index)
{
}
const TrackType &TrackReference::type() const
{
return type_;
}
const int &TrackReference::index() const
{
return index_;
}
bool TrackReference::operator==(const TrackReference &ref) const
{
return type_ == ref.type_ && index_ == ref.index_;
}
+45
View File
@@ -0,0 +1,45 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef TRACKREFERENCE_H
#define TRACKREFERENCE_H
#include "node/output/timeline/tracktypes.h"
class TrackReference
{
public:
TrackReference();
TrackReference(const TrackType& type, const int& index);
const TrackType& type() const;
const int& index() const;
bool operator==(const TrackReference& ref) const;
private:
TrackType type_;
int index_;
};
#endif // TRACKREFERENCE_H
-2
View File
@@ -19,8 +19,6 @@ add_subdirectory(undo)
set(OLIVE_SOURCES
${OLIVE_SOURCES}
widget/timelineview/timelinecoordinate.h
widget/timelineview/timelinecoordinate.cpp
widget/timelineview/timelineplayhead.h
widget/timelineview/timelineplayhead.cpp
widget/timelineview/timelinescaledobject.h
@@ -6,7 +6,32 @@ TimelineScaledObject::TimelineScaledObject() :
}
double TimelineScaledObject::TimeToScreenCoord(const rational &time)
const rational &TimelineScaledObject::timebase()
{
return timebase_;
}
const double &TimelineScaledObject::timebase_dbl()
{
return timebase_dbl_;
}
double TimelineScaledObject::TimeToScene(const rational &time)
{
return time.toDouble() * scale_;
}
rational TimelineScaledObject::SceneToTime(const double &x)
{
// Adjust screen point by scale and timebase
qint64 scaled_x_mvmt = qRound64(x / scale_ / timebase_dbl_);
// Return a time in the timebase
return rational(scaled_x_mvmt * timebase_.numerator(), timebase_.denominator());
}
void TimelineScaledObject::SetTimebaseInternal(const rational &timebase)
{
timebase_ = timebase;
timebase_dbl_ = timebase_.toDouble();
}
+10 -1
View File
@@ -8,13 +8,22 @@ class TimelineScaledObject
public:
TimelineScaledObject();
const rational& timebase();
const double& timebase_dbl();
protected:
double TimeToScreenCoord(const rational& time);
double TimeToScene(const rational& time);
rational SceneToTime(const double &x);
void SetTimebaseInternal(const rational& timebase);
double scale_;
private:
rational timebase_;
double timebase_dbl_;
};
#endif // TIMELINESCALEDOBJECT_H
+34 -236
View File
@@ -32,7 +32,6 @@
#include "core.h"
#include "node/input/media/media.h"
#include "project/item/footage/footage.h"
#include "tool/tool.h"
TimelineView::TimelineView(Qt::Alignment vertical_alignment, QWidget *parent) :
QGraphicsView(parent),
@@ -48,25 +47,6 @@ TimelineView::TimelineView(Qt::Alignment vertical_alignment, QWidget *parent) :
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
setBackgroundRole(QPalette::Window);
// Create tools
tools_.resize(olive::tool::kCount);
tools_.fill(nullptr);
tools_.replace(olive::tool::kPointer, std::make_shared<PointerTool>(this));
// tools_.replace(olive::tool::kEdit, new PointerTool(this)); FIXME: Implement
tools_.replace(olive::tool::kRipple, std::make_shared<RippleTool>(this));
tools_.replace(olive::tool::kRolling, std::make_shared<RollingTool>(this));
tools_.replace(olive::tool::kRazor, std::make_shared<RazorTool>(this));
tools_.replace(olive::tool::kSlip, std::make_shared<SlipTool>(this));
tools_.replace(olive::tool::kSlide, std::make_shared<SlideTool>(this));
tools_.replace(olive::tool::kHand, std::make_shared<HandTool>(this));
tools_.replace(olive::tool::kZoom, std::make_shared<ZoomTool>(this));
//tools_.replace(olive::tool::kTransition, new (this)); FIXME: Implement
//tools_.replace(olive::tool::kRecord, new PointerTool(this)); FIXME: Implement
//tools_.replace(olive::tool::kAdd, new PointerTool(this)); FIXME: Implement
import_tool_ = std::make_shared<ImportTool>(this);
connect(&scene_, SIGNAL(changed(const QList<QRectF>&)), this, SLOT(UpdateSceneRect()));
// Create end item
@@ -77,43 +57,6 @@ TimelineView::TimelineView(Qt::Alignment vertical_alignment, QWidget *parent) :
SetScale(1.0);
}
void TimelineView::AddBlock(Block *block, int track)
{
switch (block->type()) {
case Block::kClip:
case Block::kGap:
{
TimelineViewBlockItem* item = new TimelineViewBlockItem();
// Set up clip with view parameters (clip item will automatically size its rect accordingly)
item->SetBlock(block);
item->SetY(GetTrackY(track));
item->SetHeight(GetTrackHeight(track));
item->SetScale(scale_);
item->SetTrack(track);
// Add to list of clip items that can be iterated through
block_items_.insert(block, item);
// Add item to graphics scene
scene_.addItem(item);
connect(block, SIGNAL(Refreshed()), this, SLOT(BlockChanged()));
break;
}
case Block::kEnd:
// Do nothing
break;
}
}
void TimelineView::RemoveBlock(Block *block)
{
delete block_items_[block];
block_items_.remove(block);
}
void TimelineView::AddTrack(TrackOutput *track)
{
foreach (Block* b, track->Blocks()) {
@@ -132,20 +75,6 @@ void TimelineView::SetScale(const double &scale)
{
scale_ = scale;
QMapIterator<Block*, TimelineViewBlockItem*> iterator(block_items_);
while (iterator.hasNext()) {
iterator.next();
if (iterator.value() != nullptr) {
iterator.value()->SetScale(scale_);
}
}
foreach (TimelineViewGhostItem* ghost, ghost_items_) {
ghost->SetScale(scale_);
}
// Force redraw for playhead
viewport()->update();
@@ -154,36 +83,18 @@ void TimelineView::SetScale(const double &scale)
void TimelineView::SetTimebase(const rational &timebase)
{
timebase_ = timebase;
timebase_dbl_ = timebase_.toDouble();
SetTimebaseInternal(timebase);
// Timebase influences position/visibility of playhead
viewport()->update();
}
void TimelineView::Clear()
{
QMapIterator<Block*, TimelineViewBlockItem*> iterator(block_items_);
while (iterator.hasNext()) {
iterator.next();
if (iterator.value() != nullptr) {
delete iterator.value();
}
}
block_items_.clear();
}
void TimelineView::ConnectTimelineNode(TrackList *node)
{
if (timeline_node_ != nullptr) {
disconnect(timeline_node_, SIGNAL(TimebaseChanged(const rational&)), this, SIGNAL(TimebaseChanged(const rational&)));
disconnect(timeline_node_, SIGNAL(TimebaseChanged(const rational&)), this, SLOT(SetTimebase(const rational&)));
disconnect(timeline_node_, SIGNAL(TimelineCleared()), this, SLOT(Clear()));
disconnect(timeline_node_, SIGNAL(BlockAdded(Block*, int)), this, SLOT(AddBlock(Block*, int)));
disconnect(timeline_node_, SIGNAL(BlockRemoved(Block*)), this, SLOT(RemoveBlock(Block*)));
disconnect(timeline_node_, SIGNAL(TrackAdded(TrackOutput*)), this, SLOT(AddTrack(TrackOutput*)));
disconnect(timeline_node_, SIGNAL(TrackRemoved(TrackOutput*)), this, SLOT(RemoveTrack(TrackOutput*)));
disconnect(timeline_node_, SIGNAL(LengthChanged(const rational&)), this, SLOT(UpdateEndTimeFromTrackList(const rational&)));
@@ -195,13 +106,11 @@ void TimelineView::ConnectTimelineNode(TrackList *node)
if (timeline_node_ != nullptr) {
SetTimebase(timeline_node_->Timebase());
emit TimebaseChanged(timebase_);
emit TimebaseChanged(timeline_node_->Timebase());
connect(timeline_node_, SIGNAL(TimebaseChanged(const rational&)), this, SIGNAL(TimebaseChanged(const rational&)));
connect(timeline_node_, SIGNAL(TimebaseChanged(const rational&)), this, SLOT(SetTimebase(const rational&)));
connect(timeline_node_, SIGNAL(TimelineCleared()), this, SLOT(Clear()));
connect(timeline_node_, SIGNAL(BlockAdded(Block*, int)), this, SLOT(AddBlock(Block*, int)));
connect(timeline_node_, SIGNAL(BlockRemoved(Block*)), this, SLOT(RemoveBlock(Block*)));
connect(timeline_node_, SIGNAL(TrackAdded(TrackOutput*)), this, SLOT(AddTrack(TrackOutput*)));
connect(timeline_node_, SIGNAL(TrackRemoved(TrackOutput*)), this, SLOT(RemoveTrack(TrackOutput*)));
connect(timeline_node_, SIGNAL(LengthChanged(const rational&)), this, SLOT(UpdateEndTimeFromTrackList(const rational&)));
@@ -251,134 +160,74 @@ void TimelineView::SetTime(const int64_t time)
void TimelineView::mousePressEvent(QMouseEvent *event)
{
active_tool_ = GetActiveTool();
TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()),
event->modifiers());
// Cache these since we modify the event's later on
Qt::KeyboardModifiers mods = event->modifiers();
emit MousePressed(&timeline_event);
if (active_tool_ != nullptr) {
setDragMode(active_tool_->drag_mode());
}
if (active_tool_ == nullptr || active_tool_->enable_default_behavior()) {
// We use Shift for multiple selection while Qt uses Ctrl, we flip those modifiers here to compensate
event->setModifiers(FlipControlAndShiftModifiers(event->modifiers()));
QGraphicsView::mousePressEvent(event);
}
if (timeline_node_ != nullptr && active_tool_ != nullptr) {
TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()),
mods);
active_tool_->MousePress(&timeline_event);
}
}
void TimelineView::mouseMoveEvent(QMouseEvent *event)
{
// Cache these since we modify the event's later on
Qt::KeyboardModifiers mods = event->modifiers();
TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()),
event->modifiers());
if (active_tool_ == nullptr || active_tool_->enable_default_behavior()) {
// We use Shift for multiple selection while Qt uses Ctrl, we flip those modifiers here to compensate
event->setModifiers(FlipControlAndShiftModifiers(event->modifiers()));
QGraphicsView::mouseMoveEvent(event);
}
if (timeline_node_ != nullptr && active_tool_ != nullptr) {
TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()),
mods);
active_tool_->MouseMove(&timeline_event);
}
emit MouseMoved(&timeline_event);
}
void TimelineView::mouseReleaseEvent(QMouseEvent *event)
{
// Cache these since we modify the event's later on
Qt::KeyboardModifiers mods = event->modifiers();
TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()),
event->modifiers());
if (active_tool_ == nullptr || active_tool_->enable_default_behavior()) {
// We use Shift for multiple selection while Qt uses Ctrl, we flip those modifiers here to compensate
event->setModifiers(FlipControlAndShiftModifiers(event->modifiers()));
QGraphicsView::mouseReleaseEvent(event);
}
if (timeline_node_ != nullptr && active_tool_ != nullptr) {
TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()),
mods);
active_tool_->MouseRelease(&timeline_event);
}
emit MouseReleased(&timeline_event);
}
void TimelineView::mouseDoubleClickEvent(QMouseEvent *event)
{
// Cache these since we modify the event's later on
Qt::KeyboardModifiers mods = event->modifiers();
TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()),
event->modifiers());
if (active_tool_ == nullptr || active_tool_->enable_default_behavior()) {
// We use Shift for multiple selection while Qt uses Ctrl, we flip those modifiers here to compensate
event->setModifiers(FlipControlAndShiftModifiers(event->modifiers()));
QGraphicsView::mouseDoubleClickEvent(event);
}
if (timeline_node_ != nullptr && active_tool_ != nullptr) {
TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()),
mods);
active_tool_->MouseDoubleClick(&timeline_event);
}
emit MouseDoubleClicked(&timeline_event);
}
void TimelineView::dragEnterEvent(QDragEnterEvent *event)
{
if (timeline_node_ != nullptr) {
TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()),
event->keyboardModifiers());
TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()),
event->keyboardModifiers());
timeline_event.SetMimeData(event->mimeData());
timeline_event.SetEvent(event);
timeline_event.SetMimeData(event->mimeData());
timeline_event.SetEvent(event);
import_tool_->DragEnter(&timeline_event);
}
emit DragEntered(&timeline_event);
}
void TimelineView::dragMoveEvent(QDragMoveEvent *event)
{
if (timeline_node_ != nullptr) {
TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()),
event->keyboardModifiers());
TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()),
event->keyboardModifiers());
timeline_event.SetMimeData(event->mimeData());
timeline_event.SetEvent(event);
timeline_event.SetMimeData(event->mimeData());
timeline_event.SetEvent(event);
import_tool_->DragMove(&timeline_event);
}
emit DragMoved(&timeline_event);
}
void TimelineView::dragLeaveEvent(QDragLeaveEvent *event)
{
if (timeline_node_ != nullptr) {
import_tool_->DragLeave(event);
}
emit DragLeft(event);
}
void TimelineView::dropEvent(QDropEvent *event)
{
if (timeline_node_ != nullptr) {
TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()),
event->keyboardModifiers());
TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()),
event->keyboardModifiers());
timeline_event.SetMimeData(event->mimeData());
timeline_event.SetEvent(event);
timeline_event.SetMimeData(event->mimeData());
timeline_event.SetEvent(event);
import_tool_->DragDrop(&timeline_event);
}
emit DragDropped(&timeline_event);
}
void TimelineView::resizeEvent(QResizeEvent *event)
@@ -392,9 +241,9 @@ void TimelineView::drawForeground(QPainter *painter, const QRectF &rect)
{
QGraphicsView::drawForeground(painter, rect);
if (!timebase_.isNull()) {
double x = TimeToScreenCoord(rational(playhead_ * timebase_.numerator(), timebase_.denominator()));
double width = TimeToScreenCoord(timebase_);
if (!timebase().isNull()) {
double x = TimeToScene(rational(playhead_ * timebase().numerator(), timebase().denominator()));
double width = TimeToScene(timebase());
QRectF playhead_rect(x, rect.top(), width, rect.height());
@@ -444,11 +293,6 @@ TimelineCoordinate TimelineView::SceneToCoordinate(const QPointF& pt)
return TimelineCoordinate(SceneToTime(pt.x()), SceneToTrack(pt.y()));
}
TimelineView::Tool *TimelineView::GetActiveTool()
{
return tools_.at(olive::core.tool()).get();
}
int TimelineView::GetTrackY(int track_index)
{
int y = 0;
@@ -479,20 +323,6 @@ void TimelineView::AddGhost(TimelineViewGhostItem *ghost)
scene_.addItem(ghost);
}
bool TimelineView::HasGhosts()
{
return !ghost_items_.isEmpty();
}
rational TimelineView::SceneToTime(const double &x)
{
// Adjust screen point by scale and timebase
qint64 scaled_x_mvmt = qRound64(x / scale_ / timebase_dbl_);
// Return a time in the timebase
return rational(scaled_x_mvmt * timebase_.numerator(), timebase_.denominator());
}
int TimelineView::SceneToTrack(double y)
{
int track = -1;
@@ -510,17 +340,6 @@ int TimelineView::SceneToTrack(double y)
return track;
}
void TimelineView::ClearGhosts()
{
if (!ghost_items_.isEmpty()) {
foreach (TimelineViewGhostItem* ghost, ghost_items_) {
delete ghost;
}
ghost_items_.clear();
}
}
void TimelineView::UserSetTime(const int64_t &time)
{
SetTime(time);
@@ -529,7 +348,7 @@ void TimelineView::UserSetTime(const int64_t &time)
rational TimelineView::GetPlayheadTime()
{
return rational(playhead_ * timebase_.numerator(), timebase_.denominator());
return rational(playhead_ * timebase().numerator(), timebase().denominator());
}
void TimelineView::BlockChanged()
@@ -587,24 +406,3 @@ void TimelineView::SetEndTime(const rational &length)
{
end_item_->SetEndTime(length);
}
void TimelineView::SetSiblings(TimelineView *a, TimelineView *b)
{
if (a == b)
return;
if (!a->siblings_.contains(b))
a->siblings_.append(b);
if (!b->siblings_.contains(a))
b->siblings_.append(a);
}
void TimelineView::SetSiblings(const QList<TimelineView *> &siblings)
{
foreach (TimelineView* view, siblings) {
foreach (TimelineView* sibling, siblings) {
SetSiblings(view, sibling);
}
}
}
+12 -267
View File
@@ -62,21 +62,14 @@ public:
void SetEndTime(const rational& length);
static void SetSiblings(TimelineView* a, TimelineView* b);
static void SetSiblings(const QList<TimelineView*>& siblings);
int GetTrackY(int track_index);
int GetTrackHeight(int track_index);
public slots:
void SetTimebase(const rational& timebase);
void SetTime(const int64_t time);
void Clear();
void AddBlock(Block* block, int track);
void RemoveBlock(Block* block);
void AddTrack(TrackOutput* track);
void RemoveTrack(TrackOutput* track);
@@ -88,6 +81,16 @@ signals:
void TimeChanged(const int64_t& time);
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);
protected:
virtual void mousePressEvent(QMouseEvent *event) override;
virtual void mouseMoveEvent(QMouseEvent *event) override;
@@ -104,284 +107,28 @@ protected:
virtual void drawForeground(QPainter *painter, const QRectF &rect) override;
private:
class Tool
{
public:
Tool(TimelineView* parent);
virtual ~Tool();
virtual void MousePress(TimelineViewMouseEvent *){}
virtual void MouseMove(TimelineViewMouseEvent *){}
virtual void MouseRelease(TimelineViewMouseEvent *){}
virtual void MouseDoubleClick(TimelineViewMouseEvent *){}
virtual void DragEnter(TimelineViewMouseEvent *){}
virtual void DragMove(TimelineViewMouseEvent *){}
virtual void DragLeave(QDragLeaveEvent *){}
virtual void DragDrop(TimelineViewMouseEvent *){}
TimelineView* parent();
static olive::timeline::MovementMode FlipTrimMode(const olive::timeline::MovementMode& trim_mode);
const DragMode& drag_mode();
bool enable_default_behavior();
protected:
void set_drag_mode(const DragMode& mode);
void set_enable_default_behavior(bool enable);
/**
* @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
*/
TimelineViewBlockItem* GetItemAtScenePos(const TimelineCoordinate &coord);
/**
* @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 ValidateFrameMovement(rational movement, const QVector<TimelineViewGhostItem*> ghosts);
/**
* @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);
enum SnapPoints {
kSnapToClips = 0x1,
kSnapToPlayhead = 0x2,
kSnapAll = 0xFF
};
/**
* @brief Snaps point `start_point` that is moving by `movement` to currently existing clips
*/
bool SnapPoint(QList<rational> start_times, rational *movement, int snap_points = kSnapAll);
QList<rational> snap_points_;
bool dragging_;
TimelineCoordinate drag_start_;
private:
TimelineView* parent_;
DragMode drag_mode_;
bool enable_default_behavior_;
};
class PointerTool : public Tool
{
public:
PointerTool(TimelineView* parent);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
protected:
void SetMovementAllowed(bool allowed);
void SetTrackMovementAllowed(bool allowed);
void SetTrimmingAllowed(bool allowed);
virtual void MouseReleaseInternal(TimelineViewMouseEvent *event);
virtual rational FrameValidateInternal(rational time_movement, const QVector<TimelineViewGhostItem *> &ghosts);
virtual void InitiateGhosts(TimelineViewBlockItem* clicked_item,
olive::timeline::MovementMode trim_mode,
bool allow_gap_trimming);
TimelineViewGhostItem* AddGhostFromBlock(Block *block, int track, olive::timeline::MovementMode mode);
TimelineViewGhostItem* AddGhostFromNull(const rational& in, const rational& out, int track, olive::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, const QVector<TimelineViewGhostItem*> ghosts, bool prevent_overwriting);
/**
* @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, const QVector<TimelineViewGhostItem*> ghosts, bool prevent_overwriting);
virtual void ProcessDrag(const TimelineCoordinate &mouse_pos);
private:
void InitiateDrag(const TimelineCoordinate &mouse_pos);
void AddGhostInternal(TimelineViewGhostItem* ghost, olive::timeline::MovementMode mode);
QList<TimelineViewBlockItem*> GetSelectedClips();
bool IsClipTrimmable(TimelineViewBlockItem* clip,
const QList<TimelineViewBlockItem*>& items,
const olive::timeline::MovementMode& mode);
int track_start_;
bool movement_allowed_;
bool trimming_allowed_;
bool track_movement_allowed_;
};
class ImportTool : public Tool
{
public:
ImportTool(TimelineView* 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;
private:
int import_pre_buffer_;
};
class RazorTool : public Tool
{
public:
RazorTool(TimelineView* parent);
virtual void MousePress(TimelineViewMouseEvent *event);
virtual void MouseMove(TimelineViewMouseEvent *event);
virtual void MouseRelease(TimelineViewMouseEvent *event);
private:
QVector<int> split_tracks_;
};
class RippleTool : public PointerTool
{
public:
RippleTool(TimelineView* parent);
protected:
virtual void MouseReleaseInternal(TimelineViewMouseEvent *event) override;
virtual rational FrameValidateInternal(rational time_movement, const QVector<TimelineViewGhostItem*>& ghosts) override;
virtual void InitiateGhosts(TimelineViewBlockItem* clicked_item,
olive::timeline::MovementMode trim_mode,
bool allow_gap_trimming) override;
};
class RollingTool : public PointerTool
{
public:
RollingTool(TimelineView* parent);
protected:
virtual void MouseReleaseInternal(TimelineViewMouseEvent *event) override;
virtual rational FrameValidateInternal(rational time_movement, const QVector<TimelineViewGhostItem*>& ghosts) override;
virtual void InitiateGhosts(TimelineViewBlockItem* clicked_item,
olive::timeline::MovementMode trim_mode,
bool allow_gap_trimming) override;
};
class SlideTool : public PointerTool
{
public:
SlideTool(TimelineView* parent);
protected:
virtual void MouseReleaseInternal(TimelineViewMouseEvent *event) override;
virtual rational FrameValidateInternal(rational time_movement, const QVector<TimelineViewGhostItem*>& ghosts) override;
virtual void InitiateGhosts(TimelineViewBlockItem* clicked_item,
olive::timeline::MovementMode trim_mode,
bool allow_gap_trimming) override;
};
class SlipTool : public PointerTool
{
public:
SlipTool(TimelineView* parent);
protected:
virtual void ProcessDrag(const TimelineCoordinate &mouse_pos) override;
virtual void MouseReleaseInternal(TimelineViewMouseEvent *event) override;
};
class HandTool : public Tool
{
public:
HandTool(TimelineView* parent);
private:
QPoint screen_drag_start_;
QPoint scrollbar_start_;
};
class ZoomTool : public Tool
{
public:
ZoomTool(TimelineView* parent);
virtual void MousePress(TimelineViewMouseEvent *event);
virtual void MouseMove(TimelineViewMouseEvent *event);
virtual void MouseRelease(TimelineViewMouseEvent *event);
};
TrackType ConnectedTrackType();
Stream::Type TrackTypeToStreamType(TrackType track_type);
TimelineCoordinate ScreenToCoordinate(const QPoint& pt);
TimelineCoordinate SceneToCoordinate(const QPointF& pt);
Tool* GetActiveTool();
int GetTrackY(int track_index);
int GetTrackHeight(int track_index);
QVector< std::shared_ptr<Tool> > tools_;
std::shared_ptr<ImportTool> import_tool_;
TrackList* timeline_node_;
void AddGhost(TimelineViewGhostItem* ghost);
bool HasGhosts();
rational SceneToTime(const double &x);
int SceneToTrack(double y);
void ClearGhosts();
void UserSetTime(const int64_t& time);
QGraphicsScene scene_;
rational timebase_;
double timebase_dbl_;
int64_t playhead_;
QMap<Block*, TimelineViewBlockItem*> block_items_;
QVector<TimelineViewGhostItem*> ghost_items_;
QVector<int> track_heights_;
TimelineViewEndItem* end_item_;
Tool* active_tool_;
TimelinePlayhead playhead_style_;
rational GetPlayheadTime();
@@ -392,8 +139,6 @@ private:
bool use_tracklist_length_directly_;
QVector<TimelineView*> siblings_;
private slots:
/**
* @brief Slot for when a Block node changes its parameters and the graphics need to update
@@ -52,8 +52,8 @@ void TimelineViewBlockItem::UpdateRect()
return;
}
double item_left = TimeToScreenCoord(block_->in());
double item_width = TimeToScreenCoord(block_->length());
double item_left = TimeToScene(block_->in());
double item_width = TimeToScene(block_->length());
// -1 on width and height so we don't overlap any adjacent clips
setRect(0, y_, item_width - 1, height_ - 1);
@@ -25,7 +25,7 @@ void TimelineViewEndItem::UpdateRect()
// Doesn't need to be more than one pixel
setRect(0, 0, 1, 1);
setPos(TimeToScreenCoord(end_time_) + end_padding_, 0);
setPos(TimeToScene(end_time_) + end_padding_, 0);
}
void TimelineViewEndItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
@@ -32,7 +32,7 @@ TimelineViewGhostItem::TimelineViewGhostItem(QGraphicsItem *parent) :
SetInvisible(false);
}
TimelineViewGhostItem *TimelineViewGhostItem::FromBlock(Block *block, int track, int y, int height)
TimelineViewGhostItem *TimelineViewGhostItem::FromBlock(Block *block, const TrackReference& track, int y, int height)
{
TimelineViewGhostItem* ghost = new TimelineViewGhostItem();
@@ -170,7 +170,7 @@ rational TimelineViewGhostItem::GetAdjustedMediaIn() const
return media_in_ + media_in_adj_;
}
int TimelineViewGhostItem::GetAdjustedTrack() const
TrackReference TimelineViewGhostItem::GetAdjustedTrack() const
{
return track_ + track_adj_;
}
@@ -189,7 +189,7 @@ void TimelineViewGhostItem::UpdateRect()
{
rational length = GetAdjustedOut() - GetAdjustedIn();
setRect(0, y_, TimeToScreenCoord(length), height_ - 1);
setRect(0, y_, TimeToScene(length), height_ - 1);
setPos(TimeToScreenCoord(GetAdjustedIn()), 0);
setPos(TimeToScene(GetAdjustedIn()), 0);
}
@@ -42,7 +42,7 @@ public:
TimelineViewGhostItem(QGraphicsItem* parent = nullptr);
static TimelineViewGhostItem* FromBlock(Block *block, int track, int y, int height);
static TimelineViewGhostItem* FromBlock(Block *block, const TrackReference &track, int y, int height);
bool CanHaveZeroLength();
@@ -72,7 +72,7 @@ public:
rational GetAdjustedIn() const;
rational GetAdjustedOut() const;
rational GetAdjustedMediaIn() const;
int GetAdjustedTrack() const;
TrackReference GetAdjustedTrack() const;
const olive::timeline::MovementMode& mode() const;
void SetMode(const olive::timeline::MovementMode& mode);
@@ -32,7 +32,7 @@ TimelineViewMouseEvent::TimelineViewMouseEvent(const TimelineCoordinate &coord,
}
TimelineViewMouseEvent::TimelineViewMouseEvent(const rational &frame,
const int &track,
const TrackReference &track,
const Qt::KeyboardModifiers &modifiers) :
coord_(frame, track),
modifiers_(modifiers),
@@ -25,7 +25,7 @@
#include <QPointF>
#include <QPoint>
#include "timelinecoordinate.h"
#include "timeline/timelinecoordinate.h"
class TimelineViewMouseEvent
{
@@ -34,7 +34,7 @@ public:
const Qt::KeyboardModifiers& modifiers = Qt::NoModifier);
TimelineViewMouseEvent(const rational& frame,
const int& track,
const TrackReference &track,
const Qt::KeyboardModifiers& modifiers = Qt::NoModifier);
const TimelineCoordinate& GetCoordinates();
+2 -2
View File
@@ -52,12 +52,12 @@ void TimelineViewRect::SetHeight(const int &height)
UpdateRect();
}
const int &TimelineViewRect::Track()
const TrackReference &TimelineViewRect::Track()
{
return track_;
}
void TimelineViewRect::SetTrack(const int &track)
void TimelineViewRect::SetTrack(const TrackReference &track)
{
track_ = track;
}
+4 -3
View File
@@ -23,6 +23,7 @@
#include <QGraphicsRectItem>
#include "timeline/timelinecoordinate.h"
#include "timelinescaledobject.h"
/**
@@ -39,8 +40,8 @@ public:
const int& Height();
void SetHeight(const int& height);
const int& Track();
void SetTrack(const int& track);
const TrackReference& Track();
void SetTrack(const TrackReference& track);
void SetScale(const double& scale);
@@ -51,7 +52,7 @@ protected:
int height_;
int track_;
TrackReference track_;
};
#endif // TIMELINEVIEWRECT_H
+3 -3
View File
@@ -18,12 +18,12 @@
***/
#include "widget/timelineview/timelineview.h"
#include "widget/timelinewidget/timelinewidget.h"
#include <QScrollBar>
TimelineView::HandTool::HandTool(TimelineView* parent) :
TimelineWidget::HandTool::HandTool(TimelineWidget* parent) :
Tool(parent)
{
set_drag_mode(ScrollHandDrag);
set_drag_mode(QGraphicsView::ScrollHandDrag);
}
+59 -32
View File
@@ -18,7 +18,7 @@
***/
#include "widget/timelineview/timelineview.h"
#include "widget/timelinewidget/timelinewidget.h"
#include <QMimeData>
#include <QToolTip>
@@ -30,7 +30,26 @@
#include "node/color/opacity/opacity.h"
#include "node/input/media/media.h"
TimelineView::ImportTool::ImportTool(TimelineView *parent) :
TrackType TrackTypeFromStreamType(Stream::Type stream_type)
{
switch (stream_type) {
case Stream::kVideo:
case Stream::kImage:
return kTrackTypeVideo;
case Stream::kAudio:
return kTrackTypeAudio;
case Stream::kSubtitle:
return kTrackTypeSubtitle;
case Stream::kUnknown:
case Stream::kData:
case Stream::kAttachment:
break;
}
return kTrackTypeNone;
}
TimelineWidget::ImportTool::ImportTool(TimelineWidget *parent) :
Tool(parent)
{
// Calculate width used for importing to give ghosts a slight lead-in so the ghosts aren't right on the cursor
@@ -38,7 +57,7 @@ TimelineView::ImportTool::ImportTool(TimelineView *parent) :
import_pre_buffer_ = QFontMetricsWidth(&fm, "HHHHHHHH");
}
void TimelineView::ImportTool::DragEnter(TimelineViewMouseEvent *event)
void TimelineWidget::ImportTool::DragEnter(TimelineViewMouseEvent *event)
{
QStringList mime_formats = event->GetMimeData()->formats();
@@ -80,30 +99,34 @@ void TimelineView::ImportTool::DragEnter(TimelineViewMouseEvent *event)
// Loop through all streams in footage
foreach (StreamPtr stream, footage->streams()) {
// Check if this stream is compatible with this TrackList
if (stream->type() == parent()->TrackTypeToStreamType(parent()->ConnectedTrackType())) {
TimelineViewGhostItem* ghost = new TimelineViewGhostItem();
TrackType track_type = TrackTypeFromStreamType(stream->type());
if (stream->type() == Stream::kImage) {
// Stream is essentially length-less - use config's default image length
footage_duration = Config::Current()["DefaultStillLength"].value<rational>();
} else {
// Use duration from file
footage_duration = rational(stream->timebase().numerator() * stream->duration(),
stream->timebase().denominator());
}
ghost->SetIn(ghost_start);
ghost->SetOut(ghost_start + footage_duration);
snap_points_.append(ghost->In());
snap_points_.append(ghost->Out());
ghost->setData(TimelineViewGhostItem::kAttachedFootage, QVariant::fromValue(stream));
ghost->SetMode(olive::timeline::kMove);
parent()->AddGhost(ghost);
// Check if this stream has a compatible TrackList
if (track_type == kTrackTypeNone) {
continue;
}
TimelineViewGhostItem* ghost = new TimelineViewGhostItem();
if (stream->type() == Stream::kImage) {
// Stream is essentially length-less - use config's default image length
footage_duration = Config::Current()["DefaultStillLength"].value<rational>();
} else {
// Use duration from file
footage_duration = rational(stream->timebase().numerator() * stream->duration(),
stream->timebase().denominator());
}
ghost->SetIn(ghost_start);
ghost->SetOut(ghost_start + footage_duration);
snap_points_.append(ghost->In());
snap_points_.append(ghost->Out());
ghost->setData(TimelineViewGhostItem::kAttachedFootage, QVariant::fromValue(stream));
ghost->SetMode(olive::timeline::kMove);
parent()->AddGhost(ghost);
}
// Stack each ghost one after the other
@@ -118,12 +141,12 @@ void TimelineView::ImportTool::DragEnter(TimelineViewMouseEvent *event)
}
}
void TimelineView::ImportTool::DragMove(TimelineViewMouseEvent *event)
void TimelineWidget::ImportTool::DragMove(TimelineViewMouseEvent *event)
{
if (parent()->HasGhosts()) {
rational time_movement = event->GetCoordinates().GetFrame() - drag_start_.GetFrame();
int ghost_track = event->GetCoordinates().GetTrack();
const TrackReference& ghost_track = event->GetCoordinates().GetTrack();
int ghost_y = parent()->GetTrackY(ghost_track);
int ghost_height = parent()->GetTrackHeight(ghost_track);
@@ -150,9 +173,9 @@ void TimelineView::ImportTool::DragMove(TimelineViewMouseEvent *event)
}
// Generate tooltip (showing earliest in point of imported clip)
int64_t earliest_timestamp = olive::time_to_timestamp(earliest_ghost, parent()->timebase_);
int64_t earliest_timestamp = olive::time_to_timestamp(earliest_ghost, parent()->timebase());
QString tooltip_text = olive::timestamp_to_timecode(earliest_timestamp,
parent()->timebase_,
parent()->timebase(),
olive::CurrentTimecodeDisplay());
QToolTip::showText(QCursor::pos(),
tooltip_text,
@@ -164,7 +187,7 @@ void TimelineView::ImportTool::DragMove(TimelineViewMouseEvent *event)
}
}
void TimelineView::ImportTool::DragLeave(QDragLeaveEvent* event)
void TimelineWidget::ImportTool::DragLeave(QDragLeaveEvent* event)
{
if (parent()->HasGhosts()) {
parent()->ClearGhosts();
@@ -175,7 +198,7 @@ void TimelineView::ImportTool::DragLeave(QDragLeaveEvent* event)
}
}
void TimelineView::ImportTool::DragDrop(TimelineViewMouseEvent *event)
void TimelineWidget::ImportTool::DragDrop(TimelineViewMouseEvent *event)
{
if (parent()->HasGhosts()) {
// We use QObject as the parent for the nodes we create. If there is no TimelineOutput node, this object going out
@@ -209,7 +232,11 @@ void TimelineView::ImportTool::DragDrop(TimelineViewMouseEvent *event)
if (event->GetModifiers() & Qt::ControlModifier) {
//emit parent()->RequestInsertBlockAtTime(clip, ghost->GetAdjustedIn());
} else {
new TrackPlaceBlockCommand(parent()->timeline_node_, ghost->Track(), clip, ghost->GetAdjustedIn(), command);
new TrackPlaceBlockCommand(parent()->timeline_node_->track_list(ghost->Track().type()),
ghost->Track().index(),
clip,
ghost->GetAdjustedIn(),
command);
}
}
+40 -31
View File
@@ -18,7 +18,7 @@
***/
#include "widget/timelineview/timelineview.h"
#include "widget/timelinewidget/timelinewidget.h"
#include <QDebug>
#include <QToolTip>
@@ -31,23 +31,23 @@
#include "core.h"
#include "node/block/gap/gap.h"
TimelineView::PointerTool::PointerTool(TimelineView *parent) :
TimelineWidget::PointerTool::PointerTool(TimelineWidget *parent) :
Tool(parent),
movement_allowed_(true),
trimming_allowed_(true),
track_movement_allowed_(true)
{
set_drag_mode(RubberBandDrag);
set_drag_mode(QGraphicsView::RubberBandDrag);
set_enable_default_behavior(true);
}
void TimelineView::PointerTool::MousePress(TimelineViewMouseEvent *event)
void TimelineWidget::PointerTool::MousePress(TimelineViewMouseEvent *event)
{
// We don't initiate dragging here since clicking could easily be just for selecting
Q_UNUSED(event)
}
void TimelineView::PointerTool::MouseMove(TimelineViewMouseEvent *event)
void TimelineWidget::PointerTool::MouseMove(TimelineViewMouseEvent *event)
{
qDebug() << dragging_ << parent()->ghost_items_.isEmpty();
@@ -68,7 +68,7 @@ void TimelineView::PointerTool::MouseMove(TimelineViewMouseEvent *event)
}
}
void TimelineView::PointerTool::MouseRelease(TimelineViewMouseEvent *event)
void TimelineWidget::PointerTool::MouseRelease(TimelineViewMouseEvent *event)
{
if (!parent()->ghost_items_.isEmpty()) {
MouseReleaseInternal(event);
@@ -82,22 +82,22 @@ void TimelineView::PointerTool::MouseRelease(TimelineViewMouseEvent *event)
dragging_ = false;
}
void TimelineView::PointerTool::SetMovementAllowed(bool allowed)
void TimelineWidget::PointerTool::SetMovementAllowed(bool allowed)
{
movement_allowed_ = allowed;
}
void TimelineView::PointerTool::SetTrackMovementAllowed(bool allowed)
void TimelineWidget::PointerTool::SetTrackMovementAllowed(bool allowed)
{
track_movement_allowed_ = allowed;
}
void TimelineView::PointerTool::SetTrimmingAllowed(bool allowed)
void TimelineWidget::PointerTool::SetTrimmingAllowed(bool allowed)
{
trimming_allowed_ = allowed;
}
void TimelineView::PointerTool::MouseReleaseInternal(TimelineViewMouseEvent *event)
void TimelineWidget::PointerTool::MouseReleaseInternal(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
@@ -117,7 +117,10 @@ void TimelineView::PointerTool::MouseReleaseInternal(TimelineViewMouseEvent *eve
gap->setParent(&block_memory_manager);
gap->set_length(b->length());
new TrackReplaceBlockCommand(parent()->timeline_node_->TrackAt(ghost->Track()), b, gap, command);
new TrackReplaceBlockCommand(parent()->GetTrackFromReference(ghost->Track()),
b,
gap,
command);
}
// Now we place the clips back in the timeline where the user moved them. It's legal for them to overwrite parts or
@@ -137,13 +140,19 @@ void TimelineView::PointerTool::MouseReleaseInternal(TimelineViewMouseEvent *eve
}
}
new TrackPlaceBlockCommand(parent()->timeline_node_, ghost->GetAdjustedTrack(), b, ghost->GetAdjustedIn(), command);
const TrackReference& track_ref = ghost->GetAdjustedTrack();
new TrackPlaceBlockCommand(parent()->timeline_node_->track_list(track_ref.type()),
track_ref.index(),
b,
ghost->GetAdjustedIn(),
command);
}
olive::undo_stack.pushIfHasChildren(command);
}
rational TimelineView::PointerTool::FrameValidateInternal(rational time_movement, const QVector<TimelineViewGhostItem *>& ghosts)
rational TimelineWidget::PointerTool::FrameValidateInternal(rational time_movement, const QVector<TimelineViewGhostItem *>& ghosts)
{
// Default behavior is to validate all movement and trimming
time_movement = ValidateFrameMovement(time_movement, ghosts);
@@ -153,7 +162,7 @@ rational TimelineView::PointerTool::FrameValidateInternal(rational time_movement
return time_movement;
}
void TimelineView::PointerTool::InitiateDrag(const TimelineCoordinate &mouse_pos)
void TimelineWidget::PointerTool::InitiateDrag(const TimelineCoordinate &mouse_pos)
{
// Record where the drag started in timeline coordinates
drag_start_ = mouse_pos;
@@ -177,7 +186,7 @@ void TimelineView::PointerTool::InitiateDrag(const TimelineCoordinate &mouse_pos
// FIXME: Hardcoded number
const int kTrimHandle = 20;
qreal mouse_x = parent()->TimeToScreenCoord(mouse_pos.GetFrame());
qreal mouse_x = parent()->TimeToScene(mouse_pos.GetFrame());
if (trimming_allowed_ && mouse_x < clicked_item->x() + kTrimHandle) {
trim_mode = olive::timeline::kTrimIn;
@@ -200,14 +209,14 @@ void TimelineView::PointerTool::InitiateDrag(const TimelineCoordinate &mouse_pos
}
}
void TimelineView::PointerTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
void TimelineWidget::PointerTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
{
// Determine track movement
int cursor_track = mouse_pos.GetTrack();
const TrackReference& cursor_track = mouse_pos.GetTrack();
int track_movement = 0;
if (track_movement_allowed_) {
track_movement = cursor_track - track_start_;
track_movement = cursor_track.index() - track_start_.index();
}
// Determine frame movement
@@ -240,7 +249,7 @@ void TimelineView::PointerTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
// Track movement is only legal for moving, not for trimming
ghost->SetTrackAdjustment(track_movement);
int track = ghost->GetAdjustedTrack();
const TrackReference& track = ghost->GetAdjustedTrack();
ghost->SetY(parent()->GetTrackY(track));
ghost->SetHeight(parent()->GetTrackHeight(track));
break;
@@ -250,9 +259,9 @@ void TimelineView::PointerTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
// Show tooltip
// Generate tooltip (showing earliest in point of imported clip)
int64_t earliest_timestamp = olive::time_to_timestamp(time_movement, parent()->timebase_);
int64_t earliest_timestamp = olive::time_to_timestamp(time_movement, parent()->timebase());
QString tooltip_text = olive::timestamp_to_timecode(earliest_timestamp,
parent()->timebase_,
parent()->timebase(),
olive::CurrentTimecodeDisplay(),
true);
QToolTip::showText(QCursor::pos(),
@@ -260,7 +269,7 @@ void TimelineView::PointerTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
parent());
}
void TimelineView::PointerTool::InitiateGhosts(TimelineViewBlockItem* clicked_item,
void TimelineWidget::PointerTool::InitiateGhosts(TimelineViewBlockItem* clicked_item,
olive::timeline::MovementMode trim_mode,
bool allow_gap_trimming)
{
@@ -313,7 +322,7 @@ void TimelineView::PointerTool::InitiateGhosts(TimelineViewBlockItem* clicked_it
}
}
TimelineViewGhostItem* TimelineView::PointerTool::AddGhostFromBlock(Block* block, int track, olive::timeline::MovementMode mode)
TimelineViewGhostItem* TimelineWidget::PointerTool::AddGhostFromBlock(Block* block, const TrackReference& track, olive::timeline::MovementMode mode)
{
TimelineViewGhostItem* ghost = TimelineViewGhostItem::FromBlock(block,
track,
@@ -325,7 +334,7 @@ TimelineViewGhostItem* TimelineView::PointerTool::AddGhostFromBlock(Block* block
return ghost;
}
TimelineViewGhostItem* TimelineView::PointerTool::AddGhostFromNull(const rational &in, const rational &out, int track, olive::timeline::MovementMode mode)
TimelineViewGhostItem* TimelineWidget::PointerTool::AddGhostFromNull(const rational &in, const rational &out, const TrackReference& track, olive::timeline::MovementMode mode)
{
TimelineViewGhostItem* ghost = new TimelineViewGhostItem();
@@ -340,7 +349,7 @@ TimelineViewGhostItem* TimelineView::PointerTool::AddGhostFromNull(const rationa
return ghost;
}
void TimelineView::PointerTool::AddGhostInternal(TimelineViewGhostItem* ghost, olive::timeline::MovementMode mode)
void TimelineWidget::PointerTool::AddGhostInternal(TimelineViewGhostItem* ghost, olive::timeline::MovementMode mode)
{
ghost->SetScale(parent()->scale_);
ghost->SetMode(mode);
@@ -365,7 +374,7 @@ void TimelineView::PointerTool::AddGhostInternal(TimelineViewGhostItem* ghost, o
parent()->scene_.addItem(ghost);
}
QList<TimelineViewBlockItem *> TimelineView::PointerTool::GetSelectedClips()
QList<TimelineViewBlockItem *> TimelineWidget::PointerTool::GetSelectedClips()
{
QList<QGraphicsItem*> selected_items = parent()->scene_.selectedItems();
@@ -382,7 +391,7 @@ QList<TimelineViewBlockItem *> TimelineView::PointerTool::GetSelectedClips()
return clips;
}
bool TimelineView::PointerTool::IsClipTrimmable(TimelineViewBlockItem* clip,
bool TimelineWidget::PointerTool::IsClipTrimmable(TimelineViewBlockItem* clip,
const QList<TimelineViewBlockItem*>& items,
const olive::timeline::MovementMode& mode)
{
@@ -398,7 +407,7 @@ bool TimelineView::PointerTool::IsClipTrimmable(TimelineViewBlockItem* clip,
return true;
}
rational TimelineView::PointerTool::ValidateInTrimming(rational movement,
rational TimelineWidget::PointerTool::ValidateInTrimming(rational movement,
const QVector<TimelineViewGhostItem *> ghosts,
bool prevent_overwriting)
{
@@ -428,7 +437,7 @@ rational TimelineView::PointerTool::ValidateInTrimming(rational movement,
rational latest_in = ghost->Out();
if (!ghost->CanHaveZeroLength()) {
latest_in -= parent()->timebase_;
latest_in -= parent()->timebase();
}
// Clamp adjusted value between the earliest and latest values
@@ -443,7 +452,7 @@ rational TimelineView::PointerTool::ValidateInTrimming(rational movement,
return movement;
}
rational TimelineView::PointerTool::ValidateOutTrimming(rational movement,
rational TimelineWidget::PointerTool::ValidateOutTrimming(rational movement,
const QVector<TimelineViewGhostItem *> ghosts,
bool prevent_overwriting)
{
@@ -458,7 +467,7 @@ rational TimelineView::PointerTool::ValidateOutTrimming(rational movement,
rational earliest_out = ghost->In();
if (!ghost->CanHaveZeroLength()) {
earliest_out += parent()->timebase_;
earliest_out += parent()->timebase();
}
rational latest_out = RATIONAL_MAX;
+8 -8
View File
@@ -18,21 +18,21 @@
***/
#include "widget/timelineview/timelineview.h"
#include "widget/timelinewidget/timelinewidget.h"
TimelineView::RazorTool::RazorTool(TimelineView* parent) :
TimelineWidget::RazorTool::RazorTool(TimelineWidget* parent) :
Tool(parent)
{
}
void TimelineView::RazorTool::MousePress(TimelineViewMouseEvent *event)
void TimelineWidget::RazorTool::MousePress(TimelineViewMouseEvent *event)
{
split_tracks_.clear();
MouseMove(event);
}
void TimelineView::RazorTool::MouseMove(TimelineViewMouseEvent *event)
void TimelineWidget::RazorTool::MouseMove(TimelineViewMouseEvent *event)
{
if (!dragging_) {
drag_start_ = event->GetCoordinates();
@@ -40,14 +40,14 @@ void TimelineView::RazorTool::MouseMove(TimelineViewMouseEvent *event)
}
// Split at the current cursor track
int split_track = event->GetCoordinates().GetTrack();
TrackReference split_track = event->GetCoordinates().GetTrack();
if (!split_tracks_.contains(split_track)) {
split_tracks_.append(split_track);
}
}
void TimelineView::RazorTool::MouseRelease(TimelineViewMouseEvent *event)
void TimelineWidget::RazorTool::MouseRelease(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
@@ -56,8 +56,8 @@ void TimelineView::RazorTool::MouseRelease(TimelineViewMouseEvent *event)
QUndoCommand* command = new QUndoCommand();
foreach (int track, split_tracks_) {
new TrackSplitAtTimeCommand(parent()->timeline_node_->TrackAt(track), split_time, command);
foreach (const TrackReference& track, split_tracks_) {
new TrackSplitAtTimeCommand(parent()->GetTrackFromReference(track), split_time, command);
}
split_tracks_.clear();
+8 -8
View File
@@ -18,17 +18,17 @@
***/
#include "widget/timelineview/timelineview.h"
#include "widget/timelinewidget/timelinewidget.h"
#include "node/block/gap/gap.h"
TimelineView::RippleTool::RippleTool(TimelineView* parent) :
TimelineWidget::RippleTool::RippleTool(TimelineWidget* parent) :
PointerTool(parent)
{
SetMovementAllowed(false);
}
void TimelineView::RippleTool::MouseReleaseInternal(TimelineViewMouseEvent *event)
void TimelineWidget::RippleTool::MouseReleaseInternal(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
@@ -51,7 +51,7 @@ void TimelineView::RippleTool::MouseReleaseInternal(TimelineViewMouseEvent *even
Block* block_to_append_gap_to = Node::ValueToPtr<Block>(ghost->data(TimelineViewGhostItem::kReferenceBlock));
new TrackInsertBlockBetweenBlocksCommand(parent()->timeline_node_->Tracks().at(ghost->Track()),
new TrackInsertBlockBetweenBlocksCommand(parent()->GetTrackFromReference(ghost->Track()),
gap,
block_to_append_gap_to,
block_to_append_gap_to->next());
@@ -67,7 +67,7 @@ void TimelineView::RippleTool::MouseReleaseInternal(TimelineViewMouseEvent *even
}
} else {
// Assumed the Block was a Gap and it was reduced to zero length, remove it here
new TrackRippleRemoveBlockCommand(parent()->timeline_node_->Tracks().at(ghost->Track()), b, command);
new TrackRippleRemoveBlockCommand(parent()->GetTrackFromReference(ghost->Track()), b, command);
}
}
}
@@ -75,7 +75,7 @@ void TimelineView::RippleTool::MouseReleaseInternal(TimelineViewMouseEvent *even
olive::undo_stack.pushIfHasChildren(command);
}
rational TimelineView::RippleTool::FrameValidateInternal(rational time_movement, const QVector<TimelineViewGhostItem *> &ghosts)
rational TimelineWidget::RippleTool::FrameValidateInternal(rational time_movement, const QVector<TimelineViewGhostItem *> &ghosts)
{
// Only validate trimming, and we don't care about "overwriting" since the ripple tool is nondestructive
time_movement = ValidateInTrimming(time_movement, ghosts, false);
@@ -84,7 +84,7 @@ rational TimelineView::RippleTool::FrameValidateInternal(rational time_movement,
return time_movement;
}
void TimelineView::RippleTool::InitiateGhosts(TimelineViewBlockItem *clicked_item,
void TimelineWidget::RippleTool::InitiateGhosts(TimelineViewBlockItem *clicked_item,
olive::timeline::MovementMode trim_mode,
bool allow_gap_trimming)
{
@@ -117,7 +117,7 @@ void TimelineView::RippleTool::InitiateGhosts(TimelineViewBlockItem *clicked_ite
bool ghost_on_this_track_exists = false;
foreach (TimelineViewGhostItem* ghost, parent()->ghost_items_) {
if (ghost->Track() == track->Index()) {
if (parent()->GetTrackFromReference(ghost->Track()) == track) {
ghost_on_this_track_exists = true;
break;
}
+13 -7
View File
@@ -18,17 +18,17 @@
***/
#include "widget/timelineview/timelineview.h"
#include "widget/timelinewidget/timelinewidget.h"
#include "node/block/gap/gap.h"
TimelineView::RollingTool::RollingTool(TimelineView* parent) :
TimelineWidget::RollingTool::RollingTool(TimelineWidget* parent) :
PointerTool(parent)
{
SetMovementAllowed(false);
}
void TimelineView::RollingTool::MouseReleaseInternal(TimelineViewMouseEvent *event)
void TimelineWidget::RollingTool::MouseReleaseInternal(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
@@ -44,13 +44,19 @@ void TimelineView::RollingTool::MouseReleaseInternal(TimelineViewMouseEvent *eve
GapBlock* gap = new GapBlock();
gap->set_length(ghost->Length());
new TrackReplaceBlockCommand(parent()->timeline_node_->TrackAt(ghost->Track()), b, gap, command);
new TrackReplaceBlockCommand(parent()->GetTrackFromReference(ghost->Track()), b, gap, command);
}
new BlockResizeWithMediaInCommand(b, ghost->AdjustedLength(), command);
if (b->previous() == nullptr) {
new TrackPlaceBlockCommand(parent()->timeline_node_, ghost->Track(), b, ghost->GetAdjustedIn(), command);
const TrackReference& track_ref = ghost->Track();
new TrackPlaceBlockCommand(parent()->timeline_node_->track_list(track_ref.type()),
track_ref.index(),
b,
ghost->GetAdjustedIn(),
command);
}
} else if (ghost->mode() == olive::timeline::kTrimOut) {
new BlockResizeCommand(b, ghost->AdjustedLength(), command);
@@ -60,7 +66,7 @@ void TimelineView::RollingTool::MouseReleaseInternal(TimelineViewMouseEvent *eve
olive::undo_stack.pushIfHasChildren(command);
}
rational TimelineView::RollingTool::FrameValidateInternal(rational time_movement, const QVector<TimelineViewGhostItem *> &ghosts)
rational TimelineWidget::RollingTool::FrameValidateInternal(rational time_movement, const QVector<TimelineViewGhostItem *> &ghosts)
{
// Only validate trimming, and we don't care about "overwriting" since the rolling tool is designed to trim at collisions
time_movement = ValidateInTrimming(time_movement, ghosts, false);
@@ -69,7 +75,7 @@ rational TimelineView::RollingTool::FrameValidateInternal(rational time_movement
return time_movement;
}
void TimelineView::RollingTool::InitiateGhosts(TimelineViewBlockItem *clicked_item,
void TimelineWidget::RollingTool::InitiateGhosts(TimelineViewBlockItem *clicked_item,
olive::timeline::MovementMode trim_mode,
bool allow_gap_trimming)
{
+6 -6
View File
@@ -18,18 +18,18 @@
***/
#include "widget/timelineview/timelineview.h"
#include "widget/timelinewidget/timelinewidget.h"
#include "node/block/gap/gap.h"
TimelineView::SlideTool::SlideTool(TimelineView* parent) :
TimelineWidget::SlideTool::SlideTool(TimelineWidget* parent) :
PointerTool(parent)
{
SetTrimmingAllowed(false);
SetTrackMovementAllowed(false);
}
void TimelineView::SlideTool::MouseReleaseInternal(TimelineViewMouseEvent *event)
void TimelineWidget::SlideTool::MouseReleaseInternal(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
@@ -46,14 +46,14 @@ void TimelineView::SlideTool::MouseReleaseInternal(TimelineViewMouseEvent *event
} else if (ghost->mode() == olive::timeline::kMove && b->previous() == nullptr) {
GapBlock* gap = new GapBlock();
gap->set_length(ghost->InAdjustment());
new TrackPrependBlockCommand(parent()->timeline_node_->TrackAt(ghost->Track()), gap, command);
new TrackPrependBlockCommand(parent()->GetTrackFromReference(ghost->Track()), gap, command);
}
}
olive::undo_stack.pushIfHasChildren(command);
}
rational TimelineView::SlideTool::FrameValidateInternal(rational time_movement, const QVector<TimelineViewGhostItem *> &ghosts)
rational TimelineWidget::SlideTool::FrameValidateInternal(rational time_movement, const QVector<TimelineViewGhostItem *> &ghosts)
{
// Only validate trimming, and we don't care about "overwriting" since the rolling tool is designed to trim at collisions
time_movement = ValidateInTrimming(time_movement, ghosts, false);
@@ -62,7 +62,7 @@ rational TimelineView::SlideTool::FrameValidateInternal(rational time_movement,
return time_movement;
}
void TimelineView::SlideTool::InitiateGhosts(TimelineViewBlockItem *clicked_item,
void TimelineWidget::SlideTool::InitiateGhosts(TimelineViewBlockItem *clicked_item,
olive::timeline::MovementMode trim_mode,
bool allow_gap_trimming)
{
+6 -6
View File
@@ -18,21 +18,21 @@
***/
#include "widget/timelineview/timelineview.h"
#include "widget/timelinewidget/timelinewidget.h"
#include <QToolTip>
#include "common/timecodefunctions.h"
#include "config/config.h"
TimelineView::SlipTool::SlipTool(TimelineView *parent) :
TimelineWidget::SlipTool::SlipTool(TimelineWidget *parent) :
PointerTool(parent)
{
SetTrimmingAllowed(false);
SetTrackMovementAllowed(false);
}
void TimelineView::SlipTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
void TimelineWidget::SlipTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
{
// Determine frame movement
rational time_movement = drag_start_.GetFrame() - mouse_pos.GetFrame();
@@ -51,9 +51,9 @@ void TimelineView::SlipTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
// Show tooltip
// Generate tooltip (showing earliest in point of imported clip)
int64_t earliest_timestamp = olive::time_to_timestamp(time_movement, parent()->timebase_);
int64_t earliest_timestamp = olive::time_to_timestamp(time_movement, parent()->timebase());
QString tooltip_text = olive::timestamp_to_timecode(earliest_timestamp,
parent()->timebase_,
parent()->timebase(),
olive::CurrentTimecodeDisplay(),
true);
QToolTip::showText(QCursor::pos(),
@@ -61,7 +61,7 @@ void TimelineView::SlipTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
parent());
}
void TimelineView::SlipTool::MouseReleaseInternal(TimelineViewMouseEvent *event)
void TimelineWidget::SlipTool::MouseReleaseInternal(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
+29 -27
View File
@@ -18,30 +18,30 @@
***/
#include "widget/timelineview/timelineview.h"
#include "widget/timelinewidget/timelinewidget.h"
#include <float.h>
#include "common/range.h"
TimelineView::Tool::Tool(TimelineView *parent) :
TimelineWidget::Tool::Tool(TimelineWidget *parent) :
dragging_(false),
parent_(parent),
drag_mode_(NoDrag),
drag_mode_(QGraphicsView::NoDrag),
enable_default_behavior_(false)
{
}
TimelineView::Tool::~Tool()
TimelineWidget::Tool::~Tool()
{
}
TimelineView *TimelineView::Tool::parent()
TimelineWidget *TimelineWidget::Tool::parent()
{
return parent_;
}
olive::timeline::MovementMode TimelineView::Tool::FlipTrimMode(const olive::timeline::MovementMode &trim_mode)
olive::timeline::MovementMode TimelineWidget::Tool::FlipTrimMode(const olive::timeline::MovementMode &trim_mode)
{
if (trim_mode == olive::timeline::kTrimIn) {
return olive::timeline::kTrimOut;
@@ -54,27 +54,27 @@ olive::timeline::MovementMode TimelineView::Tool::FlipTrimMode(const olive::time
return trim_mode;
}
const QGraphicsView::DragMode &TimelineView::Tool::drag_mode()
const QGraphicsView::DragMode &TimelineWidget::Tool::drag_mode()
{
return drag_mode_;
}
bool TimelineView::Tool::enable_default_behavior()
bool TimelineWidget::Tool::enable_default_behavior()
{
return enable_default_behavior_;
}
void TimelineView::Tool::set_drag_mode(const QGraphicsView::DragMode &mode)
void TimelineWidget::Tool::set_drag_mode(const QGraphicsView::DragMode &mode)
{
drag_mode_ = mode;
}
void TimelineView::Tool::set_enable_default_behavior(bool enable)
void TimelineWidget::Tool::set_enable_default_behavior(bool enable)
{
enable_default_behavior_ = enable;
}
TimelineViewBlockItem *TimelineView::Tool::GetItemAtScenePos(const TimelineCoordinate& coord)
TimelineViewBlockItem *TimelineWidget::Tool::GetItemAtScenePos(const TimelineCoordinate& coord)
{
QMapIterator<Block*, TimelineViewBlockItem*> iterator(parent()->block_items_);
@@ -116,7 +116,7 @@ void AttemptSnap(const QList<double>& proposed_pts,
}
}
rational TimelineView::Tool::ValidateFrameMovement(rational movement, const QVector<TimelineViewGhostItem *> ghosts)
rational TimelineWidget::Tool::ValidateFrameMovement(rational movement, const QVector<TimelineViewGhostItem *> ghosts)
{
foreach (TimelineViewGhostItem* ghost, ghosts) {
if (ghost->mode() != olive::timeline::kMove) {
@@ -132,26 +132,24 @@ rational TimelineView::Tool::ValidateFrameMovement(rational movement, const QVec
return movement;
}
int TimelineView::Tool::ValidateTrackMovement(int movement, const QVector<TimelineViewGhostItem *> ghosts)
int TimelineWidget::Tool::ValidateTrackMovement(int movement, const QVector<TimelineViewGhostItem *> ghosts)
{
foreach (TimelineViewGhostItem* ghost, ghosts) {
// Prevents any ghosts from going to a non-existent negative track
if (ghost->Track() + movement < 0) {
if (ghost->Track().index() + movement < 0) {
if (ghost->mode() != olive::timeline::kMove) {
continue;
}
movement = -ghost->Track();
movement = -ghost->Track().index();
}
}
return movement;
}
bool TimelineView::Tool::SnapPoint(QList<rational> start_times, rational* movement, int snap_points)
bool TimelineWidget::Tool::SnapPoint(QList<rational> start_times, rational* movement, int snap_points)
{
QList<QGraphicsItem*> items = parent()->scene_.items();
double diff = DBL_MAX;
QList<double> proposed_pts;
@@ -163,8 +161,8 @@ bool TimelineView::Tool::SnapPoint(QList<rational> start_times, rational* moveme
if (snap_points & kSnapToPlayhead) {
rational playhead_abs_time = rational(parent()->playhead_ * parent()->timebase_.numerator(),
parent()->timebase_.denominator());
rational playhead_abs_time = rational(parent()->playhead_ * parent()->timebase().numerator(),
parent()->timebase().denominator());
qreal playhead_pos = playhead_abs_time.toDouble() * parent()->scale_;
@@ -172,18 +170,22 @@ bool TimelineView::Tool::SnapPoint(QList<rational> start_times, rational* moveme
}
if (snap_points & kSnapToClips) {
foreach (QGraphicsItem* it, items) {
TimelineViewBlockItem* timeline_rect = dynamic_cast<TimelineViewBlockItem*>(it);
QMapIterator<Block*, TimelineViewBlockItem*> iterator(parent()->block_items_);
if (timeline_rect != nullptr) {
qreal rect_left = timeline_rect->x();
qreal rect_right = rect_left + timeline_rect->rect().width();
while (iterator.hasNext()) {
iterator.next();
TimelineViewBlockItem* item = iterator.value();
if (item != nullptr) {
qreal rect_left = item->x();
qreal rect_right = rect_left + item->rect().width();
// Attempt snapping to clip in point
AttemptSnap(proposed_pts, rect_left, start_times, timeline_rect->block()->in(), movement, &diff);
AttemptSnap(proposed_pts, rect_left, start_times, item->block()->in(), movement, &diff);
// Attempt snapping to clip out point
AttemptSnap(proposed_pts, rect_right, start_times, timeline_rect->block()->out(), movement, &diff);
AttemptSnap(proposed_pts, rect_right, start_times, item->block()->out(), movement, &diff);
}
}
}
+8 -17
View File
@@ -18,36 +18,29 @@
***/
#include "widget/timelineview/timelineview.h"
#include "widget/timelinewidget/timelinewidget.h"
TimelineView::ZoomTool::ZoomTool(TimelineView* parent) :
TimelineWidget::ZoomTool::ZoomTool(TimelineWidget *parent) :
Tool(parent)
{
}
void TimelineView::ZoomTool::MousePress(TimelineViewMouseEvent *event)
void TimelineWidget::ZoomTool::MousePress(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
}
void TimelineView::ZoomTool::MouseMove(TimelineViewMouseEvent *event)
void TimelineWidget::ZoomTool::MouseMove(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
}
void TimelineView::ZoomTool::MouseRelease(TimelineViewMouseEvent *event)
void TimelineWidget::ZoomTool::MouseRelease(TimelineViewMouseEvent *event)
{
double scale = parent()->scale_;
// Get center of viewport
QPoint viewport_center = parent()->viewport()->rect().center();
QPointF scene_center = parent()->mapToScene(viewport_center);
// Set X to time
scene_center.setX(parent()->TimeToScreenCoord(event->GetCoordinates().GetFrame()));
// Normalize zoom location for 1.0 scale
double scaled_x = scene_center.x() / scale;
double frame_x = parent()->TimeToScene(event->GetCoordinates().GetFrame());
if (event->GetModifiers() & Qt::AltModifier) {
// Zoom out if the user clicks while holding Alt
@@ -58,11 +51,9 @@ void TimelineView::ZoomTool::MouseRelease(TimelineViewMouseEvent *event)
}
parent()->SetScale(scale);
emit parent()->ScaleChanged(scale);
// Adjust zoom location for new scale
scaled_x *= scale;
scene_center.setX(scaled_x);
frame_x *= scale;
parent()->centerOn(scene_center);
parent()->CenterOn(frame_x);
}
+194 -18
View File
@@ -4,7 +4,9 @@
#include <QVBoxLayout>
#include <QtMath>
#include "core.h"
#include "common/timecodefunctions.h"
#include "tool/tool.h"
TimelineWidget::TimelineWidget(QWidget *parent) :
QWidget(parent),
@@ -32,8 +34,24 @@ TimelineWidget::TimelineWidget(QWidget *parent) :
// Audio view
views_.append(new TimelineView(Qt::AlignTop));
// Set both views as siblings
TimelineView::SetSiblings(views_);
// Create tools
tools_.resize(olive::tool::kCount);
tools_.fill(nullptr);
tools_.replace(olive::tool::kPointer, std::make_shared<PointerTool>(this));
// tools_.replace(olive::tool::kEdit, new PointerTool(this)); FIXME: Implement
tools_.replace(olive::tool::kRipple, std::make_shared<RippleTool>(this));
tools_.replace(olive::tool::kRolling, std::make_shared<RollingTool>(this));
tools_.replace(olive::tool::kRazor, std::make_shared<RazorTool>(this));
tools_.replace(olive::tool::kSlip, std::make_shared<SlipTool>(this));
tools_.replace(olive::tool::kSlide, std::make_shared<SlideTool>(this));
tools_.replace(olive::tool::kHand, std::make_shared<HandTool>(this));
tools_.replace(olive::tool::kZoom, std::make_shared<ZoomTool>(this));
//tools_.replace(olive::tool::kTransition, new (this)); FIXME: Implement
//tools_.replace(olive::tool::kRecord, new PointerTool(this)); FIXME: Implement
//tools_.replace(olive::tool::kAdd, new PointerTool(this)); FIXME: Implement
import_tool_ = std::make_shared<ImportTool>(this);
// Global scrollbar
horizontal_scroll_ = new QScrollBar(Qt::Horizontal);
@@ -75,14 +93,22 @@ void TimelineWidget::Clear()
{
SetTimebase(0);
foreach (TimelineView* view, views_) {
view->Clear();
QMapIterator<Block*, TimelineViewBlockItem*> iterator(block_items_);
while (iterator.hasNext()) {
iterator.next();
if (iterator.value() != nullptr) {
delete iterator.value();
}
}
block_items_.clear();
}
void TimelineWidget::SetTimebase(const rational &timebase)
{
timebase_ = timebase;
SetTimebaseInternal(timebase);
ruler_->SetTimebase(timebase);
@@ -113,20 +139,20 @@ void TimelineWidget::ConnectTimelineNode(TimelineOutput *node)
{
if (timeline_node_ != nullptr) {
disconnect(timeline_node_, SIGNAL(LengthChanged(const rational&)), this, SLOT(UpdateTimelineLength(const rational&)));
disconnect(timeline_node_, SIGNAL(BlockAdded(Block*, TrackReference)), this, SLOT(AddBlock(Block*, TrackReference)));
disconnect(timeline_node_, SIGNAL(BlockRemoved(Block*)), this, SLOT(RemoveBlock(Block*)));
}
timeline_node_ = node;
int track_type = 0;
foreach (TimelineView* view, views_) {
view->ConnectTimelineNode(node->track_list(static_cast<TrackType>(track_type)));
track_type++;
for (int track_type=0;track_type<views_.size();track_type++) {
views_.at(track_type)->ConnectTimelineNode(node->track_list(static_cast<TrackType>(track_type)));
}
if (timeline_node_ != nullptr) {
connect(timeline_node_, SIGNAL(LengthChanged(const rational&)), this, SLOT(UpdateTimelineLength(const rational&)));
connect(timeline_node_, SIGNAL(BlockAdded(Block*, TrackReference)), this, SLOT(AddBlock(Block*, TrackReference)));
connect(timeline_node_, SIGNAL(BlockRemoved(Block*)), this, SLOT(RemoveBlock(Block*)));
foreach (TimelineView* view, views_) {
view->SetEndTime(timeline_node_->timeline_length());
@@ -203,7 +229,7 @@ void TimelineWidget::GoToPrevCut()
int64_t this_track_closest_cut = 0;
foreach (Block* block, track->Blocks()) {
int64_t block_out_ts = olive::time_to_timestamp(block->out(), timebase_);
int64_t block_out_ts = olive::time_to_timestamp(block->out(), timebase());
if (block_out_ts < playhead_) {
this_track_closest_cut = block_out_ts;
@@ -227,14 +253,14 @@ void TimelineWidget::GoToNextCut()
int64_t closest_cut = INT64_MAX;
foreach (TrackOutput* track, timeline_node_->Tracks()) {
int64_t this_track_closest_cut = olive::time_to_timestamp(track->in(), timebase_);
int64_t this_track_closest_cut = olive::time_to_timestamp(track->in(), timebase());
if (this_track_closest_cut <= playhead_) {
this_track_closest_cut = INT64_MAX;
}
foreach (Block* block, track->Blocks()) {
int64_t block_in_ts = olive::time_to_timestamp(block->in(), timebase_);
int64_t block_in_ts = olive::time_to_timestamp(block->in(), timebase());
if (block_in_ts > playhead_) {
this_track_closest_cut = block_in_ts;
@@ -252,7 +278,7 @@ void TimelineWidget::GoToNextCut()
void TimelineWidget::RippleEditTo(olive::timeline::MovementMode mode, bool insert_gaps)
{
rational playhead_time = olive::timestamp_to_time(playhead_, timebase_);
rational playhead_time = olive::timestamp_to_time(playhead_, timebase());
rational closest_point_to_playhead;
if (mode == olive::timeline::kTrimIn) {
@@ -278,9 +304,9 @@ void TimelineWidget::RippleEditTo(olive::timeline::MovementMode mode, bool inser
if (closest_point_to_playhead == playhead_time) {
// Remove one frame only
if (mode == olive::timeline::kTrimIn) {
playhead_time += timebase_;
playhead_time += timebase();
} else {
playhead_time -= timebase_;
playhead_time -= timebase();
}
}
@@ -304,7 +330,7 @@ void TimelineWidget::RippleEditTo(olive::timeline::MovementMode mode, bool inser
olive::undo_stack.pushIfHasChildren(command);
if (mode == olive::timeline::kTrimIn && !insert_gaps) {
int64_t new_time = olive::time_to_timestamp(closest_point_to_playhead, timebase_);
int64_t new_time = olive::time_to_timestamp(closest_point_to_playhead, timebase());
SetTimeAndSignal(new_time);
}
@@ -316,17 +342,67 @@ void TimelineWidget::SetTimeAndSignal(const int64_t &t)
emit TimeChanged(t);
}
TrackOutput *TimelineWidget::GetTrackFromReference(const TrackReference &ref)
{
return timeline_node_->track_list(ref.type())->TrackAt(ref.index());
}
int TimelineWidget::GetTrackY(const TrackReference &ref)
{
return views_.at(ref.type())->GetTrackY(ref.index());
}
int TimelineWidget::GetTrackHeight(const TrackReference &ref)
{
return views_.at(ref.type())->GetTrackHeight(ref.index());
}
void TimelineWidget::CenterOn(qreal scene_pos)
{
horizontal_scroll_->setValue(qRound(scene_pos - horizontal_scroll_->width()/2));
}
void TimelineWidget::SetScale(double scale)
{
scale_ = scale;
ruler_->SetScale(scale_);
QMapIterator<Block*, TimelineViewBlockItem*> iterator(block_items_);
while (iterator.hasNext()) {
iterator.next();
if (iterator.value() != nullptr) {
iterator.value()->SetScale(scale_);
}
}
foreach (TimelineViewGhostItem* ghost, ghost_items_) {
ghost->SetScale(scale_);
}
foreach (TimelineView* view, views_) {
view->SetScale(scale_);
}
}
void TimelineWidget::ClearGhosts()
{
if (!ghost_items_.isEmpty()) {
foreach (TimelineViewGhostItem* ghost, ghost_items_) {
delete ghost;
}
ghost_items_.clear();
}
}
bool TimelineWidget::HasGhosts()
{
return !ghost_items_.isEmpty();
}
void TimelineWidget::UpdateInternalTime(const int64_t &timestamp)
{
playhead_ = timestamp;
@@ -338,3 +414,103 @@ void TimelineWidget::UpdateTimelineLength(const rational &length)
view->SetEndTime(length);
}
}
TimelineWidget::Tool *TimelineWidget::GetActiveTool()
{
return tools_.at(olive::core.tool()).get();
}
void TimelineWidget::ViewMousePressed(TimelineViewMouseEvent *event)
{
active_tool_ = GetActiveTool();
if (timeline_node_ != nullptr && active_tool_ != nullptr) {
active_tool_->MousePress(event);
}
}
void TimelineWidget::ViewMouseMoved(TimelineViewMouseEvent *event)
{
if (timeline_node_ != nullptr && active_tool_ != nullptr) {
active_tool_->MouseMove(event);
}
}
void TimelineWidget::ViewMouseReleased(TimelineViewMouseEvent *event)
{
if (timeline_node_ != nullptr && active_tool_ != nullptr) {
active_tool_->MouseRelease(event);
}
}
void TimelineWidget::ViewMouseDoubleClicked(TimelineViewMouseEvent *event)
{
if (timeline_node_ != nullptr && active_tool_ != nullptr) {
active_tool_->MouseDoubleClick(event);
}
}
void TimelineWidget::ViewDragEntered(TimelineViewMouseEvent *event)
{
if (timeline_node_ != nullptr) {
import_tool_->DragEnter(event);
}
}
void TimelineWidget::ViewDragMoved(TimelineViewMouseEvent *event)
{
if (timeline_node_ != nullptr) {
import_tool_->DragMove(event);
}
}
void TimelineWidget::ViewDragLeft(QDragLeaveEvent *event)
{
if (timeline_node_ != nullptr) {
import_tool_->DragLeave(event);
}
}
void TimelineWidget::ViewDragDropped(TimelineViewMouseEvent *event)
{
if (timeline_node_ != nullptr) {
import_tool_->DragDrop(event);
}
}
void TimelineWidget::AddBlock(Block *block, TrackReference track)
{
switch (block->type()) {
case Block::kClip:
case Block::kGap:
{
TimelineViewBlockItem* item = new TimelineViewBlockItem();
// Set up clip with view parameters (clip item will automatically size its rect accordingly)
item->SetBlock(block);
item->SetY(GetTrackY(track));
item->SetHeight(GetTrackHeight(track));
item->SetScale(scale_);
item->SetTrack(track);
// Add to list of clip items that can be iterated through
block_items_.insert(block, item);
// Add item to graphics scene
views_.at(track.type())->scene()->addItem(item);
connect(block, SIGNAL(Refreshed()), this, SLOT(BlockChanged()));
break;
}
case Block::kEnd:
// Do nothing
break;
}
}
void TimelineWidget::RemoveBlock(Block *block)
{
delete block_items_[block];
block_items_.remove(block);
}
+269 -5
View File
@@ -4,6 +4,7 @@
#include <QScrollBar>
#include <QWidget>
#include "widget/timelineview/timelinescaledobject.h"
#include "widget/timelineview/timelineview.h"
#include "widget/timeruler/timeruler.h"
@@ -12,7 +13,7 @@
*
* Encapsulates TimelineViews, TimeRulers, and scrollbars for a complete widget to manipulate Timelines
*/
class TimelineWidget : public QWidget
class TimelineWidget : public QWidget, public TimelineScaledObject
{
Q_OBJECT
public:
@@ -56,24 +57,274 @@ signals:
void TimeChanged(const int64_t& time);
private:
class Tool
{
public:
Tool(TimelineWidget* parent);
virtual ~Tool();
virtual void MousePress(TimelineViewMouseEvent *){}
virtual void MouseMove(TimelineViewMouseEvent *){}
virtual void MouseRelease(TimelineViewMouseEvent *){}
virtual void MouseDoubleClick(TimelineViewMouseEvent *){}
virtual void DragEnter(TimelineViewMouseEvent *){}
virtual void DragMove(TimelineViewMouseEvent *){}
virtual void DragLeave(QDragLeaveEvent *){}
virtual void DragDrop(TimelineViewMouseEvent *){}
TimelineWidget* parent();
static olive::timeline::MovementMode FlipTrimMode(const olive::timeline::MovementMode& trim_mode);
const QGraphicsView::DragMode& drag_mode();
bool enable_default_behavior();
protected:
void set_drag_mode(const QGraphicsView::DragMode& mode);
void set_enable_default_behavior(bool enable);
/**
* @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
*/
TimelineViewBlockItem* GetItemAtScenePos(const TimelineCoordinate &coord);
/**
* @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 ValidateFrameMovement(rational movement, const QVector<TimelineViewGhostItem*> ghosts);
/**
* @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);
enum SnapPoints {
kSnapToClips = 0x1,
kSnapToPlayhead = 0x2,
kSnapAll = 0xFF
};
/**
* @brief Snaps point `start_point` that is moving by `movement` to currently existing clips
*/
bool SnapPoint(QList<rational> start_times, rational *movement, int snap_points = kSnapAll);
QList<rational> snap_points_;
bool dragging_;
TimelineCoordinate drag_start_;
private:
TimelineWidget* parent_;
QGraphicsView::DragMode drag_mode_;
bool enable_default_behavior_;
};
class PointerTool : public Tool
{
public:
PointerTool(TimelineWidget* parent);
virtual void MousePress(TimelineViewMouseEvent *event) override;
virtual void MouseMove(TimelineViewMouseEvent *event) override;
virtual void MouseRelease(TimelineViewMouseEvent *event) override;
protected:
void SetMovementAllowed(bool allowed);
void SetTrackMovementAllowed(bool allowed);
void SetTrimmingAllowed(bool allowed);
virtual void MouseReleaseInternal(TimelineViewMouseEvent *event);
virtual rational FrameValidateInternal(rational time_movement, const QVector<TimelineViewGhostItem *> &ghosts);
virtual void InitiateGhosts(TimelineViewBlockItem* clicked_item,
olive::timeline::MovementMode trim_mode,
bool allow_gap_trimming);
TimelineViewGhostItem* AddGhostFromBlock(Block *block, const TrackReference& track, olive::timeline::MovementMode mode);
TimelineViewGhostItem* AddGhostFromNull(const rational& in, const rational& out, const TrackReference& track, olive::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, const QVector<TimelineViewGhostItem*> ghosts, bool prevent_overwriting);
/**
* @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, const QVector<TimelineViewGhostItem*> ghosts, bool prevent_overwriting);
virtual void ProcessDrag(const TimelineCoordinate &mouse_pos);
private:
void InitiateDrag(const TimelineCoordinate &mouse_pos);
void AddGhostInternal(TimelineViewGhostItem* ghost, olive::timeline::MovementMode mode);
QList<TimelineViewBlockItem*> GetSelectedClips();
bool IsClipTrimmable(TimelineViewBlockItem* clip,
const QList<TimelineViewBlockItem*>& items,
const olive::timeline::MovementMode& mode);
TrackReference track_start_;
bool movement_allowed_;
bool trimming_allowed_;
bool track_movement_allowed_;
};
class ImportTool : public Tool
{
public:
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;
private:
int import_pre_buffer_;
};
class RazorTool : public Tool
{
public:
RazorTool(TimelineWidget* parent);
virtual void MousePress(TimelineViewMouseEvent *event);
virtual void MouseMove(TimelineViewMouseEvent *event);
virtual void MouseRelease(TimelineViewMouseEvent *event);
private:
QVector<TrackReference> split_tracks_;
};
class RippleTool : public PointerTool
{
public:
RippleTool(TimelineWidget* parent);
protected:
virtual void MouseReleaseInternal(TimelineViewMouseEvent *event) override;
virtual rational FrameValidateInternal(rational time_movement, const QVector<TimelineViewGhostItem*>& ghosts) override;
virtual void InitiateGhosts(TimelineViewBlockItem* clicked_item,
olive::timeline::MovementMode trim_mode,
bool allow_gap_trimming) override;
};
class RollingTool : public PointerTool
{
public:
RollingTool(TimelineWidget* parent);
protected:
virtual void MouseReleaseInternal(TimelineViewMouseEvent *event) override;
virtual rational FrameValidateInternal(rational time_movement, const QVector<TimelineViewGhostItem*>& ghosts) override;
virtual void InitiateGhosts(TimelineViewBlockItem* clicked_item,
olive::timeline::MovementMode trim_mode,
bool allow_gap_trimming) override;
};
class SlideTool : public PointerTool
{
public:
SlideTool(TimelineWidget* parent);
protected:
virtual void MouseReleaseInternal(TimelineViewMouseEvent *event) override;
virtual rational FrameValidateInternal(rational time_movement, const QVector<TimelineViewGhostItem*>& ghosts) override;
virtual void InitiateGhosts(TimelineViewBlockItem* clicked_item,
olive::timeline::MovementMode trim_mode,
bool allow_gap_trimming) override;
};
class SlipTool : public PointerTool
{
public:
SlipTool(TimelineWidget* parent);
protected:
virtual void ProcessDrag(const TimelineCoordinate &mouse_pos) override;
virtual void MouseReleaseInternal(TimelineViewMouseEvent *event) override;
};
class HandTool : public Tool
{
public:
HandTool(TimelineWidget* parent);
private:
QPoint screen_drag_start_;
QPoint scrollbar_start_;
};
class ZoomTool : public Tool
{
public:
ZoomTool(TimelineWidget* parent);
virtual void MousePress(TimelineViewMouseEvent *event);
virtual void MouseMove(TimelineViewMouseEvent *event);
virtual void MouseRelease(TimelineViewMouseEvent *event);
};
Tool* GetActiveTool();
QVector< std::shared_ptr<Tool> > tools_;
std::shared_ptr<ImportTool> import_tool_;
Tool* active_tool_;
void ClearGhosts();
bool HasGhosts();
QVector<TimelineViewGhostItem*> ghost_items_;
QMap<Block*, TimelineViewBlockItem*> block_items_;
void RippleEditTo(olive::timeline::MovementMode mode, bool insert_gaps);
void SetTimeAndSignal(const int64_t& t);
TrackOutput* GetTrackFromReference(const TrackReference& ref);
QList<TimelineView*> views_;
TimeRuler* ruler_;
double scale_;
TimelineOutput* timeline_node_;
rational timebase_;
int64_t playhead_;
QScrollBar* horizontal_scroll_;
int GetTrackY(const TrackReference& ref);
int GetTrackHeight(const TrackReference& ref);
void CenterOn(qreal scene_pos);
private slots:
void SetScale(double scale);
@@ -81,6 +332,19 @@ private slots:
void UpdateTimelineLength(const rational& length);
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 AddBlock(Block* block, TrackReference track);
void RemoveBlock(Block* block);
};
#endif // TIMELINEWIDGET_H