/*** 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 TimelineView::TimelineView(QWidget *parent) : QGraphicsView(parent), playhead_(0) { setScene(&scene_); setAlignment(Qt::AlignLeft | Qt::AlignVCenter); setDragMode(RubberBandDrag); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); // Set default scale SetScale(1.0); // FIXME: Make CSS configurable playhead_line_ = new QGraphicsLineItem(); playhead_line_->setPen(QPen(Qt::red)); // Ensure playhead line is always on top playhead_line_->setZValue(100); scene_.addItem(playhead_line_); } void TimelineView::AddClip(ClipBlock *clip) { TimelineViewClipItem* clip_item = new TimelineViewClipItem(); // Set up clip with view parameters (clip item will automatically size its rect accordingly) clip_item->SetClip(clip); clip_item->SetTimebase(timebase_); clip_item->SetScale(scale_); // Add to list of clip items that can be iterated through clip_items_.append(clip_item); // Add item to graphics scene scene_.addItem(clip_item); } void TimelineView::SetScale(const double &scale) { scale_ = scale; foreach (TimelineViewClipItem* item, clip_items_) { item->SetScale(scale_); } UpdatePlayheadPosition(); } void TimelineView::SetTimebase(const rational &timebase) { timebase_ = timebase; foreach (TimelineViewClipItem* item, clip_items_) { item->SetTimebase(timebase_); } UpdatePlayheadPosition(); } void TimelineView::Clear() { scene_.removeItem(playhead_line_); scene_.clear(); clip_items_.clear(); scene_.addItem(playhead_line_); } void TimelineView::SetTime(const int64_t time) { playhead_ = time; UpdatePlayheadPosition(); } void TimelineView::mousePressEvent(QMouseEvent *event) { QGraphicsView::mousePressEvent(event); if (itemAt(event->pos()) != nullptr) { QList selected_items = scene_.selectedItems(); foreach (QGraphicsItem* item, selected_items) { TimelineViewGhostItem* ghost = new TimelineViewGhostItem(); TimelineViewClipItem* clip_item = static_cast(item); ghost->setRect(clip_item->rect()); ghost->setPos(clip_item->pos()); ghost_items_.append(ghost); scene_.addItem(ghost); } } } void TimelineView::mouseMoveEvent(QMouseEvent *event) { QGraphicsView::mouseMoveEvent(event); if (!ghost_items_.isEmpty()) { foreach (TimelineViewGhostItem* ghost, ghost_items_) { QPointF scene_pos = mapToScene(event->pos()); ghost->setX(qMax(0.0, scene_pos.x())); } } } void TimelineView::mouseReleaseEvent(QMouseEvent *event) { QGraphicsView::mouseReleaseEvent(event); if (!ghost_items_.isEmpty()) { foreach (TimelineViewGhostItem* ghost, ghost_items_) { delete ghost; } ghost_items_.clear(); } } void TimelineView::UpdatePlayheadPosition() { if (timebase_.denominator() != 0) { double timebase_dbl = timebase_.ToDouble(); double playhead_x = double(playhead_ * timebase_.numerator()) / double(timebase_.denominator()) / timebase_dbl * scale_; playhead_line_->setLine(playhead_x, 0, playhead_x, height()); } }