From 0508acc6133c5abb49ced38feebe9f7bd284cc4c Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Fri, 2 Oct 2020 17:10:15 +1000 Subject: [PATCH] timeline: began crude edit tool functionality --- app/node/block/block.cpp | 5 ++ app/node/block/block.h | 2 + app/widget/timelinewidget/timelinewidget.cpp | 71 ++++++++++++++----- app/widget/timelinewidget/timelinewidget.h | 17 +++++ app/widget/timelinewidget/tool/edit.cpp | 38 +++++++++- app/widget/timelinewidget/tool/pointer.cpp | 7 +- .../timelinewidget/view/timelineview.cpp | 19 +++++ app/widget/timelinewidget/view/timelineview.h | 7 ++ .../view/timelineviewblockitem.cpp | 4 -- 9 files changed, 143 insertions(+), 27 deletions(-) diff --git a/app/node/block/block.cpp b/app/node/block/block.cpp index 85df9aa3b..79264c572 100644 --- a/app/node/block/block.cpp +++ b/app/node/block/block.cpp @@ -122,6 +122,11 @@ void Block::set_length_and_media_in(const rational &length) LengthChangedEvent(old_length, length, Timeline::kTrimIn); } +TimeRange Block::range() const +{ + return TimeRange(in(), out()); +} + Block *Block::previous() { return previous_; diff --git a/app/node/block/block.h b/app/node/block/block.h index 7fa036302..ca5c700ee 100644 --- a/app/node/block/block.h +++ b/app/node/block/block.h @@ -54,6 +54,8 @@ public: void set_length_and_media_out(const rational &length); void set_length_and_media_in(const rational &length); + TimeRange range() const; + Block* previous(); Block* next(); void set_previous(Block* previous); diff --git a/app/widget/timelinewidget/timelinewidget.cpp b/app/widget/timelinewidget/timelinewidget.cpp index 6bb7c11b2..b21bf6092 100644 --- a/app/widget/timelinewidget/timelinewidget.cpp +++ b/app/widget/timelinewidget/timelinewidget.cpp @@ -107,6 +107,7 @@ TimelineWidget::TimelineWidget(QWidget *parent) : view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); view->SetSnapService(this); + view->SetSelectionList(&selections_); view_splitter_->addWidget(tview); @@ -165,7 +166,7 @@ void TimelineWidget::Clear() QMap::const_iterator iterator; for (iterator=block_items_.begin(); iterator!=block_items_.end(); iterator++) { - if (iterator.value()->isSelected()) { + if (IsItemSelected(iterator.value())) { deselected_blocks.append(iterator.key()); } @@ -384,8 +385,8 @@ void TimelineWidget::SelectAll() QMap::const_iterator i; for (i=block_items_.constBegin(); i!=block_items_.end(); i++) { - if (!i.value()->isSelected()) { - i.value()->setSelected(true); + if (!IsItemSelected(i.value())) { + AddSelection(i.value()); blocks_selected.append(i.key()); } } @@ -400,8 +401,8 @@ void TimelineWidget::DeselectAll() QMap::const_iterator i; for (i=block_items_.constBegin(); i!=block_items_.end(); i++) { - if (i.value()->isSelected()) { - i.value()->setSelected(false); + if (IsItemSelected(i.value())) { + RemoveSelection(i.value()); blocks_deselected.append(i.key()); } } @@ -791,7 +792,7 @@ QList TimelineWidget::GetSelectedBlocks() TimelineViewBlockItem* item = iterator.value(); - if (item && item->isSelected()) { + if (item && IsItemSelected(item)) { list.append(item); } } @@ -893,9 +894,8 @@ void TimelineWidget::ViewMouseReleased(TimelineViewMouseEvent *event) void TimelineWidget::ViewMouseDoubleClicked(TimelineViewMouseEvent *event) { - if (GetConnectedNode() && active_tool_ != nullptr) { - active_tool_->MouseDoubleClick(event); - active_tool_ = nullptr; + if (GetConnectedNode()) { + GetActiveTool()->MouseDoubleClick(event); } } @@ -968,7 +968,7 @@ void TimelineWidget::RemoveBlock(const QList &blocks) TimelineViewBlockItem* item = block_items_.take(b); delete_items.append(item); - if (item->isSelected()) { + if (IsItemSelected(item)) { deselect_blocks.append(b); } } @@ -1211,8 +1211,14 @@ void TimelineWidget::SetBlockLinksSelected(Block* block, bool selected) TimelineViewBlockItem* link_item; foreach (Block* link, block->linked_clips()) { - if ((link_item = block_items_[link]) != nullptr) { - link_item->setSelected(selected); + link_item = block_items_.value(link); + + if (link_item) { + if (selected) { + AddSelection(link_item); + } else { + RemoveSelection(link_item); + } } } } @@ -1383,7 +1389,7 @@ void TimelineWidget::StartRubberBandSelect(bool enable_selecting, bool select_li // We don't touch any blocks that are already selected. If you want these to be deselected by // default, call DeselectAll() befoer calling StartRubberBandSelect() foreach (TimelineViewBlockItem* block, block_items_) { - if (block->isSelected()) { + if (IsItemSelected(block)) { rubberband_already_selected_.append(block); } } @@ -1428,7 +1434,11 @@ void TimelineWidget::MoveRubberBandSelect(bool enable_selecting, bool select_lin } foreach (QGraphicsItem* item, rubberband_now_selected_) { - item->setSelected(false); + TimelineViewBlockItem* block_item = dynamic_cast(item); + + if (block_item) { + RemoveSelection(block_item); + } } // Cache limit because we append to this array in this loop and don't need to process those @@ -1446,7 +1456,7 @@ void TimelineWidget::MoveRubberBandSelect(bool enable_selecting, bool select_lin // Since new_selected_list is filtered by rubberband_already_selected_, this should certainly // be deselected by now - block_item->setSelected(true); + AddSelection(block_item); if (select_links) { // Select the block's links @@ -1456,7 +1466,7 @@ void TimelineWidget::MoveRubberBandSelect(bool enable_selecting, bool select_lin TimelineViewBlockItem* link_item; foreach (Block* link, b->linked_clips()) { if ((link_item = block_items_[link]) != nullptr) { - link_item->setSelected(true); + AddSelection(link_item); if (!new_selected_list.contains(link_item) && !rubberband_already_selected_.contains(link_item)) { @@ -1485,6 +1495,35 @@ void TimelineWidget::EndRubberBandSelect() rubberband_already_selected_.clear(); } +void TimelineWidget::AddSelection(const TimeRange &time, const TrackReference &track) +{ + selections_[track].InsertTimeRange(time); + + views_.at(track.type())->view()->viewport()->update(); +} + +void TimelineWidget::AddSelection(TimelineViewBlockItem *item) +{ + AddSelection(item->block()->range(), item->Track()); +} + +void TimelineWidget::RemoveSelection(const TimeRange &time, const TrackReference &track) +{ + selections_[track].RemoveTimeRange(time); + + views_.at(track.type())->view()->viewport()->update(); +} + +void TimelineWidget::RemoveSelection(TimelineViewBlockItem *item) +{ + RemoveSelection(item->block()->range(), item->Track()); +} + +bool TimelineWidget::IsItemSelected(TimelineViewBlockItem *item) const +{ + return selections_[item->Track()].ContainsTimeRange(item->block()->range()); +} + struct SnapData { rational time; rational movement; diff --git a/app/widget/timelinewidget/timelinewidget.h b/app/widget/timelinewidget/timelinewidget.h index d03b1e5a3..f7121af03 100644 --- a/app/widget/timelinewidget/timelinewidget.h +++ b/app/widget/timelinewidget/timelinewidget.h @@ -361,6 +361,13 @@ private: virtual void MousePress(TimelineViewMouseEvent *event) override; virtual void MouseMove(TimelineViewMouseEvent *event) override; virtual void MouseRelease(TimelineViewMouseEvent *event) override; + virtual void MouseDoubleClick(TimelineViewMouseEvent *event) override; + + private: + QHash start_selections_; + + TimelineCoordinate start_coord_; + }; class RazorTool : public BeamTool @@ -481,6 +488,16 @@ private: QList rubberband_already_selected_; QList rubberband_now_selected_; + QHash selections_; + + void AddSelection(const TimeRange& time, const TrackReference& track); + void AddSelection(TimelineViewBlockItem* item); + + void RemoveSelection(const TimeRange& time, const TrackReference& track); + void RemoveSelection(TimelineViewBlockItem* item); + + bool IsItemSelected(TimelineViewBlockItem* item) const; + Tool* GetActiveTool(); QVector tools_; diff --git a/app/widget/timelinewidget/tool/edit.cpp b/app/widget/timelinewidget/tool/edit.cpp index cb804bebc..e8b79f312 100644 --- a/app/widget/timelinewidget/tool/edit.cpp +++ b/app/widget/timelinewidget/tool/edit.cpp @@ -29,17 +29,49 @@ TimelineWidget::EditTool::EditTool(TimelineWidget* parent) : void TimelineWidget::EditTool::MousePress(TimelineViewMouseEvent *event) { - Q_UNUSED(event) + if (!(event->GetModifiers() & Qt::ShiftModifier)) { + parent()->DeselectAll(); + } } void TimelineWidget::EditTool::MouseMove(TimelineViewMouseEvent *event) { - Q_UNUSED(event) + if (dragging_) { + parent()->selections_ = start_selections_; + parent()->AddSelection(TimeRange(start_coord_.GetFrame(), event->GetFrame()), + start_coord_.GetTrack()); + } else { + start_selections_ = parent()->selections_; + + dragging_ = true; + + start_coord_ = event->GetCoordinates(true); + + // Snap if we're snapping + if (Core::instance()->snapping()) { + rational movement; + parent()->SnapPoint({start_coord_.GetFrame()}, &movement); + if (!movement.isNull()) { + start_coord_.SetFrame(start_coord_.GetFrame() + movement); + } + } + + dragging_ = true; + } } void TimelineWidget::EditTool::MouseRelease(TimelineViewMouseEvent *event) { - Q_UNUSED(event) + dragging_ = false; +} + +void TimelineWidget::EditTool::MouseDoubleClick(TimelineViewMouseEvent *event) +{ + TimelineViewBlockItem* item = GetItemAtScenePos(event->GetCoordinates()); + + if (item && !parent()->GetTrackFromReference(item->Track())->IsLocked()) { + parent()->AddSelection(item); + } } OLIVE_NAMESPACE_EXIT diff --git a/app/widget/timelinewidget/tool/pointer.cpp b/app/widget/timelinewidget/tool/pointer.cpp index 200c0aa6d..186b8e93e 100644 --- a/app/widget/timelinewidget/tool/pointer.cpp +++ b/app/widget/timelinewidget/tool/pointer.cpp @@ -52,7 +52,6 @@ void TimelineWidget::PointerTool::MousePress(TimelineViewMouseEvent *event) clicked_item_ = GetItemAtScenePos(event->GetCoordinates()); bool selectable_item = (clicked_item_ - && clicked_item_->flags() & QGraphicsItem::ItemIsSelectable && !parent()->GetTrackFromReference(clicked_item_->Track())->IsLocked()); if (selectable_item) { @@ -76,14 +75,14 @@ void TimelineWidget::PointerTool::MousePress(TimelineViewMouseEvent *event) } // If this item is already selected, no further selection needs to be made - if (clicked_item_->isSelected()) { + if (parent()->IsItemSelected(clicked_item_)) { // Collect item deselections QList deselected_blocks; // If shift is held, deselect it if (event->GetModifiers() & Qt::ShiftModifier) { - clicked_item_->setSelected(false); + parent()->RemoveSelection(clicked_item_); deselected_blocks.append(clicked_item_->block()); // If not holding alt, deselect all links as well @@ -110,7 +109,7 @@ void TimelineWidget::PointerTool::MousePress(TimelineViewMouseEvent *event) QList selected_blocks; // Select this item - clicked_item_->setSelected(true); + parent()->AddSelection(clicked_item_); selected_blocks.append(clicked_item_->block()); // If not holding alt, select all links as well diff --git a/app/widget/timelinewidget/view/timelineview.cpp b/app/widget/timelinewidget/view/timelineview.cpp index 4b60ec0b7..2f1d5c6e0 100644 --- a/app/widget/timelinewidget/view/timelineview.cpp +++ b/app/widget/timelinewidget/view/timelineview.cpp @@ -37,6 +37,7 @@ OLIVE_NAMESPACE_ENTER TimelineView::TimelineView(Qt::Alignment vertical_alignment, QWidget *parent) : TimelineViewBase(parent), + selections_(nullptr), show_beam_cursor_(false), connected_track_list_(nullptr) { @@ -242,6 +243,24 @@ void TimelineView::drawForeground(QPainter *painter, const QRectF &rect) cursor_x, track_y + GetTrackHeight(track_index)); } + + if (selections_ && !selections_->isEmpty()) { + painter->setPen(Qt::NoPen); + painter->setBrush(QColor(0, 0, 0, 64)); + + for (auto it=selections_->cbegin(); it!=selections_->cend(); it++) { + if (it.key().type() == connected_track_list_->type()) { + int track_index = it.key().index(); + + foreach (const TimeRange& range, it.value()) { + painter->drawRect(TimeToScene(range.in()), + GetTrackY(track_index), + TimeToScene(range.length()), + GetTrackHeight(track_index)); + } + } + } + } } void TimelineView::ToolChangedEvent(Tool::Item tool) diff --git a/app/widget/timelinewidget/view/timelineview.h b/app/widget/timelinewidget/view/timelineview.h index e409b425d..67606dcea 100644 --- a/app/widget/timelinewidget/view/timelineview.h +++ b/app/widget/timelinewidget/view/timelineview.h @@ -59,6 +59,11 @@ public: void SetBeamCursor(const TimelineCoordinate& coord); + void SetSelectionList(QHash* s) + { + selections_ = s; + } + signals: void MousePressed(TimelineViewMouseEvent* event); void MouseMoved(TimelineViewMouseEvent* event); @@ -108,6 +113,8 @@ private: void UpdatePlayheadRect(); + QHash* selections_; + bool show_beam_cursor_; TimelineCoordinate cursor_coord_; diff --git a/app/widget/timelinewidget/view/timelineviewblockitem.cpp b/app/widget/timelinewidget/view/timelineviewblockitem.cpp index 790e1c59e..3d1225e11 100644 --- a/app/widget/timelinewidget/view/timelineviewblockitem.cpp +++ b/app/widget/timelinewidget/view/timelineviewblockitem.cpp @@ -43,10 +43,6 @@ TimelineViewBlockItem::TimelineViewBlockItem(Block *block, QGraphicsItem* parent { setBrush(Qt::white); setCursor(Qt::DragMoveCursor); - setFlag(QGraphicsItem::ItemIsSelectable, - block_->type() == Block::kClip - || block_->type() == Block::kGap - || block_->type() == Block::kTransition); UpdateRect(); }