Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
2edfb0b
Updates fork from upstream
tatatupi Jun 20, 2025
988ce45
wip: adds NodeValidationState info to NodeDelegateModel
tatatupi Jun 22, 2025
1c84750
makes the nodeObject red in case of invalid state and adds a tooltip …
tatatupi Jun 22, 2025
3007c23
adds warning state and adapts calculator example
tatatupi Jun 22, 2025
129d414
adds validation icon and adapts calculation example
tatatupi Jun 22, 2025
e1d7023
improves NodeValidationState struct
tatatupi Jun 23, 2025
2e91091
qt6 for linux-gcc
tatatupi Jun 23, 2025
e0b0c4a
core improvements to develop node processing status
g-abilio Jul 14, 2025
e002f5b
first commit on the creation of a processing status example
g-abilio Jul 15, 2025
985b638
fixes nodeprocessingstatus cast
tatatupi Jul 15, 2025
3f55e35
creation of random gen example, and fix of icon color
g-abilio Jul 16, 2025
50c6bec
Connect delegate UI update signal
tatatupi Jul 17, 2025
1c09ecf
fix random number node dynamic
g-abilio Jul 17, 2025
50ce760
Merge pull request #5 from fabns-nano/codex/add-signal-for-ui-updates…
g-abilio Jul 17, 2025
f2c120f
clean up test code in multiplication node
g-abilio Jul 17, 2025
965eb15
Add per-node background color API
hudsonmiranda291 Jul 22, 2025
545c018
Updates fork from upstream
Gabrielnmds Aug 5, 2025
550be10
updates from upstream
Gabrielnmds Aug 5, 2025
9a48404
refactor(node delegate model): remove unnecessary lines of code
Gabrielnmds Aug 5, 2025
97b0638
first try to replicate nodegroup schema
g-abilio Aug 26, 2025
4f862bd
fix errors in building, as well as include TODO methods
g-abilio Aug 28, 2025
57d595d
improves in grouping structure, as well as future TODO methods
g-abilio Aug 29, 2025
0dbe816
adapts setHovered method from v1 to v3
Gabrielnmds Sep 1, 2025
97d48d5
Merge branch 'paceholder:master' into master
tatatupi Sep 2, 2025
24f0780
replicate v1 grouping calls schema in v3 basicgraphicsscene
g-abilio Sep 2, 2025
da27d38
solve TODO methods in NodeGroup
g-abilio Sep 3, 2025
7f1e7c0
Fixes methods in Node Graphics Object from v1 to v3
Gabrielnmds Sep 5, 2025
89ac7f2
Merge branch 'master' of https://github.com/paceholder/nodeeditor
tatatupi Sep 5, 2025
e52b7ed
solve correct usage of nodeId in save method
g-abilio Sep 8, 2025
fbe43d7
solve TODO methods and generate a connection to create a node group
g-abilio Sep 9, 2025
37c3bf8
solves conflict
tatatupi Sep 10, 2025
b23ecc3
revert unnecessary changes in multiplication model
tatatupi Sep 10, 2025
0a35f76
revert unnecessary changes
tatatupi Sep 10, 2025
a9be092
solve icon size and refactor NodeProcessingStatus code
g-abilio Sep 11, 2025
5530b72
update and merge new code
g-abilio Sep 11, 2025
03e311a
remove duplicate code
g-abilio Sep 11, 2025
a87ceb2
add space to better organize processing status in node display
g-abilio Sep 15, 2025
ae3715b
remove processing value default value
g-abilio Sep 19, 2025
eedc666
fix bugs in node processing status
g-abilio Sep 19, 2025
1298605
add Q_DECLARE_METATYPE to solve linux build problems
g-abilio Sep 24, 2025
47d948f
declaring metatype in the correct place
g-abilio Sep 24, 2025
cc9c95d
add group menu and fix std menu signature
g-abilio Sep 25, 2025
d4812ed
add correct menu creation dynamics
g-abilio Sep 25, 2025
4cbd243
reimplement loadNodeToMap and loadConnectionToMap in v3
Gabrielnmds Sep 26, 2025
d7b6a92
add the functionality of the add to group submenu
g-abilio Sep 26, 2025
1b16810
add correct cut action
g-abilio Sep 26, 2025
88a34ed
solve undefined behavior at the menu creation
g-abilio Sep 26, 2025
ffb73f5
solve copy and cut commands for node groups
g-abilio Sep 26, 2025
3814dce
add padlock feature
g-abilio Sep 29, 2025
a262354
solve copy/past command not saving connections inside a group
g-abilio Sep 29, 2025
177a224
fix save and load for node groups
Gabrielnmds Oct 3, 2025
5cd3c65
change delete shortcut and add standard cut shortcut
g-abilio Oct 6, 2025
a330f40
sync with previous group changes
g-abilio Oct 6, 2025
42d2c63
pull upstream changes
g-abilio Oct 7, 2025
6eb2198
remove unnecessary comments
g-abilio Oct 7, 2025
25007c0
add save/load of group files
g-abilio Oct 7, 2025
19d7169
add correct group saving
g-abilio Oct 8, 2025
7cd2d4c
fix ctrl+z bug in node groups
g-abilio Oct 8, 2025
4bc2264
add flag to make group usage optional
g-abilio Oct 9, 2025
7aebc0b
set group node flag false
Gabrielnmds Oct 9, 2025
2083a64
solve info-tooltip svg file problem
g-abilio Oct 10, 2025
2189e77
Merge branch 'node_group' of github.com:fabns-nano/nodeeditor2 into n…
g-abilio Oct 10, 2025
1d93313
solve mistakes in modules usage
g-abilio Oct 10, 2025
4c33dd8
minor error fixes
g-abilio Oct 10, 2025
354743e
fix on errors in macos building
g-abilio Oct 10, 2025
616e9af
add node group test suite
g-abilio Oct 13, 2025
88234d0
add test suite to cmake
g-abilio Oct 13, 2025
837954f
Add description to created methods
Gabrielnmds Oct 13, 2025
b33275a
add docstring to BasicGraphicsScene methods
g-abilio Oct 13, 2025
4e7e167
Merge branch 'node_group' of github.com:fabns-nano/nodeeditor2 into n…
g-abilio Oct 13, 2025
21b55ac
Merge pull request #6 from fabns-nano/node_processing_status
g-abilio Oct 20, 2025
2ddee6f
change group identifier to unsigned int
g-abilio Nov 11, 2025
4f1b23c
fix undocommands module inclusion
g-abilio Dec 3, 2025
87e219b
solve conflicts
g-abilio Dec 3, 2025
dea439b
Merge pull request #7 from fabns-nano/codex/expose-setbackgroundcolor…
g-abilio Dec 3, 2025
cc81264
Adds node nickname functionality (#11)
g-abilio Dec 11, 2025
741a57e
solve conflicts
g-abilio Jan 14, 2026
9f31b18
solve conflicts
g-abilio Jan 27, 2026
b2e1db5
revert unnecessary commit
g-abilio Jan 27, 2026
0ee5052
remove unnecessary changes
g-abilio Jan 27, 2026
94a363b
minor fixes
g-abilio Jan 27, 2026
be91633
fix undesired changes
g-abilio Jan 28, 2026
3253acf
fix undesired changes
g-abilio Jan 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/cmake_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ jobs:
- toolchain: linux-gcc
os: ubuntu-22.04
compiler: gcc
qt_version: "5.15.2"
qt_version: "6.3.0"
modules: ""
use_qt6: "OFF"
use_qt6: "ON"

- toolchain: macos-clang
os: macos-latest
Expand Down
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ set(CPP_SOURCE_FILES
src/StyleCollection.cpp
src/UndoCommands.cpp
src/locateNode.cpp
src/GroupGraphicsObject.cpp
src/NodeGroup.cpp
resources/resources.qrc
)

Expand Down Expand Up @@ -127,6 +129,8 @@ set(HPP_HEADER_FILES
include/QtNodes/internal/DefaultVerticalNodeGeometry.hpp
include/QtNodes/internal/NodeConnectionInteraction.hpp
include/QtNodes/internal/UndoCommands.hpp
include/QtNodes/internal/NodeGroup.hpp
include/QtNodes/internal/GroupGraphicsObject.hpp
)

# If we want to give the option to build a static library,
Expand Down
5 changes: 5 additions & 0 deletions examples/calculator/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ int main(int argc, char *argv[])
mainWidget.setWindowModified(true);
});

if (scene->groupingEnabled()) {
auto loadGroupAction = menu->addAction("Load Group...");
QObject::connect(loadGroupAction, &QAction::triggered, [scene] { scene->loadGroupFile(); });
}

mainWidget.setWindowTitle("[*]Data Flow: simplest calculator");
mainWidget.resize(800, 600);
// Center window.
Expand Down
1 change: 1 addition & 0 deletions include/QtNodes/GroupGraphicsObject
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "internal/GroupGraphicsObject.hpp"
1 change: 1 addition & 0 deletions include/QtNodes/NodeGroup
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "internal/NodeGroup.hpp"
145 changes: 142 additions & 3 deletions include/QtNodes/internal/BasicGraphicsScene.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
#include "ConnectionIdHash.hpp"
#include "Definitions.hpp"
#include "Export.hpp"
#include "GroupGraphicsObject.hpp"
#include "NodeGroup.hpp"
#include "UndoCommands.hpp"

#include "QUuidStdHash.hpp"

#include <QtCore/QUuid>
#include <QtCore/QJsonObject>
#include <QtWidgets/QGraphicsScene>
#include <QtWidgets/QMenu>

Expand All @@ -27,6 +28,11 @@ class AbstractNodePainter;
class ConnectionGraphicsObject;
class NodeGraphicsObject;
class NodeStyle;
class DeleteCommand;
class CopyCommand;
class NodeGroup;
class GroupGraphicsObject;
struct ConnectionId;

/// An instance of QGraphicsScene, holds connections and nodes.
class NODE_EDITOR_PUBLIC BasicGraphicsScene : public QGraphicsScene
Expand Down Expand Up @@ -62,6 +68,17 @@ class NODE_EDITOR_PUBLIC BasicGraphicsScene : public QGraphicsScene

QUndoStack &undoStack();

/**
* @brief Setter for the _groupingEnabled flag.
* @param boolean to set or not the flag.
*/
void setGroupingEnabled(bool enabled);

/**
* @brief Getter for the _groupingEnabled flag.
*/
bool groupingEnabled() const { return _groupingEnabled; }

public:
/**
* @brief Creates a "draft" instance of ConnectionGraphicsObject.
Expand All @@ -87,6 +104,83 @@ class NODE_EDITOR_PUBLIC BasicGraphicsScene : public QGraphicsScene
/// Deletes all the nodes. Connections are removed automatically.
void clearScene();

/**
* @brief Creates a list of the connections that are incident only to nodes within a
* given group.
* @param groupID ID of the desired group.
* @return List of (pointers of) connections whose both endpoints belong to members of
* the specified group.
*/
std::vector<std::shared_ptr<ConnectionId>> connectionsWithinGroup(GroupId groupID);
/**
* @brief Creates a group in the scene containing the given nodes.
* @param nodes Reference to the list of nodes to be included in the group.
* @param name Group's name.
* @param groupId Group's id.
* @return Pointer to the newly-created group.
*/
std::weak_ptr<NodeGroup> createGroup(std::vector<NodeGraphicsObject *> &nodes,
QString name = QStringLiteral(""),
GroupId groupId = InvalidGroupId);

/**
* @brief Creates a group in the scene containing the currently selected nodes.
* @param name Group's name
* @return Pointer to the newly-created group.
*/
std::weak_ptr<NodeGroup> createGroupFromSelection(QString groupName = QStringLiteral(""));

/**
* @brief Restores a group from a JSON object.
* @param groupJson JSON object containing the group data.
* @return Pair consisting of a pointer to the newly-created group and the mapping
* between old and new nodes.
*/
std::pair<std::weak_ptr<NodeGroup>, std::unordered_map<GroupId, GroupId>> restoreGroup(
QJsonObject const &groupJson);

/**
* @brief Returns a const reference to the mapping of existing groups.
*/
std::unordered_map<GroupId, std::shared_ptr<NodeGroup>> const &groups() const;

/**
* @brief Loads a group from a file specified by the user.
* @return Pointer to the newly-created group.
*/
std::weak_ptr<NodeGroup> loadGroupFile();

/**
* @brief Saves a group in a .group file.
* @param groupID Group's id.
*/
void saveGroupFile(GroupId groupID);

/**
* @brief Calculates the selected nodes.
* @return Vector containing the NodeGraphicsObject pointers related to the selected nodes.
*/
std::vector<NodeGraphicsObject *> selectedNodes() const;

/**
* @brief Calculates the selected groups.
* @return Vector containing the GroupGraphicsObject pointers related to the selected groups.
*/
std::vector<GroupGraphicsObject *> selectedGroups() const;

/**
* @brief Adds a node to a group, if both node and group exists.
* @param nodeId Node's id.
* @param groupId Group's id.
*/
void addNodeToGroup(NodeId nodeId, GroupId groupId);

/**
* @brief Removes a node from a group, if the node exists and is within a group.
* @param nodeId Node's id.
*/
void removeNodeFromGroup(NodeId nodeId);

public:
/**
* @returns NodeGraphicsObject associated with the given nodeId.
Expand All @@ -111,6 +205,17 @@ class NODE_EDITOR_PUBLIC BasicGraphicsScene : public QGraphicsScene
*/
virtual QMenu *createSceneMenu(QPointF const scenePos);

/**
* @brief Creates the default menu when a node is selected.
*/
QMenu *createStdMenu(QPointF const scenePos);

/**
* @brief Creates the menu when a group is selected.
* @param groupGo reference to the GroupGraphicsObject related to the selected group.
*/
QMenu *createGroupMenu(QPointF const scenePos, GroupGraphicsObject *groupGo);

Q_SIGNALS:
void modified(BasicGraphicsScene *);
void nodeMoved(NodeId const nodeId, QPointF const &newLocation);
Expand Down Expand Up @@ -141,6 +246,24 @@ class NODE_EDITOR_PUBLIC BasicGraphicsScene : public QGraphicsScene
/// Redraws adjacent nodes for given `connectionId`
void updateAttachedNodes(ConnectionId const connectionId, PortType const portType);

/**
* @brief Loads a JSON object that represents a node, with the option
* to keep the stored node id or generate a new one.
* @param nodeJson The JSON object representing a node.
* @param keepOriginalId If true, the loaded node will have the same id as the one stored in
* the file; otherwise, a new id will be generated
* @return A reference to the NodeGraphicsObject related to the loaded node.
*/
NodeGraphicsObject &loadNodeToMap(QJsonObject nodeJson, bool keepOriginalId = false);

/**
* @brief Loads a connection between nodes from a JSON file.
* @param connectionJson JSON object that stores the connection's endpoints.
* @param nodeIdMap Map of nodes (i.e. all possible endpoints).
*/
void loadConnectionToMap(QJsonObject const &connectionJson,
std::unordered_map<NodeId, NodeId> const &nodeIdMap);

public Q_SLOTS:
/// Slot called when the `connectionId` is erased form the AbstractGraphModel.
virtual void onConnectionDeleted(ConnectionId const connectionId);
Expand All @@ -155,21 +278,37 @@ public Q_SLOTS:
virtual void onNodeClicked(NodeId const nodeId);
virtual void onModelReset();

/**
* @brief Slot called to trigger the copy command action.
*/
void onCopySelectedObjects() { undoStack().push(new CopyCommand(this)); }

/**
* @brief Slot called to trigger the delete command action.
*/
void onDeleteSelectedObjects() { undoStack().push(new DeleteCommand(this)); }

private:
AbstractGraphModel &_graphModel;

using UniqueNodeGraphicsObject = std::unique_ptr<NodeGraphicsObject>;
using UniqueConnectionGraphicsObject = std::unique_ptr<ConnectionGraphicsObject>;
using SharedGroup = std::shared_ptr<NodeGroup>;

std::unordered_map<NodeId, UniqueNodeGraphicsObject> _nodeGraphicsObjects;
std::unordered_map<ConnectionId, UniqueConnectionGraphicsObject> _connectionGraphicsObjects;
GroupId nextGroupId();

std::unordered_map<GroupId, SharedGroup> _groups{};
GroupId _nextGroupId{0};
std::unique_ptr<ConnectionGraphicsObject> _draftConnection;
std::unique_ptr<AbstractNodeGeometry> _nodeGeometry;
std::unique_ptr<AbstractNodePainter> _nodePainter;
std::unique_ptr<AbstractConnectionPainter> _connectionPainter;
bool _nodeDrag;
QUndoStack *_undoStack;
Qt::Orientation _orientation;
bool _groupingEnabled;
};

} // namespace QtNodes
35 changes: 20 additions & 15 deletions include/QtNodes/internal/Definitions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,23 @@ NODE_EDITOR_PUBLIC Q_NAMESPACE
Q_NAMESPACE_EXPORT(NODE_EDITOR_PUBLIC)
#endif

/**
/**
* Constants used for fetching QVariant data from GraphModel.
*/
enum class NodeRole {
Type = 0, ///< Type of the current node, usually a string.
Position = 1, ///< `QPointF` positon of the node on the scene.
Size = 2, ///< `QSize` for resizable nodes.
CaptionVisible = 3, ///< `bool` for caption visibility.
Caption = 4, ///< `QString` for node caption.
Style = 5, ///< Custom NodeStyle as QJsonDocument
InternalData = 6, ///< Node-stecific user data as QJsonObject
InPortCount = 7, ///< `unsigned int`
OutPortCount = 9, ///< `unsigned int`
Widget = 10, ///< Optional `QWidget*` or `nullptr`
ValidationState = 11, ///< Enum NodeValidationState of the node
ProcessingStatus = 12 ///< Enum NodeProcessingStatus of the node
};
enum class NodeRole {
Type = 0, ///< Type of the current node, usually a string.
Position = 1, ///< `QPointF` positon of the node on the scene.
Size = 2, ///< `QSize` for resizable nodes.
CaptionVisible = 3, ///< `bool` for caption visibility.
Caption = 4, ///< `QString` for node caption.
Style = 5, ///< Custom NodeStyle as QJsonDocument
InternalData = 6, ///< Node-stecific user data as QJsonObject
InPortCount = 7, ///< `unsigned int`
OutPortCount = 9, ///< `unsigned int`
Widget = 10, ///< Optional `QWidget*` or `nullptr`
ValidationState = 11, ///< Enum NodeValidationState of the node
ProcessingStatus = 12 ///< Enum NodeProcessingStatus of the node
};
Q_ENUM_NS(NodeRole)

/**
Expand Down Expand Up @@ -94,6 +94,11 @@ using NodeId = unsigned int;

static constexpr NodeId InvalidNodeId = std::numeric_limits<NodeId>::max();

/// Unique Id associated with each node group.
using GroupId = unsigned int;

static constexpr GroupId InvalidGroupId = std::numeric_limits<GroupId>::max();

/**
* A unique connection identificator that stores
* out `NodeId`, out `PortIndex`, in `NodeId`, in `PortIndex`
Expand Down
1 change: 1 addition & 0 deletions include/QtNodes/internal/GraphicsView.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ public Q_SLOTS:
private:
QAction *_clearSelectionAction = nullptr;
QAction *_deleteSelectionAction = nullptr;
QAction *_cutSelectionAction = nullptr;
QAction *_duplicateSelectionAction = nullptr;
QAction *_copySelectionAction = nullptr;
QAction *_pasteAction = nullptr;
Expand Down
Loading
Loading