目录
1. 声明总结
枚举类型:
(1)NodeRole节点属性,比如节点类型、节点标题、节点输入输出端口数、节点位置等;
(2) NodeFlag节点标志,是否允许调整节点大小;
(3) PortRole端口信息,比如端口描述、该描述是否可见、端口连接策略等;
(4)ConnectionPolicy连接策略,包括一对一,还是一对多;
(5)PortType端口类型,包括输入端口、输出端口、无效端口;
类型别名定义:
(1)using PortCount = unsigned int; // 端口数量
(2) using PortIndex = unsigned int; // 端口索引
(3)using NodeId = unsigned int; // 节点id,表示每个节点在图形模型中的唯一ID。
语义上是等价的。
常量:
(1)InvalidPortIndex 无效端口索引常量
(2)InvalidNodeId 无效节点id,无效的节点ID,表示一个无效的或未使用的节点。
结构体:
(1)ConnectionId, 包含输出节点 ID、输出端口索引、输入节点 ID、输入端口索引。
函数接口:
(1)==,使用ConnectionID判断两个节点是否是同一个节点;
(2)!=,使用ConnectionID判断两个节点是否不是同一个节点;
(3)invertConnection,输入和输出反转。
2. 具体声明
// 这段代码定义了一些常量、枚举和数据结构,用于节点编辑器库中的重要定义。
// 判断当前的Qt版本,如果版本低于6.0.0,就使用Q_NAMESPACE宏,否则使用Q_NAMESPACE_EXPORT宏。
namespace QtNodes {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
NODE_EDITOR_PUBLIC Q_NAMESPACE
#else
Q_NAMESPACE_EXPORT(NODE_EDITOR_PUBLIC)
#endif
// 定义了一组用于从GraphModel中获取QVariant数据的枚举常量,这些常量表示不同的角色。
enum class NodeRole {
Type = 0, ///< 当前节点的类型,通常是一个字符串。
Position = 1, ///< 节点在场景中的位置,使用QPointF类型表示。
Size = 2, ///< 可调整大小节点的大小,使用QSize表示。
CaptionVisible = 3, ///< 标识节点标题是否可见,使用bool表示。
Caption = 4, ///< 节点的标题,使用QString表示。
Style = 5, ///< 自定义的节点样式,存储为QJsonDocument。
InternalData = 6, ///< 节点特定的用户数据,存储为QJsonObject。
InPortCount = 7, ///< 输入端口的数量,使用unsigned int表示。
OutPortCount = 9, ///< 输出端口的数量,使用unsigned int表示。
Widget = 10, ///< 可选的QWidget指针,或者为nullptr。
};
Q_ENUM_NS(NodeRole)
// 定义了一组节点特性和外观的标志。
enum NodeFlag {
NoFlags = 0x0, ///< 默认标志
Resizable = 0x1, ///< 允许节点调整大小
Locked = 0x2 ///< 节点锁定标志
};
Q_DECLARE_FLAGS(NodeFlags, NodeFlag) // 将多个枚举值合并到一个标志值中
Q_FLAG_NS(NodeFlags) // 这个宏用于在 QFlags 命名空间中为 NodeFlags 枚举类型生成相应的位标志类型。
Q_DECLARE_OPERATORS_FOR_FLAGS(NodeFlags)
// QFlags 是 Qt 中的一个模板类,它用于处理位标志。它允许您将多个标志值组合成一个对象,
// 并提供了一些方便的操作符,如 |(按位或)、&(按位与)和 ~(按位取反), 以便更轻松地进行位标志操作。
// Q_DECLARE_OPERATORS_FOR_FLAGS宏它用于自动生成一些运算符重载函数,以便您可以更自然地操作 QFlags 对象,而不必手动编写这些函数。
// 定义了一组用于从GraphModel中获取端口相关信息的枚举常量,这些常量表示不同的角色。
enum class PortRole {
Data = 0, ///< std::shared_ptr<NodeData>类型的端口数据。
DataType = 1, ///< 描述端口数据类型的QString。
ConnectionPolicyRole = 2, ///< ConnectionPolicyRole枚举类型的连接策略。
CaptionVisible = 3, ///< 标识端口标题是否可见,使用bool表示。
Caption = 4, ///< 端口的标题,使用QString表示。
};
Q_ENUM_NS(PortRole) //Qt宏将枚举类型注册到元对象系统,可以在Qt的信号槽机制中使用这个枚举类型。
// 定义了连接策略的枚举,用于控制连接到端口的连接数。
enum class ConnectionPolicy {
One, ///< 每个端口只允许一个连接。
Many, ///< 一个端口允许多个连接。
};
Q_ENUM_NS(ConnectionPolicy)
// 用于区分输入端口和输出端口的枚举。
enum class PortType {
In = 0, ///< 输入端口(从左侧连接)。
Out = 1, ///< 输出端口(从右侧连接)。
None = 2 ///< 无效端口。
};
Q_ENUM_NS(PortType)
// 定义了一些用于标识节点、端口等的数据类型(类型别名定义)。
using PortCount = unsigned int; // 端口数量
using PortIndex = unsigned int; // 端口索引
// 无效的端口索引,表示一个无效的或未使用的端口。
// 创建一个表示无效端口索引的常量。它将 InvalidPortIndex 设置为 PortIndex 类型的最大值
static constexpr PortIndex InvalidPortIndex = std::numeric_limits<PortIndex>::max();
// 表示每个节点在图形模型中的唯一ID。
using NodeId = unsigned int; // 节点ID
// 无效的节点ID,表示一个无效的或未使用的节点。
static constexpr NodeId InvalidNodeId = std::numeric_limits<NodeId>::max();
/**
* 一个唯一的连接标识符,存储
* 输出节点 ID、输出端口索引、输入节点 ID、输入端口索引
*/
struct ConnectionId
{
NodeId outNodeId; ///< 输出节点 ID
PortIndex outPortIndex; ///< 输出端口索引
NodeId inNodeId; ///< 输入节点 ID
PortIndex inPortIndex; ///< 输入端口索引
};
/**
* 检查两个 ConnectionId 对象是否相等的运算符。
* 如果它们的各个成员都相等,则它们被视为相等。
*/
inline bool operator==(ConnectionId const &a, ConnectionId const &b)
{
return a.outNodeId == b.outNodeId && a.outPortIndex == b.outPortIndex
&& a.inNodeId == b.inNodeId && a.inPortIndex == b.inPortIndex;
}
/**
* 检查两个 ConnectionId 对象是否不相等的运算符。
* 如果它们的任何一个成员不相等,则它们被视为不相等。
*/
inline bool operator!=(ConnectionId const &a, ConnectionId const &b)
{
return !(a == b);
}
/**
* 反转 ConnectionId 的函数,通过交换源和目标节点和端口来实现。
*/
inline void invertConnection(ConnectionId &id)
{
std::swap(id.outNodeId, id.inNodeId);
std::swap(id.outPortIndex, id.inPortIndex);
}
} // namespace QtNodes
3. 多个枚举值合并
Q_DECLARE_FLAGS(NodeFlags, NodeFlag)
用于声明一个名为 NodeFlags
的标志类型,该类型包含 NodeFlag
枚举值。这意味着您可以将多个 NodeFlag
枚举值组合成一个 NodeFlags
类型的标志值。
例如,如果您有以下的 NodeFlag
枚举值:
enum NodeFlag {
NoFlags = 0x0, // 默认标志
Resizable = 0x1, // 允许节点可调整大小
Locked = 0x2 // 节点锁定
};
// 将多个 NodeFlag 枚举值组合成一个 NodeFlags 类型的标志值
NodeFlags flags = NodeFlag::Resizable | NodeFlag::Locked;
// 优点是:使用位运算来设置、清除和测试这些标志,以控制节点的行为和外观
// 检查是否设置了 Resizable 标志
if (flags & NodeFlag::Resizable) {
// 执行可调整大小的逻辑
}
// 清除 Locked 标志
flags &= ~NodeFlag::Locked;
然后,使用 Q_DECLARE_FLAGS
宏,您可以创建一个包含这些标志的 NodeFlags
类型,以便更轻松地管理和操作多个标志。这允许您使用位运算来设置、清除和测试这些标志,以控制节点的行为和外观。例如:
flags &= ~NodeFlag::Locked;
这行代码实现了清除功能,因为它使用了位运算技巧来清除 flags
中的特定标志位。
让我解释一下:
-
&
是按位与运算符。当您执行flags & NodeFlag::Locked
时,它会检查flags
中是否设置了NodeFlag::Locked
标志位。如果设置了该标志位,结果为非零;否则,结果为零。 -
~
是按位取反运算符。它会反转二进制数的每个位,将 0 变为 1,将 1 变为 0。
所以,~NodeFlag::Locked
会创建一个只有 NodeFlag::Locked
位为 0,其他位都为 1 的掩码。这个掩码可以用来清除 flags
中的 NodeFlag::Locked
位。
最后,&=
是位与赋值运算符,用于将 flags
和右侧的表达式结果按位与,然后将结果存储回 flags
。因此,flags &= ~NodeFlag::Locked;
的操作将清除 flags
中的 NodeFlag::Locked
标志位。
这是一种常见的技巧,用于操作和修改位标志,允许您动态地控制标志的状态。