diff --git a/app/common/CMakeLists.txt b/app/common/CMakeLists.txt index f3cb1ca7e..930eb2d53 100644 --- a/app/common/CMakeLists.txt +++ b/app/common/CMakeLists.txt @@ -22,6 +22,8 @@ set(OLIVE_SOURCES common/debug.cpp common/filefunctions.h common/filefunctions.cpp + common/flipmodifiers.h + common/flipmodifiers.cpp common/lerp.h common/range.h common/rational.h diff --git a/app/common/flipmodifiers.cpp b/app/common/flipmodifiers.cpp new file mode 100644 index 000000000..3652babcf --- /dev/null +++ b/app/common/flipmodifiers.cpp @@ -0,0 +1,37 @@ +/*** + + 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 . + +***/ + +#include "flipmodifiers.h" + +Qt::KeyboardModifiers FlipControlAndShiftModifiers(Qt::KeyboardModifiers e) { + if (e & Qt::ControlModifier & Qt::ShiftModifier) { + return e; + } + + if (e & Qt::ShiftModifier) { + e |= Qt::ControlModifier; + e &= ~Qt::ShiftModifier; + } else if (e & Qt::ControlModifier) { + e |= Qt::ShiftModifier; + e &= ~Qt::ControlModifier; + } + + return e; +} diff --git a/app/common/flipmodifiers.h b/app/common/flipmodifiers.h new file mode 100644 index 000000000..8fb754eda --- /dev/null +++ b/app/common/flipmodifiers.h @@ -0,0 +1,28 @@ +/*** + + 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 . + +***/ + +#ifndef FLIPMODIFIERS_H +#define FLIPMODIFIERS_H + +#include + +Qt::KeyboardModifiers FlipControlAndShiftModifiers(Qt::KeyboardModifiers e); + +#endif // FLIPMODIFIERS_H diff --git a/app/node/output/timeline/timeline.cpp b/app/node/output/timeline/timeline.cpp index f31f4db98..ffdbdcf75 100644 --- a/app/node/output/timeline/timeline.cpp +++ b/app/node/output/timeline/timeline.cpp @@ -39,7 +39,7 @@ TimelineOutput::TimelineOutput() AddParameter(track_input); track_inputs_[i] = track_input; - TrackList* list = new TrackList(this, track_input); + TrackList* list = new TrackList(this, static_cast(i), track_input); track_lists_[i] = list; connect(list, SIGNAL(TrackListChanged()), this, SLOT(UpdateTrackCache())); connect(list, SIGNAL(LengthChanged(const rational &)), this, SLOT(UpdateLength(const rational &))); @@ -141,12 +141,12 @@ void TimelineOutput::SetTimebase(const rational &timebase) } } -NodeInput *TimelineOutput::track_input(TimelineOutput::TrackType type) +NodeInput *TimelineOutput::track_input(TrackType type) { return track_inputs_.at(type); } -TrackList *TimelineOutput::track_list(TimelineOutput::TrackType type) +TrackList *TimelineOutput::track_list(TrackType type) { return track_lists_.at(type); } diff --git a/app/node/output/timeline/timeline.h b/app/node/output/timeline/timeline.h index 60418ad98..ff233bd11 100644 --- a/app/node/output/timeline/timeline.h +++ b/app/node/output/timeline/timeline.h @@ -25,6 +25,7 @@ #include "node/block/block.h" #include "node/output/track/track.h" #include "tracklist.h" +#include "tracktypes.h" /** * @brief Node that represents the end of the Timeline as well as a time traversal Node @@ -33,14 +34,6 @@ class TimelineOutput : public Node { Q_OBJECT public: - enum TrackType { - kTrackTypeNone = -1, - kTrackTypeVideo, - kTrackTypeAudio, - kTrackTypeSubtitle, - kTrackTypeCount - }; - TimelineOutput(); virtual QString Name() override; diff --git a/app/node/output/timeline/tracklist.cpp b/app/node/output/timeline/tracklist.cpp index c65c413e3..e373d9a6b 100644 --- a/app/node/output/timeline/tracklist.cpp +++ b/app/node/output/timeline/tracklist.cpp @@ -23,9 +23,10 @@ #include "node/blend/alphaover/alphaover.h" #include "timeline.h" -TrackList::TrackList(TimelineOutput* parent, NodeInput *track_input) : +TrackList::TrackList(TimelineOutput* parent, const enum TrackType &type, NodeInput *track_input) : QObject(parent), - track_input_(track_input) + track_input_(track_input), + type_(type) { connect(parent, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SLOT(TrackConnectionAdded(NodeEdgePtr))); connect(parent, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SLOT(TrackConnectionRemoved(NodeEdgePtr))); @@ -125,6 +126,11 @@ const rational &TrackList::TrackLength() return total_length_; } +const enum TrackType &TrackList::TrackType() +{ + return type_; +} + void TrackList::AddTrack() { TrackOutput* track = new TrackOutput(); diff --git a/app/node/output/timeline/tracklist.h b/app/node/output/timeline/tracklist.h index ae670092c..7b0858d13 100644 --- a/app/node/output/timeline/tracklist.h +++ b/app/node/output/timeline/tracklist.h @@ -25,13 +25,14 @@ #include "node/graph.h" #include "node/output/track/track.h" +#include "tracktypes.h" class TimelineOutput; class TrackList : public QObject { Q_OBJECT public: - TrackList(TimelineOutput *parent, NodeInput* track_input); + TrackList(TimelineOutput *parent, const enum TrackType& type, NodeInput* track_input); TrackOutput* attached_track(); @@ -53,6 +54,8 @@ public: const rational& TrackLength(); + const enum TrackType& TrackType(); + public slots:/** * @brief Slot for when the track connection is added */ @@ -114,6 +117,8 @@ private: rational total_length_; + enum TrackType type_; + private slots: void UpdateTotalLength(); }; diff --git a/app/node/output/timeline/tracktypes.h b/app/node/output/timeline/tracktypes.h new file mode 100644 index 000000000..f3cb28a50 --- /dev/null +++ b/app/node/output/timeline/tracktypes.h @@ -0,0 +1,12 @@ +#ifndef TRACKTYPES_H +#define TRACKTYPES_H + +enum TrackType { + kTrackTypeNone = -1, + kTrackTypeVideo, + kTrackTypeAudio, + kTrackTypeSubtitle, + kTrackTypeCount +}; + +#endif // TRACKTYPES_H diff --git a/app/project/item/sequence/sequence.cpp b/app/project/item/sequence/sequence.cpp index 3af8939ce..3dd0c77c3 100644 --- a/app/project/item/sequence/sequence.cpp +++ b/app/project/item/sequence/sequence.cpp @@ -84,8 +84,8 @@ void Sequence::AddDefaultNodes() NodeParam::ConnectEdge(renderer_processor_->texture_output(), viewer_output_->texture_input()); // Connect track to timeline - NodeParam::ConnectEdge(video_track_output_->track_output(), timeline_output_->track_input(TimelineOutput::kTrackTypeVideo)); - NodeParam::ConnectEdge(audio_track_output_->track_output(), timeline_output_->track_input(TimelineOutput::kTrackTypeAudio)); + NodeParam::ConnectEdge(video_track_output_->track_output(), timeline_output_->track_input(kTrackTypeVideo)); + NodeParam::ConnectEdge(audio_track_output_->track_output(), timeline_output_->track_input(kTrackTypeAudio)); // Connect timeline end point to renderer NodeParam::ConnectEdge(timeline_output_->length_output(), renderer_processor_->length_input()); diff --git a/app/tool/tool.h b/app/tool/tool.h index 079a9839f..5e4734b7a 100644 --- a/app/tool/tool.h +++ b/app/tool/tool.h @@ -66,7 +66,9 @@ enum Tool { kRecord, /// Add tool - kAdd + kAdd, + + kCount }; } diff --git a/app/widget/timelineview/CMakeLists.txt b/app/widget/timelineview/CMakeLists.txt index a52e59a95..515a529bf 100644 --- a/app/widget/timelineview/CMakeLists.txt +++ b/app/widget/timelineview/CMakeLists.txt @@ -19,12 +19,16 @@ 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 widget/timelineview/timelinescaledobject.cpp widget/timelineview/timelineview.h widget/timelineview/timelineview.cpp + widget/timelineview/timelineviewmouseevent.h + widget/timelineview/timelineviewmouseevent.cpp widget/timelineview/timelineviewrect.h widget/timelineview/timelineviewrect.cpp widget/timelineview/timelineviewblockitem.h diff --git a/app/widget/timelineview/timelinecoordinate.cpp b/app/widget/timelineview/timelinecoordinate.cpp new file mode 100644 index 000000000..8a41d84f5 --- /dev/null +++ b/app/widget/timelineview/timelinecoordinate.cpp @@ -0,0 +1,52 @@ +/*** + + 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 . + +***/ + +#include "timelinecoordinate.h" + +TimelineCoordinate::TimelineCoordinate() : + track_(0) +{ +} + +TimelineCoordinate::TimelineCoordinate(const rational &frame, const int &track) : + frame_(frame), + track_(track) +{ +} + +const rational &TimelineCoordinate::GetFrame() const +{ + return frame_; +} + +const int &TimelineCoordinate::GetTrack() const +{ + return track_; +} + +void TimelineCoordinate::SetFrame(const rational &frame) +{ + frame_ = frame; +} + +void TimelineCoordinate::SetTrack(const int &track) +{ + track_ = track; +} diff --git a/app/widget/timelineview/timelinecoordinate.h b/app/widget/timelineview/timelinecoordinate.h new file mode 100644 index 000000000..605135684 --- /dev/null +++ b/app/widget/timelineview/timelinecoordinate.h @@ -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 . + +***/ + +#ifndef TIMELINECOORDINATE_H +#define TIMELINECOORDINATE_H + +#include "common/rational.h" + +class TimelineCoordinate +{ +public: + TimelineCoordinate(); + TimelineCoordinate(const rational& frame, const int& track); + + const rational& GetFrame() const; + const int& GetTrack() const; + + void SetFrame(const rational& frame); + void SetTrack(const int& track); + +private: + rational frame_; + + int track_; + +}; + +#endif // TIMELINECOORDINATE_H diff --git a/app/widget/timelineview/timelineview.cpp b/app/widget/timelineview/timelineview.cpp index 66aba1dfb..00fbefa87 100644 --- a/app/widget/timelineview/timelineview.cpp +++ b/app/widget/timelineview/timelineview.cpp @@ -27,6 +27,7 @@ #include #include +#include "common/flipmodifiers.h" #include "common/timecodefunctions.h" #include "core.h" #include "node/input/media/media.h" @@ -35,15 +36,6 @@ TimelineView::TimelineView(Qt::Alignment vertical_alignment, QWidget *parent) : QGraphicsView(parent), - pointer_tool_(this), - import_tool_(this), - ripple_tool_(this), - rolling_tool_(this), - razor_tool_(this), - slide_tool_(this), - slip_tool_(this), - hand_tool_(this), - zoom_tool_(this), timeline_node_(nullptr), playhead_(0), use_tracklist_length_directly_(true) @@ -56,6 +48,25 @@ 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(this)); + // tools_.replace(olive::tool::kEdit, new PointerTool(this)); FIXME: Implement + tools_.replace(olive::tool::kRipple, std::make_shared(this)); + tools_.replace(olive::tool::kRolling, std::make_shared(this)); + tools_.replace(olive::tool::kRazor, std::make_shared(this)); + tools_.replace(olive::tool::kSlip, std::make_shared(this)); + tools_.replace(olive::tool::kSlide, std::make_shared(this)); + tools_.replace(olive::tool::kHand, std::make_shared(this)); + tools_.replace(olive::tool::kZoom, std::make_shared(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(this); + connect(&scene_, SIGNAL(changed(const QList&)), this, SLOT(UpdateSceneRect())); // Create end item @@ -121,7 +132,7 @@ void TimelineView::SetScale(const double &scale) { scale_ = scale; - QMapIterator iterator(block_items_); + QMapIterator iterator(block_items_); while (iterator.hasNext()) { iterator.next(); @@ -145,11 +156,14 @@ void TimelineView::SetTimebase(const rational &timebase) { timebase_ = timebase; timebase_dbl_ = timebase_.toDouble(); + + // Timebase influences position/visibility of playhead + viewport()->update(); } void TimelineView::Clear() { - QMapIterator iterator(block_items_); + QMapIterator iterator(block_items_); while (iterator.hasNext()) { iterator.next(); @@ -239,50 +253,131 @@ void TimelineView::mousePressEvent(QMouseEvent *event) { active_tool_ = GetActiveTool(); + // Cache these since we modify the event's later on + Qt::KeyboardModifiers mods = event->modifiers(); + + 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) { - active_tool_->MousePress(event); + 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(); + + 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) { - active_tool_->MouseMove(event); + TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()), + mods); + + active_tool_->MouseMove(&timeline_event); } } void TimelineView::mouseReleaseEvent(QMouseEvent *event) { + // Cache these since we modify the event's later on + Qt::KeyboardModifiers mods = 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) { - active_tool_->MouseRelease(event); + TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()), + mods); + + active_tool_->MouseRelease(&timeline_event); + } +} + +void TimelineView::mouseDoubleClickEvent(QMouseEvent *event) +{ + // Cache these since we modify the event's later on + Qt::KeyboardModifiers mods = 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); } } void TimelineView::dragEnterEvent(QDragEnterEvent *event) { if (timeline_node_ != nullptr) { - import_tool_.DragEnter(event); + TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()), + event->keyboardModifiers()); + + timeline_event.SetMimeData(event->mimeData()); + timeline_event.SetEvent(event); + + import_tool_->DragEnter(&timeline_event); } } void TimelineView::dragMoveEvent(QDragMoveEvent *event) { if (timeline_node_ != nullptr) { - import_tool_.DragMove(event); + TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()), + event->keyboardModifiers()); + + timeline_event.SetMimeData(event->mimeData()); + timeline_event.SetEvent(event); + + import_tool_->DragMove(&timeline_event); } } void TimelineView::dragLeaveEvent(QDragLeaveEvent *event) { if (timeline_node_ != nullptr) { - import_tool_.DragLeave(event); + import_tool_->DragLeave(event); } } void TimelineView::dropEvent(QDropEvent *event) { if (timeline_node_ != nullptr) { - import_tool_.DragDrop(event); + TimelineViewMouseEvent timeline_event(ScreenToCoordinate(event->pos()), + event->keyboardModifiers()); + + timeline_event.SetMimeData(event->mimeData()); + timeline_event.SetEvent(event); + + import_tool_->DragDrop(&timeline_event); } } @@ -297,52 +392,61 @@ void TimelineView::drawForeground(QPainter *painter, const QRectF &rect) { QGraphicsView::drawForeground(painter, rect); - double x = TimeToScreenCoord(rational(playhead_ * timebase_.numerator(), timebase_.denominator())); - double width = TimeToScreenCoord(timebase_); + if (!timebase_.isNull()) { + double x = TimeToScreenCoord(rational(playhead_ * timebase_.numerator(), timebase_.denominator())); + double width = TimeToScreenCoord(timebase_); - QRectF playhead_rect(x, rect.top(), width, rect.height()); + QRectF playhead_rect(x, rect.top(), width, rect.height()); - painter->setPen(Qt::NoPen); - painter->setBrush(playhead_style_.PlayheadHighlightColor()); - painter->drawRect(playhead_rect); + painter->setPen(Qt::NoPen); + painter->setBrush(playhead_style_.PlayheadHighlightColor()); + painter->drawRect(playhead_rect); - painter->setPen(playhead_style_.PlayheadColor()); - painter->setBrush(Qt::NoBrush); - painter->drawLine(QLineF(playhead_rect.topLeft(), playhead_rect.bottomLeft())); + painter->setPen(playhead_style_.PlayheadColor()); + painter->setBrush(Qt::NoBrush); + painter->drawLine(QLineF(playhead_rect.topLeft(), playhead_rect.bottomLeft())); + } +} + +TrackType TimelineView::ConnectedTrackType() +{ + if (timeline_node_ != nullptr) { + return timeline_node_->TrackType(); + } + + return kTrackTypeNone; +} + +Stream::Type TimelineView::TrackTypeToStreamType(TrackType track_type) +{ + switch (track_type) { + case kTrackTypeNone: + case kTrackTypeCount: + break; + case kTrackTypeVideo: + return Stream::kVideo; + case kTrackTypeAudio: + return Stream::kAudio; + case kTrackTypeSubtitle: + return Stream::kSubtitle; + } + + return Stream::kUnknown; +} + +TimelineCoordinate TimelineView::ScreenToCoordinate(const QPoint& pt) +{ + return SceneToCoordinate(mapToScene(pt)); +} + +TimelineCoordinate TimelineView::SceneToCoordinate(const QPointF& pt) +{ + return TimelineCoordinate(SceneToTime(pt.x()), SceneToTrack(pt.y())); } TimelineView::Tool *TimelineView::GetActiveTool() { - switch (olive::core.tool()) { - case olive::tool::kNone: - return nullptr; - case olive::tool::kPointer: - return &pointer_tool_; - case olive::tool::kEdit: - return nullptr; // FIXME: Implement - case olive::tool::kRipple: - return &ripple_tool_; - case olive::tool::kRolling: - return &rolling_tool_; - case olive::tool::kRazor: - return &razor_tool_; - case olive::tool::kSlip: - return &slip_tool_; - case olive::tool::kSlide: - return &slide_tool_; - case olive::tool::kHand: - return &hand_tool_; - case olive::tool::kZoom: - return &zoom_tool_; - case olive::tool::kTransition: - return nullptr; // FIXME: Implement - case olive::tool::kRecord: - return nullptr; // FIXME: Implement - case olive::tool::kAdd: - return nullptr; // FIXME: Implement - } - - return nullptr; + return tools_.at(olive::core.tool()).get(); } int TimelineView::GetTrackY(int track_index) @@ -383,7 +487,7 @@ bool TimelineView::HasGhosts() rational TimelineView::SceneToTime(const double &x) { // Adjust screen point by scale and timebase - int scaled_x_mvmt = qRound(x / scale_ / timebase_dbl_); + qint64 scaled_x_mvmt = qRound64(x / scale_ / timebase_dbl_); // Return a time in the timebase return rational(scaled_x_mvmt * timebase_.numerator(), timebase_.denominator()); diff --git a/app/widget/timelineview/timelineview.h b/app/widget/timelineview/timelineview.h index 2442d8615..29b4d4217 100644 --- a/app/widget/timelineview/timelineview.h +++ b/app/widget/timelineview/timelineview.h @@ -31,6 +31,7 @@ #include "node/output/timeline/timeline.h" #include "timelineplayhead.h" #include "timelineviewblockitem.h" +#include "timelineviewmouseevent.h" #include "timelineviewenditem.h" #include "timelineviewghostitem.h" #include "widget/timelineview/undo/undo.h" @@ -91,6 +92,7 @@ protected: virtual void mousePressEvent(QMouseEvent *event) override; virtual void mouseMoveEvent(QMouseEvent *event) override; virtual void mouseReleaseEvent(QMouseEvent *event) override; + virtual void mouseDoubleClickEvent(QMouseEvent *event) override; virtual void dragEnterEvent(QDragEnterEvent *event) override; virtual void dragMoveEvent(QDragMoveEvent *event) override; @@ -109,27 +111,28 @@ private: Tool(TimelineView* parent); virtual ~Tool(); - virtual void MousePress(QMouseEvent *event); - virtual void MouseMove(QMouseEvent *event); - virtual void MouseRelease(QMouseEvent *event); + virtual void MousePress(TimelineViewMouseEvent *){} + virtual void MouseMove(TimelineViewMouseEvent *){} + virtual void MouseRelease(TimelineViewMouseEvent *){} + virtual void MouseDoubleClick(TimelineViewMouseEvent *){} - virtual void DragEnter(QDragEnterEvent *event); - virtual void DragMove(QDragMoveEvent *event); - virtual void DragLeave(QDragLeaveEvent *event); - virtual void DragDrop(QDropEvent *event); + 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: - /** - * @brief Convert a integer screen point to a float scene point - * - * Useful for converting a mouse coordinate provided by a QMouseEvent to a inner-timeline scene position (the - * coordinates that the graphics items use) - */ - QPointF GetScenePos(const QPoint& screen_pos); + void set_drag_mode(const DragMode& mode); + + void set_enable_default_behavior(bool enable); /** * @brief Retrieve the QGraphicsItem at a particular scene position @@ -137,7 +140,7 @@ private: * Requires a float-based scene position. If you have a screen position, use GetScenePos() first to convert it to a * scene position */ - QGraphicsItem* GetItemAtScenePos(const QPointF& scene_pos); + TimelineViewBlockItem* GetItemAtScenePos(const TimelineCoordinate &coord); /** * @brief Validates Ghosts that are moving horizontally (time-based) @@ -169,11 +172,15 @@ private: bool dragging_; - QPointF drag_start_; + TimelineCoordinate drag_start_; private: TimelineView* parent_; + DragMode drag_mode_; + + bool enable_default_behavior_; + }; class PointerTool : public Tool @@ -181,14 +188,14 @@ private: public: PointerTool(TimelineView* parent); - virtual void MousePress(QMouseEvent *event) override; - virtual void MouseMove(QMouseEvent *event) override; - virtual void MouseRelease(QMouseEvent *event) override; + 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(QMouseEvent *event); + virtual void MouseReleaseInternal(TimelineViewMouseEvent *event); virtual rational FrameValidateInternal(rational time_movement, const QVector &ghosts); virtual void InitiateGhosts(TimelineViewBlockItem* clicked_item, @@ -215,9 +222,9 @@ private: */ rational ValidateOutTrimming(rational movement, const QVector ghosts, bool prevent_overwriting); - virtual void ProcessDrag(const QPoint &mouse_pos); + virtual void ProcessDrag(const TimelineCoordinate &mouse_pos); private: - void InitiateDrag(const QPoint &mouse_pos); + void InitiateDrag(const TimelineCoordinate &mouse_pos); void AddGhostInternal(TimelineViewGhostItem* ghost, olive::timeline::MovementMode mode); @@ -238,10 +245,10 @@ private: public: ImportTool(TimelineView* parent); - virtual void DragEnter(QDragEnterEvent *event) override; - virtual void DragMove(QDragMoveEvent *event) override; + virtual void DragEnter(TimelineViewMouseEvent *event) override; + virtual void DragMove(TimelineViewMouseEvent *event) override; virtual void DragLeave(QDragLeaveEvent *event) override; - virtual void DragDrop(QDropEvent *event) override; + virtual void DragDrop(TimelineViewMouseEvent *event) override; private: int import_pre_buffer_; }; @@ -251,9 +258,9 @@ private: public: RazorTool(TimelineView* parent); - virtual void MousePress(QMouseEvent *event); - virtual void MouseMove(QMouseEvent *event); - virtual void MouseRelease(QMouseEvent *event); + virtual void MousePress(TimelineViewMouseEvent *event); + virtual void MouseMove(TimelineViewMouseEvent *event); + virtual void MouseRelease(TimelineViewMouseEvent *event); private: QVector split_tracks_; @@ -264,7 +271,7 @@ private: public: RippleTool(TimelineView* parent); protected: - virtual void MouseReleaseInternal(QMouseEvent *event) override; + virtual void MouseReleaseInternal(TimelineViewMouseEvent *event) override; virtual rational FrameValidateInternal(rational time_movement, const QVector& ghosts) override; virtual void InitiateGhosts(TimelineViewBlockItem* clicked_item, @@ -278,7 +285,7 @@ private: RollingTool(TimelineView* parent); protected: - virtual void MouseReleaseInternal(QMouseEvent *event) override; + virtual void MouseReleaseInternal(TimelineViewMouseEvent *event) override; virtual rational FrameValidateInternal(rational time_movement, const QVector& ghosts) override; virtual void InitiateGhosts(TimelineViewBlockItem* clicked_item, @@ -292,7 +299,7 @@ private: SlideTool(TimelineView* parent); protected: - virtual void MouseReleaseInternal(QMouseEvent *event) override; + virtual void MouseReleaseInternal(TimelineViewMouseEvent *event) override; virtual rational FrameValidateInternal(rational time_movement, const QVector& ghosts) override; virtual void InitiateGhosts(TimelineViewBlockItem* clicked_item, olive::timeline::MovementMode trim_mode, @@ -305,8 +312,8 @@ private: SlipTool(TimelineView* parent); protected: - virtual void ProcessDrag(const QPoint &mouse_pos) override; - virtual void MouseReleaseInternal(QMouseEvent *event) override; + virtual void ProcessDrag(const TimelineCoordinate &mouse_pos) override; + virtual void MouseReleaseInternal(TimelineViewMouseEvent *event) override; }; class HandTool : public Tool @@ -314,10 +321,6 @@ private: public: HandTool(TimelineView* parent); - virtual void MousePress(QMouseEvent *event); - virtual void MouseMove(QMouseEvent *event); - virtual void MouseRelease(QMouseEvent *event); - private: QPoint screen_drag_start_; QPoint scrollbar_start_; @@ -328,25 +331,25 @@ private: public: ZoomTool(TimelineView* parent); - virtual void MousePress(QMouseEvent *event); - virtual void MouseMove(QMouseEvent *event); - virtual void MouseRelease(QMouseEvent *event); + 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); - PointerTool pointer_tool_; - ImportTool import_tool_; - RippleTool ripple_tool_; - RollingTool rolling_tool_; - RazorTool razor_tool_; - SlideTool slide_tool_; - SlipTool slip_tool_; - HandTool hand_tool_; - ZoomTool zoom_tool_; + QVector< std::shared_ptr > tools_; + + std::shared_ptr import_tool_; TrackList* timeline_node_; @@ -369,7 +372,7 @@ private: int64_t playhead_; - QMap block_items_; + QMap block_items_; QVector ghost_items_; diff --git a/app/widget/timelineview/timelineviewblockitem.cpp b/app/widget/timelineview/timelineviewblockitem.cpp index 8d0c326f1..b1690b544 100644 --- a/app/widget/timelineview/timelineviewblockitem.cpp +++ b/app/widget/timelineview/timelineviewblockitem.cpp @@ -70,29 +70,41 @@ void TimelineViewBlockItem::paint(QPainter *painter, const QStyleOptionGraphicsI { Q_UNUSED(widget) - if (block_ == nullptr || block_->type() == Block::kGap) { + if (block_ == nullptr) { return; } - /*QLinearGradient grad; - grad.setStart(0, rect().top()); - grad.setFinalStop(0, rect().bottom()); - grad.setColorAt(0.0, QColor(160, 160, 240)); - grad.setColorAt(1.0, QColor(128, 128, 192)); - painter->fillRect(rect(), grad);*/ - painter->fillRect(rect(), QColor(128, 128, 192)); + switch (block_->type()) { + case Block::kClip: + /*QLinearGradient grad; + grad.setStart(0, rect().top()); + grad.setFinalStop(0, rect().bottom()); + grad.setColorAt(0.0, QColor(160, 160, 240)); + grad.setColorAt(1.0, QColor(128, 128, 192)); + painter->fillRect(rect(), grad);*/ + painter->fillRect(rect(), QColor(128, 128, 192)); - if (option->state & QStyle::State_Selected) { - painter->fillRect(rect(), QColor(0, 0, 0, 64)); + if (option->state & QStyle::State_Selected) { + painter->fillRect(rect(), QColor(0, 0, 0, 64)); + } + + painter->setPen(Qt::white); + painter->drawLine(rect().topLeft(), QPointF(rect().right(), rect().top())); + painter->drawLine(rect().topLeft(), QPointF(rect().left(), rect().bottom() - 1)); + + painter->drawText(rect(), static_cast(Qt::AlignLeft | Qt::AlignTop), block_->block_name()); + + painter->setPen(QColor(64, 64, 64)); + painter->drawLine(QPointF(rect().left(), rect().bottom() - 1), QPointF(rect().right(), rect().bottom() - 1)); + painter->drawLine(QPointF(rect().right(), rect().bottom() - 1), QPointF(rect().right(), rect().top())); + break; + case Block::kGap: + if (option->state & QStyle::State_Selected) { + // FIXME: Make this palette or CSS + painter->fillRect(rect(), Qt::white); + } + break; + case Block::kEnd: + break; } - - painter->setPen(Qt::white); - painter->drawLine(rect().topLeft(), QPointF(rect().right(), rect().top())); - painter->drawLine(rect().topLeft(), QPointF(rect().left(), rect().bottom() - 1)); - - painter->drawText(rect(), static_cast(Qt::AlignLeft | Qt::AlignTop), block_->block_name()); - - painter->setPen(QColor(64, 64, 64)); - painter->drawLine(QPointF(rect().left(), rect().bottom() - 1), QPointF(rect().right(), rect().bottom() - 1)); - painter->drawLine(QPointF(rect().right(), rect().bottom() - 1), QPointF(rect().right(), rect().top())); } diff --git a/app/widget/timelineview/timelineviewmouseevent.cpp b/app/widget/timelineview/timelineviewmouseevent.cpp new file mode 100644 index 000000000..592fda769 --- /dev/null +++ b/app/widget/timelineview/timelineviewmouseevent.cpp @@ -0,0 +1,79 @@ +/*** + + 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 . + +***/ + +#include "timelineviewmouseevent.h" + +#include + +TimelineViewMouseEvent::TimelineViewMouseEvent(const TimelineCoordinate &coord, + const Qt::KeyboardModifiers &modifiers) : + coord_(coord), + modifiers_(modifiers), + source_event_(nullptr), + mime_data_(nullptr) +{ +} + +TimelineViewMouseEvent::TimelineViewMouseEvent(const rational &frame, + const int &track, + const Qt::KeyboardModifiers &modifiers) : + coord_(frame, track), + modifiers_(modifiers), + source_event_(nullptr), + mime_data_(nullptr) +{ +} + +const TimelineCoordinate &TimelineViewMouseEvent::GetCoordinates() +{ + return coord_; +} + +const Qt::KeyboardModifiers TimelineViewMouseEvent::GetModifiers() +{ + return modifiers_; +} + +const QMimeData* TimelineViewMouseEvent::GetMimeData() +{ + return mime_data_; +} + +void TimelineViewMouseEvent::SetMimeData(const QMimeData *data) +{ + mime_data_ = data; +} + +void TimelineViewMouseEvent::SetEvent(QEvent *event) +{ + source_event_ = event; +} + +void TimelineViewMouseEvent::accept() +{ + if (source_event_ != nullptr) + source_event_->accept(); +} + +void TimelineViewMouseEvent::ignore() +{ + if (source_event_ != nullptr) + source_event_->ignore(); +} diff --git a/app/widget/timelineview/timelineviewmouseevent.h b/app/widget/timelineview/timelineviewmouseevent.h new file mode 100644 index 000000000..61afbb7ba --- /dev/null +++ b/app/widget/timelineview/timelineviewmouseevent.h @@ -0,0 +1,62 @@ +/*** + + 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 . + +***/ + +#ifndef TIMELINEVIEWMOUSEEVENT_H +#define TIMELINEVIEWMOUSEEVENT_H + +#include +#include +#include + +#include "timelinecoordinate.h" + +class TimelineViewMouseEvent +{ +public: + TimelineViewMouseEvent(const TimelineCoordinate& coord, + const Qt::KeyboardModifiers& modifiers = Qt::NoModifier); + + TimelineViewMouseEvent(const rational& frame, + const int& track, + const Qt::KeyboardModifiers& modifiers = Qt::NoModifier); + + const TimelineCoordinate& GetCoordinates(); + const Qt::KeyboardModifiers GetModifiers(); + + const QMimeData *GetMimeData(); + void SetMimeData(const QMimeData *data); + + void SetEvent(QEvent* event); + + void accept(); + void ignore(); + +private: + TimelineCoordinate coord_; + + Qt::KeyboardModifiers modifiers_; + + QEvent* source_event_; + + const QMimeData* mime_data_; + +}; + +#endif // TIMELINEVIEWMOUSEEVENT_H diff --git a/app/widget/timelineview/tool/hand.cpp b/app/widget/timelineview/tool/hand.cpp index b7486dc1b..89d1076a6 100644 --- a/app/widget/timelineview/tool/hand.cpp +++ b/app/widget/timelineview/tool/hand.cpp @@ -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); } diff --git a/app/widget/timelineview/tool/import.cpp b/app/widget/timelineview/tool/import.cpp index 470f65363..68e4386c5 100644 --- a/app/widget/timelineview/tool/import.cpp +++ b/app/widget/timelineview/tool/import.cpp @@ -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(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(); - } 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(); + } 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); diff --git a/app/widget/timelineview/tool/pointer.cpp b/app/widget/timelineview/tool/pointer.cpp index eaa013fae..545674dcf 100644 --- a/app/widget/timelineview/tool/pointer.cpp +++ b/app/widget/timelineview/tool/pointer.cpp @@ -24,6 +24,7 @@ #include #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(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()) { diff --git a/app/widget/timelineview/tool/razor.cpp b/app/widget/timelineview/tool/razor.cpp index 1eab31cf6..b6e02f206 100644 --- a/app/widget/timelineview/tool/razor.cpp +++ b/app/widget/timelineview/tool/razor.cpp @@ -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(); diff --git a/app/widget/timelineview/tool/ripple.cpp b/app/widget/timelineview/tool/ripple.cpp index d030fe435..a42345ad0 100644 --- a/app/widget/timelineview/tool/ripple.cpp +++ b/app/widget/timelineview/tool/ripple.cpp @@ -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) diff --git a/app/widget/timelineview/tool/rolling.cpp b/app/widget/timelineview/tool/rolling.cpp index f6e839c90..2db6f8bc6 100644 --- a/app/widget/timelineview/tool/rolling.cpp +++ b/app/widget/timelineview/tool/rolling.cpp @@ -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) diff --git a/app/widget/timelineview/tool/slide.cpp b/app/widget/timelineview/tool/slide.cpp index 8f466fb10..46d89e313 100644 --- a/app/widget/timelineview/tool/slide.cpp +++ b/app/widget/timelineview/tool/slide.cpp @@ -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) diff --git a/app/widget/timelineview/tool/slip.cpp b/app/widget/timelineview/tool/slip.cpp index d70aa1916..a095ac99b 100644 --- a/app/widget/timelineview/tool/slip.cpp +++ b/app/widget/timelineview/tool/slip.cpp @@ -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) diff --git a/app/widget/timelineview/tool/tool.cpp b/app/widget/timelineview/tool/tool.cpp index 77a99b322..6b5219e12 100644 --- a/app/widget/timelineview/tool/tool.cpp +++ b/app/widget/timelineview/tool/tool.cpp @@ -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 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& proposed_pts, diff --git a/app/widget/timelineview/tool/zoom.cpp b/app/widget/timelineview/tool/zoom.cpp index da9f786fe..6215fba8b 100644 --- a/app/widget/timelineview/tool/zoom.cpp +++ b/app/widget/timelineview/tool/zoom.cpp @@ -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); } diff --git a/app/widget/timelinewidget/timelinewidget.cpp b/app/widget/timelinewidget/timelinewidget.cpp index b9d3dc078..8ee886c32 100644 --- a/app/widget/timelinewidget/timelinewidget.cpp +++ b/app/widget/timelinewidget/timelinewidget.cpp @@ -120,7 +120,7 @@ void TimelineWidget::ConnectTimelineNode(TimelineOutput *node) int track_type = 0; foreach (TimelineView* view, views_) { - view->ConnectTimelineNode(node->track_list(static_cast(track_type))); + view->ConnectTimelineNode(node->track_list(static_cast(track_type))); track_type++; }