/*** 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 "timelineview.h" #include #include #include #include #include #include #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(Qt::Alignment vertical_alignment, QWidget *parent) : TimelineViewBase(parent), connected_track_list_(nullptr) { 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); viewport()->setMouseTracking(true); } void TimelineView::SelectAll() { QList all_items = items(); foreach (QGraphicsItem* i, all_items) { i->setSelected(true); } } void TimelineView::DeselectAll() { QList 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); } } void TimelineView::ToolChangedEvent(Tool::Item tool) { switch (tool) { case Tool::kRazor: setCursor(Qt::SplitHCursor); break; case Tool::kEdit: setCursor(Qt::IBeamCursor); break; case Tool::kAdd: case Tool::kTransition: case Tool::kZoom: setCursor(Qt::CrossCursor); break; default: unsetCursor(); } } Timeline::TrackType TimelineView::ConnectedTrackType() { if (connected_track_list_) { return connected_track_list_->type(); } return Timeline::kTrackTypeNone; } Stream::Type TimelineView::TrackTypeToStreamType(Timeline::TrackType track_type) { switch (track_type) { case Timeline::kTrackTypeNone: case Timeline::kTrackTypeCount: break; case Timeline::kTrackTypeVideo: return Stream::kVideo; case Timeline::kTrackTypeAudio: return Stream::kAudio; case Timeline::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(ConnectedTrackType(), SceneToTrack(pt.y()))); } TimelineViewMouseEvent TimelineView::CreateMouseEvent(const QPoint& pos, Qt::KeyboardModifiers modifiers) { QPointF scene_pt = mapToScene(pos); TimelineViewMouseEvent timeline_event(scene_pt.x(), GetScale(), timebase(), TrackReference(ConnectedTrackType(), 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= 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); }