#pragma once #include #include #include #include "node.hpp" namespace ZShell::settings { // Derived from Node and has ctor(path, fallback, parent) template concept LayerType = std::derived_from && std::constructible_from; template class LayerRegistry { public: explicit LayerRegistry(const QString& prefix, const QString& suffix, QObject* parent); [[nodiscard]] QString pathFor(const QString& name) const; [[nodiscard]] QString nameFor(T* layer) const; [[nodiscard]] T* get(const QString& name, T* fallback, bool* created = nullptr); // Created on demand private: const QString m_prefix; const QString m_suffix; QObject* const m_parent; QHash m_layers; }; namespace detail { inline QString stripTrailingSlashes(QStringView str) { while (str.endsWith(u'/')) str = str.left(str.length() - 1); return str.toString(); } inline QString stripLeadingSlashes(QStringView str) { while (str.startsWith(u'/')) str = str.mid(1); return str.toString(); } } // namespace detail template LayerRegistry::LayerRegistry(const QString& prefix, const QString& suffix, QObject* parent) : m_prefix(detail::stripTrailingSlashes(prefix)) , m_suffix(detail::stripLeadingSlashes(suffix)) , m_parent(parent) {} template QString LayerRegistry::pathFor(const QString& name) const { return m_prefix + u'/' + name + u'/' + m_suffix; } template QString LayerRegistry::nameFor(T* layer) const { return m_layers.key(layer); } template T* LayerRegistry::get(const QString& name, T* fallback, bool* created) { if (auto* const layer = m_layers.value(name)) { if (created) *created = false; return layer; } if (created) *created = true; auto* const layer = new T(pathFor(name), fallback, m_parent); m_layers.insert(name, layer); return layer; } } // namespace ZShell::settings