#pragma once #include "confignode.hpp" #include #include #include #include #include #include #include #include namespace ZShell::config { inline QVariantMap vmap( std::initializer_list> entries) { QVariantMap map; for (const auto& [key, value] : entries) map.insert(key, value); return map; } #define CFG_PROPERTY(Type, name, ...) \ Q_PROPERTY(Type name READ name WRITE set_##name NOTIFY name##Changed) \ public: \ [[nodiscard]] Type name() const { \ return m_##name; \ } \ void set_##name(const Type& value) { \ if (ConfigObject::updateMember(m_##name, value)) { \ markPropertyLoaded(QStringLiteral(#name)); \ Q_EMIT name##Changed(); \ notifyPropertyChanged( \ QStringLiteral(#name), QVariant::fromValue(m_##name)); \ } \ } \ Q_SIGNAL void name##Changed(); \ \ private: \ Type m_##name __VA_OPT__(= __VA_ARGS__); #define CONFIG_SUBOBJECT(Type, name) \ Q_PROPERTY(ZShell::config::Type* name READ name CONSTANT) \ \ public: \ [[nodiscard]] Type* name() const { \ return m_##name; \ } \ \ private: \ Type* m_##name = nullptr; class ConfigObject : public ConfigNode { Q_OBJECT public: explicit ConfigObject(QObject* parent = nullptr); void loadFromJson(const QJsonValue& json) override; [[nodiscard]] QJsonValue toJson() const override; void clearLoadedKeys() override; [[nodiscard]] QStringList unknownKeys() const override; [[nodiscard]] QList childNodes() const override; void materializeDefaults() override; void resyncFromGlobal() override; [[nodiscard]] virtual QStringList identityKeys() const; [[nodiscard]] bool isPropertyLoaded(const QString& name) const; [[nodiscard]] bool isGlobalOnly(const QString& name) const; [[nodiscard]] QStringList globalOnlyKeys() const; Q_INVOKABLE void resetOption(const QString& name); template static bool updateMember(T& member, const T& value) { if constexpr (std::is_floating_point_v) { if (qFuzzyCompare(member + 1.0, value + 1.0)) return false; } else { if (member == value) return false; } member = value; return true; } protected: void syncValuesFromGlobal() override; void onGlobalPropertiesChanged( const QMap& changed) override; [[nodiscard]] QString childPath(const ConfigNode* child) const override; void markPropertyLoaded(const QString& name); void markGlobalOnly(const QString& name); private: QSet m_loadedKeys; QSet m_globalOnlyKeys; QJsonObject m_extras; }; } // namespace ZShell::config