diff --git a/cli/cli.cc b/cli/cli.cc index 750fa79c7..6a10d3872 100644 --- a/cli/cli.cc +++ b/cli/cli.cc @@ -204,8 +204,6 @@ int tr_main(int argc, char* argv[]) tr_locale_set_global(""); - tr_variant settings; - tr_formatter_mem_init(MemK, MemKStr, MemMStr, MemGStr, MemTStr); tr_formatter_size_init(DiskK, DiskKStr, DiskMStr, DiskGStr, DiskTStr); tr_formatter_speed_init(SpeedK, SpeedKStr, SpeedMStr, SpeedGStr, SpeedTStr); @@ -220,9 +218,8 @@ int tr_main(int argc, char* argv[]) } /* load the defaults from config file + libtransmission defaults */ - tr_variantInitDict(&settings, 0); auto const config_dir = getConfigDir(argc, (char const**)argv); - tr_sessionLoadSettings(&settings, config_dir.c_str(), MyConfigName); + auto settings = tr_sessionLoadSettings(config_dir.c_str(), MyConfigName); /* the command line overrides defaults */ if (parseCommandLine(&settings, argc, (char const**)argv) != 0) diff --git a/daemon/daemon.cc b/daemon/daemon.cc index 56c9d91fe..d269f1105 100644 --- a/daemon/daemon.cc +++ b/daemon/daemon.cc @@ -669,7 +669,6 @@ void tr_daemon::reconfigure(void) } else { - tr_variant newsettings; char const* configDir; /* reopen the logfile to allow for log rotation */ @@ -680,9 +679,11 @@ void tr_daemon::reconfigure(void) configDir = tr_sessionGetConfigDir(my_session_); tr_logAddInfo(fmt::format(_("Reloading settings from '{path}'"), fmt::arg("path", configDir))); - tr_variantInitDict(&newsettings, 0); + + auto newsettings = tr_variant::make_map(); tr_variantDictAddBool(&newsettings, TR_KEY_rpc_enabled, true); - tr_sessionLoadSettings(&newsettings, configDir, MyName); + newsettings.merge(tr_sessionLoadSettings(configDir, MyName)); + tr_sessionSet(my_session_, &newsettings); tr_sessionReloadBlocklists(my_session_); } @@ -905,9 +906,9 @@ bool tr_daemon::init(int argc, char const* const argv[], bool* foreground, int* config_dir_ = getConfigDir(argc, argv); /* load settings from defaults + config file */ - tr_variantInitDict(&settings_, 0); + settings_ = tr_variant::make_map(); tr_variantDictAddBool(&settings_, TR_KEY_rpc_enabled, true); - bool const loaded = tr_sessionLoadSettings(&settings_, config_dir_.c_str(), MyName); + settings_.merge(tr_sessionLoadSettings(config_dir_.c_str(), MyName)); bool dumpSettings; @@ -925,13 +926,6 @@ bool tr_daemon::init(int argc, char const* const argv[], bool* foreground, int* logfile_flush_ = tr_sys_file_flush_possible(logfile_); } - if (!loaded) - { - printMessage(logfile_, TR_LOG_ERROR, MyName, "Error loading config file -- exiting.", __FILE__, __LINE__); - *ret = 1; - goto EXIT_EARLY; - } - if (dumpSettings) { fmt::print("{:s}\n", tr_variant_serde::json().to_string(settings_)); diff --git a/gtk/Application.cc b/gtk/Application.cc index a2a3b42bc..dbdced752 100644 --- a/gtk/Application.cc +++ b/gtk/Application.cc @@ -69,6 +69,7 @@ #include // std::back_inserter #include #include +#include #include #include #include @@ -473,34 +474,36 @@ bool Application::Impl::on_rpc_changed_idle(tr_rpc_callback_type type, tr_torren case TR_RPC_SESSION_CHANGED: { - tr_variant tmp; - tr_variant* newval = nullptr; - tr_variant* oldvals = gtr_pref_get_all(); - tr_quark key = TR_KEY_NONE; - std::vector changed_keys; auto const* const session = core_->get_session(); - tr_variantInitDict(&tmp, 100); - tr_sessionGetSettings(session, &tmp); + auto const newvals = tr_sessionGetSettings(session); + // determine which settings changed + auto changed_keys = std::set{}; + auto& oldvals = gtr_pref_get_all(); auto const serde = tr_variant_serde::benc(); - for (int i = 0; tr_variantDictChild(&tmp, i, &key, &newval); ++i) + if (auto const* const newvals_map = newvals.get_if(); newvals_map != nullptr) { - bool changed = true; - - if (tr_variant const* oldval = tr_variantDictFind(oldvals, key); oldval != nullptr) + for (auto const& [key, newval] : *newvals_map) { - changed = serde.to_string(*oldval) != serde.to_string(*newval); - } + bool changed = true; - if (changed) - { - changed_keys.push_back(key); + if (tr_variant const* oldval = tr_variantDictFind(&oldvals, key); oldval != nullptr) + { + changed = serde.to_string(*oldval) != serde.to_string(newval); + } + + if (changed) + { + changed_keys.emplace(key); + } } } - tr_sessionGetSettings(session, oldvals); + // update our settings + oldvals.merge(newvals); - for (auto const changed_key : changed_keys) + // emit change notifications + for (auto const& changed_key : changed_keys) { core_->signal_prefs_changed().emit(changed_key); } @@ -604,7 +607,7 @@ void Application::Impl::on_startup() } /* initialize the libtransmission session */ - session = tr_sessionInit(config_dir_.c_str(), true, gtr_pref_get_all()); + session = tr_sessionInit(config_dir_.c_str(), true, >r_pref_get_all()); gtr_pref_flag_set(TR_KEY_alt_speed_enabled, tr_sessionUsesAltSpeed(session)); gtr_pref_int_set(TR_KEY_peer_port, tr_sessionGetPeerPort(session)); diff --git a/gtk/Prefs.cc b/gtk/Prefs.cc index 856299dfd..44266e0c6 100644 --- a/gtk/Prefs.cc +++ b/gtk/Prefs.cc @@ -31,55 +31,61 @@ void gtr_pref_init(std::string_view config_dir) **** ***/ +[[nodiscard]] static std::string get_default_download_dir() +{ + if (auto dir = Glib::get_user_special_dir(TR_GLIB_USER_DIRECTORY(DOWNLOAD)); !std::empty(dir)) + { + return dir; + } + + if (auto dir = Glib::get_user_special_dir(TR_GLIB_USER_DIRECTORY(DESKTOP)); !std::empty(dir)) + { + return dir; + } + + return tr_getDefaultDownloadDir(); +} + /** * This is where we initialize the preferences file with the default values. * If you add a new preferences key, you /must/ add a default value here. */ -static void tr_prefs_init_defaults(tr_variant* d) +[[nodiscard]] static tr_variant get_default_app_settings() { - auto dir = Glib::get_user_special_dir(TR_GLIB_USER_DIRECTORY(DOWNLOAD)); + auto const dir = get_default_download_dir(); - if (dir.empty()) - { - dir = Glib::get_user_special_dir(TR_GLIB_USER_DIRECTORY(DESKTOP)); - } - - if (dir.empty()) - { - dir = tr_getDefaultDownloadDir(); - } - - tr_variantDictReserve(d, 31); - tr_variantDictAddStr(d, TR_KEY_watch_dir, dir); - tr_variantDictAddBool(d, TR_KEY_watch_dir_enabled, false); - tr_variantDictAddBool(d, TR_KEY_user_has_given_informed_consent, false); - tr_variantDictAddBool(d, TR_KEY_inhibit_desktop_hibernation, false); - tr_variantDictAddBool(d, TR_KEY_blocklist_updates_enabled, true); - tr_variantDictAddStr(d, TR_KEY_open_dialog_dir, Glib::get_home_dir()); - tr_variantDictAddBool(d, TR_KEY_show_toolbar, true); - tr_variantDictAddBool(d, TR_KEY_show_filterbar, true); - tr_variantDictAddBool(d, TR_KEY_show_statusbar, true); - tr_variantDictAddBool(d, TR_KEY_trash_can_enabled, true); - tr_variantDictAddBool(d, TR_KEY_show_notification_area_icon, false); - tr_variantDictAddBool(d, TR_KEY_show_tracker_scrapes, false); - tr_variantDictAddBool(d, TR_KEY_show_extra_peer_details, false); - tr_variantDictAddBool(d, TR_KEY_show_backup_trackers, false); - tr_variantDictAddStr(d, TR_KEY_statusbar_stats, "total-ratio"sv); - tr_variantDictAddBool(d, TR_KEY_torrent_added_notification_enabled, true); - tr_variantDictAddBool(d, TR_KEY_torrent_complete_notification_enabled, true); - tr_variantDictAddBool(d, TR_KEY_torrent_complete_sound_enabled, true); - tr_variantDictAddBool(d, TR_KEY_show_options_window, true); - tr_variantDictAddBool(d, TR_KEY_main_window_is_maximized, false); - tr_variantDictAddInt(d, TR_KEY_main_window_height, 500); - tr_variantDictAddInt(d, TR_KEY_main_window_width, 300); - tr_variantDictAddInt(d, TR_KEY_main_window_x, 50); - tr_variantDictAddInt(d, TR_KEY_main_window_y, 50); - tr_variantDictAddInt(d, TR_KEY_details_window_height, 500); - tr_variantDictAddInt(d, TR_KEY_details_window_width, 700); - tr_variantDictAddStr(d, TR_KEY_download_dir, dir); - tr_variantDictAddStr(d, TR_KEY_sort_mode, "sort-by-name"sv); - tr_variantDictAddBool(d, TR_KEY_sort_reversed, false); - tr_variantDictAddBool(d, TR_KEY_compact_view, false); + auto map = tr_variant::Map{}; + map.try_emplace(TR_KEY_blocklist_updates_enabled, true); + map.try_emplace(TR_KEY_compact_view, false); + map.try_emplace(TR_KEY_details_window_height, 500); + map.try_emplace(TR_KEY_details_window_width, 700); + map.try_emplace(TR_KEY_download_dir, dir); + map.try_emplace(TR_KEY_inhibit_desktop_hibernation, false); + map.try_emplace(TR_KEY_main_window_height, 500); + map.try_emplace(TR_KEY_main_window_is_maximized, false); + map.try_emplace(TR_KEY_main_window_width, 300); + map.try_emplace(TR_KEY_main_window_x, 50); + map.try_emplace(TR_KEY_main_window_y, 50); + map.try_emplace(TR_KEY_open_dialog_dir, Glib::get_home_dir()); + map.try_emplace(TR_KEY_show_backup_trackers, false); + map.try_emplace(TR_KEY_show_extra_peer_details, false); + map.try_emplace(TR_KEY_show_filterbar, true); + map.try_emplace(TR_KEY_show_notification_area_icon, false); + map.try_emplace(TR_KEY_show_options_window, true); + map.try_emplace(TR_KEY_show_statusbar, true); + map.try_emplace(TR_KEY_show_toolbar, true); + map.try_emplace(TR_KEY_show_tracker_scrapes, false); + map.try_emplace(TR_KEY_sort_mode, "sort-by-name"sv); + map.try_emplace(TR_KEY_sort_reversed, false); + map.try_emplace(TR_KEY_statusbar_stats, "total-ratio"sv); + map.try_emplace(TR_KEY_torrent_added_notification_enabled, true); + map.try_emplace(TR_KEY_torrent_complete_notification_enabled, true); + map.try_emplace(TR_KEY_torrent_complete_sound_enabled, true); + map.try_emplace(TR_KEY_trash_can_enabled, true); + map.try_emplace(TR_KEY_user_has_given_informed_consent, false); + map.try_emplace(TR_KEY_watch_dir, dir); + map.try_emplace(TR_KEY_watch_dir_enabled, false); + return tr_variant{ std::move(map) }; } static void ensure_sound_cmd_is_a_list(tr_variant* dict) @@ -100,28 +106,25 @@ static void ensure_sound_cmd_is_a_list(tr_variant* dict) tr_variantListAddStr(list, "transmission torrent downloaded"sv); } -static tr_variant* getPrefs() +static tr_variant& getPrefs() { - static tr_variant settings; - static bool loaded = false; + static auto settings = tr_variant{}; - if (!loaded) + if (!settings.has_value()) { - tr_variantInitDict(&settings, 0); - tr_prefs_init_defaults(&settings); - tr_sessionLoadSettings(&settings, gl_confdir.c_str(), nullptr); + settings = get_default_app_settings(); + settings.merge(tr_sessionLoadSettings(gl_confdir.c_str(), nullptr)); ensure_sound_cmd_is_a_list(&settings); - loaded = true; } - return &settings; + return settings; } /*** **** ***/ -tr_variant* gtr_pref_get_all() +tr_variant& gtr_pref_get_all() { return getPrefs(); } @@ -130,24 +133,24 @@ int64_t gtr_pref_int_get(tr_quark const key) { int64_t i = 0; - return tr_variantDictFindInt(getPrefs(), key, &i) ? i : 0; + return tr_variantDictFindInt(&getPrefs(), key, &i) ? i : 0; } void gtr_pref_int_set(tr_quark const key, int64_t value) { - tr_variantDictAddInt(getPrefs(), key, value); + tr_variantDictAddInt(&getPrefs(), key, value); } double gtr_pref_double_get(tr_quark const key) { double d = 0; - return tr_variantDictFindReal(getPrefs(), key, &d) ? d : 0.0; + return tr_variantDictFindReal(&getPrefs(), key, &d) ? d : 0.0; } void gtr_pref_double_set(tr_quark const key, double value) { - tr_variantDictAddReal(getPrefs(), key, value); + tr_variantDictAddReal(&getPrefs(), key, value); } /*** @@ -158,12 +161,12 @@ bool gtr_pref_flag_get(tr_quark const key) { bool boolVal = false; - return tr_variantDictFindBool(getPrefs(), key, &boolVal) ? boolVal : false; + return tr_variantDictFindBool(&getPrefs(), key, &boolVal) ? boolVal : false; } void gtr_pref_flag_set(tr_quark const key, bool value) { - tr_variantDictAddBool(getPrefs(), key, value); + tr_variantDictAddBool(&getPrefs(), key, value); } /*** @@ -174,7 +177,7 @@ std::vector gtr_pref_strv_get(tr_quark const key) { std::vector ret; - if (tr_variant* list = nullptr; tr_variantDictFindList(getPrefs(), key, &list)) + if (tr_variant* list = nullptr; tr_variantDictFindList(&getPrefs(), key, &list)) { size_t const n = tr_variantListSize(list); ret.reserve(n); @@ -195,13 +198,13 @@ std::vector gtr_pref_strv_get(tr_quark const key) std::string gtr_pref_string_get(tr_quark const key) { auto sv = std::string_view{}; - (void)tr_variantDictFindStrView(getPrefs(), key, &sv); + (void)tr_variantDictFindStrView(&getPrefs(), key, &sv); return std::string{ sv }; } void gtr_pref_string_set(tr_quark const key, std::string_view value) { - tr_variantDictAddStr(getPrefs(), key, value); + tr_variantDictAddStr(&getPrefs(), key, value); } /*** @@ -210,5 +213,5 @@ void gtr_pref_string_set(tr_quark const key, std::string_view value) void gtr_pref_save(tr_session* session) { - tr_sessionSaveSettings(session, gl_confdir.c_str(), getPrefs()); + tr_sessionSaveSettings(session, gl_confdir.c_str(), &getPrefs()); } diff --git a/gtk/Prefs.h b/gtk/Prefs.h index 4a3a5dd5d..2b12687a7 100644 --- a/gtk/Prefs.h +++ b/gtk/Prefs.h @@ -29,4 +29,4 @@ std::string gtr_pref_string_get(tr_quark key); void gtr_pref_string_set(tr_quark key, std::string_view value); void gtr_pref_save(tr_session* /*session*/); -tr_variant* gtr_pref_get_all(); +tr_variant& gtr_pref_get_all(); diff --git a/libtransmission/rpc-server.cc b/libtransmission/rpc-server.cc index f73cb5567..cb42b1722 100644 --- a/libtransmission/rpc-server.cc +++ b/libtransmission/rpc-server.cc @@ -840,7 +840,7 @@ void tr_rpc_server::set_anti_brute_force_enabled(bool enabled) noexcept // --- LIFECYCLE -tr_rpc_server::tr_rpc_server(tr_session* session_in, tr_variant* settings) +tr_rpc_server::tr_rpc_server(tr_session* session_in, tr_variant const& settings) : compressor{ libdeflate_alloc_compressor(DeflateLevel), libdeflate_free_compressor } , web_client_dir_{ tr_getWebClientDir(session_in) } , bind_address_(std::make_unique()) @@ -849,18 +849,22 @@ tr_rpc_server::tr_rpc_server(tr_session* session_in, tr_variant* settings) load(settings); } -void tr_rpc_server::load(tr_variant* src) +void tr_rpc_server::load(tr_variant const& src) { + auto const* const src_map = src.get_if(); + if (src_map != nullptr) + { #define V(key, field, type, default_value, comment) \ - if (auto* const child = tr_variantDictFind(src, key); child != nullptr) \ + if (auto const iter = src_map->find(key); iter != std::end(*src_map)) \ { \ - if (auto val = libtransmission::VariantConverter::load(child); val) \ + if (auto val = libtransmission::VariantConverter::load(iter->second); val) \ { \ this->field = *val; \ } \ } - RPC_SETTINGS_FIELDS(V) + RPC_SETTINGS_FIELDS(V) #undef V + } if (!tr_strv_ends_with(url_, '/')) { @@ -910,23 +914,24 @@ void tr_rpc_server::load(tr_variant* src) } } -void tr_rpc_server::save(tr_variant* tgt) const +tr_variant tr_rpc_server::settings() const { + auto settings = tr_variant::Map{}; #define V(key, field, type, default_value, comment) \ - tr_variantDictRemove(tgt, key); \ - libtransmission::VariantConverter::save(tr_variantDictAdd(tgt, key), field); + settings.try_emplace(key, libtransmission::VariantConverter::save(field)); RPC_SETTINGS_FIELDS(V) #undef V + return tr_variant{ std::move(settings) }; } -void tr_rpc_server::default_settings(tr_variant* tgt){ +tr_variant tr_rpc_server::default_settings() +{ + auto settings = tr_variant::Map{}; #define V(key, field, type, default_value, comment) \ - { \ - tr_variantDictRemove(tgt, key); \ - libtransmission::VariantConverter::save(tr_variantDictAdd(tgt, key), default_value); \ - } + settings.try_emplace(key, libtransmission::VariantConverter::save(default_value)); RPC_SETTINGS_FIELDS(V) #undef V + return tr_variant{ std::move(settings) }; } tr_rpc_server::~tr_rpc_server() diff --git a/libtransmission/rpc-server.h b/libtransmission/rpc-server.h index 249cc6f94..c6346eada 100644 --- a/libtransmission/rpc-server.h +++ b/libtransmission/rpc-server.h @@ -50,7 +50,7 @@ class Timer; class tr_rpc_server { public: - tr_rpc_server(tr_session* session, tr_variant* settings); + tr_rpc_server(tr_session* session, tr_variant const& settings); ~tr_rpc_server(); tr_rpc_server(tr_rpc_server&) = delete; @@ -58,9 +58,9 @@ public: tr_rpc_server& operator=(tr_rpc_server&) = delete; tr_rpc_server& operator=(tr_rpc_server&&) = delete; - void load(tr_variant* src); - void save(tr_variant* tgt) const; - static void default_settings(tr_variant* tgt); + void load(tr_variant const& src); + [[nodiscard]] tr_variant settings() const; + [[nodiscard]] static tr_variant default_settings(); [[nodiscard]] constexpr tr_port port() const noexcept { diff --git a/libtransmission/session-alt-speeds.cc b/libtransmission/session-alt-speeds.cc index 9806ec7c1..7c13d05a7 100644 --- a/libtransmission/session-alt-speeds.cc +++ b/libtransmission/session-alt-speeds.cc @@ -17,41 +17,44 @@ using namespace std::literals; -void tr_session_alt_speeds::load(tr_variant* src) +void tr_session_alt_speeds::load(tr_variant const& src) { + auto const* const src_map = src.get_if(); + if (src_map != nullptr) + { #define V(key, field, type, default_value, comment) \ - if (auto* const child = tr_variantDictFind(src, key); child != nullptr) \ + if (auto const iter = src_map->find(key); iter != std::end(*src_map)) \ { \ - if (auto val = libtransmission::VariantConverter::load(child); val) \ + if (auto val = libtransmission::VariantConverter::load(iter->second); val) \ { \ this->field = *val; \ } \ } - ALT_SPEEDS_FIELDS(V) + ALT_SPEEDS_FIELDS(V) #undef V + } update_scheduler(); } -void tr_session_alt_speeds::save(tr_variant* tgt) const +tr_variant tr_session_alt_speeds::settings() const { + auto settings = tr_variant::Map{}; #define V(key, field, type, default_value, comment) \ - tr_variantDictRemove(tgt, key); \ - libtransmission::VariantConverter::save(tr_variantDictAdd(tgt, key), field); + settings.try_emplace(key, libtransmission::VariantConverter::save(field)); ALT_SPEEDS_FIELDS(V) #undef V + return tr_variant{ std::move(settings) }; } -void tr_session_alt_speeds::default_settings(tr_variant* tgt) +tr_variant tr_session_alt_speeds::default_settings() { + auto settings = tr_variant::Map{}; #define V(key, field, type, default_value, comment) \ - { \ - type const val = default_value; \ - tr_variantDictRemove(tgt, key); \ - libtransmission::VariantConverter::save(tr_variantDictAdd(tgt, key), val); \ - } + settings.try_emplace(key, libtransmission::VariantConverter::save(static_cast(default_value))); ALT_SPEEDS_FIELDS(V) #undef V + return tr_variant{ std::move(settings) }; } // --- minutes diff --git a/libtransmission/session-alt-speeds.h b/libtransmission/session-alt-speeds.h index 0dd723a03..5c21c6811 100644 --- a/libtransmission/session-alt-speeds.h +++ b/libtransmission/session-alt-speeds.h @@ -54,9 +54,9 @@ public: { } - void load(tr_variant* src); - void save(tr_variant* tgt) const; - static void default_settings(tr_variant* tgt); + void load(tr_variant const& src); + [[nodiscard]] tr_variant settings() const; + [[nodiscard]] static tr_variant default_settings(); [[nodiscard]] constexpr bool is_active() const noexcept { diff --git a/libtransmission/session-settings.cc b/libtransmission/session-settings.cc index e02852fc8..cd38134fa 100644 --- a/libtransmission/session-settings.cc +++ b/libtransmission/session-settings.cc @@ -6,12 +6,18 @@ #include "libtransmission/session-settings.h" #include "libtransmission/variant.h" -void tr_session_settings::load(tr_variant* src) +void tr_session_settings::load(tr_variant const& src) { + auto const* map = src.get_if(); + if (map == nullptr) + { + return; + } + #define V(key, field, type, default_value, comment) \ - if (auto* const child = tr_variantDictFind(src, key); child != nullptr) \ + if (auto const iter = map->find(key); iter != std::end(*map)) \ { \ - if (auto val = libtransmission::VariantConverter::load(child); val) \ + if (auto val = libtransmission::VariantConverter::load(iter->second); val) \ { \ this->field = *val; \ } \ @@ -20,11 +26,17 @@ void tr_session_settings::load(tr_variant* src) #undef V } -void tr_session_settings::save(tr_variant* tgt) const +tr_variant tr_session_settings::settings() const { + auto map = tr_variant::Map{}; #define V(key, field, type, default_value, comment) \ - tr_variantDictRemove(tgt, key); \ - libtransmission::VariantConverter::save(tr_variantDictAdd(tgt, key), field); + map.try_emplace(key, libtransmission::VariantConverter::save(field)); SESSION_SETTINGS_FIELDS(V) #undef V + return tr_variant{ std::move(map) }; +} + +tr_variant tr_session_settings::default_settings() +{ + return tr_session_settings{}.settings(); } diff --git a/libtransmission/session-settings.h b/libtransmission/session-settings.h index 21116b2c0..83d0a734b 100644 --- a/libtransmission/session-settings.h +++ b/libtransmission/session-settings.h @@ -82,13 +82,14 @@ struct tr_session_settings { tr_session_settings() = default; - explicit tr_session_settings(tr_variant* src) + explicit tr_session_settings(tr_variant const& src) { load(src); } - void load(tr_variant* src); - void save(tr_variant* tgt) const; + void load(tr_variant const& src); + [[nodiscard]] tr_variant settings() const; + [[nodiscard]] static tr_variant default_settings(); #define V(key, name, type, default_value, comment) type name = type{ default_value }; SESSION_SETTINGS_FIELDS(V) diff --git a/libtransmission/session.cc b/libtransmission/session.cc index 8475e52f6..4a3213c7e 100644 --- a/libtransmission/session.cc +++ b/libtransmission/session.cc @@ -452,82 +452,45 @@ tr_address tr_session::bind_address(tr_address_type type) const noexcept // --- -namespace +tr_variant tr_sessionGetDefaultSettings() { -namespace settings_helpers -{ - -void get_settings_filename(tr_pathbuf& setme, char const* config_dir, char const* appname) -{ - if (!tr_str_is_empty(config_dir)) - { - setme.assign(std::string_view{ config_dir }, "/settings.json"sv); - return; - } - - auto const default_config_dir = tr_getDefaultConfigDir(appname); - setme.assign(std::string_view{ default_config_dir }, "/settings.json"sv); + auto ret = tr_variant::make_map(); + ret.merge(tr_session_settings::default_settings()); + ret.merge(tr_rpc_server::default_settings()); + ret.merge(tr_session_alt_speeds::default_settings()); + return ret; } -} // namespace settings_helpers -} // namespace - -void tr_sessionGetDefaultSettings(tr_variant* setme_dictionary) +tr_variant tr_sessionGetSettings(tr_session const* session) { - tr_session_settings{}.save(setme_dictionary); - tr_rpc_server::default_settings(setme_dictionary); - tr_session_alt_speeds::default_settings(setme_dictionary); + auto settings = tr_variant::make_map(); + settings.merge(session->settings_.settings()); + settings.merge(session->alt_speeds_.settings()); + settings.merge(session->rpc_server_->settings()); + + tr_variantDictRemove(&settings, TR_KEY_message_level); + tr_variantDictAddInt(&settings, TR_KEY_message_level, tr_logGetLevel()); + + return settings; } -void tr_sessionGetSettings(tr_session const* session, tr_variant* setme_dictionary) +tr_variant tr_sessionLoadSettings(char const* config_dir, char const* app_name) { - session->settings_.save(setme_dictionary); - session->alt_speeds_.save(setme_dictionary); - session->rpc_server_->save(setme_dictionary); + auto settings = tr_sessionGetDefaultSettings(); - tr_variantDictRemove(setme_dictionary, TR_KEY_message_level); - tr_variantDictAddInt(setme_dictionary, TR_KEY_message_level, tr_logGetLevel()); -} - -bool tr_sessionLoadSettings(tr_variant* settings_in, char const* config_dir, char const* app_name) -{ - using namespace settings_helpers; - - TR_ASSERT(settings_in != nullptr); - TR_ASSERT(settings_in->holds_alternative()); - - // first, start with the libtransmission default settings - auto settings = tr_variant{}; - tr_variantInitDict(&settings, 0); - tr_sessionGetDefaultSettings(&settings); - - // now use the app default settings passed in - tr_variantMergeDicts(&settings, settings_in); - - // now use a settings file to override all the defaults - auto success = bool{}; - auto filename = tr_pathbuf{}; - get_settings_filename(filename, config_dir, app_name); - if (!tr_sys_path_exists(filename)) + // if a settings file exists, use it to override the defaults + if (auto const filename = fmt::format( + "{:s}/settings.json", + config_dir != nullptr ? config_dir : tr_getDefaultConfigDir(app_name)); + tr_sys_path_exists(filename)) { - success = true; - } - else if (auto file_settings = tr_variant_serde::json().parse_file(filename); file_settings) - { - tr_variantMergeDicts(&settings, &*file_settings); - success = true; - } - else - { - success = false; + if (auto file_settings = tr_variant_serde::json().parse_file(filename); file_settings) + { + settings.merge(*file_settings); + } } - if (success) - { - std::swap(*settings_in, settings); - } - - return success; + return settings; } void tr_sessionSaveSettings(tr_session* session, char const* config_dir, tr_variant const* client_settings) @@ -552,12 +515,7 @@ void tr_sessionSaveSettings(tr_session* session, char const* config_dir, tr_vari tr_variantMergeDicts(&settings, client_settings); /* the session's true values override the file & client settings */ - { - auto session_settings = tr_variant{}; - tr_variantInitDict(&session_settings, 0); - tr_sessionGetSettings(session, &session_settings); - tr_variantMergeDicts(&settings, &session_settings); - } + settings.merge(tr_sessionGetSettings(session)); /* save the result */ tr_variant_serde::json().to_file(settings, filename); @@ -592,7 +550,7 @@ tr_session* tr_sessionInit(char const* config_dir, bool message_queueing_enabled } /* initialize the bare skeleton of the session object */ - auto* const session = new tr_session{ config_dir }; + auto* const session = new tr_session{ config_dir, tr_variant::make_map() }; bandwidthGroupRead(session, config_dir); auto data = tr_session::init_data{}; @@ -638,9 +596,7 @@ void tr_session::initImpl(init_data& data) tr_logAddTrace(fmt::format("tr_sessionInit: the session's top-level bandwidth object is {}", fmt::ptr(&top_bandwidth_))); - auto settings = tr_variant{}; - tr_variantInitDict(&settings, 0); - tr_sessionGetDefaultSettings(&settings); + auto settings = tr_sessionGetDefaultSettings(); tr_variantMergeDicts(&settings, client_settings); #ifndef _WIN32 @@ -675,12 +631,12 @@ void tr_session::setSettings(tr_variant* settings_dict, bool force) // load the session settings auto new_settings = tr_session_settings{}; - new_settings.load(settings_dict); + new_settings.load(*settings_dict); setSettings(std::move(new_settings), force); // delegate loading out the other settings - alt_speeds_.load(settings_dict); - rpc_server_->load(settings_dict); + alt_speeds_.load(*settings_dict); + rpc_server_->load(*settings_dict); } void tr_session::setSettings(tr_session_settings&& settings_in, bool force) @@ -2139,7 +2095,7 @@ auto makeBlocklistDir(std::string_view config_dir) } // namespace -tr_session::tr_session(std::string_view config_dir, tr_variant* settings_dict) +tr_session::tr_session(std::string_view config_dir, tr_variant const& settings_dict) : config_dir_{ config_dir } , resume_dir_{ makeResumeDir(config_dir) } , torrent_dir_{ makeTorrentDir(config_dir) } diff --git a/libtransmission/session.h b/libtransmission/session.h index 8b925fb74..648c9f8dd 100644 --- a/libtransmission/session.h +++ b/libtransmission/session.h @@ -352,7 +352,7 @@ private: }; public: - explicit tr_session(std::string_view config_dir, tr_variant* settings_dict = nullptr); + explicit tr_session(std::string_view config_dir, tr_variant const& settings_dict); [[nodiscard]] std::string_view sessionId() const noexcept { @@ -998,7 +998,7 @@ private: friend uint16_t tr_sessionGetRPCPort(tr_session const* session); friend uint16_t tr_sessionSetPeerPortRandom(tr_session* session); friend void tr_sessionClose(tr_session* session, size_t timeout_secs); - friend void tr_sessionGetSettings(tr_session const* s, tr_variant* setme_dictionary); + friend tr_variant tr_sessionGetSettings(tr_session const* s); friend void tr_sessionLimitSpeed(tr_session* session, tr_direction dir, bool limited); friend void tr_sessionReloadBlocklists(tr_session* session); friend void tr_sessionSet(tr_session* session, tr_variant* settings); diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index 1162ad8ec..9b8a86a43 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -148,32 +148,30 @@ size_t tr_getDefaultDownloadDirToBuf(char* buf, size_t buflen); * * Example: * @code - * tr_variant settings; * int64_t i; * - * tr_variantInitDict(&settings, 0); - * tr_sessionGetDefaultSettings(&settings); + * auto settings = tr_sessionGetDefaultSettings(); * if (tr_variantDictFindInt(&settings, TR_PREFS_KEY_PEER_PORT, &i)) * fprintf(stderr, "the default peer port is %d\n", (int)i); * @endcode * - * @param setme_dictionary pointer to a tr_variant dictionary + * @return a variant map of the default settinggs * @see `tr_sessionLoadSettings()` * @see `tr_sessionInit()` * @see `tr_getDefaultConfigDir()` */ -void tr_sessionGetDefaultSettings(struct tr_variant* setme_dictionary); +tr_variant tr_sessionGetDefaultSettings(); /** * Add the session's current configuration settings to the benc dictionary. * * TODO: if we ever make libtransmissionapp, this would go there. * - * @param session the session to query - * @param setme_dictionary the dictionary to populate + * @return a variant map of the session's current settings + * @param session the session to query * @see `tr_sessionGetDefaultSettings()` */ -void tr_sessionGetSettings(tr_session const* session, struct tr_variant* setme_dictionary); +tr_variant tr_sessionGetSettings(tr_session const* session); /** * Load settings from the configuration directory's settings.json file, @@ -181,15 +179,14 @@ void tr_sessionGetSettings(tr_session const* session, struct tr_variant* setme_d * * TODO: if we ever make libtransmissionapp, this would go there. * - * @param dictionary pointer to an uninitialized tr_variant * @param config_dir the configuration directory to find settings.json * @param app_name if config_dir is empty, app_name is used to find the default dir. - * @return success true if the settings were loaded, false otherwise + * @return the loaded settings * @see `tr_sessionGetDefaultSettings()` * @see `tr_sessionInit()` * @see `tr_sessionSaveSettings()` */ -bool tr_sessionLoadSettings(tr_variant* settings, char const* config_dir, char const* app_name); +tr_variant tr_sessionLoadSettings(char const* config_dir, char const* app_name); /** * Add the session's configuration settings to the benc dictionary @@ -209,14 +206,9 @@ void tr_sessionSaveSettings(tr_session* session, char const* config_dir, struct * * For example, this will instantiate a session with all the default values: * @code - * tr_variant settings; - * tr_session* session; - * char const* configDir; - * - * tr_variantInitDict(&settings, 0); - * tr_sessionGetDefaultSettings(&settings); - * configDir = tr_getDefaultConfigDir("Transmission"); - * session = tr_sessionInit(configDir, true, &settings); + * auto settings = tr_sessionGetDefaultSettings(); + * char const* const configDir = tr_getDefaultConfigDir("Transmission"); + * tr_session* const session = tr_sessionInit(configDir, true, &settings); * @endcode * * @param config_dir where Transmission will look for resume files, blocklists, etc. diff --git a/libtransmission/variant-converters.cc b/libtransmission/variant-converters.cc index af5c92d5e..d2f23b40a 100644 --- a/libtransmission/variant-converters.cc +++ b/libtransmission/variant-converters.cc @@ -57,51 +57,51 @@ auto constexpr VerifyModeKeys = std::array -std::optional VariantConverter::load(tr_variant* src) +std::optional VariantConverter::load(tr_variant const& src) { - if (auto val = bool{}; tr_variantGetBool(src, &val)) + if (auto val = src.get_if(); val != nullptr) { - return val; + return *val; } return {}; } template<> -void VariantConverter::save(tr_variant* tgt, bool const& val) +tr_variant VariantConverter::save(bool const& val) { - tr_variantInitBool(tgt, val); + return val; } // --- template<> -std::optional VariantConverter::load(tr_variant* src) +std::optional VariantConverter::load(tr_variant const& src) { - if (auto val = double{}; tr_variantGetReal(src, &val)) + if (auto val = src.get_if(); val != nullptr) { - return val; + return *val; } return {}; } template<> -void VariantConverter::save(tr_variant* tgt, double const& val) +tr_variant VariantConverter::save(double const& val) { - tr_variantInitReal(tgt, val); + return val; } // --- template<> -std::optional VariantConverter::load(tr_variant* src) +std::optional VariantConverter::load(tr_variant const& src) { static constexpr auto Keys = EncryptionKeys; - if (auto val = std::string_view{}; tr_variantGetStrView(src, &val)) + if (auto const* val = src.get_if(); val != nullptr) { - auto const needle = tr_strlower(tr_strv_strip(val)); + auto const needle = tr_strlower(tr_strv_strip(*val)); for (auto const& [key, encryption] : Keys) { @@ -112,11 +112,11 @@ std::optional VariantConverter::load(tr_ } } - if (auto val = int64_t{}; tr_variantGetInt(src, &val)) + if (auto const* val = src.get_if(); val != nullptr) { for (auto const& [key, encryption] : Keys) { - if (encryption == val) + if (encryption == *val) { return encryption; } @@ -127,21 +127,21 @@ std::optional VariantConverter::load(tr_ } template<> -void VariantConverter::save(tr_variant* tgt, tr_encryption_mode const& val) +tr_variant VariantConverter::save(tr_encryption_mode const& val) { - tr_variantInitInt(tgt, val); + return static_cast(val); } // --- template<> -std::optional VariantConverter::load(tr_variant* src) +std::optional VariantConverter::load(tr_variant const& src) { static constexpr auto Keys = LogKeys; - if (auto val = std::string_view{}; tr_variantGetStrView(src, &val)) + if (auto const* val = src.get_if(); val != nullptr) { - auto const needle = tr_strlower(tr_strv_strip(val)); + auto const needle = tr_strlower(tr_strv_strip(*val)); for (auto const& [name, log_level] : Keys) { @@ -152,11 +152,11 @@ std::optional VariantConverter::load(tr_variant* src } } - if (auto val = int64_t{}; tr_variantGetInt(src, &val)) + if (auto const* val = src.get_if(); val != nullptr) { for (auto const& [name, log_level] : Keys) { - if (log_level == val) + if (log_level == *val) { return log_level; } @@ -167,67 +167,67 @@ std::optional VariantConverter::load(tr_variant* src } template<> -void VariantConverter::save(tr_variant* tgt, tr_log_level const& val) +tr_variant VariantConverter::save(tr_log_level const& val) { - tr_variantInitInt(tgt, val); + return static_cast(val); } // --- template<> -std::optional VariantConverter::load(tr_variant* src) +std::optional VariantConverter::load(tr_variant const& src) { - if (auto val = std::string_view{}; tr_variantGetStrView(src, &val)) + if (auto const* val = src.get_if(); val != nullptr) { - if (auto const mode = tr_num_parse(val, nullptr, 8); mode) + if (auto const mode = tr_num_parse(*val, nullptr, 8); mode) { return static_cast(*mode); } } - if (auto val = int64_t{}; tr_variantGetInt(src, &val)) + if (auto const* val = src.get_if(); val != nullptr) { - return static_cast(val); + return static_cast(*val); } return {}; } template<> -void VariantConverter::save(tr_variant* tgt, tr_mode_t const& val) +tr_variant VariantConverter::save(tr_mode_t const& val) { - tr_variantInitStr(tgt, fmt::format("{:#03o}", val)); + return fmt::format("{:#03o}", val); } // --- template<> -std::optional VariantConverter::load(tr_variant* src) +std::optional VariantConverter::load(tr_variant const& src) { - if (auto val = int64_t{}; tr_variantGetInt(src, &val)) + if (auto const* val = src.get_if(); val != nullptr) { - return tr_port::from_host(val); + return tr_port::from_host(*val); } return {}; } template<> -void VariantConverter::save(tr_variant* tgt, tr_port const& val) +tr_variant VariantConverter::save(tr_port const& val) { - tr_variantInitInt(tgt, val.host()); + return int64_t{ val.host() }; } // --- template<> -std::optional VariantConverter::load(tr_variant* src) +std::optional VariantConverter::load(tr_variant const& src) { static constexpr auto Keys = PreallocationKeys; - if (auto val = std::string_view{}; tr_variantGetStrView(src, &val)) + if (auto const* val = src.get_if(); val != nullptr) { - auto const needle = tr_strlower(tr_strv_strip(val)); + auto const needle = tr_strlower(tr_strv_strip(*val)); for (auto const& [name, value] : Keys) { @@ -238,11 +238,11 @@ std::optional VariantConverter::load(); val != nullptr) { for (auto const& [name, value] : Keys) { - if (value == val) + if (value == *val) { return value; } @@ -253,83 +253,83 @@ std::optional VariantConverter::load -void VariantConverter::save(tr_variant* tgt, tr_preallocation_mode const& val) +tr_variant VariantConverter::save(tr_preallocation_mode const& val) { - tr_variantInitInt(tgt, val); + return int64_t{ val }; } // --- template<> -std::optional VariantConverter::load(tr_variant* src) +std::optional VariantConverter::load(tr_variant const& src) { - if (auto val = int64_t{}; tr_variantGetInt(src, &val)) + if (auto const* val = src.get_if(); val != nullptr) { - return static_cast(val); + return static_cast(*val); } return {}; } template<> -void VariantConverter::save(tr_variant* tgt, size_t const& val) +tr_variant VariantConverter::save(size_t const& val) { - tr_variantInitInt(tgt, val); + return uint64_t{ val }; } // --- template<> -std::optional VariantConverter::load(tr_variant* src) +std::optional VariantConverter::load(tr_variant const& src) { - if (auto val = std::string_view{}; tr_variantGetStrView(src, &val)) + if (auto const* val = src.get_if(); val != nullptr) { - return std::string{ val }; + return std::string{ *val }; } return {}; } template<> -void VariantConverter::save(tr_variant* tgt, std::string const& val) +tr_variant VariantConverter::save(std::string const& val) { - tr_variantInitStr(tgt, val); + return val; } // --- template<> -std::optional VariantConverter::load(tr_variant* src) +std::optional VariantConverter::load(tr_variant const& src) { - if (auto val = std::string_view{}; tr_variantGetStrView(src, &val)) + if (auto const* val = src.get_if(); val != nullptr) { - return tr_tos_t::from_string(val); + return tr_tos_t::from_string(*val); } - if (auto val = int64_t{}; tr_variantGetInt(src, &val)) + if (auto const* val = src.get_if(); val != nullptr) { - return tr_tos_t{ static_cast(val) }; + return tr_tos_t{ static_cast(*val) }; } return {}; } template<> -void VariantConverter::save(tr_variant* tgt, tr_tos_t const& val) +tr_variant VariantConverter::save(tr_tos_t const& val) { - tr_variantInitStr(tgt, val.toString()); + return val.toString(); } // --- template<> -std::optional VariantConverter::load(tr_variant* src) +std::optional VariantConverter::load(tr_variant const& src) { static constexpr auto& Keys = VerifyModeKeys; - if (auto val = std::string_view{}; tr_variantGetStrView(src, &val)) + if (auto const* val = src.get_if(); val != nullptr) { - auto const needle = tr_strlower(tr_strv_strip(val)); + auto const needle = tr_strlower(tr_strv_strip(*val)); for (auto const& [name, value] : Keys) { @@ -340,11 +340,11 @@ std::optional VariantConverter::load } } - if (auto val = int64_t{}; tr_variantGetInt(src, &val)) + if (auto const* val = src.get_if(); val != nullptr) { for (auto const& [name, value] : Keys) { - if (value == val) + if (value == *val) { return value; } @@ -355,18 +355,17 @@ std::optional VariantConverter::load } template<> -void VariantConverter::save(tr_variant* tgt, tr_verify_added_mode const& val) +tr_variant VariantConverter::save(tr_verify_added_mode const& val) { for (auto const& [key, value] : VerifyModeKeys) { if (value == val) { - tr_variantInitStrView(tgt, key); - return; + return key; } } - tr_variantInitInt(tgt, val); + return static_cast(val); } } // namespace libtransmission diff --git a/libtransmission/variant.h b/libtransmission/variant.h index 0ce332208..77a8cca74 100644 --- a/libtransmission/variant.h +++ b/libtransmission/variant.h @@ -51,8 +51,15 @@ public: tr_variant& operator=(tr_variant const&) = delete; tr_variant& operator=(tr_variant&& that) noexcept = default; + [[nodiscard]] static auto make_map() noexcept + { + auto ret = tr_variant{}; + ret.val_.emplace(); + return ret; + } + template - explicit tr_variant(Val value) + tr_variant(Val value) { *this = std::move(value); } @@ -82,6 +89,18 @@ public: return *this; } + tr_variant& operator=(int value) + { + *this = static_cast(value); + return *this; + } + + tr_variant& operator=(uint64_t value) + { + *this = static_cast(value); // hmmm + return *this; + } + [[nodiscard]] constexpr auto index() const noexcept { return val_.index(); @@ -407,10 +426,10 @@ struct VariantConverter { public: template - static std::optional load(tr_variant* src); + static std::optional load(tr_variant const& src); template - static void save(tr_variant* tgt, T const& val); + static tr_variant save(T const& val); }; } // namespace libtransmission diff --git a/macosx/Controller.mm b/macosx/Controller.mm index 832064397..7770905e3 100644 --- a/macosx/Controller.mm +++ b/macosx/Controller.mm @@ -417,9 +417,7 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool //upgrading from versions < 2.40: clear recent items [NSDocumentController.sharedDocumentController clearRecentDocuments:nil]; - tr_variant settings; - tr_variantInitDict(&settings, 41); - tr_sessionGetDefaultSettings(&settings); + auto settings = tr_sessionGetDefaultSettings(); BOOL const usesSpeedLimitSched = [_fDefaults boolForKey:@"SpeedLimitAuto"]; if (!usesSpeedLimitSched) diff --git a/qt/Prefs.cc b/qt/Prefs.cc index 032192198..d6fc0d60b 100644 --- a/qt/Prefs.cc +++ b/qt/Prefs.cc @@ -227,10 +227,8 @@ Prefs::Prefs(QString config_dir) // when the application exits. temporary_prefs_ << FILTER_TEXT; - tr_variant top; - tr_variantInitDict(&top, 0); - initDefaults(&top); - tr_sessionLoadSettings(&top, config_dir_.toUtf8().constData(), nullptr); + auto top = get_default_app_settings(); + top.merge(tr_sessionLoadSettings(config_dir_.toUtf8().constData(), nullptr)); ensureSoundCommandIsAList(&top); for (int i = 0; i < PREFS_COUNT; ++i) @@ -420,7 +418,7 @@ Prefs::~Prefs() * This is where we initialize the preferences file with the default values. * If you add a new preferences key, you /must/ add a default value here. */ -void Prefs::initDefaults(tr_variant* d) const +tr_variant Prefs::get_default_app_settings() { auto constexpr FilterMode = std::string_view{ "all" }; auto constexpr SessionHost = std::string_view{ "localhost" }; @@ -432,46 +430,47 @@ void Prefs::initDefaults(tr_variant* d) const auto const download_dir = tr_getDefaultDownloadDir(); - tr_variantDictReserve(d, 38); - dictAdd(d, TR_KEY_blocklist_updates_enabled, true); - dictAdd(d, TR_KEY_compact_view, false); - dictAdd(d, TR_KEY_inhibit_desktop_hibernation, false); - dictAdd(d, TR_KEY_prompt_before_exit, true); - dictAdd(d, TR_KEY_remote_session_enabled, false); - dictAdd(d, TR_KEY_remote_session_requres_authentication, false); - dictAdd(d, TR_KEY_show_backup_trackers, false); - dictAdd(d, TR_KEY_show_extra_peer_details, false); - dictAdd(d, TR_KEY_show_filterbar, true); - dictAdd(d, TR_KEY_show_notification_area_icon, false); - dictAdd(d, TR_KEY_start_minimized, false); - dictAdd(d, TR_KEY_show_options_window, true); - dictAdd(d, TR_KEY_show_statusbar, true); - dictAdd(d, TR_KEY_show_toolbar, true); - dictAdd(d, TR_KEY_show_tracker_scrapes, false); - dictAdd(d, TR_KEY_sort_reversed, false); - dictAdd(d, TR_KEY_torrent_added_notification_enabled, true); - dictAdd(d, TR_KEY_torrent_complete_notification_enabled, true); - dictAdd(d, TR_KEY_torrent_complete_sound_enabled, true); - dictAdd(d, TR_KEY_user_has_given_informed_consent, false); - dictAdd(d, TR_KEY_watch_dir_enabled, false); - dictAdd(d, TR_KEY_blocklist_date, 0); - dictAdd(d, TR_KEY_main_window_height, 500); - dictAdd(d, TR_KEY_main_window_width, 300); - dictAdd(d, TR_KEY_main_window_x, 50); - dictAdd(d, TR_KEY_main_window_y, 50); - dictAdd(d, TR_KEY_remote_session_port, TR_DEFAULT_RPC_PORT); - dictAdd(d, TR_KEY_download_dir, download_dir); - dictAdd(d, TR_KEY_filter_mode, FilterMode); - dictAdd(d, TR_KEY_main_window_layout_order, WindowLayout); - dictAdd(d, TR_KEY_open_dialog_dir, QDir::home().absolutePath()); - dictAdd(d, TR_KEY_remote_session_https, false); - dictAdd(d, TR_KEY_remote_session_host, SessionHost); - dictAdd(d, TR_KEY_remote_session_password, SessionPassword); - dictAdd(d, TR_KEY_remote_session_username, SessionUsername); - dictAdd(d, TR_KEY_sort_mode, SortMode); - dictAdd(d, TR_KEY_statusbar_stats, StatsMode); - dictAdd(d, TR_KEY_watch_dir, download_dir); - dictAdd(d, TR_KEY_read_clipboard, false); + auto settings = tr_variant::Map{}; + settings.try_emplace(TR_KEY_blocklist_updates_enabled, true); + settings.try_emplace(TR_KEY_compact_view, false); + settings.try_emplace(TR_KEY_inhibit_desktop_hibernation, false); + settings.try_emplace(TR_KEY_prompt_before_exit, true); + settings.try_emplace(TR_KEY_remote_session_enabled, false); + settings.try_emplace(TR_KEY_remote_session_requres_authentication, false); + settings.try_emplace(TR_KEY_show_backup_trackers, false); + settings.try_emplace(TR_KEY_show_extra_peer_details, false); + settings.try_emplace(TR_KEY_show_filterbar, true); + settings.try_emplace(TR_KEY_show_notification_area_icon, false); + settings.try_emplace(TR_KEY_start_minimized, false); + settings.try_emplace(TR_KEY_show_options_window, true); + settings.try_emplace(TR_KEY_show_statusbar, true); + settings.try_emplace(TR_KEY_show_toolbar, true); + settings.try_emplace(TR_KEY_show_tracker_scrapes, false); + settings.try_emplace(TR_KEY_sort_reversed, false); + settings.try_emplace(TR_KEY_torrent_added_notification_enabled, true); + settings.try_emplace(TR_KEY_torrent_complete_notification_enabled, true); + settings.try_emplace(TR_KEY_torrent_complete_sound_enabled, true); + settings.try_emplace(TR_KEY_user_has_given_informed_consent, false); + settings.try_emplace(TR_KEY_watch_dir_enabled, false); + settings.try_emplace(TR_KEY_blocklist_date, 0); + settings.try_emplace(TR_KEY_main_window_height, 500); + settings.try_emplace(TR_KEY_main_window_width, 300); + settings.try_emplace(TR_KEY_main_window_x, 50); + settings.try_emplace(TR_KEY_main_window_y, 50); + settings.try_emplace(TR_KEY_remote_session_port, TR_DEFAULT_RPC_PORT); + settings.try_emplace(TR_KEY_download_dir, download_dir); + settings.try_emplace(TR_KEY_filter_mode, FilterMode); + settings.try_emplace(TR_KEY_main_window_layout_order, WindowLayout); + settings.try_emplace(TR_KEY_open_dialog_dir, QDir::home().absolutePath().toStdString()); + settings.try_emplace(TR_KEY_remote_session_https, false); + settings.try_emplace(TR_KEY_remote_session_host, SessionHost); + settings.try_emplace(TR_KEY_remote_session_password, SessionPassword); + settings.try_emplace(TR_KEY_remote_session_username, SessionUsername); + settings.try_emplace(TR_KEY_sort_mode, SortMode); + settings.try_emplace(TR_KEY_statusbar_stats, StatsMode); + settings.try_emplace(TR_KEY_watch_dir, download_dir); + settings.try_emplace(TR_KEY_read_clipboard, false); + return tr_variant{ std::move(settings) }; } /*** diff --git a/qt/Prefs.h b/qt/Prefs.h index 9ddfd51c2..b0e5165e6 100644 --- a/qt/Prefs.h +++ b/qt/Prefs.h @@ -198,7 +198,7 @@ private: int type; }; - void initDefaults(tr_variant*) const; + [[nodiscard]] static tr_variant get_default_app_settings(); void set(int key, char const* value) = delete; diff --git a/qt/Session.cc b/qt/Session.cc index 1e5b1d679..d512b2e1f 100644 --- a/qt/Session.cc +++ b/qt/Session.cc @@ -356,9 +356,7 @@ void Session::start() } else { - tr_variant settings; - tr_variantInitDict(&settings, 0); - tr_sessionLoadSettings(&settings, config_dir_.toUtf8().constData(), "qt"); + auto settings = tr_sessionLoadSettings(config_dir_.toUtf8().constData(), "qt"); session_ = tr_sessionInit(config_dir_.toUtf8().constData(), true, &settings); rpc_.start(session_); diff --git a/tests/libtransmission/session-test.cc b/tests/libtransmission/session-test.cc index 6590407fd..8a87926ef 100644 --- a/tests/libtransmission/session-test.cc +++ b/tests/libtransmission/session-test.cc @@ -282,9 +282,7 @@ TEST_F(SessionTest, sessionId) TEST_F(SessionTest, getDefaultSettingsIncludesSubmodules) { - auto settings = tr_variant{}; - tr_variantInitDict(&settings, 0); - tr_sessionGetDefaultSettings(&settings); + auto settings = tr_sessionGetDefaultSettings(); // Choose a setting from each of [tr_session, tr_session_alt_speeds, tr_rpc_server] to test all of them. // These are all `false` by default @@ -305,9 +303,7 @@ TEST_F(SessionTest, honorsSettings) // Choose a setting from each of [tr_session, tr_session_alt_speeds, tr_rpc_server] to test all of them. // These are all `false` by default - auto settings = tr_variant{}; - tr_variantInitDict(&settings, 0); - tr_sessionGetDefaultSettings(&settings); + auto settings = tr_sessionGetDefaultSettings(); for (auto const& key : { TR_KEY_peer_port_random_on_start, TR_KEY_alt_speed_time_enabled, TR_KEY_rpc_enabled }) { tr_variantDictRemove(&settings, key); @@ -335,9 +331,7 @@ TEST_F(SessionTest, savesSettings) tr_sessionSetRPCEnabled(session_, true); // Choose a setting from each of [tr_session, tr_session_alt_speeds, tr_rpc_server] to test all of them. - auto settings = tr_variant{}; - tr_variantInitDict(&settings, 0); - tr_sessionGetSettings(session_, &settings); + auto settings = tr_sessionGetSettings(session_); for (auto const& key : { TR_KEY_peer_port_random_on_start, TR_KEY_alt_speed_time_enabled, TR_KEY_rpc_enabled }) { auto flag = bool{}; diff --git a/tests/libtransmission/settings-test.cc b/tests/libtransmission/settings-test.cc index 133165e9a..b1b902076 100644 --- a/tests/libtransmission/settings-test.cc +++ b/tests/libtransmission/settings-test.cc @@ -30,9 +30,8 @@ TEST_F(SettingsTest, canInstantiate) { auto settings = tr_session_settings{}; - auto var = tr_variant{}; - tr_variantInitDict(&var, 100); - settings.save(&var); + auto var = settings.settings(); + EXPECT_TRUE(var.has_value()); } TEST_F(SettingsTest, canLoadBools) @@ -45,7 +44,7 @@ TEST_F(SettingsTest, canLoadBools) auto var = tr_variant{}; tr_variantInitDict(&var, 1); tr_variantDictAddBool(&var, Key, expected_value); - settings.load(&var); + settings.load(var); EXPECT_EQ(expected_value, settings.seed_queue_enabled); } @@ -58,9 +57,7 @@ TEST_F(SettingsTest, canSaveBools) auto const expected_value = !settings.seed_queue_enabled; settings.seed_queue_enabled = expected_value; - auto var = tr_variant{}; - tr_variantInitDict(&var, 100); - settings.save(&var); + auto var = settings.settings(); auto val = bool{}; EXPECT_TRUE(tr_variantDictFindBool(&var, Key, &val)); EXPECT_EQ(expected_value, val); @@ -76,7 +73,7 @@ TEST_F(SettingsTest, canLoadDoubles) auto var = tr_variant{}; tr_variantInitDict(&var, 1); tr_variantDictAddReal(&var, Key, expected_value); - settings.load(&var); + settings.load(var); EXPECT_NEAR(expected_value, settings.ratio_limit, 0.001); } @@ -89,9 +86,7 @@ TEST_F(SettingsTest, canSaveDoubles) auto const expected_value = !default_value; settings.seed_queue_enabled = expected_value; - auto var = tr_variant{}; - tr_variantInitDict(&var, 100); - settings.save(&var); + auto var = settings.settings(); auto val = bool{}; EXPECT_TRUE(tr_variantDictFindBool(&var, Key, &val)); EXPECT_EQ(expected_value, val); @@ -108,14 +103,14 @@ TEST_F(SettingsTest, canLoadEncryptionMode) auto var = tr_variant{}; tr_variantInitDict(&var, 1); tr_variantDictAddInt(&var, Key, ExpectedValue); - settings->load(&var); + settings->load(var); EXPECT_EQ(ExpectedValue, settings->encryption_mode); var.clear(); settings = std::make_unique(); tr_variantInitDict(&var, 1); tr_variantDictAddStrView(&var, Key, "required"); - settings->load(&var); + settings->load(var); EXPECT_EQ(ExpectedValue, settings->encryption_mode); } @@ -128,9 +123,7 @@ TEST_F(SettingsTest, canSaveEncryptionMode) EXPECT_NE(ExpectedValue, settings.seed_queue_enabled); settings.encryption_mode = ExpectedValue; - auto var = tr_variant{}; - tr_variantInitDict(&var, 100); - settings.save(&var); + auto var = settings.settings(); auto val = int64_t{}; EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val)); EXPECT_EQ(ExpectedValue, val); @@ -148,14 +141,14 @@ TEST_F(SettingsTest, canLoadLogLevel) auto var = tr_variant{}; tr_variantInitDict(&var, 1); tr_variantDictAddInt(&var, Key, ExpectedValue); - settings->load(&var); + settings->load(var); EXPECT_EQ(ExpectedValue, settings->log_level); var.clear(); settings = std::make_unique(); tr_variantInitDict(&var, 1); tr_variantDictAddStrView(&var, Key, "debug"); - settings->load(&var); + settings->load(var); EXPECT_EQ(ExpectedValue, settings->log_level); } @@ -168,10 +161,8 @@ TEST_F(SettingsTest, canSaveLogLevel) auto constexpr ExpectedValue = TR_LOG_DEBUG; ASSERT_NE(ExpectedValue, default_value); - auto var = tr_variant{}; - tr_variantInitDict(&var, 100); settings.log_level = ExpectedValue; - settings.save(&var); + auto var = settings.settings(); auto val = int64_t{}; EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val)); EXPECT_EQ(ExpectedValue, val); @@ -189,14 +180,14 @@ TEST_F(SettingsTest, canLoadMode) auto var = tr_variant{}; tr_variantInitDict(&var, 1); tr_variantDictAddInt(&var, Key, ExpectedValue); - settings->load(&var); + settings->load(var); EXPECT_EQ(ExpectedValue, settings->umask); var.clear(); settings = std::make_unique(); tr_variantInitDict(&var, 1); tr_variantDictAddStrView(&var, Key, "0777"); - settings->load(&var); + settings->load(var); EXPECT_EQ(ExpectedValue, settings->umask); } @@ -209,10 +200,8 @@ TEST_F(SettingsTest, canSaveMode) auto constexpr ExpectedValue = tr_mode_t{ 0777 }; ASSERT_NE(ExpectedValue, default_value); - auto var = tr_variant{}; - tr_variantInitDict(&var, 100); settings.umask = ExpectedValue; - settings.save(&var); + auto var = settings.settings(); auto val = std::string_view{}; EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val)); EXPECT_EQ("0777", val); @@ -230,7 +219,7 @@ TEST_F(SettingsTest, canLoadPort) auto var = tr_variant{}; tr_variantInitDict(&var, 1); tr_variantDictAddInt(&var, Key, ExpectedValue.host()); - settings.load(&var); + settings.load(var); EXPECT_EQ(ExpectedValue, settings.peer_port); } @@ -243,10 +232,8 @@ TEST_F(SettingsTest, canSavePort) auto constexpr ExpectedValue = tr_port::from_host(8080); ASSERT_NE(ExpectedValue, default_value); - auto var = tr_variant{}; - tr_variantInitDict(&var, 100); settings.peer_port = ExpectedValue; - settings.save(&var); + auto var = settings.settings(); auto val = int64_t{}; EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val)); EXPECT_EQ(ExpectedValue.host(), val); @@ -264,14 +251,14 @@ TEST_F(SettingsTest, canLoadPreallocation) auto var = tr_variant{}; tr_variantInitDict(&var, 1); tr_variantDictAddInt(&var, Key, ExpectedValue); - settings->load(&var); + settings->load(var); EXPECT_EQ(ExpectedValue, settings->preallocation_mode); var.clear(); settings = std::make_unique(); tr_variantInitDict(&var, 1); tr_variantDictAddStrView(&var, Key, "full"); - settings->load(&var); + settings->load(var); EXPECT_EQ(ExpectedValue, settings->preallocation_mode); } @@ -284,10 +271,8 @@ TEST_F(SettingsTest, canSavePreallocation) auto constexpr ExpectedValue = TR_PREALLOCATE_FULL; ASSERT_NE(ExpectedValue, default_value); - auto var = tr_variant{}; - tr_variantInitDict(&var, 100); settings.preallocation_mode = ExpectedValue; - settings.save(&var); + auto var = settings.settings(); auto val = int64_t{}; EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val)); EXPECT_EQ(ExpectedValue, val); @@ -303,7 +288,7 @@ TEST_F(SettingsTest, canLoadSizeT) auto var = tr_variant{}; tr_variantInitDict(&var, 1); tr_variantDictAddInt(&var, Key, expected_value); - settings.load(&var); + settings.load(var); EXPECT_EQ(expected_value, settings.queue_stalled_minutes); } @@ -314,10 +299,8 @@ TEST_F(SettingsTest, canSaveSizeT) auto settings = tr_session_settings{}; auto const expected_value = settings.queue_stalled_minutes + 5U; - auto var = tr_variant{}; - tr_variantInitDict(&var, 100); settings.queue_stalled_minutes = expected_value; - settings.save(&var); + auto var = settings.settings(); auto val = int64_t{}; EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val)); EXPECT_EQ(expected_value, static_cast(val)); @@ -334,7 +317,7 @@ TEST_F(SettingsTest, canLoadString) auto var = tr_variant{}; tr_variantInitDict(&var, 1); tr_variantDictAddStrView(&var, Key, ChangedValue); - settings.load(&var); + settings.load(var); EXPECT_EQ(ChangedValue, settings.bind_address_ipv4); } @@ -346,10 +329,8 @@ TEST_F(SettingsTest, canSaveString) auto settings = tr_session_settings{}; EXPECT_NE(ChangedValue, tr_session_settings{}.bind_address_ipv4); - auto var = tr_variant{}; - tr_variantInitDict(&var, 100); settings.bind_address_ipv4 = ChangedValue; - settings.save(&var); + auto var = settings.settings(); auto val = std::string_view{}; EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val)); EXPECT_EQ(ChangedValue, val); @@ -367,14 +348,14 @@ TEST_F(SettingsTest, canLoadTos) auto var = tr_variant{}; tr_variantInitDict(&var, 1); tr_variantDictAddInt(&var, Key, 0x20); - settings->load(&var); + settings->load(var); EXPECT_EQ(ChangedValue, settings->peer_socket_tos); var.clear(); settings = std::make_unique(); tr_variantInitDict(&var, 1); tr_variantDictAddStrView(&var, Key, "cs1"); - settings->load(&var); + settings->load(var); EXPECT_EQ(ChangedValue, settings->peer_socket_tos); } @@ -386,10 +367,8 @@ TEST_F(SettingsTest, canSaveTos) auto settings = tr_session_settings{}; ASSERT_NE(ChangedValue, settings.peer_socket_tos); - auto var = tr_variant{}; - tr_variantInitDict(&var, 100); settings.peer_socket_tos = tr_tos_t(0x20); - settings.save(&var); + auto var = settings.settings(); auto val = std::string_view{}; EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val)); EXPECT_EQ(ChangedValue.toString(), val); @@ -407,14 +386,14 @@ TEST_F(SettingsTest, canLoadVerify) auto var = tr_variant{}; tr_variantInitDict(&var, 1); tr_variantDictAddStrView(&var, Key, "full"); - settings->load(&var); + settings->load(var); EXPECT_EQ(ChangedValue, settings->torrent_added_verify_mode); var.clear(); settings = std::make_unique(); tr_variantInitDict(&var, 1); tr_variantDictAddInt(&var, Key, ChangedValue); - settings->load(&var); + settings->load(var); EXPECT_EQ(ChangedValue, settings->torrent_added_verify_mode); } @@ -426,10 +405,8 @@ TEST_F(SettingsTest, canSaveVerify) auto settings = tr_session_settings{}; ASSERT_NE(ChangedValue, settings.torrent_added_verify_mode); - auto var = tr_variant{}; - tr_variantInitDict(&var, 100); settings.torrent_added_verify_mode = ChangedValue; - settings.save(&var); + auto var = settings.settings(); auto val = std::string_view{}; EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val)); EXPECT_EQ("full", val);