From c80dd2e156e20f028cf4631fd7874a89c3568bab Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 28 Apr 2018 17:25:35 +0200 Subject: settings: store untranslated chosen module names Now that we translate module names, they have to be stored as language-neutral in the config. - add tie_setting overload with from/to conversions - add logic to opentrack/main-window - add migration - remove actually useless tie_setting_traits --- logic/main-settings.cpp | 7 ++- migration/20180428_00-module-names.cpp | 84 ++++++++++++++++++++++++++ options/tie.hpp | 94 +++++++++++------------------ variant/default/main-window.cpp | 106 ++++++++++++++++++++++++++++----- variant/default/main-window.hpp | 21 +++---- 5 files changed, 222 insertions(+), 90 deletions(-) create mode 100644 migration/20180428_00-module-names.cpp diff --git a/logic/main-settings.cpp b/logic/main-settings.cpp index c735ac6e..53a5054c 100644 --- a/logic/main-settings.cpp +++ b/logic/main-settings.cpp @@ -49,9 +49,9 @@ main_settings::main_settings() : module_settings::module_settings() : b(make_bundle("modules")), - tracker_dll(b, "tracker-dll", "PointTracker 1.1"), - filter_dll(b, "filter-dll", "Accela"), - protocol_dll(b, "protocol-dll", "freetrack 2.0 Enhanced") + tracker_dll(b, "tracker-dll", "pt"), + filter_dll(b, "filter-dll", "accela"), + protocol_dll(b, "protocol-dll", "freetrack") { } @@ -60,3 +60,4 @@ key_opts::key_opts(bundle b, const QString& name) : guid(b, QString("guid-%1").arg(name), ""), button(b, QString("button-%1").arg(name), -1) {} + diff --git a/migration/20180428_00-module-names.cpp b/migration/20180428_00-module-names.cpp new file mode 100644 index 00000000..fbb7a161 --- /dev/null +++ b/migration/20180428_00-module-names.cpp @@ -0,0 +1,84 @@ +#include "migration.hpp" +#include "options/options.hpp" + +using namespace migrations; +using namespace options; + +#include "api/plugin-support.hpp" +#include "compat/library-path.hpp" + +struct module_names : migration +{ + using dylib_ptr = Modules::dylib_ptr; + using dylib_list = Modules::dylib_list; + + QString unique_date() const override + { + return "20180428_00"; + } + + QString name() const override + { + return "module names"; + } + + bool should_run() const override + { + return true; + } + + void run() override + { + struct module_type { + QString name, def; + dylib_list const& list; + }; + + Modules m { OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH }; + + module_type types[3] { + { "tracker-dll", "pt", m.trackers() }, + { "protocol-dll", "freetrack", m.protocols() }, + { "filter-dll", "accela", m.filters() }, + }; + + bundle b = make_bundle("modules"); + + for (module_type& type : types) + { + QByteArray n = type.name.toUtf8(); + + if (!b->contains(type.name)) + { + qDebug() << n.constData() << "=>" << "EMPTY"; + b->store_kv(type.name, type.def); + continue; + } + + QString value = b->get(type.name); + + bool found = false; + + for (dylib_ptr lib : type.list) + { + if (value == lib->name) + { + qDebug() << n.constData() << "=>" << lib->module_name; + b->store_kv(type.name, lib->module_name); + found = true; + break; + } + } + + if (!found) + { + qDebug() << n.constData() << "=>" << "not found" << value; + b->store_kv(type.name, type.def); + } + } + + b->save(); + } +}; + +OPENTRACK_MIGRATION(module_names); diff --git a/options/tie.hpp b/options/tie.hpp index 307f5930..ca5eae5e 100644 --- a/options/tie.hpp +++ b/options/tie.hpp @@ -8,12 +8,10 @@ #pragma once -#include "value-traits.hpp" +#include "export.hpp" #include "value.hpp" #include "compat/run-in-thread.hpp" -#include "compat/macros.hpp" - -#include +#include "compat/meta.hpp" #include #include @@ -26,8 +24,6 @@ #include -#include "export.hpp" - #if defined __GNUG__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wattributes" @@ -35,67 +31,48 @@ namespace options { -namespace detail { - template -struct tie_setting_traits_helper -{ - using traits = detail::value_traits; - using value_type = typename traits::value_type; - using element_type = typename traits::element_type; - - static element_type to_element_type(const value& v) - { - return static_cast(static_cast(v)); - } -}; - -template -struct tie_setting_traits final : tie_setting_traits_helper +std::enable_if_t> tie_setting(value& v, QComboBox* cb) { - static constexpr inline bool should_bind_to_itemdata() { return false; } -}; - -template -struct tie_setting_traits>> : tie_setting_traits_helper -{ - static constexpr inline bool should_bind_to_itemdata() { return true; } - - static t itemdata_to_value(int, const QVariant& var) - { - return static_cast(var.toInt()); - } -}; - -} // ns options::detail - -template> -std::enable_if_t -tie_setting(value& v, QComboBox* cb, const traits_type& traits = traits_type()) -{ - using element_type = typename detail::value_traits::element_type; - - cb->setCurrentIndex(cb->findData(traits.to_element_type(v))); - v = traits.itemdata_to_value(cb->currentIndex(), cb->currentData()); + cb->setCurrentIndex(cb->findData(int(static_cast(v)))); + v = static_cast(cb->currentData().toInt()); base_value::connect(cb, static_cast(&QComboBox::currentIndexChanged), - &v, - [&v, cb, traits](int idx) - { - run_in_thread_sync(cb, - [&, traits]() { - v = traits.itemdata_to_value(idx, cb->currentData()); - }); - }, - v.DIRECT_CONNTYPE); - base_value::connect(&v, base_value::value_changed(), + &v, [&v, cb](int idx) { + run_in_thread_sync(cb, [&]() { + v = static_cast(cb->itemData(idx).toInt()); + }); + }, + v.DIRECT_CONNTYPE); + + base_value::connect(&v, base_value::value_changed(), cb, [cb](int x) { - run_in_thread_sync(cb, [&]() { cb->setCurrentIndex(cb->findData(x)); }); + run_in_thread_sync(cb, [=]() { cb->setCurrentIndex(cb->findData(x)); }); }, v.DIRECT_CONNTYPE); } +template +void tie_setting(value& v, QComboBox* cb, From&& fn_to_index, To&& fn_to_value) +{ + cb->setCurrentIndex(fn_to_index(v)); + v = fn_to_value(cb->currentIndex(), cb->currentData()); + + base_value::connect(cb, static_cast(&QComboBox::currentIndexChanged), + &v, [&v, cb, fn_to_value](int idx) { + run_in_thread_sync(cb, [&]() { + v = fn_to_value(idx, cb->currentData()); + }); + }, v.DIRECT_CONNTYPE); + base_value::connect(&v, base_value::value_changed(), + cb, [&v, cb, fn_to_index](cv_qualified& v) { + run_in_thread_sync(cb, [&]() { + cb->setCurrentIndex(fn_to_index(v)); + }); + }); +} + template void tie_setting(value& v, QLabel* lb, F&& fun) { @@ -120,9 +97,6 @@ void tie_setting(value& v, QObject* obj, F&& fun) v.DIRECT_CONNTYPE); } -// XXX TODO add combobox transform both ways via std::function -// need for non-translated `module_settings' dylib names - OTR_OPTIONS_EXPORT void tie_setting(value& v, QComboBox* cb); OTR_OPTIONS_EXPORT void tie_setting(value& v, QComboBox* cb); OTR_OPTIONS_EXPORT void tie_setting(value& v, QComboBox* cb); diff --git a/variant/default/main-window.cpp b/variant/default/main-window.cpp index 62b969e1..c52a806e 100644 --- a/variant/default/main-window.cpp +++ b/variant/default/main-window.cpp @@ -17,6 +17,8 @@ #include "compat/library-path.hpp" #include "compat/math.hpp" +#include + #include #include #include @@ -82,7 +84,7 @@ main_window::main_window() : if (!refresh_config_list()) { - exit(64); + exit(EX_OSFILE); return; } @@ -97,16 +99,16 @@ main_window::main_window() : // fill dylib comboboxen { - modules.filters().push_front(std::make_shared("", dylib::Filter)); + modules.filters().push_front(std::make_shared(QString(), dylib::Filter)); - for (std::shared_ptr& x : modules.trackers()) - ui.iconcomboTrackerSource->addItem(x->icon, x->name); + for (dylib_ptr& x : modules.trackers()) + ui.iconcomboTrackerSource->addItem(x->icon, x->name, x->module_name); - for (std::shared_ptr& x : modules.protocols()) - ui.iconcomboProtocol->addItem(x->icon, x->name); + for (dylib_ptr& x : modules.protocols()) + ui.iconcomboProtocol->addItem(x->icon, x->name, x->module_name); - for (std::shared_ptr& x : modules.filters()) - ui.iconcomboFilter->addItem(x->icon, x->name); + for (dylib_ptr& x : modules.filters()) + ui.iconcomboFilter->addItem(x->icon, x->name, x->module_name); } // timers @@ -155,13 +157,48 @@ main_window::main_window() : this, [&](const QString&) { if (pFilterDialog) pFilterDialog = nullptr; }); - connect(&m.tracker_dll, base_value::value_changed(), this, &main_window::save_modules, Qt::DirectConnection); - connect(&m.protocol_dll, base_value::value_changed(), this, &main_window::save_modules, Qt::DirectConnection); - connect(&m.filter_dll, base_value::value_changed(), this, &main_window::save_modules, Qt::DirectConnection); + connect(&m.tracker_dll, base_value::value_changed(), + this, &main_window::save_modules, + Qt::DirectConnection); + + connect(&m.protocol_dll, base_value::value_changed(), + this, &main_window::save_modules, + Qt::DirectConnection); - tie_setting(m.tracker_dll, ui.iconcomboTrackerSource); - tie_setting(m.protocol_dll, ui.iconcomboProtocol); - tie_setting(m.filter_dll, ui.iconcomboFilter); + connect(&m.filter_dll, base_value::value_changed(), + this, &main_window::save_modules, + Qt::DirectConnection); + + { + struct list { + dylib_list& libs; + QComboBox* input; + value& place; + }; + + list types[] { + { modules.trackers(), ui.iconcomboTrackerSource, m.tracker_dll }, + { modules.protocols(), ui.iconcomboProtocol, m.protocol_dll }, + { modules.filters(), ui.iconcomboFilter, m.filter_dll }, + }; + + for (list& type : types) + { + list& t = type; + tie_setting(t.place, t.input, + [t](const QString& name) { + auto [ptr, idx] = module_by_name(name, t.libs); + return idx; + }, + [t](int, const QVariant& userdata) { + auto [ptr, idx] = module_by_name(userdata.toString(), t.libs); + if (ptr) + return ptr->module_name; + else + return QString(); + }); + } + } } connect(this, &main_window::start_tracker, @@ -461,6 +498,39 @@ bool main_window::refresh_config_list() return true; } +std::tuple main_window::module_by_name(const QString& name, Modules::dylib_list& list) +{ + auto it = std::find_if(list.cbegin(), list.cend(), [&name](const dylib_ptr& lib) { + if (!lib) + return name.isEmpty(); + else + return name == lib->module_name; + }); + + if (it == list.cend()) + return { nullptr, -1 }; + else + return { *it, int(std::distance(list.cbegin(), it)) }; +} + +main_window::dylib_ptr main_window::current_tracker() +{ + auto [ptr, idx] = module_by_name(m.tracker_dll, modules.trackers()); + return ptr; +} + +main_window::dylib_ptr main_window::current_protocol() +{ + auto [ptr, idx] = module_by_name(m.protocol_dll, modules.protocols()); + return ptr; +} + +main_window::dylib_ptr main_window::current_filter() +{ + auto [ptr, idx] = module_by_name(m.filter_dll, modules.filters()); + return ptr; +} + void main_window::update_button_state(bool running, bool inertialp) { bool not_running = !running; @@ -718,13 +788,19 @@ bool main_window::set_profile(const QString& new_name_) ui.iconcomboProfile->setCurrentText(new_name); set_profile_in_registry(new_name); - set_title(); + // XXX workaround migration breakage -sh 20180428 + QSignalBlocker b1(ui.iconcomboTrackerSource); + QSignalBlocker b2(ui.iconcomboProtocol); + QSignalBlocker b3(ui.iconcomboFilter); + options::detail::bundler::refresh_all_bundles(); // migrations are for config layout changes and other user-visible // incompatibilities in future versions run_migrations(); + set_title(); + return true; } diff --git a/variant/default/main-window.hpp b/variant/default/main-window.hpp index c28aadc4..6e85a13c 100644 --- a/variant/default/main-window.hpp +++ b/variant/default/main-window.hpp @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -72,18 +73,14 @@ class main_window : public QMainWindow, private State menu_action_options { &tray_menu }, menu_action_mappings { &tray_menu }; - std::shared_ptr current_tracker() - { - return modules.trackers().value(ui.iconcomboTrackerSource->currentIndex(), nullptr); - } - std::shared_ptr current_protocol() - { - return modules.protocols().value(ui.iconcomboProtocol->currentIndex(), nullptr); - } - std::shared_ptr current_filter() - { - return modules.filters().value(ui.iconcomboFilter->currentIndex(), nullptr); - } + using dylib_ptr = Modules::dylib_ptr; + using dylib_list = Modules::dylib_list; + + static std::tuple module_by_name(const QString& name, Modules::dylib_list& list); + + dylib_ptr current_tracker(); + dylib_ptr current_protocol(); + dylib_ptr current_filter(); void update_button_state(bool running, bool inertialp); void display_pose(const double* mapped, const double* raw); -- cgit v1.2.3