添加项目文件。

This commit is contained in:
keyeslll
2023-02-28 14:50:28 +08:00
commit e20fa428dd
187 changed files with 18135 additions and 0 deletions

View File

@ -0,0 +1,53 @@
#pragma once
#if \
defined (__MINGW32__) || \
defined (__MINGW64__)
# define NODE_EDITOR_COMPILER "MinGW"
# define NODE_EDITOR_COMPILER_MINGW
#elif \
defined (__GNUC__)
# define NODE_EDITOR_COMPILER "GNU"
# define NODE_EDITOR_COMPILER_GNU
# define NODE_EDITOR_COMPILER_GNU_VERSION_MAJOR __GNUC__
# define NODE_EDITOR_COMPILER_GNU_VERSION_MINOR __GNUC_MINOR__
# define NODE_EDITOR_COMPILER_GNU_VERSION_PATCH __GNUC_PATCHLEVEL__
#elif \
defined (__clang__)
# define NODE_EDITOR_COMPILER "Clang"
# define NODE_EDITOR_COMPILER_CLANG
#elif \
defined (_MSC_VER)
# define NODE_EDITOR_COMPILER "Microsoft Visual C++"
# define NODE_EDITOR_COMPILER_MICROSOFT
#elif \
defined (__BORLANDC__)
# define NODE_EDITOR_COMPILER "Borland C++ Builder"
# define NODE_EDITOR_COMPILER_BORLAND
#elif \
defined (__CODEGEARC__)
# define NODE_EDITOR_COMPILER "CodeGear C++ Builder"
# define NODE_EDITOR_COMPILER_CODEGEAR
#elif \
defined (__INTEL_COMPILER) || \
defined (__ICL)
# define NODE_EDITOR_COMPILER "Intel C++"
# define NODE_EDITOR_COMPILER_INTEL
#elif \
defined (__xlC__) || \
defined (__IBMCPP__)
# define NODE_EDITOR_COMPILER "IBM XL C++"
# define NODE_EDITOR_COMPILER_IBM
#elif \
defined (__HP_aCC)
# define NODE_EDITOR_COMPILER "HP aC++"
# define NODE_EDITOR_COMPILER_HP
#elif \
defined (__WATCOMC__)
# define NODE_EDITOR_COMPILER "Watcom C++"
# define NODE_EDITOR_COMPILER_WATCOM
#endif
#ifndef NODE_EDITOR_COMPILER
# error "Current compiler is not supported."
#endif

View File

@ -0,0 +1,167 @@
#pragma once
#include <QtCore/QObject>
#include <QtCore/QUuid>
#include <QtCore/QVariant>
#include "PortType.hpp"
#include "NodeData.hpp"
#include "Serializable.hpp"
#include "ConnectionState.hpp"
#include "ConnectionGeometry.hpp"
#include "TypeConverter.hpp"
#include "QUuidStdHash.hpp"
#include "Export.hpp"
#include "memory.hpp"
class QPointF;
namespace QtNodes
{
class Node;
class NodeData;
class ConnectionGraphicsObject;
/**
* \brief 节点连接线
*/
class Connection
: public QObject
, public Serializable
{
Q_OBJECT
public:
/// 新的连接对象会连接到目标节点,连接的端口应当有 端口类型,端口序号
/// 连接对象的另一端应当是相反的端口。
Connection(PortType portType,
Node& node,
PortIndex portIndex);
Connection(Node& nodeIn,
PortIndex portIndexIn,
Node& nodeOut,
PortIndex portIndexOut,
TypeConverter converter =
TypeConverter{});
Connection(const Connection&) = delete;
Connection operator=(const Connection&) = delete;
~Connection();
public:
QJsonObject
save() const override;
public:
QUuid
id() const;
/// Remembers the end being dragged.
/// Invalidates Node address.
/// Grabs mouse.
void
setRequiredPort(PortType portType);
PortType
requiredPort() const;
void
setGraphicsObject(std::unique_ptr<ConnectionGraphicsObject>&& graphics);
/// Assigns a node to the required port.
/// It is assumed that there is a required port, no extra checks
void
setNodeToPort(Node& node,
PortType portType,
PortIndex portIndex);
void
removeFromNodes() const;
public:
ConnectionGraphicsObject&
getConnectionGraphicsObject() const;
ConnectionState const&
connectionState() const;
ConnectionState&
connectionState();
ConnectionGeometry&
connectionGeometry();
ConnectionGeometry const&
connectionGeometry() const;
Node*
getNode(PortType portType) const;
Node*&
getNode(PortType portType);
PortIndex
getPortIndex(PortType portType) const;
void
clearNode(PortType portType);
NodeDataType
dataType(PortType portType) const;
void
setTypeConverter(TypeConverter converter);
bool
complete() const;
public: // data propagation
void
propagateData(std::shared_ptr<NodeData> nodeData) const;
void
propagateEmptyData() const;
Q_SIGNALS:
void
connectionCompleted(Connection const&) const;
void
connectionMadeIncomplete(Connection const&) const;
private:
QUuid _uid;
private:
Node* _outNode = nullptr;
Node* _inNode = nullptr;
PortIndex _outPortIndex;
PortIndex _inPortIndex;
private:
ConnectionState _connectionState;
ConnectionGeometry _connectionGeometry;
std::unique_ptr<ConnectionGraphicsObject>_connectionGraphicsObject;
TypeConverter _converter;
Q_SIGNALS:
void
updated(Connection& conn) const;
};
}

View File

@ -0,0 +1,60 @@
#pragma once
#include "PortType.hpp"
#include <QtCore/QPointF>
#include <QtCore/QRectF>
#include <iostream>
namespace QtNodes
{
class ConnectionGeometry
{
public:
ConnectionGeometry();
public:
QPointF const&
getEndPoint(PortType portType) const;
void
setEndPoint(PortType portType, QPointF const& point);
void
moveEndPoint(PortType portType, QPointF const& offset);
QRectF
boundingRect() const;
std::pair<QPointF, QPointF>
pointsC1C2() const;
QPointF
source() const { return _out; }
QPointF
sink() const { return _in; }
double
lineWidth() const { return _lineWidth; }
bool
hovered() const { return _hovered; }
void
setHovered(bool hovered) { _hovered = hovered; }
private:
// local object coordinates
QPointF _in;
QPointF _out;
//int _animationPhase;
double _lineWidth;
bool _hovered;
};
}

View File

@ -0,0 +1,89 @@
#pragma once
#include <QtCore/QUuid>
#include <QtWidgets/QGraphicsObject>
class QGraphicsSceneMouseEvent;
namespace QtNodes
{
class FlowScene;
class Connection;
class ConnectionGeometry;
class Node;
/// Graphic Object for connection. Adds itself to scene
class ConnectionGraphicsObject
: public QGraphicsObject
{
Q_OBJECT
public:
ConnectionGraphicsObject(FlowScene& scene,
Connection& connection);
virtual
~ConnectionGraphicsObject();
enum { Type = UserType + 2 };
int
type() const override { return Type; }
public:
Connection&
connection();
QRectF
boundingRect() const override;
QPainterPath
shape() const override;
void
setGeometryChanged();
/// Updates the position of both ends
void
move();
void
lock(bool locked);
protected:
void
paint(QPainter* painter,
QStyleOptionGraphicsItem const* option,
QWidget* widget = 0) override;
void
mousePressEvent(QGraphicsSceneMouseEvent* event) override;
void
mouseMoveEvent(QGraphicsSceneMouseEvent* event) override;
void
mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override;
void
hoverEnterEvent(QGraphicsSceneHoverEvent* event) override;
void
hoverLeaveEvent(QGraphicsSceneHoverEvent* event) override;
private:
void
addGraphicsEffect();
private:
FlowScene& _scene;
Connection& _connection;
};
}

View File

@ -0,0 +1,71 @@
#pragma once
#include <QtCore/QUuid>
#include "PortType.hpp"
class QPointF;
namespace QtNodes
{
class Node;
/// Stores currently draggind end.
/// Remembers last hovered Node.
class ConnectionState
{
public:
ConnectionState(PortType port = PortType::None)
: _requiredPort(port)
{}
ConnectionState(const ConnectionState&) = delete;
ConnectionState operator=(const ConnectionState&) = delete;
~ConnectionState();
public:
void setRequiredPort(PortType end)
{
_requiredPort = end;
}
PortType requiredPort() const
{
return _requiredPort;
}
bool requiresPort() const
{
return _requiredPort != PortType::None;
}
void setNoRequiredPort()
{
_requiredPort = PortType::None;
}
public:
void interactWithNode(Node* node);
void setLastHoveredNode(Node* node);
Node*
lastHoveredNode() const
{
return _lastHoveredNode;
}
void resetLastHoveredNode();
private:
PortType _requiredPort;
Node* _lastHoveredNode{ nullptr };
};
}

View File

@ -0,0 +1,58 @@
#pragma once
#include <QtGui/QColor>
#include "Export.hpp"
#include "Style.hpp"
namespace QtNodes
{
class ConnectionStyle : public Style
{
public:
ConnectionStyle();
ConnectionStyle(QString jsonText);
public:
static void setConnectionStyle(QString fileName);
private:
void loadJsonFile(QString fileName) override;
void saveJsonFile(QString fileName) override;
public:
QColor constructionColor() const;
QColor normalColor() const;
QColor normalColor(QString typeId) const;
QColor selectedColor() const;
QColor selectedHaloColor() const;
QColor hoveredColor() const;
float lineWidth() const;
float constructionLineWidth() const;
float pointDiameter() const;
bool useDataDefinedColors() const;
public:
QColor ConstructionColor;
QColor NormalColor;
QColor SelectedColor;
QColor SelectedHaloColor;
QColor HoveredColor;
float LineWidth;
float ConstructionLineWidth;
float PointDiameter;
bool UseDataDefinedColors;
};
}

View File

@ -0,0 +1,166 @@
#pragma once
#include <functional>
#include <memory>
#include <set>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>
#include <QtCore/QString>
#include "NodeDataModel.hpp"
#include "TypeConverter.hpp"
#include "Export.hpp"
#include "QStringStdHash.hpp"
#include "memory.hpp"
namespace QtNodes
{
/// Class uses map for storing models (name, model)
class DataModelRegistry
{
public:
using RegistryItemPtr = std::unique_ptr<NodeDataModel>;
using RegistryItemCreator = std::function<RegistryItemPtr()>;
using RegisteredModelCreatorsMap = std::unordered_map<QString, RegistryItemCreator>;
using RegisteredModelsCategoryMap = std::unordered_map<QString, QString>;
using CategoriesSet = std::set<QString>;
using RegisteredTypeConvertersMap = std::unordered_map<
TypeConverterId, TypeConverter, TypeConverterIdHash>;
DataModelRegistry() = default;
~DataModelRegistry() = default;
DataModelRegistry(DataModelRegistry const&) = delete;
DataModelRegistry(DataModelRegistry&&) = default;
DataModelRegistry& operator=(DataModelRegistry const&) = delete;
DataModelRegistry& operator=(DataModelRegistry&&) = default;
public:
template<typename ModelType>
void registerModel(RegistryItemCreator creator,
QString const& category = u8"默认节点")
{
const QString name = computeName<ModelType>(HasStaticMethodName<ModelType>{}, creator);
if (!_registeredItemCreators.count(name))
{
_registeredItemCreators[name] = std::move(creator);
_categories.insert(category);
_registeredModelsCategory[name] = category;
}
}
template<typename ModelType>
void registerModel(QString const& category = u8"默认节点")
{
RegistryItemCreator creator = []() { return std::make_unique<ModelType>(); };
registerModel<ModelType>(std::move(creator), category);
}
template<typename ModelType>
void registerModel(QString const& category,
RegistryItemCreator creator)
{
registerModel<ModelType>(std::move(creator), category);
}
template <typename ModelCreator>
void registerModel(ModelCreator&& creator, QString const& category = u8"默认节点")
{
using ModelType = compute_model_type_t<decltype(creator())>;
registerModel<ModelType>(std::forward<ModelCreator>(creator), category);
}
template <typename ModelCreator>
void registerModel(QString const& category, ModelCreator&& creator)
{
registerModel(std::forward<ModelCreator>(creator), category);
}
void registerTypeConverter(TypeConverterId const& id,
TypeConverter typeConverter)
{
_registeredTypeConverters[id] = std::move(typeConverter);
}
std::unique_ptr<NodeDataModel>create(QString const& modelName);
RegisteredModelCreatorsMap const& registeredModelCreators() const;
RegisteredModelsCategoryMap const& registeredModelsCategoryAssociation() const;
CategoriesSet const& categories() const;
TypeConverter getTypeConverter(NodeDataType const& d1,
NodeDataType const& d2) const;
private:
RegisteredModelsCategoryMap _registeredModelsCategory;
CategoriesSet _categories;
RegisteredModelCreatorsMap _registeredItemCreators;
RegisteredTypeConvertersMap _registeredTypeConverters;
private:
template <typename T, typename = void>
struct HasStaticMethodName
: std::false_type
{};
template <typename T>
struct HasStaticMethodName<T,
typename std::enable_if<std::is_same<decltype(T::Name()), QString>::value>::type>
: std::true_type
{};
template <typename ModelType>
static QString
computeName(std::true_type, RegistryItemCreator const&)
{
return ModelType::Name();
}
template <typename ModelType>
static QString
computeName(std::false_type, RegistryItemCreator const& creator)
{
return creator()->name();
}
template <typename T>
struct UnwrapUniquePtr
{
// Assert always fires, but the compiler doesn't know this:
static_assert(!std::is_same<T, T>::value,
"The ModelCreator must return a std::unique_ptr<T>, where T "
"inherits from NodeDataModel");
};
template <typename T>
struct UnwrapUniquePtr<std::unique_ptr<T>>
{
static_assert(std::is_base_of<NodeDataModel, T>::value,
"The ModelCreator must return a std::unique_ptr<T>, where T "
"inherits from NodeDataModel");
using type = T;
};
template <typename CreatorResult>
using compute_model_type_t = typename UnwrapUniquePtr<CreatorResult>::type;
};
}

View File

@ -0,0 +1,51 @@
#pragma once
#include "Compiler.hpp"
#include "OperatingSystem.hpp"
#ifdef NODE_EDITOR_PLATFORM_WINDOWS
# define NODE_EDITOR_EXPORT __declspec(dllexport)
# define NODE_EDITOR_IMPORT __declspec(dllimport)
# define NODE_EDITOR_LOCAL
#elif \
NODE_EDITOR_COMPILER_GNU_VERSION_MAJOR >= 4 || \
defined (NODE_EDITOR_COMPILER_CLANG)
# define NODE_EDITOR_EXPORT __attribute__((visibility("default")))
# define NODE_EDITOR_IMPORT __attribute__((visibility("default")))
# define NODE_EDITOR_LOCAL __attribute__((visibility("hidden")))
#else
# define NODE_EDITOR_EXPORT
# define NODE_EDITOR_IMPORT
# define NODE_EDITOR_LOCAL
#endif
#ifdef __cplusplus
# define NODE_EDITOR_DEMANGLED extern "C"
#else
# define NODE_EDITOR_DEMANGLED
#endif
//#if defined (NODE_EDITOR_SHARED) && !defined (NODE_EDITOR_STATIC)
//# ifdef NODE_EDITOR_EXPORTS
//# define NODE_EDITOR_EXPORT
//# else
//# define NODE_EDITOR_IMPORT
//# endif
//# define NODE_EDITOR_PRIVATE NODE_EDITOR_LOCAL
//#elif !defined (NODE_EDITOR_SHARED) && defined (NODE_EDITOR_STATIC)
//# define
//# define NODE_EDITOR_PRIVATE
//#elif defined (NODE_EDITOR_SHARED) && defined (NODE_EDITOR_STATIC)
//# ifdef NODE_EDITOR_EXPORTS
//# error "Cannot build as shared and static simultaneously."
//# else
//# error "Cannot link against shared and static simultaneously."
//# endif
//#else
//# ifdef NODE_EDITOR_EXPORTS
//# error "Choose whether to build as shared or static."
//# else
//# error "Choose whether to link against shared or static."
//# endif
//#endif

View File

@ -0,0 +1,168 @@
#pragma once
#include <QtCore/QUuid>
#include <QtWidgets/QGraphicsScene>
#include <QThread>
#include <unordered_map>
#include <tuple>
#include <functional>
#include "QUuidStdHash.hpp"
#include "Export.hpp"
#include "DataModelRegistry.hpp"
#include "TypeConverter.hpp"
#include "memory.hpp"
namespace QtNodes
{
class NodeDataModel;
class FlowItemInterface;
class Node;
class NodeGraphicsObject;
class Connection;
class ConnectionGraphicsObject;
class NodeStyle;
/// Scene holds connections and nodes.
class FlowScene
: public QGraphicsScene
{
Q_OBJECT
public:
FlowScene(std::shared_ptr<DataModelRegistry> registry,
QObject* parent = Q_NULLPTR);
FlowScene(QObject* parent = Q_NULLPTR);
~FlowScene();
public:
std::shared_ptr<Connection>
createConnection(PortType connectedPort,
Node& node,
PortIndex portIndex);
std::shared_ptr<Connection>
createConnection(Node& nodeIn,
PortIndex portIndexIn,
Node& nodeOut,
PortIndex portIndexOut,
TypeConverter const& converter = TypeConverter{});
std::shared_ptr<Connection> restoreConnection(QJsonObject const& connectionJson);
void deleteConnection(Connection const& connection);
Node& createNode(std::unique_ptr<NodeDataModel>&& dataModel);
Node& restoreNode(QJsonObject const& nodeJson);
void removeNode(Node& node);
DataModelRegistry& registry() const;
void setRegistry(std::shared_ptr<DataModelRegistry> registry);
void iterateOverNodes(std::function<void(Node*)> const& visitor);
void iterateOverNodeData(std::function<void(NodeDataModel*)> const& visitor);
void iterateOverNodeDataDependentOrder(std::function<void(NodeDataModel*)> const& visitor);
QPointF getNodePosition(Node const& node) const;
void setNodePosition(Node& node, QPointF const& pos) const;
QSizeF getNodeSize(Node const& node) const;
public:
std::unordered_map<QUuid, std::unique_ptr<Node> > const& nodes() const;
std::unordered_map<QUuid, std::shared_ptr<Connection> > const& connections() const;
std::vector<Node*> allNodes() const;
std::vector<Node*> selectedNodes() const;
public:
void clearScene();
void save() const;
void load();
QByteArray saveToMemory() const;
void loadFromMemory(const QByteArray& data);
Q_SIGNALS:
/**
* @brief Node has been created but not on the scene yet.
* @see nodePlaced()
*/
void nodeCreated(Node& n);
/**
* @brief Node has been added to the scene.
* @details Connect to this signal if need a correct position of node.
* @see nodeCreated()
*/
void nodePlaced(Node& n);
void nodeDeleted(Node& n);
void connectionCreated(Connection const& c);
void connectionDeleted(Connection const& c);
void nodeMoved(Node& n, const QPointF& newLocation);
void nodeDoubleClicked(Node& n);
void nodeClicked(Node& n);
void connectionHovered(Connection& c, QPoint screenPos);
void nodeHovered(Node& n, QPoint screenPos);
void connectionHoverLeft(Connection& c);
void nodeHoverLeft(Node& n);
void nodeContextMenu(Node& n, const QPointF& pos);
private:
using SharedConnection = std::shared_ptr<Connection>;
using UniqueNode = std::unique_ptr<Node>;
// DO NOT reorder this member to go after the others.
// This should outlive all the connections and nodes of
// the graph, so that nodes can potentially have pointers into it,
// which is why it comes first in the class.
std::shared_ptr<DataModelRegistry> _registry;
std::unordered_map<QUuid, SharedConnection> _connections;
std::unordered_map<QUuid, UniqueNode> _nodes;
private Q_SLOTS:
void setupConnectionSignals(Connection const& c);
void sendConnectionCreatedToNodes(Connection const& c);
void sendConnectionDeletedToNodes(Connection const& c);
};
Node*
locateNodeAt(QPointF scenePoint, FlowScene& scene,
QTransform const& viewTransform);
}

View File

@ -0,0 +1,72 @@
#pragma once
#include <QtWidgets/QGraphicsView>
#include <QDebug>
#include "Export.hpp"
namespace QtNodes
{
class FlowScene;
class FlowView
: public QGraphicsView
{
Q_OBJECT
public:
FlowView(QWidget* parent = Q_NULLPTR);
FlowView(FlowScene* scene, QWidget* parent = Q_NULLPTR);
FlowView(const FlowView&) = delete;
FlowView operator=(const FlowView&) = delete;
QAction* clearSelectionAction() const;
QAction* deleteSelectionAction() const;
void setScene(FlowScene* scene);
public Q_SLOTS:
void scaleUp();
void scaleDown();
void deleteSelectedNodes();
protected:
void contextMenuEvent(QContextMenuEvent* event) override;
void wheelEvent(QWheelEvent* event) override;
void keyPressEvent(QKeyEvent* event) override;
void keyReleaseEvent(QKeyEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void drawBackground(QPainter* painter, const QRectF& r) override;
void showEvent(QShowEvent* event) override;
protected:
FlowScene* scene();
private:
QAction* _clearSelectionAction;
QAction* _deleteSelectionAction;
QPointF _clickPos;
FlowScene* _scene;
};
}

View File

@ -0,0 +1,35 @@
#pragma once
#include <QtGui/QColor>
#include "Export.hpp"
#include "Style.hpp"
namespace QtNodes
{
class FlowViewStyle : public Style
{
public:
FlowViewStyle();
FlowViewStyle(QString jsonText);
public:
static void setStyle(QString jsonText);
private:
void loadJsonFile(QString fileName) override;
void saveJsonFile(QString fileName) override;
public:
QColor BackgroundColor;
QColor FineGridColor;
QColor CoarseGridColor;
};
}

View File

@ -0,0 +1,133 @@
#pragma once
#include <QtCore/QObject>
#include <QtCore/QUuid>
#include <QtCore/QJsonObject>
#include "PortType.hpp"
#include "Export.hpp"
#include "NodeState.hpp"
#include "NodeGeometry.hpp"
#include "NodeData.hpp"
#include "NodeGraphicsObject.hpp"
#include "ConnectionGraphicsObject.hpp"
#include "Serializable.hpp"
#include "memory.hpp"
namespace QtNodes
{
class Connection;
class ConnectionState;
class NodeGraphicsObject;
class NodeDataModel;
class Node
: public QObject
, public Serializable
{
Q_OBJECT
public:
/// NodeDataModel should be an rvalue and is moved into the Node
Node(std::unique_ptr<NodeDataModel>&& dataModel);
virtual
~Node();
public:
/**
* \brief Json序列化
* \return json object
*/
QJsonObject
save() const override;
/**
* \brief Json反序列化
* \param json json
*/
void
restore(QJsonObject const& json) override;
public:
/**
* \brief 节点的QUuid
* \return uid
*/
QUuid
id() const;
void reactToPossibleConnection(PortType,
NodeDataType const&,
QPointF const& scenePoint);
void
resetReactionToConnection();
public:
NodeGraphicsObject const&
nodeGraphicsObject() const;
NodeGraphicsObject&
nodeGraphicsObject();
void
setGraphicsObject(std::unique_ptr<NodeGraphicsObject>&& graphics);
NodeGeometry&
nodeGeometry();
NodeGeometry const&
nodeGeometry() const;
NodeState const&
nodeState() const;
NodeState&
nodeState();
NodeDataModel*
nodeDataModel() const;
public Q_SLOTS: // data propagation
/// Propagates incoming data to the underlying model.
void
propagateData(std::shared_ptr<NodeData> nodeData,
PortIndex inPortIndex,
const QUuid& connectionId) const;
/// Fetches data from model's OUT #index port
/// and propagates it to the connection
void
onDataUpdated(PortIndex index);
/// Propagates empty data to the attached connection.
void
onDataInvalidated(PortIndex index);
/// update the graphic part if the size of the embeddedwidget changes
void
onNodeSizeUpdated();
private:
// addressing
QUuid _uid;
// data
std::unique_ptr<NodeDataModel> _nodeDataModel;
NodeState _nodeState;
// painting
NodeGeometry _nodeGeometry;
std::unique_ptr<NodeGraphicsObject> _nodeGraphicsObject;
};
}

View File

@ -0,0 +1,52 @@
#pragma once
#include <QtCore/QString>
#include "Export.hpp"
namespace QtNodes
{
struct NodeDataType
{
QString id;
/**
* \brief 用于比较的名称
*/
QString name;
friend bool operator<(QtNodes::NodeDataType const& d1,
QtNodes::NodeDataType const& d2)
{
return d1.id < d2.id;
}
friend bool operator==(const QtNodes::NodeDataType& d1,
const QtNodes::NodeDataType& d2) noexcept
{
return d1.id == d2.id;
}
};
/// Class represents data transferred between nodes.
/// @param type is used for comparing the types
/// The actual data is stored in subtypes
class NodeData
{
public:
virtual ~NodeData() = default;
virtual bool sameType(NodeData const& nodeData) const
{
return (this->type().id == nodeData.type().id);
}
/**
* \brief 节点标签
* \return 标签名字
*/
virtual NodeDataType type() const = 0;
};
}

View File

@ -0,0 +1,206 @@
#pragma once
#include <QtWidgets/QWidget>
#include <QDebug>
#include <QThread>
#include "PortType.hpp"
#include "NodeData.hpp"
#include "Serializable.hpp"
#include "NodeGeometry.hpp"
#include "NodeStyle.hpp"
#include "NodePainterDelegate.hpp"
#include "Export.hpp"
#include "memory.hpp"
namespace QtNodes
{
enum class NodeValidationState
{
Valid,
Warning,
Error
};
class Connection;
class StyleCollection;
class NodeDataModel
: public QObject,
//public QThread,
public Serializable
{
Q_OBJECT
public:
NodeDataModel();
virtual
~NodeDataModel() = default;
/// Caption is used in GUI
virtual QString
caption() const = 0;
/// It is possible to hide caption in GUI
virtual bool
captionVisible() const { return true; }
/// Port caption is used in GUI to label individual ports
virtual QString
portCaption(PortType, PortIndex) const { return QString(); }
/// It is possible to hide port caption in GUI
virtual bool
portCaptionVisible(PortType, PortIndex) const { return false; }
/// Name makes this model unique
virtual QString
name() const = 0;
public:
QJsonObject
save() const override;
public:
/**
* \brief 定义该节点有几个输入输出端口
* \param portType 查询的端口类型
* \return 返回查询类型的端口个数
*/
virtual
unsigned int nPorts(PortType portType) const = 0;
virtual
NodeDataType dataType(PortType portType, PortIndex portIndex) const = 0;
public:
enum class ConnectionPolicy
{
One,
Many,
};
virtual
ConnectionPolicy
portOutConnectionPolicy(PortIndex) const
{
return ConnectionPolicy::Many;
}
virtual
ConnectionPolicy
portInConnectionPolicy(PortIndex) const
{
return ConnectionPolicy::One;
}
NodeStyle const&
nodeStyle() const;
void
setNodeStyle(NodeStyle const& style);
public:
/// Triggers the algorithm
virtual
void
setInData(std::shared_ptr<NodeData> nodeData,
PortIndex port) = 0;
// Use this if portInConnectionPolicy returns ConnectionPolicy::Many
virtual
void
setInData(std::shared_ptr<NodeData> nodeData,
PortIndex port,
const QUuid& connectionId)
{
Q_UNUSED(connectionId);
setInData(nodeData, port);
}
virtual
std::shared_ptr<NodeData>
outData(PortIndex port) = 0;
/**
* It is recommented to preform a lazy initialization for the
* embedded widget and create it inside this function, not in the
* constructor of the current model.
*
* Our Model Registry is able to shortly instantiate models in order
* to call the non-static `Model::name()`. If the embedded widget is
* allocated in the constructor but not actually embedded into some
* QGraphicsProxyWidget, we'll gonna have a dangling pointer.
*/
virtual
QWidget*
embeddedWidget() = 0;
virtual
bool
resizable() const { return false; }
virtual
NodeValidationState
validationState() const { return NodeValidationState::Valid; }
virtual
QString
validationMessage() const { return QString(""); }
virtual
NodePainterDelegate* painterDelegate() const { return nullptr; }
public Q_SLOTS:
virtual void
inputConnectionCreated(Connection const&)
{
}
virtual void
inputConnectionDeleted(Connection const&)
{
//qDebug() << "inputConnectionDeleted";
//emit sigInputConnectionDeleted();
}
virtual void
outputConnectionCreated(Connection const&)
{
}
virtual void
outputConnectionDeleted(Connection const&)
{
}
Q_SIGNALS:
/// Triggers the updates in the nodes downstream.
void dataUpdated(PortIndex index);
/// Triggers the propagation of the empty data downstream.
void dataInvalidated(PortIndex index);
void computingStarted();
void computingFinished();
void embeddedWidgetSizeUpdated();
void sigInputConnectionDeleted();//输入连接移出信号
private:
NodeStyle _nodeStyle;
};
}

View File

@ -0,0 +1,166 @@
#pragma once
#include <QtCore/QRectF>
#include <QtCore/QPointF>
#include <QtGui/QTransform>
#include <QtGui/QFontMetrics>
#include "PortType.hpp"
#include "Export.hpp"
#include "memory.hpp"
namespace QtNodes
{
class NodeState;
class NodeDataModel;
class Node;
class NodeGeometry
{
public:
NodeGeometry(std::unique_ptr<NodeDataModel> const& dataModel);
public:
unsigned int
height() const { return _height; }
void
setHeight(unsigned int h) { _height = h; }
unsigned int
width() const { return _width; }
void
setWidth(unsigned int w) { _width = w; }
unsigned int
entryHeight() const { return _entryHeight; }
void
setEntryHeight(unsigned int h) { _entryHeight = h; }
unsigned int
entryWidth() const { return _entryWidth; }
void
setEntryWidth(unsigned int w) { _entryWidth = w; }
unsigned int
spacing() const { return _spacing; }
void
setSpacing(unsigned int s) { _spacing = s; }
bool
hovered() const { return _hovered; }
void
setHovered(unsigned int h) { _hovered = h; }
unsigned int
nSources() const;
unsigned int
nSinks() const;
QPointF const&
draggingPos() const
{
return _draggingPos;
}
void
setDraggingPosition(QPointF const& pos)
{
_draggingPos = pos;
}
public:
QRectF
entryBoundingRect() const;
QRectF
boundingRect() const;
/// Updates size unconditionally
void
recalculateSize() const;
/// Updates size if the QFontMetrics is changed
void
recalculateSize(QFont const& font) const;
// TODO removed default QTransform()
QPointF
portScenePosition(PortIndex index,
PortType portType,
QTransform const& t = QTransform()) const;
PortIndex
checkHitScenePoint(PortType portType,
QPointF point,
QTransform const& t = QTransform()) const;
QRect
resizeRect() const;
/// Returns the position of a widget on the Node surface
QPointF
widgetPosition() const;
/// Returns the maximum height a widget can be without causing the node to grow.
int
equivalentWidgetHeight() const;
unsigned int
validationHeight() const;
unsigned int
validationWidth() const;
static
QPointF
calculateNodePositionBetweenNodePorts(PortIndex targetPortIndex, PortType targetPort, Node* targetNode,
PortIndex sourcePortIndex, PortType sourcePort, Node* sourceNode,
Node& newNode);
private:
unsigned int
captionHeight() const;
unsigned int
captionWidth() const;
unsigned int
portWidth(PortType portType) const;
private:
// some variables are mutable because
// we need to change drawing metrics
// corresponding to fontMetrics
// but this doesn't change constness of Node
mutable unsigned int _width;
mutable unsigned int _height;
unsigned int _entryWidth;
mutable unsigned int _inputPortWidth;
mutable unsigned int _outputPortWidth;
mutable unsigned int _entryHeight;
unsigned int _spacing;
bool _hovered;
unsigned int _nSources;
unsigned int _nSinks;
QPointF _draggingPos;
std::unique_ptr<NodeDataModel> const& _dataModel;
mutable QFontMetrics _fontMetrics;
mutable QFontMetrics _boldFontMetrics;
};
}

View File

@ -0,0 +1,106 @@
#pragma once
#include <QtCore/QUuid>
#include <QtWidgets/QGraphicsObject>
#include "Connection.hpp"
#include "NodeGeometry.hpp"
#include "NodeState.hpp"
class QGraphicsProxyWidget;
namespace QtNodes
{
class FlowScene;
class FlowItemEntry;
/// Class reacts on GUI events, mouse clicks and
/// forwards painting operation.
class NodeGraphicsObject : public QGraphicsObject
{
Q_OBJECT
public:
NodeGraphicsObject(FlowScene& scene,
Node& node);
virtual
~NodeGraphicsObject();
Node&
node();
Node const&
node() const;
QRectF
boundingRect() const override;
void
setGeometryChanged();
/// Visits all attached connections and corrects
/// their corresponding end points.
void
moveConnections() const;
enum { Type = UserType + 1 };
int
type() const override { return Type; }
void
lock(bool locked);
protected:
void
paint(QPainter* painter,
QStyleOptionGraphicsItem const* option,
QWidget* widget = 0) override;
QVariant
itemChange(GraphicsItemChange change, const QVariant& value) override;
void
mousePressEvent(QGraphicsSceneMouseEvent* event) override;
void
mouseMoveEvent(QGraphicsSceneMouseEvent* event) override;
void
mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override;
void
hoverEnterEvent(QGraphicsSceneHoverEvent* event) override;
void
hoverLeaveEvent(QGraphicsSceneHoverEvent* event) override;
void
hoverMoveEvent(QGraphicsSceneHoverEvent*) override;
void
mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event) override;
void
contextMenuEvent(QGraphicsSceneContextMenuEvent* event) override;
private:
void
embedQWidget();
private:
FlowScene& _scene;
Node& _node;
bool _locked;
// either nullptr or owned by parent QGraphicsItem
QGraphicsProxyWidget* _proxyWidget;
};
}

View File

@ -0,0 +1,25 @@
#pragma once
#include <QPainter>
#include "NodeGeometry.hpp"
#include "NodeDataModel.hpp"
#include "Export.hpp"
namespace QtNodes {
/// Class to allow for custom painting
class NodePainterDelegate
{
public:
virtual
~NodePainterDelegate() = default;
virtual void
paint(QPainter* painter,
NodeGeometry const& geom,
NodeDataModel const* model) = 0;
};
}

View File

@ -0,0 +1,97 @@
#pragma once
#include <vector>
#include <unordered_map>
#include <QtCore/QUuid>
#include "Export.hpp"
#include "PortType.hpp"
#include "NodeData.hpp"
#include "memory.hpp"
namespace QtNodes
{
class Connection;
class NodeDataModel;
/// Contains vectors of connected input and output connections.
/// Stores bool for reacting on hovering connections
class NodeState
{
public:
enum ReactToConnectionState
{
REACTING,
NOT_REACTING
};
public:
NodeState(std::unique_ptr<NodeDataModel> const& model);
public:
using ConnectionPtrSet =
std::unordered_map<QUuid, Connection*>;
/// Returns vector of connections ID.
/// Some of them can be empty (null)
std::vector<ConnectionPtrSet> const&
getEntries(PortType) const;
std::vector<ConnectionPtrSet>&
getEntries(PortType);
ConnectionPtrSet
connections(PortType portType, PortIndex portIndex) const;
void
setConnection(PortType portType,
PortIndex portIndex,
Connection& connection);
void
eraseConnection(PortType portType,
PortIndex portIndex,
QUuid id);
ReactToConnectionState
reaction() const;
PortType
reactingPortType() const;
NodeDataType
reactingDataType() const;
void
setReaction(ReactToConnectionState reaction,
PortType reactingPortType = PortType::None,
NodeDataType reactingDataType =
NodeDataType());
bool
isReacting() const;
void
setResizing(bool resizing);
bool
resizing() const;
private:
std::vector<ConnectionPtrSet> _inConnections;
std::vector<ConnectionPtrSet> _outConnections;
ReactToConnectionState _reaction;
PortType _reactingPortType;
NodeDataType _reactingDataType;
bool _resizing;
};
}

View File

@ -0,0 +1,55 @@
#pragma once
#include <QtGui/QColor>
#include "Export.hpp"
#include "Style.hpp"
namespace QtNodes
{
class NodeStyle : public Style
{
public:
NodeStyle();
NodeStyle(QString jsonText);
public:
static void setNodeStyle(QString fileName);
private:
void loadJsonFile(QString fileName) override;
void saveJsonFile(QString fileName) override;
public:
QColor NormalBoundaryColor;
QColor SelectedBoundaryColor;
QColor BackgroundColor;
QColor TitleColor;
QColor GradientColor0;
QColor GradientColor1;
QColor GradientColor2;
QColor GradientColor3;
QColor ShadowColor;
QColor FontColor;
QColor FontColorFaded;
QColor ConnectionPointColor;
QColor FilledConnectionPointColor;
QColor WarningColor;
QColor ErrorColor;
float PenWidth;
float HoveredPenWidth;
float ConnectionPointDiameter;
float Opacity;
};
}

View File

@ -0,0 +1,78 @@
#pragma once
#if \
defined (__CYGWIN__) || \
defined (__CYGWIN32__)
# define NODE_EDITOR_PLATFORM "Cygwin"
# define NODE_EDITOR_PLATFORM_CYGWIN
# define NODE_EDITOR_PLATFORM_UNIX
# define NODE_EDITOR_PLATFORM_WINDOWS
#elif \
defined (_WIN16) || \
defined (_WIN32) || \
defined (_WIN64) || \
defined (__WIN32__) || \
defined (__TOS_WIN__) || \
defined (__WINDOWS__)
# define NODE_EDITOR_PLATFORM "Windows"
# define NODE_EDITOR_PLATFORM_WINDOWS
#elif \
defined (macintosh) || \
defined (Macintosh) || \
defined (__TOS_MACOS__) || \
(defined (__APPLE__) && defined (__MACH__))
# define NODE_EDITOR_PLATFORM "Mac"
# define NODE_EDITOR_PLATFORM_MAC
# define NODE_EDITOR_PLATFORM_UNIX
#elif \
defined (linux) || \
defined (__linux) || \
defined (__linux__) || \
defined (__TOS_LINUX__)
# define NODE_EDITOR_PLATFORM "Linux"
# define NODE_EDITOR_PLATFORM_LINUX
# define NODE_EDITOR_PLATFORM_UNIX
#elif \
defined (__FreeBSD__) || \
defined (__OpenBSD__) || \
defined (__NetBSD__) || \
defined (__bsdi__) || \
defined (__DragonFly__)
# define NODE_EDITOR_PLATFORM "BSD"
# define NODE_EDITOR_PLATFORM_BSD
# define NODE_EDITOR_PLATFORM_UNIX
#elif \
defined (sun) || \
defined (__sun)
# define NODE_EDITOR_PLATFORM "Solaris"
# define NODE_EDITOR_PLATFORM_SOLARIS
# define NODE_EDITOR_PLATFORM_UNIX
#elif \
defined (_AIX) || \
defined (__TOS_AIX__)
# define NODE_EDITOR_PLATFORM "AIX"
# define NODE_EDITOR_PLATFORM_AIX
# define NODE_EDITOR_PLATFORM_UNIX
#elif \
defined (hpux) || \
defined (_hpux) || \
defined (__hpux)
# define NODE_EDITOR_PLATFORM "HPUX"
# define NODE_EDITOR_PLATFORM_HPUX
# define NODE_EDITOR_PLATFORM_UNIX
#elif \
defined (__QNX__)
# define NODE_EDITOR_PLATFORM "QNX"
# define NODE_EDITOR_PLATFORM_QNX
# define NODE_EDITOR_PLATFORM_UNIX
#elif \
defined (unix) || \
defined (__unix) || \
defined (__unix__)
# define NODE_EDITOR_PLATFORM "Unix"
# define NODE_EDITOR_PLATFORM_UNIX
#endif
#ifndef NODE_EDITOR_PLATFORM
# error "Current platform is not supported."
#endif

View File

@ -0,0 +1,67 @@
#pragma once
#include <utility>
#include <QtCore/QUuid>
namespace QtNodes
{
enum class PortType
{
None,
In,
Out
};
static const int INVALID = -1;
using PortIndex = int;
struct Port
{
PortType type;
PortIndex index;
Port()
: type(PortType::None)
, index(INVALID)
{}
Port(PortType t, PortIndex i)
: type(t)
, index(i)
{}
bool
indexIsValid() { return index != INVALID; }
bool
portTypeIsValid() { return type != PortType::None; }
};
//using PortAddress = std::pair<QUuid, PortIndex>;
inline
PortType
oppositePort(PortType port)
{
PortType result = PortType::None;
switch (port)
{
case PortType::In:
result = PortType::Out;
break;
case PortType::Out:
result = PortType::In;
break;
default:
break;
}
return result;
}
}

View File

@ -0,0 +1,27 @@
#pragma once
#include <QtGlobal>
#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))
// As of 5.14 there is a specialization std::hash<QString>
#include <functional>
#include <QtCore/QString>
#include <QtCore/QVariant>
namespace std
{
template<>
struct hash<QString>
{
inline std::size_t
operator()(QString const& s) const
{
return qHash(s);
}
};
}
#endif

View File

@ -0,0 +1,21 @@
#pragma once
#include <functional>
#include <QtCore/QUuid>
#include <QtCore/QVariant>
namespace std
{
template<>
struct hash<QUuid>
{
inline
std::size_t
operator()(QUuid const& uid) const
{
return qHash(uid);
}
};
}

View File

@ -0,0 +1,22 @@
#pragma once
#include <QtCore/QJsonObject>
namespace QtNodes
{
class Serializable
{
public:
virtual
~Serializable() = default;
virtual
QJsonObject
save() const = 0;
virtual void
restore(QJsonObject const& /*p*/) {}
};
}

View File

@ -0,0 +1,23 @@
#pragma once
#include <QtCore/QString>
namespace QtNodes
{
class Style
{
public:
virtual
~Style() = default;
private:
virtual void
loadJsonFile(QString fileName) = 0;
virtual void
saveJsonFile(QString fileName) = 0;
};
}

View File

@ -0,0 +1,62 @@
#pragma once
#include "NodeStyle.hpp"
#include "ConnectionStyle.hpp"
#include "FlowViewStyle.hpp"
#include "Export.hpp"
namespace QtNodes
{
class StyleCollection
{
public:
static
NodeStyle const&
nodeStyle();
static
ConnectionStyle const&
connectionStyle();
static
FlowViewStyle const&
flowViewStyle();
public:
static
void
setNodeStyle(NodeStyle);
static
void
setConnectionStyle(ConnectionStyle);
static
void
setFlowViewStyle(FlowViewStyle);
private:
StyleCollection() = default;
StyleCollection(StyleCollection const&) = delete;
StyleCollection&
operator=(StyleCollection const&) = delete;
static
StyleCollection&
instance();
private:
NodeStyle _nodeStyle;
ConnectionStyle _connectionStyle;
FlowViewStyle _flowViewStyle;
};
}

View File

@ -0,0 +1,30 @@
#pragma once
#include "NodeData.hpp"
#include "memory.hpp"
#include <functional>
namespace QtNodes
{
using SharedNodeData = std::shared_ptr<NodeData>;
// a function taking in NodeData and returning NodeData
using TypeConverter =
std::function<SharedNodeData(SharedNodeData)>;
// data-type-in, data-type-out
using TypeConverterId =
std::pair<NodeDataType, NodeDataType>;
struct TypeConverterIdHash
{
std::size_t operator()(const QtNodes::TypeConverterId& converter) const noexcept
{
return qHash(converter.first.id)
^ qHash(converter.second.id);
}
};
}

View File

@ -0,0 +1,26 @@
#pragma once
#include <memory>
#include <utility>
namespace QtNodes
{
namespace detail {
#if (!defined(_MSC_VER) && (__cplusplus < 201300)) || \
( defined(_MSC_VER) && (_MSC_VER < 1800))
//_MSC_VER == 1800 is Visual Studio 2013, which is already somewhat C++14 compilant,
// and it has make_unique in it's standard library implementation
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
#else
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
return std::make_unique<T>(std::forward<Args>(args)...);
}
#endif
}
}