diff --git a/data/gui/window/addon_list.cfg b/data/gui/window/addon_list.cfg index d4ab8096b6d..c9c62ea4caa 100644 --- a/data/gui/window/addon_list.cfg +++ b/data/gui/window/addon_list.cfg @@ -640,28 +640,9 @@ horizontal_alignment = "left" - # TODO: maybe do this in the source code? [menu_button] + id = "install_status_filter" definition = "default" - [option] - label = "All Add-ons" - [/option] - - [option] - label = "Installed" - [/option] - - [option] - label = "Upgradable" - [/option] - - [option] - label = "Not Installed" - [/option] - - [option] - label = "Not Uploaded" - [/option] [/menu_button] [/column] diff --git a/src/gui/dialogs/addon/manager.cpp b/src/gui/dialogs/addon/manager.cpp index 62f4de575c1..93d64a930dd 100644 --- a/src/gui/dialogs/addon/manager.cpp +++ b/src/gui/dialogs/addon/manager.cpp @@ -23,15 +23,18 @@ #include "desktop/clipboard.hpp" #include "desktop/open.hpp" +#include "config_assign.hpp" #include "help/help.hpp" #include "gettext.hpp" #include "gui/auxiliary/filter.hpp" #include "gui/auxiliary/find_widget.hpp" +#include "gui/dialogs/addon/filter_options.hpp" #include "gui/dialogs/helper.hpp" #include "gui/dialogs/message.hpp" #include "gui/widgets/addon_list.hpp" #include "gui/widgets/button.hpp" #include "gui/widgets/label.hpp" +#include "gui/widgets/menu_button.hpp" #include "gui/widgets/stacked_widget.hpp" #include "gui/widgets/drawing.hpp" #include "gui/widgets/image.hpp" @@ -45,9 +48,9 @@ #include "gui/widgets/toggle_button.hpp" #include "gui/widgets/text_box.hpp" #include "gui/widgets/window.hpp" -#include "gui/dialogs/addon/filter_options.hpp" #include "serialization/string_utils.hpp" #include "formula/string_utils.hpp" +#include "language.hpp" #include "preferences.hpp" #include "utils/general.hpp" @@ -151,6 +154,56 @@ namespace { } return it->second; } + + std::string make_display_dependencies(const std::string& addon_id, + const addons_list& addons_list, + const addons_tracking_list& addon_states) + { + const addon_info& addon = const_at(addon_id, addons_list); + std::string str; + + const std::set& deps = addon.resolve_dependencies(addons_list); + + for(const auto& dep_id : deps) { + addon_info dep; + addon_tracking_info depstate; + + addons_list::const_iterator ali = addons_list.find(dep_id); + addons_tracking_list::const_iterator tli = addon_states.find(dep_id); + + if(ali == addons_list.end()) { + dep.id = dep_id; // Build dummy addon_info. + } else { + dep = ali->second; + } + + if(tli == addon_states.end()) { + depstate = get_addon_tracking_info(dep); + } else { + depstate = tli->second; + } + + if(!str.empty()) { + str += ", "; + } + + str += addon_list::colorify_addon_state_string(dep.display_title(), depstate.state); + } + + return str; + } + + std::string langcode_to_string(const std::string& lcode) + { + for(const auto & ld : get_languages()) + { + if(ld.localename == lcode || ld.localename.substr(0, 2) == lcode) { + return ld.language; + } + } + + return ""; + } } REGISTER_DIALOG(addon_manager) @@ -163,6 +216,12 @@ addon_manager::addon_manager(addons_client& client) , addons_() , tracking_info_() { + status_filter_types_ = { + {FILTER_ALL, _("addons_view^All Add-ons")}, + {FILTER_INSTALLED, _("addons_view^Installed")}, + {FILTER_UPGRADABLE, _("addons_view^Upgradable")}, + {FILTER_NOT_INSTALLED, _("addons_view^Not Installed")}, + }; } void addon_manager::on_filtertext_changed(text_box_base* textbox, const std::string& text) @@ -191,57 +250,44 @@ static std::string describe_status_verbose(const addon_tracking_info& state) { std::string s; - utils::string_map i18n_symbols; - i18n_symbols["local_version"] = state.installed_version.str(); + utils::string_map i18n_symbols {{"local_version", state.installed_version.str()}}; switch(state.state) { case ADDON_NONE: - if(!state.can_publish) { - s = _("addon_state^Not installed"); - } else { - s = _("addon_state^Published, not installed"); - } + s = !state.can_publish + ? _("addon_state^Not installed") + : _("addon_state^Published, not installed"); break; case ADDON_INSTALLED: - if(!state.can_publish) { - s = _("addon_state^Installed"); - } else { - s = _("addon_state^Published"); - } + s = !state.can_publish + ? _("addon_state^Installed") + : _("addon_state^Published"); break; case ADDON_NOT_TRACKED: - if(!state.can_publish) { - s = _("addon_state^Installed, not tracking local version"); - } else { + s = !state.can_publish + ? _("addon_state^Installed, not tracking local version") // Published add-ons often don't have local status information, // hence untracked. This should be considered normal. - s = _("addon_state^Published, not tracking local version"); - } + : _("addon_state^Published, not tracking local version"); break; case ADDON_INSTALLED_UPGRADABLE: { - const std::string vstr - = !state.can_publish - ? _("addon_state^Installed ($local_version|), " - "upgradable") - : _("addon_state^Published ($local_version| " - "installed), upgradable"); + const std::string vstr = !state.can_publish + ? _("addon_state^Installed ($local_version|), upgradable") + : _("addon_state^Published ($local_version| installed), upgradable"); + s = utils::interpolate_variables_into_string(vstr, &i18n_symbols); } break; case ADDON_INSTALLED_OUTDATED: { - const std::string vstr - = !state.can_publish - ? _("addon_state^Installed ($local_version|), " - "outdated on server") - : _("addon_state^Published ($local_version| " - "installed), outdated on server"); + const std::string vstr = !state.can_publish + ? _("addon_state^Installed ($local_version|), outdated on server") + : _("addon_state^Published ($local_version| installed), outdated on server"); + s = utils::interpolate_variables_into_string(vstr, &i18n_symbols); } break; case ADDON_INSTALLED_BROKEN: - if(!state.can_publish) { - s = _("addon_state^Installed, broken"); - } else { - s = _("addon_state^Published, broken"); - } + s = !state.can_publish + ? _("addon_state^Installed, broken") + : _("addon_state^Published, broken"); break; default: s = _("addon_state^Unknown"); @@ -259,20 +305,29 @@ void addon_manager::pre_show(window& window) #ifdef GUI2_EXPERIMENTAL_LISTBOX connect_signal_notify_modified(list, - std::bind(&addon_manager::on_addon_select, - *this, - std::ref(window))); + std::bind(&addon_manager::on_addon_select, *this, std::ref(window))); #else list.set_install_function(std::bind(&addon_manager::install_addon, this, std::placeholders::_1, std::ref(window))); list.set_uninstall_function(std::bind(&addon_manager::uninstall_addon, this, std::placeholders::_1, std::ref(window))); list.set_callback_value_change( - dialog_callback); + dialog_callback); #endif load_addon_list(window); + menu_button& status_filter = find_widget(&window, "install_status_filter", false); + + std::vector status_filter_entries; + for(const auto& filter : status_filter_types_) { + status_filter_entries.push_back(config_of("label", filter.second)); + } + + // TODO: initial selection based on preferences + status_filter.set_values(status_filter_entries); + status_filter.connect_click_handler(std::bind(&addon_manager::status_filter_callback, this, std::ref(window))); + button& url_go_button = find_widget