From 844141b6bb6ef731405fe5ecf1695ef79b5901e4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Mar 2026 05:16:37 +0000 Subject: [PATCH 1/5] Cleanup: remove dead code, fix bug, deduplicate style/model helpers - Fix bug in NodeGraphicsObject::hoverMoveEvent: `|` -> `&` for flag test (line 466 was always true due to bitwise OR with Resizable) - Replace triplicated JSON style read/write macros across NodeStyle, ConnectionStyle, and GraphicsViewStyle with shared helpers in Style.hpp - Extract portCountRole() helper to eliminate repeated ternary expressions across 7 files - Extract DataFlowGraphModel::connectDelegateModel() to deduplicate ~30 lines of identical signal connection setup in addNode/loadNode - Remove unused hash specializations (pair/tuple) from ConnectionIdHash.hpp - Remove commented-out code from NodeGraphicsObject, ConnectionGraphicsObject, ConnectionState, and Style.hpp - Remove unused NODE_EDITOR_DEMANGLED macro from Export.hpp - Remove unused PySide2/Shiboken2 cmake modules (never referenced) - Simplify oppositePort() switch with direct returns Net reduction: ~715 lines across 20 files. https://claude.ai/code/session_015aZAxLSpakeTpF7zaq6D2F --- cmake/FindPySide2.cmake | 160 --------------- cmake/FindShiboken2.cmake | 187 ------------------ cmake/PySide2ModuleBuild.cmake | 157 --------------- include/QtNodes/internal/ConnectionIdHash.hpp | 32 +-- .../QtNodes/internal/ConnectionIdUtils.hpp | 22 +-- .../QtNodes/internal/DataFlowGraphModel.hpp | 2 + include/QtNodes/internal/Export.hpp | 6 - include/QtNodes/internal/Style.hpp | 56 +++++- src/AbstractGraphModel.cpp | 8 +- src/AbstractNodeGeometry.cpp | 6 +- src/ConnectionGraphicsObject.cpp | 6 - src/ConnectionState.cpp | 5 +- src/ConnectionStyle.cpp | 106 ++-------- src/DataFlowGraphModel.cpp | 113 ++++------- src/DefaultHorizontalNodeGeometry.cpp | 7 +- src/DefaultNodePainter.cpp | 15 +- src/DefaultVerticalNodeGeometry.cpp | 7 +- src/GraphicsViewStyle.cpp | 53 +---- src/NodeGraphicsObject.cpp | 6 +- src/NodeStyle.cpp | 145 ++++---------- 20 files changed, 192 insertions(+), 907 deletions(-) delete mode 100644 cmake/FindPySide2.cmake delete mode 100644 cmake/FindShiboken2.cmake delete mode 100644 cmake/PySide2ModuleBuild.cmake diff --git a/cmake/FindPySide2.cmake b/cmake/FindPySide2.cmake deleted file mode 100644 index 7ebb33d02..000000000 --- a/cmake/FindPySide2.cmake +++ /dev/null @@ -1,160 +0,0 @@ -# -# SPDX-FileCopyrightText: 2020-2021 Klarälvdalens Datakonsult AB, a KDAB Group company -# Author: Renato Araujo Oliveira Filho -# -# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only -# -# Contact KDAB at for commercial licensing options. -# - -# PYSIDE_BASEDIR - Top of the PySide2 installation -# PYSIDE_INCLUDE_DIR - Directories to include to use PySide2 -# PYSIDE_LIBRARY - Files to link against to use PySide2 -# PYSIDE_TYPESYSTEMS - Type system files that should be used by other bindings extending PySide2 -# -# You can install PySide2 from Qt repository with -# pip3 install --index-url=https://download.qt.io/official_releases/QtForPython --trusted-host download.qt.io pyside2 - -find_package(PkgConfig) -if(PKG_CONFIG_FOUND) - pkg_check_modules(PYSIDE2_PRIV QUIET pyside2) -endif() - -set(PYSIDE2_FOUND FALSE) - -if(PYSIDE2_PRIV_FOUND) - set(PYSIDE2_FOUND TRUE) - message(STATUS "Using PySide2 found in the system!") - pkg_get_variable(SHIBOKEN_BINARY - pyside2 - generator_location - ) - pkg_get_variable(PYSIDE2_BASEDIR - pyside2 - typesystemdir - ) - pkg_get_variable(PYSIDE_INCLUDE_DIR - pyside2 - includedir - ) - set(PYSIDE_TYPESYSTEMS ${PYSIDE2_BASEDIR}) - set(PYSIDE2_SO_VERSION ${PYSIDE2_PRIV_VERSION}) - set(PYSIDE_LIBRARY ${PYSIDE2_PRIV_LINK_LIBRARIES}) - list(GET PYSIDE_LIBRARY 0 PYSIDE_LIBRARY) -else() - # extract python library basename - list(GET Python3_LIBRARIES 0 PYTHON_LIBRARY_FILENAME) - get_filename_component(PYTHON_LIBRARY_FILENAME ${PYTHON_LIBRARY_FILENAME} NAME) - - execute_process( - COMMAND ${Python3_EXECUTABLE} -c "if True: - import os, sys - try: - import PySide2.QtCore as QtCore - print(os.path.dirname(QtCore.__file__)) - except Exception as error: - print(error, file=sys.stderr) - exit() - " - OUTPUT_VARIABLE PYSIDE2_BASEDIR - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - if(PYSIDE2_BASEDIR) - set(PYSIDE_BASEDIR ${PYSIDE2_BASEDIR} CACHE PATH "Top level install of PySide2" FORCE) - execute_process( - COMMAND ${Python3_EXECUTABLE} -c "if True: - import os - import PySide2.QtCore as QtCore - print(os.path.basename(QtCore.__file__).split('.', 1)[1]) - " - OUTPUT_VARIABLE PYSIDE2_SUFFIX - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - execute_process( - COMMAND ${Python3_EXECUTABLE} -c "if True: - import os - import PySide2.QtCore as QtCore - print(';'.join(map(str, QtCore.__version_info__))) - " - OUTPUT_VARIABLE PYSIDE2_SO_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - list(GET PYSIDE2_SO_VERSION 0 PYSIDE2_SO_MACRO_VERSION) - list(GET PYSIDE2_SO_VERSION 1 PYSIDE2_SO_MICRO_VERSION) - list(GET PYSIDE2_SO_VERSION 2 PYSIDE2_SO_MINOR_VERSION) - string(REPLACE ";" "." PYSIDE2_SO_VERSION "${PYSIDE2_SO_VERSION}") - - if(NOT APPLE) - set(PYSIDE2_SUFFIX "${PYSIDE2_SUFFIX}.${PYSIDE2_SO_MACRO_VERSION}.${PYSIDE2_SO_MICRO_VERSION}") - else() - string(REPLACE ".so" "" PYSIDE2_SUFFIX ${PYSIDE2_SUFFIX}) - set(PYSIDE2_SUFFIX "${PYSIDE2_SUFFIX}.${PYSIDE2_SO_MACRO_VERSION}.${PYSIDE2_SO_MICRO_VERSION}.dylib") - endif() - - set(PYSIDE2_FOUND TRUE) - message(STATUS "PySide2 base dir: ${PYSIDE2_BASEDIR}" ) - message(STATUS "PySide2 suffix: ${PYSIDE2_SUFFIX}") - endif() - - if (PYSIDE2_FOUND) - #PySide - #=============================================================================== - find_path(PYSIDE_INCLUDE_DIR - pyside.h - PATHS ${PYSIDE2_BASEDIR}/include ${PYSIDE2_CUSTOM_PREFIX}/include/PySide2 - NO_DEFAULT_PATH) - - # Platform specific library names - if(MSVC) - SET(PYSIDE_LIBRARY_BASENAMES "pyside2.abi3.lib") - elseif(CYGWIN) - SET(PYSIDE_LIBRARY_BASENAMES "") - elseif(WIN32) - SET(PYSIDE_LIBRARY_BASENAMES "libpyside2.${PYSIDE2_SUFFIX}") - else() - SET(PYSIDE_LIBRARY_BASENAMES "libpyside2.${PYSIDE2_SUFFIX}") - endif() - - find_file(PYSIDE_LIBRARY - ${PYSIDE_LIBRARY_BASENAMES} - PATHS ${PYSIDE2_BASEDIR} ${PYSIDE2_CUSTOM_PREFIX}/lib - NO_DEFAULT_PATH) - - find_path(PYSIDE_TYPESYSTEMS - typesystem_core.xml - PATHS ${PYSIDE2_BASEDIR}/typesystems ${PYSIDE2_CUSTOM_PREFIX}/share/PySide2/typesystems - NO_DEFAULT_PATH) - endif() -endif() - -if(PYSIDE2_FOUND) - message(STATUS "PySide include dir: ${PYSIDE_INCLUDE_DIR}") - message(STATUS "PySide library: ${PYSIDE_LIBRARY}") - message(STATUS "PySide typesystems: ${PYSIDE_TYPESYSTEMS}") - message(STATUS "PySide2 version: ${PYSIDE2_SO_VERSION}") - - # Create PySide2 target - add_library(PySide2::pyside2 SHARED IMPORTED GLOBAL) - if(MSVC) - set_property(TARGET PySide2::pyside2 PROPERTY - IMPORTED_IMPLIB ${PYSIDE_LIBRARY}) - endif() - set_property(TARGET PySide2::pyside2 PROPERTY - IMPORTED_LOCATION ${PYSIDE_LIBRARY}) - set_property(TARGET PySide2::pyside2 APPEND PROPERTY - INTERFACE_INCLUDE_DIRECTORIES - ${PYSIDE_INCLUDE_DIR} - ${PYSIDE_INCLUDE_DIR}/QtCore/ - ${PYSIDE_INCLUDE_DIR}/QtGui/ - ${PYSIDE_INCLUDE_DIR}/QtWidgets/ - ${Python3_INCLUDE_DIRS} - ) -endif() - - -find_package_handle_standard_args(PySide2 - REQUIRED_VARS PYSIDE2_BASEDIR PYSIDE_INCLUDE_DIR PYSIDE_LIBRARY PYSIDE_TYPESYSTEMS - VERSION_VAR PYSIDE2_SO_VERSION -) diff --git a/cmake/FindShiboken2.cmake b/cmake/FindShiboken2.cmake deleted file mode 100644 index b86e6ad14..000000000 --- a/cmake/FindShiboken2.cmake +++ /dev/null @@ -1,187 +0,0 @@ -# -# SPDX-FileCopyrightText: 2020-2021 Klarälvdalens Datakonsult AB, a KDAB Group company -# Author: Renato Araujo Oliveira Filho -# -# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only -# -# Contact KDAB at for commercial licensing options. -# - -# SHIBOKEN_INCLUDE_DIR - Directories to include to use SHIBOKEN -# SHIBOKEN_LIBRARY - Files to link against to use SHIBOKEN -# SHIBOKEN_BINARY - Executable name -# SHIBOKEN_BUILD_TYPE - Tells if Shiboken was compiled in Release or Debug mode. - -# You can install Shiboken from Qt repository with -# pip3 install --index-url=https://download.qt.io/official_releases/QtForPython --trusted-host download.qt.io shiboken2-generator - -find_package(PkgConfig) -if(PKG_CONFIG_FOUND) - pkg_check_modules(SHIBOKEN2_PRIV QUIET shiboken2) -endif() - -set(SHIBOKEN_FOUND FALSE) - -if(SHIBOKEN2_PRIV_FOUND) - set(SHIBOKEN_FOUND TRUE) - message(STATUS "Using shiboken found in the system!") - pkg_get_variable(SHIBOKEN_BINARY - shiboken2 - generator_location - ) - pkg_get_variable(SHIBOKEN_BASEDIR - shiboken2 - libdir - ) - pkg_get_variable(SHIBOKEN_INCLUDE_DIR - shiboken2 - includedir - ) - set(SHIBOKEN_VERSION ${SHIBOKEN2_PRIV_VERSION}) - set(SHIBOKEN_LIBRARY ${SHIBOKEN2_PRIV_LINK_LIBRARIES}) -else() - execute_process( - COMMAND ${Python3_EXECUTABLE} -c "if True: - import os - try: - import shiboken2_generator - print(shiboken2_generator.__path__[0]) - except: - exit() - " - OUTPUT_VARIABLE SHIBOKEN_GENERATOR_BASEDIR - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - execute_process( - COMMAND ${Python3_EXECUTABLE} -c "if True: - import os - try: - import shiboken2 - print(shiboken2.__path__[0]) - except: - exit() - " - OUTPUT_VARIABLE SHIBOKEN_BASEDIR - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - execute_process( - COMMAND ${Python3_EXECUTABLE} -c "if True: - import os - import shiboken2 - print(';'.join(filter(None, map(str, shiboken2.__version_info__)))) - " - OUTPUT_VARIABLE SHIBOKEN_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - list(GET SHIBOKEN_VERSION 0 SHIBOKEN_MACRO_VERSION) - list(GET SHIBOKEN_VERSION 1 SHIBOKEN_MICRO_VERSION) - list(GET SHIBOKEN_VERSION 2 SHIBOKEN_MINOR_VERSION) - string(REPLACE ";" "." SHIBOKEN_VERSION "${SHIBOKEN_VERSION}") - - message(STATUS "ShibokenGenerator base dir: ${SHIBOKEN_GENERATOR_BASEDIR}") - message(STATUS "Shiboken base dir: ${SHIBOKEN_BASEDIR}") - message(STATUS "Shiboken custom path: ${SHIBOKEN_CUSTOM_PATH}") - - if(SHIBOKEN_BASEDIR) - find_path(SHIBOKEN_INCLUDE_DIR - shiboken.h - PATHS ${SHIBOKEN_CUSTOM_PATH} ${SHIBOKEN_GENERATOR_BASEDIR}/include - NO_DEFAULT_PATH) - if(MSVC) - SET(SHIBOKEN_LIBRARY_BASENAMES "shiboken2.abi3.lib") - elseif(CYGWIN) - SET(SHIBOKEN_LIBRARY_BASENAMES "") - elseif(WIN32) - SET(SHIBOKEN_LIBRARY_BASENAMES "libshiboken2.${PYSIDE2_SUFFIX}") - elseif(APPLE) - SET(SHIBOKEN_LIBRARY_BASENAMES - libshiboken2.abi3.dylib - libshiboken2.abi3.${SHIBOKEN_MACRO_VERSION}.dylib - libshiboken2.abi3.${SHIBOKEN_MACRO_VERSION}.${SHIBOKEN_MICRO_VERSION}.dylib - libshiboken2.abi3.${SHIBOKEN_VERSION}.dylib - ) - else() - SET(SHIBOKEN_LIBRARY_BASENAMES - libshiboken2.abi3.so - libshiboken2.abi3.so.${SHIBOKEN_MACRO_VERSION} - libshiboken2.abi3.so.${SHIBOKEN_MACRO_VERSION}.${SHIBOKEN_MICRO_VERSION} - libshiboken2.abi3.so.${SHIBOKEN_VERSION} - ) - endif() - - if (NOT SHIBOKEN_INCLUDE_DIR) - return() - endif() - set(SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_CUSTOM_PATH}) - list(APPEND SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_BASEDIR}) - list(APPEND SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_GENERATOR_BASEDIR}) - find_file(SHIBOKEN_LIBRARY - ${SHIBOKEN_LIBRARY_BASENAMES} - PATHS ${SHIBOKEN_SEARCH_PATHS} - NO_DEFAULT_PATH) - - find_program(SHIBOKEN_BINARY - shiboken2 - PATHS ${SHIBOKEN_SEARCH_PATHS} - NO_DEFAULT_PATH - ) - endif() - if (SHIBOKEN_INCLUDE_DIR AND SHIBOKEN_LIBRARY AND SHIBOKEN_BINARY) - set(SHIBOKEN_FOUND TRUE) - endif() - - if(SHIBOKEN_FOUND) - endif() - - - if(MSVC) - # On Windows we must link to python3.dll that is a small library that links against python3x.dll - # that allow us to choose any python3x.dll at runtime - execute_process( - COMMAND ${Python3_EXECUTABLE} -c "if True: - for lib in '${Python3_LIBRARIES}'.split(';'): - if '/' in lib: - prefix, py = lib.rsplit('/', 1) - if py.startswith('python3'): - print(prefix + '/python3.lib') - break - " - OUTPUT_VARIABLE PYTHON_LIMITED_LIBRARIES - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - else() - # On Linux and MacOs our modules should not link with any python library - # that must be handled by the main process - set(PYTHON_LIMITED_LIBRARIES "") - endif() -endif() -if (SHIBOKEN_FOUND) - message(STATUS "Shiboken include dir: ${SHIBOKEN_INCLUDE_DIR}") - message(STATUS "Shiboken library: ${SHIBOKEN_LIBRARY}") - message(STATUS "Shiboken binary: ${SHIBOKEN_BINARY}") - message(STATUS "Shiboken version: ${SHIBOKEN_VERSION}") - - # Create shiboke2 target - add_library(Shiboken2::libshiboken SHARED IMPORTED GLOBAL) - if(MSVC) - set_property(TARGET Shiboken2::libshiboken PROPERTY - IMPORTED_IMPLIB ${SHIBOKEN_LIBRARY}) - endif() - set_property(TARGET Shiboken2::libshiboken PROPERTY - IMPORTED_LOCATION ${SHIBOKEN_LIBRARY}) - set_property(TARGET Shiboken2::libshiboken APPEND PROPERTY - INTERFACE_INCLUDE_DIRECTORIES ${SHIBOKEN_INCLUDE_DIR} ${Python3_INCLUDE_DIRS}) - set_property(TARGET Shiboken2::libshiboken APPEND PROPERTY - INTERFACE_LINK_LIBRARIES ${PYTHON_LIMITED_LIBRARIES}) - - # Generator target - add_executable(Shiboken2::shiboken IMPORTED GLOBAL) - set_property(TARGET Shiboken2::shiboken PROPERTY - IMPORTED_LOCATION ${SHIBOKEN_BINARY}) -endif() - -find_package_handle_standard_args(Shiboken2 - REQUIRED_VARS SHIBOKEN_BASEDIR SHIBOKEN_INCLUDE_DIR SHIBOKEN_LIBRARY SHIBOKEN_BINARY - VERSION_VAR SHIBOKEN_VERSION -) - diff --git a/cmake/PySide2ModuleBuild.cmake b/cmake/PySide2ModuleBuild.cmake deleted file mode 100644 index 06f2b620e..000000000 --- a/cmake/PySide2ModuleBuild.cmake +++ /dev/null @@ -1,157 +0,0 @@ -# -# SPDX-FileCopyrightText: 2020-2021 Klarälvdalens Datakonsult AB, a KDAB Group company -# Author: Renato Araujo Oliveira Filho -# -# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only -# -# Contact KDAB at for commercial licensing options. -# - -if (NOT ${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX) - SET(${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} CACHE FILEPATH "Custom path to install python bindings.") -endif() - -message(STATUS "PYTHON INSTALL PREFIX ${${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX}") - -if (WIN32) - set(PATH_SEP "\;") -else() - set(PATH_SEP ":") -endif() -if (NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 17) -endif() - -# On macOS, check if Qt is a framework build. This affects how include paths should be handled. -get_target_property(QtCore_is_framework Qt5::Core FRAMEWORK) -if (QtCore_is_framework) - # Get the path to the framework dir. - list(GET Qt5Core_INCLUDE_DIRS 0 QT_INCLUDE_DIR) - get_filename_component(QT_FRAMEWORK_INCLUDE_DIR "${QT_INCLUDE_DIR}/../" ABSOLUTE) - - # QT_INCLUDE_DIR points to the QtCore.framework directory, so we need to adjust this to point - # to the actual include directory, which has include files for non-framework parts of Qt. - get_filename_component(QT_INCLUDE_DIR "${QT_INCLUDE_DIR}/../../include" ABSOLUTE) -endif() - -# Flags that we will pass to shiboken-generator -# --generator-set=shiboken: tells the generator that we want to use shiboken to generate code, -# a doc generator is also available -# --enable-parent-ctor-heuristic: Enable heuristics to detect parent relationship on constructors, -# this try to guess parent ownership based on the arguments of the constructors -# --enable-pyside-extensionsL: This will generate code for Qt based classes, adding extra attributes, -# like signal, slot; -# --enable-return-value-heuristic: Similar as --enable-parent-ctor-heuristic this use some logic to guess -# parent child relationship based on the returned argument -# --use-isnull-as-nb_nonzero: If a class have an isNull() const method, it will be used to compute -# the value of boolean casts. -# Example, QImage::isNull() will be used when on python side you do `if (myQImage)` -set(GENERATOR_EXTRA_FLAGS --generator-set=shiboken - --enable-parent-ctor-heuristic - --enable-pyside-extensions - --enable-return-value-heuristic - --use-isnull-as-nb_nonzero - -std=c++${CMAKE_CXX_STANDARD}) - -# 2017-04-24 The protected hack can unfortunately not be disabled, because -# Clang does produce linker errors when we disable the hack. -# But the ugly workaround in Python is replaced by a shiboken change. -if(WIN32 OR DEFINED AVOID_PROTECTED_HACK) - set(GENERATOR_EXTRA_FLAGS ${GENERATOR_EXTRA_FLAGS} --avoid-protected-hack) - add_definitions(-DAVOID_PROTECTED_HACK) -endif() - -macro(make_path varname) - # accepts any number of path variables - string(REPLACE ";" "${PATH_SEP}" ${varname} "${ARGN}") -endmacro() - -# Creates a PySide module target based on the arguments -# This will: -# 1 - Create a Cmake custom-target that call shiboken-generator passign the correct arguments -# 2 - Create a Cmake library target called "Py${LIBRARY_NAME}" the output name of this target -# will be changed to match PySide template -# Args: -# LIBRARY_NAME - The name of the output module -# TYPESYSTEM_PATHS - A list of paths where shiboken should look for typesystem files -# INCLUDE_PATHS - Include pahts necessary to parse your class. *This is not the same as build* -# OUTPUT_SOURCES - The files that will be generated by shiboken -# TARGET_INCLUDE_DIRS - This will be passed to target_include_directories -# TARGET_LINK_LIBRARIES - This will be passed to target_link_libraries -# GLOBAL_INCLUDE - A header-file that contains alls classes that will be generated -# TYPESYSTEM_XML - The target binding typesystem (that should be the full path) -# DEPENDS - This var will be passed to add_custom_command(DEPENDS) so a new generation will be -# trigger if one of these files changes -# MODULE_OUTPUT_DIR - Where the library file should be stored -macro(CREATE_PYTHON_BINDINGS - LIBRARY_NAME - TYPESYSTEM_PATHS - INCLUDE_PATHS - OUTPUT_SOURCES - TARGET_INCLUDE_DIRS - TARGET_LINK_LIBRARIES - GLOBAL_INCLUDE - TYPESYSTEM_XML - DEPENDS - MODULE_OUTPUT_DIR) - - # Transform the path separators into something shiboken understands. - make_path(shiboken_include_dirs ${INCLUDE_PATHS}) - make_path(shiboken_typesystem_dirs ${TYPESYSTEM_PATHS}) - get_property(raw_python_dir_include_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES) - make_path(python_dir_include_dirs ${raw_python_dir_include_dirs}) - set(shiboken_include_dirs "${shiboken_include_dirs}${PATH_SEP}${python_dir_include_dirs}") - - set(shiboken_framework_include_dirs_option "") - if(CMAKE_HOST_APPLE) - set(shiboken_framework_include_dirs "${QT_FRAMEWORK_INCLUDE_DIR}") - make_path(shiboken_framework_include_dirs ${shiboken_framework_include_dirs}) - set(shiboken_framework_include_dirs_option "--framework-include-paths=${shiboken_framework_include_dirs}") - endif() - set_property(SOURCE ${OUTPUT_SOURCES} PROPERTY SKIP_AUTOGEN ON) - add_custom_command(OUTPUT ${OUTPUT_SOURCES} - COMMAND $ ${GENERATOR_EXTRA_FLAGS} - ${GLOBAL_INCLUDE} - --include-paths=${shiboken_include_dirs} - --typesystem-paths=${shiboken_typesystem_dirs} - ${shiboken_framework_include_dirs_option} - --output-directory=${CMAKE_CURRENT_BINARY_DIR} - ${TYPESYSTEM_XML} - DEPENDS ${TYPESYSTEM_XML} ${DEPENDS} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Running generator for ${LIBRARY_NAME} binding...") - - set(TARGET_NAME "Py${LIBRARY_NAME}") - set(MODULE_NAME "${LIBRARY_NAME}") - add_library(${TARGET_NAME} MODULE ${OUTPUT_SOURCES}) - - set_target_properties(${TARGET_NAME} PROPERTIES - PREFIX "" - OUTPUT_NAME ${MODULE_NAME} - LIBRARY_OUTPUT_DIRECTORY ${MODULE_OUTPUT_DIR} - ) - - if(WIN32) - set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX ".pyd") - endif() - - target_include_directories(${TARGET_NAME} PUBLIC - ${TARGET_INCLUDE_DIRS} - ${PYSIDE_EXTRA_INCLUDES} - ) - - target_link_libraries(${TARGET_NAME} - ${TARGET_LINK_LIBRARIES} - PySide2::pyside2 - Shiboken2::libshiboken - ) - target_compile_definitions(${TARGET_NAME} - PRIVATE Py_LIMITED_API=0x03050000 - ) - if(APPLE) - set_property(TARGET ${TARGET_NAME} APPEND PROPERTY - LINK_FLAGS "-undefined dynamic_lookup") - endif() - install(TARGETS ${TARGET_NAME} - LIBRARY DESTINATION ${${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX}/${TARGET_NAME}) -endmacro() diff --git a/include/QtNodes/internal/ConnectionIdHash.hpp b/include/QtNodes/internal/ConnectionIdHash.hpp index 09eaced6c..1ab3f01eb 100644 --- a/include/QtNodes/internal/ConnectionIdHash.hpp +++ b/include/QtNodes/internal/ConnectionIdHash.hpp @@ -4,17 +4,14 @@ #include "Definitions.hpp" -inline void hash_combine(std::size_t &seed) -{ - Q_UNUSED(seed); -} - template inline void hash_combine(std::size_t &seed, const T &v, Rest... rest) { std::hash hasher; seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); - hash_combine(seed, rest...); + if constexpr (sizeof...(rest) > 0) { + hash_combine(seed, rest...); + } } namespace std { @@ -29,27 +26,4 @@ struct hash } }; -template<> -struct hash> -{ - inline std::size_t operator()(std::pair const &nodePort) const - { - std::size_t h = 0; - hash_combine(h, nodePort.first, nodePort.second); - return h; - } -}; - -template<> -struct hash> -{ - using Key = std::tuple; - - inline std::size_t operator()(Key const &key) const - { - std::size_t h = 0; - hash_combine(h, std::get<0>(key), std::get<1>(key), std::get<2>(key)); - return h; - } -}; } // namespace std diff --git a/include/QtNodes/internal/ConnectionIdUtils.hpp b/include/QtNodes/internal/ConnectionIdUtils.hpp index 3e29babf2..554218833 100644 --- a/include/QtNodes/internal/ConnectionIdUtils.hpp +++ b/include/QtNodes/internal/ConnectionIdUtils.hpp @@ -37,25 +37,14 @@ inline PortIndex getPortIndex(PortType portType, ConnectionId connectionId) inline PortType oppositePort(PortType port) { - PortType result = PortType::None; - switch (port) { case PortType::In: - result = PortType::Out; - break; - + return PortType::Out; case PortType::Out: - result = PortType::In; - break; - - case PortType::None: - result = PortType::None; - break; - + return PortType::In; default: - break; + return PortType::None; } - return result; } inline bool isPortIndexValid(PortIndex index) @@ -156,4 +145,9 @@ inline ConnectionId fromJson(QJsonObject const &connJson) return connId; } +inline NodeRole portCountRole(PortType portType) +{ + return (portType == PortType::Out) ? NodeRole::OutPortCount : NodeRole::InPortCount; +} + } // namespace QtNodes diff --git a/include/QtNodes/internal/DataFlowGraphModel.hpp b/include/QtNodes/internal/DataFlowGraphModel.hpp index b1ef892e8..3e10c3a73 100644 --- a/include/QtNodes/internal/DataFlowGraphModel.hpp +++ b/include/QtNodes/internal/DataFlowGraphModel.hpp @@ -107,6 +107,8 @@ class NODE_EDITOR_PUBLIC DataFlowGraphModel private: NodeId newNodeId() override { return _nextNodeId++; } + void connectDelegateModel(NodeDelegateModel *model, NodeId nodeId); + void sendConnectionCreation(ConnectionId const connectionId); void sendConnectionDeletion(ConnectionId const connectionId); diff --git a/include/QtNodes/internal/Export.hpp b/include/QtNodes/internal/Export.hpp index 41e6e3d0a..78ac2edfa 100644 --- a/include/QtNodes/internal/Export.hpp +++ b/include/QtNodes/internal/Export.hpp @@ -17,12 +17,6 @@ #define NODE_EDITOR_LOCAL #endif -#ifdef __cplusplus -#define NODE_EDITOR_DEMANGLED extern "C" -#else -#define NODE_EDITOR_DEMANGLED -#endif - #if defined(NODE_EDITOR_SHARED) && !defined(NODE_EDITOR_STATIC) #ifdef NODE_EDITOR_EXPORTS #define NODE_EDITOR_PUBLIC NODE_EDITOR_EXPORT diff --git a/include/QtNodes/internal/Style.hpp b/include/QtNodes/internal/Style.hpp index f878083e2..262bdfadc 100644 --- a/include/QtNodes/internal/Style.hpp +++ b/include/QtNodes/internal/Style.hpp @@ -3,16 +3,15 @@ #include #include #include +#include #include #include #include namespace QtNodes { -class Style // : public QObject +class Style { - //Q_OBJECT - public: virtual ~Style() = default; @@ -45,4 +44,55 @@ class Style // : public QObject } }; +namespace detail { + +inline bool readColor(QJsonObject const &obj, QString const &key, QColor &color) +{ + if (!obj.contains(key)) + return false; + + QJsonValue value = obj[key]; + if (value.isArray()) { + auto colorArray = value.toArray(); + int rgb[] = {colorArray[0].toInt(), colorArray[1].toInt(), colorArray[2].toInt()}; + color = QColor(rgb[0], rgb[1], rgb[2]); + } else { + color = QColor(value.toString()); + } + return true; +} + +inline void writeColor(QJsonObject &obj, QString const &key, QColor const &color) +{ + obj[key] = color.name(); +} + +inline bool readFloat(QJsonObject const &obj, QString const &key, double &val) +{ + if (!obj.contains(key)) + return false; + val = obj[key].toDouble(); + return true; +} + +inline void writeFloat(QJsonObject &obj, QString const &key, double val) +{ + obj[key] = val; +} + +inline bool readBool(QJsonObject const &obj, QString const &key, bool &val) +{ + if (!obj.contains(key)) + return false; + val = obj[key].toBool(); + return true; +} + +inline void writeBool(QJsonObject &obj, QString const &key, bool val) +{ + obj[key] = val; +} + +} // namespace detail + } // namespace QtNodes diff --git a/src/AbstractGraphModel.cpp b/src/AbstractGraphModel.cpp index 3ea47435d..06a696177 100644 --- a/src/AbstractGraphModel.cpp +++ b/src/AbstractGraphModel.cpp @@ -11,9 +11,7 @@ void AbstractGraphModel::portsAboutToBeDeleted(NodeId const nodeId, { _shiftedByDynamicPortsConnections.clear(); - auto portCountRole = portType == PortType::In ? NodeRole::InPortCount : NodeRole::OutPortCount; - - unsigned int portCount = nodeData(nodeId, portCountRole).toUInt(); + unsigned int portCount = nodeData(nodeId, portCountRole(portType)).toUInt(); if (first > portCount - 1) return; @@ -67,9 +65,7 @@ void AbstractGraphModel::portsAboutToBeInserted(NodeId const nodeId, { _shiftedByDynamicPortsConnections.clear(); - auto portCountRole = portType == PortType::In ? NodeRole::InPortCount : NodeRole::OutPortCount; - - unsigned int portCount = nodeData(nodeId, portCountRole).toUInt(); + unsigned int portCount = nodeData(nodeId, portCountRole(portType)).toUInt(); if (first > portCount) return; diff --git a/src/AbstractNodeGeometry.cpp b/src/AbstractNodeGeometry.cpp index f6c893df7..8240ff6c5 100644 --- a/src/AbstractNodeGeometry.cpp +++ b/src/AbstractNodeGeometry.cpp @@ -1,6 +1,7 @@ #include "AbstractNodeGeometry.hpp" #include "AbstractGraphModel.hpp" +#include "ConnectionIdUtils.hpp" #include "StyleCollection.hpp" #include @@ -38,10 +39,7 @@ PortIndex AbstractNodeGeometry::checkPortHit(NodeId const nodeId, double const tolerance = 2.0 * nodeStyle.ConnectionPointDiameter; - size_t const n = _graphModel.nodeData(nodeId, - (portType == PortType::Out) - ? NodeRole::OutPortCount - : NodeRole::InPortCount); + size_t const n = _graphModel.nodeData(nodeId, portCountRole(portType)); for (unsigned int portIndex = 0; portIndex < n; ++portIndex) { auto pp = portPosition(nodeId, portType, portIndex); diff --git a/src/ConnectionGraphicsObject.cpp b/src/ConnectionGraphicsObject.cpp index a840e4746..931f76316 100644 --- a/src/ConnectionGraphicsObject.cpp +++ b/src/ConnectionGraphicsObject.cpp @@ -42,8 +42,6 @@ ConnectionGraphicsObject::ConnectionGraphicsObject(BasicGraphicsScene &scene, setAcceptHoverEvents(true); - //addGraphicsEffect(); - setZValue(-1.0); initializePosition(); @@ -362,10 +360,6 @@ void ConnectionGraphicsObject::addGraphicsEffect() effect->setBlurRadius(5); setGraphicsEffect(effect); - //auto effect = new QGraphicsDropShadowEffect; - //auto effect = new ConnectionBlurEffect(this); - //effect->setOffset(4, 4); - //effect->setColor(QColor(Qt::gray).darker(800)); } std::pair ConnectionGraphicsObject::pointsC1C2Horizontal() const diff --git a/src/ConnectionState.cpp b/src/ConnectionState.cpp index eed24a2ff..5b411a9b6 100644 --- a/src/ConnectionState.cpp +++ b/src/ConnectionState.cpp @@ -10,10 +10,7 @@ namespace QtNodes { -ConnectionState::~ConnectionState() -{ - //resetLastHoveredNode(); -} +ConnectionState::~ConnectionState() = default; PortType ConnectionState::requiredPort() const { diff --git a/src/ConnectionStyle.cpp b/src/ConnectionStyle.cpp index 812658989..a784aa9de 100644 --- a/src/ConnectionStyle.cpp +++ b/src/ConnectionStyle.cpp @@ -2,15 +2,14 @@ #include "StyleCollection.hpp" -#include #include -#include #include #include using QtNodes::ConnectionStyle; +using namespace QtNodes::detail; inline void initResources() { @@ -40,103 +39,38 @@ void ConnectionStyle::setConnectionStyle(QString jsonText) StyleCollection::setConnectionStyle(style); } -#ifdef STYLE_DEBUG -#define CONNECTION_STYLE_CHECK_UNDEFINED_VALUE(v, variable) \ - { \ - if (v.type() == QJsonValue::Undefined || v.type() == QJsonValue::Null) \ - qWarning() << "Undefined value for parameter:" << #variable; \ - } -#else -#define CONNECTION_STYLE_CHECK_UNDEFINED_VALUE(v, variable) -#endif - -#define CONNECTION_VALUE_EXISTS(v) \ - (v.type() != QJsonValue::Undefined && v.type() != QJsonValue::Null) - -#define CONNECTION_STYLE_READ_COLOR(values, variable) \ - { \ - auto valueRef = values[#variable]; \ - CONNECTION_STYLE_CHECK_UNDEFINED_VALUE(valueRef, variable) \ - if (CONNECTION_VALUE_EXISTS(valueRef)) { \ - if (valueRef.isArray()) { \ - auto colorArray = valueRef.toArray(); \ - std::vector rgb; \ - rgb.reserve(3); \ - for (auto it = colorArray.begin(); it != colorArray.end(); ++it) { \ - rgb.push_back((*it).toInt()); \ - } \ - variable = QColor(rgb[0], rgb[1], rgb[2]); \ - } else { \ - variable = QColor(valueRef.toString()); \ - } \ - } \ - } - -#define CONNECTION_STYLE_WRITE_COLOR(values, variable) \ - { \ - values[#variable] = variable.name(); \ - } - -#define CONNECTION_STYLE_READ_FLOAT(values, variable) \ - { \ - auto valueRef = values[#variable]; \ - CONNECTION_STYLE_CHECK_UNDEFINED_VALUE(valueRef, variable) \ - if (CONNECTION_VALUE_EXISTS(valueRef)) \ - variable = valueRef.toDouble(); \ - } - -#define CONNECTION_STYLE_WRITE_FLOAT(values, variable) \ - { \ - values[#variable] = variable; \ - } - -#define CONNECTION_STYLE_READ_BOOL(values, variable) \ - { \ - auto valueRef = values[#variable]; \ - CONNECTION_STYLE_CHECK_UNDEFINED_VALUE(valueRef, variable) \ - if (CONNECTION_VALUE_EXISTS(valueRef)) \ - variable = valueRef.toBool(); \ - } - -#define CONNECTION_STYLE_WRITE_BOOL(values, variable) \ - { \ - values[#variable] = variable; \ - } - void ConnectionStyle::loadJson(QJsonObject const &json) { - QJsonValue nodeStyleValues = json["ConnectionStyle"]; - - QJsonObject obj = nodeStyleValues.toObject(); + QJsonObject obj = json["ConnectionStyle"].toObject(); - CONNECTION_STYLE_READ_COLOR(obj, ConstructionColor); - CONNECTION_STYLE_READ_COLOR(obj, NormalColor); - CONNECTION_STYLE_READ_COLOR(obj, SelectedColor); - CONNECTION_STYLE_READ_COLOR(obj, SelectedHaloColor); - CONNECTION_STYLE_READ_COLOR(obj, HoveredColor); + readColor(obj, "ConstructionColor", ConstructionColor); + readColor(obj, "NormalColor", NormalColor); + readColor(obj, "SelectedColor", SelectedColor); + readColor(obj, "SelectedHaloColor", SelectedHaloColor); + readColor(obj, "HoveredColor", HoveredColor); - CONNECTION_STYLE_READ_FLOAT(obj, LineWidth); - CONNECTION_STYLE_READ_FLOAT(obj, ConstructionLineWidth); - CONNECTION_STYLE_READ_FLOAT(obj, PointDiameter); + readFloat(obj, "LineWidth", LineWidth); + readFloat(obj, "ConstructionLineWidth", ConstructionLineWidth); + readFloat(obj, "PointDiameter", PointDiameter); - CONNECTION_STYLE_READ_BOOL(obj, UseDataDefinedColors); + readBool(obj, "UseDataDefinedColors", UseDataDefinedColors); } QJsonObject ConnectionStyle::toJson() const { QJsonObject obj; - CONNECTION_STYLE_WRITE_COLOR(obj, ConstructionColor); - CONNECTION_STYLE_WRITE_COLOR(obj, NormalColor); - CONNECTION_STYLE_WRITE_COLOR(obj, SelectedColor); - CONNECTION_STYLE_WRITE_COLOR(obj, SelectedHaloColor); - CONNECTION_STYLE_WRITE_COLOR(obj, HoveredColor); + writeColor(obj, "ConstructionColor", ConstructionColor); + writeColor(obj, "NormalColor", NormalColor); + writeColor(obj, "SelectedColor", SelectedColor); + writeColor(obj, "SelectedHaloColor", SelectedHaloColor); + writeColor(obj, "HoveredColor", HoveredColor); - CONNECTION_STYLE_WRITE_FLOAT(obj, LineWidth); - CONNECTION_STYLE_WRITE_FLOAT(obj, ConstructionLineWidth); - CONNECTION_STYLE_WRITE_FLOAT(obj, PointDiameter); + writeFloat(obj, "LineWidth", LineWidth); + writeFloat(obj, "ConstructionLineWidth", ConstructionLineWidth); + writeFloat(obj, "PointDiameter", PointDiameter); - CONNECTION_STYLE_WRITE_BOOL(obj, UseDataDefinedColors); + writeBool(obj, "UseDataDefinedColors", UseDataDefinedColors); QJsonObject root; root["ConnectionStyle"] = obj; diff --git a/src/DataFlowGraphModel.cpp b/src/DataFlowGraphModel.cpp index d269dc9db..958ab0c8c 100644 --- a/src/DataFlowGraphModel.cpp +++ b/src/DataFlowGraphModel.cpp @@ -1,6 +1,7 @@ #include "DataFlowGraphModel.hpp" #include "ConnectionIdHash.hpp" +#include "ConnectionIdUtils.hpp" #include "Definitions.hpp" #include @@ -66,39 +67,7 @@ NodeId DataFlowGraphModel::addNode(QString const nodeType) if (model) { NodeId newId = newNodeId(); - connect(model.get(), - &NodeDelegateModel::dataUpdated, - [newId, this](PortIndex const portIndex) { - onOutPortDataUpdated(newId, portIndex); - }); - - connect(model.get(), - &NodeDelegateModel::portsAboutToBeDeleted, - this, - [newId, this](PortType const portType, PortIndex const first, PortIndex const last) { - portsAboutToBeDeleted(newId, portType, first, last); - }); - - connect(model.get(), - &NodeDelegateModel::portsDeleted, - this, - &DataFlowGraphModel::portsDeleted); - - connect(model.get(), - &NodeDelegateModel::portsAboutToBeInserted, - this, - [newId, this](PortType const portType, PortIndex const first, PortIndex const last) { - portsAboutToBeInserted(newId, portType, first, last); - }); - - connect(model.get(), - &NodeDelegateModel::portsInserted, - this, - &DataFlowGraphModel::portsInserted); - - connect(model.get(), &NodeDelegateModel::requestNodeUpdate, this, [newId, this]() { - Q_EMIT nodeUpdated(newId); - }); + connectDelegateModel(model.get(), newId); _models[newId] = std::move(model); @@ -120,10 +89,7 @@ bool DataFlowGraphModel::connectionPossible(ConnectionId const connectionId) con // Check port bounds, i.e. that we do not connect non-existing port numbers auto checkPortBounds = [&](PortType const portType) { NodeId const nodeId = getNodeId(portType, connectionId); - auto portCountRole = (portType == PortType::Out) ? NodeRole::OutPortCount - : NodeRole::InPortCount; - - std::size_t const portCount = nodeData(nodeId, portCountRole).toUInt(); + std::size_t const portCount = nodeData(nodeId, portCountRole(portType)).toUInt(); return getPortIndex(portType, connectionId) < portCount; }; @@ -203,6 +169,43 @@ void DataFlowGraphModel::addConnection(ConnectionId const connectionId) PortRole::Data); } +void DataFlowGraphModel::connectDelegateModel(NodeDelegateModel *model, NodeId nodeId) +{ + connect(model, + &NodeDelegateModel::dataUpdated, + [nodeId, this](PortIndex const portIndex) { + onOutPortDataUpdated(nodeId, portIndex); + }); + + connect(model, + &NodeDelegateModel::portsAboutToBeDeleted, + this, + [nodeId, this](PortType const portType, PortIndex const first, PortIndex const last) { + portsAboutToBeDeleted(nodeId, portType, first, last); + }); + + connect(model, + &NodeDelegateModel::portsDeleted, + this, + &DataFlowGraphModel::portsDeleted); + + connect(model, + &NodeDelegateModel::portsAboutToBeInserted, + this, + [nodeId, this](PortType const portType, PortIndex const first, PortIndex const last) { + portsAboutToBeInserted(nodeId, portType, first, last); + }); + + connect(model, + &NodeDelegateModel::portsInserted, + this, + &DataFlowGraphModel::portsInserted); + + connect(model, &NodeDelegateModel::requestNodeUpdate, this, [nodeId, this]() { + Q_EMIT nodeUpdated(nodeId); + }); +} + void DataFlowGraphModel::sendConnectionCreation(ConnectionId const connectionId) { Q_EMIT connectionCreated(connectionId); @@ -558,41 +561,7 @@ void DataFlowGraphModel::loadNode(QJsonObject const &nodeJson) std::unique_ptr model = _registry->create(delegateModelName); if (model) { - connect(model.get(), - &NodeDelegateModel::dataUpdated, - [restoredNodeId, this](PortIndex const portIndex) { - onOutPortDataUpdated(restoredNodeId, portIndex); - }); - - connect(model.get(), - &NodeDelegateModel::portsAboutToBeDeleted, - this, - [restoredNodeId, - this](PortType const portType, PortIndex const first, PortIndex const last) { - portsAboutToBeDeleted(restoredNodeId, portType, first, last); - }); - - connect(model.get(), - &NodeDelegateModel::portsDeleted, - this, - &DataFlowGraphModel::portsDeleted); - - connect(model.get(), - &NodeDelegateModel::portsAboutToBeInserted, - this, - [restoredNodeId, - this](PortType const portType, PortIndex const first, PortIndex const last) { - portsAboutToBeInserted(restoredNodeId, portType, first, last); - }); - - connect(model.get(), - &NodeDelegateModel::portsInserted, - this, - &DataFlowGraphModel::portsInserted); - - connect(model.get(), &NodeDelegateModel::requestNodeUpdate, this, [restoredNodeId, this]() { - Q_EMIT nodeUpdated(restoredNodeId); - }); + connectDelegateModel(model.get(), restoredNodeId); _models[restoredNodeId] = std::move(model); diff --git a/src/DefaultHorizontalNodeGeometry.cpp b/src/DefaultHorizontalNodeGeometry.cpp index f7f8c6324..eebf1a699 100644 --- a/src/DefaultHorizontalNodeGeometry.cpp +++ b/src/DefaultHorizontalNodeGeometry.cpp @@ -1,6 +1,7 @@ #include "DefaultHorizontalNodeGeometry.hpp" #include "AbstractGraphModel.hpp" +#include "ConnectionIdUtils.hpp" #include "NodeRenderingUtils.hpp" #include "NodeData.hpp" @@ -227,11 +228,7 @@ unsigned int DefaultHorizontalNodeGeometry::maxPortsTextAdvance(NodeId const nod { unsigned int width = 0; - size_t const n = _graphModel - .nodeData(nodeId, - (portType == PortType::Out) ? NodeRole::OutPortCount - : NodeRole::InPortCount) - .toUInt(); + size_t const n = _graphModel.nodeData(nodeId, portCountRole(portType)).toUInt(); for (PortIndex portIndex = 0ul; portIndex < n; ++portIndex) { QString name; diff --git a/src/DefaultNodePainter.cpp b/src/DefaultNodePainter.cpp index 9830d1b1e..6e344bef5 100644 --- a/src/DefaultNodePainter.cpp +++ b/src/DefaultNodePainter.cpp @@ -477,9 +477,7 @@ void DefaultNodePainter::drawConnectionPoints(QPainter *painter, NodeGraphicsObj auto reducedDiameter = diameter * 0.6; for (PortType portType : {PortType::Out, PortType::In}) { - auto portCountRole = (portType == PortType::Out) ? NodeRole::OutPortCount - : NodeRole::InPortCount; - size_t const n = model.nodeData(nodeId, portCountRole).toUInt(); + size_t const n = model.nodeData(nodeId, portCountRole(portType)).toUInt(); for (PortIndex portIndex = 0; portIndex < n; ++portIndex) { QPointF p = geometry.portPosition(nodeId, portType, portIndex); @@ -541,11 +539,7 @@ void DefaultNodePainter::drawFilledConnectionPoints(QPainter *painter, NodeGraph auto diameter = nodeStyle.ConnectionPointDiameter; for (PortType portType : {PortType::Out, PortType::In}) { - size_t const n = model - .nodeData(nodeId, - (portType == PortType::Out) ? NodeRole::OutPortCount - : NodeRole::InPortCount) - .toUInt(); + size_t const n = model.nodeData(nodeId, portCountRole(portType)).toUInt(); for (PortIndex portIndex = 0; portIndex < n; ++portIndex) { QPointF p = geometry.portPosition(nodeId, portType, portIndex); @@ -611,10 +605,7 @@ void DefaultNodePainter::drawEntryLabels(QPainter *painter, NodeGraphicsObject & AbstractNodeGeometry &geometry = ngo.nodeScene()->nodeGeometry(); for (PortType portType : {PortType::Out, PortType::In}) { - unsigned int n = model.nodeData(nodeId, - (portType == PortType::Out) - ? NodeRole::OutPortCount - : NodeRole::InPortCount); + unsigned int n = model.nodeData(nodeId, portCountRole(portType)); for (PortIndex portIndex = 0; portIndex < n; ++portIndex) { auto const &connected = model.connections(nodeId, portType, portIndex); diff --git a/src/DefaultVerticalNodeGeometry.cpp b/src/DefaultVerticalNodeGeometry.cpp index 08d89b19a..43a9c8d0c 100644 --- a/src/DefaultVerticalNodeGeometry.cpp +++ b/src/DefaultVerticalNodeGeometry.cpp @@ -1,6 +1,7 @@ #include "DefaultVerticalNodeGeometry.hpp" #include "AbstractGraphModel.hpp" +#include "ConnectionIdUtils.hpp" #include "NodeRenderingUtils.hpp" #include "NodeData.hpp" @@ -247,11 +248,7 @@ unsigned int DefaultVerticalNodeGeometry::maxPortsTextAdvance(NodeId const nodeI { unsigned int width = 0; - size_t const n = _graphModel - .nodeData(nodeId, - (portType == PortType::Out) ? NodeRole::OutPortCount - : NodeRole::InPortCount) - .toUInt(); + size_t const n = _graphModel.nodeData(nodeId, portCountRole(portType)).toUInt(); for (PortIndex portIndex = 0ul; portIndex < n; ++portIndex) { QString name; diff --git a/src/GraphicsViewStyle.cpp b/src/GraphicsViewStyle.cpp index 3138e8eee..c09645f30 100644 --- a/src/GraphicsViewStyle.cpp +++ b/src/GraphicsViewStyle.cpp @@ -2,13 +2,10 @@ #include "StyleCollection.hpp" -#include -#include #include -#include - using QtNodes::GraphicsViewStyle; +using namespace QtNodes::detail; inline void initResources() { @@ -37,56 +34,22 @@ void GraphicsViewStyle::setStyle(QString jsonText) StyleCollection::setGraphicsViewStyle(style); } -#ifdef STYLE_DEBUG -#define FLOW_VIEW_STYLE_CHECK_UNDEFINED_VALUE(v, variable) \ - { \ - if (v.type() == QJsonValue::Undefined || v.type() == QJsonValue::Null) \ - qWarning() << "Undefined value for parameter:" << #variable; \ - } -#else -#define FLOW_VIEW_STYLE_CHECK_UNDEFINED_VALUE(v, variable) -#endif - -#define FLOW_VIEW_STYLE_READ_COLOR(values, variable) \ - { \ - auto valueRef = values[#variable]; \ - FLOW_VIEW_STYLE_CHECK_UNDEFINED_VALUE(valueRef, variable) \ - if (valueRef.isArray()) { \ - auto colorArray = valueRef.toArray(); \ - std::vector rgb; \ - rgb.reserve(3); \ - for (auto it = colorArray.begin(); it != colorArray.end(); ++it) { \ - rgb.push_back((*it).toInt()); \ - } \ - variable = QColor(rgb[0], rgb[1], rgb[2]); \ - } else { \ - variable = QColor(valueRef.toString()); \ - } \ - } - -#define FLOW_VIEW_STYLE_WRITE_COLOR(values, variable) \ - { \ - values[#variable] = variable.name(); \ - } - void GraphicsViewStyle::loadJson(QJsonObject const &json) { - QJsonValue nodeStyleValues = json["GraphicsViewStyle"]; - - QJsonObject obj = nodeStyleValues.toObject(); + QJsonObject obj = json["GraphicsViewStyle"].toObject(); - FLOW_VIEW_STYLE_READ_COLOR(obj, BackgroundColor); - FLOW_VIEW_STYLE_READ_COLOR(obj, FineGridColor); - FLOW_VIEW_STYLE_READ_COLOR(obj, CoarseGridColor); + readColor(obj, "BackgroundColor", BackgroundColor); + readColor(obj, "FineGridColor", FineGridColor); + readColor(obj, "CoarseGridColor", CoarseGridColor); } QJsonObject GraphicsViewStyle::toJson() const { QJsonObject obj; - FLOW_VIEW_STYLE_WRITE_COLOR(obj, BackgroundColor); - FLOW_VIEW_STYLE_WRITE_COLOR(obj, FineGridColor); - FLOW_VIEW_STYLE_WRITE_COLOR(obj, CoarseGridColor); + writeColor(obj, "BackgroundColor", BackgroundColor); + writeColor(obj, "FineGridColor", FineGridColor); + writeColor(obj, "CoarseGridColor", CoarseGridColor); QJsonObject root; root["GraphicsViewStyle"] = obj; diff --git a/src/NodeGraphicsObject.cpp b/src/NodeGraphicsObject.cpp index 98719b041..1b2e8331b 100644 --- a/src/NodeGraphicsObject.cpp +++ b/src/NodeGraphicsObject.cpp @@ -147,7 +147,7 @@ void NodeGraphicsObject::embedQWidget() updateQWidgetEmbedPos(); - //update(); + _proxyWidget->setOpacity(1.0); _proxyWidget->setFlag(QGraphicsItem::ItemIgnoresParentOpacity); @@ -169,7 +169,6 @@ QRectF NodeGraphicsObject::boundingRect() const { AbstractNodeGeometry &geometry = nodeScene()->nodeGeometry(); return geometry.boundingRect(_nodeId); - //return NodeGeometry(_nodeId, _graphModel, nodeScene()).boundingRect(); } void NodeGraphicsObject::setGeometryChanged() @@ -460,10 +459,9 @@ void NodeGraphicsObject::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { auto pos = event->pos(); - //NodeGeometry geometry(_nodeId, _graphModel, nodeScene()); AbstractNodeGeometry &geometry = nodeScene()->nodeGeometry(); - if ((_graphModel.nodeFlags(_nodeId) | NodeFlag::Resizable) + if ((_graphModel.nodeFlags(_nodeId) & NodeFlag::Resizable) && geometry.resizeHandleRect(_nodeId).contains(QPoint(pos.x(), pos.y()))) { setCursor(QCursor(Qt::SizeFDiagCursor)); } else { diff --git a/src/NodeStyle.cpp b/src/NodeStyle.cpp index 0cfacf51b..9702373e6 100644 --- a/src/NodeStyle.cpp +++ b/src/NodeStyle.cpp @@ -2,13 +2,12 @@ #include "StyleCollection.hpp" -#include #include -#include #include using QtNodes::NodeStyle; +using namespace QtNodes::detail; inline void initResources() { @@ -50,114 +49,56 @@ void NodeStyle::setNodeStyle(QString jsonText) StyleCollection::setNodeStyle(style); } -#ifdef STYLE_DEBUG -#define NODE_STYLE_CHECK_UNDEFINED_VALUE(v, variable) \ - { \ - if (v.type() == QJsonValue::Undefined || v.type() == QJsonValue::Null) \ - qWarning() << "Undefined value for parameter:" << #variable; \ - } -#else -#define NODE_STYLE_CHECK_UNDEFINED_VALUE(v, variable) -#endif - -#define NODE_STYLE_READ_COLOR(values, variable) \ - { \ - auto valueRef = values[#variable]; \ - NODE_STYLE_CHECK_UNDEFINED_VALUE(valueRef, variable) \ - if (valueRef.isArray()) { \ - auto colorArray = valueRef.toArray(); \ - std::vector rgb; \ - rgb.reserve(3); \ - for (auto it = colorArray.begin(); it != colorArray.end(); ++it) { \ - rgb.push_back((*it).toInt()); \ - } \ - variable = QColor(rgb[0], rgb[1], rgb[2]); \ - } else { \ - variable = QColor(valueRef.toString()); \ - } \ - } - -#define NODE_STYLE_WRITE_COLOR(values, variable) \ - { \ - values[#variable] = variable.name(); \ - } - -#define NODE_STYLE_READ_FLOAT(values, variable) \ - { \ - auto valueRef = values[#variable]; \ - NODE_STYLE_CHECK_UNDEFINED_VALUE(valueRef, variable) \ - variable = valueRef.toDouble(); \ - } - -#define NODE_STYLE_WRITE_FLOAT(values, variable) \ - { \ - values[#variable] = variable; \ - } - -#define NODE_STYLE_READ_BOOL(values, variable) \ - { \ - auto valueRef = values[#variable]; \ - NODE_STYLE_CHECK_UNDEFINED_VALUE(valueRef, variable) \ - variable = valueRef.toBool(); \ - } - -#define NODE_STYLE_WRITE_BOOL(values, variable) \ - { \ - values[#variable] = variable; \ - } - void NodeStyle::loadJson(QJsonObject const &json) { - QJsonValue nodeStyleValues = json["NodeStyle"]; - - QJsonObject obj = nodeStyleValues.toObject(); - - NODE_STYLE_READ_COLOR(obj, NormalBoundaryColor); - NODE_STYLE_READ_COLOR(obj, SelectedBoundaryColor); - NODE_STYLE_READ_COLOR(obj, GradientColor0); - NODE_STYLE_READ_COLOR(obj, GradientColor1); - NODE_STYLE_READ_COLOR(obj, GradientColor2); - NODE_STYLE_READ_COLOR(obj, GradientColor3); - NODE_STYLE_READ_COLOR(obj, ShadowColor); - NODE_STYLE_READ_BOOL(obj, ShadowEnabled); - NODE_STYLE_READ_COLOR(obj, FontColor); - NODE_STYLE_READ_COLOR(obj, FontColorFaded); - NODE_STYLE_READ_COLOR(obj, ConnectionPointColor); - NODE_STYLE_READ_COLOR(obj, FilledConnectionPointColor); - NODE_STYLE_READ_COLOR(obj, WarningColor); - NODE_STYLE_READ_COLOR(obj, ErrorColor); - - NODE_STYLE_READ_FLOAT(obj, PenWidth); - NODE_STYLE_READ_FLOAT(obj, HoveredPenWidth); - NODE_STYLE_READ_FLOAT(obj, ConnectionPointDiameter); - - NODE_STYLE_READ_FLOAT(obj, Opacity); + QJsonObject obj = json["NodeStyle"].toObject(); + + readColor(obj, "NormalBoundaryColor", NormalBoundaryColor); + readColor(obj, "SelectedBoundaryColor", SelectedBoundaryColor); + readColor(obj, "GradientColor0", GradientColor0); + readColor(obj, "GradientColor1", GradientColor1); + readColor(obj, "GradientColor2", GradientColor2); + readColor(obj, "GradientColor3", GradientColor3); + readColor(obj, "ShadowColor", ShadowColor); + readBool(obj, "ShadowEnabled", ShadowEnabled); + readColor(obj, "FontColor", FontColor); + readColor(obj, "FontColorFaded", FontColorFaded); + readColor(obj, "ConnectionPointColor", ConnectionPointColor); + readColor(obj, "FilledConnectionPointColor", FilledConnectionPointColor); + readColor(obj, "WarningColor", WarningColor); + readColor(obj, "ErrorColor", ErrorColor); + + readFloat(obj, "PenWidth", PenWidth); + readFloat(obj, "HoveredPenWidth", HoveredPenWidth); + readFloat(obj, "ConnectionPointDiameter", ConnectionPointDiameter); + + readFloat(obj, "Opacity", Opacity); } QJsonObject NodeStyle::toJson() const { QJsonObject obj; - NODE_STYLE_WRITE_COLOR(obj, NormalBoundaryColor); - NODE_STYLE_WRITE_COLOR(obj, SelectedBoundaryColor); - NODE_STYLE_WRITE_COLOR(obj, GradientColor0); - NODE_STYLE_WRITE_COLOR(obj, GradientColor1); - NODE_STYLE_WRITE_COLOR(obj, GradientColor2); - NODE_STYLE_WRITE_COLOR(obj, GradientColor3); - NODE_STYLE_WRITE_COLOR(obj, ShadowColor); - NODE_STYLE_WRITE_BOOL(obj, ShadowEnabled); - NODE_STYLE_WRITE_COLOR(obj, FontColor); - NODE_STYLE_WRITE_COLOR(obj, FontColorFaded); - NODE_STYLE_WRITE_COLOR(obj, ConnectionPointColor); - NODE_STYLE_WRITE_COLOR(obj, FilledConnectionPointColor); - NODE_STYLE_WRITE_COLOR(obj, WarningColor); - NODE_STYLE_WRITE_COLOR(obj, ErrorColor); - - NODE_STYLE_WRITE_FLOAT(obj, PenWidth); - NODE_STYLE_WRITE_FLOAT(obj, HoveredPenWidth); - NODE_STYLE_WRITE_FLOAT(obj, ConnectionPointDiameter); - - NODE_STYLE_WRITE_FLOAT(obj, Opacity); + writeColor(obj, "NormalBoundaryColor", NormalBoundaryColor); + writeColor(obj, "SelectedBoundaryColor", SelectedBoundaryColor); + writeColor(obj, "GradientColor0", GradientColor0); + writeColor(obj, "GradientColor1", GradientColor1); + writeColor(obj, "GradientColor2", GradientColor2); + writeColor(obj, "GradientColor3", GradientColor3); + writeColor(obj, "ShadowColor", ShadowColor); + writeBool(obj, "ShadowEnabled", ShadowEnabled); + writeColor(obj, "FontColor", FontColor); + writeColor(obj, "FontColorFaded", FontColorFaded); + writeColor(obj, "ConnectionPointColor", ConnectionPointColor); + writeColor(obj, "FilledConnectionPointColor", FilledConnectionPointColor); + writeColor(obj, "WarningColor", WarningColor); + writeColor(obj, "ErrorColor", ErrorColor); + + writeFloat(obj, "PenWidth", PenWidth); + writeFloat(obj, "HoveredPenWidth", HoveredPenWidth); + writeFloat(obj, "ConnectionPointDiameter", ConnectionPointDiameter); + + writeFloat(obj, "Opacity", Opacity); QJsonObject root; root["NodeStyle"] = obj; From 6ac178bca06d53c4a410cf2a80be6fa4f6e1bb94 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Mar 2026 05:21:15 +0000 Subject: [PATCH 2/5] Remove dead code, unused includes, and stale forward declarations - Remove phantom forward declarations for non-existent classes: NodeDataModel, ConnectionGeometry, GraphModel, NodeGeometry - Remove redundant forward declarations where the header is already included (QPainter, ConnectionId, DataFlowGraphModel, etc.) - Remove unused forward declarations (NodeStyle, NodeState, StyleCollection, NodeDelegateModel, NodeConnectionInteraction, etc.) - Remove dead methods: connectionRequiredPort(), nodePortScenePosition(), connectionEndScenePosition() in NodeConnectionInteraction; addGraphicsEffect() in ConnectionGraphicsObject - Remove #if 0 blocks in NodeDelegateModelRegistry.hpp (old registerModel overloads, type converter API) - Remove unused includes: QUuid (3 headers), QUuidStdHash, iostream, QFile, QMessageBox, QMargins, QPointF, QIcon, QJsonObject, NodeConnectionInteraction, NodeState, ConnectionGraphicsObject - Remove duplicate includes: NodeState.hpp (NodeGraphicsObject.hpp), QColor (NodeDelegateModel.hpp) - Remove unused using declarations and variables: DataFlowGraphModel, NodeConnectionInteraction, NodeDataType, QVariant result in setPortData https://claude.ai/code/session_015aZAxLSpakeTpF7zaq6D2F --- .../internal/AbstractConnectionPainter.hpp | 2 - .../QtNodes/internal/AbstractNodePainter.hpp | 3 -- .../QtNodes/internal/BasicGraphicsScene.hpp | 5 --- .../internal/ConnectionGraphicsObject.hpp | 2 - include/QtNodes/internal/ConnectionState.hpp | 4 -- .../internal/DataFlowGraphicsScene.hpp | 2 - .../internal/DefaultConnectionPainter.hpp | 2 - .../DefaultHorizontalNodeGeometry.hpp | 1 - .../QtNodes/internal/DefaultNodePainter.hpp | 4 -- .../internal/DefaultVerticalNodeGeometry.hpp | 1 - .../internal/NodeConnectionInteraction.hpp | 6 --- .../QtNodes/internal/NodeDelegateModel.hpp | 3 -- .../internal/NodeDelegateModelRegistry.hpp | 39 ------------------- .../QtNodes/internal/NodeGraphicsObject.hpp | 3 -- include/QtNodes/internal/NodeGroup.hpp | 8 ---- src/AbstractNodeGeometry.cpp | 2 - src/BasicGraphicsScene.cpp | 1 - src/ConnectionGraphicsObject.cpp | 9 ----- src/ConnectionState.cpp | 1 - src/DataFlowGraphModel.cpp | 2 - src/NodeConnectionInteraction.cpp | 22 ----------- src/NodeDelegateModelRegistry.cpp | 4 -- src/NodeGroup.cpp | 3 -- 23 files changed, 129 deletions(-) diff --git a/include/QtNodes/internal/AbstractConnectionPainter.hpp b/include/QtNodes/internal/AbstractConnectionPainter.hpp index f838a0b99..fd81a1d4e 100644 --- a/include/QtNodes/internal/AbstractConnectionPainter.hpp +++ b/include/QtNodes/internal/AbstractConnectionPainter.hpp @@ -4,8 +4,6 @@ #include "Export.hpp" -class QPainter; - namespace QtNodes { class ConnectionGraphicsObject; diff --git a/include/QtNodes/internal/AbstractNodePainter.hpp b/include/QtNodes/internal/AbstractNodePainter.hpp index cd4c7d63e..aac648976 100644 --- a/include/QtNodes/internal/AbstractNodePainter.hpp +++ b/include/QtNodes/internal/AbstractNodePainter.hpp @@ -4,12 +4,9 @@ #include "Export.hpp" -class QPainter; - namespace QtNodes { class NodeGraphicsObject; -class NodeDataModel; /// Class enables custom painting. class NODE_EDITOR_PUBLIC AbstractNodePainter diff --git a/include/QtNodes/internal/BasicGraphicsScene.hpp b/include/QtNodes/internal/BasicGraphicsScene.hpp index 64b11d9a8..ff9e26d01 100644 --- a/include/QtNodes/internal/BasicGraphicsScene.hpp +++ b/include/QtNodes/internal/BasicGraphicsScene.hpp @@ -7,10 +7,7 @@ #include "Export.hpp" #include "GroupGraphicsObject.hpp" #include "NodeGroup.hpp" -#include "QUuidStdHash.hpp" #include "UndoCommands.hpp" -#include -#include #include #include @@ -28,12 +25,10 @@ class AbstractGraphModel; 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 diff --git a/include/QtNodes/internal/ConnectionGraphicsObject.hpp b/include/QtNodes/internal/ConnectionGraphicsObject.hpp index 435972efd..3f883e07f 100644 --- a/include/QtNodes/internal/ConnectionGraphicsObject.hpp +++ b/include/QtNodes/internal/ConnectionGraphicsObject.hpp @@ -90,8 +90,6 @@ class NODE_EDITOR_PUBLIC ConnectionGraphicsObject : public QGraphicsObject private: void initializePosition(); - void addGraphicsEffect(); - std::pair pointsC1C2Horizontal() const; std::pair pointsC1C2Vertical() const; diff --git a/include/QtNodes/internal/ConnectionState.hpp b/include/QtNodes/internal/ConnectionState.hpp index d13738260..6d1a5fcb1 100644 --- a/include/QtNodes/internal/ConnectionState.hpp +++ b/include/QtNodes/internal/ConnectionState.hpp @@ -1,13 +1,9 @@ #pragma once -#include - #include "Export.hpp" #include "Definitions.hpp" -class QPointF; - namespace QtNodes { class ConnectionGraphicsObject; diff --git a/include/QtNodes/internal/DataFlowGraphicsScene.hpp b/include/QtNodes/internal/DataFlowGraphicsScene.hpp index 30bcc9491..e928f830d 100644 --- a/include/QtNodes/internal/DataFlowGraphicsScene.hpp +++ b/include/QtNodes/internal/DataFlowGraphicsScene.hpp @@ -1,10 +1,8 @@ #pragma once #include "BasicGraphicsScene.hpp" -#include "ConnectionGraphicsObject.hpp" #include "DataFlowGraphModel.hpp" #include "Export.hpp" -#include "NodeConnectionInteraction.hpp" namespace QtNodes { diff --git a/include/QtNodes/internal/DefaultConnectionPainter.hpp b/include/QtNodes/internal/DefaultConnectionPainter.hpp index 42e79f1bb..f4c2913f9 100644 --- a/include/QtNodes/internal/DefaultConnectionPainter.hpp +++ b/include/QtNodes/internal/DefaultConnectionPainter.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include @@ -10,7 +9,6 @@ namespace QtNodes { -class ConnectionGeometry; class ConnectionGraphicsObject; class DefaultConnectionPainter : public AbstractConnectionPainter diff --git a/include/QtNodes/internal/DefaultHorizontalNodeGeometry.hpp b/include/QtNodes/internal/DefaultHorizontalNodeGeometry.hpp index 33367e109..22c34b1e0 100644 --- a/include/QtNodes/internal/DefaultHorizontalNodeGeometry.hpp +++ b/include/QtNodes/internal/DefaultHorizontalNodeGeometry.hpp @@ -7,7 +7,6 @@ namespace QtNodes { class AbstractGraphModel; -class BasicGraphicsScene; class NODE_EDITOR_PUBLIC DefaultHorizontalNodeGeometry : public AbstractNodeGeometry { diff --git a/include/QtNodes/internal/DefaultNodePainter.hpp b/include/QtNodes/internal/DefaultNodePainter.hpp index 3c763e5be..be4d1eb89 100644 --- a/include/QtNodes/internal/DefaultNodePainter.hpp +++ b/include/QtNodes/internal/DefaultNodePainter.hpp @@ -9,12 +9,8 @@ namespace QtNodes { -class BasicGraphicsScene; class GraphicsView; -class GraphModel; -class NodeGeometry; class NodeGraphicsObject; -class NodeState; /// @ Lightweight class incapsulating paint code. /// diff --git a/include/QtNodes/internal/DefaultVerticalNodeGeometry.hpp b/include/QtNodes/internal/DefaultVerticalNodeGeometry.hpp index ce4dd9f17..05cdb1a9d 100644 --- a/include/QtNodes/internal/DefaultVerticalNodeGeometry.hpp +++ b/include/QtNodes/internal/DefaultVerticalNodeGeometry.hpp @@ -7,7 +7,6 @@ namespace QtNodes { class AbstractGraphModel; -class BasicGraphicsScene; class NODE_EDITOR_PUBLIC DefaultVerticalNodeGeometry : public AbstractNodeGeometry { diff --git a/include/QtNodes/internal/NodeConnectionInteraction.hpp b/include/QtNodes/internal/NodeConnectionInteraction.hpp index f71ae97e0..4fe589d55 100644 --- a/include/QtNodes/internal/NodeConnectionInteraction.hpp +++ b/include/QtNodes/internal/NodeConnectionInteraction.hpp @@ -59,12 +59,6 @@ class NodeConnectionInteraction NodeGraphicsObject &nodeGraphicsObject() { return _ngo; } private: - PortType connectionRequiredPort() const; - - QPointF connectionEndScenePosition(PortType) const; - - QPointF nodePortScenePosition(PortType portType, PortIndex portIndex) const; - PortIndex nodePortIndexUnderScenePoint(PortType portType, QPointF const &p) const; private: diff --git a/include/QtNodes/internal/NodeDelegateModel.hpp b/include/QtNodes/internal/NodeDelegateModel.hpp index de0cc0736..5d1b776fc 100644 --- a/include/QtNodes/internal/NodeDelegateModel.hpp +++ b/include/QtNodes/internal/NodeDelegateModel.hpp @@ -14,7 +14,6 @@ #include "NodeData.hpp" #include "NodeStyle.hpp" #include "Serializable.hpp" -#include namespace QtNodes { @@ -49,8 +48,6 @@ enum class NodeProcessingStatus : int { Partial = 6, ///< Computation finished incompletely; only partial results are available. }; -class StyleCollection; - /** * The class wraps Node-specific data operations and propagates it to * the nesting DataFlowGraphModel which is a subclass of diff --git a/include/QtNodes/internal/NodeDelegateModelRegistry.hpp b/include/QtNodes/internal/NodeDelegateModelRegistry.hpp index 3ab66062b..86a462f50 100644 --- a/include/QtNodes/internal/NodeDelegateModelRegistry.hpp +++ b/include/QtNodes/internal/NodeDelegateModelRegistry.hpp @@ -27,8 +27,6 @@ class NODE_EDITOR_PUBLIC NodeDelegateModelRegistry using RegisteredModelsCategoryMap = std::unordered_map; using CategoriesSet = std::set; - //using RegisteredTypeConvertersMap = std::map; - NodeDelegateModelRegistry() = default; ~NodeDelegateModelRegistry() = default; @@ -68,33 +66,6 @@ class NODE_EDITOR_PUBLIC NodeDelegateModelRegistry } -#if 0 - template - void - registerModel(RegistryItemCreator creator, - QString const& category = "Nodes") - { - registerModel(std::move(creator), category); - } - - - template - void - registerModel(QString const& category, ModelCreator&& creator) - { - registerModel(std::forward(creator), category); - } - - - void - registerTypeConverter(TypeConverterId const& id, - TypeConverter typeConverter) - { - _registeredTypeConverters[id] = std::move(typeConverter); - } - -#endif - std::unique_ptr create(QString const &modelName); RegisteredModelCreatorsMap const ®isteredModelCreators() const; @@ -103,12 +74,6 @@ class NODE_EDITOR_PUBLIC NodeDelegateModelRegistry CategoriesSet const &categories() const; -#if 0 - TypeConverter - getTypeConverter(NodeDataType const& d1, - NodeDataType const& d2) const; -#endif - private: RegisteredModelsCategoryMap _registeredModelsCategory; @@ -116,10 +81,6 @@ class NODE_EDITOR_PUBLIC NodeDelegateModelRegistry RegisteredModelCreatorsMap _registeredItemCreators; -#if 0 - RegisteredTypeConvertersMap _registeredTypeConverters; -#endif - private: // If the registered ModelType class has the static member method // `static QString Name();`, use it. Otherwise use the non-static diff --git a/include/QtNodes/internal/NodeGraphicsObject.hpp b/include/QtNodes/internal/NodeGraphicsObject.hpp index e8cd640f1..bd7072912 100644 --- a/include/QtNodes/internal/NodeGraphicsObject.hpp +++ b/include/QtNodes/internal/NodeGraphicsObject.hpp @@ -5,11 +5,9 @@ #include "NodeState.hpp" #include #include -#include #include #include "Export.hpp" -#include "NodeState.hpp" class QGraphicsProxyWidget; @@ -19,7 +17,6 @@ class BasicGraphicsScene; class AbstractGraphModel; class GraphicsView; class NodeGroup; -class NodeDelegateModel; class GroupGraphicsObject; class NODE_EDITOR_PUBLIC NodeGraphicsObject : public QGraphicsObject diff --git a/include/QtNodes/internal/NodeGroup.hpp b/include/QtNodes/internal/NodeGroup.hpp index f9f6c5ab0..de27f8d76 100644 --- a/include/QtNodes/internal/NodeGroup.hpp +++ b/include/QtNodes/internal/NodeGroup.hpp @@ -4,21 +4,13 @@ #include #include -#include "DataFlowGraphModel.hpp" #include "Definitions.hpp" #include "Export.hpp" #include "GroupGraphicsObject.hpp" -#include "NodeConnectionInteraction.hpp" -#include "NodeState.hpp" namespace QtNodes { -class DataFlowGraphModel; -class GroupGraphicsObject; -class NodeState; -class NodeConnectionInteraction; class NodeGraphicsObject; -struct ConnectionId; /** * @brief The NodeGroup class defines a controller for node groups. It is diff --git a/src/AbstractNodeGeometry.cpp b/src/AbstractNodeGeometry.cpp index 8240ff6c5..0b20bccca 100644 --- a/src/AbstractNodeGeometry.cpp +++ b/src/AbstractNodeGeometry.cpp @@ -4,8 +4,6 @@ #include "ConnectionIdUtils.hpp" #include "StyleCollection.hpp" -#include - #include namespace QtNodes { diff --git a/src/BasicGraphicsScene.cpp b/src/BasicGraphicsScene.cpp index 724baa527..4b6b5b4c3 100644 --- a/src/BasicGraphicsScene.cpp +++ b/src/BasicGraphicsScene.cpp @@ -33,7 +33,6 @@ #include #include -#include #include #include #include diff --git a/src/ConnectionGraphicsObject.cpp b/src/ConnectionGraphicsObject.cpp index 931f76316..02f90c3b1 100644 --- a/src/ConnectionGraphicsObject.cpp +++ b/src/ConnectionGraphicsObject.cpp @@ -353,15 +353,6 @@ std::pair ConnectionGraphicsObject::pointsC1C2() const throw std::logic_error("Unreachable code after switch statement"); } -void ConnectionGraphicsObject::addGraphicsEffect() -{ - auto effect = new QGraphicsBlurEffect; - - effect->setBlurRadius(5); - setGraphicsEffect(effect); - -} - std::pair ConnectionGraphicsObject::pointsC1C2Horizontal() const { double const defaultOffset = 200; diff --git a/src/ConnectionState.cpp b/src/ConnectionState.cpp index 5b411a9b6..b279f77cd 100644 --- a/src/ConnectionState.cpp +++ b/src/ConnectionState.cpp @@ -5,7 +5,6 @@ #include "NodeGraphicsObject.hpp" #include -#include namespace QtNodes { diff --git a/src/DataFlowGraphModel.cpp b/src/DataFlowGraphModel.cpp index 958ab0c8c..4465558b0 100644 --- a/src/DataFlowGraphModel.cpp +++ b/src/DataFlowGraphModel.cpp @@ -436,8 +436,6 @@ bool DataFlowGraphModel::setPortData( { Q_UNUSED(nodeId); - QVariant result; - auto it = _models.find(nodeId); if (it == _models.end()) return false; diff --git a/src/NodeConnectionInteraction.cpp b/src/NodeConnectionInteraction.cpp index c43fe36f1..e44cad1cb 100644 --- a/src/NodeConnectionInteraction.cpp +++ b/src/NodeConnectionInteraction.cpp @@ -104,28 +104,6 @@ bool NodeConnectionInteraction::disconnect(PortType portToDisconnect) const return true; } -// ------------------ util functions below - -PortType NodeConnectionInteraction::connectionRequiredPort() const -{ - auto const &state = _cgo.connectionState(); - - return state.requiredPort(); -} - -QPointF NodeConnectionInteraction::nodePortScenePosition(PortType portType, - PortIndex portIndex) const -{ - AbstractNodeGeometry &geometry = _scene.nodeGeometry(); - - QPointF p = geometry.portScenePosition(_ngo.nodeId(), - portType, - portIndex, - _ngo.sceneTransform()); - - return p; -} - PortIndex NodeConnectionInteraction::nodePortIndexUnderScenePoint(PortType portType, QPointF const &scenePoint) const { diff --git a/src/NodeDelegateModelRegistry.cpp b/src/NodeDelegateModelRegistry.cpp index 11a1f84aa..1698c7538 100644 --- a/src/NodeDelegateModelRegistry.cpp +++ b/src/NodeDelegateModelRegistry.cpp @@ -1,9 +1,5 @@ #include "NodeDelegateModelRegistry.hpp" -#include -#include - -using QtNodes::NodeDataType; using QtNodes::NodeDelegateModel; using QtNodes::NodeDelegateModelRegistry; diff --git a/src/NodeGroup.cpp b/src/NodeGroup.cpp index 1c2149737..a414d9350 100644 --- a/src/NodeGroup.cpp +++ b/src/NodeGroup.cpp @@ -1,14 +1,11 @@ #include "NodeGroup.hpp" #include "ConnectionIdUtils.hpp" -#include "NodeConnectionInteraction.hpp" #include #include #include -using QtNodes::DataFlowGraphModel; using QtNodes::GroupGraphicsObject; -using QtNodes::NodeConnectionInteraction; using QtNodes::NodeGraphicsObject; using QtNodes::NodeGroup; using QtNodes::NodeId; From f61ea0d7234ce6d8437f9cf1fae5214b4232fb88 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Mar 2026 05:22:53 +0000 Subject: [PATCH 3/5] Fix broken NodeGeometry forwarding header and remove unused includes - Fix include/QtNodes/NodeGeometry: was pointing to non-existent internal/NodeGeometry.hpp, now correctly points to internal/AbstractNodeGeometry.hpp - Remove unused QVariant includes from QUuidStdHash.hpp and QStringStdHash.hpp - Remove unused QObject include from Style.hpp https://claude.ai/code/session_015aZAxLSpakeTpF7zaq6D2F --- include/QtNodes/NodeGeometry | 3 +-- include/QtNodes/internal/QStringStdHash.hpp | 1 - include/QtNodes/internal/QUuidStdHash.hpp | 1 - include/QtNodes/internal/Style.hpp | 1 - 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/include/QtNodes/NodeGeometry b/include/QtNodes/NodeGeometry index 46a70a6d7..c4265e1dd 100644 --- a/include/QtNodes/NodeGeometry +++ b/include/QtNodes/NodeGeometry @@ -1,2 +1 @@ -#include "internal/NodeGeometry.hpp" - +#include "internal/AbstractNodeGeometry.hpp" diff --git a/include/QtNodes/internal/QStringStdHash.hpp b/include/QtNodes/internal/QStringStdHash.hpp index 617d9b50d..bbf7b8455 100644 --- a/include/QtNodes/internal/QStringStdHash.hpp +++ b/include/QtNodes/internal/QStringStdHash.hpp @@ -9,7 +9,6 @@ #include #include -#include namespace std { template<> diff --git a/include/QtNodes/internal/QUuidStdHash.hpp b/include/QtNodes/internal/QUuidStdHash.hpp index 224bc9f49..63ff51a5d 100644 --- a/include/QtNodes/internal/QUuidStdHash.hpp +++ b/include/QtNodes/internal/QUuidStdHash.hpp @@ -3,7 +3,6 @@ #include #include -#include namespace std { template<> diff --git a/include/QtNodes/internal/Style.hpp b/include/QtNodes/internal/Style.hpp index 262bdfadc..08af63006 100644 --- a/include/QtNodes/internal/Style.hpp +++ b/include/QtNodes/internal/Style.hpp @@ -5,7 +5,6 @@ #include #include #include -#include #include namespace QtNodes { From 864769b95bd3bcad9fcad5342dd6a6dfa1abe650 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 25 Mar 2026 05:27:56 +0000 Subject: [PATCH 4/5] Refactor: extract geometry base class, unify connection control points 1. Extract DefaultNodeGeometryBase from duplicated geometry classes DefaultHorizontalNodeGeometry and DefaultVerticalNodeGeometry shared ~120 lines of identical code (constructor, boundingRect, size, captionRect, portTextRect, maxPortsTextAdvance, maxPortsExtent, and all 4 member variables). Extract these into a new intermediate base class DefaultNodeGeometryBase, leaving only orientation-specific methods in the subclasses. 2. Unify pointsC1C2Horizontal/pointsC1C2Vertical These two methods had identical algorithmic structure with X/Y axes swapped. Replace with a single computeControlPoints(Qt::Orientation) method that parameterizes by axis. 3. Extract selectedItemsOfType template helper selectedNodes() and selectedGroups() shared the same iteration pattern over QGraphicsScene::selectedItems() with qgraphicsitem_cast. Extract into a local template function. https://claude.ai/code/session_015aZAxLSpakeTpF7zaq6D2F --- CMakeLists.txt | 1 + .../internal/ConnectionGraphicsObject.hpp | 4 +- .../DefaultHorizontalNodeGeometry.hpp | 28 +---- .../internal/DefaultNodeGeometryBase.hpp | 45 +++++++ .../internal/DefaultVerticalNodeGeometry.hpp | 27 +---- src/BasicGraphicsScene.cpp | 35 +++--- src/ConnectionGraphicsObject.cpp | 84 +++++-------- src/DefaultHorizontalNodeGeometry.cpp | 102 +--------------- src/DefaultNodeGeometryBase.cpp | 112 ++++++++++++++++++ src/DefaultVerticalNodeGeometry.cpp | 104 +--------------- 10 files changed, 214 insertions(+), 328 deletions(-) create mode 100644 include/QtNodes/internal/DefaultNodeGeometryBase.hpp create mode 100644 src/DefaultNodeGeometryBase.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d4f8a2d6..5cc0e7c4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,6 +72,7 @@ set(CPP_SOURCE_FILES src/DataFlowGraphModel.cpp src/DataFlowGraphicsScene.cpp src/DefaultConnectionPainter.cpp + src/DefaultNodeGeometryBase.cpp src/DefaultHorizontalNodeGeometry.cpp src/DefaultNodePainter.cpp src/DefaultVerticalNodeGeometry.cpp diff --git a/include/QtNodes/internal/ConnectionGraphicsObject.hpp b/include/QtNodes/internal/ConnectionGraphicsObject.hpp index 3f883e07f..7371391ae 100644 --- a/include/QtNodes/internal/ConnectionGraphicsObject.hpp +++ b/include/QtNodes/internal/ConnectionGraphicsObject.hpp @@ -90,9 +90,7 @@ class NODE_EDITOR_PUBLIC ConnectionGraphicsObject : public QGraphicsObject private: void initializePosition(); - std::pair pointsC1C2Horizontal() const; - - std::pair pointsC1C2Vertical() const; + std::pair computeControlPoints(Qt::Orientation orientation) const; void rebuildCachedGeometry() const; static constexpr int k_path_sample_count = 61; diff --git a/include/QtNodes/internal/DefaultHorizontalNodeGeometry.hpp b/include/QtNodes/internal/DefaultHorizontalNodeGeometry.hpp index 22c34b1e0..66abdec08 100644 --- a/include/QtNodes/internal/DefaultHorizontalNodeGeometry.hpp +++ b/include/QtNodes/internal/DefaultHorizontalNodeGeometry.hpp @@ -1,23 +1,17 @@ #pragma once -#include "AbstractNodeGeometry.hpp" - -#include +#include "DefaultNodeGeometryBase.hpp" namespace QtNodes { class AbstractGraphModel; -class NODE_EDITOR_PUBLIC DefaultHorizontalNodeGeometry : public AbstractNodeGeometry +class NODE_EDITOR_PUBLIC DefaultHorizontalNodeGeometry : public DefaultNodeGeometryBase { public: DefaultHorizontalNodeGeometry(AbstractGraphModel &graphModel); public: - QRectF boundingRect(NodeId const nodeId) const override; - - QSize size(NodeId const nodeId) const override; - void recomputeSize(NodeId const nodeId) const override; QPointF portPosition(NodeId const nodeId, @@ -29,31 +23,13 @@ class NODE_EDITOR_PUBLIC DefaultHorizontalNodeGeometry : public AbstractNodeGeom PortIndex const PortIndex) const override; QPointF captionPosition(NodeId const nodeId) const override; - QRectF captionRect(NodeId const nodeId) const override; - QPointF widgetPosition(NodeId const nodeId) const override; QRect resizeHandleRect(NodeId const nodeId) const override; private: - QRectF portTextRect(NodeId const nodeId, - PortType const portType, - PortIndex const portIndex) const; - /// Finds max number of ports and multiplies by (a port height + interval) unsigned int maxVerticalPortsExtent(NodeId const nodeId) const; - - unsigned int maxPortsTextAdvance(NodeId const nodeId, PortType const portType) const; - -private: - // Some variables are mutable because we need to change drawing - // metrics corresponding to fontMetrics but this doesn't change - // constness of the Node. - - mutable unsigned int _portSize; - unsigned int _portSpasing; - mutable QFontMetrics _fontMetrics; - mutable QFontMetrics _boldFontMetrics; }; } // namespace QtNodes diff --git a/include/QtNodes/internal/DefaultNodeGeometryBase.hpp b/include/QtNodes/internal/DefaultNodeGeometryBase.hpp new file mode 100644 index 000000000..704285ca1 --- /dev/null +++ b/include/QtNodes/internal/DefaultNodeGeometryBase.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include "AbstractNodeGeometry.hpp" + +#include + +namespace QtNodes { + +class AbstractGraphModel; + +/** + * Shared base for DefaultHorizontalNodeGeometry and DefaultVerticalNodeGeometry. + * + * Contains common member variables and methods that are identical in both + * orientations: boundingRect, size, captionRect, portTextRect, + * maxPortsTextAdvance, and maxPortsExtent. + */ +class NODE_EDITOR_PUBLIC DefaultNodeGeometryBase : public AbstractNodeGeometry +{ +public: + DefaultNodeGeometryBase(AbstractGraphModel &graphModel); + + QRectF boundingRect(NodeId const nodeId) const override; + + QSize size(NodeId const nodeId) const override; + + QRectF captionRect(NodeId const nodeId) const override; + +protected: + QRectF portTextRect(NodeId const nodeId, + PortType const portType, + PortIndex const portIndex) const; + + unsigned int maxPortsExtent(NodeId const nodeId) const; + + unsigned int maxPortsTextAdvance(NodeId const nodeId, PortType const portType) const; + +protected: + mutable unsigned int _portSize; + unsigned int _portSpasing; + mutable QFontMetrics _fontMetrics; + mutable QFontMetrics _boldFontMetrics; +}; + +} // namespace QtNodes diff --git a/include/QtNodes/internal/DefaultVerticalNodeGeometry.hpp b/include/QtNodes/internal/DefaultVerticalNodeGeometry.hpp index 05cdb1a9d..2fda46fde 100644 --- a/include/QtNodes/internal/DefaultVerticalNodeGeometry.hpp +++ b/include/QtNodes/internal/DefaultVerticalNodeGeometry.hpp @@ -1,23 +1,17 @@ #pragma once -#include "AbstractNodeGeometry.hpp" - -#include +#include "DefaultNodeGeometryBase.hpp" namespace QtNodes { class AbstractGraphModel; -class NODE_EDITOR_PUBLIC DefaultVerticalNodeGeometry : public AbstractNodeGeometry +class NODE_EDITOR_PUBLIC DefaultVerticalNodeGeometry : public DefaultNodeGeometryBase { public: DefaultVerticalNodeGeometry(AbstractGraphModel &graphModel); public: - QRectF boundingRect(NodeId const nodeId) const override; - - QSize size(NodeId const nodeId) const override; - void recomputeSize(NodeId const nodeId) const override; QPointF portPosition(NodeId const nodeId, @@ -30,32 +24,15 @@ class NODE_EDITOR_PUBLIC DefaultVerticalNodeGeometry : public AbstractNodeGeomet QPointF captionPosition(NodeId const nodeId) const override; - QRectF captionRect(NodeId const nodeId) const override; - QPointF widgetPosition(NodeId const nodeId) const override; QRect resizeHandleRect(NodeId const nodeId) const override; private: - QRectF portTextRect(NodeId const nodeId, - PortType const portType, - PortIndex const portIndex) const; /// Finds unsigned int maxHorizontalPortsExtent(NodeId const nodeId) const; - unsigned int maxPortsTextAdvance(NodeId const nodeId, PortType const portType) const; - unsigned int portCaptionsHeight(NodeId const nodeId, PortType const portType) const; - -private: - // Some variables are mutable because we need to change drawing - // metrics corresponding to fontMetrics but this doesn't change - // constness of the Node. - - mutable unsigned int _portSize; - unsigned int _portSpasing; - mutable QFontMetrics _fontMetrics; - mutable QFontMetrics _boldFontMetrics; }; } // namespace QtNodes diff --git a/src/BasicGraphicsScene.cpp b/src/BasicGraphicsScene.cpp index 4b6b5b4c3..850b27fc0 100644 --- a/src/BasicGraphicsScene.cpp +++ b/src/BasicGraphicsScene.cpp @@ -512,43 +512,36 @@ std::weak_ptr BasicGraphicsScene::createGroup(std::vector BasicGraphicsScene::selectedNodes() const +namespace { +template +std::vector selectedItemsOfType(QGraphicsScene const *scene) { - QList graphicsItems = selectedItems(); + QList graphicsItems = scene->selectedItems(); - std::vector result; + std::vector result; result.reserve(graphicsItems.size()); for (QGraphicsItem *item : graphicsItems) { - auto ngo = qgraphicsitem_cast(item); - - if (ngo) { - result.push_back(ngo); + if (auto typed = qgraphicsitem_cast(item)) { + result.push_back(typed); } } return result; } +} // namespace + +std::vector BasicGraphicsScene::selectedNodes() const +{ + return selectedItemsOfType(this); +} std::vector BasicGraphicsScene::selectedGroups() const { if (!_groupingEnabled) return {}; - QList graphicsItems = selectedItems(); - - std::vector result; - result.reserve(graphicsItems.size()); - - for (QGraphicsItem *item : graphicsItems) { - auto ngo = qgraphicsitem_cast(item); - - if (ngo) { - result.push_back(ngo); - } - } - - return result; + return selectedItemsOfType(this); } void BasicGraphicsScene::addNodeToGroup(NodeId nodeId, GroupId groupId) diff --git a/src/ConnectionGraphicsObject.cpp b/src/ConnectionGraphicsObject.cpp index 02f90c3b1..9abf21fb4 100644 --- a/src/ConnectionGraphicsObject.cpp +++ b/src/ConnectionGraphicsObject.cpp @@ -340,77 +340,53 @@ void ConnectionGraphicsObject::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) std::pair ConnectionGraphicsObject::pointsC1C2() const { - switch (nodeScene()->orientation()) { - case Qt::Horizontal: - return pointsC1C2Horizontal(); - break; - - case Qt::Vertical: - return pointsC1C2Vertical(); - break; - } - - throw std::logic_error("Unreachable code after switch statement"); + return computeControlPoints(nodeScene()->orientation()); } -std::pair ConnectionGraphicsObject::pointsC1C2Horizontal() const +std::pair ConnectionGraphicsObject::computeControlPoints( + Qt::Orientation orientation) const { double const defaultOffset = 200; - double xDistance = _in.x() - _out.x(); - - double horizontalOffset = qMin(defaultOffset, std::abs(xDistance)); - - double verticalOffset = 0; - - double ratioX = 0.5; - - if (xDistance <= 0) { - double yDistance = _in.y() - _out.y() + 20; - - double vector = yDistance < 0 ? -1.0 : 1.0; - - verticalOffset = qMin(defaultOffset, std::abs(yDistance)) * vector; - - ratioX = 1.0; - } - - horizontalOffset *= ratioX; - - QPointF c1(_out.x() + horizontalOffset, _out.y() + verticalOffset); - - QPointF c2(_in.x() - horizontalOffset, _in.y() - verticalOffset); - - return std::make_pair(c1, c2); -} - -std::pair ConnectionGraphicsObject::pointsC1C2Vertical() const -{ - double const defaultOffset = 200; + // In horizontal mode the primary axis is X; in vertical mode it is Y. + auto primary = [&](QPointF const &p) { + return orientation == Qt::Horizontal ? p.x() : p.y(); + }; + auto secondary = [&](QPointF const &p) { + return orientation == Qt::Horizontal ? p.y() : p.x(); + }; - double yDistance = _in.y() - _out.y(); + double primaryDistance = primary(_in) - primary(_out); - double verticalOffset = qMin(defaultOffset, std::abs(yDistance)); + double primaryOffset = qMin(defaultOffset, std::abs(primaryDistance)); - double horizontalOffset = 0; + double secondaryOffset = 0; - double ratioY = 0.5; + double ratio = 0.5; - if (yDistance <= 0) { - double xDistance = _in.x() - _out.x() + 20; + if (primaryDistance <= 0) { + double secDistance = secondary(_in) - secondary(_out) + 20; - double vector = xDistance < 0 ? -1.0 : 1.0; + double vector = secDistance < 0 ? -1.0 : 1.0; - horizontalOffset = qMin(defaultOffset, std::abs(xDistance)) * vector; + secondaryOffset = qMin(defaultOffset, std::abs(secDistance)) * vector; - ratioY = 1.0; + ratio = 1.0; } - verticalOffset *= ratioY; + primaryOffset *= ratio; - QPointF c1(_out.x() + horizontalOffset, _out.y() + verticalOffset); + double hOff, vOff; + if (orientation == Qt::Horizontal) { + hOff = primaryOffset; + vOff = secondaryOffset; + } else { + hOff = secondaryOffset; + vOff = primaryOffset; + } - QPointF c2(_in.x() - horizontalOffset, _in.y() - verticalOffset); + QPointF c1(_out.x() + hOff, _out.y() + vOff); + QPointF c2(_in.x() - hOff, _in.y() - vOff); return std::make_pair(c1, c2); } diff --git a/src/DefaultHorizontalNodeGeometry.cpp b/src/DefaultHorizontalNodeGeometry.cpp index eebf1a699..1e63a3847 100644 --- a/src/DefaultHorizontalNodeGeometry.cpp +++ b/src/DefaultHorizontalNodeGeometry.cpp @@ -1,48 +1,16 @@ #include "DefaultHorizontalNodeGeometry.hpp" #include "AbstractGraphModel.hpp" -#include "ConnectionIdUtils.hpp" -#include "NodeRenderingUtils.hpp" -#include "NodeData.hpp" #include #include #include -#include - namespace QtNodes { DefaultHorizontalNodeGeometry::DefaultHorizontalNodeGeometry(AbstractGraphModel &graphModel) - : AbstractNodeGeometry(graphModel) - , _portSize(20) - , _portSpasing(10) - , _fontMetrics(QFont()) - , _boldFontMetrics(QFont()) -{ - QFont f; - f.setBold(true); - _boldFontMetrics = QFontMetrics(f); - - _portSize = _fontMetrics.height(); -} - -QRectF DefaultHorizontalNodeGeometry::boundingRect(NodeId const nodeId) const -{ - QSize s = size(nodeId); - std::optional fallback_style; - NodeStyle const &style = node_rendering::resolved_node_style(_graphModel, nodeId, fallback_style); - QMarginsF const margins = node_rendering::node_visual_margins(style.ShadowEnabled); - - QRectF r(QPointF(0, 0), s); - - return r.marginsAdded(margins); -} - -QSize DefaultHorizontalNodeGeometry::size(NodeId const nodeId) const -{ - return _graphModel.nodeData(nodeId, NodeRole::Size); -} + : DefaultNodeGeometryBase(graphModel) +{} void DefaultHorizontalNodeGeometry::recomputeSize(NodeId const nodeId) const { @@ -149,16 +117,6 @@ QPointF DefaultHorizontalNodeGeometry::portTextPosition(NodeId const nodeId, return p; } -QRectF DefaultHorizontalNodeGeometry::captionRect(NodeId const nodeId) const -{ - if (!_graphModel.nodeData(nodeId, NodeRole::CaptionVisible)) - return QRect(); - - QString name = _graphModel.nodeData(nodeId, NodeRole::Caption); - - return _boldFontMetrics.boundingRect(name); -} - QPointF DefaultHorizontalNodeGeometry::captionPosition(NodeId const nodeId) const { QSize size = _graphModel.nodeData(nodeId, NodeRole::Size); @@ -195,63 +153,9 @@ QRect DefaultHorizontalNodeGeometry::resizeHandleRect(NodeId const nodeId) const return QRect(size.width() - _portSpasing, size.height() - _portSpasing, rectSize, rectSize); } -QRectF DefaultHorizontalNodeGeometry::portTextRect(NodeId const nodeId, - PortType const portType, - PortIndex const portIndex) const -{ - QString s; - if (_graphModel.portData(nodeId, portType, portIndex, PortRole::CaptionVisible)) { - s = _graphModel.portData(nodeId, portType, portIndex, PortRole::Caption); - } else { - auto portData = _graphModel.portData(nodeId, portType, portIndex, PortRole::DataType); - - s = portData.value().name; - } - - return _fontMetrics.boundingRect(s); -} - unsigned int DefaultHorizontalNodeGeometry::maxVerticalPortsExtent(NodeId const nodeId) const { - PortCount nInPorts = _graphModel.nodeData(nodeId, NodeRole::InPortCount); - - PortCount nOutPorts = _graphModel.nodeData(nodeId, NodeRole::OutPortCount); - - unsigned int maxNumOfEntries = std::max(nInPorts, nOutPorts); - unsigned int step = _portSize + _portSpasing; - - return step * maxNumOfEntries; -} - -unsigned int DefaultHorizontalNodeGeometry::maxPortsTextAdvance(NodeId const nodeId, - PortType const portType) const -{ - unsigned int width = 0; - - size_t const n = _graphModel.nodeData(nodeId, portCountRole(portType)).toUInt(); - - for (PortIndex portIndex = 0ul; portIndex < n; ++portIndex) { - QString name; - - if (_graphModel.portData(nodeId, portType, portIndex, PortRole::CaptionVisible)) { - name = _graphModel.portData(nodeId, portType, portIndex, PortRole::Caption); - } else { - NodeDataType portData = _graphModel.portData(nodeId, - portType, - portIndex, - PortRole::DataType); - - name = portData.name; - } - -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - width = std::max(unsigned(_fontMetrics.horizontalAdvance(name)), width); -#else - width = std::max(unsigned(_fontMetrics.width(name)), width); -#endif - } - - return width; + return maxPortsExtent(nodeId); } } // namespace QtNodes diff --git a/src/DefaultNodeGeometryBase.cpp b/src/DefaultNodeGeometryBase.cpp new file mode 100644 index 000000000..e032e7c3b --- /dev/null +++ b/src/DefaultNodeGeometryBase.cpp @@ -0,0 +1,112 @@ +#include "DefaultNodeGeometryBase.hpp" + +#include "AbstractGraphModel.hpp" +#include "ConnectionIdUtils.hpp" +#include "NodeRenderingUtils.hpp" +#include "NodeData.hpp" + +#include + +namespace QtNodes { + +DefaultNodeGeometryBase::DefaultNodeGeometryBase(AbstractGraphModel &graphModel) + : AbstractNodeGeometry(graphModel) + , _portSize(20) + , _portSpasing(10) + , _fontMetrics(QFont()) + , _boldFontMetrics(QFont()) +{ + QFont f; + f.setBold(true); + _boldFontMetrics = QFontMetrics(f); + + _portSize = _fontMetrics.height(); +} + +QRectF DefaultNodeGeometryBase::boundingRect(NodeId const nodeId) const +{ + QSize s = size(nodeId); + std::optional fallback_style; + NodeStyle const &style = node_rendering::resolved_node_style(_graphModel, nodeId, fallback_style); + QMarginsF const margins = node_rendering::node_visual_margins(style.ShadowEnabled); + + QRectF r(QPointF(0, 0), s); + + return r.marginsAdded(margins); +} + +QSize DefaultNodeGeometryBase::size(NodeId const nodeId) const +{ + return _graphModel.nodeData(nodeId, NodeRole::Size); +} + +QRectF DefaultNodeGeometryBase::captionRect(NodeId const nodeId) const +{ + if (!_graphModel.nodeData(nodeId, NodeRole::CaptionVisible)) + return QRect(); + + QString name = _graphModel.nodeData(nodeId, NodeRole::Caption); + + return _boldFontMetrics.boundingRect(name); +} + +QRectF DefaultNodeGeometryBase::portTextRect(NodeId const nodeId, + PortType const portType, + PortIndex const portIndex) const +{ + QString s; + if (_graphModel.portData(nodeId, portType, portIndex, PortRole::CaptionVisible)) { + s = _graphModel.portData(nodeId, portType, portIndex, PortRole::Caption); + } else { + auto portData = _graphModel.portData(nodeId, portType, portIndex, PortRole::DataType); + + s = portData.value().name; + } + + return _fontMetrics.boundingRect(s); +} + +unsigned int DefaultNodeGeometryBase::maxPortsExtent(NodeId const nodeId) const +{ + PortCount nInPorts = _graphModel.nodeData(nodeId, NodeRole::InPortCount); + + PortCount nOutPorts = _graphModel.nodeData(nodeId, NodeRole::OutPortCount); + + unsigned int maxNumOfEntries = std::max(nInPorts, nOutPorts); + unsigned int step = _portSize + _portSpasing; + + return step * maxNumOfEntries; +} + +unsigned int DefaultNodeGeometryBase::maxPortsTextAdvance(NodeId const nodeId, + PortType const portType) const +{ + unsigned int width = 0; + + size_t const n = _graphModel.nodeData(nodeId, portCountRole(portType)).toUInt(); + + for (PortIndex portIndex = 0ul; portIndex < n; ++portIndex) { + QString name; + + if (_graphModel.portData(nodeId, portType, portIndex, PortRole::CaptionVisible)) { + name = _graphModel.portData(nodeId, portType, portIndex, PortRole::Caption); + } else { + NodeDataType portData = _graphModel.portData(nodeId, + portType, + portIndex, + PortRole::DataType); + + name = portData.name; + } + +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + width = std::max(unsigned(_fontMetrics.horizontalAdvance(name)), width); +#else + width = std::max(unsigned(_fontMetrics.width(name)), width); +#endif + } + + return width; +} + +} // namespace QtNodes diff --git a/src/DefaultVerticalNodeGeometry.cpp b/src/DefaultVerticalNodeGeometry.cpp index 43a9c8d0c..cb2e4cbdd 100644 --- a/src/DefaultVerticalNodeGeometry.cpp +++ b/src/DefaultVerticalNodeGeometry.cpp @@ -1,52 +1,20 @@ #include "DefaultVerticalNodeGeometry.hpp" #include "AbstractGraphModel.hpp" -#include "ConnectionIdUtils.hpp" -#include "NodeRenderingUtils.hpp" -#include "NodeData.hpp" #include #include #include -#include - namespace QtNodes { DefaultVerticalNodeGeometry::DefaultVerticalNodeGeometry(AbstractGraphModel &graphModel) - : AbstractNodeGeometry(graphModel) - , _portSize(20) - , _portSpasing(10) - , _fontMetrics(QFont()) - , _boldFontMetrics(QFont()) -{ - QFont f; - f.setBold(true); - _boldFontMetrics = QFontMetrics(f); - - _portSize = _fontMetrics.height(); -} - -QRectF DefaultVerticalNodeGeometry::boundingRect(NodeId const nodeId) const -{ - QSize s = size(nodeId); - std::optional fallback_style; - NodeStyle const &style = node_rendering::resolved_node_style(_graphModel, nodeId, fallback_style); - QMarginsF const margins = node_rendering::node_visual_margins(style.ShadowEnabled); - - QRectF r(QPointF(0, 0), s); - - return r.marginsAdded(margins); -} - -QSize DefaultVerticalNodeGeometry::size(NodeId const nodeId) const -{ - return _graphModel.nodeData(nodeId, NodeRole::Size); -} + : DefaultNodeGeometryBase(graphModel) +{} void DefaultVerticalNodeGeometry::recomputeSize(NodeId const nodeId) const { - unsigned int height = _portSpasing; // maxHorizontalPortsExtent(nodeId); + unsigned int height = _portSpasing; if (auto w = _graphModel.nodeData(nodeId, NodeRole::Widget)) { height = std::max(height, static_cast(w->height())); @@ -165,16 +133,6 @@ QPointF DefaultVerticalNodeGeometry::portTextPosition(NodeId const nodeId, return p; } -QRectF DefaultVerticalNodeGeometry::captionRect(NodeId const nodeId) const -{ - if (!_graphModel.nodeData(nodeId, NodeRole::CaptionVisible)) - return QRect(); - - QString name = _graphModel.nodeData(nodeId, NodeRole::Caption); - - return _boldFontMetrics.boundingRect(name); -} - QPointF DefaultVerticalNodeGeometry::captionPosition(NodeId const nodeId) const { QSize size = _graphModel.nodeData(nodeId, NodeRole::Size); @@ -215,63 +173,9 @@ QRect DefaultVerticalNodeGeometry::resizeHandleRect(NodeId const nodeId) const return QRect(size.width() - rectSize, size.height() - rectSize, rectSize, rectSize); } -QRectF DefaultVerticalNodeGeometry::portTextRect(NodeId const nodeId, - PortType const portType, - PortIndex const portIndex) const -{ - QString s; - if (_graphModel.portData(nodeId, portType, portIndex, PortRole::CaptionVisible)) { - s = _graphModel.portData(nodeId, portType, portIndex, PortRole::Caption); - } else { - auto portData = _graphModel.portData(nodeId, portType, portIndex, PortRole::DataType); - - s = portData.value().name; - } - - return _fontMetrics.boundingRect(s); -} - unsigned int DefaultVerticalNodeGeometry::maxHorizontalPortsExtent(NodeId const nodeId) const { - PortCount nInPorts = _graphModel.nodeData(nodeId, NodeRole::InPortCount); - - PortCount nOutPorts = _graphModel.nodeData(nodeId, NodeRole::OutPortCount); - - unsigned int maxNumOfEntries = std::max(nInPorts, nOutPorts); - unsigned int step = _portSize + _portSpasing; - - return step * maxNumOfEntries; -} - -unsigned int DefaultVerticalNodeGeometry::maxPortsTextAdvance(NodeId const nodeId, - PortType const portType) const -{ - unsigned int width = 0; - - size_t const n = _graphModel.nodeData(nodeId, portCountRole(portType)).toUInt(); - - for (PortIndex portIndex = 0ul; portIndex < n; ++portIndex) { - QString name; - - if (_graphModel.portData(nodeId, portType, portIndex, PortRole::CaptionVisible)) { - name = _graphModel.portData(nodeId, portType, portIndex, PortRole::Caption); - } else { - NodeDataType portData = _graphModel.portData(nodeId, - portType, - portIndex, - PortRole::DataType); - - name = portData.name; - } - -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - width = std::max(unsigned(_fontMetrics.horizontalAdvance(name)), width); -#else - width = std::max(unsigned(_fontMetrics.width(name)), width); -#endif - } - - return width; + return maxPortsExtent(nodeId); } unsigned int DefaultVerticalNodeGeometry::portCaptionsHeight(NodeId const nodeId, From 67a8cd15f73c12444f9e8f8d6b1cf41db3629480 Mon Sep 17 00:00:00 2001 From: Ioannis Makris Date: Wed, 25 Mar 2026 06:42:26 +0100 Subject: [PATCH 5/5] Initialize NodeStyle primitive defaults --- include/QtNodes/internal/NodeStyle.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/QtNodes/internal/NodeStyle.hpp b/include/QtNodes/internal/NodeStyle.hpp index 01ecd2ea1..aa26ef83b 100644 --- a/include/QtNodes/internal/NodeStyle.hpp +++ b/include/QtNodes/internal/NodeStyle.hpp @@ -60,7 +60,7 @@ class NODE_EDITOR_PUBLIC NodeStyle : public Style QColor GradientColor2; QColor GradientColor3; QColor ShadowColor; - bool ShadowEnabled; + bool ShadowEnabled{false}; QColor FontColor; QColor FontColorFaded; @@ -71,12 +71,12 @@ class NODE_EDITOR_PUBLIC NodeStyle : public Style QColor ErrorColor; QColor ToolTipIconColor; - float PenWidth; - float HoveredPenWidth; + float PenWidth{0.0f}; + float HoveredPenWidth{0.0f}; - float ConnectionPointDiameter; + float ConnectionPointDiameter{0.0f}; - float Opacity; + float Opacity{0.0f}; // Status icons - initialized in constructor after Q_INIT_RESOURCE QIcon statusUpdated;