From ce58671fd6296f1dca2a4933e26042418431ed80 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Mon, 11 May 2020 22:48:27 +1000 Subject: [PATCH] nodeview: started core node filtering work --- app/panel/node/node.cpp | 5 + app/panel/node/node.h | 2 + app/panel/timeline/timeline.h | 2 +- app/widget/nodeview/nodeview.cpp | 169 +++++++++++++++++-- app/widget/nodeview/nodeview.h | 24 +++ app/widget/nodeview/nodeviewscene.cpp | 11 -- app/widget/nodeview/nodeviewscene.h | 9 - app/widget/timelinewidget/timelinewidget.cpp | 32 +++- app/widget/timelinewidget/timelinewidget.h | 6 +- app/window/mainwindow/mainwindow.cpp | 2 +- 10 files changed, 224 insertions(+), 38 deletions(-) diff --git a/app/panel/node/node.cpp b/app/panel/node/node.cpp index 892b0c32f..72a1c7c23 100644 --- a/app/panel/node/node.cpp +++ b/app/panel/node/node.cpp @@ -88,6 +88,11 @@ void NodePanel::SelectWithDependencies(const QList &nodes) node_view_->SelectWithDependencies(nodes); } +void NodePanel::SelectBlocks(const QList &nodes) +{ + node_view_->SelectBlocks(nodes); +} + void NodePanel::Retranslate() { SetTitle(tr("Node Editor")); diff --git a/app/panel/node/node.h b/app/panel/node/node.h index 9dc9533b8..c2b4f370e 100644 --- a/app/panel/node/node.h +++ b/app/panel/node/node.h @@ -53,6 +53,8 @@ public slots: void Select(const QList& nodes); void SelectWithDependencies(const QList& nodes); + void SelectBlocks(const QList& nodes); + signals: /** * @brief Wrapper for NodeView::SelectionChanged() diff --git a/app/panel/timeline/timeline.h b/app/panel/timeline/timeline.h index 8739b6eb5..bafc9b0d1 100644 --- a/app/panel/timeline/timeline.h +++ b/app/panel/timeline/timeline.h @@ -87,7 +87,7 @@ protected: virtual void Retranslate() override; signals: - void SelectionChanged(const QList& selected_blocks); + void SelectionChanged(const QList& selected_blocks); }; diff --git a/app/widget/nodeview/nodeview.cpp b/app/widget/nodeview/nodeview.cpp index 88fc74040..958be003a 100644 --- a/app/widget/nodeview/nodeview.cpp +++ b/app/widget/nodeview/nodeview.cpp @@ -36,7 +36,8 @@ OLIVE_NAMESPACE_ENTER NodeView::NodeView(QWidget *parent) : HandMovableView(parent), graph_(nullptr), - drop_edge_(nullptr) + drop_edge_(nullptr), + filter_mode_(kFilterShowSelectedBlocks) { setScene(&scene_); SetDefaultDragMode(RubberBandDrag); @@ -65,9 +66,9 @@ void NodeView::SetGraph(NodeGraph *graph) } if (graph_ != nullptr) { - disconnect(graph_, &NodeGraph::NodeAdded, &scene_, &NodeViewScene::AddNode); + disconnect(graph_, &NodeGraph::NodeAdded, this, &NodeView::AddNode); disconnect(graph_, &NodeGraph::NodeRemoved, &scene_, &NodeViewScene::RemoveNode); - disconnect(graph_, &NodeGraph::EdgeAdded, &scene_, &NodeViewScene::AddEdge); + disconnect(graph_, &NodeGraph::EdgeAdded, this, &NodeView::AddEdge); disconnect(graph_, &NodeGraph::EdgeRemoved, &scene_, &NodeViewScene::RemoveEdge); } @@ -80,16 +81,12 @@ void NodeView::SetGraph(NodeGraph *graph) // If the graph is valid, add UI objects for each of its Nodes if (graph_ != nullptr) { - connect(graph_, &NodeGraph::NodeAdded, &scene_, &NodeViewScene::AddNode); + connect(graph_, &NodeGraph::NodeAdded, this, &NodeView::AddNode); connect(graph_, &NodeGraph::NodeRemoved, &scene_, &NodeViewScene::RemoveNode); - connect(graph_, &NodeGraph::EdgeAdded, &scene_, &NodeViewScene::AddEdge); + connect(graph_, &NodeGraph::EdgeAdded, this, &NodeView::AddEdge); connect(graph_, &NodeGraph::EdgeRemoved, &scene_, &NodeViewScene::RemoveEdge); - QList graph_nodes = graph_->nodes(); - - foreach (Node* node, graph_nodes) { - scene_.AddNode(node); - } + AddNodes(graph_->nodes()); } } @@ -185,6 +182,25 @@ void NodeView::SelectWithDependencies(QList nodes) Select(nodes); } +void NodeView::SelectBlocks(const QList &blocks) +{ + selected_blocks_ = blocks; + + if (filter_mode_ == kFilterShowSelectedBlocks) { + UpdateBlockFilter(); + } + + QList nodes; + nodes.reserve(blocks.size()); + + foreach (Block* b, blocks) { + nodes.append(b); + nodes.append(b->GetDependencies()); + } + + SelectWithDependencies(nodes); +} + void NodeView::CopySelected(bool cut) { if (!graph_) { @@ -460,11 +476,19 @@ void NodeView::ShowContextMenu(const QPoint &pos) m.addSeparator(); Menu* filter_menu = new Menu(tr("Filter"), &m); + m.addMenu(filter_menu); + + filter_menu->AddActionWithData(tr("Show All"), + kFilterShowAll, + filter_mode_); + + filter_menu->AddActionWithData(tr("Show Selected Blocks Only"), + kFilterShowSelectedBlocks, + filter_mode_); + + connect(filter_menu, &Menu::triggered, this, &NodeView::ContextMenuFilterChanged); - filter_menu->addAction(tr("Show All"))->setData(NodeViewScene::kFilterShowAll); - filter_menu->addAction(tr("Show Selected Blocks Only"))->setData(NodeViewScene::kFilterShowSelectedBlocks); - m.addSeparator(); Menu* direction_menu = new Menu(tr("Direction"), &m); m.addMenu(direction_menu); @@ -555,6 +579,28 @@ void NodeView::ContextMenuShowFiltersDialog() fd.exec(); } +void NodeView::ContextMenuFilterChanged(QAction *action) +{ + FilterMode filter = static_cast(action->data().toInt()); + + if (filter_mode_ != filter) { + filter_mode_ = filter; + + if (filter == kFilterShowAll) { + // Un-hide all blocks + foreach (NodeViewItem* item, scene_.item_map()) { + item->setVisible(true); + } + + foreach (NodeViewEdge* edge, scene_.edge_map()) { + edge->setVisible(true); + } + } + + ValidateFilter(); + } +} + void NodeView::PlaceNode(NodeViewItem *n, const QPointF &pos) { QRectF destination_rect = n->rect(); @@ -751,4 +797,101 @@ void NodeView::DisconnectSelectionChangedSignal() disconnect(&scene_, &QGraphicsScene::selectionChanged, this, &NodeView::SceneSelectionChangedSlot); } +void NodeView::UpdateBlockFilter() +{ + // Hide all nodes + foreach (NodeViewItem* item, scene_.item_map()) { + item->setVisible(false); + } + + bool first = true; + QRectF last_rect; + + QList all_nodes; + + foreach (Block* b, selected_blocks_) { + scene_.ReorganizeFrom(b); + + QPointF node_pos = b->GetPosition(); + QRectF anchor(node_pos, node_pos); + + all_nodes.append(b); + + QList deps = b->GetDependencies(); + all_nodes.append(deps); + + // Show nodes that are block dependencies + scene_.NodeToUIObject(b)->setVisible(true); + + foreach (Node* d, deps) { + QPointF dep_pos = d->GetPosition(); + + anchor.setLeft(qMin(anchor.left(), dep_pos.x())); + anchor.setRight(qMax(anchor.right(), dep_pos.x())); + anchor.setTop(qMin(anchor.top(), dep_pos.y())); + anchor.setBottom(qMax(anchor.bottom(), dep_pos.y())); + + scene_.NodeToUIObject(d)->setVisible(true); + } + + if (first) { + first = false; + } else { + QPointF desired_anchor_pos = last_rect.bottomRight() + QPointF(0, 2); + + QPointF necessary_movement = anchor.topRight() - desired_anchor_pos; + + b->SetPosition(b->GetPosition() - necessary_movement); + foreach (Node* d, deps) { + d->SetPosition(d->GetPosition() - necessary_movement); + } + } + + last_rect = anchor; + } + + // Show only edges between those dependencies + foreach (NodeViewEdge* edge, scene_.edge_map()) { + edge->setVisible((all_nodes.contains(edge->edge()->input()->parentNode()) + && all_nodes.contains(edge->edge()->output()->parentNode()))); + } +} + +void NodeView::AddNodes(const QList node) +{ + foreach (Node* n, node) { + scene_.AddNode(n); + } + + ValidateFilter(); +} + +void NodeView::AddNode(Node *node) +{ + scene_.AddNode(node); + + ValidateFilter(); +} + +void NodeView::AddEdge(NodeEdgePtr edge) +{ + scene_.AddEdge(edge); + + ValidateFilter(); +} + +void NodeView::ValidateFilter() +{ + // Force auto-positioning + switch (filter_mode_) { + case kFilterShowAll: + // NOTE: Assumes Sequence + scene_.ReorganizeFrom(static_cast(graph_)->viewer_output()); + break; + case kFilterShowSelectedBlocks: + UpdateBlockFilter(); + break; + } +} + OLIVE_NAMESPACE_EXIT diff --git a/app/widget/nodeview/nodeview.h b/app/widget/nodeview/nodeview.h index 8ec3e62ac..06fe381af 100644 --- a/app/widget/nodeview/nodeview.h +++ b/app/widget/nodeview/nodeview.h @@ -61,6 +61,8 @@ public: void Select(const QList& nodes); void SelectWithDependencies(QList nodes); + void SelectBlocks(const QList& blocks); + void CopySelected(bool cut); void Paste(); @@ -98,6 +100,8 @@ private: void ReconnectSelectionChangedSignal(); void DisconnectSelectionChangedSignal(); + void UpdateBlockFilter(); + NodeGraph* graph_; struct AttachedItem { @@ -112,7 +116,22 @@ private: NodeViewScene scene_; + QList selected_blocks_; + + enum FilterMode { + kFilterShowAll, + kFilterShowSelectedBlocks + }; + + FilterMode filter_mode_; + private slots: + void AddNodes(const QList node); + void AddNode(Node* node); + void AddEdge(NodeEdgePtr edge); + + void ValidateFilter(); + /** * @brief Internal function triggered when any change is signalled from the QGraphicsScene * @@ -155,6 +174,11 @@ private slots: */ void ContextMenuShowFiltersDialog(); + /** + * @brief Receiver for the user changing the filter + */ + void ContextMenuFilterChanged(QAction* action); + }; OLIVE_NAMESPACE_EXIT diff --git a/app/widget/nodeview/nodeviewscene.cpp b/app/widget/nodeview/nodeviewscene.cpp index daa38428c..070bff7c1 100644 --- a/app/widget/nodeview/nodeviewscene.cpp +++ b/app/widget/nodeview/nodeviewscene.cpp @@ -219,17 +219,11 @@ void NodeViewScene::AddEdge(NodeEdgePtr edge) addItem(edge_ui); edge_map_.insert(edge.get(), edge_ui); - - // FIXME: Not optimal, fairly brute force/shotgun approach to positioning - ReorganizeFrom(static_cast(graph_)->viewer_output()); } void NodeViewScene::RemoveEdge(NodeEdgePtr edge) { delete edge_map_.take(edge.get()); - - // FIXME: Not optimal, fairly brute force/shotgun approach to positioning - ReorganizeFrom(static_cast(graph_)->viewer_output()); } int NodeViewScene::DetermineWeight(Node *n) @@ -290,11 +284,6 @@ void NodeViewScene::ReorganizeFrom(Node* n) } } -void NodeViewScene::SetFilterMode(const NodeViewScene::FilterMode &f) -{ - filter_mode_ = f; -} - bool NodeViewScene::GetEdgesAreCurved() const { return curved_edges_; diff --git a/app/widget/nodeview/nodeviewscene.h b/app/widget/nodeview/nodeviewscene.h index a27d41a8c..1cb3d1a6c 100644 --- a/app/widget/nodeview/nodeviewscene.h +++ b/app/widget/nodeview/nodeviewscene.h @@ -80,13 +80,6 @@ public: */ void ReorganizeFrom(Node* n); - enum FilterMode { - kFilterShowAll, - kFilterShowSelectedBlocks - }; - - void SetFilterMode(const FilterMode& f); - bool GetEdgesAreCurved() const; public slots: @@ -138,8 +131,6 @@ private: NodeViewCommon::FlowDirection direction_; - FilterMode filter_mode_; - bool curved_edges_; private slots: diff --git a/app/widget/timelinewidget/timelinewidget.cpp b/app/widget/timelinewidget/timelinewidget.cpp index 41a1da410..f2689d1e5 100644 --- a/app/widget/timelinewidget/timelinewidget.cpp +++ b/app/widget/timelinewidget/timelinewidget.cpp @@ -124,7 +124,7 @@ TimelineWidget::TimelineWidget(QWidget *parent) : connect(view, &TimelineView::DragMoved, this, &TimelineWidget::ViewDragMoved); connect(view, &TimelineView::DragLeft, this, &TimelineWidget::ViewDragLeft); connect(view, &TimelineView::DragDropped, this, &TimelineWidget::ViewDragDropped); - connect(view, &TimelineView::SelectionChanged, this, &TimelineWidget::ViewSelectionChanged); + ConnectViewSelectionSignal(view); connect(tview->splitter(), &QSplitter::splitterMoved, this, &TimelineWidget::UpdateHorizontalSplitters); @@ -156,12 +156,22 @@ TimelineWidget::~TimelineWidget() void TimelineWidget::Clear() { + foreach (TimelineAndTrackView* tview, views_) { + DisconnectViewSelectionSignal(tview->view()); + } + QMap::const_iterator iterator; for (iterator=block_items_.begin(); iterator!=block_items_.end(); iterator++) { delete iterator.value(); } block_items_.clear(); + foreach (TimelineAndTrackView* tview, views_) { + ConnectViewSelectionSignal(tview->view()); + } + + emit SelectionChanged(QList()); + SetTimebase(0); } @@ -359,15 +369,23 @@ rational TimelineWidget::GetToolTipTimebase() const void TimelineWidget::SelectAll() { foreach (TimelineAndTrackView* view, views_) { + DisconnectViewSelectionSignal(view->view()); view->view()->SelectAll(); + ConnectViewSelectionSignal(view->view()); } + + ViewSelectionChanged(); } void TimelineWidget::DeselectAll() { foreach (TimelineAndTrackView* view, views_) { + DisconnectViewSelectionSignal(view->view()); view->view()->DeselectAll(); + ConnectViewSelectionSignal(view->view()); } + + emit SelectionChanged(QList()); } void TimelineWidget::RippleToIn() @@ -884,6 +902,16 @@ TrackOutput *TimelineWidget::GetTrackFromReference(const TrackReference &ref) return GetConnectedNode()->track_list(ref.type())->GetTrackAt(ref.index()); } +void TimelineWidget::ConnectViewSelectionSignal(TimelineView *view) +{ + connect(view, &TimelineView::SelectionChanged, this, &TimelineWidget::ViewSelectionChanged); +} + +void TimelineWidget::DisconnectViewSelectionSignal(TimelineView *view) +{ + disconnect(view, &TimelineView::SelectionChanged, this, &TimelineWidget::ViewSelectionChanged); +} + int TimelineWidget::GetTrackY(const TrackReference &ref) { return views_.at(ref.type())->view()->GetTrackY(ref.index()); @@ -1058,7 +1086,7 @@ void TimelineWidget::ViewSelectionChanged() } QList selected_items = GetSelectedBlocks(); - QList selected_blocks; + QList selected_blocks; foreach (TimelineViewBlockItem* item, selected_items) { selected_blocks.append(item->block()); diff --git a/app/widget/timelinewidget/timelinewidget.h b/app/widget/timelinewidget/timelinewidget.h index 6f7b6a41c..3d96b9bfe 100644 --- a/app/widget/timelinewidget/timelinewidget.h +++ b/app/widget/timelinewidget/timelinewidget.h @@ -93,7 +93,7 @@ public: QList GetSelectedBlocks(); signals: - void SelectionChanged(const QList& selected_blocks); + void SelectionChanged(const QList& selected_blocks); protected: virtual void resizeEvent(QResizeEvent *event) override; @@ -453,6 +453,10 @@ private: TrackOutput* GetTrackFromReference(const TrackReference& ref); + void ConnectViewSelectionSignal(TimelineView* view); + + void DisconnectViewSelectionSignal(TimelineView* view); + QList views_; TimeSlider* timecode_label_; diff --git a/app/window/mainwindow/mainwindow.cpp b/app/window/mainwindow/mainwindow.cpp index 008a90ccf..46e71c876 100644 --- a/app/window/mainwindow/mainwindow.cpp +++ b/app/window/mainwindow/mainwindow.cpp @@ -490,7 +490,7 @@ TimelinePanel* MainWindow::AppendTimelinePanel() connect(panel, &PanelWidget::CloseRequested, this, &MainWindow::TimelineCloseRequested); connect(panel, &TimelinePanel::TimeChanged, param_panel_, &ParamPanel::SetTimestamp); connect(panel, &TimelinePanel::TimeChanged, sequence_viewer_panel_, &SequenceViewerPanel::SetTimestamp); - connect(panel, &TimelinePanel::SelectionChanged, node_panel_, &NodePanel::SelectWithDependencies); + connect(panel, &TimelinePanel::SelectionChanged, node_panel_, &NodePanel::SelectBlocks); connect(param_panel_, &ParamPanel::TimeChanged, panel, &TimelinePanel::SetTimestamp); connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, panel, &TimelinePanel::SetTimestamp); connect(sequence_viewer_panel_->video_renderer(), &VideoRenderBackend::CachedTimeReady, panel->ruler(), &TimeRuler::CacheTimeReady);