16 #define GETTEXT_DOMAIN "wesnoth-lib"
47 , rng_mode_(RNG_DEFAULT)
51 , current_difficulty_()
52 , current_sorting_(RANK)
53 , currently_sorted_asc_(true)
56 set_show_even_without_video(
true);
57 set_allow_plugin_skip(
false);
62 tree_view& tree = find_widget<tree_view>(
"campaign_tree");
71 if(!campaign_id.empty()) {
74 button& ok_button = find_widget<button>(
"proceed");
76 ok_button.
set_label((campaign_id ==
addons_) ?
_(
"game^Get Add-ons") :
_(
"game^Play"));
78 const int choice = std::distance(
page_ids_.begin(), iter);
83 multi_page& pages = find_widget<multi_page>(
"campaign_details");
88 styled_widget& background = find_widget<styled_widget>(
"campaign_background");
94 auto& diff_menu = find_widget<menu_button>(
"difficulty_menu");
97 diff_menu.set_active(diff_config.child_count(
"difficulty") > 1);
99 if(!diff_config.empty()) {
100 std::vector<config> entry_list;
101 unsigned n = 0, selection = 0, max_n = diff_config.child_count(
"difficulty");
103 for(
const auto& cfg : diff_config.child_range(
"difficulty")) {
107 entry[
"label"] = cfg[
"label"].str() +
" (" + cfg[
"description"].str() +
")";
108 entry[
"image"] = cfg[
"image"].str(
"misc/blank-hex.png");
110 if(
prefs::get().is_campaign_completed(campaign_id, cfg[
"define"])) {
121 entry[
"image"] = laurel +
"~BLIT(" + entry[
"image"].str() +
")";
124 if(!cfg[
"description"].empty()) {
126 if(cfg[
"auto_markup"].to_bool(
true) ==
false) {
127 desc = cfg[
"description"].str();
129 if(!cfg[
"old_markup"].to_bool()) {
138 desc = cfg[
"label"].str() +
"\n" + desc;
140 entry[
"details"] = std::move(desc);
143 entry_list.emplace_back(std::move(entry));
146 if(cfg[
"default"].to_bool(
false)) {
153 diff_menu.set_values(entry_list);
154 diff_menu.set_selected(selection);
161 const std::size_t selection = find_widget<menu_button>(
"difficulty_menu").get_value();
181 std::sort(levels.begin(), levels.end(), [ascending](
const level_ptr& a,
const level_ptr&
b) {
182 auto cpn_a = std::dynamic_pointer_cast<ng::campaign>(a);
183 auto cpn_b = std::dynamic_pointer_cast<ng::campaign>(b);
185 if(cpn_b == nullptr) {
186 return cpn_a != nullptr;
189 if(cpn_a ==
nullptr) {
194 ? cpn_a->dates().first < cpn_b->dates().first
195 : cpn_a->dates().first > cpn_b->dates().first;
201 std::sort(levels.begin(), levels.end(), [ascending](
const level_ptr& a,
const level_ptr&
b) {
202 const int cmp = translation::icompare(a->name(), b->name());
203 return ascending ? cmp < 0 : cmp > 0;
209 tree_view& tree = find_widget<tree_view>(
"campaign_tree");
212 std::string was_selected;
218 boost::dynamic_bitset<> show_items;
219 show_items.resize(levels.size(),
true);
221 if(!last_search_words_.empty()) {
222 for(
unsigned i = 0;
i < levels.size(); ++
i) {
224 for(
const auto& word : last_search_words_) {
237 show_items[
i] = found;
242 boost::dynamic_bitset<> filter_comp_options = find_widget<multimenu_button>(
"filter_completion").get_toggle_states();
244 bool exists_in_filtered_result =
false;
245 for(
unsigned i = 0;
i < levels.size(); ++
i) {
248 auto did_complete_at = [](
const config&
c) {
return c[
"completed_at"].to_bool(); };
251 const bool only_first_completed = difficulties.size() > 1 &&
252 std::none_of(difficulties.begin() + 1, difficulties.end(), did_complete_at);
253 const bool completed_easy = only_first_completed && did_complete_at(difficulties.front());
254 const bool completed_hardest = !difficulties.empty() && did_complete_at(difficulties.back());
255 const bool completed_mid = completed && !completed_hardest && !completed_easy;
257 if( show_items[
i] && (
258 ( (!completed) && filter_comp_options[0] )
259 || ( completed && filter_comp_options[4] )
260 || ( completed_hardest && filter_comp_options[3] )
261 || ( completed_easy && filter_comp_options[1] )
262 || ( completed_mid && filter_comp_options[2])
264 add_campaign_to_tree(levels[
i]->
data());
265 if (!exists_in_filtered_result) {
266 exists_in_filtered_result = levels[
i]->id() == was_selected;
271 if(!was_selected.empty() && exists_in_filtered_result) {
272 find_widget<tree_view_node>(was_selected).select_node();
280 static bool force =
false;
302 find_widget<toggle_button>(
"sort_time").set_value(0);
303 }
else if(order ==
DATE) {
304 find_widget<toggle_button>(
"sort_name").set_value(0);
315 const std::vector<std::string> words =
utils::split(text,
' ');
327 text_box*
filter = find_widget<text_box>(
"filter_box",
false,
true);
331 tree_view& tree = find_widget<tree_view>(
"campaign_tree");
336 toggle_button& sort_name = find_widget<toggle_button>(
"sort_name");
337 toggle_button& sort_time = find_widget<toggle_button>(
"sort_time");
352 multi_page& pages = find_widget<multi_page>(
"campaign_details");
355 multimenu_button& filter_comp = find_widget<multimenu_button>(
"filter_completion");
358 for (
unsigned j = 0; j < filter_comp.
num_options(); j++) {
373 item[
"label"] = campaign[
"description"];
374 item[
"use_markup"] =
"true";
376 if(!campaign[
"description_alignment"].empty()) {
377 item[
"text_alignment"] = campaign[
"description_alignment"];
380 data.emplace(
"description", item);
382 item[
"label"] = campaign[
"image"];
383 data.emplace(
"image", item);
393 addons[
"icon"] =
"icons/icon-game.png~BLIT(icons/icon-addon-publish.png)";
394 addons[
"name"] =
_(
"More campaigns...");
395 addons[
"completed"] =
false;
403 item[
"label"] =
_(
"In addition to the mainline campaigns, Wesnoth also has an ever-growing list of add-on content created by other players available via the Add-ons server, included but not limited to more single and multiplayer campaigns, multiplayer maps, additional media and various other content! Be sure to give it a try!");
404 data.emplace(
"description", item);
408 std::vector<std::string> dirs;
410 if(dirs.size() <= 15) {
412 missing[
"icon"] =
"units/unknown-unit.png";
413 missing[
"name"] =
_(
"Missing Campaigns");
424 item[
"label"] =
_(
"Wesnoth normally includes more than 15 mainline campaigns, even before installing any from the add-ons server. If you’ve installed the game via a package manager, there’s probably a separate package to install the complete game data.");
425 data.emplace(
"description", item);
437 std::vector<config> mod_menu_values;
441 const bool active =
std::find(enabled.begin(), enabled.end(), mod->id) != enabled.end();
443 mod_menu_values.emplace_back(
"label", mod->name,
"checkbox", active);
455 mods_menu.
set_label(
_(
"active_modifications^None"));
461 menu_button& diff_menu = find_widget<menu_button>(
"difficulty_menu");
473 const std::string
id = cfg[
"id"].str();
476 "index", result.second,
486 choice_ = cfg[
"index"].to_int();
493 tree_view& tree = find_widget<tree_view>(
"campaign_tree");
497 item[
"label"] = campaign[
"icon"];
498 data.emplace(
"icon", item);
500 item[
"label"] = campaign[
"name"];
501 data.emplace(
"name", item);
504 if(campaign[
"completed"].to_bool()) {
507 auto did_complete_at = [](
const config&
c) {
return c[
"completed_at"].to_bool(); };
510 const bool only_first_completed = difficulties.size() > 1 &&
511 std::none_of(difficulties.begin() + 1, difficulties.end(), did_complete_at);
524 if(!difficulties.empty() && did_complete_at(difficulties.back())) {
526 }
else if(only_first_completed && did_complete_at(difficulties.front())) {
532 data.emplace(
"victory", item);
536 node.
set_id(campaign[
"id"]);
545 tree_view& tree = find_widget<tree_view>(
"campaign_tree");
553 if(!campaign_id.empty()) {
573 boost::dynamic_bitset<> new_mod_states =
574 find_widget<multimenu_button>(
"mods_menu").get_toggle_states();
A config object defines a single node in a WML file, with access to child nodes.
child_itors child_range(config_key_type key)
boost::iterator_range< const_child_iterator > const_child_itors
void toggle_sorting_selection(CAMPAIGN_ORDER order)
RNG_MODE rng_mode_
whether the player checked the "Deterministic" checkbox.
CAMPAIGN_ORDER current_sorting_
void difficulty_selected()
Called when the difficulty selection changes.
int choice_
The chosen campaign.
std::vector< std::string > mod_ids_
std::vector< std::string > difficulties_
static const int OPEN_ADDON_MANAGER
RNG_MODE
RNG mode selection values.
static const std::string missing_campaign_
boost::dynamic_bitset mod_states_
std::string current_difficulty_
virtual void pre_show() override
Actions to be taken before showing the window.
void sort_campaigns(CAMPAIGN_ORDER order, bool ascending)
static const std::string addons_
bool currently_sorted_asc_
ng::create_engine & engine_
void add_campaign_to_tree(const config &campaign)
void filter_text_changed(const std::string &text)
void campaign_selected()
Called when another campaign is selected.
std::vector< std::string > last_search_words_
std::vector< std::string > page_ids_
Abstract base class for all modal dialogs.
std::unique_ptr< plugins_context > plugins_context_
grid & add_page(const widget_item &item)
Adds single page to the grid.
void select_page(const unsigned page, const bool select=true)
Selects a page.
A widget that allows the user to input text in single line.
tree_view_node & add_node(const std::string &id, const widget_data &data, const int index=-1)
tree_view_node * selected_item()
void set_retval(const int retval, const bool close_window=true)
Sets there return value of the window.
void keyboard_capture(widget *widget)
void add_to_keyboard_chain(widget *widget)
Adds the widget to the keyboard chain.
int find_extra_by_id(const MP_EXTRA extra_type, const std::string &id) const
bool toggle_mod(const std::string &id, bool force=false)
std::vector< std::string > & active_mods()
const std::vector< extras_metadata_ptr > & get_const_extras_by_type(const MP_EXTRA extra_type) const
std::shared_ptr< level > level_ptr
std::pair< level_type::type, int > find_level_by_id(const std::string &id) const
std::vector< level_ptr > get_levels_by_type_unfiltered(level_type::type type) const
void set_current_level(const std::size_t index)
level & current_level() const
const config & data() const
bool is_campaign_completed(const std::string &campaign_id)
void set_modifications(const std::vector< std::string > &value, bool mp=true)
Declarations for File-IO.
static std::string _(const char *str)
void get_files_in_dir(const std::string &dir, std::vector< std::string > *files, std::vector< std::string > *dirs, name_mode mode, filter_mode filter, reorder_mode reorder, file_tree_checksum *checksum)
Get a list of all files and/or directories in a given directory.
std::string victory_laurel_hardest
std::string victory_laurel
std::string victory_laurel_easy
config generate_difficulty_config(const config &source)
Helper function to convert old difficulty markup.
REGISTER_DIALOG(editor_edit_unit)
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification &signal)
Connects a signal handler for getting a notification upon modification.
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
void connect_signal_mouse_left_double_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button double click.
std::map< std::string, widget_item > widget_data
std::map< std::string, t_string > widget_item
@ OK
Dialog was closed with the OK button.
@ CANCEL
Dialog was closed with the CANCEL button.
std::string span_color(const color_t &color, Args &&... data)
Applies Pango markup to the input specifying its display color.
bool ci_search(const std::string &s1, const std::string &s2)
std::vector< std::string > split(const config_attribute_value &val)
auto * find(Container &container, const Value &value)
Convenience wrapper for using find on a container without needing to comare to end()
static std::string get_string(enum_type key)
Converts a enum to its string equivalent.
static map_location::direction n