timeline import interaction progress
This commit is contained in:
@@ -41,6 +41,8 @@ TimelineView::TimelineView(QWidget *parent) :
|
||||
setDragMode(RubberBandDrag);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
|
||||
connect(&scene_, SIGNAL(changed(const QList<QRectF>&)), this, SLOT(UpdateSceneRect()));
|
||||
|
||||
// Create playhead line and ensure it's always on top
|
||||
playhead_line_ = new TimelineViewPlayheadItem();
|
||||
playhead_line_->setZValue(100);
|
||||
@@ -51,7 +53,7 @@ TimelineView::TimelineView(QWidget *parent) :
|
||||
SetScale(1.0);
|
||||
}
|
||||
|
||||
void TimelineView::AddBlock(Block *block)
|
||||
void TimelineView::AddBlock(Block *block, int track)
|
||||
{
|
||||
switch (block->type()) {
|
||||
case Block::kClip:
|
||||
@@ -61,7 +63,10 @@ void TimelineView::AddBlock(Block *block)
|
||||
|
||||
// Set up clip with view parameters (clip item will automatically size its rect accordingly)
|
||||
clip_item->SetClip(clip);
|
||||
clip_item->SetY(GetTrackY(track));
|
||||
clip_item->SetHeight(GetTrackHeight(track));
|
||||
clip_item->SetScale(scale_);
|
||||
clip_item->SetTrack(track);
|
||||
|
||||
// Add to list of clip items that can be iterated through
|
||||
clip_items_.insert(clip, clip_item);
|
||||
@@ -119,12 +124,17 @@ void TimelineView::SetTimebase(const rational &timebase)
|
||||
|
||||
void TimelineView::Clear()
|
||||
{
|
||||
scene_.removeItem(playhead_line_);
|
||||
QMapIterator<Block*, TimelineViewRect*> iterator(clip_items_);
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
iterator.next();
|
||||
|
||||
if (iterator.value() != nullptr) {
|
||||
delete iterator.value();
|
||||
}
|
||||
}
|
||||
|
||||
scene_.clear();
|
||||
clip_items_.clear();
|
||||
|
||||
scene_.addItem(playhead_line_);
|
||||
}
|
||||
|
||||
void TimelineView::SetTime(const int64_t time)
|
||||
@@ -173,11 +183,26 @@ void TimelineView::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QGraphicsView::resizeEvent(event);
|
||||
|
||||
if (scene_.height() < height()) {
|
||||
QRectF rect = scene_.sceneRect();
|
||||
rect.setHeight(height() - horizontalScrollBar()->height() - 2);
|
||||
scene_.setSceneRect(rect);
|
||||
UpdateSceneRect();
|
||||
}
|
||||
|
||||
int TimelineView::GetTrackY(int track_index)
|
||||
{
|
||||
int y = 0;
|
||||
|
||||
for (int i=0;i<track_index;i++) {
|
||||
y += GetTrackHeight(i);
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
int TimelineView::GetTrackHeight(int track_index)
|
||||
{
|
||||
// FIXME: Make this adjustable
|
||||
Q_UNUSED(track_index)
|
||||
|
||||
return fontMetrics().height() * 3;
|
||||
}
|
||||
|
||||
void TimelineView::AddGhost(TimelineViewGhostItem *ghost)
|
||||
@@ -192,7 +217,7 @@ bool TimelineView::HasGhosts()
|
||||
return !ghost_items_.isEmpty();
|
||||
}
|
||||
|
||||
rational TimelineView::ScreenToTime(const int &x)
|
||||
rational TimelineView::SceneToTime(const double &x)
|
||||
{
|
||||
// Adjust screen point by scale and timebase
|
||||
int scaled_x_mvmt = qRound(x / scale_ / timebase_dbl_);
|
||||
@@ -201,6 +226,19 @@ rational TimelineView::ScreenToTime(const int &x)
|
||||
return rational(scaled_x_mvmt * timebase_.numerator(), timebase_.denominator());
|
||||
}
|
||||
|
||||
int TimelineView::SceneToTrack(const double &y)
|
||||
{
|
||||
int track = -1;
|
||||
int heights = 0;
|
||||
|
||||
do {
|
||||
track++;
|
||||
heights += GetTrackHeight(track);
|
||||
} while (y > heights);
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
void TimelineView::ClearGhosts()
|
||||
{
|
||||
if (!ghost_items_.isEmpty()) {
|
||||
@@ -221,6 +259,30 @@ void TimelineView::BlockChanged()
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineView::UpdateSceneRect()
|
||||
{
|
||||
QRectF bounding_rect = scene_.itemsBoundingRect();
|
||||
|
||||
// Ensure the scene left and top are always 0
|
||||
bounding_rect.setTopLeft(QPointF(0, 0));
|
||||
|
||||
// Ensure the scene height is always AT LEAST the height of the view
|
||||
int minimum_height = height() - horizontalScrollBar()->height() - 2;
|
||||
if (bounding_rect.height() < minimum_height) {
|
||||
bounding_rect.setHeight(minimum_height);
|
||||
}
|
||||
|
||||
// Ensure playhead is the correct height
|
||||
playhead_line_->UpdateRect();
|
||||
|
||||
// If the scene is already this rect, do nothing
|
||||
if (scene_.sceneRect() == bounding_rect) {
|
||||
return;
|
||||
}
|
||||
|
||||
scene_.setSceneRect(bounding_rect);
|
||||
}
|
||||
|
||||
TimelineView::Tool::Tool(TimelineView *parent) :
|
||||
dragging_(false),
|
||||
parent_(parent)
|
||||
@@ -247,3 +309,13 @@ TimelineView *TimelineView::Tool::parent()
|
||||
{
|
||||
return parent_;
|
||||
}
|
||||
|
||||
QPointF TimelineView::Tool::GetScenePos(const QPoint &screen_pos)
|
||||
{
|
||||
return parent()->mapToScene(screen_pos);
|
||||
}
|
||||
|
||||
QGraphicsItem *TimelineView::Tool::GetItemAtScenePos(const QPointF &scene_pos)
|
||||
{
|
||||
return parent()->scene_.itemAt(scene_pos, parent()->transform());
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ class TimelineView : public QGraphicsView
|
||||
public:
|
||||
TimelineView(QWidget* parent);
|
||||
|
||||
void AddBlock(Block* block);
|
||||
void AddBlock(Block* block, int track);
|
||||
|
||||
void RemoveBlock(Block* block);
|
||||
|
||||
@@ -59,11 +59,7 @@ public slots:
|
||||
void SetTime(const int64_t time);
|
||||
|
||||
signals:
|
||||
void RequestInsertBlockAtIndex(Block* block, int index);
|
||||
|
||||
void RequestPlaceBlock(Block* block, rational start);
|
||||
|
||||
void RequestInsertBlockAtTime(Block* block, rational time);
|
||||
void RequestPlaceBlock(Block* block, rational start, int track);
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
@@ -97,12 +93,17 @@ private:
|
||||
TimelineView* parent();
|
||||
|
||||
protected:
|
||||
QPointF GetScenePos(const QPoint& screen_pos);
|
||||
|
||||
QGraphicsItem* GetItemAtScenePos(const QPointF& scene_pos);
|
||||
|
||||
bool dragging_;
|
||||
|
||||
QPoint drag_start_;
|
||||
QPointF drag_start_;
|
||||
|
||||
private:
|
||||
TimelineView* parent_;
|
||||
|
||||
};
|
||||
|
||||
class PointerTool : public Tool
|
||||
@@ -126,6 +127,9 @@ private:
|
||||
virtual void DragDrop(QDropEvent *event) override;
|
||||
};
|
||||
|
||||
int GetTrackY(int track_index);
|
||||
int GetTrackHeight(int track_index);
|
||||
|
||||
PointerTool pointer_tool_;
|
||||
ImportTool import_tool_;
|
||||
|
||||
@@ -133,7 +137,8 @@ private:
|
||||
|
||||
bool HasGhosts();
|
||||
|
||||
rational ScreenToTime(const int& x);
|
||||
rational SceneToTime(const double &x);
|
||||
int SceneToTrack(const double &y);
|
||||
|
||||
void ClearGhosts();
|
||||
|
||||
@@ -151,6 +156,8 @@ private:
|
||||
|
||||
QVector<TimelineViewGhostItem*> ghost_items_;
|
||||
|
||||
QVector<int> track_heights_;
|
||||
|
||||
TimelineViewPlayheadItem* playhead_line_;
|
||||
|
||||
private slots:
|
||||
@@ -161,6 +168,11 @@ private slots:
|
||||
* derivatives.
|
||||
*/
|
||||
void BlockChanged();
|
||||
|
||||
/**
|
||||
* @brief Slot called whenever the view resizes or the scene contents change to enforce minimum scene sizes
|
||||
*/
|
||||
void UpdateSceneRect();
|
||||
};
|
||||
|
||||
#endif // TIMELINEVIEW_H
|
||||
|
||||
@@ -55,7 +55,7 @@ void TimelineViewClipItem::UpdateRect()
|
||||
double item_left = TimeToScreenCoord(clip_->in());
|
||||
double item_width = TimeToScreenCoord(clip_->length());
|
||||
|
||||
setRect(0, 0, item_width - 1, 64);
|
||||
setRect(0, y_, item_width - 1, height_ - 1);
|
||||
setPos(item_left, 0.0);
|
||||
}
|
||||
|
||||
@@ -63,13 +63,13 @@ void TimelineViewClipItem::paint(QPainter *painter, const QStyleOptionGraphicsIt
|
||||
{
|
||||
Q_UNUSED(widget)
|
||||
|
||||
/*QLinearGradient grad;
|
||||
grad.setStart(0, 0);
|
||||
grad.setFinalStop(0, rect().height());
|
||||
grad.setColorAt(0.0, QColor(192, 192, 255));
|
||||
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));
|
||||
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));
|
||||
|
||||
@@ -102,7 +102,7 @@ void TimelineViewGhostItem::UpdateRect()
|
||||
{
|
||||
rational length = GetAdjustedOut() - GetAdjustedIn();
|
||||
|
||||
setRect(0, 0, TimeToScreenCoord(length), 64);
|
||||
setRect(0, y_, TimeToScreenCoord(length), height_ - 1);
|
||||
|
||||
setPos(TimeToScreenCoord(GetAdjustedIn()), 0);
|
||||
}
|
||||
|
||||
@@ -22,11 +22,47 @@
|
||||
|
||||
TimelineViewRect::TimelineViewRect(QGraphicsItem* parent) :
|
||||
QGraphicsRectItem(parent),
|
||||
scale_(1.0)
|
||||
scale_(1.0),
|
||||
y_(0),
|
||||
height_(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const int &TimelineViewRect::Y()
|
||||
{
|
||||
return y_;
|
||||
}
|
||||
|
||||
void TimelineViewRect::SetY(const int &y)
|
||||
{
|
||||
y_ = y;
|
||||
|
||||
UpdateRect();
|
||||
}
|
||||
|
||||
const int &TimelineViewRect::Height()
|
||||
{
|
||||
return height_;
|
||||
}
|
||||
|
||||
void TimelineViewRect::SetHeight(const int &height)
|
||||
{
|
||||
height_ = height;
|
||||
|
||||
UpdateRect();
|
||||
}
|
||||
|
||||
const int &TimelineViewRect::Track()
|
||||
{
|
||||
return track_;
|
||||
}
|
||||
|
||||
void TimelineViewRect::SetTrack(const int &track)
|
||||
{
|
||||
track_ = track;
|
||||
}
|
||||
|
||||
void TimelineViewRect::SetScale(const double &scale)
|
||||
{
|
||||
scale_ = scale;
|
||||
|
||||
@@ -33,6 +33,15 @@ class TimelineViewRect : public QGraphicsRectItem
|
||||
public:
|
||||
TimelineViewRect(QGraphicsItem* parent = nullptr);
|
||||
|
||||
const int& Y();
|
||||
void SetY(const int& y);
|
||||
|
||||
const int& Height();
|
||||
void SetHeight(const int& height);
|
||||
|
||||
const int& Track();
|
||||
void SetTrack(const int& track);
|
||||
|
||||
void SetScale(const double& scale);
|
||||
|
||||
virtual void UpdateRect() = 0;
|
||||
@@ -41,6 +50,12 @@ protected:
|
||||
double TimeToScreenCoord(const rational& time);
|
||||
|
||||
double scale_;
|
||||
|
||||
int y_;
|
||||
|
||||
int height_;
|
||||
|
||||
int track_;
|
||||
};
|
||||
|
||||
#endif // TIMELINEVIEWRECT_H
|
||||
|
||||
@@ -47,8 +47,11 @@ void TimelineView::ImportTool::DragEnter(QDragEnterEvent *event)
|
||||
quintptr item_ptr;
|
||||
int r;
|
||||
|
||||
// Set drag start position
|
||||
drag_start_ = GetScenePos(event->pos());
|
||||
|
||||
// Set ghosts to start where the cursor entered
|
||||
rational ghost_start = parent()->ScreenToTime(event->pos().x());
|
||||
rational ghost_start = parent()->SceneToTime(drag_start_.x());
|
||||
|
||||
while (!stream.atEnd()) {
|
||||
stream >> r >> item_ptr;
|
||||
@@ -79,8 +82,6 @@ void TimelineView::ImportTool::DragEnter(QDragEnterEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
drag_start_ = event->pos();
|
||||
|
||||
event->accept();
|
||||
} else {
|
||||
// FIXME: Implement dropping from file
|
||||
@@ -93,12 +94,22 @@ void TimelineView::ImportTool::DragMove(QDragMoveEvent *event)
|
||||
if (parent()->HasGhosts()) {
|
||||
// Move ghosts to the mouse cursor
|
||||
foreach (TimelineViewGhostItem* ghost, parent()->ghost_items_) {
|
||||
QPoint movement = event->pos() - drag_start_;
|
||||
QPointF pos = GetScenePos(event->pos());
|
||||
QPointF movement = pos - drag_start_;
|
||||
|
||||
rational time_movement = parent()->ScreenToTime(movement.x());
|
||||
rational time_movement = parent()->SceneToTime(movement.x());
|
||||
|
||||
ghost->SetInAdjustment(time_movement);
|
||||
ghost->SetOutAdjustment(time_movement);
|
||||
|
||||
int ghost_track = parent()->SceneToTrack(pos.y());
|
||||
ghost->SetTrack(ghost_track);
|
||||
|
||||
int ghost_y = parent()->GetTrackY(ghost_track);
|
||||
int ghost_height = parent()->GetTrackHeight(ghost_track);
|
||||
|
||||
ghost->SetY(ghost_y);
|
||||
ghost->SetHeight(ghost_height);
|
||||
}
|
||||
|
||||
event->accept();
|
||||
@@ -130,8 +141,6 @@ void TimelineView::ImportTool::DragDrop(QDropEvent *event)
|
||||
MediaInput* media = new MediaInput();
|
||||
|
||||
// Set parents to node_memory_manager in case no TimelineOutput receives this signal
|
||||
// FIXME: Moving nodes to shared_ptrs might be a better idea, except they all use the QObject system for hierarchy
|
||||
// already...
|
||||
clip->setParent(&node_memory_manager);
|
||||
media->setParent(&node_memory_manager);
|
||||
|
||||
@@ -141,9 +150,9 @@ void TimelineView::ImportTool::DragDrop(QDropEvent *event)
|
||||
NodeParam::ConnectEdge(media->texture_output(), clip->texture_input());
|
||||
|
||||
if (event->keyboardModifiers() & Qt::ControlModifier) {
|
||||
emit parent()->RequestInsertBlockAtTime(clip, ghost->GetAdjustedIn());
|
||||
//emit parent()->RequestInsertBlockAtTime(clip, ghost->GetAdjustedIn());
|
||||
} else {
|
||||
emit parent()->RequestPlaceBlock(clip, ghost->GetAdjustedIn());
|
||||
emit parent()->RequestPlaceBlock(clip, ghost->GetAdjustedIn(), ghost->Track());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,8 +52,10 @@ void TimelineView::PointerTool::MouseMove(QMouseEvent *event)
|
||||
|
||||
if (!dragging_) {
|
||||
|
||||
drag_start_ = GetScenePos(event->pos());
|
||||
|
||||
// Let's see if there's anything selected to drag
|
||||
if (parent()->itemAt(event->pos()) != nullptr) {
|
||||
if (GetItemAtScenePos(drag_start_) != nullptr) {
|
||||
QList<QGraphicsItem*> selected_items = parent()->scene_.selectedItems();
|
||||
|
||||
foreach (QGraphicsItem* item, selected_items) {
|
||||
@@ -62,6 +64,8 @@ void TimelineView::PointerTool::MouseMove(QMouseEvent *event)
|
||||
|
||||
ClipBlock* clip = clip_item->clip();
|
||||
|
||||
ghost->SetY(clip_item->Y());
|
||||
ghost->SetHeight(clip_item->Height());
|
||||
ghost->SetIn(clip->in());
|
||||
ghost->SetOut(clip->out());
|
||||
ghost->SetScale(parent()->scale_);
|
||||
@@ -73,16 +77,16 @@ void TimelineView::PointerTool::MouseMove(QMouseEvent *event)
|
||||
|
||||
parent()->scene_.addItem(ghost);
|
||||
}
|
||||
|
||||
drag_start_ = event->pos();
|
||||
}
|
||||
|
||||
dragging_ = true;
|
||||
|
||||
} else if (!parent()->ghost_items_.isEmpty()) {
|
||||
QPoint movement = event->pos() - drag_start_;
|
||||
QPointF scene_pos = GetScenePos(event->pos());
|
||||
|
||||
rational time_movement = parent()->ScreenToTime(movement.x());
|
||||
QPointF movement = scene_pos - drag_start_;
|
||||
|
||||
rational time_movement = parent()->SceneToTime(movement.x());
|
||||
|
||||
// Validate movement
|
||||
foreach (TimelineViewGhostItem* ghost, parent()->ghost_items_) {
|
||||
|
||||
Reference in New Issue
Block a user