DataModelRegistry 是 QtNodes 框架中的模型注册中心,负责管理所有可用的节点数据模型和类型转换器。
核心职责
-
节点模型注册与管理:维护所有可用的节点数据模型
-
分类管理:将模型按类别组织
-
模型实例创建:根据名称创建模型实例
-
类型转换器管理:注册和查找数据类型转换器
#pragma once
#include "Export.hpp"
#include "NodeDataModel.hpp"
#include "QStringStdHash.hpp"
#include "TypeConverter.hpp"
#include "memory.hpp"
#include <QtCore/QString>
#include <functional>
#include <memory>
#include <set>
#include <unordered_map>
#include <vector>
namespace QtNodes
{
/// Class uses map for storing models (name, model)
class NODE_EDITOR_PUBLIC 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::map<TypeConverterId, TypeConverter>;
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 = "Nodes")
{
registerModelImpl<ModelType>(std::move(creator), category);
}
template<typename ModelType>
void registerModel(QString const &category = "Nodes")
{
RegistryItemCreator creator = []() {
return std::make_unique<ModelType>();
};
registerModelImpl<ModelType>(std::move(creator), category);
}
template<typename ModelType>
void registerModel(QString const &category, RegistryItemCreator creator)
{
registerModelImpl<ModelType>(std::move(creator), category);
}
void registerTypeConverter(TypeConverterId const &id, TypeConverter typeConverter)
{
_registeredTypeConverters[id] = std::move(typeConverter);
}
std::unique_ptr<NodeDataModel> create(QString const &modelName);
RegisteredModelCreatorsMap const ®isteredModelCreators() const;
RegisteredModelsCategoryMap const ®isteredModelsCategoryAssociation() const;
CategoriesSet const &categories() const;
TypeConverter getTypeConverter(NodeDataTypeId const &d1, NodeDataTypeId const &d2) const;
private:
RegisteredModelsCategoryMap _registeredModelsCategory;
CategoriesSet _categories;
RegisteredModelCreatorsMap _registeredItemCreators;
RegisteredTypeConvertersMap _registeredTypeConverters;
private:
// If the registered ModelType class has the static member method
//
// static Qstring Name();
//
// use it. Otherwise use the non-static method:
//
// virtual QString name() const;
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>
typename std::enable_if<HasStaticMethodName<ModelType>::value>::type registerModelImpl(RegistryItemCreator creator,
QString const &category)
{
const QString name = ModelType::Name();
if (_registeredItemCreators.count(name) == 0)
{
_registeredItemCreators[name] = std::move(creator);
_categories.insert(category);
_registeredModelsCategory[name] = category;
}
}
template<typename ModelType>
typename std::enable_if<!HasStaticMethodName<ModelType>::value>::type registerModelImpl(RegistryItemCreator creator,
QString const &category)
{
const QString name = creator()->name();
if (_registeredItemCreators.count(name) == 0)
{
_registeredItemCreators[name] = std::move(creator);
_categories.insert(category);
_registeredModelsCategory[name] = category;
}
}
};
} // namespace QtNodes
#include "DataModelRegistry.hpp"
#include <QtCore/QFile>
#include <QtWidgets/QMessageBox>
using QtNodes::DataModelRegistry;
using QtNodes::NodeDataModel;
using QtNodes::NodeDataType;
using QtNodes::TypeConverter;
std::unique_ptr<NodeDataModel> DataModelRegistry::create(QString const &modelName)
{
auto it = _registeredItemCreators.find(modelName);
if (it != _registeredItemCreators.end())
{
return it->second();
}
return nullptr;
}
DataModelRegistry::RegisteredModelCreatorsMap const &DataModelRegistry::registeredModelCreators() const
{
return _registeredItemCreators;
}
DataModelRegistry::RegisteredModelsCategoryMap const &DataModelRegistry::registeredModelsCategoryAssociation() const
{
return _registeredModelsCategory;
}
DataModelRegistry::CategoriesSet const &DataModelRegistry::categories() const
{
return _categories;
}
TypeConverter DataModelRegistry::getTypeConverter(QtNodes::NodeDataTypeId const &d1, QtNodes::NodeDataTypeId const &d2) const
{
TypeConverterId converterId = std::make_pair(d1, d2);
auto it = _registeredTypeConverters.find(converterId);
if (it != _registeredTypeConverters.end())
{
return it->second;
}
return TypeConverter{};
}
类成员详解
关键类型定义
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::map<TypeConverterId, TypeConverter>; // 类型转换器映射
注册方法
模型注册
// 三种重载形式
template<typename ModelType>
void registerModel(RegistryItemCreator creator, QString const &category = "Nodes");
template<typename ModelType>
void registerModel(QString const &category = "Nodes");
template<typename ModelType>
void registerModel(QString const &category, RegistryItemCreator creator);
-
支持自定义创建函数或使用默认构造函数
-
可指定模型所属类别(默认为"Nodes")
-
自动检测模型是否有静态
Name()方法
类型转换器注册
void registerTypeConverter(TypeConverterId const &id, TypeConverter typeConverter);
查询方法
std::unique_ptr<NodeDataModel> create(QString const &modelName); // 创建模型实例
RegisteredModelCreatorsMap const ®isteredModelCreators() const; // 获取所有模型创建器
RegisteredModelsCategoryMap const ®isteredModelsCategoryAssociation() const; // 获取模型-类别映射
CategoriesSet const &categories() const; // 获取所有类别
TypeConverter getTypeConverter(NodeDataTypeId const &d1, NodeDataTypeId const &d2) const; // 获取类型转换器
内部实现细节
SFINAE 检测静态 Name() 方法
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 {};
// 根据是否有静态Name()方法选择不同实现
template<typename ModelType>
typename std::enable_if<HasStaticMethodName<ModelType>::value>::type
registerModelImpl(RegistryItemCreator creator, QString const &category);
template<typename ModelType>
typename std::enable_if<!HasStaticMethodName<ModelType>::value>::type
registerModelImpl(RegistryItemCreator creator, QString const &category);
使用示例
注册模型
registry.registerModel<MyNodeModel>("Custom Nodes");
注册带自定义创建的模型
registry.registerModel<MyNodeModel>(
"Custom Nodes",
[]() { return std::make_unique<MyNodeModel>(param1, param2); }
);
创建模型实例
auto model = registry.create("MyNodeModel");
注册类型转换器
registry.registerTypeConverter(
{sourceType.id(), targetType.id()},
[](std::shared_ptr<NodeData> data) {
// 转换逻辑
return std::make_shared<TargetType>(...);
}
);
设计特点
-
灵活注册:支持多种模型注册方式
-
类型安全:使用模板确保模型类型正确
-
自动检测:智能检测模型的命名方式
-
分类管理:方便UI按类别展示模型
-
扩展性强:易于添加新的模型和转换器
典型应用场景
-
初始化注册:在应用启动时注册所有可用模型
-
插件系统:动态加载和注册模型
-
模型选择器:提供可用的模型列表供用户选择
-
类型转换:处理不同类型节点间的数据连接
这个注册中心是 QtNodes 框架可扩展性的关键,使得添加新节点类型变得简单而规范。

被折叠的 条评论
为什么被折叠?



