diff --git a/app/widget/nodeview/nodeview.cpp b/app/widget/nodeview/nodeview.cpp index b27b0b862..5cb1d767c 100644 --- a/app/widget/nodeview/nodeview.cpp +++ b/app/widget/nodeview/nodeview.cpp @@ -140,20 +140,7 @@ void NodeView::SelectAll() ConnectSelectionChangedSignal(); - // Determine which nodes aren't selected and add them to a separate vector - QVector new_selection; - for (auto it=scene_.item_map().cbegin(); it!=scene_.item_map().cend(); it++) { - Node *n = it.key(); - if (!selected_nodes_.contains(n)) { - new_selection.append(n); - } - } - - // Add this vector to our total selection vector - selected_nodes_.append(new_selection); - - // Signal new nodes - emit NodesSelected(new_selection); + UpdateSelectionCache(); } void NodeView::DeselectAll() @@ -175,7 +162,7 @@ void NodeView::DeselectAll() selected_nodes_.clear(); } -void NodeView::Select(QVector nodes, bool center_view_on_item) +void NodeView::Select(const QVector &nodes, bool center_view_on_item) { // Optimization: rather than respond to every single item being selected, ignore the signal and // then handle them all at the end. @@ -186,54 +173,21 @@ void NodeView::Select(QVector nodes, bool center_view_on_item) scene_.DeselectAll(); - // Remove any duplicates - QVector processed; - - NodeViewItem *first_item = nullptr; - - for (Node* n : qAsConst(nodes)) { - if (processed.contains(n)) { - continue; - } - - processed.append(n); - - NodeViewItem* item = scene_.NodeToUIObject(n); - - if (item) { - item->setSelected(true); - - if (!first_item) { - first_item = item; - } - - if (deselections.contains(n)) { - deselections.removeOne(n); - } else { - new_selections.append(n); - } - } + foreach (NodeViewContext *context, scene_.context_map()) { + context->Select(nodes); } + /* // Center on something + Node *first_item = nodes.isEmpty() ? nullptr : nodes.first(); if (center_view_on_item && first_item) { centerOn(first_item); } + */ ConnectSelectionChangedSignal(); - // Emit deselect signal for any nodes that weren't in the list - if (!deselections.isEmpty()) { - emit NodesDeselected(deselections); - } - - // Emit select signal for any nodes that weren't in the list - if (!new_selections.isEmpty()) { - emit NodesSelected(new_selections); - } - - // Update selected list to the list we received - selected_nodes_ = nodes; + UpdateSelectionCache(); } void NodeView::CopySelected(bool cut) @@ -256,7 +210,7 @@ void NodeView::Paste() void NodeView::Duplicate() { - PasteNodesInternal(scene_.GetSelectedNodes()); + PasteNodesInternal(selected_nodes_); } void NodeView::SetColorLabel(int index) @@ -292,7 +246,7 @@ void NodeView::keyPressEvent(QKeyEvent *event) for (Node *n : qAsConst(selected_nodes_)) { for (Node *context : qAsConst(contexts_)) { if (context->ContextContainsNode(n)) { - QPointF old_pos = context->GetNodePositionInContext(n); + Node::Position old_pos = context->GetNodePositionInContext(n); // Determine one pixel in scene units double movement_amt = 1.0 / scale_; @@ -420,7 +374,7 @@ void NodeView::mousePressEvent(QMouseEvent *event) foreach (NodeViewItem *i, selected_items) { // Ignore items attached to the cursor if (!IsItemAttachedToCursor(i)) { - dragging_nodes_.insert(i, i->GetNodePosition()); + dragging_items_.insert(i, i->GetNodePosition()); } } } @@ -554,6 +508,11 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event) } command->add_child(new NodeEdgeAddCommand(creating_output, creating_input)); + + // If the output is not in the input's context, add it now + if (!create_edge_input_item_->GetContext()->ContextContainsNode(creating_output)) { + command->add_child(new NodeSetPositionCommand(creating_output, create_edge_input_item_->GetContext(), scene_.context_map().value(create_edge_input_item_->GetContext())->MapScenePosToNodePosInContext(create_edge_output_item_->scenePos()))); + } } creating_input.Reset(); @@ -640,14 +599,14 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event) DetachItemsFromCursor(); } - for (auto it=dragging_nodes_.cbegin(); it!=dragging_nodes_.cend(); it++) { + for (auto it=dragging_items_.cbegin(); it!=dragging_items_.cend(); it++) { NodeViewItem *i = it.key(); QPointF current_pos = i->GetNodePosition(); if (it.value() != current_pos) { command->add_child(new NodeSetPositionCommand(i->GetNode(), i->GetContext(), current_pos)); } } - dragging_nodes_.clear(); + dragging_items_.clear(); Core::instance()->undo_stack()->pushIfHasChildren(command); @@ -663,37 +622,42 @@ void NodeView::resizeEvent(QResizeEvent *event) void NodeView::UpdateSelectionCache() { - QVector current_selection = scene_.GetSelectedNodes(); + QVector current_selection = scene_.GetSelectedItems(); QVector selected; QVector deselected; // Determine which nodes are newly selected - if (selected_nodes_.isEmpty()) { - // All nodes in the current selection have just been selected - selected = current_selection; - } else { - for (Node* n : qAsConst(current_selection)) { - if (!selected_nodes_.contains(n)) { - selected.append(n); - } + foreach (NodeViewItem* i, current_selection) { + Node *n = i->GetNode(); + if (!selected_nodes_.contains(n)) { + selected.append(n); + selected_nodes_.append(n); } } // Determine which nodes are newly deselected if (current_selection.isEmpty()) { - // All nodes that were selected have been deselected + // All nodes that were selected have been deselected, so we'll just set them all to `deselected` deselected = selected_nodes_; } else { - for (Node* n : qAsConst(selected_nodes_)) { - if (!current_selection.contains(n)) { + foreach (Node* n, selected_nodes_) { + bool still_selected = false; + + foreach (NodeViewItem *i, current_selection) { + if (i->GetNode() == n) { + still_selected = true; + break; + } + } + + if (still_selected) { deselected.append(n); + selected_nodes_.removeOne(n); } } } - selected_nodes_ = current_selection; - if (!selected.isEmpty()) { emit NodesSelected(selected); } @@ -722,7 +686,7 @@ void NodeView::ShowContextMenu(const QPoint &pos) // Label node action QAction* label_action = m.addAction(tr("Label")); connect(label_action, &QAction::triggered, this, [this](){ - Core::instance()->LabelNodes(scene_.GetSelectedNodes()); + Core::instance()->LabelNodes(selected_nodes_); }); // Grouping @@ -807,11 +771,12 @@ void NodeView::ContextMenuSetDirection(QAction *action) void NodeView::OpenSelectedNodeInViewer() { - QVector selected = scene_.GetSelectedNodes(); - ViewerOutput* viewer = selected.isEmpty() ? nullptr : dynamic_cast(selected.first()); - - if (viewer) { - Core::instance()->OpenNodeInViewer(viewer); + // Find first viewer in list of selected nodes and open it + foreach (Node *n, selected_nodes_) { + if (ViewerOutput* viewer = dynamic_cast(n)) { + Core::instance()->OpenNodeInViewer(viewer); + break; + } } } @@ -875,17 +840,6 @@ void NodeView::NodeRemovedFromGraph() contexts_.removeOne(context); } -void NodeView::AttachNodesToCursor(const QVector &nodes) -{ - QVector items(nodes.size()); - - for (int i=0; i& items) { DetachItemsFromCursor(); @@ -974,7 +928,8 @@ bool NodeView::eventFilter(QObject *object, QEvent *event) void NodeView::CopyNodesToClipboardInternal(QXmlStreamWriter *writer, const QVector &nodes, void *userdata) { - writer->writeStartElement(QStringLiteral("pos")); + qDebug() << "STUB!"; + /*writer->writeStartElement(QStringLiteral("pos")); for (Node *n : nodes) { NodeViewItem *item = scene_.item_map().value(n); @@ -987,7 +942,7 @@ void NodeView::CopyNodesToClipboardInternal(QXmlStreamWriter *writer, const QVec writer->writeEndElement(); // node } - writer->writeEndElement(); // pos + writer->writeEndElement(); // pos*/ } void NodeView::PasteNodesFromClipboardInternal(QXmlStreamReader *reader, XMLNodeData &xml_node_data, void *userdata) @@ -1210,25 +1165,4 @@ bool NodeView::IsItemAttachedToCursor(NodeViewItem *item) const return false; } -NodeView::NodeViewAttachNodesToCursor::NodeViewAttachNodesToCursor(NodeView *view, const QVector &nodes) : - view_(view), - nodes_(nodes) -{ -} - -void NodeView::NodeViewAttachNodesToCursor::redo() -{ - view_->AttachNodesToCursor(nodes_); -} - -void NodeView::NodeViewAttachNodesToCursor::undo() -{ - view_->DetachItemsFromCursor(); -} - -Project *NodeView::NodeViewAttachNodesToCursor::GetRelevantProject() const -{ - return nullptr; -} - } diff --git a/app/widget/nodeview/nodeview.h b/app/widget/nodeview/nodeview.h index c2259a780..fd5e2c0c9 100644 --- a/app/widget/nodeview/nodeview.h +++ b/app/widget/nodeview/nodeview.h @@ -63,7 +63,7 @@ public: void SelectAll(); void DeselectAll(); - void Select(QVector nodes, bool center_view_on_item); + void Select(const QVector &nodes, bool center_view_on_item); void CopySelected(bool cut); void Paste(); @@ -120,8 +120,6 @@ protected: virtual void PasteNodesFromClipboardInternal(QXmlStreamReader *reader, XMLNodeData &xml_node_data, void* userdata) override; private: - void AttachNodesToCursor(const QVector &nodes); - void AttachItemsToCursor(const QVector &items); void DetachItemsFromCursor(); @@ -149,25 +147,6 @@ private: bool IsItemAttachedToCursor(NodeViewItem *item) const; - class NodeViewAttachNodesToCursor : public UndoCommand - { - public: - NodeViewAttachNodesToCursor(NodeView* view, const QVector& nodes); - - virtual Project * GetRelevantProject() const override; - - protected: - virtual void redo() override; - - virtual void undo() override; - - private: - NodeView* view_; - - QVector nodes_; - - }; - NodeViewMiniMap *minimap_; struct AttachedItem { @@ -198,7 +177,7 @@ private: QVector last_set_filter_nodes_; QMap context_offsets_; - QMap dragging_nodes_; + QMap dragging_items_; double scale_; diff --git a/app/widget/nodeview/nodeviewcontext.cpp b/app/widget/nodeview/nodeviewcontext.cpp index 947762ee1..b608ee58b 100644 --- a/app/widget/nodeview/nodeviewcontext.cpp +++ b/app/widget/nodeview/nodeviewcontext.cpp @@ -186,6 +186,13 @@ void NodeViewContext::DeleteSelected(NodeViewDeleteCommand *command) } } +void NodeViewContext::Select(const QVector &nodes) +{ + foreach (Node *n, nodes) { + item_map_.value(n)->setSelected(true); + } +} + QVector NodeViewContext::GetSelectedItems() const { QVector items; diff --git a/app/widget/nodeview/nodeviewcontext.h b/app/widget/nodeview/nodeviewcontext.h index 62be15974..cf49b332d 100644 --- a/app/widget/nodeview/nodeviewcontext.h +++ b/app/widget/nodeview/nodeviewcontext.h @@ -30,6 +30,8 @@ public: void DeleteSelected(NodeViewDeleteCommand *command); + void Select(const QVector &nodes); + QVector GetSelectedItems() const; QPointF MapScenePosToNodePosInContext(const QPointF &pos) const; diff --git a/app/widget/nodeview/nodeviewitem.cpp b/app/widget/nodeview/nodeviewitem.cpp index 57f67ddaf..1c645601e 100644 --- a/app/widget/nodeview/nodeviewitem.cpp +++ b/app/widget/nodeview/nodeviewitem.cpp @@ -47,7 +47,6 @@ NodeViewItem::NodeViewItem(Node* n, Node *context, QGraphicsItem *parent) : hide_titlebar_(false), highlighted_index_(-1), flow_dir_(NodeViewCommon::kLeftToRight), - prevent_removing_(false), label_as_output_(false) { // Set flags for this widget diff --git a/app/widget/nodeview/nodeviewitem.h b/app/widget/nodeview/nodeviewitem.h index 974cb1b3e..60d1f3874 100644 --- a/app/widget/nodeview/nodeviewitem.h +++ b/app/widget/nodeview/nodeviewitem.h @@ -122,16 +122,6 @@ public: void SetHighlightedIndex(int index); - void SetPreventRemoving(bool e) - { - prevent_removing_ = e; - } - - bool GetPreventRemoving() const - { - return prevent_removing_; - } - void SetLabelAsOutput(bool e); NodeInput GetInputFromInputConnector(NodeViewItemConnector *connector); @@ -210,8 +200,6 @@ private: QPointF cached_node_pos_; - bool prevent_removing_; - std::vector > input_connectors_; NodeViewItemConnector *output_connector_; diff --git a/app/widget/nodeview/nodeviewscene.cpp b/app/widget/nodeview/nodeviewscene.cpp index 2e422c24b..37a226710 100644 --- a/app/widget/nodeview/nodeviewscene.cpp +++ b/app/widget/nodeview/nodeviewscene.cpp @@ -44,37 +44,16 @@ void NodeViewScene::SetFlowDirection(NodeViewCommon::FlowDirection direction) } } -void NodeViewScene::clear() -{ - // Deselect everything (prevents signals that a selection has changed after deleting an object) - DeselectAll(); - - // HACK: QGraphicsScene contains some sort of internal caching of the selected items which doesn't update unless - // we call a function like this. That means even though we deselect all items above, QGraphicsScene will - // continue to incorrectly signal selectionChanged() when items that were selected (but are now not) get - // deleted. Calling this function appears to update the internal cache and prevent this. - selectedItems(); - - for (auto it=item_map_.cbegin(); it!=item_map_.cend(); it++) { - delete it.value(); - } - item_map_.clear(); -} - void NodeViewScene::SelectAll() { - QList all_items = this->items(); - - foreach (QGraphicsItem* i, all_items) { + foreach (QGraphicsItem* i, items()) { i->setSelected(true); } } void NodeViewScene::DeselectAll() { - QList selected_items = this->selectedItems(); - - foreach (QGraphicsItem* i, selected_items) { + foreach (QGraphicsItem* i, items()) { i->setSelected(false); } } @@ -90,25 +69,6 @@ void NodeViewScene::DeleteSelected() Core::instance()->undo_stack()->push(command); } -NodeViewItem *NodeViewScene::NodeToUIObject(Node *n) -{ - return item_map_.value(n); -} - -QVector NodeViewScene::GetSelectedNodes() const -{ - QHash::const_iterator iterator; - QVector selected; - - for (iterator=item_map_.begin();iterator!=item_map_.end();iterator++) { - if (iterator.value()->isSelected()) { - selected.append(iterator.key()); - } - } - - return selected; -} - QVector NodeViewScene::GetSelectedItems() const { QVector items; @@ -151,31 +111,11 @@ void NodeViewScene::RemoveContext(Node *node) delete context_map_.take(node); } -int NodeViewScene::DetermineWeight(Node *n) -{ - QVector inputs = n->GetImmediateDependencies(); - - int weight = 0; - - foreach (Node* i, inputs) { - if (i->GetNumberOfRoutesTo(n) == 1) { - weight += DetermineWeight(i); - } - } - - return qMax(1, weight); -} - Qt::Orientation NodeViewScene::GetFlowOrientation() const { return NodeViewCommon::GetFlowOrientation(direction_); } -NodeViewCommon::FlowDirection NodeViewScene::GetFlowDirection() const -{ - return direction_; -} - void NodeViewScene::SetEdgesAreCurved(bool curved) { if (curved_edges_ != curved) { diff --git a/app/widget/nodeview/nodeviewscene.h b/app/widget/nodeview/nodeviewscene.h index b9949d59c..467109923 100644 --- a/app/widget/nodeview/nodeviewscene.h +++ b/app/widget/nodeview/nodeviewscene.h @@ -37,27 +37,11 @@ class NodeViewScene : public QGraphicsScene public: NodeViewScene(QObject *parent = nullptr); - void clear(); - void SelectAll(); void DeselectAll(); void DeleteSelected(); - /** - * @brief Retrieve the graphical widget corresponding to a specific Node - * - * In situations where you know what Node you're working with but need the UI object (e.g. for positioning), this - * static function will retrieve the NodeViewItem (Node UI representation) connected to this Node in a certain - * QGraphicsScene. This can be called from any other UI object, since it'll have a reference to the QGraphicsScene - * through QGraphicsItem::scene(). - * - * If the scene does not contain a widget for this node (usually meaning the node's graph is not the active graph - * in this view/scene), this function returns nullptr. - */ - NodeViewItem* NodeToUIObject(Node* n); - - QVector GetSelectedNodes() const; QVector GetSelectedItems() const; const QHash &context_map() const @@ -65,14 +49,13 @@ public: return context_map_; } - const QHash& item_map() const - { - return item_map_; - } - Qt::Orientation GetFlowOrientation() const; - NodeViewCommon::FlowDirection GetFlowDirection() const; + NodeViewCommon::FlowDirection GetFlowDirection() const + { + return direction_; + } + void SetFlowDirection(NodeViewCommon::FlowDirection direction); bool GetEdgesAreCurved() const @@ -90,12 +73,8 @@ public slots: void SetEdgesAreCurved(bool curved); private: - static int DetermineWeight(Node* n); - QHash context_map_; - QHash item_map_; - NodeGraph* graph_; NodeViewCommon::FlowDirection direction_;