From c34e6e374b13da5d3301ca622dbea52ed986248d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Taiguara=20Tupinamb=C3=A1s?= Date: Wed, 6 Aug 2025 13:32:36 -0300 Subject: [PATCH 1/5] adds version to Catch2 due to compatibility issues --- external/CMakeLists.txt | 2 +- test/CMakeLists.txt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index d7fbfcca7..0d39af5c9 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -1,5 +1,5 @@ if(BUILD_TESTING) - find_package(Catch2 QUIET) + find_package(Catch2 2.13.7 QUIET) if(NOT Catch2_FOUND) add_subdirectory(Catch2) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 681251330..98a8c306a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,6 +4,8 @@ else() find_package(Qt5 COMPONENTS Test) endif() +find_package(Catch2) + add_executable(test_nodes test_main.cpp src/TestAbstractGraphModel.cpp From 422cdd52e28096976bb9600f3a0e481092f4bc41 Mon Sep 17 00:00:00 2001 From: Gabrielnmds Date: Tue, 5 Aug 2025 14:49:10 -0300 Subject: [PATCH 2/5] adds zoomFitAll and zoomFitSelected methods --- include/QtNodes/internal/GraphicsView.hpp | 4 ++++ src/GraphicsView.cpp | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/QtNodes/internal/GraphicsView.hpp b/include/QtNodes/internal/GraphicsView.hpp index f21c58799..9a657962d 100644 --- a/include/QtNodes/internal/GraphicsView.hpp +++ b/include/QtNodes/internal/GraphicsView.hpp @@ -58,6 +58,10 @@ public Q_SLOTS: virtual void onPasteObjects(); + void zoomFitAll(); + + void zoomFitSelected(); + Q_SIGNALS: void scaleChanged(double scale); diff --git a/src/GraphicsView.cpp b/src/GraphicsView.cpp index c587f081c..4b996b8ec 100644 --- a/src/GraphicsView.cpp +++ b/src/GraphicsView.cpp @@ -434,3 +434,25 @@ QPointF GraphicsView::scenePastePosition() return mapToScene(origin); } + +void GraphicsView::zoomFitAll() +{ + fitInView(scene()->itemsBoundingRect(), Qt::KeepAspectRatio); + //clipCurrentScale(); +} + +void GraphicsView::zoomFitSelected() +{ + if(scene()->selectedItems().count() > 0){ + + QRectF unitedBoundingRect{}; + + for(QGraphicsItem * item : scene()->selectedItems()) + { + unitedBoundingRect = unitedBoundingRect.united(item->mapRectToScene(item->boundingRect())); + } + + fitInView(unitedBoundingRect, Qt::KeepAspectRatio); + //clipCurrentScale(); + } +} From 9fdc3e81e8de20ff1a4235efdb1d8386b843fc59 Mon Sep 17 00:00:00 2001 From: Gabrielnmds Date: Mon, 15 Dec 2025 15:19:03 -0300 Subject: [PATCH 3/5] refactor(zoom fit): minor code fixes --- src/GraphicsView.cpp | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/src/GraphicsView.cpp b/src/GraphicsView.cpp index 4b996b8ec..0ba9f21a0 100644 --- a/src/GraphicsView.cpp +++ b/src/GraphicsView.cpp @@ -75,8 +75,7 @@ QAction *GraphicsView::deleteSelectionAction() const void GraphicsView::setScene(BasicGraphicsScene *scene) { QGraphicsView::setScene(scene); - if (!scene) - { + if (!scene) { // Clear actions. delete _clearSelectionAction; delete _deleteSelectionAction; @@ -181,12 +180,21 @@ void GraphicsView::centerScene() void GraphicsView::contextMenuEvent(QContextMenuEvent *event) { - if (itemAt(event->pos())) { - QGraphicsView::contextMenuEvent(event); - return; + QGraphicsView::contextMenuEvent(event); + QMenu *menu = nullptr; + + bool isZoomFitMenu; + + if (auto *dfModel = dynamic_cast(&nodeScene()->graphModel())) { + if (auto n = qgraphicsitem_cast(itemAt(event->pos()))) { + if (auto *delegate = dfModel->delegateModel(n->nodeId())) { + isZoomFitMenu = delegate->zoomFitMenu(); + } + } } - if (!nodeScene()) return; + if (!nodeScene()) + return; auto const scenePos = mapToScene(event->pos()); @@ -291,14 +299,16 @@ void GraphicsView::setupScale(double scale) void GraphicsView::onDeleteSelectedObjects() { - if (!nodeScene()) return; + if (!nodeScene()) + return; nodeScene()->undoStack().push(new DeleteCommand(nodeScene())); } void GraphicsView::onDuplicateSelectedObjects() { - if (!nodeScene()) return; + if (!nodeScene()) + return; QPointF const pastePosition = scenePastePosition(); @@ -308,14 +318,16 @@ void GraphicsView::onDuplicateSelectedObjects() void GraphicsView::onCopySelectedObjects() { - if (!nodeScene()) return; + if (!nodeScene()) + return; nodeScene()->undoStack().push(new CopyCommand(nodeScene())); } void GraphicsView::onPasteObjects() { - if (!nodeScene()) return; + if (!nodeScene()) + return; QPointF const pastePosition = scenePastePosition(); nodeScene()->undoStack().push(new PasteCommand(nodeScene(), pastePosition)); @@ -360,7 +372,8 @@ void GraphicsView::mouseMoveEvent(QMouseEvent *event) { QGraphicsView::mouseMoveEvent(event); - if (!scene()) return; + if (!scene()) + return; if (scene()->mouseGrabberItem() == nullptr && event->buttons() == Qt::LeftButton) { // Make sure shift is not being pressed @@ -443,13 +456,12 @@ void GraphicsView::zoomFitAll() void GraphicsView::zoomFitSelected() { - if(scene()->selectedItems().count() > 0){ - + if (scene()->selectedItems().count() > 0) { QRectF unitedBoundingRect{}; - for(QGraphicsItem * item : scene()->selectedItems()) - { - unitedBoundingRect = unitedBoundingRect.united(item->mapRectToScene(item->boundingRect())); + for (QGraphicsItem *item : scene()->selectedItems()) { + unitedBoundingRect = unitedBoundingRect.united( + item->mapRectToScene(item->boundingRect())); } fitInView(unitedBoundingRect, Qt::KeepAspectRatio); From f2473e7fd234627297d43f0bc5e8f2395f009ea2 Mon Sep 17 00:00:00 2001 From: Gabrielnmds Date: Wed, 17 Dec 2025 11:56:56 -0300 Subject: [PATCH 4/5] refactor(zoom fit): fixes code conflicts --- .../QtNodes/internal/BasicGraphicsScene.hpp | 6 +- .../QtNodes/internal/NodeDelegateModel.hpp | 6 ++ src/BasicGraphicsScene.cpp | 68 +++++++++++++++++++ src/GraphicsView.cpp | 24 ++++--- 4 files changed, 95 insertions(+), 9 deletions(-) diff --git a/include/QtNodes/internal/BasicGraphicsScene.hpp b/include/QtNodes/internal/BasicGraphicsScene.hpp index 568835ff7..21fea8389 100644 --- a/include/QtNodes/internal/BasicGraphicsScene.hpp +++ b/include/QtNodes/internal/BasicGraphicsScene.hpp @@ -17,7 +17,6 @@ #include #include - class QUndoStack; namespace QtNodes { @@ -112,6 +111,8 @@ class NODE_EDITOR_PUBLIC BasicGraphicsScene : public QGraphicsScene */ virtual QMenu *createSceneMenu(QPointF const scenePos); + QMenu *createZoomMenu(QPointF const scenePos); + Q_SIGNALS: void modified(BasicGraphicsScene *); void nodeMoved(NodeId const nodeId, QPointF const &newLocation); @@ -125,6 +126,9 @@ class NODE_EDITOR_PUBLIC BasicGraphicsScene : public QGraphicsScene /// Signal allows showing custom context menu upon clicking a node. void nodeContextMenu(NodeId const nodeId, QPointF const pos); + /// Signals to call Graphics View's zoomFit methods + void zoomFitAllClicked(); + void zoomFitSelectedClicked(); private: /** diff --git a/include/QtNodes/internal/NodeDelegateModel.hpp b/include/QtNodes/internal/NodeDelegateModel.hpp index 04cc78a12..46dc94cc8 100644 --- a/include/QtNodes/internal/NodeDelegateModel.hpp +++ b/include/QtNodes/internal/NodeDelegateModel.hpp @@ -132,6 +132,10 @@ class NODE_EDITOR_PUBLIC NodeDelegateModel virtual bool resizable() const { return false; } + bool zoomFitMenu() const { return _zoomFitMenu; } + + void setZoomFitMenu(bool state) { _zoomFitMenu = state; } + public Q_SLOTS: virtual void inputConnectionCreated(ConnectionId const &) {} virtual void inputConnectionDeleted(ConnectionId const &) {} @@ -188,6 +192,8 @@ public Q_SLOTS: NodeValidationState _nodeValidationState; NodeProcessingStatus _processingStatus{NodeProcessingStatus::NoStatus}; + + bool _zoomFitMenu{false}; }; } // namespace QtNodes diff --git a/src/BasicGraphicsScene.cpp b/src/BasicGraphicsScene.cpp index 84bf9a314..2fbed3369 100644 --- a/src/BasicGraphicsScene.cpp +++ b/src/BasicGraphicsScene.cpp @@ -11,6 +11,10 @@ #include +#include +#include +#include +#include #include #include @@ -203,6 +207,70 @@ QMenu *BasicGraphicsScene::createSceneMenu(QPointF const scenePos) return nullptr; } +QMenu *BasicGraphicsScene::createZoomMenu(QPointF const scenePos) +{ + Q_UNUSED(scenePos); + + QMenu *menu = new QMenu(); + + auto *txtBox = new QLineEdit(menu); + txtBox->setPlaceholderText(QStringLiteral("Filter")); + txtBox->setClearButtonEnabled(true); + + auto *txtBoxAction = new QWidgetAction(menu); + txtBoxAction->setDefaultWidget(txtBox); + menu->addAction(txtBoxAction); + + QTreeWidget *treeView = new QTreeWidget(menu); + treeView->header()->close(); + + treeView->setMaximumHeight(100); + treeView->setMaximumWidth(150); + + auto *treeViewAction = new QWidgetAction(menu); + treeViewAction->setDefaultWidget(treeView); + menu->addAction(treeViewAction); + + auto freezeItem = new QTreeWidgetItem(treeView); + freezeItem->setText(0, "Zoom Fit All"); + + auto unfreezeItem = new QTreeWidgetItem(treeView); + unfreezeItem->setText(0, "Zoom Fit Selected"); + + treeView->expandAll(); + + connect(treeView, &QTreeWidget::itemClicked, [this, menu](QTreeWidgetItem *item, int) { + if (item->text(0) == "Zoom Fit All") { + Q_EMIT zoomFitAllClicked(); + + menu->close(); + return; + } + if (item->text(0) == "Zoom Fit Selected") { + Q_EMIT zoomFitSelectedClicked(); + + menu->close(); + return; + } + }); + + // Filter + connect(txtBox, &QLineEdit::textChanged, [treeView](const QString &text) { + QTreeWidgetItemIterator it(treeView); + while (*it) { + auto modelName = (*it)->text(0); + const bool match = (modelName.contains(text, Qt::CaseInsensitive)); + (*it)->setHidden(!match); + ++it; + } + }); + + txtBox->setFocus(); + menu->setAttribute(Qt::WA_DeleteOnClose); + + return menu; +} + void BasicGraphicsScene::traverseGraphAndPopulateGraphicsObjects() { auto allNodeIds = _graphModel.allNodeIds(); diff --git a/src/GraphicsView.cpp b/src/GraphicsView.cpp index 0ba9f21a0..57905d002 100644 --- a/src/GraphicsView.cpp +++ b/src/GraphicsView.cpp @@ -2,6 +2,7 @@ #include "BasicGraphicsScene.hpp" #include "ConnectionGraphicsObject.hpp" +#include "DataFlowGraphModel.hpp" #include "NodeGraphicsObject.hpp" #include "StyleCollection.hpp" #include "UndoCommands.hpp" @@ -23,6 +24,7 @@ #include using QtNodes::BasicGraphicsScene; +using QtNodes::DataFlowGraphModel; using QtNodes::GraphicsView; GraphicsView::GraphicsView(QWidget *parent) @@ -161,6 +163,13 @@ void GraphicsView::setScene(BasicGraphicsScene *scene) auto redoAction = scene->undoStack().createRedoAction(this, tr("&Redo")); redoAction->setShortcuts(QKeySequence::Redo); addAction(redoAction); + + /// Connections to context menu funcionality + connect(scene, &BasicGraphicsScene::zoomFitAllClicked, this, &GraphicsView::zoomFitAll); + connect(scene, + &BasicGraphicsScene::zoomFitSelectedClicked, + this, + &GraphicsView::zoomFitSelected); } void GraphicsView::centerScene() @@ -193,16 +202,17 @@ void GraphicsView::contextMenuEvent(QContextMenuEvent *event) } } - if (!nodeScene()) - return; - - auto const scenePos = mapToScene(event->pos()); - - QMenu *menu = nodeScene()->createSceneMenu(scenePos); + if (itemAt(event->pos()) && isZoomFitMenu) { + menu = nodeScene()->createZoomMenu(mapToScene(event->pos())); + } else if (!itemAt(event->pos())) { + menu = nodeScene()->createSceneMenu(mapToScene(event->pos())); + } if (menu) { menu->exec(event->globalPos()); } + + return; } void GraphicsView::wheelEvent(QWheelEvent *event) @@ -451,7 +461,6 @@ QPointF GraphicsView::scenePastePosition() void GraphicsView::zoomFitAll() { fitInView(scene()->itemsBoundingRect(), Qt::KeepAspectRatio); - //clipCurrentScale(); } void GraphicsView::zoomFitSelected() @@ -465,6 +474,5 @@ void GraphicsView::zoomFitSelected() } fitInView(unitedBoundingRect, Qt::KeepAspectRatio); - //clipCurrentScale(); } } From bc1b6cb62a5ff02289c672b38bd8b5f0836aad59 Mon Sep 17 00:00:00 2001 From: Gabrielnmds Date: Wed, 17 Dec 2025 15:37:11 -0300 Subject: [PATCH 5/5] Refactor(node editor): solve conflicts --- external/CMakeLists.txt | 2 +- test/CMakeLists.txt | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 0d39af5c9..d7fbfcca7 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -1,5 +1,5 @@ if(BUILD_TESTING) - find_package(Catch2 2.13.7 QUIET) + find_package(Catch2 QUIET) if(NOT Catch2_FOUND) add_subdirectory(Catch2) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 98a8c306a..681251330 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,8 +4,6 @@ else() find_package(Qt5 COMPONENTS Test) endif() -find_package(Catch2) - add_executable(test_nodes test_main.cpp src/TestAbstractGraphModel.cpp