summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorisanae <14251494+isanae@users.noreply.github.com>2019-09-02 15:07:35 -0400
committerisanae <14251494+isanae@users.noreply.github.com>2019-09-02 15:07:35 -0400
commit3757aa3f532c943f8a47e997d0a4f250d9dacdd3 (patch)
tree65fa840ea06ba27b8a22f23db1089b9d20ff1f85
parente9dba260cb9548dd5863ac66da18c295f6499b92 (diff)
split into settingsutilities
-rw-r--r--src/CMakeLists.txt9
-rw-r--r--src/settings.cpp452
-rw-r--r--src/settings.h3
-rw-r--r--src/settingsutilities.cpp247
-rw-r--r--src/settingsutilities.h266
5 files changed, 522 insertions, 455 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d8316e7e..ea27184b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -45,6 +45,7 @@ SET(organizer_SRCS
settingsdialogsteam.cpp
settingsdialogworkarounds.cpp
settings.cpp
+ settingsutilities.cpp
selfupdater.cpp
selectiondialog.cpp
queryoverwritedialog.cpp
@@ -166,6 +167,7 @@ SET(organizer_HDRS
settingsdialogsteam.h
settingsdialogworkarounds.h
settings.h
+ settingsutilities.h
selfupdater.h
selectiondialog.h
queryoverwritedialog.h
@@ -444,6 +446,10 @@ set(profiles
set(settings
settings
+ settingsutilities
+)
+
+set(settingsdialog
settingsdialog
settingsdialogdiagnostics
settingsdialoggeneral
@@ -490,7 +496,8 @@ set(widgets
set(src_filters
application core browser dialogs downloads env executables locking modinfo
- modinfo\\dialog modlist plugins previews profiles settings utilities widgets
+ modinfo\\dialog modlist plugins previews profiles settings settingsdialog
+ utilities widgets
)
foreach(filter in list ${src_filters})
diff --git a/src/settings.cpp b/src/settings.cpp
index 8b063efb..14189be3 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -18,6 +18,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "settings.h"
+#include "settingsutilities.h"
#include "serverinfo.h"
#include "executableslist.h"
#include "appconfig.h"
@@ -27,310 +28,6 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
using namespace MOBase;
-template <class T, class=void>
-struct ValueConverter
-{
- static const T& convert(const T& t)
- {
- return t;
- }
-};
-
-template <class T>
-struct ValueConverter<T, std::enable_if_t<std::is_enum_v<T>>>
-{
- static QString convert(const T& t)
- {
- return QString("%1").arg(static_cast<std::underlying_type_t<T>>(t));
- }
-};
-
-
-template <class T>
-void logChange(
- const QString& displayName, std::optional<T> oldValue, const T& newValue)
-{
- using VC = ValueConverter<T>;
-
- if (oldValue) {
- log::debug(
- "setting '{}' changed from '{}' to '{}'",
- displayName, VC::convert(*oldValue), VC::convert(newValue));
- } else {
- log::debug(
- "setting '{}' set to '{}'",
- displayName, VC::convert(newValue));
- }
-}
-
-void logRemoval(const QString& name)
-{
- log::debug("setting '{}' removed", name);
-}
-
-
-QString settingName(const QString& section, const QString& key)
-{
- if (section.isEmpty()) {
- return key;
- } else if (key.isEmpty()) {
- return section;
- } else {
- if (section.compare("General", Qt::CaseInsensitive) == 0) {
- return key;
- } else {
- return section + "/" + key;
- }
- }
-}
-
-template <class T>
-void setImpl(
- QSettings& settings, const QString& displayName,
- const QString& section, const QString& key, const T& value)
-{
- const auto current = getOptional<T>(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<T>) {
- settings.setValue(
- name, static_cast<std::underlying_type_t<T>>(value));
- } else {
- settings.setValue(name, value);
- }
-}
-
-void removeImpl(
- QSettings& settings, const QString& displayName,
- const QString& section, const QString& key)
-{
- if (key.isEmpty()) {
- if (!settings.childGroups().contains(section, Qt::CaseInsensitive)) {
- // not there
- return;
- }
- } else {
- if (!settings.contains(settingName(section, key))) {
- // not there
- return;
- }
- }
-
- logRemoval(displayName);
- settings.remove(settingName(section, key));
-}
-
-
-template <class T>
-std::optional<T> getOptional(
- const QSettings& settings,
- const QString& section, const QString& key, std::optional<T> def={})
-{
- if (settings.contains(settingName(section, key))) {
- const auto v = settings.value(settingName(section, key));
-
- if constexpr (std::is_enum_v<T>) {
- return static_cast<T>(v.value<std::underlying_type_t<T>>());
- } else {
- return v.value<T>();
- }
- }
-
- return def;
-}
-
-template <class T>
-T get(
- const QSettings& settings,
- const QString& section, const QString& key, T def)
-{
- if (auto v=getOptional<T>(settings, section, key)) {
- return *v;
- } else {
- return def;
- }
-}
-
-template <class T>
-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)
-{
- removeImpl(settings, settingName(section, key), section, key);
-}
-
-void removeSection(QSettings& settings, const QString& section)
-{
- removeImpl(settings, section, section, "");
-}
-
-
-class ScopedGroup
-{
-public:
- ScopedGroup(QSettings& s, const QString& name)
- : m_settings(s), m_name(name)
- {
- m_settings.beginGroup(m_name);
- }
-
- ~ScopedGroup()
- {
- m_settings.endGroup();
- }
-
- ScopedGroup(const ScopedGroup&) = delete;
- ScopedGroup& operator=(const ScopedGroup&) = delete;
-
- template <class T>
- void set(const QString& key, const T& value)
- {
- setImpl(m_settings, settingName(m_name, key), "", key, value);
- }
-
- void remove(const QString& key)
- {
- removeImpl(m_settings, settingName(m_name, key), "", key);
- }
-
- QStringList keys() const
- {
- return m_settings.childKeys();
- }
-
- template <class F>
- void for_each(F&& f) const
- {
- for (const QString& key : keys()) {
- f(key);
- }
- }
-
- template <class T>
- std::optional<T> getOptional(const QString& key, std::optional<T> def={}) const
- {
- return ::getOptional<T>(m_settings, "", key, def);
- }
-
- template <class T>
- T get(const QString& key, T def={}) const
- {
- return ::get<T>(m_settings, "", key, def);
- }
-
-private:
- QSettings& m_settings;
- QString m_name;
-};
-
-
-class ScopedReadArray
-{
-public:
- ScopedReadArray(QSettings& s, const QString& section)
- : m_settings(s), m_count(0)
- {
- m_count = m_settings.beginReadArray(section);
- }
-
- ~ScopedReadArray()
- {
- m_settings.endArray();
- }
-
- ScopedReadArray(const ScopedReadArray&) = delete;
- ScopedReadArray& operator=(const ScopedReadArray&) = delete;
-
- template <class F>
- void for_each(F&& f) const
- {
- for (int i=0; i<count(); ++i) {
- m_settings.setArrayIndex(i);
- f();
- }
- }
-
- template <class T>
- std::optional<T> getOptional(const QString& key, std::optional<T> def={}) const
- {
- return ::getOptional<T>(m_settings, "", key, def);
- }
-
- template <class T>
- T get(const QString& key, T def={}) const
- {
- return ::get<T>(m_settings, "", key, def);
- }
-
- int count() const
- {
- return m_count;
- }
-
- QStringList keys() const
- {
- return m_settings.childKeys();
- }
-
-private:
- QSettings& m_settings;
- int m_count;
-};
-
-
-class ScopedWriteArray
-{
-public:
- ScopedWriteArray(QSettings& s, const QString& section)
- : m_settings(s), m_section(section), m_i(0)
- {
- m_settings.beginWriteArray(section);
- }
-
- ~ScopedWriteArray()
- {
- m_settings.endArray();
- }
-
- ScopedWriteArray(const ScopedWriteArray&) = delete;
- ScopedWriteArray& operator=(const ScopedWriteArray&) = delete;
-
- void next()
- {
- m_settings.setArrayIndex(m_i);
- ++m_i;
- }
-
- template <class T>
- 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;
-};
-
EndorsementState endorsementStateFromString(const QString& s)
{
@@ -360,153 +57,6 @@ QString toString(EndorsementState s)
}
-QString widgetNameWithTopLevel(const QWidget* widget)
-{
- QStringList components;
-
- auto* tl = widget->window();
-
- if (tl == widget) {
- // this is a top level widget, such as a dialog
- components.push_back(widget->objectName());
- } else {
- // this is a widget
- const auto toplevelName = tl->objectName();
- if (!toplevelName.isEmpty()) {
- components.push_back(toplevelName);
- }
-
- const auto widgetName = widget->objectName();
- if (!widgetName.isEmpty()) {
- components.push_back(widgetName);
- }
- }
-
- if (components.isEmpty()) {
- // can't do much
- return "unknown_widget";
- }
-
- return components.join("_");
-}
-
-QString widgetName(const QMainWindow* w)
-{
- return w->objectName();
-}
-
-QString widgetName(const QHeaderView* w)
-{
- return widgetNameWithTopLevel(w->parentWidget());
-}
-
-QString widgetName(const ExpanderWidget* w)
-{
- return widgetNameWithTopLevel(w->button());
-}
-
-QString widgetName(const QWidget* w)
-{
- return widgetNameWithTopLevel(w);
-}
-
-template <class Widget>
-QString geoSettingName(const Widget* widget)
-{
- return widgetName(widget) + "_geometry";
-}
-
-template <class Widget>
-QString stateSettingName(const Widget* widget)
-{
- return widgetName(widget) + "_state";
-}
-
-template <class Widget>
-QString visibilitySettingName(const Widget* widget)
-{
- return widgetName(widget) + "_visibility";
-}
-
-QString dockSettingName(const QDockWidget* dock)
-{
- return "MainWindow_docks_" + dock->objectName() + "_size";
-}
-
-QString indexSettingName(const QWidget* widget)
-{
- return widgetNameWithTopLevel(widget) + "_index";
-}
-
-QString checkedSettingName(const QAbstractButton* b)
-{
- return widgetNameWithTopLevel(b) + "_checked";
-}
-
-void warnIfNotCheckable(const QAbstractButton* b)
-{
- if (!b->isCheckable()) {
- log::warn(
- "button '{}' used in the settings as a checkbox or radio button "
- "but is not checkable", b->objectName());
- }
-}
-
-
-bool setWindowsCredential(const QString key, const QString data)
-{
- QString finalKey("ModOrganizer2_" + key);
- wchar_t* keyData = new wchar_t[finalKey.size()+1];
- finalKey.toWCharArray(keyData);
- keyData[finalKey.size()] = L'\0';
- bool result = false;
- if (data.isEmpty()) {
- result = CredDeleteW(keyData, CRED_TYPE_GENERIC, 0);
- if (!result)
- if (GetLastError() == ERROR_NOT_FOUND)
- result = true;
- } else {
- wchar_t* charData = new wchar_t[data.size()];
- data.toWCharArray(charData);
-
- CREDENTIALW cred = {};
- cred.Flags = 0;
- cred.Type = CRED_TYPE_GENERIC;
- cred.TargetName = keyData;
- cred.CredentialBlob = (LPBYTE)charData;
- cred.CredentialBlobSize = sizeof(wchar_t) * data.size();
- cred.Persist = CRED_PERSIST_LOCAL_MACHINE;
-
- result = CredWriteW(&cred, 0);
- delete[] charData;
- }
- delete[] keyData;
- return result;
-}
-
-QString getWindowsCredential(const QString key)
-{
- QString result;
- QString finalKey("ModOrganizer2_" + key);
- wchar_t* keyData = new wchar_t[finalKey.size()+1];
- finalKey.toWCharArray(keyData);
- keyData[finalKey.size()] = L'\0';
- PCREDENTIALW creds;
- if (CredReadW(keyData, 1, 0, &creds)) {
- wchar_t *charData = (wchar_t *)creds->CredentialBlob;
- result = QString::fromWCharArray(charData, creds->CredentialBlobSize / sizeof(wchar_t));
- CredFree(creds);
- } else {
- const auto e = GetLastError();
- if (e != ERROR_NOT_FOUND) {
- log::error("Retrieving encrypted data failed: {}", formatSystemMessage(e));
- }
- }
- delete[] keyData;
- return result;
-}
-
-
Settings *Settings::s_Instance = nullptr;
Settings::Settings(const QString& path) :
diff --git a/src/settings.h b/src/settings.h
index 5c0a2542..68cfb9b7 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -36,8 +36,6 @@ namespace MOBase {
class QSplitter;
-class PluginContainer;
-class ServerInfo;
class ServerList;
class Settings;
class ExpanderWidget;
@@ -505,7 +503,6 @@ private:
};
-
/**
* manages the settings for Mod Organizer. The settings are not cached
* inside the class but read/written directly from/to disc
diff --git a/src/settingsutilities.cpp b/src/settingsutilities.cpp
new file mode 100644
index 00000000..7ac95b5f
--- /dev/null
+++ b/src/settingsutilities.cpp
@@ -0,0 +1,247 @@
+#include "settingsutilities.h"
+#include "expanderwidget.h"
+#include <utility.h>
+
+using namespace MOBase;
+
+void logRemoval(const QString& name)
+{
+ log::debug("setting '{}' removed", name);
+}
+
+
+QString settingName(const QString& section, const QString& key)
+{
+ if (section.isEmpty()) {
+ return key;
+ } else if (key.isEmpty()) {
+ return section;
+ } else {
+ if (section.compare("General", Qt::CaseInsensitive) == 0) {
+ return key;
+ } else {
+ return section + "/" + key;
+ }
+ }
+}
+
+void removeImpl(
+ QSettings& settings, const QString& displayName,
+ const QString& section, const QString& key)
+{
+ if (key.isEmpty()) {
+ if (!settings.childGroups().contains(section, Qt::CaseInsensitive)) {
+ // not there
+ return;
+ }
+ } else {
+ if (!settings.contains(settingName(section, key))) {
+ // not there
+ return;
+ }
+ }
+
+ logRemoval(displayName);
+ settings.remove(settingName(section, key));
+}
+
+void remove(QSettings& settings, const QString& section, const QString& key)
+{
+ removeImpl(settings, settingName(section, key), section, key);
+}
+
+void removeSection(QSettings& settings, const QString& section)
+{
+ removeImpl(settings, section, section, "");
+}
+
+
+ScopedGroup::ScopedGroup(QSettings& s, const QString& name)
+ : m_settings(s), m_name(name)
+{
+ m_settings.beginGroup(m_name);
+}
+
+ScopedGroup::~ScopedGroup()
+{
+ m_settings.endGroup();
+}
+
+void ScopedGroup::remove(const QString& key)
+{
+ removeImpl(m_settings, settingName(m_name, key), "", key);
+}
+
+QStringList ScopedGroup::keys() const
+{
+ return m_settings.childKeys();
+}
+
+
+ScopedReadArray::ScopedReadArray(QSettings& s, const QString& section)
+ : m_settings(s), m_count(0)
+{
+ m_count = m_settings.beginReadArray(section);
+}
+
+ScopedReadArray::~ScopedReadArray()
+{
+ m_settings.endArray();
+}
+
+int ScopedReadArray::count() const
+{
+ return m_count;
+}
+
+QStringList ScopedReadArray::keys() const
+{
+ return m_settings.childKeys();
+}
+
+
+ScopedWriteArray::ScopedWriteArray(QSettings& s, const QString& section)
+ : m_settings(s), m_section(section), m_i(0)
+{
+ m_settings.beginWriteArray(section);
+}
+
+ScopedWriteArray::~ScopedWriteArray()
+{
+ m_settings.endArray();
+}
+
+void ScopedWriteArray::next()
+{
+ m_settings.setArrayIndex(m_i);
+ ++m_i;
+}
+
+
+QString widgetNameWithTopLevel(const QWidget* widget)
+{
+ QStringList components;
+
+ auto* tl = widget->window();
+
+ if (tl == widget) {
+ // this is a top level widget, such as a dialog
+ components.push_back(widget->objectName());
+ } else {
+ // this is a widget
+ const auto toplevelName = tl->objectName();
+ if (!toplevelName.isEmpty()) {
+ components.push_back(toplevelName);
+ }
+
+ const auto widgetName = widget->objectName();
+ if (!widgetName.isEmpty()) {
+ components.push_back(widgetName);
+ }
+ }
+
+ if (components.isEmpty()) {
+ // can't do much
+ return "unknown_widget";
+ }
+
+ return components.join("_");
+}
+
+QString widgetName(const QMainWindow* w)
+{
+ return w->objectName();
+}
+
+QString widgetName(const QHeaderView* w)
+{
+ return widgetNameWithTopLevel(w->parentWidget());
+}
+
+QString widgetName(const ExpanderWidget* w)
+{
+ return widgetNameWithTopLevel(w->button());
+}
+
+QString widgetName(const QWidget* w)
+{
+ return widgetNameWithTopLevel(w);
+}
+
+QString dockSettingName(const QDockWidget* dock)
+{
+ return "MainWindow_docks_" + dock->objectName() + "_size";
+}
+
+QString indexSettingName(const QWidget* widget)
+{
+ return widgetNameWithTopLevel(widget) + "_index";
+}
+
+QString checkedSettingName(const QAbstractButton* b)
+{
+ return widgetNameWithTopLevel(b) + "_checked";
+}
+
+void warnIfNotCheckable(const QAbstractButton* b)
+{
+ if (!b->isCheckable()) {
+ log::warn(
+ "button '{}' used in the settings as a checkbox or radio button "
+ "but is not checkable", b->objectName());
+ }
+}
+
+
+bool setWindowsCredential(const QString key, const QString data)
+{
+ QString finalKey("ModOrganizer2_" + key);
+ wchar_t* keyData = new wchar_t[finalKey.size()+1];
+ finalKey.toWCharArray(keyData);
+ keyData[finalKey.size()] = L'\0';
+ bool result = false;
+ if (data.isEmpty()) {
+ result = CredDeleteW(keyData, CRED_TYPE_GENERIC, 0);
+ if (!result)
+ if (GetLastError() == ERROR_NOT_FOUND)
+ result = true;
+ } else {
+ wchar_t* charData = new wchar_t[data.size()];
+ data.toWCharArray(charData);
+
+ CREDENTIALW cred = {};
+ cred.Flags = 0;
+ cred.Type = CRED_TYPE_GENERIC;
+ cred.TargetName = keyData;
+ cred.CredentialBlob = (LPBYTE)charData;
+ cred.CredentialBlobSize = sizeof(wchar_t) * data.size();
+ cred.Persist = CRED_PERSIST_LOCAL_MACHINE;
+
+ result = CredWriteW(&cred, 0);
+ delete[] charData;
+ }
+ delete[] keyData;
+ return result;
+}
+
+QString getWindowsCredential(const QString key)
+{
+ QString result;
+ QString finalKey("ModOrganizer2_" + key);
+ wchar_t* keyData = new wchar_t[finalKey.size()+1];
+ finalKey.toWCharArray(keyData);
+ keyData[finalKey.size()] = L'\0';
+ PCREDENTIALW creds;
+ if (CredReadW(keyData, 1, 0, &creds)) {
+ wchar_t *charData = (wchar_t *)creds->CredentialBlob;
+ result = QString::fromWCharArray(charData, creds->CredentialBlobSize / sizeof(wchar_t));
+ CredFree(creds);
+ } else {
+ const auto e = GetLastError();
+ if (e != ERROR_NOT_FOUND) {
+ log::error("Retrieving encrypted data failed: {}", formatSystemMessage(e));
+ }
+ }
+ delete[] keyData;
+ return result;
+}
diff --git a/src/settingsutilities.h b/src/settingsutilities.h
new file mode 100644
index 00000000..b70e55ef
--- /dev/null
+++ b/src/settingsutilities.h
@@ -0,0 +1,266 @@
+#ifndef SETTINGSUTILITIES_H
+#define SETTINGSUTILITIES_H
+
+#include <log.h>
+
+class ExpanderWidget;
+
+template <class T, class=void>
+struct ValueConverter
+{
+ static const T& convert(const T& t)
+ {
+ return t;
+ }
+};
+
+template <class T>
+struct ValueConverter<T, std::enable_if_t<std::is_enum_v<T>>>
+{
+ static QString convert(const T& t)
+ {
+ return QString("%1").arg(static_cast<std::underlying_type_t<T>>(t));
+ }
+};
+
+
+template <class T>
+void logChange(
+ const QString& displayName, std::optional<T> oldValue, const T& newValue)
+{
+ using VC = ValueConverter<T>;
+
+ if (oldValue) {
+ log::debug(
+ "setting '{}' changed from '{}' to '{}'",
+ displayName, VC::convert(*oldValue), VC::convert(newValue));
+ } else {
+ log::debug(
+ "setting '{}' set to '{}'",
+ displayName, VC::convert(newValue));
+ }
+}
+
+void logRemoval(const QString& name);
+
+
+QString settingName(const QString& section, const QString& key);
+
+template <class T>
+void setImpl(
+ QSettings& settings, const QString& displayName,
+ const QString& section, const QString& key, const T& value)
+{
+ const auto current = getOptional<T>(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<T>) {
+ settings.setValue(
+ name, static_cast<std::underlying_type_t<T>>(value));
+ } else {
+ settings.setValue(name, value);
+ }
+}
+
+void removeImpl(
+ QSettings& settings, const QString& displayName,
+ const QString& section, const QString& key);
+
+
+template <class T>
+std::optional<T> getOptional(
+ const QSettings& settings,
+ const QString& section, const QString& key, std::optional<T> def={})
+{
+ if (settings.contains(settingName(section, key))) {
+ const auto v = settings.value(settingName(section, key));
+
+ if constexpr (std::is_enum_v<T>) {
+ return static_cast<T>(v.value<std::underlying_type_t<T>>());
+ } else {
+ return v.value<T>();
+ }
+ }
+
+ return def;
+}
+
+template <class T>
+T get(
+ const QSettings& settings,
+ const QString& section, const QString& key, T def)
+{
+ if (auto v=getOptional<T>(settings, section, key)) {
+ return *v;
+ } else {
+ return def;
+ }
+}
+
+template <class T>
+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 <class T>
+ 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 <class F>
+ void for_each(F&& f) const
+ {
+ for (const QString& key : keys()) {
+ f(key);
+ }
+ }
+
+ template <class T>
+ std::optional<T> getOptional(const QString& key, std::optional<T> def={}) const
+ {
+ return ::getOptional<T>(m_settings, "", key, def);
+ }
+
+ template <class T>
+ T get(const QString& key, T def={}) const
+ {
+ return ::get<T>(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 <class F>
+ void for_each(F&& f) const
+ {
+ for (int i=0; i<count(); ++i) {
+ m_settings.setArrayIndex(i);
+ f();
+ }
+ }
+
+ template <class T>
+ std::optional<T> getOptional(const QString& key, std::optional<T> def={}) const
+ {
+ return ::getOptional<T>(m_settings, "", key, def);
+ }
+
+ template <class T>
+ T get(const QString& key, T def={}) const
+ {
+ return ::get<T>(m_settings, "", key, def);
+ }
+
+ int count() const;
+ QStringList keys() const;
+
+private:
+ QSettings& m_settings;
+ int m_count;
+};
+
+
+class ScopedWriteArray
+{
+public:
+ ScopedWriteArray(QSettings& s, const QString& section);
+ ~ScopedWriteArray();
+
+ ScopedWriteArray(const ScopedWriteArray&) = delete;
+ ScopedWriteArray& operator=(const ScopedWriteArray&) = delete;
+
+ void next();
+
+ template <class T>
+ 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 ExpanderWidget* w);
+QString widgetName(const QWidget* w);
+
+template <class Widget>
+QString geoSettingName(const Widget* widget)
+{
+ return widgetName(widget) + "_geometry";
+}
+
+template <class Widget>
+QString stateSettingName(const Widget* widget)
+{
+ return widgetName(widget) + "_state";
+}
+
+template <class Widget>
+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