#ifndef SETTINGSUTILITIES_H #define SETTINGSUTILITIES_H #include namespace MOBase { class ExpanderWidget; } template struct ValueConverter { static const T& convert(const T& t) { return t; } }; template struct ValueConverter>> { static QString convert(const T& t) { return QString("%1").arg(static_cast>(t)); } }; template <> struct ValueConverter { static QString convert(const QVariantList& t) { return QString("%1").arg(QVariant(t).toStringList().join(",")); } }; template <> struct ValueConverter { static QString convert(const QStringList& t) { return t.join(", "); } }; bool shouldLogSetting(const QString& displayName); template void logChange(const QString& displayName, std::optional oldValue, const T& newValue) { if (!shouldLogSetting(displayName)) { return; } using VC = ValueConverter; if (oldValue) { MOBase::log::debug("setting '{}' changed from '{}' to '{}'", displayName, VC::convert(*oldValue), VC::convert(newValue)); } else { MOBase::log::debug("setting '{}' set to '{}'", displayName, VC::convert(newValue)); } } void logRemoval(const QString& name); QString settingName(const QString& section, const QString& key); template void setImpl(QSettings& settings, const QString& displayName, const QString& section, const QString& key, const T& value) { const auto current = getOptional(settings, section, key); if (current && *current == value) { // no change return; } const auto name = settingName(section, key); logChange(displayName, current, value); if constexpr (std::is_enum_v) { settings.setValue(name, static_cast>(value)); } else { settings.setValue(name, value); } } void removeImpl(QSettings& settings, const QString& displayName, const QString& section, const QString& key); template std::optional getOptional(const QSettings& settings, const QString& section, const QString& key, std::optional def = {}) { if (settings.contains(settingName(section, key))) { const auto v = settings.value(settingName(section, key)); if constexpr (std::is_enum_v) { return static_cast(v.value>()); } else { return v.value(); } } return def; } template T get(const QSettings& settings, const QString& section, const QString& key, T def) { if (auto v = getOptional(settings, section, key)) { return *v; } else { return def; } } template void set(QSettings& settings, const QString& section, const QString& key, const T& value) { setImpl(settings, settingName(section, key), section, key, value); } void remove(QSettings& settings, const QString& section, const QString& key); void removeSection(QSettings& settings, const QString& section); class ScopedGroup { public: ScopedGroup(QSettings& s, const QString& name); ~ScopedGroup(); ScopedGroup(const ScopedGroup&) = delete; ScopedGroup& operator=(const ScopedGroup&) = delete; template void set(const QString& key, const T& value) { setImpl(m_settings, settingName(m_name, key), "", key, value); } void remove(const QString& key); QStringList keys() const; template void for_each(F&& f) const { for (const QString& key : keys()) { f(key); } } template std::optional getOptional(const QString& key, std::optional def = {}) const { return ::getOptional(m_settings, "", key, def); } template T get(const QString& key, T def = {}) const { return ::get(m_settings, "", key, def); } private: QSettings& m_settings; QString m_name; }; class ScopedReadArray { public: ScopedReadArray(QSettings& s, const QString& section); ~ScopedReadArray(); ScopedReadArray(const ScopedReadArray&) = delete; ScopedReadArray& operator=(const ScopedReadArray&) = delete; template void for_each(F&& f) const { for (int i = 0; i < count(); ++i) { m_settings.setArrayIndex(i); f(); } } template std::optional getOptional(const QString& key, std::optional def = {}) const { return ::getOptional(m_settings, "", key, def); } template T get(const QString& key, T def = {}) const { return ::get(m_settings, "", key, def); } int count() const; QStringList keys() const; private: QSettings& m_settings; int m_count; }; class ScopedWriteArray { public: static const auto NoSize = std::numeric_limits::max(); ScopedWriteArray(QSettings& s, const QString& section, std::size_t size = NoSize); ~ScopedWriteArray(); ScopedWriteArray(const ScopedWriteArray&) = delete; ScopedWriteArray& operator=(const ScopedWriteArray&) = delete; void next(); template void set(const QString& key, const T& value) { const auto displayName = QString("%1/%2\\%3").arg(m_section).arg(m_i).arg(key); setImpl(m_settings, displayName, "", key, value); } private: QSettings& m_settings; QString m_section; int m_i; }; QString widgetNameWithTopLevel(const QWidget* widget); QString widgetName(const QMainWindow* w); QString widgetName(const QHeaderView* w); QString widgetName(const MOBase::ExpanderWidget* w); QString widgetName(const QWidget* w); template QString geoSettingName(const Widget* widget) { return widgetName(widget) + "_geometry"; } template QString stateSettingName(const Widget* widget) { return widgetName(widget) + "_state"; } template QString visibilitySettingName(const Widget* widget) { return widgetName(widget) + "_visibility"; } QString dockSettingName(const QDockWidget* dock); QString indexSettingName(const QWidget* widget); QString checkedSettingName(const QAbstractButton* b); void warnIfNotCheckable(const QAbstractButton* b); bool setWindowsCredential(const QString& key, const QString& data); QString getWindowsCredential(const QString& key); #endif // SETTINGSUTILITIES_H