#pragma once #include "nodeData.h" #include "nodeDelegateModel.h" #include /// Class uses map for storing models (name, model) class NodeDelegateModelRegistry { public: using RegistryItemPtr = QSharedPointer; using RegistryItemCreator = RegistryItemPtr; using RegisteredModelCreatorsMap = QMap; using RegisteredModelsCategoryMap = QMap; using CategoriesSet = QSet; //using RegisteredTypeConvertersMap = std::map; NodeDelegateModelRegistry() = default; ~NodeDelegateModelRegistry() = default; NodeDelegateModelRegistry(NodeDelegateModelRegistry const &) = delete; NodeDelegateModelRegistry(NodeDelegateModelRegistry &&) = default; NodeDelegateModelRegistry &operator=(NodeDelegateModelRegistry const &) = delete; NodeDelegateModelRegistry &operator=(NodeDelegateModelRegistry &&) = default; public: template void registerModel(RegistryItemCreator creator, QString const &category = "Nodes") { QString const 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 = "Nodes") { RegistryItemCreator creator = []() { return std::make_unique(); }; registerModel(std::move(creator), category); } #if 0 template void registerModel(RegistryItemCreator creator, QString const& category = "Nodes") { registerModel(std::move(creator), category); } template void registerModel(ModelCreator&& creator, QString const& category = "Nodes") { 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); } #endif QSharedPointer create(QString const &modelName); RegisteredModelCreatorsMap const ®isteredModelCreators() const; RegisteredModelsCategoryMap const ®isteredModelsCategoryAssociation() const; CategoriesSet const &categories() const; #if 0 TypeConverter getTypeConverter(NodeDataType const& d1, NodeDataType const& d2) const; #endif private: RegisteredModelsCategoryMap _registeredModelsCategory; CategoriesSet _categories; RegisteredModelCreatorsMap _registeredItemCreators; #if 0 RegisteredTypeConvertersMap _registeredTypeConverters; #endif 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 struct HasStaticMethodName : std::false_type {}; template struct HasStaticMethodName< T, typename std::enable_if::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 NodeDelegateModel"); }; template struct UnwrapUniquePtr> { static_assert(std::is_base_of::value, "The ModelCreator must return a std::unique_ptr, where T " "inherits from NodeDelegateModel"); using type = T; }; template using compute_model_type_t = typename UnwrapUniquePtr::type; };