327 lines
7.8 KiB
C++
327 lines
7.8 KiB
C++
/***
|
|
|
|
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 "timelineview.h"
|
|
|
|
#include <QDebug>
|
|
#include <QMimeData>
|
|
#include <QMouseEvent>
|
|
#include <QScrollBar>
|
|
#include <QtMath>
|
|
#include <QPen>
|
|
|
|
#include "config/config.h"
|
|
#include "common/flipmodifiers.h"
|
|
#include "common/timecodefunctions.h"
|
|
#include "node/input/media/media.h"
|
|
#include "project/item/footage/footage.h"
|
|
|
|
TimelineView::TimelineView(const TrackType &type, Qt::Alignment vertical_alignment, QWidget *parent) :
|
|
TimelineViewBase(parent),
|
|
connected_track_list_(nullptr),
|
|
type_(type)
|
|
{
|
|
Q_ASSERT(vertical_alignment == Qt::AlignTop || vertical_alignment == Qt::AlignBottom);
|
|
setAlignment(Qt::AlignLeft | vertical_alignment);
|
|
|
|
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
|
setBackgroundRole(QPalette::Window);
|
|
setContextMenuPolicy(Qt::CustomContextMenu);
|
|
SetLimitYAxis(true);
|
|
}
|
|
|
|
void TimelineView::SelectAll()
|
|
{
|
|
QList<QGraphicsItem*> all_items = items();
|
|
|
|
foreach (QGraphicsItem* i, all_items) {
|
|
i->setSelected(true);
|
|
}
|
|
}
|
|
|
|
void TimelineView::DeselectAll()
|
|
{
|
|
QList<QGraphicsItem*> all_items = items();
|
|
|
|
foreach (QGraphicsItem* i, all_items) {
|
|
i->setSelected(false);
|
|
}
|
|
}
|
|
|
|
void TimelineView::mousePressEvent(QMouseEvent *event)
|
|
{
|
|
if (HandPress(event) || PlayheadPress(event)) {
|
|
// Let the parent handle this
|
|
return;
|
|
}
|
|
|
|
if (dragMode() != GetDefaultDragMode()) {
|
|
TimelineViewBase::mousePressEvent(event);
|
|
return;
|
|
}
|
|
|
|
TimelineViewMouseEvent timeline_event = CreateMouseEvent(event->pos(), event->modifiers());
|
|
|
|
emit MousePressed(&timeline_event);
|
|
}
|
|
|
|
void TimelineView::mouseMoveEvent(QMouseEvent *event)
|
|
{
|
|
if (HandMove(event) || PlayheadMove(event)) {
|
|
// Let the parent handle this
|
|
return;
|
|
}
|
|
|
|
if (dragMode() != GetDefaultDragMode()) {
|
|
TimelineViewBase::mouseMoveEvent(event);
|
|
return;
|
|
}
|
|
|
|
TimelineViewMouseEvent timeline_event = CreateMouseEvent(event->pos(), event->modifiers());
|
|
|
|
emit MouseMoved(&timeline_event);
|
|
}
|
|
|
|
void TimelineView::mouseReleaseEvent(QMouseEvent *event)
|
|
{
|
|
if (HandRelease(event) || PlayheadRelease(event)) {
|
|
// Let the parent handle this
|
|
return;
|
|
}
|
|
|
|
if (dragMode() != GetDefaultDragMode()) {
|
|
TimelineViewBase::mouseReleaseEvent(event);
|
|
return;
|
|
}
|
|
|
|
TimelineViewMouseEvent timeline_event = CreateMouseEvent(event->pos(), event->modifiers());
|
|
|
|
emit MouseReleased(&timeline_event);
|
|
}
|
|
|
|
void TimelineView::mouseDoubleClickEvent(QMouseEvent *event)
|
|
{
|
|
TimelineViewMouseEvent timeline_event = CreateMouseEvent(event->pos(), event->modifiers());
|
|
|
|
emit MouseDoubleClicked(&timeline_event);
|
|
}
|
|
|
|
void TimelineView::wheelEvent(QWheelEvent *event)
|
|
{
|
|
if (HandleZoomFromScroll(event)) {
|
|
return;
|
|
} else if (Config::Current()["InvertTimelineScrollAxes"].toBool()) {
|
|
QWheelEvent e(event->pos(),
|
|
event->delta(),
|
|
event->buttons(),
|
|
event->modifiers(),
|
|
event->orientation() == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal);
|
|
|
|
QGraphicsView::wheelEvent(&e);
|
|
} else {
|
|
QGraphicsView::wheelEvent(event);
|
|
}
|
|
}
|
|
|
|
void TimelineView::dragEnterEvent(QDragEnterEvent *event)
|
|
{
|
|
TimelineViewMouseEvent timeline_event = CreateMouseEvent(event->pos(), event->keyboardModifiers());
|
|
|
|
timeline_event.SetMimeData(event->mimeData());
|
|
timeline_event.SetEvent(event);
|
|
|
|
emit DragEntered(&timeline_event);
|
|
}
|
|
|
|
void TimelineView::dragMoveEvent(QDragMoveEvent *event)
|
|
{
|
|
TimelineViewMouseEvent timeline_event = CreateMouseEvent(event->pos(), event->keyboardModifiers());
|
|
|
|
timeline_event.SetMimeData(event->mimeData());
|
|
timeline_event.SetEvent(event);
|
|
|
|
emit DragMoved(&timeline_event);
|
|
}
|
|
|
|
void TimelineView::dragLeaveEvent(QDragLeaveEvent *event)
|
|
{
|
|
emit DragLeft(event);
|
|
}
|
|
|
|
void TimelineView::dropEvent(QDropEvent *event)
|
|
{
|
|
TimelineViewMouseEvent timeline_event = CreateMouseEvent(event->pos(), event->keyboardModifiers());
|
|
|
|
timeline_event.SetMimeData(event->mimeData());
|
|
timeline_event.SetEvent(event);
|
|
|
|
emit DragDropped(&timeline_event);
|
|
}
|
|
|
|
void TimelineView::drawBackground(QPainter *painter, const QRectF &rect)
|
|
{
|
|
if (!connected_track_list_) {
|
|
return;
|
|
}
|
|
|
|
painter->setPen(palette().base().color());
|
|
|
|
int line_y = 0;
|
|
|
|
foreach (TrackOutput* track, connected_track_list_->Tracks()) {
|
|
if (!track) {
|
|
continue;
|
|
}
|
|
|
|
line_y += track->GetTrackHeight();
|
|
|
|
// One px gap between tracks
|
|
line_y++;
|
|
|
|
int this_line_y;
|
|
|
|
if (alignment() & Qt::AlignTop) {
|
|
this_line_y = line_y;
|
|
} else {
|
|
this_line_y = -line_y;
|
|
}
|
|
|
|
painter->drawLine(qRound(rect.left()), this_line_y, qRound(rect.right()), this_line_y);
|
|
}
|
|
}
|
|
|
|
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()), TrackReference(type_, SceneToTrack(pt.y())));
|
|
}
|
|
|
|
TimelineViewMouseEvent TimelineView::CreateMouseEvent(const QPoint& pos, Qt::KeyboardModifiers modifiers)
|
|
{
|
|
QPointF scene_pt = mapToScene(pos);
|
|
|
|
TimelineViewMouseEvent timeline_event(scene_pt.x(),
|
|
scale_,
|
|
timebase(),
|
|
TrackReference(type_, SceneToTrack(scene_pt.y())),
|
|
modifiers);
|
|
|
|
return timeline_event;
|
|
}
|
|
|
|
int TimelineView::GetTrackY(int track_index)
|
|
{
|
|
int y = 0;
|
|
|
|
if (alignment() & Qt::AlignBottom) {
|
|
track_index++;
|
|
}
|
|
|
|
for (int i=0;i<track_index;i++) {
|
|
y += GetTrackHeight(i);
|
|
|
|
// One px line between each track
|
|
y++;
|
|
}
|
|
|
|
if (alignment() & Qt::AlignBottom) {
|
|
y = -y + 1;
|
|
}
|
|
|
|
return y;
|
|
}
|
|
|
|
int TimelineView::GetTrackHeight(int track_index)
|
|
{
|
|
if (!connected_track_list_ || track_index >= connected_track_list_->TrackCount()) {
|
|
return TrackOutput::GetDefaultTrackHeight();
|
|
}
|
|
|
|
return connected_track_list_->TrackAt(track_index)->GetTrackHeight();
|
|
}
|
|
|
|
QPoint TimelineView::GetScrollCoordinates()
|
|
{
|
|
return QPoint(horizontalScrollBar()->value(), verticalScrollBar()->value());
|
|
}
|
|
|
|
void TimelineView::SetScrollCoordinates(const QPoint &pt)
|
|
{
|
|
horizontalScrollBar()->setValue(pt.x());
|
|
verticalScrollBar()->setValue(pt.y());
|
|
}
|
|
|
|
void TimelineView::ConnectTrackList(TrackList *list)
|
|
{
|
|
if (connected_track_list_) {
|
|
disconnect(connected_track_list_, SIGNAL(TrackHeightChanged(int, int)), viewport(), SLOT(update()));
|
|
}
|
|
|
|
connected_track_list_ = list;
|
|
|
|
if (connected_track_list_) {
|
|
connect(connected_track_list_, SIGNAL(TrackHeightChanged(int, int)), viewport(), SLOT(update()));
|
|
}
|
|
}
|
|
|
|
int TimelineView::SceneToTrack(double y)
|
|
{
|
|
int track = -1;
|
|
int heights = 0;
|
|
|
|
if (alignment() & Qt::AlignBottom) {
|
|
y = -y;
|
|
}
|
|
|
|
do {
|
|
track++;
|
|
heights += GetTrackHeight(track);
|
|
} while (y > heights);
|
|
|
|
return track;
|
|
}
|
|
|
|
void TimelineView::UserSetTime(const int64_t &time)
|
|
{
|
|
SetTime(time);
|
|
emit TimeChanged(time);
|
|
}
|