diff --git a/CMakeLists.txt b/CMakeLists.txt index 2dc02dbb0..8d2eff1dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,16 +1,13 @@ cmake_minimum_required(VERSION 3.8) -cmake_policy(SET CMP0072 NEW) # new in 3.11. The NEW behavior for this policy is to set OpenGL_GL_PREFERENCE to GLVND. -cmake_policy(SET CMP0068 NEW) # new in 3.9. The NEW behavior of this policy is to ignore the RPATH settings for install_name on macOS. - - project(QtNodesLibrary CXX) -set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") + +set(CMAKE_CXX_STANDARD 11) set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) -set(CMAKE_DISABLE_SOURCE_CHANGES ON) -set(OpenGL_GL_PREFERENCE LEGACY) +set(CMAKE_DISABLE_SOURCE_CHANGES ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) get_directory_property(_has_parent PARENT_DIRECTORY) @@ -53,7 +50,7 @@ else() find_package(QT NAMES Qt5 REQUIRED COMPONENTS Widgets) endif() -find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Widgets Gui OpenGL) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Widgets Gui Quick QuickWidgets) message(STATUS "QT_VERSION: ${QT_VERSION}, QT_DIR: ${QT_DIR}") if (${QT_VERSION} VERSION_LESS 5.11.0) @@ -161,7 +158,6 @@ target_link_libraries(QtNodes Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Gui - Qt${QT_VERSION_MAJOR}::OpenGL ) target_compile_definitions(QtNodes @@ -188,12 +184,6 @@ if(NOT "${CMAKE_CXX_SIMULATE_ID}" STREQUAL "MSVC") ) endif() -if(QT_NODES_DEVELOPER_DEFAULTS) - target_compile_features(QtNodes PUBLIC cxx_std_14) - set_target_properties(QtNodes PROPERTIES CXX_EXTENSIONS OFF) -endif() - - set_target_properties(QtNodes PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib diff --git a/cmake/QtNodesConfig.cmake.in b/cmake/QtNodesConfig.cmake.in index e08a6e9f5..14fc33450 100644 --- a/cmake/QtNodesConfig.cmake.in +++ b/cmake/QtNodesConfig.cmake.in @@ -1,4 +1,4 @@ -get_filename_component(QtNodes_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +@PACKAGE_INIT@ include(CMakeFindDependencyMacro) @@ -8,11 +8,6 @@ find_dependency(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets) find_dependency(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Widgets - Gui - OpenGL) + Gui) -if(NOT TARGET QtNodes::QtNodes) - include("${QtNodes_CMAKE_DIR}/QtNodesTargets.cmake") -endif() - -set(QtNodes_LIBRARIES QtNodes::QtNodes) +include("${CMAKE_CURRENT_LIST_DIR}/QtNodesTargets.cmake") diff --git a/docs/features.rst b/docs/features.rst index 536e57480..6b1e7efb9 100644 --- a/docs/features.rst +++ b/docs/features.rst @@ -26,7 +26,7 @@ The ``ConnectionId`` is nothing else but a combination of input and output :: - // Definitinos.hpp + // Definitions.hpp struct ConnectionId { NodeId outNodeId; @@ -369,7 +369,7 @@ redraw the receiver node and could be hooked up for other user's purposes. // Source Delegate Model -> source NodeId DataFlowGraphModel::onOutPortDataUpdated(NodeId, PortIndex) - // soure NodeId -> target NodeId + // source NodeId -> target NodeId DataFlowGraphModel::setPortData() // target NodeId -> target Delegate Model diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 49494da2e..0f59ceda8 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -16,3 +16,8 @@ add_subdirectory(dynamic_ports) add_subdirectory(lock_nodes_and_connections) +add_subdirectory(calculator_qml) + +add_subdirectory(acquisition_viewer) + +add_subdirectory(compute_viewer) diff --git a/examples/acquisition_viewer/AcqData.hpp b/examples/acquisition_viewer/AcqData.hpp new file mode 100644 index 000000000..301459f02 --- /dev/null +++ b/examples/acquisition_viewer/AcqData.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include + +using QtNodes::NodeData; +using QtNodes::NodeDataType; + +/// The class can potentially incapsulate any user data which +/// need to be transferred within the Node Editor graph +class AcqData : public NodeData +{ +public: + NodeDataType type() const override { return NodeDataType{"acquisition", ""}; } +}; diff --git a/examples/acquisition_viewer/AcqModel.cpp b/examples/acquisition_viewer/AcqModel.cpp new file mode 100644 index 000000000..ddfeee385 --- /dev/null +++ b/examples/acquisition_viewer/AcqModel.cpp @@ -0,0 +1,86 @@ +#include "AcqModel.hpp" +#include "AcqData.hpp" +#include +#include +#include +#include +#include +#include +#include + +using QtNodes::NodeStyle; + +unsigned int AcqModel::nPorts(PortType portType) const +{ + unsigned int result; + + if (portType == PortType::In) + result = 1; + else + result = 1; + + return result; +} + +NodeDataType AcqModel::dataType(PortType, PortIndex) const +{ + return AcqData().type(); +} + +std::shared_ptr AcqModel::outData(PortIndex) +{ + return std::static_pointer_cast(_result); +} + +void AcqModel::setInData(std::shared_ptr data, PortIndex portIndex) +{ + auto numberData = std::dynamic_pointer_cast(data); + + if (!data) { + Q_EMIT dataInvalidated(0); + } +} + +QWidget *AcqModel::embeddedWidget() +{ + if (_result) { + return nullptr; + } + + _result = std::make_shared(); + + if (_title.isEmpty()) { + bool ok; + + QString text = QInputDialog::getText(nullptr, + "Acquisition node", + "Title:", + QLineEdit::Normal, + "", + &ok); + if (ok && !text.isEmpty()) + _title = text; + } + + NodeStyle style; + style.GradientColor0 = {rand() % 256, rand() % 256, rand() % 256}; + style.GradientColor1 = {rand() % 256, rand() % 256, rand() % 256}; + style.GradientColor2 = {rand() % 256, rand() % 256, rand() % 256}; + style.GradientColor3 = {rand() % 256, rand() % 256, rand() % 256}; + setNodeStyle(style); + + return nullptr; +} + +QJsonObject AcqModel::save() const +{ + QJsonObject retval = NodeDelegateModel::save(); + retval["Title"] = _title; + return retval; +} + +void AcqModel::load(QJsonObject const &object) +{ + NodeDelegateModel::load(object); + _title = object["Title"].toString(); +} diff --git a/examples/acquisition_viewer/AcqModel.hpp b/examples/acquisition_viewer/AcqModel.hpp new file mode 100644 index 000000000..c58cc82c0 --- /dev/null +++ b/examples/acquisition_viewer/AcqModel.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +class AcqData; + +using QtNodes::ConnectionPolicy; +using QtNodes::NodeData; +using QtNodes::NodeDataType; +using QtNodes::NodeDelegateModel; +using QtNodes::PortIndex; +using QtNodes::PortType; + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class AcqModel : public NodeDelegateModel +{ + Q_OBJECT + +public: + ~AcqModel() override = default; + +public: + unsigned int nPorts(PortType portType) const override; + + NodeDataType dataType(PortType portType, PortIndex portIndex) const override; + + std::shared_ptr outData(PortIndex port) override; + + void setInData(std::shared_ptr data, PortIndex portIndex) override; + + QWidget *embeddedWidget() override; + + QString caption() const override { return _title; } + + QString name() const override { return QStringLiteral("Acquisition"); } + + ConnectionPolicy portConnectionPolicy(PortType, PortIndex) const override + { + return ConnectionPolicy::Many; + } + + QJsonObject save() const override; + + void load(QJsonObject const &) override; + +private: + std::shared_ptr _result; + QString _title; +}; diff --git a/examples/acquisition_viewer/CMakeLists.txt b/examples/acquisition_viewer/CMakeLists.txt new file mode 100644 index 000000000..81319308c --- /dev/null +++ b/examples/acquisition_viewer/CMakeLists.txt @@ -0,0 +1,16 @@ +set(ACQ_SOURCE_FILES main.cpp AcqModel.cpp) + +set(ACQ_HEADER_FILES AcqData.hpp AcqModel.hpp) + +add_executable(acquisition_viewer WIN32 ${ACQ_SOURCE_FILES} ${ACQ_HEADER_FILES} + CMakeLists.txt) + +target_link_libraries(acquisition_viewer QtNodes) + +if(WIN32 AND BUILD_SHARED_LIBS) + add_custom_command( + TARGET acquisition_viewer + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E env VCINSTALLDIR=${CMAKE_GENERATOR_INSTANCE}/VC + ${WINDEPLOYQT_EXECUTABLE} --pdb "$") +endif() diff --git a/examples/acquisition_viewer/main.cpp b/examples/acquisition_viewer/main.cpp new file mode 100644 index 000000000..8eb3fdaa3 --- /dev/null +++ b/examples/acquisition_viewer/main.cpp @@ -0,0 +1,96 @@ +#include "AcqModel.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using QtNodes::ConnectionStyle; +using QtNodes::DataFlowGraphicsScene; +using QtNodes::DataFlowGraphModel; +using QtNodes::GraphicsView; +using QtNodes::NodeDelegateModelRegistry; + +static std::shared_ptr registerDataModels() +{ + auto ret = std::make_shared(); + + ret->registerModel("Acquisition"); + + return ret; +} + +static void setStyle() +{ + /* + ConnectionStyle::setConnectionStyle( + R"( + { + "ConnectionStyle": { + "ConstructionColor": "gray", + "NormalColor": "black", + "SelectedColor": "gray", + "SelectedHaloColor": "deepskyblue", + "HoveredColor": "deepskyblue", + + "LineWidth": 3.0, + "ConstructionLineWidth": 2.0, + "PointDiameter": 10.0, + + "UseDataDefinedColors": true + } + } + )");*/ +} + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + setStyle(); + + std::shared_ptr registry = registerDataModels(); + + QWidget mainWidget; + + auto menuBar = new QMenuBar(); + QMenu *menu = menuBar->addMenu("File"); + auto saveAction = menu->addAction("Save Scene"); + auto loadAction = menu->addAction("Load Scene"); + + QVBoxLayout *l = new QVBoxLayout(&mainWidget); + + DataFlowGraphModel dataFlowGraphModel(registry); + + l->addWidget(menuBar); + auto scene = new DataFlowGraphicsScene(dataFlowGraphModel, &mainWidget); + + auto view = new GraphicsView(scene); + l->addWidget(view); + l->setContentsMargins(0, 0, 0, 0); + l->setSpacing(0); + + QObject::connect(saveAction, &QAction::triggered, scene, &DataFlowGraphicsScene::save); + + QObject::connect(loadAction, &QAction::triggered, scene, &DataFlowGraphicsScene::load); + + QObject::connect(scene, &DataFlowGraphicsScene::sceneLoaded, view, &GraphicsView::centerScene); + + mainWidget.setWindowTitle("Data Flow: simplest calculator"); + mainWidget.resize(800, 600); + // Center window. + mainWidget.move(QApplication::primaryScreen()->availableGeometry().center() + - mainWidget.rect().center()); + mainWidget.showNormal(); + + return app.exec(); +} diff --git a/examples/acquisition_viewer/render.png b/examples/acquisition_viewer/render.png new file mode 100644 index 000000000..bb41f557d Binary files /dev/null and b/examples/acquisition_viewer/render.png differ diff --git a/examples/acquisition_viewer/sample.flow b/examples/acquisition_viewer/sample.flow new file mode 100644 index 000000000..df88187ef --- /dev/null +++ b/examples/acquisition_viewer/sample.flow @@ -0,0 +1,171 @@ +{ + "connections": [ + { + "inPortIndex": 0, + "intNodeId": 4, + "outNodeId": 3, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 2, + "outNodeId": 3, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 6, + "outNodeId": 5, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 3, + "outNodeId": 2, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 1, + "outNodeId": 3, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 7, + "outNodeId": 6, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 3, + "outNodeId": 1, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 5, + "outNodeId": 4, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 8, + "outNodeId": 7, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 9, + "outNodeId": 8, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 3, + "outNodeId": 9, + "outPortIndex": 0 + } + ], + "nodes": [ + { + "id": 1, + "internal-data": { + "Title": "HD2", + "model-name": "Acquisition" + }, + "position": { + "x": 160, + "y": -34 + } + }, + { + "id": 2, + "internal-data": { + "Title": "Ultrafast", + "model-name": "Acquisition" + }, + "position": { + "x": 118, + "y": 206 + } + }, + { + "id": 3, + "internal-data": { + "Title": "BMode-25Hz", + "model-name": "Acquisition" + }, + "position": { + "x": -33, + "y": 159 + } + }, + { + "id": 4, + "internal-data": { + "Title": "Push #1", + "model-name": "Acquisition" + }, + "position": { + "x": 257, + "y": 160 + } + }, + { + "id": 5, + "internal-data": { + "Title": "Imaging #1", + "model-name": "Acquisition" + }, + "position": { + "x": 380, + "y": 159 + } + }, + { + "id": 6, + "internal-data": { + "Title": "Push #2", + "model-name": "Acquisition" + }, + "position": { + "x": 516, + "y": 159 + } + }, + { + "id": 7, + "internal-data": { + "Title": "Imaging #2", + "model-name": "Acquisition" + }, + "position": { + "x": 634, + "y": 160 + } + }, + { + "id": 8, + "internal-data": { + "Title": "Push #3", + "model-name": "Acquisition" + }, + "position": { + "x": 769, + "y": 160 + } + }, + { + "id": 9, + "internal-data": { + "Title": "Imaging #3", + "model-name": "Acquisition" + }, + "position": { + "x": 892, + "y": 159 + } + } + ] +} diff --git a/examples/calculator/AdditionModel.hpp b/examples/calculator/AdditionModel.hpp index b172b6ae5..2da05b2cc 100644 --- a/examples/calculator/AdditionModel.hpp +++ b/examples/calculator/AdditionModel.hpp @@ -2,10 +2,8 @@ #include "DecimalData.hpp" #include "MathOperationDataModel.hpp" - -#include - #include +#include #include /// The model dictates the number of inputs and outputs for the Node. diff --git a/examples/calculator/CMakeLists.txt b/examples/calculator/CMakeLists.txt index 60d2d14d7..3fcb0d518 100644 --- a/examples/calculator/CMakeLists.txt +++ b/examples/calculator/CMakeLists.txt @@ -10,20 +10,21 @@ set(CALC_HEADER_FILES DivisionModel.hpp DecimalData.hpp MathOperationDataModel.hpp + MultiplicationModel.hpp NumberDisplayDataModel.hpp NumberSourceDataModel.hpp SubtractionModel.hpp ) add_executable(calculator + WIN32 ${CALC_SOURCE_FILES} - ${CALC_HEAEDR_FILES} + ${CALC_HEADER_FILES} + CMakeLists.txt ) target_link_libraries(calculator QtNodes) - - set(HEADLESS_CALC_SOURCE_FILES headless_main.cpp MathOperationDataModel.cpp @@ -33,7 +34,22 @@ set(HEADLESS_CALC_SOURCE_FILES add_executable(headless_calculator ${HEADLESS_CALC_SOURCE_FILES} - ${CALC_HEAEDR_FILES} + ${CALC_HEADER_FILES} + CMakeLists.txt ) target_link_libraries(headless_calculator QtNodes) + +if(WIN32 AND BUILD_SHARED_LIBS) + add_custom_command( + TARGET calculator + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E env VCINSTALLDIR=${CMAKE_GENERATOR_INSTANCE}/VC + ${WINDEPLOYQT_EXECUTABLE} --pdb "$") + add_custom_command( + TARGET headless_calculator + POST_BUILD + COMMAND + ${CMAKE_COMMAND} -E env VCINSTALLDIR=${CMAKE_GENERATOR_INSTANCE}/VC + ${WINDEPLOYQT_EXECUTABLE} --pdb "$") +endif() diff --git a/examples/calculator/DivisionModel.hpp b/examples/calculator/DivisionModel.hpp index 9018450c8..a4f1a15a5 100644 --- a/examples/calculator/DivisionModel.hpp +++ b/examples/calculator/DivisionModel.hpp @@ -2,10 +2,8 @@ #include "DecimalData.hpp" #include "MathOperationDataModel.hpp" - -#include - #include +#include #include /// The model dictates the number of inputs and outputs for the Node. diff --git a/examples/calculator/MathOperationDataModel.cpp b/examples/calculator/MathOperationDataModel.cpp index f6a3a26d0..e6fb25932 100644 --- a/examples/calculator/MathOperationDataModel.cpp +++ b/examples/calculator/MathOperationDataModel.cpp @@ -1,6 +1,6 @@ #include "MathOperationDataModel.hpp" - #include "DecimalData.hpp" +#include unsigned int MathOperationDataModel::nPorts(PortType portType) const { @@ -30,6 +30,7 @@ void MathOperationDataModel::setInData(std::shared_ptr data, PortIndex if (!data) { Q_EMIT dataInvalidated(0); + return; } if (portIndex == 0) { diff --git a/examples/calculator/MathOperationDataModel.hpp b/examples/calculator/MathOperationDataModel.hpp index 6d279642b..c360a6648 100644 --- a/examples/calculator/MathOperationDataModel.hpp +++ b/examples/calculator/MathOperationDataModel.hpp @@ -1,13 +1,10 @@ #pragma once +#include +#include +#include #include -#include -#include -#include - -#include - class DecimalData; using QtNodes::NodeData; diff --git a/examples/calculator/MultiplicationModel.hpp b/examples/calculator/MultiplicationModel.hpp index 127ae4011..52ac02618 100644 --- a/examples/calculator/MultiplicationModel.hpp +++ b/examples/calculator/MultiplicationModel.hpp @@ -1,14 +1,11 @@ #pragma once -#include - +#include "DecimalData.hpp" +#include "MathOperationDataModel.hpp" #include +#include #include -#include "MathOperationDataModel.hpp" - -#include "DecimalData.hpp" - /// The model dictates the number of inputs and outputs for the Node. /// In this example it has no logic. class MultiplicationModel : public MathOperationDataModel diff --git a/examples/calculator/NumberDisplayDataModel.cpp b/examples/calculator/NumberDisplayDataModel.cpp index 5086050c8..ae24c1fae 100644 --- a/examples/calculator/NumberDisplayDataModel.cpp +++ b/examples/calculator/NumberDisplayDataModel.cpp @@ -1,6 +1,6 @@ #include "NumberDisplayDataModel.hpp" - -#include +#include +#include NumberDisplayDataModel::NumberDisplayDataModel() : _label{nullptr} diff --git a/examples/calculator/NumberDisplayDataModel.hpp b/examples/calculator/NumberDisplayDataModel.hpp index 78f984f5f..277966ab6 100644 --- a/examples/calculator/NumberDisplayDataModel.hpp +++ b/examples/calculator/NumberDisplayDataModel.hpp @@ -1,12 +1,12 @@ #pragma once -#include - -#include - -#include - #include "DecimalData.hpp" +#include +#include +#include +#include +#include +#include using QtNodes::NodeData; using QtNodes::NodeDataType; diff --git a/examples/calculator/NumberSourceDataModel.cpp b/examples/calculator/NumberSourceDataModel.cpp index f6a7ca55d..96bcedafe 100644 --- a/examples/calculator/NumberSourceDataModel.cpp +++ b/examples/calculator/NumberSourceDataModel.cpp @@ -1,10 +1,10 @@ #include "NumberSourceDataModel.hpp" - #include "DecimalData.hpp" - -#include -#include -#include +#include +#include +#include +#include +#include NumberSourceDataModel::NumberSourceDataModel() : _lineEdit{nullptr} diff --git a/examples/calculator/NumberSourceDataModel.hpp b/examples/calculator/NumberSourceDataModel.hpp index 8ae4e324a..30b2637bc 100644 --- a/examples/calculator/NumberSourceDataModel.hpp +++ b/examples/calculator/NumberSourceDataModel.hpp @@ -1,11 +1,13 @@ #pragma once +#include +#include +#include +#include +#include +#include #include -#include - -#include - class DecimalData; using QtNodes::NodeData; diff --git a/examples/calculator/SubtractionModel.hpp b/examples/calculator/SubtractionModel.hpp index ce6e926e3..8ef4c8b06 100644 --- a/examples/calculator/SubtractionModel.hpp +++ b/examples/calculator/SubtractionModel.hpp @@ -1,13 +1,10 @@ #pragma once +#include "DecimalData.hpp" +#include "MathOperationDataModel.hpp" #include -#include - #include - -#include "MathOperationDataModel.hpp" - -#include "DecimalData.hpp" +#include /// The model dictates the number of inputs and outputs for the Node. /// In this example it has no logic. diff --git a/examples/calculator/headless_main.cpp b/examples/calculator/headless_main.cpp index e4dafa022..0699c68da 100644 --- a/examples/calculator/headless_main.cpp +++ b/examples/calculator/headless_main.cpp @@ -4,9 +4,12 @@ #include "NumberDisplayDataModel.hpp" #include "NumberSourceDataModel.hpp" #include "SubtractionModel.hpp" - +#include +#include +#include +#include #include -#include +#include using QtNodes::DataFlowGraphModel; using QtNodes::NodeDelegateModelRegistry; diff --git a/examples/calculator/main.cpp b/examples/calculator/main.cpp index 980c0f23a..67ec28abd 100644 --- a/examples/calculator/main.cpp +++ b/examples/calculator/main.cpp @@ -1,23 +1,23 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - #include "AdditionModel.hpp" #include "DivisionModel.hpp" #include "MultiplicationModel.hpp" #include "NumberDisplayDataModel.hpp" #include "NumberSourceDataModel.hpp" #include "SubtractionModel.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using QtNodes::ConnectionStyle; using QtNodes::DataFlowGraphicsScene; diff --git a/examples/calculator/render.png b/examples/calculator/render.png new file mode 100644 index 000000000..90a559203 Binary files /dev/null and b/examples/calculator/render.png differ diff --git a/examples/calculator_qml/AdditionModel.hpp b/examples/calculator_qml/AdditionModel.hpp new file mode 100644 index 000000000..2da05b2cc --- /dev/null +++ b/examples/calculator_qml/AdditionModel.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include "DecimalData.hpp" +#include "MathOperationDataModel.hpp" +#include +#include +#include + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class AdditionModel : public MathOperationDataModel +{ +public: + ~AdditionModel() = default; + +public: + QString caption() const override { return QStringLiteral("Addition"); } + + QString name() const override { return QStringLiteral("Addition"); } + +private: + void compute() override + { + PortIndex const outPortIndex = 0; + + auto n1 = _number1.lock(); + auto n2 = _number2.lock(); + + if (n1 && n2) { + _result = std::make_shared(n1->number() + n2->number()); + } else { + _result.reset(); + } + + Q_EMIT dataUpdated(outPortIndex); + } +}; diff --git a/examples/calculator_qml/CMakeLists.txt b/examples/calculator_qml/CMakeLists.txt new file mode 100644 index 000000000..d855a2f8d --- /dev/null +++ b/examples/calculator_qml/CMakeLists.txt @@ -0,0 +1,45 @@ +set(CALC_SOURCE_FILES + main.cpp MathOperationDataModel.cpp NumberDisplayDataModel.cpp + NumberSourceDataModel.cpp StringDataModel.cpp QmlWrapper.cpp) + +set(CALC_HEADER_FILES + AdditionModel.hpp + DivisionModel.hpp + DecimalData.hpp + MathOperationDataModel.hpp + MultiplicationModel.hpp + NumberDisplayDataModel.hpp + NumberSourceDataModel.hpp + SubtractionModel.hpp + StringDataModel.hpp + StringData.hpp + QmlWrapper.hpp) + +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +cmake_policy(SET CMP0071 NEW) + +qt_standard_project_setup(REQUIRES 6.5) + +qt_add_resources(QT_RESOURCES "main.qrc") +qt_add_executable(calculator_qml ${CALC_SOURCE_FILES} ${CALC_HEADER_FILES} + ${QT_RESOURCES}) + +qt_add_qml_module( + calculator_qml VERSION 1.0 URI hello QML_FILES main.qml Source.qml Display.qml RESOURCES + # img/world.png +) + +target_link_libraries(calculator_qml PRIVATE Qt6::Gui Qt6::Quick + Qt6::QuickWidgets QtNodes) + +if(WIN32 AND BUILD_SHARED_LIBS) + add_custom_command( + TARGET calculator_qml + POST_BUILD + COMMAND + ${CMAKE_COMMAND} -E env VCINSTALLDIR=${CMAKE_GENERATOR_INSTANCE}/VC + ${WINDEPLOYQT_EXECUTABLE} --qmldir ${CMAKE_CURRENT_SOURCE_DIR} --pdb + "$") +endif() diff --git a/examples/calculator_qml/DecimalData.hpp b/examples/calculator_qml/DecimalData.hpp new file mode 100644 index 000000000..bd337d248 --- /dev/null +++ b/examples/calculator_qml/DecimalData.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +using QtNodes::NodeData; +using QtNodes::NodeDataType; + +/// The class can potentially incapsulate any user data which +/// need to be transferred within the Node Editor graph +class DecimalData : public NodeData +{ +public: + DecimalData() + : _number(0.0) + {} + + DecimalData(double const number) + : _number(number) + {} + + NodeDataType type() const override { return NodeDataType{"decimal", "Decimal"}; } + + double number() const { return _number; } + + QString numberAsText() const { return QString::number(_number, 'f'); } + +private: + double _number; +}; diff --git a/examples/calculator_qml/Display.qml b/examples/calculator_qml/Display.qml new file mode 100644 index 000000000..50a2e0772 --- /dev/null +++ b/examples/calculator_qml/Display.qml @@ -0,0 +1,11 @@ +import QtQuick + +Rectangle { + anchors.fill: parent + Text { + id: text + objectName: "label" + text: "ff" + anchors.fill: parent + } +} diff --git a/examples/calculator_qml/DivisionModel.hpp b/examples/calculator_qml/DivisionModel.hpp new file mode 100644 index 000000000..a4f1a15a5 --- /dev/null +++ b/examples/calculator_qml/DivisionModel.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include "DecimalData.hpp" +#include "MathOperationDataModel.hpp" +#include +#include +#include + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class DivisionModel : public MathOperationDataModel +{ +public: + virtual ~DivisionModel() {} + +public: + QString caption() const override { return QStringLiteral("Division"); } + + bool portCaptionVisible(PortType portType, PortIndex portIndex) const override + { + Q_UNUSED(portType); + Q_UNUSED(portIndex); + return true; + } + + QString portCaption(PortType portType, PortIndex portIndex) const override + { + switch (portType) { + case PortType::In: + if (portIndex == 0) + return QStringLiteral("Dividend"); + else if (portIndex == 1) + return QStringLiteral("Divisor"); + + break; + + case PortType::Out: + return QStringLiteral("Result"); + + default: + break; + } + return QString(); + } + + QString name() const override { return QStringLiteral("Division"); } + +private: + void compute() override + { + PortIndex const outPortIndex = 0; + + auto n1 = _number1.lock(); + auto n2 = _number2.lock(); + + if (n2 && (n2->number() == 0.0)) { + //modelValidationState = NodeValidationState::Error; + //modelValidationError = QStringLiteral("Division by zero error"); + _result.reset(); + } else if (n1 && n2) { + //modelValidationState = NodeValidationState::Valid; + //modelValidationError = QString(); + _result = std::make_shared(n1->number() / n2->number()); + } else { + //modelValidationState = NodeValidationState::Warning; + //modelValidationError = QStringLiteral("Missing or incorrect inputs"); + _result.reset(); + } + + Q_EMIT dataUpdated(outPortIndex); + } +}; diff --git a/examples/calculator_qml/MathOperationDataModel.cpp b/examples/calculator_qml/MathOperationDataModel.cpp new file mode 100644 index 000000000..e6fb25932 --- /dev/null +++ b/examples/calculator_qml/MathOperationDataModel.cpp @@ -0,0 +1,43 @@ +#include "MathOperationDataModel.hpp" +#include "DecimalData.hpp" +#include + +unsigned int MathOperationDataModel::nPorts(PortType portType) const +{ + unsigned int result; + + if (portType == PortType::In) + result = 2; + else + result = 1; + + return result; +} + +NodeDataType MathOperationDataModel::dataType(PortType, PortIndex) const +{ + return DecimalData().type(); +} + +std::shared_ptr MathOperationDataModel::outData(PortIndex) +{ + return std::static_pointer_cast(_result); +} + +void MathOperationDataModel::setInData(std::shared_ptr data, PortIndex portIndex) +{ + auto numberData = std::dynamic_pointer_cast(data); + + if (!data) { + Q_EMIT dataInvalidated(0); + return; + } + + if (portIndex == 0) { + _number1 = numberData; + } else { + _number2 = numberData; + } + + compute(); +} diff --git a/examples/calculator_qml/MathOperationDataModel.hpp b/examples/calculator_qml/MathOperationDataModel.hpp new file mode 100644 index 000000000..c360a6648 --- /dev/null +++ b/examples/calculator_qml/MathOperationDataModel.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include +#include + +class DecimalData; + +using QtNodes::NodeData; +using QtNodes::NodeDataType; +using QtNodes::NodeDelegateModel; +using QtNodes::PortIndex; +using QtNodes::PortType; + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class MathOperationDataModel : public NodeDelegateModel +{ + Q_OBJECT + +public: + ~MathOperationDataModel() = default; + +public: + unsigned int nPorts(PortType portType) const override; + + NodeDataType dataType(PortType portType, PortIndex portIndex) const override; + + std::shared_ptr outData(PortIndex port) override; + + void setInData(std::shared_ptr data, PortIndex portIndex) override; + + QWidget *embeddedWidget() override { return nullptr; } + +protected: + virtual void compute() = 0; + +protected: + std::weak_ptr _number1; + std::weak_ptr _number2; + + std::shared_ptr _result; +}; diff --git a/examples/calculator_qml/MultiplicationModel.hpp b/examples/calculator_qml/MultiplicationModel.hpp new file mode 100644 index 000000000..52ac02618 --- /dev/null +++ b/examples/calculator_qml/MultiplicationModel.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "DecimalData.hpp" +#include "MathOperationDataModel.hpp" +#include +#include +#include + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class MultiplicationModel : public MathOperationDataModel +{ +public: + virtual ~MultiplicationModel() {} + +public: + QString caption() const override { return QStringLiteral("Multiplication"); } + + QString name() const override { return QStringLiteral("Multiplication"); } + +private: + void compute() override + { + PortIndex const outPortIndex = 0; + + auto n1 = _number1.lock(); + auto n2 = _number2.lock(); + + if (n1 && n2) { + //modelValidationState = NodeValidationState::Valid; + //modelValidationError = QString(); + _result = std::make_shared(n1->number() * n2->number()); + } else { + //modelValidationState = NodeValidationState::Warning; + //modelValidationError = QStringLiteral("Missing or incorrect inputs"); + _result.reset(); + } + + Q_EMIT dataUpdated(outPortIndex); + } +}; diff --git a/examples/calculator_qml/NumberDisplayDataModel.cpp b/examples/calculator_qml/NumberDisplayDataModel.cpp new file mode 100644 index 000000000..1ef25d674 --- /dev/null +++ b/examples/calculator_qml/NumberDisplayDataModel.cpp @@ -0,0 +1,71 @@ +#include "NumberDisplayDataModel.hpp" +#include +#include +#include +#include +#include + +unsigned int NumberDisplayDataModel::nPorts(PortType portType) const +{ + unsigned int result = 1; + + switch (portType) { + case PortType::In: + result = 1; + break; + + case PortType::Out: + result = 0; + + default: + break; + } + + return result; +} + +NodeDataType NumberDisplayDataModel::dataType(PortType, PortIndex) const +{ + return DecimalData().type(); +} + +std::shared_ptr NumberDisplayDataModel::outData(PortIndex) +{ + std::shared_ptr ptr; + return ptr; +} + +void NumberDisplayDataModel::setInData(std::shared_ptr data, PortIndex portIndex) +{ + _numberData = std::dynamic_pointer_cast(data); + + if (!_label) + return; + + if (_numberData) { + _label->setProperty("text", _numberData->numberAsText()); + } else { + _label->setProperty("text", ""); + } +} + +QWidget *NumberDisplayDataModel::embeddedWidget() +{ + if (!_label) { + _qwid = new QQuickWidget(nullptr); + _qwid->setSource(QUrl("qrc:/hello/Display.qml")); + _qwid->setFixedWidth(70); + _qwid->setFixedHeight(20); + _label = _qwid->rootObject()->findChild("label"); + } + + return _qwid; +} + +double NumberDisplayDataModel::number() const +{ + if (_numberData) + return _numberData->number(); + + return 0.0; +} diff --git a/examples/calculator_qml/NumberDisplayDataModel.hpp b/examples/calculator_qml/NumberDisplayDataModel.hpp new file mode 100644 index 000000000..cd71b03b2 --- /dev/null +++ b/examples/calculator_qml/NumberDisplayDataModel.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include "DecimalData.hpp" +#include +#include +#include +#include +#include +#include +#include + +using QtNodes::NodeData; +using QtNodes::NodeDataType; +using QtNodes::NodeDelegateModel; +using QtNodes::PortIndex; +using QtNodes::PortType; + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class NumberDisplayDataModel : public NodeDelegateModel +{ + Q_OBJECT + +public: + ~NumberDisplayDataModel() = default; + +public: + QString caption() const override { return QStringLiteral("Result"); } + + bool captionVisible() const override { return false; } + + QString name() const override { return QStringLiteral("Result"); } + +public: + unsigned int nPorts(PortType portType) const override; + + NodeDataType dataType(PortType portType, PortIndex portIndex) const override; + + std::shared_ptr outData(PortIndex port) override; + + void setInData(std::shared_ptr data, PortIndex portIndex) override; + + QWidget *embeddedWidget() override; + + double number() const; + +private: + std::shared_ptr _numberData; + + QQuickWidget *_qwid = nullptr; + QObject *_label = nullptr; +}; diff --git a/examples/calculator_qml/NumberSourceDataModel.cpp b/examples/calculator_qml/NumberSourceDataModel.cpp new file mode 100644 index 000000000..987b00d56 --- /dev/null +++ b/examples/calculator_qml/NumberSourceDataModel.cpp @@ -0,0 +1,112 @@ +#include "NumberSourceDataModel.hpp" +#include "DecimalData.hpp" +#include +#include +#include +#include +#include +#include +#include + +QJsonObject NumberSourceDataModel::save() const +{ + QJsonObject modelJson = NodeDelegateModel::save(); + + modelJson["number"] = QString::number(_number->number()); + + return modelJson; +} + +void NumberSourceDataModel::load(QJsonObject const &p) +{ + QJsonValue v = p["number"]; + + if (!v.isUndefined()) { + QString strNum = v.toString(); + + bool ok; + double d = strNum.toDouble(&ok); + if (ok) { + _number = std::make_shared(d); + + if (_lineEdit) { + _lineEdit->setProperty("text", strNum); + } + } + } +} + +unsigned int NumberSourceDataModel::nPorts(PortType portType) const +{ + unsigned int result = 1; + + switch (portType) { + case PortType::In: + result = 0; + break; + + case PortType::Out: + result = 1; + + default: + break; + } + + return result; +} + +void NumberSourceDataModel::onTextEdited(QString const &str) +{ + bool ok = false; + + double number = str.toDouble(&ok); + + if (ok) { + _number = std::make_shared(number); + + Q_EMIT dataUpdated(0); + + } else { + Q_EMIT dataInvalidated(0); + } +} + +NodeDataType NumberSourceDataModel::dataType(PortType, PortIndex) const +{ + return DecimalData().type(); +} + +std::shared_ptr NumberSourceDataModel::outData(PortIndex) +{ + return _number; +} + +QWidget *NumberSourceDataModel::embeddedWidget() +{ + if (!_qwid) { + _qwid = new QQuickWidget(nullptr); + _qwid->setSource(QUrl("qrc:/hello/Display.qml")); + _qwid->setFixedWidth(70); + _qwid->setFixedHeight(20); + _lineEdit = _qwid->rootObject()->findChild("label"); + + if (_number) { + _lineEdit->setProperty("text", QString::number(_number->number())); + } + + //connect(_lineEdit, &QLineEdit::textChanged, this, &NumberSourceDataModel::onTextEdited); + } + + return _qwid; +} + +void NumberSourceDataModel::setNumber(double n) +{ + _number = std::make_shared(n); + + Q_EMIT dataUpdated(0); + + if (_lineEdit) { + _lineEdit->setProperty("text", QString::number(_number->number())); + } +} diff --git a/examples/calculator_qml/NumberSourceDataModel.hpp b/examples/calculator_qml/NumberSourceDataModel.hpp new file mode 100644 index 000000000..c8ebc8bd3 --- /dev/null +++ b/examples/calculator_qml/NumberSourceDataModel.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include "DecimalData.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +using QtNodes::NodeData; +using QtNodes::NodeDataType; +using QtNodes::NodeDelegateModel; +using QtNodes::PortIndex; +using QtNodes::PortType; + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class NumberSourceDataModel : public NodeDelegateModel +{ + Q_OBJECT + +public: + virtual ~NumberSourceDataModel() {} + +public: + QString caption() const override { return QStringLiteral("Number Source"); } + + bool captionVisible() const override { return false; } + + QString name() const override { return QStringLiteral("NumberSource"); } + +public: + QJsonObject save() const override; + + void load(QJsonObject const &p) override; + +public: + unsigned int nPorts(PortType portType) const override; + + NodeDataType dataType(PortType portType, PortIndex portIndex) const override; + + std::shared_ptr outData(PortIndex port) override; + + void setInData(std::shared_ptr, PortIndex) override {} + + QWidget *embeddedWidget() override; + +public: + void setNumber(double number); + +private Q_SLOTS: + + void onTextEdited(QString const &string); + +private: + std::shared_ptr _number = std::make_shared(0.0); + + QQuickWidget *_qwid = nullptr; + QObject *_lineEdit = nullptr; +}; diff --git a/examples/calculator_qml/QmlWrapper.cpp b/examples/calculator_qml/QmlWrapper.cpp new file mode 100644 index 000000000..0b2db62e4 --- /dev/null +++ b/examples/calculator_qml/QmlWrapper.cpp @@ -0,0 +1,209 @@ +#include "QmlWrapper.hpp" +#include "AdditionModel.hpp" +#include "DivisionModel.hpp" +#include "MultiplicationModel.hpp" +#include "NumberDisplayDataModel.hpp" +#include "NumberSourceDataModel.hpp" +#include "StringDataModel.hpp" +#include "SubtractionModel.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using QtNodes::ConnectionStyle; +using QtNodes::DataFlowGraphicsScene; +using QtNodes::DataFlowGraphModel; +using QtNodes::GraphicsView; +using QtNodes::NodeDelegateModelRegistry; + +using QtNodes::NodeDelegateModelRegistry; + +QuickPaintedView::QuickPaintedView(QQuickItem *parent) + : QQuickPaintedItem(parent) +{ + //! NOTE It is necessary that when UI scaling is displayed without a blur + setAntialiasing(false); + setSmooth(false); +} + +QSGNode *QuickPaintedView::updatePaintNode(QSGNode *old, UpdatePaintNodeData *data) +{ + //! NOTE It is necessary that when UI scaling is displayed without a blur + setTextureSize(QSize(width(), height())); + QSGNode *n = QQuickPaintedItem::updatePaintNode(old, data); + update(); // Endless loop + return n; +} + +WidgetView::WidgetView(QQuickItem *parent) + : QuickPaintedView(parent) +{ + setFlag(QQuickItem::ItemAcceptsDrops, true); + setFlag(QQuickItem::ItemHasContents, true); + + setAcceptHoverEvents(true); + setAcceptedMouseButtons(Qt::AllButtons); +} + +void WidgetView::paint(QPainter *painter) +{ + if (qWidget()) { + qWidget()->render(painter, + QPoint(), + QRegion(), + QWidget::DrawWindowBackground | QWidget::DrawChildren); + } +} + +bool WidgetView::event(QEvent *event) +{ + if (!m_widget) { + return QQuickItem::event(event); + } + + bool ok = true; + + switch (event->type()) { + case QEvent::HoverEnter: + case QEvent::HoverMove: + case QEvent::HoverLeave: + ok = handleHoverEvent(dynamic_cast(event)); + break; + case QEvent::MouseButtonPress: { + setFocus(true); + ok = m_widget->handleEvent(event); + break; + } + default: + ok = m_widget->handleEvent(event); + break; + } + + if (ok) { + update(); + } + + return ok; +} + +bool WidgetView::handleHoverEvent(QHoverEvent *event) +{ + auto convertEventType = [](QEvent::Type type) { + static const QMap types{{QEvent::HoverLeave, QEvent::Leave}, + {QEvent::HoverEnter, QEvent::Enter}, + {QEvent::HoverMove, QEvent::MouseMove}}; + + return types[type]; + }; + + QEvent::Type convertedType = convertEventType(event->type()); + + if (convertedType == QEvent::MouseMove) { + QMouseEvent *mouseEvent = new QMouseEvent(convertedType, + event->position(), + event->scenePosition(), + event->globalPosition(), + event->button(), + event->buttons(), + event->modifiers(), + Qt::MouseEventSource::MouseEventNotSynthesized, + event->pointingDevice()); + mouseEvent->setAccepted(event->isAccepted()); + mouseEvent->setTimestamp(event->timestamp()); + bool ok = m_widget->handleEvent(mouseEvent); + setCursor(m_widget->cursor()); + return ok; + } + + QEvent newEvent(convertedType); + newEvent.setAccepted(event->isAccepted()); + + return QCoreApplication::sendEvent(m_widget, &newEvent); +} + +void WidgetView::componentComplete() +{ + QQuickItem::componentComplete(); + + setWidget(); + + connect(this, &QQuickItem::widthChanged, [this]() { updateSizeConstraints(); }); + + connect(this, &QQuickItem::heightChanged, [this]() { updateSizeConstraints(); }); +} + +QWidget *WidgetView::qWidget() const +{ + //return m_widget ? m_widget->qWidget() : nullptr; + return m_widget; +} + +void WidgetView::updateSizeConstraints() +{ + if (qWidget()) { + qWidget()->setFixedSize(width(), height()); + } +} + +static std::shared_ptr registerDataModels() +{ + auto ret = std::make_shared(); + ret->registerModel("Sources"); + + ret->registerModel("Displays"); + + ret->registerModel("Operators"); + + ret->registerModel("Operators"); + + ret->registerModel("Operators"); + + ret->registerModel("Operators"); + + ret->registerModel("Sources"); + + return ret; +} + +void WidgetView::setWidget() +{ + std::shared_ptr registry = registerDataModels(); + + m_model = new DataFlowGraphModel(registry); + + m_widget_scene = new DataFlowGraphicsScene(*m_model, nullptr); + + m_widget = new GraphicsView(m_widget_scene); // Comp + + updateSizeConstraints(); + + QObject::connect(m_widget_scene, + &DataFlowGraphicsScene::sceneLoaded, + m_widget, + &GraphicsView::centerScene); + + QFile file("C:/temp/ttt.flow"); + + file.open(QIODevice::ReadOnly); + + m_widget_scene->clearScene(); + + QByteArray const wholeFile = file.readAll(); + + m_model->load(QJsonDocument::fromJson(wholeFile).object()); + + m_widget->centerScene(); +} diff --git a/examples/calculator_qml/QmlWrapper.hpp b/examples/calculator_qml/QmlWrapper.hpp new file mode 100644 index 000000000..cd65f9fe6 --- /dev/null +++ b/examples/calculator_qml/QmlWrapper.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using QtNodes::DataFlowGraphicsScene; +using QtNodes::DataFlowGraphModel; +using QtNodes::GraphicsView; + +class QuickPaintedView : public QQuickPaintedItem +{ + Q_OBJECT +public: + QuickPaintedView(QQuickItem *parent = nullptr); + +protected: + QSGNode *updatePaintNode(QSGNode *old, UpdatePaintNodeData *d) override; +}; + +class WidgetView : public QuickPaintedView +{ + Q_OBJECT + +public: + explicit WidgetView(QQuickItem *parent = nullptr); + +protected: + void componentComplete() override; + +private: + void paint(QPainter *painter) override; + bool event(QEvent *event) override; + bool handleHoverEvent(QHoverEvent *event); + bool handleMouseEvent(QMouseEvent *event); + + QWidget *qWidget() const; + void updateSizeConstraints(); + + void setWidget(); + + GraphicsView *m_widget = nullptr; + DataFlowGraphicsScene *m_widget_scene = nullptr; + DataFlowGraphModel *m_model = nullptr; +}; diff --git a/examples/calculator_qml/Source.qml b/examples/calculator_qml/Source.qml new file mode 100644 index 000000000..f2c86d3c4 --- /dev/null +++ b/examples/calculator_qml/Source.qml @@ -0,0 +1,11 @@ +import QtQuick + +Rectangle { + anchors.fill: parent + TextEdit { + id: text + objectName: "input" + text: "ff" + anchors.fill: parent + } +} diff --git a/examples/calculator_qml/StringData.hpp b/examples/calculator_qml/StringData.hpp new file mode 100644 index 000000000..a4be2f8c7 --- /dev/null +++ b/examples/calculator_qml/StringData.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +using QtNodes::NodeData; +using QtNodes::NodeDataType; + +/// The class can potentially incapsulate any user data which +/// need to be transferred within the Node Editor graph +class StringData : public NodeData +{ +public: + StringData() + : _text() + {} + + StringData(QString const text) + : _text(text) + {} + + NodeDataType type() const override { return NodeDataType{"string", "String"}; } + + QString number() const { return _text; } + + QString numberAsText() const { return _text; } + +private: + QString _text; +}; diff --git a/examples/calculator_qml/StringDataModel.cpp b/examples/calculator_qml/StringDataModel.cpp new file mode 100644 index 000000000..a891735c6 --- /dev/null +++ b/examples/calculator_qml/StringDataModel.cpp @@ -0,0 +1 @@ +#include "StringDataModel.hpp" diff --git a/examples/calculator_qml/StringDataModel.hpp b/examples/calculator_qml/StringDataModel.hpp new file mode 100644 index 000000000..cb21262d9 --- /dev/null +++ b/examples/calculator_qml/StringDataModel.hpp @@ -0,0 +1,66 @@ +#pragma once + +#include "StringData.hpp" +#include +#include +#include +#include +#include + +using QtNodes::NodeData; +using QtNodes::NodeDataType; +using QtNodes::NodeDelegateModel; +using QtNodes::PortIndex; +using QtNodes::PortType; + +class StringDataModel : public NodeDelegateModel +{ + Q_OBJECT +public: + StringDataModel() = default; + virtual QString caption() const { return _text->numberAsText(); } + virtual QString name() const { return "Text"; }; + virtual unsigned int nPorts(PortType portType) const + { + unsigned int result = 1; + + switch (portType) { + case PortType::In: + result = 0; + break; + + case PortType::Out: + result = 1; + break; + + default: + break; + } + + return result; + } + + virtual NodeDataType dataType(PortType portType, PortIndex portIndex) const + { + switch (portType) { + case PortType::In: + return StringData().type(); + + case PortType::Out: + return StringData().type(); + case PortType::None: + default: + return {}; + } + } + virtual void setInData(std::shared_ptr nodeData, PortIndex const portIndex) {} + + virtual std::shared_ptr outData(PortIndex const port) + { + return std::static_pointer_cast(_text); + } + virtual QWidget *embeddedWidget() { return nullptr; } + +private: + std::shared_ptr _text = std::make_shared("Hello"); +}; diff --git a/examples/calculator_qml/SubtractionModel.hpp b/examples/calculator_qml/SubtractionModel.hpp new file mode 100644 index 000000000..8ef4c8b06 --- /dev/null +++ b/examples/calculator_qml/SubtractionModel.hpp @@ -0,0 +1,64 @@ +#pragma once + +#include "DecimalData.hpp" +#include "MathOperationDataModel.hpp" +#include +#include +#include + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class SubtractionModel : public MathOperationDataModel +{ +public: + virtual ~SubtractionModel() {} + +public: + QString caption() const override { return QStringLiteral("Subtraction"); } + + virtual bool portCaptionVisible(PortType portType, PortIndex portIndex) const override + { + Q_UNUSED(portType); + Q_UNUSED(portIndex); + return true; + } + + virtual QString portCaption(PortType portType, PortIndex portIndex) const override + { + switch (portType) { + case PortType::In: + if (portIndex == 0) + return QStringLiteral("Minuend"); + else if (portIndex == 1) + return QStringLiteral("Subtrahend"); + + break; + + case PortType::Out: + return QStringLiteral("Result"); + + default: + break; + } + return QString(); + } + + QString name() const override { return QStringLiteral("Subtraction"); } + +private: + void compute() override + { + PortIndex const outPortIndex = 0; + + auto n1 = _number1.lock(); + auto n2 = _number2.lock(); + + if (n1 && n2) { + _result = std::make_shared(n1->number() - n2->number()); + } else { + _result.reset(); + } + + Q_EMIT dataUpdated(outPortIndex); + } +}; diff --git a/examples/calculator_qml/main.cpp b/examples/calculator_qml/main.cpp new file mode 100644 index 000000000..73cffa2c0 --- /dev/null +++ b/examples/calculator_qml/main.cpp @@ -0,0 +1,48 @@ +#include "QmlWrapper.hpp" +#include +#include +#include +#include +#include +#include +#include + +using QtNodes::ConnectionStyle; + +static void setStyle() +{ + ConnectionStyle::setConnectionStyle( + R"( + { + "ConnectionStyle": { + "ConstructionColor": "gray", + "NormalColor": "black", + "SelectedColor": "gray", + "SelectedHaloColor": "deepskyblue", + "HoveredColor": "deepskyblue", + + "LineWidth": 3.0, + "ConstructionLineWidth": 2.0, + "PointDiameter": 10.0, + + "UseDataDefinedColors": true + } + } + )"); +} + +int main(int argc, char *argv[]) +{ + qputenv("QT_QUICK_BACKEND", "software"); + QApplication app(argc, argv); + + setStyle(); + + qmlRegisterType("bk", 0, 0, "WidgetView"); + + QQmlApplicationEngine engine; + const QUrl url("qrc:/hello/main.qml"); + engine.load(url); + + return app.exec(); +} diff --git a/examples/calculator_qml/main.qml b/examples/calculator_qml/main.qml new file mode 100644 index 000000000..fa0c396f5 --- /dev/null +++ b/examples/calculator_qml/main.qml @@ -0,0 +1,28 @@ +import QtQuick +import QtQuick.Window +import QtCharts +import bk + +Window { + width: 1500 + height: 1000 + visible: true + + Button { + id: button + width: 200 + height: 200 + anchors.top: myChart.bottom + text: qsTr("Click Me!") + onClicked: { + backend.setObject(button); + } + } + WidgetView { + id: qmlwrap + width: 800 + height: 800 + anchors.top: myChart.bottom + anchors.left: myChart.right + } +} diff --git a/examples/calculator_qml/main.qrc b/examples/calculator_qml/main.qrc new file mode 100644 index 000000000..fdac6aee2 --- /dev/null +++ b/examples/calculator_qml/main.qrc @@ -0,0 +1,7 @@ + + + main.qml + Display.qml + Source.qml + + diff --git a/examples/compute_viewer/AverageData.hpp b/examples/compute_viewer/AverageData.hpp new file mode 100644 index 000000000..31b853006 --- /dev/null +++ b/examples/compute_viewer/AverageData.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include + +using QtNodes::NodeData; +using QtNodes::NodeDataType; + +class AverageX1Data : public NodeData +{ +public: + NodeDataType type() const override { return NodeDataType{"average", "x1"}; } +}; + +class AverageX2Data : public NodeData +{ +public: + NodeDataType type() const override { return NodeDataType{"average", "x2"}; } +}; + +class AverageData : public NodeData +{ +public: + NodeDataType type() const override { return NodeDataType{"average", "x"}; } +}; diff --git a/examples/compute_viewer/AverageModel.cpp b/examples/compute_viewer/AverageModel.cpp new file mode 100644 index 000000000..d0693333d --- /dev/null +++ b/examples/compute_viewer/AverageModel.cpp @@ -0,0 +1,39 @@ +#include "AverageModel.hpp" +#include "AverageData.hpp" +#include "RoiData.hpp" +#include + +using QtNodes::NodeStyle; + +unsigned int AverageModel::nPorts(PortType portType) const +{ + unsigned int result; + + if (portType == PortType::In) + result = 1; + else + result = 1; + + return result; +} + +NodeDataType AverageModel::dataType(PortType portType, PortIndex) const +{ + if (portType == PortType::In) { + return RoiData().type(); + } else { + return AverageData().type(); + } +} + +std::shared_ptr AverageModel::outData(PortIndex) +{ + return nullptr; +} + +void AverageModel::setInData(std::shared_ptr data, PortIndex portIndex) {} + +QWidget *AverageModel::embeddedWidget() +{ + return nullptr; +} diff --git a/examples/compute_viewer/AverageModel.hpp b/examples/compute_viewer/AverageModel.hpp new file mode 100644 index 000000000..b06105905 --- /dev/null +++ b/examples/compute_viewer/AverageModel.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +using QtNodes::ConnectionPolicy; +using QtNodes::NodeData; +using QtNodes::NodeDataType; +using QtNodes::NodeDelegateModel; +using QtNodes::PortIndex; +using QtNodes::PortType; + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class AverageModel : public NodeDelegateModel +{ + Q_OBJECT + +public: + ~AverageModel() override = default; + +public: + unsigned int nPorts(PortType portType) const override; + + NodeDataType dataType(PortType portType, PortIndex portIndex) const override; + + std::shared_ptr outData(PortIndex port) override; + + void setInData(std::shared_ptr data, PortIndex portIndex) override; + + QWidget *embeddedWidget() override; + + QString caption() const override { return QStringLiteral("Average"); } + + QString name() const override { return QStringLiteral("Average"); } + +private: + float _value; +}; diff --git a/examples/compute_viewer/CMakeLists.txt b/examples/compute_viewer/CMakeLists.txt new file mode 100644 index 000000000..968b2fbf1 --- /dev/null +++ b/examples/compute_viewer/CMakeLists.txt @@ -0,0 +1,57 @@ +set(COMPUTE_SOURCE_FILES + main.cpp + InputModel.cpp + OutputModel.cpp + DecimationModel.cpp + DecimationWidget.cpp + DasPwModel.cpp + DasPwWidget.cpp + ClutterFilterModel.cpp + ClutterFilterWidget.cpp + CalculatorModel.cpp + CalculatorWidget.cpp + RoiRectModel.cpp + RoiRectWidget.cpp + RoiSphereModel.cpp + AverageModel.cpp + RoiSphereWidget.cpp + DopplerViewerModel.cpp) + +set(COMPUTE_HEADER_FILES + InputData.hpp + InputModel.hpp + OutputModel.hpp + DecimationModel.hpp + DecimationData.hpp + DecimationWidget.hpp + ClutterFilterModel.hpp + ClutterFilterData.hpp + ClutterFilterWidget.hpp + CalculatorModel.hpp + CalculatorData.hpp + CalculatorWidget.hpp + RoiData.hpp + RoiRectModel.hpp + RoiRectWidget.hpp + RoiSphereModel.hpp + RoiSphereWidget.hpp + DasPwModel.hpp + DasPwData.hpp + DopplerViewerModel.hpp + DopplerViewerData.hpp + AverageModel.hpp + AverageData.hpp + DasPwWidget.hpp) + +add_executable(compute_viewer WIN32 ${COMPUTE_SOURCE_FILES} + ${COMPUTE_HEADER_FILES} CMakeLists.txt) + +target_link_libraries(compute_viewer QtNodes) + +if(WIN32 AND BUILD_SHARED_LIBS) + add_custom_command( + TARGET compute_viewer + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E env VCINSTALLDIR=${CMAKE_GENERATOR_INSTANCE}/VC + ${WINDEPLOYQT_EXECUTABLE} --pdb "$") +endif() diff --git a/examples/compute_viewer/CalculatorData.hpp b/examples/compute_viewer/CalculatorData.hpp new file mode 100644 index 000000000..f7228a729 --- /dev/null +++ b/examples/compute_viewer/CalculatorData.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +using QtNodes::NodeData; +using QtNodes::NodeDataType; + +class CalculatorData : public NodeData +{ +public: + NodeDataType type() const override { return NodeDataType{"calculator", "Calculator"}; } +}; diff --git a/examples/compute_viewer/CalculatorModel.cpp b/examples/compute_viewer/CalculatorModel.cpp new file mode 100644 index 000000000..89b9312eb --- /dev/null +++ b/examples/compute_viewer/CalculatorModel.cpp @@ -0,0 +1,65 @@ +#include "CalculatorModel.hpp" +#include "AverageData.hpp" +#include "CalculatorData.hpp" +#include "CalculatorWidget.hpp" +#include +#include +#include + +using QtNodes::NodeStyle; + +unsigned int CalculatorModel::nPorts(PortType portType) const +{ + unsigned int result; + + if (portType == PortType::In) + result = 2; + else + result = 1; + + return result; +} + +NodeDataType CalculatorModel::dataType(PortType portType, PortIndex portIndex) const +{ + if (portType == PortType::In) { + if (portIndex == 0) { + return AverageX1Data().type(); + } else { + return AverageX2Data().type(); + } + } else { + return CalculatorData().type(); + } +} + +std::shared_ptr CalculatorModel::outData(PortIndex) +{ + return nullptr; +} + +void CalculatorModel::setInData(std::shared_ptr data, PortIndex portIndex) {} + +QWidget *CalculatorModel::embeddedWidget() +{ + if (_widget) { + return _widget; + } + + _widget = new CalculatorWidget(_value, nullptr); + + return _widget; +} + +QJsonObject CalculatorModel::save() const +{ + QJsonObject retval = NodeDelegateModel::save(); + retval["expression"] = _value; + return retval; +} + +void CalculatorModel::load(QJsonObject const &object) +{ + NodeDelegateModel::load(object); + _value = object["expression"].toString(); +} diff --git a/examples/compute_viewer/CalculatorModel.hpp b/examples/compute_viewer/CalculatorModel.hpp new file mode 100644 index 000000000..86c9bd0ae --- /dev/null +++ b/examples/compute_viewer/CalculatorModel.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "CalculatorWidget.hpp" +#include +#include +#include +#include +#include +#include +#include + +using QtNodes::ConnectionPolicy; +using QtNodes::NodeData; +using QtNodes::NodeDataType; +using QtNodes::NodeDelegateModel; +using QtNodes::PortIndex; +using QtNodes::PortType; + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class CalculatorModel : public NodeDelegateModel +{ + Q_OBJECT + +public: + ~CalculatorModel() override = default; + +public: + unsigned int nPorts(PortType portType) const override; + + NodeDataType dataType(PortType portType, PortIndex portIndex) const override; + + std::shared_ptr outData(PortIndex port) override; + + void setInData(std::shared_ptr data, PortIndex portIndex) override; + + QWidget *embeddedWidget() override; + + QString caption() const override { return QStringLiteral("Calculator"); } + + QString name() const override { return QStringLiteral("Calculator"); } + + QJsonObject save() const override; + + void load(QJsonObject const &) override; + +private: + CalculatorWidget *_widget; + QString _value; +}; diff --git a/examples/compute_viewer/CalculatorWidget.cpp b/examples/compute_viewer/CalculatorWidget.cpp new file mode 100644 index 000000000..9aea2c497 --- /dev/null +++ b/examples/compute_viewer/CalculatorWidget.cpp @@ -0,0 +1,20 @@ +#include "CalculatorWidget.hpp" +#include +#include +#include +#include + +CalculatorWidget::CalculatorWidget(QString &_value, QWidget *parent) + : QWidget(parent) +{ + setSizePolicy(QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Minimum); + + QGridLayout *layout = new QGridLayout(this); + + QLabel *exp_label = new QLabel("Formula", this); + layout->addWidget(exp_label, 0, 0, 1, 1); + _exp_line = new QLineEdit(this); + _exp_line->setText(_value); + layout->addWidget(_exp_line, 0, 1, 1, 1); + connect(_exp_line, &QLineEdit::textChanged, [this, &_value](QString obj) { _value = obj; }); +} diff --git a/examples/compute_viewer/CalculatorWidget.hpp b/examples/compute_viewer/CalculatorWidget.hpp new file mode 100644 index 000000000..99e44a7d4 --- /dev/null +++ b/examples/compute_viewer/CalculatorWidget.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +using QtNodes::NodeId; +using QtNodes::PortIndex; +using QtNodes::PortType; + +class CalculatorWidget : public QWidget +{ + Q_OBJECT +public: + CalculatorWidget(QString &_f, QWidget *parent = nullptr); + + ~CalculatorWidget() = default; + + void setF(const QString &f) { _exp_line->setText(f); } + +private: + QLabel *exp_label; + QLineEdit *_exp_line; +}; diff --git a/examples/compute_viewer/ClutterFilterData.hpp b/examples/compute_viewer/ClutterFilterData.hpp new file mode 100644 index 000000000..dd546baf5 --- /dev/null +++ b/examples/compute_viewer/ClutterFilterData.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +using QtNodes::NodeData; +using QtNodes::NodeDataType; + +class ClutterFilterData : public NodeData +{ +public: + NodeDataType type() const override { return NodeDataType{"clutterfilter", "ClutterFilter"}; } +}; diff --git a/examples/compute_viewer/ClutterFilterModel.cpp b/examples/compute_viewer/ClutterFilterModel.cpp new file mode 100644 index 000000000..78aa79d83 --- /dev/null +++ b/examples/compute_viewer/ClutterFilterModel.cpp @@ -0,0 +1,61 @@ +#include "ClutterFilterModel.hpp" +#include "ClutterFilterData.hpp" +#include "ClutterFilterWidget.hpp" +#include "DasPwData.hpp" +#include +#include +#include + +using QtNodes::NodeStyle; + +unsigned int ClutterFilterModel::nPorts(PortType portType) const +{ + unsigned int result; + + if (portType == PortType::In) + result = 1; + else + result = 1; + + return result; +} + +NodeDataType ClutterFilterModel::dataType(PortType portType, PortIndex) const +{ + if (portType == PortType::In) { + return DasPwData().type(); + } else { + return ClutterFilterData().type(); + } +} + +std::shared_ptr ClutterFilterModel::outData(PortIndex) +{ + return nullptr; +} + +void ClutterFilterModel::setInData(std::shared_ptr data, PortIndex portIndex) {} + +QWidget *ClutterFilterModel::embeddedWidget() +{ + if (_widget) { + return _widget; + } + + _widget = new ClutterFilterWidget(_value, nullptr); + + return _widget; +} + +QJsonObject ClutterFilterModel::save() const +{ + QJsonObject retval = NodeDelegateModel::save(); + retval["value"] = _value; + return retval; +} + +void ClutterFilterModel::load(QJsonObject const &object) +{ + NodeDelegateModel::load(object); + _value = object["value"].toDouble(); +} diff --git a/examples/compute_viewer/ClutterFilterModel.hpp b/examples/compute_viewer/ClutterFilterModel.hpp new file mode 100644 index 000000000..2ec8cea54 --- /dev/null +++ b/examples/compute_viewer/ClutterFilterModel.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "ClutterFilterWidget.hpp" +#include +#include +#include +#include +#include +#include +#include + +using QtNodes::ConnectionPolicy; +using QtNodes::NodeData; +using QtNodes::NodeDataType; +using QtNodes::NodeDelegateModel; +using QtNodes::PortIndex; +using QtNodes::PortType; + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class ClutterFilterModel : public NodeDelegateModel +{ + Q_OBJECT + +public: + ~ClutterFilterModel() override = default; + +public: + unsigned int nPorts(PortType portType) const override; + + NodeDataType dataType(PortType portType, PortIndex portIndex) const override; + + std::shared_ptr outData(PortIndex port) override; + + void setInData(std::shared_ptr data, PortIndex portIndex) override; + + QWidget *embeddedWidget() override; + + QString caption() const override { return QStringLiteral("ClutterFilter"); } + + QString name() const override { return QStringLiteral("ClutterFilter"); } + + QJsonObject save() const override; + + void load(QJsonObject const &) override; + +private: + ClutterFilterWidget *_widget; + float _value; +}; diff --git a/examples/compute_viewer/ClutterFilterWidget.cpp b/examples/compute_viewer/ClutterFilterWidget.cpp new file mode 100644 index 000000000..3d0df785a --- /dev/null +++ b/examples/compute_viewer/ClutterFilterWidget.cpp @@ -0,0 +1,41 @@ +#include "ClutterFilterWidget.hpp" +#include +#include +#include +#include +#include +#include +#include +#include + +ClutterFilterWidget::ClutterFilterWidget(float &_value, QWidget *parent) + : QWidget(parent) +{ + setSizePolicy(QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Minimum); + + QGridLayout *layout = new QGridLayout(this); + + _value = std::clamp(_value, 0.15f, 0.75f); + + _value_line = new QLineEdit(this); + _value_line->setValidator(new QDoubleValidator()); + _value_line->setText(QString::number(_value)); + _value_line->setFixedWidth(40); + layout->addWidget(_value_line, 0, 0, 1, 1); + + _value_scroll = new QSlider(Qt::Orientation::Horizontal, this); + _value_scroll->setMinimum(15); + _value_scroll->setMaximum(75); + _value_scroll->setValue(round(_value * 100)); + _value_scroll->setFixedWidth(150); + layout->addWidget(_value_scroll, 0, 1, 1, 1); + + connect(_value_line, &QLineEdit::textChanged, [this, &_value](QString obj) { + _value = obj.toFloat(); + _value_scroll->setValue(static_cast(round(_value * 100.))); + }); + connect(_value_scroll, &QSlider::valueChanged, [this, &_value](int value) { + _value = static_cast(value) / 100.; + _value_line->setText(QString::number(_value)); + }); +} diff --git a/examples/compute_viewer/ClutterFilterWidget.hpp b/examples/compute_viewer/ClutterFilterWidget.hpp new file mode 100644 index 000000000..9169c8da9 --- /dev/null +++ b/examples/compute_viewer/ClutterFilterWidget.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +using QtNodes::NodeId; +using QtNodes::PortIndex; +using QtNodes::PortType; + +class ClutterFilterWidget : public QWidget +{ + Q_OBJECT +public: + ClutterFilterWidget(float &_f, QWidget *parent = nullptr); + + ~ClutterFilterWidget() = default; + + void setF(float f) + { + _value_scroll->setValue(static_cast(f * 100.)); + _value_line->setText(QString::number(f)); + } + +private: + QLineEdit *_value_line; + QSlider *_value_scroll; +}; diff --git a/examples/compute_viewer/DasPwData.hpp b/examples/compute_viewer/DasPwData.hpp new file mode 100644 index 000000000..ec1f46a30 --- /dev/null +++ b/examples/compute_viewer/DasPwData.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +using QtNodes::NodeData; +using QtNodes::NodeDataType; + +class DasPwData : public NodeData +{ +public: + NodeDataType type() const override { return NodeDataType{"daspw", "DasPw"}; } +}; diff --git a/examples/compute_viewer/DasPwModel.cpp b/examples/compute_viewer/DasPwModel.cpp new file mode 100644 index 000000000..db367561e --- /dev/null +++ b/examples/compute_viewer/DasPwModel.cpp @@ -0,0 +1,63 @@ +#include "DasPwModel.hpp" +#include "DasPwData.hpp" +#include "DasPwWidget.hpp" +#include "DecimationData.hpp" +#include +#include +#include + +using QtNodes::NodeStyle; + +unsigned int DasPwModel::nPorts(PortType portType) const +{ + unsigned int result; + + if (portType == PortType::In) + result = 1; + else + result = 1; + + return result; +} + +NodeDataType DasPwModel::dataType(PortType portType, PortIndex) const +{ + if (portType == PortType::In) { + return DecimationData().type(); + } else { + return DasPwData().type(); + } +} + +std::shared_ptr DasPwModel::outData(PortIndex) +{ + return nullptr; +} + +void DasPwModel::setInData(std::shared_ptr data, PortIndex portIndex) {} + +QWidget *DasPwModel::embeddedWidget() +{ + if (_widget) { + return _widget; + } + + _widget = new DasPwWidget(_f, _c0, nullptr); + + return _widget; +} + +QJsonObject DasPwModel::save() const +{ + QJsonObject retval = NodeDelegateModel::save(); + retval["F"] = _f; + retval["c0"] = _c0; + return retval; +} + +void DasPwModel::load(QJsonObject const &object) +{ + NodeDelegateModel::load(object); + _f = object["F"].toDouble(); + _c0 = object["c0"].toDouble(); +} diff --git a/examples/compute_viewer/DasPwModel.hpp b/examples/compute_viewer/DasPwModel.hpp new file mode 100644 index 000000000..ee695d87d --- /dev/null +++ b/examples/compute_viewer/DasPwModel.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include "DasPwWidget.hpp" +#include +#include +#include +#include +#include +#include +#include + +using QtNodes::ConnectionPolicy; +using QtNodes::NodeData; +using QtNodes::NodeDataType; +using QtNodes::NodeDelegateModel; +using QtNodes::PortIndex; +using QtNodes::PortType; + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class DasPwModel : public NodeDelegateModel +{ + Q_OBJECT + +public: + ~DasPwModel() override = default; + +public: + unsigned int nPorts(PortType portType) const override; + + NodeDataType dataType(PortType portType, PortIndex portIndex) const override; + + std::shared_ptr outData(PortIndex port) override; + + void setInData(std::shared_ptr data, PortIndex portIndex) override; + + QWidget *embeddedWidget() override; + + QString caption() const override { return QStringLiteral("DasPw"); } + + QString name() const override { return QStringLiteral("DasPw"); } + + QJsonObject save() const override; + + void load(QJsonObject const &) override; + +private: + DasPwWidget *_widget; + float _f; + float _c0; +}; diff --git a/examples/compute_viewer/DasPwWidget.cpp b/examples/compute_viewer/DasPwWidget.cpp new file mode 100644 index 000000000..567ba9774 --- /dev/null +++ b/examples/compute_viewer/DasPwWidget.cpp @@ -0,0 +1,32 @@ +#include "DasPwWidget.hpp" +#include +#include +#include +#include +#include + +DasPwWidget::DasPwWidget(float &_f, float &_c0, QWidget *parent) + : QWidget(parent) +{ + setSizePolicy(QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Minimum); + + QGridLayout *layout = new QGridLayout(this); + + QLabel *f_label = new QLabel("F#", this); + layout->addWidget(f_label, 0, 0, 1, 1); + _f_line = new QLineEdit(this); + _f_line->setValidator(new QDoubleValidator()); + _f_line->setText(QString::number(_f)); + _f_line->setFixedWidth(40); + layout->addWidget(_f_line, 0, 1, 1, 1); + connect(_f_line, &QLineEdit::textChanged, [this, &_f](QString obj) { _f = obj.toFloat(); }); + + QLabel *c0_label = new QLabel("c0", this); + layout->addWidget(c0_label, 1, 0, 1, 1); + _c0_line = new QLineEdit(this); + _c0_line->setValidator(new QDoubleValidator()); + _c0_line->setText(QString::number(_c0)); + _c0_line->setFixedWidth(40); + layout->addWidget(_c0_line, 1, 1, 1, 1); + connect(_c0_line, &QLineEdit::textChanged, [this, &_c0](QString obj) { _c0 = obj.toFloat(); }); +} diff --git a/examples/compute_viewer/DasPwWidget.hpp b/examples/compute_viewer/DasPwWidget.hpp new file mode 100644 index 000000000..a43e6cb6c --- /dev/null +++ b/examples/compute_viewer/DasPwWidget.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include +#include +#include + +using QtNodes::NodeId; +using QtNodes::PortIndex; +using QtNodes::PortType; + +class DasPwWidget : public QWidget +{ + Q_OBJECT +public: + DasPwWidget(float &_f, float &_c0, QWidget *parent = nullptr); + + ~DasPwWidget() = default; + + void setF(float f) { _f_line->setText(QString::number(f)); } + + void setC0(float c0) { _c0_line->setText(QString::number(c0)); } + +private: + QLineEdit *_f_line; + QLineEdit *_c0_line; +}; diff --git a/examples/compute_viewer/DecimationData.hpp b/examples/compute_viewer/DecimationData.hpp new file mode 100644 index 000000000..6724e64d2 --- /dev/null +++ b/examples/compute_viewer/DecimationData.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +using QtNodes::NodeData; +using QtNodes::NodeDataType; + +class DecimationData : public NodeData +{ +public: + NodeDataType type() const override { return NodeDataType{"decimation", "Decimation"}; } +}; diff --git a/examples/compute_viewer/DecimationModel.cpp b/examples/compute_viewer/DecimationModel.cpp new file mode 100644 index 000000000..72811ac18 --- /dev/null +++ b/examples/compute_viewer/DecimationModel.cpp @@ -0,0 +1,61 @@ +#include "DecimationModel.hpp" +#include "DecimationData.hpp" +#include "DecimationWidget.hpp" +#include "InputData.hpp" +#include +#include +#include + +using QtNodes::NodeStyle; + +unsigned int DecimationModel::nPorts(PortType portType) const +{ + unsigned int result; + + if (portType == PortType::In) + result = 1; + else + result = 1; + + return result; +} + +NodeDataType DecimationModel::dataType(PortType portType, PortIndex) const +{ + if (portType == PortType::In) { + return InputData().type(); + } else { + return DecimationData().type(); + } +} + +std::shared_ptr DecimationModel::outData(PortIndex) +{ + return nullptr; +} + +void DecimationModel::setInData(std::shared_ptr data, PortIndex portIndex) {} + +QWidget *DecimationModel::embeddedWidget() +{ + if (_widget) { + return _widget; + } + + _widget = new DecimationWidget(_m, nullptr); + + return _widget; +} + +QJsonObject DecimationModel::save() const +{ + QJsonObject retval = NodeDelegateModel::save(); + retval["M"] = _m; + return retval; +} + +void DecimationModel::load(QJsonObject const &object) +{ + NodeDelegateModel::load(object); + _m = object["M"].toDouble(); +} diff --git a/examples/compute_viewer/DecimationModel.hpp b/examples/compute_viewer/DecimationModel.hpp new file mode 100644 index 000000000..d91e5ba01 --- /dev/null +++ b/examples/compute_viewer/DecimationModel.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "DecimationWidget.hpp" +#include +#include +#include +#include +#include +#include +#include + +using QtNodes::ConnectionPolicy; +using QtNodes::NodeData; +using QtNodes::NodeDataType; +using QtNodes::NodeDelegateModel; +using QtNodes::PortIndex; +using QtNodes::PortType; + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class DecimationModel : public NodeDelegateModel +{ + Q_OBJECT + +public: + ~DecimationModel() override = default; + +public: + unsigned int nPorts(PortType portType) const override; + + NodeDataType dataType(PortType portType, PortIndex portIndex) const override; + + std::shared_ptr outData(PortIndex port) override; + + void setInData(std::shared_ptr data, PortIndex portIndex) override; + + QWidget *embeddedWidget() override; + + QString caption() const override { return QStringLiteral("Decimation"); } + + QString name() const override { return QStringLiteral("Decimation"); } + + QJsonObject save() const override; + + void load(QJsonObject const &) override; + +private: + DecimationWidget *_widget; + float _m; +}; diff --git a/examples/compute_viewer/DecimationWidget.cpp b/examples/compute_viewer/DecimationWidget.cpp new file mode 100644 index 000000000..44af7df90 --- /dev/null +++ b/examples/compute_viewer/DecimationWidget.cpp @@ -0,0 +1,23 @@ +#include "DecimationWidget.hpp" +#include +#include +#include +#include +#include + +DecimationWidget::DecimationWidget(float &_m, QWidget *parent) + : QWidget(nullptr) +{ + setSizePolicy(QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Minimum); + + QGridLayout *layout = new QGridLayout(this); + + QLabel *m_label = new QLabel("M", this); + layout->addWidget(m_label, 0, 0, 1, 1); + _m_line = new QLineEdit(this); + _m_line->setValidator(new QDoubleValidator()); + _m_line->setText(QString::number(_m)); + _m_line->setFixedWidth(40); + layout->addWidget(_m_line, 0, 1, 1, 1); + connect(_m_line, &QLineEdit::textChanged, [this, &_m](QString obj) { _m = obj.toFloat(); }); +} diff --git a/examples/compute_viewer/DecimationWidget.hpp b/examples/compute_viewer/DecimationWidget.hpp new file mode 100644 index 000000000..c404c4e0c --- /dev/null +++ b/examples/compute_viewer/DecimationWidget.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include +#include +#include + +using QtNodes::NodeId; +using QtNodes::PortIndex; +using QtNodes::PortType; + +class DecimationWidget : public QWidget +{ + Q_OBJECT +public: + DecimationWidget(float &_m, QWidget *parent = nullptr); + + ~DecimationWidget() = default; + + void setM(float m) { _m_line->setText(QString::number(m)); } + +private: + QLineEdit *_m_line; +}; diff --git a/examples/compute_viewer/DopplerViewerData.hpp b/examples/compute_viewer/DopplerViewerData.hpp new file mode 100644 index 000000000..c5473e1a2 --- /dev/null +++ b/examples/compute_viewer/DopplerViewerData.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +using QtNodes::NodeData; +using QtNodes::NodeDataType; + +class DopplerViewerData : public NodeData +{ +public: + NodeDataType type() const override { return NodeDataType{"dopplerviewer", "DopplerViewer"}; } +}; diff --git a/examples/compute_viewer/DopplerViewerModel.cpp b/examples/compute_viewer/DopplerViewerModel.cpp new file mode 100644 index 000000000..0e52100fd --- /dev/null +++ b/examples/compute_viewer/DopplerViewerModel.cpp @@ -0,0 +1,39 @@ +#include "DopplerViewerModel.hpp" +#include "ClutterFilterData.hpp" +#include "DopplerViewerData.hpp" +#include + +using QtNodes::NodeStyle; + +unsigned int DopplerViewerModel::nPorts(PortType portType) const +{ + unsigned int result; + + if (portType == PortType::In) + result = 1; + else + result = 0; + + return result; +} + +NodeDataType DopplerViewerModel::dataType(PortType portType, PortIndex) const +{ + if (portType == PortType::In) { + return ClutterFilterData().type(); + } else { + return DopplerViewerData().type(); + } +} + +std::shared_ptr DopplerViewerModel::outData(PortIndex) +{ + return nullptr; +} + +void DopplerViewerModel::setInData(std::shared_ptr data, PortIndex portIndex) {} + +QWidget *DopplerViewerModel::embeddedWidget() +{ + return nullptr; +} diff --git a/examples/compute_viewer/DopplerViewerModel.hpp b/examples/compute_viewer/DopplerViewerModel.hpp new file mode 100644 index 000000000..5c2e660b5 --- /dev/null +++ b/examples/compute_viewer/DopplerViewerModel.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +using QtNodes::ConnectionPolicy; +using QtNodes::NodeData; +using QtNodes::NodeDataType; +using QtNodes::NodeDelegateModel; +using QtNodes::PortIndex; +using QtNodes::PortType; + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class DopplerViewerModel : public NodeDelegateModel +{ + Q_OBJECT + +public: + ~DopplerViewerModel() override = default; + +public: + unsigned int nPorts(PortType portType) const override; + + NodeDataType dataType(PortType portType, PortIndex portIndex) const override; + + std::shared_ptr outData(PortIndex port) override; + + void setInData(std::shared_ptr data, PortIndex portIndex) override; + + QWidget *embeddedWidget() override; + + QString caption() const override { return QStringLiteral("DopplerViewer"); } + + QString name() const override { return QStringLiteral("DopplerViewer"); } + +private: + float _value; +}; diff --git a/examples/compute_viewer/InputData.hpp b/examples/compute_viewer/InputData.hpp new file mode 100644 index 000000000..748a27371 --- /dev/null +++ b/examples/compute_viewer/InputData.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +using QtNodes::NodeData; +using QtNodes::NodeDataType; + +class InputData : public NodeData +{ +public: + NodeDataType type() const override { return NodeDataType{"input", "Input"}; } +}; diff --git a/examples/compute_viewer/InputModel.cpp b/examples/compute_viewer/InputModel.cpp new file mode 100644 index 000000000..e42950198 --- /dev/null +++ b/examples/compute_viewer/InputModel.cpp @@ -0,0 +1,34 @@ +#include "InputModel.hpp" +#include "InputData.hpp" +#include + +using QtNodes::NodeStyle; + +unsigned int InputModel::nPorts(PortType portType) const +{ + unsigned int result; + + if (portType == PortType::In) + result = 0; + else + result = 1; + + return result; +} + +NodeDataType InputModel::dataType(PortType, PortIndex) const +{ + return InputData().type(); +} + +std::shared_ptr InputModel::outData(PortIndex) +{ + return nullptr; +} + +void InputModel::setInData(std::shared_ptr data, PortIndex portIndex) {} + +QWidget *InputModel::embeddedWidget() +{ + return nullptr; +} diff --git a/examples/compute_viewer/InputModel.hpp b/examples/compute_viewer/InputModel.hpp new file mode 100644 index 000000000..62b75d89e --- /dev/null +++ b/examples/compute_viewer/InputModel.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +using QtNodes::ConnectionPolicy; +using QtNodes::NodeData; +using QtNodes::NodeDataType; +using QtNodes::NodeDelegateModel; +using QtNodes::PortIndex; +using QtNodes::PortType; + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class InputModel : public NodeDelegateModel +{ + Q_OBJECT + +public: + ~InputModel() override = default; + +public: + unsigned int nPorts(PortType portType) const override; + + NodeDataType dataType(PortType portType, PortIndex portIndex) const override; + + std::shared_ptr outData(PortIndex port) override; + + void setInData(std::shared_ptr data, PortIndex portIndex) override; + + QWidget *embeddedWidget() override; + + QString caption() const override { return QStringLiteral("Input"); } + + QString name() const override { return QStringLiteral("Input"); } +}; diff --git a/examples/compute_viewer/OutputModel.cpp b/examples/compute_viewer/OutputModel.cpp new file mode 100644 index 000000000..d60c73563 --- /dev/null +++ b/examples/compute_viewer/OutputModel.cpp @@ -0,0 +1,34 @@ +#include "OutputModel.hpp" +#include "CalculatorData.hpp" +#include + +using QtNodes::NodeStyle; + +unsigned int OutputModel::nPorts(PortType portType) const +{ + unsigned int result; + + if (portType == PortType::In) + result = 1; + else + result = 0; + + return result; +} + +NodeDataType OutputModel::dataType(PortType, PortIndex) const +{ + return CalculatorData().type(); +} + +std::shared_ptr OutputModel::outData(PortIndex) +{ + return nullptr; +} + +void OutputModel::setInData(std::shared_ptr data, PortIndex portIndex) {} + +QWidget *OutputModel::embeddedWidget() +{ + return nullptr; +} diff --git a/examples/compute_viewer/OutputModel.hpp b/examples/compute_viewer/OutputModel.hpp new file mode 100644 index 000000000..f003bd78d --- /dev/null +++ b/examples/compute_viewer/OutputModel.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +using QtNodes::ConnectionPolicy; +using QtNodes::NodeData; +using QtNodes::NodeDataType; +using QtNodes::NodeDelegateModel; +using QtNodes::PortIndex; +using QtNodes::PortType; + +/// The model dictates the number of outputs and outputs for the Node. +/// In this example it has no logic. +class OutputModel : public NodeDelegateModel +{ + Q_OBJECT + +public: + ~OutputModel() override = default; + +public: + unsigned int nPorts(PortType portType) const override; + + NodeDataType dataType(PortType portType, PortIndex portIndex) const override; + + std::shared_ptr outData(PortIndex port) override; + + void setInData(std::shared_ptr data, PortIndex portIndex) override; + + QWidget *embeddedWidget() override; + + QString caption() const override { return QStringLiteral("Output"); } + + QString name() const override { return QStringLiteral("Output"); } +}; diff --git a/examples/compute_viewer/RoiData.hpp b/examples/compute_viewer/RoiData.hpp new file mode 100644 index 000000000..424450339 --- /dev/null +++ b/examples/compute_viewer/RoiData.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +using QtNodes::NodeData; +using QtNodes::NodeDataType; + +class RoiData : public NodeData +{ +public: + NodeDataType type() const override { return NodeDataType{"roi", "Roi"}; } +}; diff --git a/examples/compute_viewer/RoiRectModel.cpp b/examples/compute_viewer/RoiRectModel.cpp new file mode 100644 index 000000000..c665faea7 --- /dev/null +++ b/examples/compute_viewer/RoiRectModel.cpp @@ -0,0 +1,71 @@ +#include "RoiRectModel.hpp" +#include "ClutterFilterData.hpp" +#include "RoiData.hpp" +#include "RoiRectWidget.hpp" +#include +#include +#include + +using QtNodes::NodeStyle; + +unsigned int RoiRectModel::nPorts(PortType portType) const +{ + unsigned int result; + + if (portType == PortType::In) + result = 1; + else + result = 1; + + return result; +} + +NodeDataType RoiRectModel::dataType(PortType portType, PortIndex) const +{ + if (portType == PortType::In) { + return ClutterFilterData().type(); + } else { + return RoiData().type(); + } +} + +std::shared_ptr RoiRectModel::outData(PortIndex) +{ + return nullptr; +} + +void RoiRectModel::setInData(std::shared_ptr data, PortIndex portIndex) {} + +QWidget *RoiRectModel::embeddedWidget() +{ + if (_widget) { + return _widget; + } + + _widget = new RoiRectWidget(_x1, _x2, _y1, _y2, _z1, _z2, nullptr); + + return _widget; +} + +QJsonObject RoiRectModel::save() const +{ + QJsonObject retval = NodeDelegateModel::save(); + retval["x1"] = _x1; + retval["x2"] = _x2; + retval["y1"] = _y1; + retval["y2"] = _y2; + retval["z1"] = _z1; + retval["z2"] = _z2; + return retval; +} + +void RoiRectModel::load(QJsonObject const &object) +{ + NodeDelegateModel::load(object); + _x1 = object["x1"].toDouble(); + _x2 = object["x2"].toDouble(); + _y1 = object["y1"].toDouble(); + _y2 = object["y2"].toDouble(); + _z1 = object["z1"].toDouble(); + _z2 = object["z2"].toDouble(); +} diff --git a/examples/compute_viewer/RoiRectModel.hpp b/examples/compute_viewer/RoiRectModel.hpp new file mode 100644 index 000000000..918fe920c --- /dev/null +++ b/examples/compute_viewer/RoiRectModel.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include "RoiRectWidget.hpp" +#include +#include +#include +#include +#include +#include +#include + +using QtNodes::ConnectionPolicy; +using QtNodes::NodeData; +using QtNodes::NodeDataType; +using QtNodes::NodeDelegateModel; +using QtNodes::PortIndex; +using QtNodes::PortType; + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class RoiRectModel : public NodeDelegateModel +{ + Q_OBJECT + +public: + ~RoiRectModel() override = default; + +public: + unsigned int nPorts(PortType portType) const override; + + NodeDataType dataType(PortType portType, PortIndex portIndex) const override; + + std::shared_ptr outData(PortIndex port) override; + + void setInData(std::shared_ptr data, PortIndex portIndex) override; + + QWidget *embeddedWidget() override; + + QString caption() const override { return QStringLiteral("Roi"); } + + QString name() const override { return QStringLiteral("RoiRect"); } + + QJsonObject save() const override; + + void load(QJsonObject const &) override; + +private: + RoiRectWidget *_widget; + float _x1; + float _x2; + float _y1; + float _y2; + float _z1; + float _z2; +}; diff --git a/examples/compute_viewer/RoiRectWidget.cpp b/examples/compute_viewer/RoiRectWidget.cpp new file mode 100644 index 000000000..f241bf100 --- /dev/null +++ b/examples/compute_viewer/RoiRectWidget.cpp @@ -0,0 +1,70 @@ +#include "RoiRectWidget.hpp" +#include +#include +#include +#include +#include + +RoiRectWidget::RoiRectWidget( + float &x1, float &x2, float &y1, float &y2, float &z1, float &z2, QWidget *parent) + : QWidget(parent) +{ + setSizePolicy(QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Minimum); + + QGridLayout *layout = new QGridLayout(this); + + _x1 = new QLineEdit(this); + _x1->setValidator(new QDoubleValidator()); + _x1->setText(QString::number(x1)); + _x1->setFixedWidth(40); + layout->addWidget(_x1, 1, 1, 1, 1); + connect(_x1, &QLineEdit::textChanged, [this, &x1](QString obj) { x1 = obj.toFloat(); }); + + _x2 = new QLineEdit(this); + _x2->setValidator(new QDoubleValidator()); + _x2->setText(QString::number(x2)); + _x2->setFixedWidth(40); + layout->addWidget(_x2, 1, 2, 1, 1); + connect(_x2, &QLineEdit::textChanged, [this, &x2](QString obj) { x2 = obj.toFloat(); }); + + _y1 = new QLineEdit(this); + _y1->setValidator(new QDoubleValidator()); + _y1->setText(QString::number(y1)); + _y1->setFixedWidth(40); + layout->addWidget(_y1, 2, 1, 1, 1); + connect(_y1, &QLineEdit::textChanged, [this, &y1](QString obj) { y1 = obj.toFloat(); }); + + _y2 = new QLineEdit(this); + _y2->setValidator(new QDoubleValidator()); + _y2->setText(QString::number(y2)); + _y2->setFixedWidth(40); + layout->addWidget(_y2, 2, 2, 1, 1); + connect(_y2, &QLineEdit::textChanged, [this, &y2](QString obj) { y2 = obj.toFloat(); }); + + _z1 = new QLineEdit(this); + _z1->setValidator(new QDoubleValidator()); + _z1->setText(QString::number(z1)); + _z1->setFixedWidth(40); + layout->addWidget(_z1, 3, 1, 1, 1); + connect(_z1, &QLineEdit::textChanged, [this, &z1](QString obj) { z1 = obj.toFloat(); }); + + _z2 = new QLineEdit(this); + _z2->setValidator(new QDoubleValidator()); + _z2->setText(QString::number(z2)); + _z2->setFixedWidth(40); + layout->addWidget(_z2, 3, 2, 1, 1); + connect(_z2, &QLineEdit::textChanged, [this, &z2](QString obj) { z2 = obj.toFloat(); }); + + QLabel *label; + label = new QLabel("x", this); + layout->addWidget(label, 1, 0, 1, 1); + label = new QLabel("y", this); + layout->addWidget(label, 2, 0, 1, 1); + label = new QLabel("z", this); + layout->addWidget(label, 3, 0, 1, 1); + + label = new QLabel("min", this); + layout->addWidget(label, 0, 1, 1, 1); + label = new QLabel("max", this); + layout->addWidget(label, 0, 2, 1, 1); +} diff --git a/examples/compute_viewer/RoiRectWidget.hpp b/examples/compute_viewer/RoiRectWidget.hpp new file mode 100644 index 000000000..d1f3ee70e --- /dev/null +++ b/examples/compute_viewer/RoiRectWidget.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include +#include +#include +#include +#include + +using QtNodes::NodeId; +using QtNodes::PortIndex; +using QtNodes::PortType; + +class RoiRectWidget : public QWidget +{ + Q_OBJECT +public: + RoiRectWidget( + float &x1, float &x2, float &y1, float &y2, float &z1, float &z2, QWidget *parent = nullptr); + + ~RoiRectWidget() = default; + + void setX1(float f) { _x1->setText(QString::number(f)); } + void setX2(float f) { _x2->setText(QString::number(f)); } + void setY1(float f) { _y1->setText(QString::number(f)); } + void setY2(float f) { _y2->setText(QString::number(f)); } + void setZ1(float f) { _z1->setText(QString::number(f)); } + void setZ2(float f) { _z2->setText(QString::number(f)); } + +private: + QLineEdit *_x1; + QLineEdit *_x2; + QLineEdit *_y1; + QLineEdit *_y2; + QLineEdit *_z1; + QLineEdit *_z2; +}; diff --git a/examples/compute_viewer/RoiSphereModel.cpp b/examples/compute_viewer/RoiSphereModel.cpp new file mode 100644 index 000000000..fc07afb09 --- /dev/null +++ b/examples/compute_viewer/RoiSphereModel.cpp @@ -0,0 +1,67 @@ +#include "RoiSphereModel.hpp" +#include "ClutterFilterData.hpp" +#include "RoiData.hpp" +#include "RoiSphereWidget.hpp" +#include +#include +#include + +using QtNodes::NodeStyle; + +unsigned int RoiSphereModel::nPorts(PortType portType) const +{ + unsigned int result; + + if (portType == PortType::In) + result = 1; + else + result = 1; + + return result; +} + +NodeDataType RoiSphereModel::dataType(PortType portType, PortIndex) const +{ + if (portType == PortType::In) { + return ClutterFilterData().type(); + } else { + return RoiData().type(); + } +} + +std::shared_ptr RoiSphereModel::outData(PortIndex) +{ + return nullptr; +} + +void RoiSphereModel::setInData(std::shared_ptr data, PortIndex portIndex) {} + +QWidget *RoiSphereModel::embeddedWidget() +{ + if (_widget) { + return _widget; + } + + _widget = new RoiSphereWidget(_x, _y, _z, _r, nullptr); + + return nullptr; +} + +QJsonObject RoiSphereModel::save() const +{ + QJsonObject retval = NodeDelegateModel::save(); + retval["x"] = _x; + retval["y"] = _y; + retval["z"] = _z; + retval["r"] = _r; + return retval; +} + +void RoiSphereModel::load(QJsonObject const &object) +{ + NodeDelegateModel::load(object); + _x = object["x"].toDouble(); + _y = object["y"].toDouble(); + _z = object["z"].toDouble(); + _r = object["r"].toDouble(); +} diff --git a/examples/compute_viewer/RoiSphereModel.hpp b/examples/compute_viewer/RoiSphereModel.hpp new file mode 100644 index 000000000..a7e97d719 --- /dev/null +++ b/examples/compute_viewer/RoiSphereModel.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include "RoiSphereWidget.hpp" +#include +#include +#include +#include +#include +#include +#include + +using QtNodes::ConnectionPolicy; +using QtNodes::NodeData; +using QtNodes::NodeDataType; +using QtNodes::NodeDelegateModel; +using QtNodes::PortIndex; +using QtNodes::PortType; + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class RoiSphereModel : public NodeDelegateModel +{ + Q_OBJECT + +public: + ~RoiSphereModel() override = default; + +public: + unsigned int nPorts(PortType portType) const override; + + NodeDataType dataType(PortType portType, PortIndex portIndex) const override; + + std::shared_ptr outData(PortIndex port) override; + + void setInData(std::shared_ptr data, PortIndex portIndex) override; + + QWidget *embeddedWidget() override; + + QString caption() const override { return QStringLiteral("Roi"); } + + QString name() const override { return QStringLiteral("RoiSphere"); } + + QJsonObject save() const override; + + void load(QJsonObject const &) override; + +private: + RoiSphereWidget *_widget; + float _x; + float _y; + float _z; + float _r; +}; diff --git a/examples/compute_viewer/RoiSphereWidget.cpp b/examples/compute_viewer/RoiSphereWidget.cpp new file mode 100644 index 000000000..ffad9a625 --- /dev/null +++ b/examples/compute_viewer/RoiSphereWidget.cpp @@ -0,0 +1,52 @@ +#include "RoiSphereWidget.hpp" +#include +#include +#include +#include +#include + +RoiSphereWidget::RoiSphereWidget(float &x, float &y, float &z, float &r, QWidget *parent) + : QWidget(parent) +{ + setSizePolicy(QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Minimum); + + QGridLayout *layout = new QGridLayout(this); + + _x = new QLineEdit(this); + _x->setValidator(new QDoubleValidator()); + _x->setText(QString::number(x)); + _x->setFixedWidth(40); + layout->addWidget(_x, 0, 1, 1, 1); + connect(_x, &QLineEdit::textChanged, [this, &x](QString obj) { x = obj.toFloat(); }); + + _y = new QLineEdit(this); + _y->setValidator(new QDoubleValidator()); + _y->setText(QString::number(y)); + _y->setFixedWidth(40); + layout->addWidget(_y, 1, 1, 1, 1); + connect(_y, &QLineEdit::textChanged, [this, &y](QString obj) { y = obj.toFloat(); }); + + _z = new QLineEdit(this); + _z->setValidator(new QDoubleValidator()); + _z->setText(QString::number(z)); + _z->setFixedWidth(40); + layout->addWidget(_z, 2, 1, 1, 1); + connect(_z, &QLineEdit::textChanged, [this, &z](QString obj) { z = obj.toFloat(); }); + + _r = new QLineEdit(this); + _r->setValidator(new QDoubleValidator()); + _r->setText(QString::number(r)); + _r->setFixedWidth(40); + layout->addWidget(_r, 3, 1, 1, 1); + connect(_r, &QLineEdit::textChanged, [this, &r](QString obj) { r = obj.toFloat(); }); + + QLabel *label; + label = new QLabel("x", this); + layout->addWidget(label, 0, 0, 1, 1); + label = new QLabel("y", this); + layout->addWidget(label, 1, 0, 1, 1); + label = new QLabel("z", this); + layout->addWidget(label, 2, 0, 1, 1); + label = new QLabel("r", this); + layout->addWidget(label, 3, 0, 1, 1); +} diff --git a/examples/compute_viewer/RoiSphereWidget.hpp b/examples/compute_viewer/RoiSphereWidget.hpp new file mode 100644 index 000000000..9479dbefe --- /dev/null +++ b/examples/compute_viewer/RoiSphereWidget.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include +#include + +using QtNodes::NodeId; +using QtNodes::PortIndex; +using QtNodes::PortType; + +class RoiSphereWidget : public QWidget +{ + Q_OBJECT +public: + RoiSphereWidget(float &x, float &y, float &z, float &r, QWidget *parent = nullptr); + + ~RoiSphereWidget() = default; + + void setX(float f) { _x->setText(QString::number(f)); } + void setY(float f) { _y->setText(QString::number(f)); } + void setZ(float f) { _z->setText(QString::number(f)); } + void setR(float f) { _r->setText(QString::number(f)); } + +private: + QLineEdit *_x; + QLineEdit *_y; + QLineEdit *_z; + QLineEdit *_r; +}; diff --git a/examples/compute_viewer/example.flow b/examples/compute_viewer/example.flow new file mode 100644 index 000000000..ad527a675 --- /dev/null +++ b/examples/compute_viewer/example.flow @@ -0,0 +1,197 @@ +{ + "connections": [ + { + "inPortIndex": 0, + "intNodeId": 9, + "outNodeId": 7, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 2, + "outNodeId": 1, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 1, + "outNodeId": 0, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 7, + "outNodeId": 5, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 3, + "outNodeId": 2, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 4, + "outNodeId": 3, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 5, + "outNodeId": 3, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 6, + "outNodeId": 3, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 8, + "outNodeId": 6, + "outPortIndex": 0 + }, + { + "inPortIndex": 1, + "intNodeId": 9, + "outNodeId": 8, + "outPortIndex": 0 + }, + { + "inPortIndex": 0, + "intNodeId": 10, + "outNodeId": 9, + "outPortIndex": 0 + } + ], + "nodes": [ + { + "id": 0, + "internal-data": { + "model-name": "Input" + }, + "position": { + "x": -78, + "y": -89.04032850545761 + } + }, + { + "id": 1, + "internal-data": { + "M": 4, + "model-name": "Decimation" + }, + "position": { + "x": 62, + "y": -90 + } + }, + { + "id": 2, + "internal-data": { + "F": 1.5, + "c0": 1540, + "model-name": "DasPw" + }, + "position": { + "x": 478, + "y": -42 + } + }, + { + "id": 3, + "internal-data": { + "model-name": "ClutterFilter", + "value": 0.4099999964237213 + }, + "position": { + "x": 897.3249370277077, + "y": -13.465994962216623 + } + }, + { + "id": 4, + "internal-data": { + "model-name": "DopplerViewer" + }, + "position": { + "x": 1367.9999999999998, + "y": -14.399999999999997 + } + }, + { + "id": 5, + "internal-data": { + "model-name": "RoiRect", + "x1": 1, + "x2": 2, + "y1": 3, + "y2": 4, + "z1": 5, + "z2": 6 + }, + "position": { + "x": 143.98964455639518, + "y": 199.3702770780856 + } + }, + { + "id": 6, + "internal-data": { + "model-name": "RoiSphere", + "r": 1, + "x": 4, + "y": 3, + "z": 2 + }, + "position": { + "x": 164.7573817520291, + "y": 452.7366708648194 + } + }, + { + "id": 7, + "internal-data": { + "model-name": "Average" + }, + "position": { + "x": 654.760603251236, + "y": 249.02055248468446 + } + }, + { + "id": 8, + "internal-data": { + "model-name": "Average" + }, + "position": { + "x": 642.2615021612712, + "y": 457.6593937556364 + } + }, + { + "id": 9, + "internal-data": { + "expression": "x1+x2", + "model-name": "Calculator" + }, + "position": { + "x": 841.2856502860965, + "y": 328.5020158259996 + } + }, + { + "id": 10, + "internal-data": { + "model-name": "Output" + }, + "position": { + "x": 1240, + "y": 327 + } + } + ] +} diff --git a/examples/compute_viewer/main.cpp b/examples/compute_viewer/main.cpp new file mode 100644 index 000000000..9c688aef5 --- /dev/null +++ b/examples/compute_viewer/main.cpp @@ -0,0 +1,114 @@ +#include "AverageModel.hpp" +#include "CalculatorModel.hpp" +#include "ClutterFilterModel.hpp" +#include "DasPwModel.hpp" +#include "DecimationModel.hpp" +#include "DopplerViewerModel.hpp" +#include "InputModel.hpp" +#include "OutputModel.hpp" +#include "RoiRectModel.hpp" +#include "RoiSphereModel.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using QtNodes::ConnectionStyle; +using QtNodes::DataFlowGraphicsScene; +using QtNodes::DataFlowGraphModel; +using QtNodes::GraphicsView; +using QtNodes::NodeDelegateModelRegistry; + +static std::shared_ptr registerDataModels() +{ + auto ret = std::make_shared(); + + ret->registerModel("Node"); + ret->registerModel("Node"); + ret->registerModel("Node"); + ret->registerModel("Node"); + ret->registerModel("Node"); + ret->registerModel("Node"); + ret->registerModel("Node"); + ret->registerModel("Node"); + ret->registerModel("Node"); + ret->registerModel("Node"); + + return ret; +} + +static void setStyle() +{ + /* + ConnectionStyle::setConnectionStyle( + R"( + { + "ConnectionStyle": { + "ConstructionColor": "gray", + "NormalColor": "black", + "SelectedColor": "gray", + "SelectedHaloColor": "deepskyblue", + "HoveredColor": "deepskyblue", + + "LineWidth": 3.0, + "ConstructionLineWidth": 2.0, + "PointDiameter": 10.0, + + "UseDataDefinedColors": true + } + } + )");*/ +} + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + setStyle(); + + std::shared_ptr registry = registerDataModels(); + + QWidget mainWidget; + + auto menuBar = new QMenuBar(); + QMenu *menu = menuBar->addMenu("File"); + auto saveAction = menu->addAction("Save Scene"); + auto loadAction = menu->addAction("Load Scene"); + + QVBoxLayout *l = new QVBoxLayout(&mainWidget); + + DataFlowGraphModel dataFlowGraphModel(registry); + + l->addWidget(menuBar); + auto scene = new DataFlowGraphicsScene(dataFlowGraphModel, &mainWidget); + + auto view = new GraphicsView(scene); + l->addWidget(view); + l->setContentsMargins(0, 0, 0, 0); + l->setSpacing(0); + + QObject::connect(saveAction, &QAction::triggered, scene, &DataFlowGraphicsScene::save); + + QObject::connect(loadAction, &QAction::triggered, scene, &DataFlowGraphicsScene::load); + + QObject::connect(scene, &DataFlowGraphicsScene::sceneLoaded, view, &GraphicsView::centerScene); + + mainWidget.setWindowTitle("Data Flow: simplest calculator"); + mainWidget.resize(800, 600); + // Center window. + mainWidget.move(QApplication::primaryScreen()->availableGeometry().center() + - mainWidget.rect().center()); + mainWidget.showNormal(); + + return app.exec(); +} diff --git a/examples/compute_viewer/render.png b/examples/compute_viewer/render.png new file mode 100644 index 000000000..d8c6578aa Binary files /dev/null and b/examples/compute_viewer/render.png differ diff --git a/examples/connection_colors/CMakeLists.txt b/examples/connection_colors/CMakeLists.txt index 7a6cff9d6..c1abf66e7 100644 --- a/examples/connection_colors/CMakeLists.txt +++ b/examples/connection_colors/CMakeLists.txt @@ -1,6 +1,14 @@ file(GLOB_RECURSE CPPS ./*.cpp ) file(GLOB_RECURSE HPPS ./*.hpp ) -add_executable(connection_colors ${CPPS} ${HPPS}) +add_executable(connection_colors WIN32 ${CPPS} ${HPPS}) target_link_libraries(connection_colors QtNodes) + +if(WIN32 AND BUILD_SHARED_LIBS) + add_custom_command( + TARGET connection_colors + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E env VCINSTALLDIR=${CMAKE_GENERATOR_INSTANCE}/VC + ${WINDEPLOYQT_EXECUTABLE} --pdb "$") +endif() diff --git a/examples/connection_colors/main.cpp b/examples/connection_colors/main.cpp index 2438ba733..1610f176b 100644 --- a/examples/connection_colors/main.cpp +++ b/examples/connection_colors/main.cpp @@ -1,13 +1,9 @@ -#include - +#include "models.hpp" +#include +#include #include -#include #include #include -#include -#include - -#include "models.hpp" using QtNodes::ConnectionStyle; using QtNodes::DataFlowGraphicsScene; diff --git a/examples/connection_colors/models.hpp b/examples/connection_colors/models.hpp index ffc10afe0..5d348e8d4 100644 --- a/examples/connection_colors/models.hpp +++ b/examples/connection_colors/models.hpp @@ -1,11 +1,10 @@ #pragma once -#include - -#include -#include - #include +#include +#include +#include +#include using QtNodes::NodeData; using QtNodes::NodeDataType; diff --git a/examples/connection_colors/render.png b/examples/connection_colors/render.png new file mode 100644 index 000000000..123215d0a Binary files /dev/null and b/examples/connection_colors/render.png differ diff --git a/examples/dynamic_ports/CMakeLists.txt b/examples/dynamic_ports/CMakeLists.txt index 7a2ee8016..5e302bee7 100644 --- a/examples/dynamic_ports/CMakeLists.txt +++ b/examples/dynamic_ports/CMakeLists.txt @@ -1,5 +1,19 @@ -file(GLOB_RECURSE CPPS ./*.cpp ) - -add_executable(dynamic_ports ${CPPS}) +add_executable( + dynamic_ports + WIN32 + "CMakeLists.txt" + "DynamicPortsModel.cpp" + "DynamicPortsModel.hpp" + "main.cpp" + "PortAddRemoveWidget.cpp" + "PortAddRemoveWidget.hpp") target_link_libraries(dynamic_ports QtNodes) + +if(WIN32 AND BUILD_SHARED_LIBS) + add_custom_command( + TARGET dynamic_ports + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E env VCINSTALLDIR=${CMAKE_GENERATOR_INSTANCE}/VC + ${WINDEPLOYQT_EXECUTABLE} --pdb "$") +endif() diff --git a/examples/dynamic_ports/DynamicPortsModel.cpp b/examples/dynamic_ports/DynamicPortsModel.cpp index 1d8d537e1..6b8e385da 100644 --- a/examples/dynamic_ports/DynamicPortsModel.cpp +++ b/examples/dynamic_ports/DynamicPortsModel.cpp @@ -1,12 +1,16 @@ #include "DynamicPortsModel.hpp" - #include "PortAddRemoveWidget.hpp" - -#include - -#include - +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include DynamicPortsModel::DynamicPortsModel() : _nextNodeId{0} @@ -186,12 +190,12 @@ bool DynamicPortsModel::setNodeData(NodeId nodeId, NodeRole role, QVariant value case NodeRole::InPortCount: _nodePortCounts[nodeId].in = value.toUInt(); - widget(nodeId)->populateButtons(PortType::In, value.toUInt()); + widget(nodeId)->populateButtons(PortType::In, value.toInt()); break; case NodeRole::OutPortCount: _nodePortCounts[nodeId].out = value.toUInt(); - widget(nodeId)->populateButtons(PortType::Out, value.toUInt()); + widget(nodeId)->populateButtons(PortType::Out, value.toInt()); break; case NodeRole::Widget: diff --git a/examples/dynamic_ports/DynamicPortsModel.hpp b/examples/dynamic_ports/DynamicPortsModel.hpp index af8ba6893..6f1e1ca1e 100644 --- a/examples/dynamic_ports/DynamicPortsModel.hpp +++ b/examples/dynamic_ports/DynamicPortsModel.hpp @@ -1,10 +1,15 @@ #pragma once -#include -#include -#include - +#include +#include +#include +#include +#include +#include +#include +#include #include +#include // IWYU pragma: keep #include using ConnectionId = QtNodes::ConnectionId; diff --git a/examples/dynamic_ports/PortAddRemoveWidget.cpp b/examples/dynamic_ports/PortAddRemoveWidget.cpp index 7af6397ba..6d04461e2 100644 --- a/examples/dynamic_ports/PortAddRemoveWidget.cpp +++ b/examples/dynamic_ports/PortAddRemoveWidget.cpp @@ -1,6 +1,14 @@ #include "PortAddRemoveWidget.hpp" - #include "DynamicPortsModel.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include PortAddRemoveWidget::PortAddRemoveWidget(unsigned int nInPorts, unsigned int nOutPorts, @@ -37,7 +45,7 @@ PortAddRemoveWidget::~PortAddRemoveWidget() // } -void PortAddRemoveWidget::populateButtons(PortType portType, unsigned int nPorts) +void PortAddRemoveWidget::populateButtons(PortType portType, int nPorts) { QVBoxLayout *vl = (portType == PortType::In) ? _left : _right; @@ -62,12 +70,16 @@ QHBoxLayout *PortAddRemoveWidget::addButtonGroupToLayout(QVBoxLayout *vbl, unsig l->setContentsMargins(0, 0, 0, 0); auto button = new QPushButton("+"); - button->setFixedHeight(25); + + // See DefaultHorizontalNodeGeometry. + unsigned int const step = QFontMetrics(QFont()).height() + 10; + + button->setFixedHeight(step); l->addWidget(button); connect(button, &QPushButton::clicked, this, &PortAddRemoveWidget::onPlusClicked); button = new QPushButton("-"); - button->setFixedHeight(25); + button->setFixedHeight(step); l->addWidget(button); connect(button, &QPushButton::clicked, this, &PortAddRemoveWidget::onMinusClicked); diff --git a/examples/dynamic_ports/PortAddRemoveWidget.hpp b/examples/dynamic_ports/PortAddRemoveWidget.hpp index 20dffdef3..8d3e12c6d 100644 --- a/examples/dynamic_ports/PortAddRemoveWidget.hpp +++ b/examples/dynamic_ports/PortAddRemoveWidget.hpp @@ -1,12 +1,11 @@ #pragma once -#include -#include - -#include - +#include #include +#include #include +#include +#include using QtNodes::NodeId; using QtNodes::PortIndex; @@ -51,10 +50,9 @@ class PortAddRemoveWidget : public QWidget ~PortAddRemoveWidget(); /** - * Called from constructor, creates all button groups according to models'port - * counts. + * Creates all button groups according to models'port counts. */ - void populateButtons(PortType portType, unsigned int nPorts); + void populateButtons(PortType portType, int nPorts); /** * Adds a single `[+][-]` button group to a given layout. diff --git a/examples/dynamic_ports/main.cpp b/examples/dynamic_ports/main.cpp index 4ef2edaf8..bb7d248ab 100644 --- a/examples/dynamic_ports/main.cpp +++ b/examples/dynamic_ports/main.cpp @@ -1,16 +1,33 @@ -#include -#include -#include -#include - +#include "DynamicPortsModel.hpp" #include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include -#include - -#include "DynamicPortsModel.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using QtNodes::BasicGraphicsScene; using QtNodes::ConnectionStyle; diff --git a/examples/dynamic_ports/render.png b/examples/dynamic_ports/render.png new file mode 100644 index 000000000..e07c1d944 Binary files /dev/null and b/examples/dynamic_ports/render.png differ diff --git a/examples/lock_nodes_and_connections/CMakeLists.txt b/examples/lock_nodes_and_connections/CMakeLists.txt index 04b7ad8e9..cb283485e 100644 --- a/examples/lock_nodes_and_connections/CMakeLists.txt +++ b/examples/lock_nodes_and_connections/CMakeLists.txt @@ -1,5 +1,15 @@ file(GLOB_RECURSE CPPS ./*.cpp ) -add_executable(lock_nodes_and_connections ${CPPS}) +add_executable(lock_nodes_and_connections WIN32 ${CPPS}) target_link_libraries(lock_nodes_and_connections QtNodes) + +if(WIN32 AND BUILD_SHARED_LIBS) + add_custom_command( + TARGET lock_nodes_and_connections + POST_BUILD + COMMAND + ${CMAKE_COMMAND} -E env VCINSTALLDIR=${CMAKE_GENERATOR_INSTANCE}/VC + ${WINDEPLOYQT_EXECUTABLE} --pdb + "$") +endif() diff --git a/examples/lock_nodes_and_connections/DelegateNodeModel.hpp b/examples/lock_nodes_and_connections/DelegateNodeModel.hpp index 6b7c13292..b42393421 100644 --- a/examples/lock_nodes_and_connections/DelegateNodeModel.hpp +++ b/examples/lock_nodes_and_connections/DelegateNodeModel.hpp @@ -1,11 +1,10 @@ #pragma once -#include - -#include -#include - #include +#include +#include +#include +#include using QtNodes::NodeData; using QtNodes::NodeDataType; diff --git a/examples/lock_nodes_and_connections/main.cpp b/examples/lock_nodes_and_connections/main.cpp index d0edec3a0..d7c6e4c25 100644 --- a/examples/lock_nodes_and_connections/main.cpp +++ b/examples/lock_nodes_and_connections/main.cpp @@ -1,16 +1,20 @@ -#include -#include -#include - -#include -#include -#include -#include -#include -#include - #include "DataFlowModel.hpp" #include "DelegateNodeModel.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using QtNodes::DataFlowGraphicsScene; using QtNodes::GraphicsView; diff --git a/examples/resizable_images/CMakeLists.txt b/examples/resizable_images/CMakeLists.txt index 1f810fcf9..76dcd8c52 100644 --- a/examples/resizable_images/CMakeLists.txt +++ b/examples/resizable_images/CMakeLists.txt @@ -1,6 +1,14 @@ file(GLOB_RECURSE CPPS ./*.cpp ) file(GLOB_RECURSE HPPS ./*.hpp ) -add_executable(resizable_images ${CPPS} ${HPPS}) +add_executable(resizable_images WIN32 ${CPPS} ${HPPS}) target_link_libraries(resizable_images QtNodes) + +if(WIN32 AND BUILD_SHARED_LIBS) + add_custom_command( + TARGET resizable_images + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E env VCINSTALLDIR=${CMAKE_GENERATOR_INSTANCE}/VC + ${WINDEPLOYQT_EXECUTABLE} --pdb "$") +endif() diff --git a/examples/resizable_images/ImageLoaderModel.cpp b/examples/resizable_images/ImageLoaderModel.cpp index 8cb600a99..0f8a8c380 100644 --- a/examples/resizable_images/ImageLoaderModel.cpp +++ b/examples/resizable_images/ImageLoaderModel.cpp @@ -1,9 +1,9 @@ #include "ImageLoaderModel.hpp" - -#include -#include - -#include +#include +#include +#include +#include +#include ImageLoaderModel::ImageLoaderModel() : _label(new QLabel("Double click to load image")) diff --git a/examples/resizable_images/ImageLoaderModel.hpp b/examples/resizable_images/ImageLoaderModel.hpp index 394cf28a9..3a65ba7c8 100644 --- a/examples/resizable_images/ImageLoaderModel.hpp +++ b/examples/resizable_images/ImageLoaderModel.hpp @@ -1,14 +1,14 @@ #pragma once -#include - -#include -#include - -#include -#include - #include "PixmapData.hpp" +#include +#include +#include +#include +#include +#include +#include +#include using QtNodes::NodeData; using QtNodes::NodeDataType; diff --git a/examples/resizable_images/ImageShowModel.cpp b/examples/resizable_images/ImageShowModel.cpp index 1d62f9f3f..41c6715f5 100644 --- a/examples/resizable_images/ImageShowModel.cpp +++ b/examples/resizable_images/ImageShowModel.cpp @@ -1,13 +1,10 @@ #include "ImageShowModel.hpp" - #include "PixmapData.hpp" - +#include +#include +#include #include -#include -#include -#include - ImageShowModel::ImageShowModel() : _label(new QLabel("Image will appear here")) { diff --git a/examples/resizable_images/ImageShowModel.hpp b/examples/resizable_images/ImageShowModel.hpp index 7e4c8a06c..0c4b90411 100644 --- a/examples/resizable_images/ImageShowModel.hpp +++ b/examples/resizable_images/ImageShowModel.hpp @@ -1,12 +1,12 @@ #pragma once -#include - -#include -#include - +#include +#include +#include +#include +#include +#include #include -#include using QtNodes::NodeData; using QtNodes::NodeDataType; diff --git a/examples/resizable_images/PixmapData.hpp b/examples/resizable_images/PixmapData.hpp index a907857a8..76fad5c69 100644 --- a/examples/resizable_images/PixmapData.hpp +++ b/examples/resizable_images/PixmapData.hpp @@ -1,7 +1,6 @@ #pragma once #include - #include using QtNodes::NodeData; diff --git a/examples/resizable_images/main.cpp b/examples/resizable_images/main.cpp index 2e0e91e5f..396ebb8d7 100644 --- a/examples/resizable_images/main.cpp +++ b/examples/resizable_images/main.cpp @@ -1,14 +1,13 @@ -#include -#include -#include -#include -#include - -#include -#include - #include "ImageLoaderModel.hpp" #include "ImageShowModel.hpp" +#include +#include +#include +#include +#include +#include +#include +#include using QtNodes::ConnectionStyle; using QtNodes::DataFlowGraphicsScene; diff --git a/examples/simple_graph_model/CMakeLists.txt b/examples/simple_graph_model/CMakeLists.txt index aaebe4f24..1184b3e20 100644 --- a/examples/simple_graph_model/CMakeLists.txt +++ b/examples/simple_graph_model/CMakeLists.txt @@ -1,6 +1,14 @@ file(GLOB_RECURSE CPPS ./*.cpp ) file(GLOB_RECURSE HPPS ./*.hpp ) -add_executable(simple_graph_model ${CPPS} ${HPPS}) +add_executable(simple_graph_model WIN32 ${CPPS} ${HPPS}) target_link_libraries(simple_graph_model QtNodes) + +if(WIN32 AND BUILD_SHARED_LIBS) + add_custom_command( + TARGET simple_graph_model + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E env VCINSTALLDIR=${CMAKE_GENERATOR_INSTANCE}/VC + ${WINDEPLOYQT_EXECUTABLE} --pdb "$") +endif() diff --git a/examples/simple_graph_model/SimpleGraphModel.cpp b/examples/simple_graph_model/SimpleGraphModel.cpp index 7c04440f0..7b05c4d29 100644 --- a/examples/simple_graph_model/SimpleGraphModel.cpp +++ b/examples/simple_graph_model/SimpleGraphModel.cpp @@ -1,4 +1,14 @@ #include "SimpleGraphModel.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include SimpleGraphModel::SimpleGraphModel() : _nextNodeId{0} diff --git a/examples/simple_graph_model/SimpleGraphModel.hpp b/examples/simple_graph_model/SimpleGraphModel.hpp index e3d07213c..c27c885fb 100644 --- a/examples/simple_graph_model/SimpleGraphModel.hpp +++ b/examples/simple_graph_model/SimpleGraphModel.hpp @@ -1,11 +1,14 @@ #pragma once -#include -#include -#include - +#include +#include +#include +#include +#include +#include +#include +#include #include -#include #include using ConnectionId = QtNodes::ConnectionId; diff --git a/examples/simple_graph_model/main.cpp b/examples/simple_graph_model/main.cpp index a6356ba33..89df4c1f3 100644 --- a/examples/simple_graph_model/main.cpp +++ b/examples/simple_graph_model/main.cpp @@ -1,14 +1,19 @@ +#include "SimpleGraphModel.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include #include #include -#include -#include -#include - -#include "SimpleGraphModel.hpp" - using QtNodes::BasicGraphicsScene; using QtNodes::ConnectionStyle; using QtNodes::GraphicsView; diff --git a/examples/simple_graph_model/render.png b/examples/simple_graph_model/render.png new file mode 100644 index 000000000..f9be7d92b Binary files /dev/null and b/examples/simple_graph_model/render.png differ diff --git a/examples/styles/CMakeLists.txt b/examples/styles/CMakeLists.txt index ebf3b6261..6cd612ea6 100644 --- a/examples/styles/CMakeLists.txt +++ b/examples/styles/CMakeLists.txt @@ -1,6 +1,14 @@ file(GLOB_RECURSE CPPS ./*.cpp ) file(GLOB_RECURSE HPPS ./*.hpp ) -add_executable(styles ${CPPS} ${HPPS}) +add_executable(styles WIN32 ${CPPS} ${HPPS}) target_link_libraries(styles QtNodes) + +if(WIN32 AND BUILD_SHARED_LIBS) + add_custom_command( + TARGET styles + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E env VCINSTALLDIR=${CMAKE_GENERATOR_INSTANCE}/VC + ${WINDEPLOYQT_EXECUTABLE} --pdb "$") +endif() diff --git a/examples/styles/main.cpp b/examples/styles/main.cpp index 528780583..d17b19f94 100644 --- a/examples/styles/main.cpp +++ b/examples/styles/main.cpp @@ -1,15 +1,9 @@ #include "models.hpp" - -#include -#include +#include +#include #include #include -#include -#include -#include -#include - -#include +#include using QtNodes::ConnectionStyle; using QtNodes::DataFlowGraphicsScene; diff --git a/examples/styles/models.hpp b/examples/styles/models.hpp index 1352e4bfc..1f7b2d2a4 100644 --- a/examples/styles/models.hpp +++ b/examples/styles/models.hpp @@ -1,11 +1,12 @@ #pragma once -#include - -#include -#include - #include +#include +#include +#include +#include +#include +#include using QtNodes::NodeData; using QtNodes::NodeDataType; diff --git a/examples/styles/render.png b/examples/styles/render.png new file mode 100644 index 000000000..4e2ef97f9 Binary files /dev/null and b/examples/styles/render.png differ diff --git a/examples/text/CMakeLists.txt b/examples/text/CMakeLists.txt index 7da46dd74..7e98fec64 100644 --- a/examples/text/CMakeLists.txt +++ b/examples/text/CMakeLists.txt @@ -1,6 +1,14 @@ file(GLOB_RECURSE CPPS ./*.cpp ) file(GLOB_RECURSE HPPS ./*.hpp ) -add_executable(text ${CPPS} ${HPPS}) +add_executable(text WIN32 ${CPPS} ${HPPS}) target_link_libraries(text QtNodes) + +if(WIN32 AND BUILD_SHARED_LIBS) + add_custom_command( + TARGET text + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E env VCINSTALLDIR=${CMAKE_GENERATOR_INSTANCE}/VC + ${WINDEPLOYQT_EXECUTABLE} --pdb "$") +endif() diff --git a/examples/text/TextDisplayDataModel.cpp b/examples/text/TextDisplayDataModel.cpp index 1ae83202e..3be867e2c 100644 --- a/examples/text/TextDisplayDataModel.cpp +++ b/examples/text/TextDisplayDataModel.cpp @@ -1,4 +1,5 @@ #include "TextDisplayDataModel.hpp" +#include TextDisplayDataModel::TextDisplayDataModel() : _label(new QLabel("Resulting Text")) diff --git a/examples/text/TextDisplayDataModel.hpp b/examples/text/TextDisplayDataModel.hpp index 73c53e99c..5f00df9d0 100644 --- a/examples/text/TextDisplayDataModel.hpp +++ b/examples/text/TextDisplayDataModel.hpp @@ -1,15 +1,13 @@ #pragma once #include "TextData.hpp" - +#include +#include +#include +#include +#include #include -#include -#include - -#include -#include - using QtNodes::ConnectionPolicy; using QtNodes::NodeData; using QtNodes::NodeDelegateModel; diff --git a/examples/text/TextSourceDataModel.cpp b/examples/text/TextSourceDataModel.cpp index 244da4011..3e8f8d6a3 100644 --- a/examples/text/TextSourceDataModel.cpp +++ b/examples/text/TextSourceDataModel.cpp @@ -1,6 +1,7 @@ #include "TextSourceDataModel.hpp" - -#include +#include +#include +#include TextSourceDataModel::TextSourceDataModel() : _lineEdit{nullptr} diff --git a/examples/text/TextSourceDataModel.hpp b/examples/text/TextSourceDataModel.hpp index 8e5ca69a8..b05ca8367 100644 --- a/examples/text/TextSourceDataModel.hpp +++ b/examples/text/TextSourceDataModel.hpp @@ -1,13 +1,12 @@ #pragma once -#include - #include "TextData.hpp" - +#include +#include +#include +#include #include -#include - using QtNodes::NodeData; using QtNodes::NodeDelegateModel; using QtNodes::PortIndex; diff --git a/examples/text/main.cpp b/examples/text/main.cpp index 2d22792b8..aa919f3e5 100644 --- a/examples/text/main.cpp +++ b/examples/text/main.cpp @@ -1,13 +1,9 @@ -#include -#include -#include -#include -#include - -#include - #include "TextDisplayDataModel.hpp" #include "TextSourceDataModel.hpp" +#include +#include +#include +#include using QtNodes::DataFlowGraphicsScene; using QtNodes::DataFlowGraphModel; diff --git a/examples/text/render.png b/examples/text/render.png new file mode 100644 index 000000000..283ca1089 Binary files /dev/null and b/examples/text/render.png differ diff --git a/examples/vertical_layout/CMakeLists.txt b/examples/vertical_layout/CMakeLists.txt index 4fc8e3152..c09142a6e 100644 --- a/examples/vertical_layout/CMakeLists.txt +++ b/examples/vertical_layout/CMakeLists.txt @@ -1,5 +1,13 @@ file(GLOB_RECURSE CPPS ./*.cpp ) -add_executable(vertical_layout ${CPPS}) +add_executable(vertical_layout WIN32 ${CPPS}) target_link_libraries(vertical_layout QtNodes) + +if(WIN32 AND BUILD_SHARED_LIBS) + add_custom_command( + TARGET vertical_layout + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E env VCINSTALLDIR=${CMAKE_GENERATOR_INSTANCE}/VC + ${WINDEPLOYQT_EXECUTABLE} --pdb "$") +endif() diff --git a/examples/vertical_layout/SimpleGraphModel.cpp b/examples/vertical_layout/SimpleGraphModel.cpp index 5b5e3b8b1..ba37658b1 100644 --- a/examples/vertical_layout/SimpleGraphModel.cpp +++ b/examples/vertical_layout/SimpleGraphModel.cpp @@ -1,4 +1,13 @@ #include "SimpleGraphModel.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include SimpleGraphModel::SimpleGraphModel() : _nextNodeId{0} diff --git a/examples/vertical_layout/SimpleGraphModel.hpp b/examples/vertical_layout/SimpleGraphModel.hpp index f9d1fd4d4..6ab4608ce 100644 --- a/examples/vertical_layout/SimpleGraphModel.hpp +++ b/examples/vertical_layout/SimpleGraphModel.hpp @@ -1,11 +1,14 @@ #pragma once -#include -#include -#include - +#include +#include +#include +#include +#include +#include +#include +#include #include -#include #include using ConnectionId = QtNodes::ConnectionId; diff --git a/examples/vertical_layout/main.cpp b/examples/vertical_layout/main.cpp index e036c157a..29ac9bb65 100644 --- a/examples/vertical_layout/main.cpp +++ b/examples/vertical_layout/main.cpp @@ -1,13 +1,22 @@ +#include "SimpleGraphModel.hpp" #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include #include #include -#include -#include -#include -#include - -#include "SimpleGraphModel.hpp" using QtNodes::BasicGraphicsScene; using QtNodes::GraphicsView; diff --git a/include/QtNodes/ConnectionIdHash b/include/QtNodes/ConnectionIdHash new file mode 100644 index 000000000..587d4d99a --- /dev/null +++ b/include/QtNodes/ConnectionIdHash @@ -0,0 +1 @@ +#include "internal/ConnectionIdHash.hpp" diff --git a/include/QtNodes/internal/AbstractGraphModel.hpp b/include/QtNodes/internal/AbstractGraphModel.hpp index 96d2c64bd..6e1ab7d87 100644 --- a/include/QtNodes/internal/AbstractGraphModel.hpp +++ b/include/QtNodes/internal/AbstractGraphModel.hpp @@ -1,16 +1,15 @@ #pragma once +#include "ConnectionIdHash.hpp" // IWYU pragma: keep +#include "Definitions.hpp" #include "Export.hpp" - -#include #include - -#include -#include -#include - -#include "ConnectionIdHash.hpp" -#include "Definitions.hpp" +#include +#include +#include +#include +#include +#include namespace QtNodes { diff --git a/include/QtNodes/internal/AbstractNodeGeometry.hpp b/include/QtNodes/internal/AbstractNodeGeometry.hpp index b30c5a36c..f8265e461 100644 --- a/include/QtNodes/internal/AbstractNodeGeometry.hpp +++ b/include/QtNodes/internal/AbstractNodeGeometry.hpp @@ -2,7 +2,8 @@ #include "Definitions.hpp" #include "Export.hpp" - +#include +#include #include #include #include diff --git a/include/QtNodes/internal/AbstractNodePainter.hpp b/include/QtNodes/internal/AbstractNodePainter.hpp index cd4c7d63e..aa9d215d8 100644 --- a/include/QtNodes/internal/AbstractNodePainter.hpp +++ b/include/QtNodes/internal/AbstractNodePainter.hpp @@ -1,8 +1,7 @@ #pragma once -#include - #include "Export.hpp" +#include class QPainter; diff --git a/include/QtNodes/internal/BasicGraphicsScene.hpp b/include/QtNodes/internal/BasicGraphicsScene.hpp index 59544980d..e27c9cf0e 100644 --- a/include/QtNodes/internal/BasicGraphicsScene.hpp +++ b/include/QtNodes/internal/BasicGraphicsScene.hpp @@ -1,32 +1,27 @@ #pragma once -#include -#include -#include - -#include -#include -#include -#include - #include "AbstractGraphModel.hpp" #include "AbstractNodeGeometry.hpp" -#include "ConnectionIdHash.hpp" +#include "ConnectionGraphicsObject.hpp" +#include "ConnectionIdHash.hpp" // IWYU pragma: keep #include "Definitions.hpp" #include "Export.hpp" - -#include "QUuidStdHash.hpp" - -class QUndoStack; +#include "NodeGraphicsObject.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace QtNodes { class AbstractConnectionPainter; class AbstractGraphModel; class AbstractNodePainter; -class ConnectionGraphicsObject; -class NodeGraphicsObject; -class NodeStyle; /// 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 f0e569d74..4b2856b08 100644 --- a/include/QtNodes/internal/ConnectionGraphicsObject.hpp +++ b/include/QtNodes/internal/ConnectionGraphicsObject.hpp @@ -1,14 +1,17 @@ #pragma once -#include - -#include -#include - #include "ConnectionState.hpp" #include "Definitions.hpp" - -class QGraphicsSceneMouseEvent; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace QtNodes { diff --git a/include/QtNodes/internal/ConnectionIdHash.hpp b/include/QtNodes/internal/ConnectionIdHash.hpp index 09eaced6c..689d70803 100644 --- a/include/QtNodes/internal/ConnectionIdHash.hpp +++ b/include/QtNodes/internal/ConnectionIdHash.hpp @@ -1,8 +1,9 @@ #pragma once -#include - #include "Definitions.hpp" +#include +#include +#include inline void hash_combine(std::size_t &seed) { diff --git a/include/QtNodes/internal/ConnectionIdUtils.hpp b/include/QtNodes/internal/ConnectionIdUtils.hpp index 7f70a1b4b..b004df39e 100644 --- a/include/QtNodes/internal/ConnectionIdUtils.hpp +++ b/include/QtNodes/internal/ConnectionIdUtils.hpp @@ -1,11 +1,9 @@ #pragma once #include "Definitions.hpp" - -#include - #include #include +#include namespace QtNodes { diff --git a/include/QtNodes/internal/ConnectionState.hpp b/include/QtNodes/internal/ConnectionState.hpp index ddd31cdb6..8fe1b8bb6 100644 --- a/include/QtNodes/internal/ConnectionState.hpp +++ b/include/QtNodes/internal/ConnectionState.hpp @@ -1,12 +1,7 @@ #pragma once -#include - -#include "Export.hpp" - #include "Definitions.hpp" - -class QPointF; +#include "Export.hpp" namespace QtNodes { diff --git a/include/QtNodes/internal/ConnectionStyle.hpp b/include/QtNodes/internal/ConnectionStyle.hpp index b718bcfae..1331dd1b0 100644 --- a/include/QtNodes/internal/ConnectionStyle.hpp +++ b/include/QtNodes/internal/ConnectionStyle.hpp @@ -1,9 +1,10 @@ #pragma once -#include - #include "Export.hpp" #include "Style.hpp" +#include +#include +#include namespace QtNodes { diff --git a/include/QtNodes/internal/DataFlowGraphModel.hpp b/include/QtNodes/internal/DataFlowGraphModel.hpp index 268800202..996ec1044 100644 --- a/include/QtNodes/internal/DataFlowGraphModel.hpp +++ b/include/QtNodes/internal/DataFlowGraphModel.hpp @@ -1,20 +1,28 @@ #pragma once #include "AbstractGraphModel.hpp" -#include "ConnectionIdUtils.hpp" +#include "ConnectionIdHash.hpp" // IWYU pragma: keep +#include "Definitions.hpp" +#include "Export.hpp" +#include "NodeDelegateModel.hpp" #include "NodeDelegateModelRegistry.hpp" #include "Serializable.hpp" -#include "StyleCollection.hpp" - -#include "Export.hpp" - -#include - #include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace QtNodes { -class NODE_EDITOR_PUBLIC DataFlowGraphModel : public AbstractGraphModel, public Serializable +class NODE_EDITOR_PUBLIC DataFlowGraphModel + : public AbstractGraphModel + , public Serializable { Q_OBJECT diff --git a/include/QtNodes/internal/DataFlowGraphicsScene.hpp b/include/QtNodes/internal/DataFlowGraphicsScene.hpp index 8f7b193f8..76eb6e2a5 100644 --- a/include/QtNodes/internal/DataFlowGraphicsScene.hpp +++ b/include/QtNodes/internal/DataFlowGraphicsScene.hpp @@ -2,7 +2,12 @@ #include "BasicGraphicsScene.hpp" #include "DataFlowGraphModel.hpp" +#include "Definitions.hpp" #include "Export.hpp" +#include +#include +#include +#include namespace QtNodes { diff --git a/include/QtNodes/internal/DefaultHorizontalNodeGeometry.hpp b/include/QtNodes/internal/DefaultHorizontalNodeGeometry.hpp index f5f660784..2820e87ce 100644 --- a/include/QtNodes/internal/DefaultHorizontalNodeGeometry.hpp +++ b/include/QtNodes/internal/DefaultHorizontalNodeGeometry.hpp @@ -1,15 +1,17 @@ #pragma once #include "AbstractNodeGeometry.hpp" - -#include +#include "Definitions.hpp" +#include +#include +#include +#include +#include +#include namespace QtNodes { -class AbstractGraphModel; -class BasicGraphicsScene; - -class NODE_EDITOR_PUBLIC DefaultHorizontalNodeGeometry : public AbstractNodeGeometry +class DefaultHorizontalNodeGeometry : public AbstractNodeGeometry { public: DefaultHorizontalNodeGeometry(AbstractGraphModel &graphModel); @@ -45,14 +47,11 @@ class NODE_EDITOR_PUBLIC DefaultHorizontalNodeGeometry : public AbstractNodeGeom 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; + static constexpr unsigned int _portSpasing = 10; + + QFontMetrics _fontMetrics{QFont()}; + unsigned int _portSize; + QFontMetrics _boldFontMetrics{QFont()}; }; } // namespace QtNodes diff --git a/include/QtNodes/internal/DefaultNodePainter.hpp b/include/QtNodes/internal/DefaultNodePainter.hpp index 484969f9a..13ebb88f1 100644 --- a/include/QtNodes/internal/DefaultNodePainter.hpp +++ b/include/QtNodes/internal/DefaultNodePainter.hpp @@ -1,18 +1,11 @@ #pragma once -#include - #include "AbstractNodePainter.hpp" -#include "Definitions.hpp" +#include "Export.hpp" +#include namespace QtNodes { -class BasicGraphicsScene; -class GraphModel; -class NodeGeometry; -class NodeGraphicsObject; -class NodeState; - /// @ Lightweight class incapsulating paint code. class NODE_EDITOR_PUBLIC DefaultNodePainter : public AbstractNodePainter { diff --git a/include/QtNodes/internal/DefaultVerticalNodeGeometry.hpp b/include/QtNodes/internal/DefaultVerticalNodeGeometry.hpp index ae9b62876..4c73e69f4 100644 --- a/include/QtNodes/internal/DefaultVerticalNodeGeometry.hpp +++ b/include/QtNodes/internal/DefaultVerticalNodeGeometry.hpp @@ -1,14 +1,16 @@ #pragma once #include "AbstractNodeGeometry.hpp" - -#include +#include "Definitions.hpp" +#include "Export.hpp" +#include +#include +#include +#include +#include namespace QtNodes { -class AbstractGraphModel; -class BasicGraphicsScene; - class NODE_EDITOR_PUBLIC DefaultVerticalNodeGeometry : public AbstractNodeGeometry { public: diff --git a/include/QtNodes/internal/Definitions.hpp b/include/QtNodes/internal/Definitions.hpp index 863fa40b4..6cd1a21e6 100644 --- a/include/QtNodes/internal/Definitions.hpp +++ b/include/QtNodes/internal/Definitions.hpp @@ -1,10 +1,13 @@ #pragma once #include "Export.hpp" - -#include - #include +#include +#include +#include +#include + +#undef max /** * @file diff --git a/include/QtNodes/internal/GraphicsView.hpp b/include/QtNodes/internal/GraphicsView.hpp index 52068129f..01ef87dc5 100644 --- a/include/QtNodes/internal/GraphicsView.hpp +++ b/include/QtNodes/internal/GraphicsView.hpp @@ -1,8 +1,20 @@ #pragma once -#include - #include "Export.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace QtNodes { @@ -43,6 +55,8 @@ class NODE_EDITOR_PUBLIC GraphicsView : public QGraphicsView double getScale() const; + bool handleEvent(QEvent *e); + public Q_SLOTS: void scaleUp(); @@ -62,6 +76,8 @@ public Q_SLOTS: void scaleChanged(double scale); protected: + bool handleMouseEvent(QMouseEvent *event); + void contextMenuEvent(QContextMenuEvent *event) override; void wheelEvent(QWheelEvent *event) override; @@ -93,5 +109,7 @@ public Q_SLOTS: QPointF _clickPos; ScaleRange _scaleRange; + + QWidget *m_mouseDownWidget = nullptr; }; } // namespace QtNodes diff --git a/include/QtNodes/internal/GraphicsViewStyle.hpp b/include/QtNodes/internal/GraphicsViewStyle.hpp index 32f51b9e4..f32cd2de3 100644 --- a/include/QtNodes/internal/GraphicsViewStyle.hpp +++ b/include/QtNodes/internal/GraphicsViewStyle.hpp @@ -1,9 +1,10 @@ #pragma once -#include - #include "Export.hpp" #include "Style.hpp" +#include +#include +#include namespace QtNodes { diff --git a/include/QtNodes/internal/NodeConnectionInteraction.hpp b/include/QtNodes/internal/NodeConnectionInteraction.hpp index aaefedf6e..2b34b91a0 100644 --- a/include/QtNodes/internal/NodeConnectionInteraction.hpp +++ b/include/QtNodes/internal/NodeConnectionInteraction.hpp @@ -1,10 +1,7 @@ #pragma once -#include - -#include - #include "Definitions.hpp" +#include namespace QtNodes { diff --git a/include/QtNodes/internal/NodeData.hpp b/include/QtNodes/internal/NodeData.hpp index 1ef7480a1..b1120eb2d 100644 --- a/include/QtNodes/internal/NodeData.hpp +++ b/include/QtNodes/internal/NodeData.hpp @@ -1,12 +1,10 @@ #pragma once +#include "Export.hpp" #include - #include #include -#include "Export.hpp" - namespace QtNodes { /** diff --git a/include/QtNodes/internal/NodeDelegateModel.hpp b/include/QtNodes/internal/NodeDelegateModel.hpp index 6301164db..b3d7dcafb 100644 --- a/include/QtNodes/internal/NodeDelegateModel.hpp +++ b/include/QtNodes/internal/NodeDelegateModel.hpp @@ -1,26 +1,27 @@ #pragma once -#include - -#include - #include "Definitions.hpp" #include "Export.hpp" #include "NodeData.hpp" #include "NodeStyle.hpp" #include "Serializable.hpp" +#include +#include +#include +#include +#include namespace QtNodes { -class StyleCollection; - /** * The class wraps Node-specific data operations and propagates it to * the nesting DataFlowGraphModel which is a subclass of * AbstractGraphModel. * This class is the same what has been called NodeDataModel before v3. */ -class NODE_EDITOR_PUBLIC NodeDelegateModel : public QObject, public Serializable +class NODE_EDITOR_PUBLIC NodeDelegateModel + : public QObject + , public Serializable { Q_OBJECT @@ -67,7 +68,7 @@ class NODE_EDITOR_PUBLIC NodeDelegateModel : public QObject, public Serializable virtual std::shared_ptr outData(PortIndex const port) = 0; /** - * It is recommented to preform a lazy initialization for the + * It is recommended to perform a lazy initialization for the * embedded widget and create it inside this function, not in the * constructor of the current model. * @@ -111,7 +112,7 @@ public Q_SLOTS: */ void portsAboutToBeDeleted(PortType const portType, PortIndex const first, PortIndex const last); - /// Call this function when data and port moditications are finished. + /// Call this function when data and port modifications are finished. void portsDeleted(); /// Call this function before inserting the data associated with ports. @@ -123,7 +124,7 @@ public Q_SLOTS: PortIndex const first, PortIndex const last); - /// Call this function when data and port moditications are finished. + /// Call this function when data and port modifications are finished. void portsInserted(); private: diff --git a/include/QtNodes/internal/NodeDelegateModelRegistry.hpp b/include/QtNodes/internal/NodeDelegateModelRegistry.hpp index 4f230a4f4..6278916f8 100644 --- a/include/QtNodes/internal/NodeDelegateModelRegistry.hpp +++ b/include/QtNodes/internal/NodeDelegateModelRegistry.hpp @@ -1,19 +1,15 @@ #pragma once #include "Export.hpp" -#include "NodeData.hpp" #include "NodeDelegateModel.hpp" -#include "QStringStdHash.hpp" - -#include - #include #include #include #include #include #include -#include +#include +#include namespace QtNodes { diff --git a/include/QtNodes/internal/NodeGraphicsObject.hpp b/include/QtNodes/internal/NodeGraphicsObject.hpp index 50ce7be50..87704350d 100644 --- a/include/QtNodes/internal/NodeGraphicsObject.hpp +++ b/include/QtNodes/internal/NodeGraphicsObject.hpp @@ -1,11 +1,18 @@ #pragma once -#include -#include - +#include "Definitions.hpp" #include "NodeState.hpp" - -class QGraphicsProxyWidget; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace QtNodes { diff --git a/include/QtNodes/internal/NodeState.hpp b/include/QtNodes/internal/NodeState.hpp index 18940214c..ec04225ed 100644 --- a/include/QtNodes/internal/NodeState.hpp +++ b/include/QtNodes/internal/NodeState.hpp @@ -1,16 +1,7 @@ #pragma once -#include -#include - -#include -#include -#include - #include "Export.hpp" - -#include "Definitions.hpp" -#include "NodeData.hpp" +#include namespace QtNodes { diff --git a/include/QtNodes/internal/NodeStyle.hpp b/include/QtNodes/internal/NodeStyle.hpp index 5eca74924..f0da5ada4 100644 --- a/include/QtNodes/internal/NodeStyle.hpp +++ b/include/QtNodes/internal/NodeStyle.hpp @@ -1,9 +1,10 @@ #pragma once -#include - #include "Export.hpp" #include "Style.hpp" +#include +#include +#include namespace QtNodes { diff --git a/include/QtNodes/internal/QStringStdHash.hpp b/include/QtNodes/internal/QStringStdHash.hpp index 617d9b50d..68e977f84 100644 --- a/include/QtNodes/internal/QStringStdHash.hpp +++ b/include/QtNodes/internal/QStringStdHash.hpp @@ -7,7 +7,6 @@ // As of 5.14 there is a specialization std::hash #include - #include #include diff --git a/include/QtNodes/internal/QUuidStdHash.hpp b/include/QtNodes/internal/QUuidStdHash.hpp index 224bc9f49..c29575cea 100644 --- a/include/QtNodes/internal/QUuidStdHash.hpp +++ b/include/QtNodes/internal/QUuidStdHash.hpp @@ -1,7 +1,6 @@ #pragma once #include - #include #include diff --git a/include/QtNodes/internal/StyleCollection.hpp b/include/QtNodes/internal/StyleCollection.hpp index 92a1a408e..6fc724d1d 100644 --- a/include/QtNodes/internal/StyleCollection.hpp +++ b/include/QtNodes/internal/StyleCollection.hpp @@ -1,8 +1,7 @@ #pragma once -#include "Export.hpp" - #include "ConnectionStyle.hpp" +#include "Export.hpp" #include "GraphicsViewStyle.hpp" #include "NodeStyle.hpp" diff --git a/include/QtNodes/internal/UndoCommands.hpp b/include/QtNodes/internal/UndoCommands.hpp index 22026173f..0e40228fb 100644 --- a/include/QtNodes/internal/UndoCommands.hpp +++ b/include/QtNodes/internal/UndoCommands.hpp @@ -1,12 +1,11 @@ #pragma once #include "Definitions.hpp" - -#include -#include -#include - #include +#include +#include +#include +#include namespace QtNodes { diff --git a/include/QtNodes/internal/locateNode.hpp b/include/QtNodes/internal/locateNode.hpp index cf41f83f8..fcb7b1127 100644 --- a/include/QtNodes/internal/locateNode.hpp +++ b/include/QtNodes/internal/locateNode.hpp @@ -1,7 +1,7 @@ #pragma once -#include -#include +#include +#include class QGraphicsScene; diff --git a/src/AbstractGraphModel.cpp b/src/AbstractGraphModel.cpp index 10709b7e8..0928c6009 100644 --- a/src/AbstractGraphModel.cpp +++ b/src/AbstractGraphModel.cpp @@ -1,6 +1,7 @@ #include "AbstractGraphModel.hpp" - -#include +#include "ConnectionIdUtils.hpp" +#include +#include namespace QtNodes { @@ -31,7 +32,7 @@ void AbstractGraphModel::portsAboutToBeDeleted(NodeId const nodeId, } } - std::size_t const nRemovedPorts = clampedLast - first + 1; + PortIndex const nRemovedPorts = clampedLast - first + 1; for (PortIndex portIndex = clampedLast + 1; portIndex < portCount; ++portIndex) { std::unordered_set conns = connections(nodeId, portType, portIndex); @@ -75,7 +76,7 @@ void AbstractGraphModel::portsAboutToBeInserted(NodeId const nodeId, if (last < first) return; - std::size_t const nNewPorts = last - first + 1; + PortIndex const nNewPorts = last - first + 1; for (PortIndex portIndex = first; portIndex < portCount; ++portIndex) { std::unordered_set conns = connections(nodeId, portType, portIndex); diff --git a/src/AbstractNodeGeometry.cpp b/src/AbstractNodeGeometry.cpp index 034f4cf03..4b5591028 100644 --- a/src/AbstractNodeGeometry.cpp +++ b/src/AbstractNodeGeometry.cpp @@ -1,11 +1,12 @@ #include "AbstractNodeGeometry.hpp" - #include "AbstractGraphModel.hpp" +#include "NodeStyle.hpp" #include "StyleCollection.hpp" - -#include - #include +#include +#include +#include +#include namespace QtNodes { diff --git a/src/BasicGraphicsScene.cpp b/src/BasicGraphicsScene.cpp index 39f42d5f3..0df6dd314 100644 --- a/src/BasicGraphicsScene.cpp +++ b/src/BasicGraphicsScene.cpp @@ -1,34 +1,18 @@ #include "BasicGraphicsScene.hpp" - #include "AbstractNodeGeometry.hpp" +#include "AbstractNodePainter.hpp" #include "ConnectionGraphicsObject.hpp" +#include "ConnectionIdHash.hpp" #include "ConnectionIdUtils.hpp" #include "DefaultConnectionPainter.hpp" #include "DefaultHorizontalNodeGeometry.hpp" #include "DefaultNodePainter.hpp" #include "DefaultVerticalNodeGeometry.hpp" -#include "GraphicsView.hpp" #include "NodeGraphicsObject.hpp" - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include #include #include -#include +#include +#include namespace QtNodes { diff --git a/src/ConnectionGraphicsObject.cpp b/src/ConnectionGraphicsObject.cpp index 05ae46b34..20b17360e 100644 --- a/src/ConnectionGraphicsObject.cpp +++ b/src/ConnectionGraphicsObject.cpp @@ -11,16 +11,16 @@ #include "NodeGraphicsObject.hpp" #include "StyleCollection.hpp" #include "locateNode.hpp" - -#include -#include -#include -#include -#include - -#include - +#include #include +#include +#include +#include +#include +#include +#include +#include +#include namespace QtNodes { @@ -120,16 +120,7 @@ QRectF ConnectionGraphicsObject::boundingRect() const QPainterPath ConnectionGraphicsObject::shape() const { -#ifdef DEBUG_DRAWING - - //QPainterPath path; - - //path.addRect(boundingRect()); - //return path; - -#else return nodeScene()->connectionPainter().getPainterStroke(*this); -#endif } QPointF const &ConnectionGraphicsObject::endPoint(PortType portType) const @@ -317,64 +308,86 @@ void ConnectionGraphicsObject::addGraphicsEffect() std::pair ConnectionGraphicsObject::pointsC1C2Horizontal() const { - double const defaultOffset = 200; + double const overlapNodeY = 50; + + double const maxOffset = 200; double xDistance = _in.x() - _out.x(); - double horizontalOffset = qMin(defaultOffset, std::abs(xDistance)); + double horizontalOffset = qMin(maxOffset, std::abs(xDistance)); double verticalOffset = 0; + double vector = 0; double ratioX = 0.5; - if (xDistance <= 0) { - double yDistance = _in.y() - _out.y() + 20; + double yDistance = _in.y() - _out.y(); - double vector = yDistance < 0 ? -1.0 : 1.0; + if (xDistance <= 0) { + vector = yDistance < 0 ? -1.0 : 1.0; - verticalOffset = qMin(defaultOffset, std::abs(yDistance)) * vector; + verticalOffset = qMin(maxOffset, std::abs(yDistance)) * vector; ratioX = 1.0; } horizontalOffset *= ratioX; - QPointF c1(_out.x() + horizontalOffset, _out.y() + verticalOffset); + if (std::abs(yDistance) > overlapNodeY || _out.x() < _in.x()) { + QPointF c1(_out.x() + horizontalOffset, _out.y() + verticalOffset); - QPointF c2(_in.x() - horizontalOffset, _in.y() - verticalOffset); + QPointF c2(_in.x() - horizontalOffset, _in.y() - verticalOffset); + return std::make_pair(c1, c2); + } else { + QPointF c1(_out.x() + horizontalOffset, + _out.y() - qMax(100., std::abs(verticalOffset)) * vector); - return std::make_pair(c1, c2); + QPointF c2(_in.x() - horizontalOffset, + _in.y() - qMax(100., std::abs(verticalOffset)) * vector); + return std::make_pair(c1, c2); + } } std::pair ConnectionGraphicsObject::pointsC1C2Vertical() const { - double const defaultOffset = 200; + double const overlapNodeX = 50; + + double const maxOffset = 200; double yDistance = _in.y() - _out.y(); - double verticalOffset = qMin(defaultOffset, std::abs(yDistance)); + double verticalOffset = qMin(maxOffset, std::abs(yDistance)); double horizontalOffset = 0; + double vector = 0; double ratioY = 0.5; - if (yDistance <= 0) { - double xDistance = _in.x() - _out.x() + 20; + double xDistance = _in.x() - _out.x(); - double vector = xDistance < 0 ? -1.0 : 1.0; + if (yDistance <= 0) { + vector = xDistance < 0 ? -1.0 : 1.0; - horizontalOffset = qMin(defaultOffset, std::abs(xDistance)) * vector; + horizontalOffset = qMin(maxOffset, std::abs(xDistance)) * vector; ratioY = 1.0; } verticalOffset *= ratioY; - QPointF c1(_out.x() + horizontalOffset, _out.y() + verticalOffset); + if (std::abs(xDistance) > overlapNodeX || _out.y() < _in.y()) { + QPointF c1(_out.x() + horizontalOffset, _out.y() + verticalOffset); - QPointF c2(_in.x() - horizontalOffset, _in.y() - verticalOffset); + QPointF c2(_in.x() - horizontalOffset, _in.y() - verticalOffset); + return std::make_pair(c1, c2); + } else { + QPointF c1(_out.x() + qMax(100., std::abs(horizontalOffset)) * vector, + _out.y() + verticalOffset); - return std::make_pair(c1, c2); + QPointF c2(_in.x() + qMax(100., std::abs(horizontalOffset)) * vector, + _in.y() - verticalOffset); + return std::make_pair(c1, c2); + } } } // namespace QtNodes diff --git a/src/ConnectionState.cpp b/src/ConnectionState.cpp index 52ec9b59a..2e08af475 100644 --- a/src/ConnectionState.cpp +++ b/src/ConnectionState.cpp @@ -1,8 +1,4 @@ #include "ConnectionState.hpp" - -#include -#include - #include "BasicGraphicsScene.hpp" #include "ConnectionGraphicsObject.hpp" #include "NodeGraphicsObject.hpp" diff --git a/src/ConnectionStyle.cpp b/src/ConnectionStyle.cpp index 812658989..a050e9410 100644 --- a/src/ConnectionStyle.cpp +++ b/src/ConnectionStyle.cpp @@ -1,14 +1,13 @@ #include "ConnectionStyle.hpp" - #include "StyleCollection.hpp" - -#include -#include -#include - -#include - +#include #include +#include +#include +#include +#include +#include +#include using QtNodes::ConnectionStyle; diff --git a/src/DataFlowGraphModel.cpp b/src/DataFlowGraphModel.cpp index a5ba8734f..78cd82be9 100644 --- a/src/DataFlowGraphModel.cpp +++ b/src/DataFlowGraphModel.cpp @@ -1,9 +1,21 @@ #include "DataFlowGraphModel.hpp" #include "ConnectionIdHash.hpp" - -#include - +#include "ConnectionIdUtils.hpp" +#include "NodeData.hpp" +#include "NodeStyle.hpp" +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace QtNodes { @@ -211,7 +223,7 @@ QVariant DataFlowGraphModel::nodeData(NodeId nodeId, NodeRole role) const break; case NodeRole::Style: { - auto style = StyleCollection::nodeStyle(); + auto style = model->nodeStyle(); result = style.toJson().toVariantMap(); } break; @@ -360,6 +372,7 @@ bool DataFlowGraphModel::setPortData( // Triggers repainting on the scene. Q_EMIT inPortDataWasSet(nodeId, portType, portIndex); + return true; } break; @@ -473,6 +486,7 @@ void DataFlowGraphModel::loadNode(QJsonObject const &nodeJson) onOutPortDataUpdated(restoredNodeId, portIndex); }); + model->load(internalDataJson); _models[restoredNodeId] = std::move(model); Q_EMIT nodeCreated(restoredNodeId); @@ -481,8 +495,6 @@ void DataFlowGraphModel::loadNode(QJsonObject const &nodeJson) QPointF const pos(posJson["x"].toDouble(), posJson["y"].toDouble()); setNodeData(restoredNodeId, NodeRole::Position, pos); - - _models[restoredNodeId]->load(internalDataJson); } else { throw std::logic_error(std::string("No registered model with name ") + delegateModelName.toLocal8Bit().data()); diff --git a/src/DataFlowGraphicsScene.cpp b/src/DataFlowGraphicsScene.cpp index e300ba86e..21efe4ec3 100644 --- a/src/DataFlowGraphicsScene.cpp +++ b/src/DataFlowGraphicsScene.cpp @@ -1,30 +1,33 @@ #include "DataFlowGraphicsScene.hpp" - -#include "ConnectionGraphicsObject.hpp" -#include "GraphicsView.hpp" #include "NodeDelegateModelRegistry.hpp" #include "NodeGraphicsObject.hpp" #include "UndoCommands.hpp" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace QtNodes { @@ -147,7 +150,7 @@ QMenu *DataFlowGraphicsScene::createSceneMenu(QPointF const scenePos) bool DataFlowGraphicsScene::save() const { QString fileName = QFileDialog::getSaveFileName(nullptr, - tr("Open Flow Scene"), + tr("Save Flow Scene"), QDir::homePath(), tr("Flow Scene Files (*.flow)")); diff --git a/src/DefaultConnectionPainter.cpp b/src/DefaultConnectionPainter.cpp index 4a95bc909..d7aca7cda 100644 --- a/src/DefaultConnectionPainter.cpp +++ b/src/DefaultConnectionPainter.cpp @@ -5,9 +5,22 @@ #include "AbstractGraphModel.hpp" #include "ConnectionGraphicsObject.hpp" #include "ConnectionState.hpp" +#include "ConnectionStyle.hpp" #include "Definitions.hpp" #include "NodeData.hpp" #include "StyleCollection.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace QtNodes { @@ -26,7 +39,8 @@ QPainterPath DefaultConnectionPainter::cubicPath(ConnectionGraphicsObject const return cubic; } -void DefaultConnectionPainter::drawSketchLine(QPainter *painter, ConnectionGraphicsObject const &cgo) const +void DefaultConnectionPainter::drawSketchLine(QPainter *painter, + ConnectionGraphicsObject const &cgo) const { ConnectionState const &state = cgo.connectionState(); @@ -48,7 +62,8 @@ void DefaultConnectionPainter::drawSketchLine(QPainter *painter, ConnectionGraph } } -void DefaultConnectionPainter::drawHoveredOrSelected(QPainter *painter, ConnectionGraphicsObject const &cgo) const +void DefaultConnectionPainter::drawHoveredOrSelected(QPainter *painter, + ConnectionGraphicsObject const &cgo) const { bool const hovered = cgo.connectionState().hovered(); bool const selected = cgo.isSelected(); @@ -73,7 +88,8 @@ void DefaultConnectionPainter::drawHoveredOrSelected(QPainter *painter, Connecti } } -void DefaultConnectionPainter::drawNormalLine(QPainter *painter, ConnectionGraphicsObject const &cgo) const +void DefaultConnectionPainter::drawNormalLine(QPainter *painter, + ConnectionGraphicsObject const &cgo) const { ConnectionState const &state = cgo.connectionState(); @@ -199,7 +215,8 @@ void DefaultConnectionPainter::paint(QPainter *painter, ConnectionGraphicsObject painter->drawEllipse(cgo.in(), pointRadius, pointRadius); } -QPainterPath DefaultConnectionPainter::getPainterStroke(ConnectionGraphicsObject const &connection) const +QPainterPath DefaultConnectionPainter::getPainterStroke( + ConnectionGraphicsObject const &connection) const { auto cubic = cubicPath(connection); diff --git a/src/DefaultHorizontalNodeGeometry.cpp b/src/DefaultHorizontalNodeGeometry.cpp index 466c5ef34..7725782a3 100644 --- a/src/DefaultHorizontalNodeGeometry.cpp +++ b/src/DefaultHorizontalNodeGeometry.cpp @@ -1,26 +1,25 @@ #include "DefaultHorizontalNodeGeometry.hpp" - #include "AbstractGraphModel.hpp" #include "NodeData.hpp" - -#include +#include +#include +#include #include +#include +#include +#include #include +#include namespace QtNodes { DefaultHorizontalNodeGeometry::DefaultHorizontalNodeGeometry(AbstractGraphModel &graphModel) : AbstractNodeGeometry(graphModel) - , _portSize(20) - , _portSpasing(10) - , _fontMetrics(QFont()) - , _boldFontMetrics(QFont()) + , _portSize(_fontMetrics.height()) { QFont f; f.setBold(true); _boldFontMetrics = QFontMetrics(f); - - _portSize = _fontMetrics.height(); } QSize DefaultHorizontalNodeGeometry::size(NodeId const nodeId) const diff --git a/src/DefaultNodePainter.cpp b/src/DefaultNodePainter.cpp index 8febe4cb1..3afcb8d42 100644 --- a/src/DefaultNodePainter.cpp +++ b/src/DefaultNodePainter.cpp @@ -1,17 +1,36 @@ #include "DefaultNodePainter.hpp" - -#include - -#include - #include "AbstractGraphModel.hpp" #include "AbstractNodeGeometry.hpp" #include "BasicGraphicsScene.hpp" #include "ConnectionGraphicsObject.hpp" #include "ConnectionIdUtils.hpp" +#include "ConnectionState.hpp" +#include "ConnectionStyle.hpp" +#include "Definitions.hpp" +#include "NodeData.hpp" #include "NodeGraphicsObject.hpp" #include "NodeState.hpp" +#include "NodeStyle.hpp" #include "StyleCollection.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace QtNodes { diff --git a/src/DefaultVerticalNodeGeometry.cpp b/src/DefaultVerticalNodeGeometry.cpp index 0254028ed..35e53066d 100644 --- a/src/DefaultVerticalNodeGeometry.cpp +++ b/src/DefaultVerticalNodeGeometry.cpp @@ -1,11 +1,15 @@ #include "DefaultVerticalNodeGeometry.hpp" - #include "AbstractGraphModel.hpp" #include "NodeData.hpp" - -#include +#include +#include +#include #include +#include +#include +#include #include +#include namespace QtNodes { diff --git a/src/GraphicsView.cpp b/src/GraphicsView.cpp index 1ffa8f58b..79f84f3d4 100644 --- a/src/GraphicsView.cpp +++ b/src/GraphicsView.cpp @@ -1,27 +1,26 @@ #include "GraphicsView.hpp" - #include "BasicGraphicsScene.hpp" -#include "ConnectionGraphicsObject.hpp" -#include "NodeGraphicsObject.hpp" +#include "GraphicsViewStyle.hpp" #include "StyleCollection.hpp" #include "UndoCommands.hpp" - -#include - -#include -#include - -#include - -#include -#include -#include - -#include -#include - +#include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using QtNodes::BasicGraphicsScene; using QtNodes::GraphicsView; @@ -161,6 +160,49 @@ void GraphicsView::centerScene() } } +bool GraphicsView::handleMouseEvent(QMouseEvent *event) +{ + if (event->type() == QEvent::MouseButtonPress) { + mousePressEvent(event); + } else if (event->type() == QEvent::MouseMove) { + mouseMoveEvent(event); + } + + QPoint pos = event->pos(); + + QWidget *child = childAt(pos); + + if (event->type() == QEvent::MouseButtonPress) { + m_mouseDownWidget = child; + } else if (event->type() == QEvent::MouseButtonRelease) { + m_mouseDownWidget = nullptr; + } + + QWidget *receiver = m_mouseDownWidget ? m_mouseDownWidget : child; + + if (receiver != nullptr) { + QPoint newPt = receiver->mapFrom(this, pos); + + if (event->button() == Qt::MouseButton::RightButton) { + contextMenuEvent(new QContextMenuEvent(QContextMenuEvent::Mouse, + newPt, + event->globalPosition().toPoint())); + } + QMouseEvent *eventlocal = new QMouseEvent(event->type(), + newPt, + event->scenePosition(), + newPt, + event->button(), + event->buttons(), + event->modifiers(), + event->source(), + event->pointingDevice()); + return qApp->notify(receiver, eventlocal); + } + + return false; +} + void GraphicsView::contextMenuEvent(QContextMenuEvent *event) { if (itemAt(event->pos())) { @@ -216,6 +258,19 @@ void GraphicsView::setScaleRange(ScaleRange range) setScaleRange(range.minimum, range.maximum); } +bool GraphicsView::handleEvent(QEvent *e) +{ + if (QMouseEvent *me = dynamic_cast(e)) { + return handleMouseEvent(me); + } + if (QWheelEvent *we = dynamic_cast(e)) { + wheelEvent(we); + return true; + } + + return QWidget::event(e); +} + void GraphicsView::scaleUp() { double const step = 1.2; diff --git a/src/GraphicsViewStyle.cpp b/src/GraphicsViewStyle.cpp index ae02a2c39..ccf901672 100644 --- a/src/GraphicsViewStyle.cpp +++ b/src/GraphicsViewStyle.cpp @@ -1,11 +1,10 @@ #include "GraphicsViewStyle.hpp" - -#include -#include -#include -#include - #include "StyleCollection.hpp" +#include +#include +#include +#include +#include using QtNodes::GraphicsViewStyle; diff --git a/src/NodeConnectionInteraction.cpp b/src/NodeConnectionInteraction.cpp index 9af05fc4e..022a574fa 100644 --- a/src/NodeConnectionInteraction.cpp +++ b/src/NodeConnectionInteraction.cpp @@ -1,14 +1,14 @@ #include "NodeConnectionInteraction.hpp" - +#include "AbstractGraphModel.hpp" #include "AbstractNodeGeometry.hpp" #include "BasicGraphicsScene.hpp" #include "ConnectionGraphicsObject.hpp" #include "ConnectionIdUtils.hpp" +#include "ConnectionState.hpp" #include "NodeGraphicsObject.hpp" #include "UndoCommands.hpp" - -#include - +#include +#include #include namespace QtNodes { diff --git a/src/NodeDelegateModel.cpp b/src/NodeDelegateModel.cpp index 94e47ad68..34dd43c10 100644 --- a/src/NodeDelegateModel.cpp +++ b/src/NodeDelegateModel.cpp @@ -1,6 +1,6 @@ #include "NodeDelegateModel.hpp" - #include "StyleCollection.hpp" +#include namespace QtNodes { diff --git a/src/NodeDelegateModelRegistry.cpp b/src/NodeDelegateModelRegistry.cpp index 11a1f84aa..ec736d916 100644 --- a/src/NodeDelegateModelRegistry.cpp +++ b/src/NodeDelegateModelRegistry.cpp @@ -1,7 +1,5 @@ #include "NodeDelegateModelRegistry.hpp" - -#include -#include +#include "NodeData.hpp" using QtNodes::NodeDataType; using QtNodes::NodeDelegateModel; diff --git a/src/NodeGraphicsObject.cpp b/src/NodeGraphicsObject.cpp index f4e38c63d..5f67522b5 100644 --- a/src/NodeGraphicsObject.cpp +++ b/src/NodeGraphicsObject.cpp @@ -1,11 +1,4 @@ #include "NodeGraphicsObject.hpp" - -#include -#include - -#include -#include - #include "AbstractGraphModel.hpp" #include "AbstractNodeGeometry.hpp" #include "AbstractNodePainter.hpp" @@ -13,8 +6,26 @@ #include "ConnectionGraphicsObject.hpp" #include "ConnectionIdUtils.hpp" #include "NodeConnectionInteraction.hpp" -#include "StyleCollection.hpp" +#include "NodeStyle.hpp" #include "UndoCommands.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace QtNodes { diff --git a/src/NodeState.cpp b/src/NodeState.cpp index f6ed43e15..c270991fb 100644 --- a/src/NodeState.cpp +++ b/src/NodeState.cpp @@ -1,7 +1,7 @@ #include "NodeState.hpp" - #include "ConnectionGraphicsObject.hpp" #include "NodeGraphicsObject.hpp" +#include namespace QtNodes { diff --git a/src/NodeStyle.cpp b/src/NodeStyle.cpp index a82bf8fe2..b968dd7c8 100644 --- a/src/NodeStyle.cpp +++ b/src/NodeStyle.cpp @@ -1,14 +1,10 @@ #include "NodeStyle.hpp" - -#include - -#include -#include -#include - -#include - #include "StyleCollection.hpp" +#include +#include +#include +#include +#include using QtNodes::NodeStyle; diff --git a/src/UndoCommands.cpp b/src/UndoCommands.cpp index cdd08db83..5653e3883 100644 --- a/src/UndoCommands.cpp +++ b/src/UndoCommands.cpp @@ -1,19 +1,27 @@ #include "UndoCommands.hpp" - +#include "AbstractGraphModel.hpp" #include "BasicGraphicsScene.hpp" #include "ConnectionGraphicsObject.hpp" #include "ConnectionIdUtils.hpp" #include "Definitions.hpp" #include "NodeGraphicsObject.hpp" - -#include -#include -#include -#include -#include -#include - #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace QtNodes { diff --git a/src/locateNode.cpp b/src/locateNode.cpp index ddba09985..1e54a7e6e 100644 --- a/src/locateNode.cpp +++ b/src/locateNode.cpp @@ -1,11 +1,12 @@ #include "locateNode.hpp" - -#include - -#include -#include - #include "NodeGraphicsObject.hpp" +#include +#include +#include +#include +#include +#include +#include namespace QtNodes { diff --git a/test/include/ApplicationSetup.hpp b/test/include/ApplicationSetup.hpp index 8a5685dd1..27356f054 100644 --- a/test/include/ApplicationSetup.hpp +++ b/test/include/ApplicationSetup.hpp @@ -1,7 +1,6 @@ #pragma once #include - #include inline std::unique_ptr applicationSetup() diff --git a/test/include/Stringify.hpp b/test/include/Stringify.hpp index d88a5730b..924975ec9 100644 --- a/test/include/Stringify.hpp +++ b/test/include/Stringify.hpp @@ -1,10 +1,8 @@ #pragma once +#include #include #include - -#include - #include namespace Catch { diff --git a/test/include/StubNodeDataModel.hpp b/test/include/StubNodeDataModel.hpp index 9a71d94e7..e1c7a6076 100644 --- a/test/include/StubNodeDataModel.hpp +++ b/test/include/StubNodeDataModel.hpp @@ -1,7 +1,6 @@ #pragma once #include - #include class StubNodeDataModel : public QtNodes::NodeDataModel diff --git a/test/src/TestDataModelRegistry.cpp b/test/src/TestDataModelRegistry.cpp index e19fb38f9..911a44a5d 100644 --- a/test/src/TestDataModelRegistry.cpp +++ b/test/src/TestDataModelRegistry.cpp @@ -1,8 +1,6 @@ -#include - -#include - #include "StubNodeDataModel.hpp" +#include +#include using QtNodes::DataModelRegistry; using QtNodes::NodeData; diff --git a/test/src/TestDragging.cpp b/test/src/TestDragging.cpp index 210b8860c..6fab66448 100644 --- a/test/src/TestDragging.cpp +++ b/test/src/TestDragging.cpp @@ -1,14 +1,11 @@ #include "ApplicationSetup.hpp" #include "Stringify.hpp" #include "StubNodeDataModel.hpp" - +#include #include #include #include #include - -#include - #include #include diff --git a/test/src/TestFlowScene.cpp b/test/src/TestFlowScene.cpp index 25c5c4043..28ae15fc4 100644 --- a/test/src/TestFlowScene.cpp +++ b/test/src/TestFlowScene.cpp @@ -1,17 +1,14 @@ #include "ApplicationSetup.hpp" #include "Stringify.hpp" #include "StubNodeDataModel.hpp" - -#include -#include -#include - #include - #include #include #include #include +#include +#include +#include using QtNodes::Connection; using QtNodes::DataModelRegistry; diff --git a/test/src/TestNodeGraphicsObject.cpp b/test/src/TestNodeGraphicsObject.cpp index 386ba248d..99a2b2e49 100644 --- a/test/src/TestNodeGraphicsObject.cpp +++ b/test/src/TestNodeGraphicsObject.cpp @@ -1,13 +1,10 @@ #include "ApplicationSetup.hpp" #include "StubNodeDataModel.hpp" - +#include #include #include #include #include - -#include - #include using QtNodes::FlowScene;