#pragma once #include #include #include #include #include #include #include #include #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; using RegistryItemCreator = std::function; using RegisteredModelCreatorsMap = std::unordered_map; using RegisteredModelsCategoryMap = std::unordered_map; using CategoriesSet = std::set; 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 void registerModel(RegistryItemCreator creator, QString const& category = u8"默认节点") { const QString name = computeName(HasStaticMethodName{}, creator); if (!_registeredItemCreators.count(name)) { _registeredItemCreators[name] = std::move(creator); _categories.insert(category); _registeredModelsCategory[name] = category; } } template void registerModel(QString const& category = u8"默认节点") { RegistryItemCreator creator = []() { return std::make_unique(); }; registerModel(std::move(creator), category); } template void registerModel(QString const& category, RegistryItemCreator creator) { registerModel(std::move(creator), category); } template void registerModel(ModelCreator&& creator, QString const& category = u8"默认节点") { using ModelType = compute_model_type_t; registerModel(std::forward(creator), category); } template void registerModel(QString const& category, ModelCreator&& creator) { registerModel(std::forward(creator), category); } void registerTypeConverter(TypeConverterId const& id, TypeConverter typeConverter) { _registeredTypeConverters[id] = std::move(typeConverter); } std::unique_ptrcreate(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 struct HasStaticMethodName : std::false_type {}; template struct HasStaticMethodName::value>::type> : std::true_type {}; template static QString computeName(std::true_type, RegistryItemCreator const&) { return ModelType::Name(); } template static QString computeName(std::false_type, RegistryItemCreator const& creator) { return creator()->name(); } template struct UnwrapUniquePtr { // Assert always fires, but the compiler doesn't know this: static_assert(!std::is_same::value, "The ModelCreator must return a std::unique_ptr, where T " "inherits from NodeDataModel"); }; template struct UnwrapUniquePtr> { static_assert(std::is_base_of::value, "The ModelCreator must return a std::unique_ptr, where T " "inherits from NodeDataModel"); using type = T; }; template using compute_model_type_t = typename UnwrapUniquePtr::type; }; }