updated timeline tools to take custom mouse events

This commit is contained in:
itsmattkc
2019-10-11 09:35:11 +11:00
parent df9255ce0b
commit 405f4e5e00
29 changed files with 720 additions and 304 deletions
+1 -26
View File
@@ -25,30 +25,5 @@
TimelineView::HandTool::HandTool(TimelineView* parent) :
Tool(parent)
{
}
void TimelineView::HandTool::MousePress(QMouseEvent *event)
{
screen_drag_start_ = event->pos();
scrollbar_start_.setX(parent()->horizontalScrollBar()->value());
scrollbar_start_.setY(parent()->verticalScrollBar()->value());
dragging_ = true;
}
void TimelineView::HandTool::MouseMove(QMouseEvent *event)
{
if (dragging_) {
QPoint drag_diff = event->pos() - screen_drag_start_;
parent()->horizontalScrollBar()->setValue(scrollbar_start_.x() - drag_diff.x());
parent()->verticalScrollBar()->setValue(scrollbar_start_.y() - drag_diff.y());
}
}
void TimelineView::HandTool::MouseRelease(QMouseEvent *event)
{
Q_UNUSED(event)
dragging_ = false;
set_drag_mode(ScrollHandDrag);
}
+40 -38
View File
@@ -38,16 +38,16 @@ TimelineView::ImportTool::ImportTool(TimelineView *parent) :
import_pre_buffer_ = QFontMetricsWidth(&fm, "HHHHHHHH");
}
void TimelineView::ImportTool::DragEnter(QDragEnterEvent *event)
void TimelineView::ImportTool::DragEnter(TimelineViewMouseEvent *event)
{
QStringList mime_formats = event->mimeData()->formats();
QStringList mime_formats = event->GetMimeData()->formats();
// Listen for MIME data from a ProjectViewModel
if (mime_formats.contains("application/x-oliveprojectitemdata")) {
// FIXME: Implement audio insertion
// Data is drag/drop data from a ProjectViewModel
QByteArray model_data = event->mimeData()->data("application/x-oliveprojectitemdata");
QByteArray model_data = event->GetMimeData()->data("application/x-oliveprojectitemdata");
// Use QDataStream to deserialize the data
QDataStream stream(&model_data, QIODevice::ReadOnly);
@@ -57,10 +57,11 @@ void TimelineView::ImportTool::DragEnter(QDragEnterEvent *event)
int r;
// Set drag start position
drag_start_ = GetScenePos(event->pos());
drag_start_ = event->GetCoordinates();
// Set ghosts to start where the cursor entered
rational ghost_start = parent()->SceneToTime(drag_start_.x() - import_pre_buffer_);
rational ghost_start = drag_start_.GetFrame() - parent()->SceneToTime(import_pre_buffer_);
snap_points_.clear();
@@ -75,32 +76,36 @@ void TimelineView::ImportTool::DragEnter(QDragEnterEvent *event)
// If the Item is Footage, we can create a Ghost from it
Footage* footage = static_cast<Footage*>(item);
StreamPtr stream = footage->stream(0);
TimelineViewGhostItem* ghost = new TimelineViewGhostItem();
rational footage_duration;
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());
// 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();
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);
}
}
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
ghost_start += footage_duration;
}
@@ -113,25 +118,22 @@ void TimelineView::ImportTool::DragEnter(QDragEnterEvent *event)
}
}
void TimelineView::ImportTool::DragMove(QDragMoveEvent *event)
void TimelineView::ImportTool::DragMove(TimelineViewMouseEvent *event)
{
if (parent()->HasGhosts()) {
QPointF pos = GetScenePos(event->pos());
QPointF movement = pos - drag_start_;
rational time_movement = event->GetCoordinates().GetFrame() - drag_start_.GetFrame();
rational time_movement = parent()->SceneToTime(movement.x());
int ghost_track = parent()->SceneToTrack(pos.y());
int ghost_track = event->GetCoordinates().GetTrack();
int ghost_y = parent()->GetTrackY(ghost_track);
int ghost_height = parent()->GetTrackHeight(ghost_track);
time_movement = ValidateFrameMovement(time_movement, parent()->ghost_items_);
// If snapping is enabled, check for snap points
if (olive::core.snapping()) {
SnapPoint(snap_points_, &time_movement);
}
time_movement = ValidateFrameMovement(time_movement, parent()->ghost_items_);
rational earliest_ghost = RATIONAL_MAX;
// Move ghosts to the mouse cursor
@@ -162,7 +164,7 @@ void TimelineView::ImportTool::DragMove(QDragMoveEvent *event)
}
}
void TimelineView::ImportTool::DragLeave(QDragLeaveEvent *event)
void TimelineView::ImportTool::DragLeave(QDragLeaveEvent* event)
{
if (parent()->HasGhosts()) {
parent()->ClearGhosts();
@@ -173,7 +175,7 @@ void TimelineView::ImportTool::DragLeave(QDragLeaveEvent *event)
}
}
void TimelineView::ImportTool::DragDrop(QDropEvent *event)
void TimelineView::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
@@ -204,7 +206,7 @@ void TimelineView::ImportTool::DragDrop(QDropEvent *event)
NodeParam::ConnectEdge(transform->matrix_output(), media->matrix_input());
if (event->keyboardModifiers() & Qt::ControlModifier) {
if (event->GetModifiers() & Qt::ControlModifier) {
//emit parent()->RequestInsertBlockAtTime(clip, ghost->GetAdjustedIn());
} else {
new TrackPlaceBlockCommand(parent()->timeline_node_, ghost->Track(), clip, ghost->GetAdjustedIn(), command);
+22 -48
View File
@@ -24,6 +24,7 @@
#include <QToolTip>
#include "common/clamp.h"
#include "common/flipmodifiers.h"
#include "common/range.h"
#include "common/timecodefunctions.h"
#include "config/config.h"
@@ -36,44 +37,25 @@ TimelineView::PointerTool::PointerTool(TimelineView *parent) :
trimming_allowed_(true),
track_movement_allowed_(true)
{
set_drag_mode(RubberBandDrag);
set_enable_default_behavior(true);
}
void FlipControlAndShiftModifiers(QMouseEvent* e) {
if (e->modifiers() & Qt::ControlModifier & Qt::ShiftModifier) {
return;
}
if (e->modifiers() & Qt::ShiftModifier) {
e->setModifiers((e->modifiers() | Qt::ControlModifier) & ~Qt::ShiftModifier);
} else if (e->modifiers() & Qt::ControlModifier) {
e->setModifiers((e->modifiers() | Qt::ShiftModifier) & ~Qt::ControlModifier);
}
}
void TimelineView::PointerTool::MousePress(QMouseEvent *event)
void TimelineView::PointerTool::MousePress(TimelineViewMouseEvent *event)
{
// We use Shift for multiple selection while Qt uses Ctrl, we flip those modifiers here to compensate
FlipControlAndShiftModifiers(event);
// Default QGraphicsView behavior (item selection)
parent()->QGraphicsView::mousePressEvent(event);
// We don't initiate dragging here since clicking could easily be just for selecting
Q_UNUSED(event)
}
void TimelineView::PointerTool::MouseMove(QMouseEvent *event)
void TimelineView::PointerTool::MouseMove(TimelineViewMouseEvent *event)
{
// We use Shift for multiple selection while Qt uses Ctrl, we flip those modifiers here to compensate
FlipControlAndShiftModifiers(event);
// Default QGraphicsView behavior (item selection)
parent()->QGraphicsView::mouseMoveEvent(event);
qDebug() << dragging_ << parent()->ghost_items_.isEmpty();
// Now that the cursor has moved, we will assume the intention is to drag
if (!dragging_) {
// If we haven't started dragging yet, we'll initiate a drag here
InitiateDrag(event->pos());
InitiateDrag(event->GetCoordinates());
// Set dragging to true here so no matter what, the drag isn't re-initiated until it's completed
dragging_ = true;
@@ -81,19 +63,13 @@ void TimelineView::PointerTool::MouseMove(QMouseEvent *event)
} else if (!parent()->ghost_items_.isEmpty()) {
// We're already dragging AND we have ghosts to work with
ProcessDrag(event->pos());
ProcessDrag(event->GetCoordinates());
}
}
void TimelineView::PointerTool::MouseRelease(QMouseEvent *event)
void TimelineView::PointerTool::MouseRelease(TimelineViewMouseEvent *event)
{
// We use Shift for multiple selection while Qt uses Ctrl, we flip those modifiers here to compensate
FlipControlAndShiftModifiers(event);
// Default QGraphicsView behavior (item selection)
parent()->QGraphicsView::mouseReleaseEvent(event);
if (!parent()->ghost_items_.isEmpty()) {
MouseReleaseInternal(event);
}
@@ -121,7 +97,7 @@ void TimelineView::PointerTool::SetTrimmingAllowed(bool allowed)
trimming_allowed_ = allowed;
}
void TimelineView::PointerTool::MouseReleaseInternal(QMouseEvent *event)
void TimelineView::PointerTool::MouseReleaseInternal(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
@@ -177,13 +153,13 @@ rational TimelineView::PointerTool::FrameValidateInternal(rational time_movement
return time_movement;
}
void TimelineView::PointerTool::InitiateDrag(const QPoint& mouse_pos)
void TimelineView::PointerTool::InitiateDrag(const TimelineCoordinate &mouse_pos)
{
// Record where the drag started in timeline coordinates
drag_start_ = GetScenePos(mouse_pos);
drag_start_ = mouse_pos;
// Get the item that was clicked
TimelineViewBlockItem* clicked_item = dynamic_cast<TimelineViewBlockItem*>(GetItemAtScenePos(drag_start_));
TimelineViewBlockItem* clicked_item = GetItemAtScenePos(drag_start_);
// We only initiate a pointer drag if the user actually dragged an item, otherwise if they dragged on empty space
// QGraphicsView default behavior would initiate a rubberband drag
@@ -193,7 +169,7 @@ void TimelineView::PointerTool::InitiateDrag(const QPoint& mouse_pos)
snap_points_.clear();
// Record where the drag started in timeline coordinates
track_start_ = parent()->SceneToTrack(drag_start_.y());
track_start_ = mouse_pos.GetTrack();
// Determine whether we're trimming or moving based on the position of the cursor
olive::timeline::MovementMode trim_mode = olive::timeline::kNone;
@@ -201,9 +177,11 @@ void TimelineView::PointerTool::InitiateDrag(const QPoint& mouse_pos)
// FIXME: Hardcoded number
const int kTrimHandle = 20;
if (trimming_allowed_ && drag_start_.x() < clicked_item->x() + kTrimHandle) {
qreal mouse_x = parent()->TimeToScreenCoord(mouse_pos.GetFrame());
if (trimming_allowed_ && mouse_x < clicked_item->x() + kTrimHandle) {
trim_mode = olive::timeline::kTrimIn;
} else if (trimming_allowed_ && drag_start_.x() > clicked_item->x() + clicked_item->rect().right() - kTrimHandle) {
} else if (trimming_allowed_ && mouse_x > clicked_item->x() + clicked_item->rect().right() - kTrimHandle) {
trim_mode = olive::timeline::kTrimOut;
} else if (movement_allowed_) {
// Some derived classes don't allow movement
@@ -222,14 +200,10 @@ void TimelineView::PointerTool::InitiateDrag(const QPoint& mouse_pos)
}
}
void TimelineView::PointerTool::ProcessDrag(const QPoint &mouse_pos)
void TimelineView::PointerTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
{
// Retrieve cursor position difference
QPointF scene_pos = GetScenePos(mouse_pos);
QPointF movement = scene_pos - drag_start_;
// Determine track movement
int cursor_track = parent()->SceneToTrack(scene_pos.y());
int cursor_track = mouse_pos.GetTrack();
int track_movement = 0;
if (track_movement_allowed_) {
@@ -237,7 +211,7 @@ void TimelineView::PointerTool::ProcessDrag(const QPoint &mouse_pos)
}
// Determine frame movement
rational time_movement = parent()->SceneToTime(movement.x());
rational time_movement = mouse_pos.GetFrame() - drag_start_.GetFrame();
// Perform snapping if enabled (adjusts time_movement if it's close to any potential snap points)
if (olive::core.snapping()) {
+6 -8
View File
@@ -25,36 +25,34 @@ TimelineView::RazorTool::RazorTool(TimelineView* parent) :
{
}
void TimelineView::RazorTool::MousePress(QMouseEvent *event)
void TimelineView::RazorTool::MousePress(TimelineViewMouseEvent *event)
{
split_tracks_.clear();
MouseMove(event);
}
void TimelineView::RazorTool::MouseMove(QMouseEvent *event)
void TimelineView::RazorTool::MouseMove(TimelineViewMouseEvent *event)
{
if (!dragging_) {
drag_start_ = GetScenePos(event->pos());
drag_start_ = event->GetCoordinates();
dragging_ = true;
}
QPointF current_scene_pos = GetScenePos(event->pos());
// Split at the current cursor track
int split_track = parent()->SceneToTrack(current_scene_pos.y());
int split_track = event->GetCoordinates().GetTrack();
if (!split_tracks_.contains(split_track)) {
split_tracks_.append(split_track);
}
}
void TimelineView::RazorTool::MouseRelease(QMouseEvent *event)
void TimelineView::RazorTool::MouseRelease(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
// Always split at the same time
rational split_time = parent()->SceneToTime(drag_start_.x());
rational split_time = drag_start_.GetFrame();
QUndoCommand* command = new QUndoCommand();
+1 -1
View File
@@ -28,7 +28,7 @@ TimelineView::RippleTool::RippleTool(TimelineView* parent) :
SetMovementAllowed(false);
}
void TimelineView::RippleTool::MouseReleaseInternal(QMouseEvent *event)
void TimelineView::RippleTool::MouseReleaseInternal(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
+1 -1
View File
@@ -28,7 +28,7 @@ TimelineView::RollingTool::RollingTool(TimelineView* parent) :
SetMovementAllowed(false);
}
void TimelineView::RollingTool::MouseReleaseInternal(QMouseEvent *event)
void TimelineView::RollingTool::MouseReleaseInternal(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
+1 -1
View File
@@ -29,7 +29,7 @@ TimelineView::SlideTool::SlideTool(TimelineView* parent) :
SetTrackMovementAllowed(false);
}
void TimelineView::SlideTool::MouseReleaseInternal(QMouseEvent *event)
void TimelineView::SlideTool::MouseReleaseInternal(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
+3 -7
View File
@@ -32,14 +32,10 @@ TimelineView::SlipTool::SlipTool(TimelineView *parent) :
SetTrackMovementAllowed(false);
}
void TimelineView::SlipTool::ProcessDrag(const QPoint &mouse_pos)
void TimelineView::SlipTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
{
// Retrieve cursor position difference
QPointF scene_pos = GetScenePos(mouse_pos);
QPointF movement = scene_pos - drag_start_;
// Determine frame movement
rational time_movement = -parent()->SceneToTime(movement.x());
rational time_movement = drag_start_.GetFrame() - mouse_pos.GetFrame();
// Validate slip (enforce all ghosts moving in legal ways)
foreach (TimelineViewGhostItem* ghost, parent()->ghost_items_) {
@@ -65,7 +61,7 @@ void TimelineView::SlipTool::ProcessDrag(const QPoint &mouse_pos)
parent());
}
void TimelineView::SlipTool::MouseReleaseInternal(QMouseEvent *event)
void TimelineView::SlipTool::MouseReleaseInternal(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
+40 -20
View File
@@ -26,25 +26,15 @@
TimelineView::Tool::Tool(TimelineView *parent) :
dragging_(false),
parent_(parent)
parent_(parent),
drag_mode_(NoDrag),
enable_default_behavior_(false)
{
}
TimelineView::Tool::~Tool(){}
void TimelineView::Tool::MousePress(QMouseEvent *){}
void TimelineView::Tool::MouseMove(QMouseEvent *){}
void TimelineView::Tool::MouseRelease(QMouseEvent *){}
void TimelineView::Tool::DragEnter(QDragEnterEvent *){}
void TimelineView::Tool::DragMove(QDragMoveEvent *){}
void TimelineView::Tool::DragLeave(QDragLeaveEvent *){}
void TimelineView::Tool::DragDrop(QDropEvent *){}
TimelineView::Tool::~Tool()
{
}
TimelineView *TimelineView::Tool::parent()
{
@@ -64,14 +54,44 @@ olive::timeline::MovementMode TimelineView::Tool::FlipTrimMode(const olive::time
return trim_mode;
}
QPointF TimelineView::Tool::GetScenePos(const QPoint &screen_pos)
const QGraphicsView::DragMode &TimelineView::Tool::drag_mode()
{
return parent()->mapToScene(screen_pos);
return drag_mode_;
}
QGraphicsItem *TimelineView::Tool::GetItemAtScenePos(const QPointF &scene_pos)
bool TimelineView::Tool::enable_default_behavior()
{
return parent()->scene_.itemAt(scene_pos, parent()->transform());
return enable_default_behavior_;
}
void TimelineView::Tool::set_drag_mode(const QGraphicsView::DragMode &mode)
{
drag_mode_ = mode;
}
void TimelineView::Tool::set_enable_default_behavior(bool enable)
{
enable_default_behavior_ = enable;
}
TimelineViewBlockItem *TimelineView::Tool::GetItemAtScenePos(const TimelineCoordinate& coord)
{
QMapIterator<Block*, TimelineViewBlockItem*> iterator(parent()->block_items_);
while (iterator.hasNext()) {
iterator.next();
Block* b = iterator.key();
TimelineViewBlockItem* item = iterator.value();
if (b->in() <= coord.GetFrame()
&& b->out() > coord.GetFrame()
&& item->Track() == coord.GetTrack()) {
return item;
}
}
return nullptr;
}
void AttemptSnap(const QList<double>& proposed_pts,
+13 -8
View File
@@ -25,26 +25,31 @@ TimelineView::ZoomTool::ZoomTool(TimelineView* parent) :
{
}
void TimelineView::ZoomTool::MousePress(QMouseEvent *event)
void TimelineView::ZoomTool::MousePress(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
}
void TimelineView::ZoomTool::MouseMove(QMouseEvent *event)
void TimelineView::ZoomTool::MouseMove(TimelineViewMouseEvent *event)
{
Q_UNUSED(event)
}
void TimelineView::ZoomTool::MouseRelease(QMouseEvent *event)
void TimelineView::ZoomTool::MouseRelease(TimelineViewMouseEvent *event)
{
double scale = parent()->scale_;
QPointF center_location = parent()->mapToScene(event->pos());
// 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 = center_location.x() / scale;
double scaled_x = scene_center.x() / scale;
if (event->modifiers() & Qt::AltModifier) {
if (event->GetModifiers() & Qt::AltModifier) {
// Zoom out if the user clicks while holding Alt
scale *= 0.5;
} else {
@@ -57,7 +62,7 @@ void TimelineView::ZoomTool::MouseRelease(QMouseEvent *event)
// Adjust zoom location for new scale
scaled_x *= scale;
center_location.setX(scaled_x);
scene_center.setX(scaled_x);
parent()->centerOn(center_location);
parent()->centerOn(scene_center);
}