diff options
-rw-r--r-- | gui/init.cpp | 2 | ||||
-rw-r--r-- | gui/process_detector.cpp | 13 | ||||
-rw-r--r-- | gui/settings.cpp | 9 | ||||
-rw-r--r-- | migration/20160906_00-mappings.cpp | 5 | ||||
-rw-r--r-- | migration/20180102_00-process-detector-separator.cpp | 5 | ||||
-rw-r--r-- | migration/migration.cpp | 42 | ||||
-rw-r--r-- | options/base-value.hpp | 82 | ||||
-rw-r--r-- | options/bundle.cpp | 38 | ||||
-rw-r--r-- | options/bundle.hpp | 7 | ||||
-rw-r--r-- | options/connector.cpp | 14 | ||||
-rw-r--r-- | options/defs.hpp | 30 | ||||
-rw-r--r-- | options/globals.cpp | 160 | ||||
-rw-r--r-- | options/globals.hpp | 71 | ||||
-rw-r--r-- | options/group.cpp | 157 | ||||
-rw-r--r-- | options/group.hpp | 113 | ||||
-rw-r--r-- | options/metatype.cpp | 30 | ||||
-rw-r--r-- | options/metatype.hpp | 19 | ||||
-rw-r--r-- | options/options.hpp | 3 | ||||
-rw-r--r-- | options/value-traits.hpp | 16 | ||||
-rw-r--r-- | options/value.hpp | 96 | ||||
-rw-r--r-- | variant/default/main-window.cpp | 60 | ||||
-rw-r--r-- | variant/default/new_file_dialog.cpp | 2 |
22 files changed, 523 insertions, 451 deletions
diff --git a/gui/init.cpp b/gui/init.cpp index 0e9d746a..1a4666b5 100644 --- a/gui/init.cpp +++ b/gui/init.cpp @@ -213,7 +213,7 @@ OTR_GUI_EXPORT int otr_main(int argc, char** argv, std::function<QWidget*()> con qDebug() << "locale:" << forced_locale; } - const bool no_i18n = group::with_global_settings_object([](QSettings& s) { + const bool no_i18n = options::globals::with_global_settings_object([](QSettings& s) { return s.value("disable-translation", false).toBool(); }); diff --git a/gui/process_detector.cpp b/gui/process_detector.cpp index 969b1856..0ff05f93 100644 --- a/gui/process_detector.cpp +++ b/gui/process_detector.cpp @@ -24,31 +24,32 @@ static constexpr inline auto RECORD_SEPARATOR = QChar(char(0x1e)); // RS ^] static constexpr inline auto UNIT_SEPARATOR = QChar(char(0x1f)); // US ^_ using namespace options; +using namespace options::globals; void proc_detector_settings::set_game_list(const QString &game_list) { - group::with_global_settings_object([&](QSettings& settings) { + with_global_settings_object([&](QSettings& settings) { settings.setValue("executable-list", game_list); }); } QString proc_detector_settings::get_game_list() { - return group::with_global_settings_object([&](QSettings& settings) { + return with_global_settings_object([&](QSettings& settings) { return settings.value("executable-list").toString(); }); } bool proc_detector_settings::is_enabled() { - return group::with_global_settings_object([&](QSettings& settings) { + return with_global_settings_object([&](QSettings& settings) { return settings.value("executable-detector-enabled", false).toBool(); }); } void proc_detector_settings::set_is_enabled(bool enabled) { - group::with_global_settings_object([&](QSettings& settings) { + with_global_settings_object([&](QSettings& settings) { settings.setValue("executable-detector-enabled", enabled); }); } @@ -76,7 +77,7 @@ QHash<QString, QString> proc_detector_settings::split_process_names() void BrowseButton::browse() { - QString dir_path = QFileInfo(group::ini_pathname()).absolutePath(); + QString dir_path = QFileInfo(ini_pathname()).absolutePath(); QString filename = QFileDialog::getOpenFileName( this, tr("Set executable name"), @@ -96,7 +97,7 @@ int process_detector::add_row(QString const& exe_name, QString const& profile) QComboBox* cb = new QComboBox(); cb->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Maximum); cb->addItem(""); - cb->addItems(group::ini_list()); + cb->addItems(ini_list()); ui.tableWidget->setCellWidget(i, 1, cb); QTableWidgetItem* twi = new QTableWidgetItem(exe_name); diff --git a/gui/settings.cpp b/gui/settings.cpp index 31bbd87b..5ee59260 100644 --- a/gui/settings.cpp +++ b/gui/settings.cpp @@ -18,10 +18,11 @@ #include <QFileDialog> using namespace options; +using namespace options::globals; QString options_dialog::kopts_to_string(const key_opts& kopts) { - if (static_cast<QString>(kopts.guid) != "") + if (!kopts.guid->isEmpty()) { const int btn = kopts.button & ~Qt::KeyboardModifierMask; const int mods = kopts.button & Qt::KeyboardModifierMask; @@ -31,14 +32,14 @@ QString options_dialog::kopts_to_string(const key_opts& kopts) if (mods & Qt::ShiftModifier) mm += "Shift+"; return mm + tr("Joy button %1").arg(QString::number(btn)); } - if (static_cast<QString>(kopts.keycode) == "") + if (kopts.keycode->isEmpty()) return tr("None"); return kopts.keycode; } void options_dialog::set_disable_translation_state(bool value) { - group::with_global_settings_object([&](QSettings& s) + with_global_settings_object([&](QSettings& s) { s.setValue("disable-translation", value); }); @@ -105,7 +106,7 @@ options_dialog::options_dialog(std::function<void(bool)>&& pause_keybindings) : tie_setting(main.neck_enable, ui.neck_enable); - const bool is_translation_disabled = group::with_global_settings_object([] (QSettings& s) { + const bool is_translation_disabled = with_global_settings_object([] (QSettings& s) { return s.value("disable-translation", false).toBool(); }); ui.disable_translation->setChecked(is_translation_disabled); diff --git a/migration/20160906_00-mappings.cpp b/migration/20160906_00-mappings.cpp index 0019d0ef..f94f8290 100644 --- a/migration/20160906_00-mappings.cpp +++ b/migration/20160906_00-mappings.cpp @@ -19,6 +19,7 @@ #include <QDebug> using namespace options; +using namespace options::globals; using namespace migrations; static const char* const old_names[] = @@ -44,7 +45,7 @@ static QList<QList<QPointF>> get_old_splines() { QList<QList<QPointF>> ret; - return group::with_settings_object([&](QSettings& settings) { + return with_settings_object([&](QSettings& settings) { for (const char* name : old_names) { const int max = settings.value("point-count", 0).toInt(); @@ -96,7 +97,7 @@ struct mappings_from_2_3_0_rc11 : migration void run() override { - group::with_settings_object([this](QSettings&) { + with_settings_object([](QSettings&) { const QList<QList<QPointF>> old_mappings = get_old_splines(); for (int i = 0; i < 12; i++) diff --git a/migration/20180102_00-process-detector-separator.cpp b/migration/20180102_00-process-detector-separator.cpp index ddb01cb4..6c3a2b58 100644 --- a/migration/20180102_00-process-detector-separator.cpp +++ b/migration/20180102_00-process-detector-separator.cpp @@ -2,6 +2,7 @@ #include "options/options.hpp" using namespace options; +using namespace options::globals; using namespace migrations; static constexpr auto OLD_RECORD_SEPARATOR = QChar('|'); @@ -26,7 +27,7 @@ struct process_detector_record_separator : migration bool should_run() const override { - return group::with_global_settings_object([](const QSettings& s) + return with_global_settings_object([](const QSettings& s) { const QString old_value = s.value(KEY_NAME).toString(); return old_value.contains(OLD_RECORD_SEPARATOR); @@ -35,7 +36,7 @@ struct process_detector_record_separator : migration void run() override { - return group::with_global_settings_object([](QSettings& s) + return with_global_settings_object([](QSettings& s) { QString value = s.value(KEY_NAME).toString(); value.replace(OLD_UNIT_SEPARATOR, NEW_UNIT_SEPARATOR); diff --git a/migration/migration.cpp b/migration/migration.cpp index 8e5fea5e..386fde9b 100644 --- a/migration/migration.cpp +++ b/migration/migration.cpp @@ -20,6 +20,8 @@ #include <memory> +using namespace options::globals; + // individual migrations are run in the UI thread. they can be interactive if necessary. namespace migrations { @@ -105,7 +107,7 @@ QString migrator::last_migration_time() { QString ret; - options::group::with_settings_object([&](QSettings& s) { + with_settings_object([&](QSettings& s) { s.beginGroup("migrations"); ret = s.value("last-migration-at", "19700101_00").toString(); s.endGroup(); @@ -129,13 +131,13 @@ QString migrator::time_after_migrations() void migrator::set_last_migration_time(const QString& val) { - options::group::with_settings_object([&](QSettings& s) { + with_settings_object([&](QSettings& s) { s.beginGroup("migrations"); const QString old_value = s.value("last-migration-at", "").toString(); if (val != old_value) { s.setValue("last-migration-at", val); - options::group::mark_ini_modified(); + mark_ini_modified(); } s.endGroup(); }); @@ -155,26 +157,24 @@ std::vector<QString> migrator::run() const QString last_migration = last_migration_time(); - options::group::with_global_settings_object([&](QSettings&) { - options::group::with_settings_object([&](QSettings&) { - for (mptr m : migrations()) + with_global_settings_object([&](QSettings&) { + for (mptr const& m : migrations()) + { + const QString date = m->unique_date(); + + if (date <= last_migration) + continue; + + if (m->should_run()) { - const QString date = m->unique_date(); - - if (date <= last_migration) - continue; - - if (m->should_run()) - { - const QByteArray name = m->name().toUtf8(); - const QByteArray date = m->unique_date().toUtf8(); - qDebug() << "migrate:" << date.constData() << name.constData(); - m->run(); - done.push_back(m->name()); - } + const QByteArray name = m->name().toUtf8(); + const QByteArray date = m->unique_date().toUtf8(); + qDebug() << "migrate:" << date.constData() << name.constData(); + m->run(); + done.push_back(m->name()); } - mark_config_as_not_needing_migration(); - }); + } + mark_config_as_not_needing_migration(); }); return done; diff --git a/options/base-value.hpp b/options/base-value.hpp index 5b924ab3..750f93f1 100644 --- a/options/base-value.hpp +++ b/options/base-value.hpp @@ -7,6 +7,7 @@ #include "export.hpp" #include "compat/macros.hpp" +#include "value-traits.hpp" #include <QObject> #include <QString> @@ -15,9 +16,10 @@ #include <QVariant> #include <typeindex> +#include <utility> -#define OPENTRACK_DEFINE_SLOT(t) void setValue(t datum) { store(datum); } -#define OPENTRACK_DEFINE_SIGNAL(t) void valueChanged(t) const +#define OTR_OPTIONS_SLOT(t) void setValue(t datum) { store_(datum); } +#define OTR_OPTIONS_SIGNAL(t) void valueChanged(t) const namespace options { @@ -32,15 +34,13 @@ class OTR_OPTIONS_EXPORT value_ : public QObject using signal_sig = void(value_::*)(cv_qualified<t>) const; public: - bundle get_bundle() { return b; } QString name() const { return self_name; } - value_(bundle b, const QString& name, comparator cmp, std::type_index type_idx); + value_(bundle const& b, const QString& name, comparator cmp, std::type_index type_idx); ~value_() override; - // MSVC has ODR problems in 15.4 // no C++17 "constexpr inline" for data declarations in MSVC template<typename t> - constexpr static auto value_changed() + static constexpr auto value_changed() { return static_cast<signal_sig<t>>(&value_::valueChanged); } @@ -48,22 +48,22 @@ public: void notify() const; signals: - OPENTRACK_DEFINE_SIGNAL(double); - OPENTRACK_DEFINE_SIGNAL(float); - OPENTRACK_DEFINE_SIGNAL(int); - OPENTRACK_DEFINE_SIGNAL(bool); - OPENTRACK_DEFINE_SIGNAL(const QString&); - OPENTRACK_DEFINE_SIGNAL(const slider_value&); - OPENTRACK_DEFINE_SIGNAL(const QPointF&); - OPENTRACK_DEFINE_SIGNAL(const QVariant&); - - OPENTRACK_DEFINE_SIGNAL(const QList<double>&); - OPENTRACK_DEFINE_SIGNAL(const QList<float>&); - OPENTRACK_DEFINE_SIGNAL(const QList<int>&); - OPENTRACK_DEFINE_SIGNAL(const QList<bool>&); - OPENTRACK_DEFINE_SIGNAL(const QList<QString>&); - OPENTRACK_DEFINE_SIGNAL(const QList<slider_value>&); - OPENTRACK_DEFINE_SIGNAL(const QList<QPointF>&); + OTR_OPTIONS_SIGNAL(double); + OTR_OPTIONS_SIGNAL(float); + OTR_OPTIONS_SIGNAL(int); + OTR_OPTIONS_SIGNAL(bool); + OTR_OPTIONS_SIGNAL(const QString&); + OTR_OPTIONS_SIGNAL(const slider_value&); + OTR_OPTIONS_SIGNAL(const QPointF&); + OTR_OPTIONS_SIGNAL(const QVariant&); + + OTR_OPTIONS_SIGNAL(const QList<double>&); + OTR_OPTIONS_SIGNAL(const QList<float>&); + OTR_OPTIONS_SIGNAL(const QList<int>&); + OTR_OPTIONS_SIGNAL(const QList<bool>&); + OTR_OPTIONS_SIGNAL(const QList<QString>&); + OTR_OPTIONS_SIGNAL(const QList<slider_value>&); + OTR_OPTIONS_SIGNAL(const QList<QPointF>&); protected: bundle b; @@ -71,30 +71,32 @@ protected: comparator cmp; std::type_index type_index; - void store(const QVariant& datum); + virtual void store_variant(const QVariant& x) = 0; template<typename t> - void store(const t& datum) + void store_(const t& datum) { - b->store_kv(self_name, QVariant::fromValue(datum)); + using traits = detail::value_traits<t>; + using stored_type = typename traits::stored_type; + store_variant(QVariant::fromValue<stored_type>(datum)); } public slots: - OPENTRACK_DEFINE_SLOT(double) - OPENTRACK_DEFINE_SLOT(int) - OPENTRACK_DEFINE_SLOT(bool) - OPENTRACK_DEFINE_SLOT(const QString&) - OPENTRACK_DEFINE_SLOT(const slider_value&) - OPENTRACK_DEFINE_SLOT(const QPointF&) - OPENTRACK_DEFINE_SLOT(const QVariant&) - - OPENTRACK_DEFINE_SLOT(const QList<double>&) - OPENTRACK_DEFINE_SLOT(const QList<float>&) - OPENTRACK_DEFINE_SLOT(const QList<int>&) - OPENTRACK_DEFINE_SLOT(const QList<bool>&) - OPENTRACK_DEFINE_SLOT(const QList<QString>&) - OPENTRACK_DEFINE_SLOT(const QList<slider_value>&) - OPENTRACK_DEFINE_SLOT(const QList<QPointF>&) + OTR_OPTIONS_SLOT(double) + OTR_OPTIONS_SLOT(int) + OTR_OPTIONS_SLOT(bool) + OTR_OPTIONS_SLOT(const QString&) + OTR_OPTIONS_SLOT(const slider_value&) + OTR_OPTIONS_SLOT(const QPointF&) + OTR_OPTIONS_SLOT(const QVariant&) + + OTR_OPTIONS_SLOT(const QList<double>&) + OTR_OPTIONS_SLOT(const QList<float>&) + OTR_OPTIONS_SLOT(const QList<int>&) + OTR_OPTIONS_SLOT(const QList<bool>&) + OTR_OPTIONS_SLOT(const QList<QString>&) + OTR_OPTIONS_SLOT(const QList<slider_value>&) + OTR_OPTIONS_SLOT(const QList<QPointF>&) virtual void reload() = 0; virtual void bundle_value_changed() const = 0; diff --git a/options/bundle.cpp b/options/bundle.cpp index b722338b..c426dd2e 100644 --- a/options/bundle.cpp +++ b/options/bundle.cpp @@ -8,11 +8,13 @@ #include "bundle.hpp" #include "value.hpp" +#include "globals.hpp" #include <QThread> #include <QApplication> -using options::value_; +using namespace options; +using namespace options::globals; namespace options::detail { @@ -24,9 +26,7 @@ bundle::bundle(const QString& group_name) { } -bundle::~bundle() -{ -} +bundle::~bundle() = default; void bundle::reload() { @@ -53,19 +53,23 @@ void bundle::set_all_to_default() forall([](const QString&, value_* val) { set_base_value_to_default(val); }); if (is_modified()) - group::mark_ini_modified(); + mark_ini_modified(); } -void bundle::store_kv(const QString& name, const QVariant& datum) +void bundle::store_kv(const QString& name, const QVariant& new_value) { QMutexLocker l(&mtx); - transient.put(name, datum); - - if (group_name.size()) - connector::notify_values(name); - - emit changed(); + if (!group_name.isEmpty()) + { + const QVariant old_value = transient.get_variant(name); + if (!connector::is_equal(name, old_value, new_value)) + { + transient.put(name, new_value); + connector::notify_values(name); + emit changed(); + } + } } bool bundle::contains(const QString &name) const @@ -152,14 +156,8 @@ void bundler::refresh_all_bundles() bundler_singleton().after_profile_changed_(); } -bundler::bundler() : implsgl_mtx(QMutex::Recursive) -{ -} - -bundler::~bundler() -{ - //qDebug() << "exit: bundle singleton"; -} +bundler::bundler() = default; +bundler::~bundler() = default; std::shared_ptr<bundler::v> bundler::make_bundle_(const bundler::k& key) { diff --git a/options/bundle.hpp b/options/bundle.hpp index a12a335c..98291fc5 100644 --- a/options/bundle.hpp +++ b/options/bundle.hpp @@ -48,7 +48,7 @@ class OTR_OPTIONS_EXPORT bundle final : public QObject, public connector class OTR_OPTIONS_EXPORT mutex final : public QMutex { public: - mutex(QMutex::RecursionMode mode) : QMutex(mode) {} + explicit mutex(QMutex::RecursionMode mode) : QMutex(mode) {} operator QMutex*() const { return const_cast<QMutex*>(static_cast<const QMutex*>(this)); } }; @@ -70,7 +70,7 @@ public: bundle& operator=(const bundle&) = delete; QMutex* get_mtx() const override; - cc_noinline bundle(const QString& group_name); + cc_noinline explicit bundle(const QString& group_name); cc_noinline ~bundle() override; QString name() const { return group_name; } cc_noinline void store_kv(const QString& name, const QVariant& datum); @@ -83,6 +83,7 @@ public: QMutexLocker l(mtx); return transient.get<t>(name); } + public slots: void save(); void reload(); @@ -97,7 +98,7 @@ struct OTR_OPTIONS_EXPORT bundler final using shared = std::shared_ptr<v>; private: - QMutex implsgl_mtx; + QMutex implsgl_mtx { QMutex::Recursive }; std::map<k, weak> implsgl_data; void after_profile_changed_(); diff --git a/options/connector.cpp b/options/connector.cpp index 0efac8f1..73aefed8 100644 --- a/options/connector.cpp +++ b/options/connector.cpp @@ -18,7 +18,7 @@ static bool generic_is_equal(const QVariant& val1, const QVariant& val2) return val1 == val2; } -connector::~connector() {} +connector::~connector() = default; bool connector::is_equal(const QString& name, const QVariant& val1, const QVariant& val2) const { @@ -109,23 +109,17 @@ void connector::notify_values(const QString& name) const { auto it = connected_values.find(name); if (it != connected_values.cend()) - { for (value_type val : std::get<0>((*it).second)) - { val->bundle_value_changed(); - } - } } void connector::notify_all_values() const { - for (auto& pair : connected_values) - for (value_type val : std::get<0>(pair.second)) + for (auto& [k, v] : connected_values) + for (value_type val : std::get<0>(v)) val->bundle_value_changed(); } -connector::connector() -{ -} +connector::connector() = default; } // ns options::detail diff --git a/options/defs.hpp b/options/defs.hpp index 2467a7a0..a71a56e2 100644 --- a/options/defs.hpp +++ b/options/defs.hpp @@ -7,35 +7,5 @@ #define OPENTRACK_CONFIG_FILENAME_KEY "settings-filename" #define OPENTRACK_DEFAULT_CONFIG "default.ini" -#define OTR_OPTIONS_EXPAND2(x) x -#define OTR_OPTIONS_EXPAND1(x) OTR_OPTIONS_EXPAND2(x) -#define OPENTRACK_DEFINE_METATYPE2(t, ctr) \ - OPENTRACK_DEFINE_METATYPE3(t, ctr) - -#define OPENTRACK_DEFINE_METATYPE3(t, ctr) \ - OPENTRACK_DEFINE_METATYPE4(t, init_metatype_ ## ctr) - -#define OPENTRACK_DEFINE_METATYPE4(t, sym) \ - static class sym { \ - static const int dribble; \ - } sym ## _singleton; \ - const int sym :: dribble = ::options::detail::custom_type_initializer::declare_for_type<t>(#t); - -#define OPENTRACK_DEFINE_METATYPE(t) OPENTRACK_DEFINE_METATYPE2(t, __COUNTER__) - -namespace options::detail { - -struct custom_type_initializer final -{ - template<typename t> static int declare_for_type(const char* str) - { - qRegisterMetaType<t>(str); - qRegisterMetaTypeStreamOperators<t>(); - - return -1; - } -}; - -} // ns options::detail diff --git a/options/globals.cpp b/options/globals.cpp new file mode 100644 index 00000000..85a6bdf2 --- /dev/null +++ b/options/globals.cpp @@ -0,0 +1,160 @@ +#include "globals.hpp" +#include "compat/base-path.hpp" +#include "defs.hpp" + +#include <QFile> +#include <QDir> +#include <QStandardPaths> +#include <QDebug> + +namespace options::globals::detail { + +bool is_portable_installation() +{ +#if defined _WIN32 + // must keep consistent between invocations + static const bool ret = QFile::exists(OPENTRACK_BASE_PATH + "/portable.txt"); + return ret; +#endif + return false; +} + +saver_::~saver_() +{ + if (--ctx.refcount == 0 && ctx.modifiedp) + { + ctx.modifiedp = false; + auto& settings = *ctx.qsettings; + settings.sync(); + if (settings.status() != QSettings::NoError) + qDebug() << "error with .ini file" << settings.fileName() << settings.status(); + } + ctx.mtx.unlock(); +} + +saver_::saver_(ini_ctx& ini) : ctx { ini } +{ + ctx.refcount++; +} + +ini_ctx& cur_settings() +{ + static ini_ctx ini; + const QString pathname = ini_pathname(); + static QString ini_pathname; + + ini.mtx.lock(); + + if (pathname.isEmpty()) + { + ini.qsettings.emplace(); + ini.pathname = pathname; + } + + if (pathname != ini_pathname) + { + ini.qsettings.emplace(pathname, QSettings::IniFormat); + ini.pathname = pathname; + } + + return ini; +} + +ini_ctx& global_settings() +{ + static ini_ctx ini; + + ini.mtx.lock(); + + if (!is_portable_installation()) + // Windows registry or xdg on Linux + ini.qsettings.emplace(OPENTRACK_ORG); + else + { + static const QString pathname = OPENTRACK_BASE_PATH + QStringLiteral("/globals.ini"); + // file in executable's directory + ini.qsettings.emplace(pathname, QSettings::IniFormat); + ini.pathname = pathname; + } + + return ini; +} + +} // ns options::globals::detail + +namespace options::globals +{ + +QString ini_filename() +{ + return with_global_settings_object([&](QSettings& settings) { + const QString ret = settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); + if (ret.size() == 0) + return QStringLiteral(OPENTRACK_DEFAULT_CONFIG); + return ret; + }); +} + +QString ini_pathname() +{ + const auto dir = ini_directory(); + if (dir.isEmpty()) + return {}; + return dir + "/" + ini_filename(); +} + +QString ini_combine(const QString& filename) +{ + return ini_directory() + QStringLiteral("/") + filename; +} + +QStringList ini_list() +{ + const auto dirname = ini_directory(); + if (dirname == "") + return QStringList(); + QDir settings_dir(dirname); + QStringList list = settings_dir.entryList( QStringList { "*.ini" } , QDir::Files, QDir::Name ); + std::sort(list.begin(), list.end()); + return list; +} + +void mark_ini_modified() +{ + using namespace detail; + auto& ini = cur_settings(); + ini.modifiedp = true; + ini.mtx.unlock(); +} + +QString ini_directory() +{ + QString dir; + + if (detail::is_portable_installation()) + { + dir = OPENTRACK_BASE_PATH; + + static const QString subdir = "ini"; + + if (!QDir(dir).mkpath(subdir)) + return QString(); + + return dir + '/' + subdir; + } + else + { + dir = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation).value(0, QString()); + if (dir.isEmpty()) + return QString(); + if (!QDir(dir).mkpath(OPENTRACK_ORG)) + return QString(); + + dir += '/'; + dir += OPENTRACK_ORG; + } + + return dir; +} + +} // ns options::globals diff --git a/options/globals.hpp b/options/globals.hpp new file mode 100644 index 00000000..4d74cbf0 --- /dev/null +++ b/options/globals.hpp @@ -0,0 +1,71 @@ +#pragma once + +#include "export.hpp" +#include "compat/macros.hpp" + +#include <optional> + +#include <QString> +#include <QSettings> +#include <QMutex> + +namespace options::globals::detail { + +struct ini_ctx; +struct saver_; + +OTR_OPTIONS_EXPORT ini_ctx& cur_settings(); +OTR_OPTIONS_EXPORT ini_ctx& global_settings(); +OTR_OPTIONS_EXPORT bool is_portable_installation(); + +struct ini_ctx +{ + std::optional<QSettings> qsettings { std::in_place }; + int refcount = 0; + bool modifiedp = false; + QMutex mtx { QMutex::Recursive }; + QString pathname; +}; + +struct OTR_OPTIONS_EXPORT saver_ final +{ + ini_ctx& ctx; + + cc_noinline ~saver_(); + explicit cc_noinline saver_(ini_ctx& ini); +}; + +template<typename F> +cc_noinline +auto with_settings_object_(ini_ctx& ini, F&& fun) +{ + saver_ saver { ini }; + + return fun(*ini.qsettings); +} + +} // ns options::globals::detail + +namespace options::globals +{ + OTR_OPTIONS_EXPORT void mark_ini_modified(); + OTR_OPTIONS_EXPORT QString ini_directory(); + OTR_OPTIONS_EXPORT QString ini_filename(); + OTR_OPTIONS_EXPORT QString ini_pathname(); + OTR_OPTIONS_EXPORT QString ini_combine(const QString& filename); + OTR_OPTIONS_EXPORT QStringList ini_list(); + + template<typename F> + auto with_settings_object(F&& fun) + { + using namespace detail; + return with_settings_object_(cur_settings(), fun); + } + + template<typename F> + auto with_global_settings_object(F&& fun) + { + using namespace detail; + return with_settings_object_(global_settings(), fun); + } +} // ns options::globals diff --git a/options/group.cpp b/options/group.cpp index 788dd5de..5f6c3232 100644 --- a/options/group.cpp +++ b/options/group.cpp @@ -8,18 +8,19 @@ #include "group.hpp" #include "defs.hpp" +#include "globals.hpp" -#include "compat/timer.hpp" -#include "compat/library-path.hpp" - -#include <cmath> +#include <utility> +#include <algorithm> #include <QFile> -#include <QStandardPaths> + #include <QDir> #include <QDebug> -namespace options { +namespace options::detail { + +using namespace options::globals; group::group(const QString& name) : name(name) { @@ -66,146 +67,14 @@ bool group::contains(const QString &s) const return it != kvs.cend() && it->second != QVariant::Invalid; } -bool group::is_portable_installation() -{ -#if defined _WIN32 - return QFile::exists(OPENTRACK_BASE_PATH + "/portable.txt"); -#endif - return false; -} - -QString group::ini_directory() +QVariant group::get_variant(const QString& name) const { + auto it = kvs.find(name); + if (it != kvs.cend()) + return it->second; - QString dir; - - if (is_portable_installation()) - { - dir = OPENTRACK_BASE_PATH; - - static const QString subdir = "ini"; - - if (!QDir(dir).mkpath(subdir)) - return QString(); - - return dir + '/' + subdir; - } - else - { - dir = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation).value(0, QString()); - if (dir.isEmpty()) - return QString(); - if (!QDir(dir).mkpath(OPENTRACK_ORG)) - return QString(); - - dir += '/'; - dir += OPENTRACK_ORG; - } - - return dir; + return {}; } -QString group::ini_filename() -{ - return with_global_settings_object([&](QSettings& settings) { - const QString ret = settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); - if (ret.size() == 0) - return QStringLiteral(OPENTRACK_DEFAULT_CONFIG); - return ret; - }); -} - -QString group::ini_pathname() -{ - const auto dir = ini_directory(); - if (dir == "") - return ""; - return dir + "/" + ini_filename(); -} - -QString group::ini_combine(const QString& filename) -{ - return ini_directory() + QStringLiteral("/") + filename; -} - -QStringList group::ini_list() -{ - const auto dirname = ini_directory(); - if (dirname == "") - return QStringList(); - QDir settings_dir(dirname); - QStringList list = settings_dir.entryList( QStringList { "*.ini" } , QDir::Files, QDir::Name ); - std::sort(list.begin(), list.end()); - return list; -} - -void group::mark_ini_modified() -{ - QMutexLocker l(&cur_ini_mtx); - ini_modifiedp = true; -} - -QString group::cur_ini_pathname; - -std::shared_ptr<QSettings> group::cur_ini; -QMutex group::cur_ini_mtx(QMutex::Recursive); -int group::ini_refcount = 0; -bool group::ini_modifiedp = false; - -std::shared_ptr<QSettings> group::cur_global_ini; -QMutex group::global_ini_mtx(QMutex::Recursive); -int group::global_ini_refcount = 0; -bool group::global_ini_modifiedp = false; - -std::shared_ptr<QSettings> group::cur_settings_object() -{ - const QString pathname = ini_pathname(); - - if (pathname.isEmpty()) - return std::make_shared<QSettings>(); - - if (pathname != cur_ini_pathname) - { - cur_ini = std::make_shared<QSettings>(pathname, QSettings::IniFormat); - cur_ini_pathname = pathname; - } - - return cur_ini; -} - -std::shared_ptr<QSettings> group::cur_global_settings_object() -{ - if (cur_global_ini) - return cur_global_ini; - - if (!is_portable_installation()) - cur_global_ini = std::make_shared<QSettings>(OPENTRACK_ORG); - else - { - static const QString pathname = OPENTRACK_BASE_PATH + QStringLiteral("/globals.ini"); - cur_global_ini = std::make_shared<QSettings>(pathname, QSettings::IniFormat); - } - - return cur_global_ini; -} - -cc_noinline -group::saver_::~saver_() -{ - if (--refcount == 0 && modifiedp) - { - modifiedp = false; - s.sync(); - if (s.status() != QSettings::NoError) - qDebug() << "error with .ini file" << s.fileName() << s.status(); - } -} - -cc_noinline -group::saver_::saver_(QSettings& s, int& refcount, bool& modifiedp) : - s(s), refcount(refcount), modifiedp(modifiedp) -{ - refcount++; -} +} // ns options::detail -} // ns options diff --git a/options/group.hpp b/options/group.hpp index f191fdd5..ef9f1121 100644 --- a/options/group.hpp +++ b/options/group.hpp @@ -1,96 +1,49 @@ #pragma once +#include "options/defs.hpp" + +#include "compat/base-path.hpp" +#include "compat/library-path.hpp" +#include "compat/qhash.hpp" #include "compat/macros.hpp" #include "export.hpp" -// included here to propagate into callers of options::group -#include "metatype.hpp" +#include <optional> +#include <unordered_map> -#include <map> -#include <memory> +#include <QHash> #include <QString> -#include <QList> +#include <QMutex> +#include <QFile> +#include <QDir> +#include <QStandardPaths> #include <QVariant> #include <QSettings> -#include <QMutex> +#include <QDebug> // XXX TODO remove qsettings usage -sh 20180624 -namespace options { - -// snapshot of qsettings group at given time -class OTR_OPTIONS_EXPORT group final -{ - QString name; - - static QString cur_ini_pathname; - - static std::shared_ptr<QSettings> cur_ini; - static int ini_refcount; - static bool ini_modifiedp; - static QMutex cur_ini_mtx; - - static std::shared_ptr<QSettings> cur_global_ini; - static int global_ini_refcount; - static bool global_ini_modifiedp; - static QMutex global_ini_mtx; - - struct OTR_OPTIONS_EXPORT saver_ final +namespace options::detail { + // snapshot of qsettings group at given time + class OTR_OPTIONS_EXPORT group final { - QSettings& s; - int& refcount; - bool& modifiedp; - - cc_noinline ~saver_(); - cc_noinline saver_(QSettings& s, int& refcount, bool& modifiedp); + QString name; + + public: + std::unordered_map<QString, QVariant> kvs; + explicit group(const QString& name); + void save() const; + void put(const QString& s, const QVariant& d); + bool contains(const QString& s) const; + + template<typename t> + cc_noinline t get(const QString& k) const + { + return get_variant(k).value<t>(); + } + + cc_noinline QVariant get_variant(const QString& name) const; }; - static std::shared_ptr<QSettings> cur_settings_object(); - static std::shared_ptr<QSettings> cur_global_settings_object(); - -public: - std::map<QString, QVariant> kvs; - group(const QString& name); - void save() const; - void put(const QString& s, const QVariant& d); - bool contains(const QString& s) const; - static QString ini_directory(); - static QString ini_filename(); - static QString ini_pathname(); - static QString ini_combine(const QString& filename); - static QStringList ini_list(); - static bool is_portable_installation(); - - static void mark_ini_modified(); - - template<typename t> - cc_noinline - t get(const QString& k) const - { - auto value = kvs.find(k); - if (value != kvs.cend()) - return value->second.value<t>(); - return t(); - } - - template<typename F> - cc_noinline - static auto with_settings_object(F&& fun) - { - QMutexLocker l(&cur_ini_mtx); - saver_ saver { *cur_settings_object(), ini_refcount, ini_modifiedp }; - - return fun(saver.s); - } - - template<typename F> - static auto with_global_settings_object(F&& fun) - { - QMutexLocker l(&global_ini_mtx); - saver_ saver { *cur_global_settings_object(), global_ini_refcount, global_ini_modifiedp }; - global_ini_modifiedp = true; +} // ns options::detail - return fun(saver.s); - } -}; -} diff --git a/options/metatype.cpp b/options/metatype.cpp index 0fa33933..e54970c0 100644 --- a/options/metatype.cpp +++ b/options/metatype.cpp @@ -1,3 +1,31 @@ -#include "defs.hpp" +#include <QMetaType> + +namespace options::detail { + +template<typename t> +int declare_metatype_for_type(const char* str) +{ + qRegisterMetaType<t>(str); + qRegisterMetaTypeStreamOperators<t>(); + + return -1; +} + +} // ns options::detail + +#define OPENTRACK_DEFINE_METATYPE2(t, ctr) \ + OPENTRACK_DEFINE_METATYPE3(t, ctr) + +#define OPENTRACK_DEFINE_METATYPE3(t, ctr) \ + OPENTRACK_DEFINE_METATYPE4(t, init_metatype_ ## ctr) + +#define OPENTRACK_DEFINE_METATYPE4(t, sym) \ + static class sym { \ + static const int dribble; \ + } sym ## _singleton; \ + const int sym :: dribble = ::options::detail::declare_metatype_for_type<t>(#t) + +#define OPENTRACK_DEFINE_METATYPE(t) OPENTRACK_DEFINE_METATYPE2(t, __COUNTER__) + #define OPENTRACK_METATYPE_(x) OPENTRACK_DEFINE_METATYPE(x) #include "metatype.hpp" diff --git a/options/metatype.hpp b/options/metatype.hpp index 023c1a36..9d3cbda1 100644 --- a/options/metatype.hpp +++ b/options/metatype.hpp @@ -7,6 +7,7 @@ #include "slider.hpp" #include "defs.hpp" +#include <QMetaType> #ifndef OPENTRACK_METATYPE_ # define OPENTRACK_METATYPE(x) Q_DECLARE_METATYPE(x) @@ -14,12 +15,12 @@ # define OPENTRACK_METATYPE(x) Q_DECLARE_METATYPE(x) OPENTRACK_METATYPE_(x) #endif -OPENTRACK_METATYPE(QList<double>) -OPENTRACK_METATYPE(QList<float>) -OPENTRACK_METATYPE(QList<int>) -OPENTRACK_METATYPE(QList<bool>) -OPENTRACK_METATYPE(QList<QString>) -OPENTRACK_METATYPE(QList<QPointF>) -OPENTRACK_METATYPE(::options::slider_value) - - +#if !defined __clang_analyzer__ && !defined Q_CREATOR_RUN +OPENTRACK_METATYPE(QList<double>); +OPENTRACK_METATYPE(QList<float>); +OPENTRACK_METATYPE(QList<int>); +OPENTRACK_METATYPE(QList<bool>); +OPENTRACK_METATYPE(QList<QString>); +OPENTRACK_METATYPE(QList<QPointF>); +OPENTRACK_METATYPE(::options::slider_value); +#endif diff --git a/options/options.hpp b/options/options.hpp index bc892120..a99d5c59 100644 --- a/options/options.hpp +++ b/options/options.hpp @@ -8,9 +8,8 @@ #include "defs.hpp" #include "bundle.hpp" -#include "group.hpp" #include "slider.hpp" #include "value.hpp" #include "tie.hpp" -#include "metatype.hpp" #include "scoped.hpp" +#include "globals.hpp" diff --git a/options/value-traits.hpp b/options/value-traits.hpp index b507874c..1c98f3e9 100644 --- a/options/value-traits.hpp +++ b/options/value-traits.hpp @@ -18,9 +18,19 @@ struct default_value_traits using stored_type = std::decay_t<t>; using value_type = std::decay_t<u>; - static inline value_type from_value(const value_type& val, const value_type&) { return val; } - static inline value_type from_storage(const stored_type& x) { return static_cast<value_type>(x); } - static inline stored_type to_storage(const value_type& val) { return static_cast<stored_type>(val); } + static value_type from_value(const value_type& val, const value_type&) { return val; } + static value_type from_storage(const stored_type& x) { return static_cast<value_type>(x); } + static stored_type to_storage(const value_type& val) { return static_cast<stored_type>(val); } + + static value_type value_from_variant(const QVariant& x) + { + return from_storage(storage_from_variant(x)); + } + + static stored_type storage_from_variant(const QVariant& x) + { + return x.value<stored_type>(); + } }; template<typename t, typename u = t, typename Enable = void> diff --git a/options/value.hpp b/options/value.hpp index e73456ca..af3cfd57 100644 --- a/options/value.hpp +++ b/options/value.hpp @@ -16,24 +16,19 @@ #include "value-traits.hpp" #include "compat/macros.hpp" -#include <cstdio> #include <type_traits> #include <typeinfo> -#include <typeindex> -#include <utility> -#include <QVariant> -#include <QString> -#include <QPointF> -#include <QList> -#include <QMutex> +#include <QMetaType> namespace options { template<typename t> class value final : public value_ { - using traits = detail::value_traits<t, t, void>; + const t def; + + using traits = detail::value_traits<t>; using stored_type = typename traits::stored_type; static bool is_equal(const QVariant& val1, const QVariant& val2) @@ -52,22 +47,40 @@ class value final : public value_ if (!b->contains(self_name) || variant.type() == QVariant::Invalid) return def; - const stored_type x(variant.value<stored_type>()); + const stored_type x { variant.value<stored_type>() }; return traits::from_value(traits::from_storage(x), def); } + friend class detail::connector; + void bundle_value_changed() const override + { + if (!self_name.isEmpty()) + emit valueChanged(traits::to_storage(get())); + } + + void store_variant(const QVariant& value) override + { + if (self_name.isEmpty()) + return; + + if (value.type() == qMetaTypeId<stored_type>()) + b->store_kv(self_name, value); + else + operator=(traits::value_from_variant(value)); + } + public: cc_noinline - t operator=(const t& datum) + value<t>& operator=(const t& datum) { if (self_name.isEmpty()) - return def; + return *this; if (datum != get()) - store(traits::to_storage(datum)); + b->store_kv(self_name, QVariant::fromValue<stored_type>(traits::to_storage(datum))); - return datum; + return *this; } static constexpr inline Qt::ConnectionType DIRECT_CONNTYPE = Qt::DirectConnection; @@ -79,8 +92,8 @@ public: def(def) { if (!self_name.isEmpty()) - QObject::connect(b.get(), SIGNAL(reloading()), - this, SLOT(reload()), + QObject::connect(b.get(), &detail::bundle::reloading, + this, &value_::reload, DIRECT_CONNTYPE); } @@ -96,52 +109,49 @@ public: *this = def; } - operator t() const { return get(); } + operator t() const { return get(); } // NOLINT - t operator->() const - { - return get(); - } + template<typename u, typename = decltype(static_cast<u>(std::declval<t>()))> + explicit cc_forceinline operator u() const { return to<u>(); } - cc_noinline - void reload() override + auto operator->() const { - if (!self_name.isEmpty()) - *this = static_cast<t>(*this); + struct dereference_wrapper final + { + cc_forceinline t const* operator->() const { return &x; } + cc_forceinline t* operator->() { return &x; } + t x; + explicit cc_forceinline dereference_wrapper(t&& x) : x(x) {} + }; + + return dereference_wrapper { get() }; } cc_noinline - void bundle_value_changed() const override + void reload() override { +#if 0 if (!self_name.isEmpty()) - emit valueChanged(traits::to_storage(get())); - } - - t operator()() const - { - return get(); + store(traits::to_storage(get())); +#endif } - t operator*() const - { - return get(); - } + cc_forceinline t operator()() const { return get(); } + cc_forceinline t operator*() const { return get(); } template<typename u> u to() const { return static_cast<u>(get()); } - -private: - const t def; }; -#if !defined OTR_INST_VALUE -# define OTR_INST_VALUE OTR_TEMPLATE_IMPORT -#endif - +// some linker problems #if !defined __APPLE__ +# if !defined OTR_INST_VALUE +# define OTR_INST_VALUE OTR_TEMPLATE_IMPORT +# endif + OTR_INST_VALUE(value<double>); OTR_INST_VALUE(value<float>); OTR_INST_VALUE(value<int>); diff --git a/variant/default/main-window.cpp b/variant/default/main-window.cpp index b653f139..0d817bca 100644 --- a/variant/default/main-window.cpp +++ b/variant/default/main-window.cpp @@ -25,6 +25,9 @@ extern "C" const char* const opentrack_version; +using namespace options::globals; +using namespace options; + #if !defined EXIT_SUCCESS # define EXIT_SUCCESS 0 #endif @@ -83,8 +86,7 @@ void main_window::annoy_if_root() } #endif -main_window::main_window() : - State(OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH) +main_window::main_window() : State(OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH) { ui.setupUi(this); @@ -94,7 +96,7 @@ main_window::main_window() : update_button_state(false, false); - if (group::ini_directory().size() == 0) + if (ini_directory().isEmpty()) { die_on_config_not_writable(); return; @@ -146,7 +148,7 @@ main_window::main_window() : } { - const QString cur = group::ini_filename(); + const QString cur = ini_filename(); bool ok = is_config_listed(cur) ? set_profile(cur) : set_profile(OPENTRACK_DEFAULT_CONFIG); if (!ok) { @@ -348,7 +350,7 @@ void main_window::die_on_config_not_writable() QMessageBox::critical(this, tr("The Octopus is sad"), - tr("Check permissions for your .ini directory:\n\n\"%1\"%2\n\nExiting now.").arg(group::ini_directory(), pad), + tr("Check permissions for your .ini directory:\n\n\"%1\"%2\n\nExiting now.").arg(ini_directory(), pad), QMessageBox::Close, QMessageBox::NoButton); exit(EX_OSFILE); @@ -357,24 +359,24 @@ void main_window::die_on_config_not_writable() bool main_window::maybe_die_on_config_not_writable(const QString& current, QStringList* ini_list_) { const bool writable = - group::with_settings_object([&](QSettings& s) { + with_settings_object([&](QSettings& s) { return s.isWritable(); }); if (writable) return false; - const bool open = QFile(group::ini_combine(current)).open(QFile::ReadWrite); - const QStringList ini_list = group::ini_list(); + const bool open = QFile(ini_combine(current)).open(QFile::ReadWrite); + const QStringList list = ini_list(); - if (!ini_list.contains(current) || !open) + if (!list.contains(current) || !open) { die_on_config_not_writable(); return true; } if (ini_list_ != nullptr) - *ini_list_ = ini_list; + *ini_list_ = list; return false; } @@ -415,7 +417,7 @@ void main_window::make_empty_config() QString name; if (get_new_config_name_from_dialog(name)) { - QFile(group::ini_combine(name)).open(QFile::ReadWrite); + QFile(ini_combine(name)).open(QFile::ReadWrite); if (!refresh_config_list()) return; @@ -433,11 +435,11 @@ void main_window::make_empty_config() void main_window::make_copied_config() { - const QString cur = group::ini_pathname(); + const QString cur = ini_pathname(); QString name; if (cur != "" && get_new_config_name_from_dialog(name)) { - const QString new_name = group::ini_combine(name); + const QString new_name = ini_combine(name); (void) QFile::remove(new_name); QFile::copy(cur, new_name); @@ -458,7 +460,7 @@ void main_window::make_copied_config() void main_window::open_config_directory() { - QDesktopServices::openUrl("file:///" + QDir::toNativeSeparators(group::ini_directory())); + QDesktopServices::openUrl("file:///" + QDir::toNativeSeparators(ini_directory())); } bool main_window::refresh_config_list() @@ -466,16 +468,16 @@ bool main_window::refresh_config_list() if (work) return true; - QStringList ini_list = group::ini_list(); + QStringList list = ini_list(); // check for sameness - const bool exact_same = !ini_list.empty() && progn( - if (ini_list.size() == ui.iconcomboProfile->count()) + const bool exact_same = !list.empty() && progn( + if (list.size() == ui.iconcomboProfile->count()) { - const int sz = ini_list.size(); + const int sz = list.size(); for (int i = 0; i < sz; i++) { - if (ini_list[i] != ui.iconcomboProfile->itemText(i)) + if (list[i] != ui.iconcomboProfile->itemText(i)) return false; } return true; @@ -484,12 +486,12 @@ bool main_window::refresh_config_list() return false; ); - QString current = group::ini_filename(); + QString current = ini_filename(); - if (!ini_list.contains(current)) + if (!list.contains(current)) current = OPENTRACK_DEFAULT_CONFIG; - if (maybe_die_on_config_not_writable(current, &ini_list)) + if (maybe_die_on_config_not_writable(current, &list)) return false; if (exact_same) @@ -500,9 +502,9 @@ bool main_window::refresh_config_list() QSignalBlocker l(ui.iconcomboProfile); ui.iconcomboProfile->clear(); - ui.iconcomboProfile->addItems(ini_list); + ui.iconcomboProfile->addItems(list); - for (int i = 0; i < ini_list.size(); i++) + for (int i = 0; i < list.size(); i++) ui.iconcomboProfile->setItemIcon(i, icon); ui.iconcomboProfile->setCurrentText(current); @@ -663,7 +665,7 @@ void main_window::set_title(const QString& game_title_) QString game_title; if (game_title_ != "") game_title = tr(" :: ") + game_title_; - QString current = group::ini_filename(); + QString current = ini_filename(); QString version(opentrack_version); version = tr("opentrack") + " " + version.mid(sizeof("opentrack-") - 1); setWindowTitle(version + tr(" :: ") + current + game_title); @@ -681,7 +683,7 @@ void main_window::show_pose() double mapped[6], raw[6]; - work->tracker->raw_and_mapped_pose(mapped, raw); + work->pipeline_.raw_and_mapped_pose(mapped, raw); display_pose(mapped, raw); } @@ -817,7 +819,7 @@ bool main_window::set_profile(const QString& new_name_) } void main_window::ensure_tray() -{ +{ if (!QSystemTrayIcon::isSystemTrayAvailable()) { QApplication::setQuitOnLastWindowClosed(true); @@ -953,7 +955,7 @@ void main_window::set_keys_enabled(bool flag) if (!flag) { if (work) - work->sc->reload({}); + work->sc.reload({}); global_shortcuts.reload({}); } else @@ -1011,7 +1013,7 @@ bool main_window::start_in_tray() void main_window::set_profile_in_registry(const QString &profile) { - group::with_global_settings_object([&](QSettings& s) { + with_global_settings_object([&](QSettings& s) { s.setValue(OPENTRACK_CONFIG_FILENAME_KEY, profile); }); } diff --git a/variant/default/new_file_dialog.cpp b/variant/default/new_file_dialog.cpp index 2da9ce56..70816c5d 100644 --- a/variant/default/new_file_dialog.cpp +++ b/variant/default/new_file_dialog.cpp @@ -23,7 +23,7 @@ void new_file_dialog::ok_clicked() text = text.replace('\\', ""); if (text != "" && !text.endsWith(".ini")) text += ".ini"; - if (text == "" || text == ".ini" || QFile(options::group::ini_directory() + "/" + text).exists()) + if (text == "" || text == ".ini" || QFile(options::globals::ini_directory() + "/" + text).exists()) { QMessageBox::warning(this, tr("File exists"), |