/*** 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 "nodeview.h" NodeView::NodeView(QWidget *parent) : QGraphicsView(parent), graph_(nullptr) { setScene(&scene_); setDragMode(RubberBandDrag); connect(&scene_, SIGNAL(changed(const QList&)), this, SLOT(ItemsChanged())); connect(&scene_, SIGNAL(selectionChanged()), this, SLOT(SceneSelectionChangedSlot())); } void NodeView::SetGraph(NodeGraph *graph) { if (graph_ != nullptr) { disconnect(graph_, SIGNAL(NodeAdded(Node*)), this, SLOT(AddNode(Node*))); disconnect(graph_, SIGNAL(NodeRemoved(Node*)), this, SLOT(RemoveNode(Node*))); disconnect(graph_, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SLOT(AddEdge(NodeEdgePtr))); disconnect(graph_, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SLOT(RemoveEdge(NodeEdgePtr))); } // Clear the scene of all UI objects scene_.clear(); // Set reference to the graph graph_ = graph; // If the graph is valid, add UI objects for each of its Nodes if (graph_ != nullptr) { connect(graph_, SIGNAL(NodeAdded(Node*)), this, SLOT(AddNode(Node*))); connect(graph_, SIGNAL(NodeRemoved(Node*)), this, SLOT(RemoveNode(Node*))); connect(graph_, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SLOT(AddEdge(NodeEdgePtr))); connect(graph_, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SLOT(RemoveEdge(NodeEdgePtr))); QList graph_nodes = graph_->nodes(); foreach (Node* node, graph_nodes) { AddNode(node); } } } NodeViewItem *NodeView::NodeToUIObject(QGraphicsScene *scene, Node *n) { QList graphics_items = scene->items(); for (int i=0;i(graphics_items.at(i)); if (item != nullptr) { if (item->node() == n) { return item; } } } return nullptr; } NodeViewEdge *NodeView::EdgeToUIObject(QGraphicsScene *scene, NodeEdgePtr n) { QList graphics_items = scene->items(); for (int i=0;i(graphics_items.at(i)); if (edge != nullptr) { if (edge->edge() == n) { return edge; } } } return nullptr; } NodeViewItem *NodeView::NodeToUIObject(Node *n) { return NodeToUIObject(&scene_, n); } NodeViewEdge *NodeView::EdgeToUIObject(NodeEdgePtr n) { return EdgeToUIObject(&scene_, n); } void NodeView::AddNode(Node* node) { NodeViewItem* item = new NodeViewItem(); item->SetNode(node); scene_.addItem(item); // Add a NodeViewEdge for each connection QList node_params = node->parameters(); foreach (NodeParam* param, node_params) { // We only bother working with outputs since eventually this will cover all inputs too // (covering both would lead to duplicates since every edge connects to one input and one output) if (param->type() == NodeParam::kOutput) { const QVector& edges = param->edges(); foreach(NodeEdgePtr edge, edges) { AddEdge(edge); } } } } void NodeView::RemoveNode(Node *node) { NodeViewItem* item = NodeToUIObject(scene(), node); delete item; } void NodeView::AddEdge(NodeEdgePtr edge) { NodeViewEdge* edge_ui = new NodeViewEdge(); edge_ui->SetEdge(edge); scene_.addItem(edge_ui); } void NodeView::RemoveEdge(NodeEdgePtr edge) { NodeViewEdge* edge_ui = EdgeToUIObject(scene(), edge); delete edge_ui; } void NodeView::ItemsChanged() { QList items = scene_.items(); foreach (QGraphicsItem* item, items) { NodeViewEdge* edge = dynamic_cast(item); if (edge != nullptr) { edge->Adjust(); } } } void NodeView::SceneSelectionChangedSlot() { // Get the scene's selected items and convert it into a list of selected nodes QList selected_items = scene_.selectedItems(); QList selected_nodes; for (int i=0;i(selected_items.at(i)); if (item != nullptr) { selected_nodes.append(item->node()); } } emit SelectionChanged(selected_nodes); }