Skip to content

Commit

Permalink
Add sort order dropdown to add-on manager (#1747)
Browse files Browse the repository at this point in the history
This dropdown allows the player to sort add-ons by name, author, size,
download count, type, or the time of last update or original upload.
Sorting by the last two hasn't been possible in the GUI2 add-on manager
before.

Closes #1747.
  • Loading branch information
jyrkive committed Feb 10, 2018
1 parent ce363f4 commit 3b88de6
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 2 deletions.
2 changes: 2 additions & 0 deletions changelog
@@ -1,5 +1,7 @@
Version 1.13.11:
* Add-ons client:
* Added an order dropdown that allows you to sort add-ons by the time of
latest update or original upload (issue #1747)
* Players will now be prompted to update outdated dependencies alongside
missing once when installing an add-on.
* Campaigns:
Expand Down
27 changes: 26 additions & 1 deletion data/gui/window/addon_manager.cfg
Expand Up @@ -735,7 +735,7 @@
[/column]

[column]
grow_factor = 1
grow_factor = 0
border = "all"
border_size = 5

Expand All @@ -748,6 +748,31 @@
[/multimenu_button]
[/column]

[column]
grow_factor = 0
border = "all"
border_size = 5
horizontal_alignment = "left"

[label]
definition = "default"
label = _ "Order:"
[/label]
[/column]

[column]
grow_factor = 1
border = "all"
border_size = 5

horizontal_alignment = "left"

[menu_button]
id = "order_dropdown"
definition = "default"
[/menu_button]
[/column]

[column]
grow_factor = 0
border = "all"
Expand Down
3 changes: 3 additions & 0 deletions players_changelog
Expand Up @@ -3,6 +3,9 @@ changes may be omitted). For a complete list of changes, see the main
changelog: https://github.com/wesnoth/wesnoth/blob/master/changelog

Version 1.13.11:
* Add-ons client:
* Added an order dropdown that allows you to sort add-ons by the time of
latest update or original upload (issue #1747)
* Campaigns:
* An Orcish Incursion:
* New story art.
Expand Down
59 changes: 58 additions & 1 deletion src/gui/dialogs/addon/manager.cpp
Expand Up @@ -30,7 +30,6 @@
#include "gui/dialogs/helper.hpp"
#include "gui/dialogs/message.hpp"
#include "gui/dialogs/transient_message.hpp"
#include "gui/widgets/addon_list.hpp"
#include "gui/widgets/button.hpp"
#include "gui/widgets/label.hpp"
#include "gui/widgets/menu_button.hpp"
Expand Down Expand Up @@ -212,6 +211,30 @@ const std::vector<std::pair<ADDON_TYPE, std::string>> addon_manager::type_filter
{ADDON_UNKNOWN, N_("addons_of_type^Unknown")},
};

const std::vector<addon_manager::addon_order> addon_manager::all_orders_{
{N_("addons_order^Name ($order)"),
[](const addon_info& a, const addon_info& b) { return a.title < b.title; },
[](const addon_info& a, const addon_info& b) { return a.title > b.title; }},
{N_("addons_order^Author ($order)"),
[](const addon_info& a, const addon_info& b) { return a.author < b.author; },
[](const addon_info& a, const addon_info& b) { return a.author > b.author; }},
{N_("addons_order^Size ($order)"),
[](const addon_info& a, const addon_info& b) { return a.size < b.size; },
[](const addon_info& a, const addon_info& b) { return a.size > b.size; }},
{N_("addons_order^Downloads ($order)"),
[](const addon_info& a, const addon_info& b) { return a.downloads < b.downloads; },
[](const addon_info& a, const addon_info& b) { return a.downloads > b.downloads; }},
{N_("addons_order^Type ($order)"),
[](const addon_info& a, const addon_info& b) { return a.display_type() < b.display_type(); },
[](const addon_info& a, const addon_info& b) { return a.display_type() > b.display_type(); }},
{N_("addons_order^Last updated ($order)"),
[](const addon_info& a, const addon_info& b) { return a.updated < b.updated; },
[](const addon_info& a, const addon_info& b) { return a.updated > b.updated; }},
{N_("addons_order^First uploaded ($order)"),
[](const addon_info& a, const addon_info& b) { return a.created < b.created; },
[](const addon_info& a, const addon_info& b) { return a.created > b.created; }}
};

addon_manager::addon_manager(addons_client& client)
: orders_()
, cfg_()
Expand Down Expand Up @@ -329,6 +352,25 @@ void addon_manager::pre_show(window& window)

connect_signal_notify_modified(type_filter, std::bind(&addon_manager::apply_filters, this, std::ref(window)));

menu_button& order_dropdown = find_widget<menu_button>(&window, "order_dropdown", false);

std::vector<config> order_dropdown_entries;
for(const auto& f : all_orders_) {
utils::string_map symbols;

// TRANSLATORS: ascending
symbols["order"] = _("asc");
config entry{"label", VGETTEXT(f.label.c_str(), symbols)};
order_dropdown_entries.push_back(entry);
// TRANSLATORS: descending
symbols["order"] = _("desc");
entry["label"] = VGETTEXT(f.label.c_str(), symbols);
order_dropdown_entries.push_back(entry);
}

order_dropdown.set_values(order_dropdown_entries);
order_dropdown.connect_click_handler(std::bind(&addon_manager::order_addons, this, std::ref(window)));

button& url_go_button = find_widget<button>(&window, "url_go", false);
button& url_copy_button = find_widget<button>(&window, "url_copy", false);
text_box& url_textbox = find_widget<text_box>(&window, "url", false);
Expand Down Expand Up @@ -555,6 +597,21 @@ void addon_manager::apply_filters(window& window)
find_widget<addon_list>(&window, "addons", false).set_addon_shown(res);
}

void addon_manager::order_addons(window& window)
{
const menu_button& order_menu = find_widget<const menu_button>(&window, "order_dropdown", false);
const addon_order& order_struct = all_orders_.at(order_menu.get_value() / 2);
sort_order order = order_menu.get_value() % 2 == 0 ? sort_order::ascending : sort_order::descending;
addon_list::addon_sort_func func;
if(order == sort_order::ascending) {
func = order_struct.sort_func_asc;
} else {
func = order_struct.sort_func_desc;
}

find_widget<addon_list>(&window, "addons", false).set_addon_order(func);
}

template<void(addon_manager::*fptr)(const addon_info& addon, window& window)>
void addon_manager::execute_action_on_selected_addon(window& window)
{
Expand Down
16 changes: 16 additions & 0 deletions src/gui/dialogs/addon/manager.hpp
Expand Up @@ -19,6 +19,7 @@
#include "addon/state.hpp"

#include "gui/dialogs/modal_dialog.hpp"
#include "gui/widgets/addon_list.hpp"
#include "gui/widgets/pane.hpp"

#include <boost/dynamic_bitset.hpp>
Expand Down Expand Up @@ -46,6 +47,19 @@ class addon_manager : public modal_dialog
}

private:
enum class sort_order {ascending, descending};

struct addon_order
{
std::string label;
addon_list::addon_sort_func sort_func_asc;
addon_list::addon_sort_func sort_func_desc;

addon_order(std::string label_, addon_list::addon_sort_func sort_func_asc_, addon_list::addon_sort_func sort_func_desc_)
: label(label_), sort_func_asc(sort_func_asc_), sort_func_desc(sort_func_desc_)
{}
};

void on_filtertext_changed(text_box_base* textbox);

std::vector<selectable_item*> orders_;
Expand Down Expand Up @@ -75,6 +89,7 @@ class addon_manager : public modal_dialog

static const std::vector<std::pair<ADDON_STATUS_FILTER, std::string>> status_filter_types_;
static const std::vector<std::pair<ADDON_TYPE, std::string>> type_filter_types_;
static const std::vector<addon_order> all_orders_;

bool need_wml_cache_refresh_;

Expand Down Expand Up @@ -123,6 +138,7 @@ class addon_manager : public modal_dialog
void copy_url_callback(text_box& url_box);

void apply_filters(window& window);
void order_addons(window& window);
void show_help();

boost::dynamic_bitset<> get_name_filter_visibility(const window& window) const;
Expand Down
14 changes: 14 additions & 0 deletions src/gui/widgets/addon_list.cpp
Expand Up @@ -24,6 +24,7 @@
#include "gui/core/event/dispatcher.hpp"
#include "gui/core/register_widget.hpp"
#include "gui/widgets/button.hpp"
#include "gui/widgets/generator.hpp"
#include "gui/widgets/label.hpp"
#include "gui/widgets/listbox.hpp"
#include "gui/widgets/settings.hpp"
Expand Down Expand Up @@ -362,6 +363,19 @@ void addon_list::finalize_setup()
list.set_active_sorting_option(order);
}

void addon_list::set_addon_order(addon_sort_func func)
{
listbox& list = get_listbox();

generator_base::order_func generator_func = [this, func](unsigned a, unsigned b)
{
return func(*addon_vector_[a], *addon_vector_[b]);
};

list.mark_as_unsorted();
list.order_by(generator_func);
}

void addon_list::select_first_addon()
{
if(addon_vector_.empty()) {
Expand Down
4 changes: 4 additions & 0 deletions src/gui/widgets/addon_list.hpp
Expand Up @@ -38,6 +38,8 @@ class addon_list : public container_base
friend struct implementation::builder_addon_list;

public:
using addon_sort_func = std::function<bool(const addon_info&, const addon_info&)>;

explicit addon_list(const implementation::builder_addon_list& builder);

/** Special retval for the toggle panels in the addons list */
Expand Down Expand Up @@ -106,6 +108,8 @@ class addon_list : public container_base
get_listbox().set_row_shown(shown);
}

void set_addon_order(addon_sort_func func);

/**
* Changes the color of an add-on state string (installed, outdated, etc.) according to the state itself.
* This function is here because the add-on list widget itself needs it.
Expand Down
9 changes: 9 additions & 0 deletions src/gui/widgets/listbox.cpp
Expand Up @@ -656,6 +656,15 @@ const listbox::order_pair listbox::get_active_sorting_option()
return std::make_pair(-1, SORT_NONE);
}

void listbox::mark_as_unsorted()
{
for(auto& pair : orders_) {
if(pair.first != nullptr) {
pair.first->set_value(SORT_NONE);
}
}
}

void listbox::set_content_size(const point& origin, const point& size)
{
/** @todo This function needs more testing. */
Expand Down
3 changes: 3 additions & 0 deletions src/gui/widgets/listbox.hpp
Expand Up @@ -288,6 +288,9 @@ class listbox : public scrollbar_container

const order_pair get_active_sorting_option();

/** Deactivates all sorting toggle buttons at the top, making the list look like it's not sorted. */
void mark_as_unsorted();

protected:
/***** ***** ***** ***** keyboard functions ***** ***** ***** *****/

Expand Down

0 comments on commit 3b88de6

Please sign in to comment.