The Battle for Wesnoth  1.19.1+dev
preferences_dialog.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2016 - 2024
3  by Charles Dang <exodia339gmail.com>
4  Copyright (C) 2011, 2015 by Iris Morelle <shadowm2006@gmail.com>
5  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY.
13 
14  See the COPYING file for more details.
15 */
16 
17 #define GETTEXT_DOMAIN "wesnoth-lib"
18 
20 
21 #include "display.hpp"
22 #include "events.hpp"
23 #include "filesystem.hpp"
24 #include "formatter.hpp"
25 #include "formula/string_utils.hpp"
26 #include "game_data.hpp"
27 #include "gettext.hpp"
28 #include "hotkey/hotkey_item.hpp"
29 #include "lexical_cast.hpp"
30 #include "resources.hpp"
31 #include "theme.hpp"
32 #include "video.hpp"
33 
34 // Sub-dialog includes
40 
43 #include "gui/dialogs/message.hpp"
45 #include "gui/widgets/button.hpp"
48 #include "gui/widgets/grid.hpp"
49 #include "gui/widgets/image.hpp"
50 #include "gui/widgets/label.hpp"
51 #include "gui/widgets/listbox.hpp"
52 #include "gui/widgets/slider.hpp"
55 #include "gui/widgets/text_box.hpp"
57 #include "gui/widgets/window.hpp"
58 
59 #include <functional>
60 #include <numeric>
61 
62 namespace gui2::dialogs
63 {
64 namespace
65 {
66 template<typename W>
67 void disable_widget_on_toggle(window& window, widget& w, const std::string& id)
68 {
69  find_widget<W>(&window, id, false).set_active(dynamic_cast<selectable_item&>(w).get_value_bool());
70 }
71 
72 template<typename W>
73 void disable_widget_on_toggle_inverted(window& window, widget& w, const std::string& id)
74 {
75  find_widget<W>(&window, id, false).set_active(!dynamic_cast<selectable_item&>(w).get_value_bool());
76 }
77 
78 // Ensure the specified index is between 0 and one less than the max
79 // number of pager layers (since get_layer_count returns one-past-end).
80 int index_in_pager_range(const int first, const stacked_widget& pager)
81 {
82  return std::clamp<int>(first, 0, pager.get_layer_count() - 1);
83 }
84 
85 // Helper to make it easier to immediately apply sound toggles immediately.
86 template<bool(*fptr)(bool)>
87 void sound_toggle_on_change(window& window, const std::string& id_to_toggle, widget& w)
88 {
89  std::invoke(fptr, dynamic_cast<selectable_item&>(w).get_value_bool());
90 
91  // Toggle the corresponding slider.
92  disable_widget_on_toggle<slider>(window, w, id_to_toggle);
93 }
94 
95 // Helper to make it easier to immediately apply volume (music, etc) setings on change.
96 template<void(*fptr)(int)>
97 void volume_setter_on_change(widget& w)
98 {
99  std::invoke(fptr, dynamic_cast<integer_selector&>(w).get_value());
100 }
101 
102 } // end anon namespace
103 
104 REGISTER_DIALOG(preferences_dialog)
105 
107  : modal_dialog(window_id())
108  , resolutions_() // should be populated by set_resolution_list before use
109  , themes_() // populated by set_theme_list
110  , last_selected_item_(0)
111  , accl_speeds_({0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 3, 4, 8, 16})
112  , visible_hotkeys_()
113  , visible_categories_()
114  , initial_index_(pef_view_map[initial_view])
115 {
116  initialize_callbacks();
117 }
118 
119 // Helper function to refresh resolution list
121 {
123 
124  std::vector<config> options;
125  for(const point& res : resolutions_) {
126  config option;
127  option["label"] = formatter() << res.x << font::unicode_multiplication_sign << res.y;
128 
129  const int div = std::gcd(res.x, res.y);
130  const int x_ratio = res.x / div;
131  const int y_ratio = res.y / div;
132 
133  if(x_ratio <= 10 || y_ratio <= 10) {
134  option["details"] = formatter() << "<span color='#777777'>(" << x_ratio << ':' << y_ratio << ")</span>";
135  }
136 
137  options.push_back(std::move(option));
138  }
139 
140  const unsigned current_res = std::distance(resolutions_.begin(), std::find(
142 
143  res_list.set_values(options, current_res);
144 }
145 
147 {
149 
150  std::vector<config> options;
151  std::size_t current_theme = 0;
152  for(std::size_t i = 0; i < themes_.size(); ++i) {
153  options.emplace_back("label", themes_[i].name, "tooltip", themes_[i].description);
154  if(themes_[i].id == prefs::get().theme()) {
155  current_theme = i;
156  }
157  }
158 
159  theme_list.set_values(options, current_theme);
160 }
161 
163 {
166 
167  std::string image = "friend.png";
168  std::string descriptor = _("friend");
169  std::string notes;
170 
171  if(entry.get_status() == "ignore") {
172  image = "ignore.png";
173  descriptor = _("ignored");
174  }
175 
176  if(!entry.get_notes().empty()) {
177  notes = " <small>(" + entry.get_notes() + ")</small>";
178  }
179 
180  item["use_markup"] = "true";
181 
182  item["label"] = "misc/status-" + image;
183  data.emplace("friend_icon", item);
184 
185  item["label"] = entry.get_nick() + notes;
186  data.emplace("friend_name", item);
187 
188  item["label"] = "<small>" + descriptor + "</small>";
189  data.emplace("friend_status", item);
190 
191  return data;
192 }
193 
195 {
196  const int num_friends = prefs::get().get_acquaintances().size();
197  const int sel = list.get_selected_row();
198 
199  if(sel < 0 || sel >= num_friends) {
200  return;
201  }
202 
203  std::map<std::string, preferences::acquaintance>::const_iterator who = prefs::get().get_acquaintances().begin();
204  std::advance(who, sel);
205 
206  textbox.set_value(who->second.get_nick() + " " + who->second.get_notes());
207 }
208 
210 {
211  const bool list_empty = list.get_item_count() == 0;
212 
213  if(!list_empty) {
214  list.select_row(std::min(static_cast<int>(list.get_item_count()) - 1, list.get_selected_row()));
215  }
216 
217  find_widget<button>(this, "remove", false).set_active(!list_empty);
218 
219  find_widget<label>(this, "no_friends_notice", false).set_visible(
221 }
222 
223 void preferences_dialog::add_friend_list_entry(const bool is_friend, text_box& textbox)
224 {
225  std::string username = textbox.text();
226  if(username.empty()) {
227  gui2::show_transient_message("", _("No username specified"));
228  return;
229  }
230 
231  std::string reason;
232 
233  std::size_t pos = username.find_first_of(' ');
234  if(pos != std::string::npos) {
235  reason = username.substr(pos + 1);
236  username = username.substr(0, pos);
237  }
238 
239  auto [entry, added_new] = prefs::get().add_acquaintance(username, (is_friend ? "friend": "ignore"), reason);
240 
241  if(!entry) {
242  gui2::show_transient_message(_("Error"), _("Invalid username"));
243  return;
244  }
245 
246  textbox.clear();
247 
248  listbox& list = find_widget<listbox>(this, "friends_list", false);
249 
250  //
251  // If this is a new entry, just add a new row. If it's not, we find the relevant
252  // row, remove it, and add a new row with the updated data. Should probably come
253  // up with a more elegant way to do this... the only reason I'm using the remove
254  // -and-replace method is to prevent any issues with the widgets' layout sizes.
255  //
256  if(added_new) {
257  list.add_row(get_friends_list_row_data(*entry));
258  } else {
259  for(unsigned i = 0; i < list.get_item_count(); ++i) {
260  grid* row_grid = list.get_row_grid(i);
261 
262  if(find_widget<label>(row_grid, "friend_name", false).get_label() == entry->get_nick()) {
263  list.remove_row(i);
264  list.add_row(get_friends_list_row_data(*entry), i);
265 
266  break;
267  }
268  }
269  }
270 
272 }
273 
275 {
276  const int selected_row = std::max(0, friends_list.get_selected_row());
277 
278  std::map<std::string, preferences::acquaintance>::const_iterator who = prefs::get().get_acquaintances().begin();
279  std::advance(who, selected_row);
280 
281  const std::string to_remove = !textbox.text().empty() ? textbox.text() : who->second.get_nick();
282 
283  if(to_remove.empty()) {
284  gui2::show_transient_message("", _("No username specified"));
285  return;
286  }
287 
288  if(!prefs::get().remove_acquaintance(to_remove)) {
289  gui2::show_transient_error_message(_("Not on friends or ignore lists"));
290  return;
291  }
292 
293  textbox.clear();
294 
295  listbox& list = find_widget<listbox>(this, "friends_list", false);
296  list.remove_row(selected_row);
297 
299 }
300 
302 {
303  // Update pixel scale preference.
304  slider& ps_slider = find_widget<slider>(this, "pixel_scale_slider", false);
305  prefs::get().set_pixel_scale(ps_slider.get_value());
306 
307  // Update auto pixel scale preference.
308  toggle_button& auto_ps_toggle =
309  find_widget<toggle_button>(this, "auto_pixel_scale", false);
310  prefs::get().set_auto_pixel_scale(auto_ps_toggle.get_value_bool());
311 
312  // Update draw buffers, taking these into account.
314 
315  // Update game display, if active
316  if(::display* disp = display::get_singleton()) {
317  disp->queue_rerender();
318  }
319 
320  // Raise a window resize event so we can react to the change
322 }
323 
324 template<bool(*toggle_getter)(), bool(*toggle_setter)(bool), int(*vol_getter)(), void(*vol_setter)(int)>
325 void preferences_dialog::initialize_sound_option_group(const std::string& id_suffix)
326 {
327  const std::string toggle_widget_id = "sound_toggle_" + id_suffix;
328  const std::string volume_widget_id = "sound_volume_" + id_suffix;
329 
330  // Set up the toggle. We utilize field_bool's callback-on-changed mechanism instead
331  // of manually registering the callback. Since we want the effects to apply immediately,
332  // the callback the setter callback is duplicated in the on-change callback. The field
333  // class could possibly use some reworking to make this less redundant, but for now it
334  // works well enough.
335  register_bool(toggle_widget_id, true, toggle_getter, std::bind(toggle_setter, std::placeholders::_1),
336  std::bind(sound_toggle_on_change<toggle_setter>, std::ref(*this), volume_widget_id, std::placeholders::_1), true);
337 
338  // Set up the volume slider. integer_field doesn't have a callback-on-changed mechanism.
339  // To add one would either mean adding it to the base field class or make it a proper
340  // class of is own.
341  register_integer(volume_widget_id, true, vol_getter, vol_setter);
342 
343  // Callback to actually immediately apply the volume effect.
344  connect_signal_notify_modified(find_widget<slider>(this, volume_widget_id, false),
345  std::bind(volume_setter_on_change<vol_setter>, std::placeholders::_1));
346 }
347 
348 /* SOUND FX wrappers for template */
349 static bool sound_on(){return prefs::get().sound_on();}
350 static bool set_sound(bool v){return prefs::get().set_sound(v);}
351 static int sound_volume(){return prefs::get().sound_volume();}
353 
354 /* MUSIC wrappers for template */
355 static bool music_on(){return prefs::get().music_on();}
356 static bool set_music(bool v){return prefs::get().set_music(v);}
357 static int music_volume(){return prefs::get().music_volume();}
359 
360 /* TURN BELL wrappers for template */
361 static bool turn_bell(){return prefs::get().turn_bell();}
362 static bool set_turn_bell(bool v){return prefs::get().set_turn_bell(v);}
363 static int bell_volume(){return prefs::get().bell_volume();}
364 static void set_bell_volume(int v){prefs::get().set_bell_volume(v);}
365 
366 /* UI FX wrappers for template */
367 static bool ui_sound_on(){return prefs::get().ui_sound_on();}
368 static bool set_ui_sound(bool v){return prefs::get().set_ui_sound(v);}
369 static int ui_volume(){return prefs::get().ui_volume();}
370 static void set_ui_volume(int v){prefs::get().set_ui_volume(v);}
371 
372 /**
373  * Sets up states and callbacks for each of the widgets
374  */
376 {
377  //
378  // GENERAL PANEL
379  //
380 
381  /* SCROLL SPEED */
382  register_integer("scroll_speed", true,
383  []() {return prefs::get().scroll_speed();},
384  [](int v) {prefs::get().set_scroll_speed(v);});
385 
386  /* ACCELERATED SPEED */
387  register_bool("turbo_toggle", true,
388  []() {return prefs::get().turbo();},
389  [](bool v) {prefs::get().set_turbo(v);});
390 
391  const auto accl_load = [this]()->int {
392  return std::distance(accl_speeds_.begin(), std::find(accl_speeds_.begin(), accl_speeds_.end(), prefs::get().turbo_speed()));
393  };
394 
395  const auto accl_save = [this](int i) {
397  };
398 
399  register_integer("turbo_slider", true,
400  accl_load, accl_save);
401 
402  // Set the value label transform function.
403  find_widget<slider>(this, "turbo_slider", false).set_value_labels(
404  [this](int pos, int /*max*/)->t_string { return lexical_cast<std::string>(accl_speeds_[pos]); }
405  );
406 
407  /* SKIP AI MOVES */
408  register_bool("skip_ai_moves", true,
409  []() {return prefs::get().skip_ai_moves();},
410  [](bool v) {prefs::get().set_skip_ai_moves(v);});
411 
412  /* DISABLE AUTO MOVES */
413  register_bool("disable_auto_moves", true,
414  []() {return prefs::get().disable_auto_moves();},
415  [](bool v) {prefs::get().set_disable_auto_moves(v);});
416 
417  /* TURN DIALOG */
418  register_bool("show_turn_dialog", true,
419  []() {return prefs::get().turn_dialog();},
420  [](bool v) {prefs::get().set_turn_dialog(v);});
421 
422  /* ENABLE PLANNING MODE */
423  register_bool("whiteboard_on_start", true,
424  []() {return prefs::get().enable_whiteboard_mode_on_start();},
426 
427  /* HIDE ALLY PLANS */
428  register_bool("whiteboard_hide_allies", true,
429  []() {return prefs::get().hide_whiteboard();},
430  [](bool v) {prefs::get().set_hide_whiteboard(v);});
431 
432  /* INTERRUPT ON SIGHTING */
433  register_bool("interrupt_move_when_ally_sighted", true,
434  []() {return prefs::get().interrupt_when_ally_sighted();},
435  [](bool v) {prefs::get().set_interrupt_when_ally_sighted(v);});
436 
437  /* SAVE REPLAYS */
438  register_bool("save_replays", true,
439  []() {return prefs::get().save_replays();},
440  [](bool v) {prefs::get().set_save_replays(v);});
441 
442  /* DELETE AUTOSAVES */
443  register_bool("delete_saves", true,
444  []() {return prefs::get().delete_saves();},
445  [](bool v) {prefs::get().set_delete_saves(v);});
446 
447  /* MAX AUTO SAVES */
448  register_integer("max_saves_slider", true,
449  []() {return prefs::get().autosavemax();},
450  [](int v) {prefs::get().set_autosavemax(v);});
451 
452  /* CACHE MANAGE */
453  connect_signal_mouse_left_click(find_widget<button>(this, "cachemg", false),
454  std::bind(&gui2::dialogs::game_cache_options::display<>));
455 
456  //
457  // DISPLAY PANEL
458  //
459 
460  /* FULLSCREEN TOGGLE */
462  find_widget<toggle_button>(this, "fullscreen", false);
463 
464  toggle_fullscreen.set_value(prefs::get().fullscreen());
465 
466  // We bind a special callback function, so setup_single_toggle() is not used
469 
470  /* SET RESOLUTION */
471  menu_button& res_list = find_widget<menu_button>(this, "resolution_set", false);
472 
473  res_list.set_use_markup(true);
474  res_list.set_active(!prefs::get().fullscreen());
475 
476  set_resolution_list(res_list);
477 
479  std::bind(&preferences_dialog::handle_res_select, this));
480 
481  connect_signal<event::SDL_VIDEO_RESIZE>(std::bind(&preferences_dialog::set_resolution_list, this, std::ref(res_list)));
482 
483  /* PIXEL SCALE */
484  register_integer("pixel_scale_slider", true,
485  []() {return prefs::get().pixel_scale();},
486  [](int v) {prefs::get().set_pixel_scale(v);});
487 
488  slider& ps_slider =
489  find_widget<slider>(this, "pixel_scale_slider", false);
491  std::bind(&preferences_dialog::apply_pixel_scale, this));
492 
493  /* AUTOMATIC PIXEL SCALE */
494  register_bool("auto_pixel_scale", true,
495  []() {return prefs::get().auto_pixel_scale();},
496  [](bool v) {prefs::get().set_auto_pixel_scale(v);},
497  [&](widget& w) { disable_widget_on_toggle_inverted<slider>(*this, w, "pixel_scale_slider"); }, true);
498 
499  toggle_button& auto_ps_toggle =
500  find_widget<toggle_button>(this, "auto_pixel_scale", false);
501  connect_signal_mouse_left_click(auto_ps_toggle,
502  std::bind(&preferences_dialog::apply_pixel_scale, this));
503 
504  /* SHOW FLOATING LABELS */
505  register_bool("show_floating_labels", true,
506  []() {return prefs::get().show_floating_labels();},
507  [](bool v) {prefs::get().set_show_floating_labels(v);});
508 
509  /* SHOW TEAM COLORS */
510  register_bool("show_ellipses", true,
511  []() {return prefs::get().show_side_colors();},
512  [](bool v) {prefs::get().set_show_side_colors(v);});
513 
514  /* SHOW GRID */
515  register_bool("show_grid", true,
516  []() {return prefs::get().grid();},
517  [](bool v) {prefs::get().set_grid(v);});
518 
519  /* ANIMATE MAP */
520  register_bool("animate_terrains", true,
521  []() {return prefs::get().animate_map();},
522  [](bool v) {prefs::get().set_animate_map(v);},
523  [&](widget& w) { disable_widget_on_toggle<toggle_button>(*this, w, "animate_water"); }, true);
524 
525  /* ANIMATE WATER */
526  register_bool("animate_water", true,
527  []() {return prefs::get().animate_water();},
528  [](bool v) {prefs::get().set_animate_water(v);});
529 
530  /* SHOW UNIT STANDING ANIMS */
531  register_bool("animate_units_standing", true,
532  []() {return prefs::get().show_standing_animations();},
533  [](bool v) {prefs::get().set_show_standing_animations(v);});
534 
535  /* SHOW UNIT IDLE ANIMS */
536  register_bool("animate_units_idle", true,
537  []() {return prefs::get().idle_anim();},
538  [](bool v) {prefs::get().set_idle_anim(v);},
539  [&](widget& w) { disable_widget_on_toggle<slider>(*this, w, "idle_anim_frequency"); });
540 
541  register_integer("idle_anim_frequency", true,
542  []() {return prefs::get().idle_anim_rate();},
543  [](int v) {prefs::get().set_idle_anim_rate(v);});
544 
545  /* FONT SCALING */
546  //register_integer("scaling_slider", true,
547  // font_scaling, set_font_scaling);
548 
549  /* FPS LIMITER */
550  register_bool("fps_limiter", true,
551  []() { return prefs::get().draw_delay() != 0; }, [](bool v) { prefs::get().set_draw_delay(v ? -1 : 0); });
552 
553  /* VSYNC */
554  register_bool("vsync", true,
555  []() {return prefs::get().vsync();},
556  [](bool v) {prefs::get().set_vsync(v);});
557 
558  /* SELECT THEME */
559  menu_button& theme_list = find_widget<menu_button>(this, "choose_theme", false);
562  std::bind(&preferences_dialog::handle_theme_select, this));
563  //connect_signal_mouse_left_click(
564  // find_widget<button>(this, "choose_theme", false),
565  // std::bind(&show_theme_dialog));
566 
567  //
568  // SOUND PANEL
569  //
570 
571  /* SOUND FX */
572  initialize_sound_option_group<sound_on, set_sound, sound_volume, set_sound_volume>("sfx");
573 
574  /* MUSIC */
575  initialize_sound_option_group<music_on, set_music, music_volume, set_music_volume>("music");
576 
577  register_bool("sound_toggle_stop_music_in_background", true,
578  []() {return prefs::get().stop_music_in_background();},
579  [](bool v) {prefs::get().set_stop_music_in_background(v);});
580 
581  /* TURN BELL */
582  initialize_sound_option_group<turn_bell, set_turn_bell, bell_volume, set_bell_volume>("bell");
583 
584  /* UI FX */
585  initialize_sound_option_group<ui_sound_on, set_ui_sound, ui_volume, set_ui_volume>("uisfx");
586 
587  //
588  // MULTIPLAYER PANEL
589  //
590 
591  /* CHAT LINES */
592  register_integer("chat_lines", true,
593  []() {return prefs::get().chat_lines();},
594  [](int v) {prefs::get().set_chat_lines(v);});
595 
596  /* CHAT TIMESTAMPPING */
597  register_bool("chat_timestamps", true,
598  []() {return prefs::get().chat_timestamping();},
599  [](bool v) {prefs::get().set_chat_timestamping(v);});
600 
601  /* SAVE PASSWORD */
602  register_bool("remember_password", true,
603  []() {return prefs::get().remember_password();},
604  [](bool v) {prefs::get().set_remember_password(v);});
605 
606  /* WHISPERS FROM FRIENDS ONLY */
607  register_bool("lobby_whisper_friends_only", true,
608  []() {return prefs::get().whisper_friends_only();},
609  [](bool v) {prefs::get().set_whisper_friends_only(v);});
610 
611  /* LOBBY JOIN NOTIFICATIONS */
612  lobby_joins_group.add_member(find_widget<toggle_button>(this, "lobby_joins_none", false, true), pref_constants::lobby_joins::show_none);
613  lobby_joins_group.add_member(find_widget<toggle_button>(this, "lobby_joins_friends", false, true), pref_constants::lobby_joins::show_friends);
614  lobby_joins_group.add_member(find_widget<toggle_button>(this, "lobby_joins_all", false, true), pref_constants::lobby_joins::show_all);
615 
617 
620  });
621 
622  /* FRIENDS LIST */
623  listbox& friends_list = find_widget<listbox>(this, "friends_list", false);
624 
625  friends_list.clear();
626 
627  for(const auto& entry : prefs::get().get_acquaintances()) {
628  friends_list.add_row(get_friends_list_row_data(entry.second));
629  }
630 
631  update_friends_list_controls(friends_list);
632 
633  text_box& textbox = find_widget<text_box>(this, "friend_name_box", false);
634 
636  find_widget<button>(this, "add_friend", false), std::bind(
638  this, true,
639  std::ref(textbox)));
640 
642  find_widget<button>(this, "add_ignored", false), std::bind(
644  this, false,
645  std::ref(textbox)));
646 
648  find_widget<button>(this, "remove", false), std::bind(
650  this,
651  std::ref(friends_list),
652  std::ref(textbox)));
653 
654  connect_signal_notify_modified(friends_list, std::bind(
656  this,
657  std::ref(friends_list),
658  std::ref(textbox)));
659 
660  /* ALERTS */
662  find_widget<button>(this, "mp_alerts", false),
663  std::bind(&gui2::dialogs::mp_alerts_options::display<>));
664 
665  /* SET WESNOTHD PATH */
667  find_widget<button>(this, "mp_wesnothd", false), std::bind([]() {return prefs::get().show_wesnothd_server_search();}));
668 
669 
670  //
671  // ADVANCED PANEL
672  //
673 
674  listbox& advanced = find_widget<listbox>(this, "advanced_prefs", false);
675 
676  widget_data row_data;
677 
678  for(const auto& option : prefs::get().get_advanced_preferences()) {
679  const std::string pref_name = option.field;
680 
681  row_data["pref_name"]["label"] = option.name;
682  grid* main_grid = &advanced.add_row(row_data);
683 
684  grid& details_grid = find_widget<grid>(main_grid, "prefs_setter_grid", false);
686 
687  // The toggle widget for toggle-type options (hidden for other types)
688  toggle_button& toggle_box = find_widget<toggle_button>(main_grid, "value_toggle", false);
690 
691  if(!option.description.empty()) {
692  find_widget<styled_widget>(main_grid, "description", false).set_label(option.description);
693  }
694 
695  switch(option.type) {
697 
699  toggle_box.set_value(preferences_dialog_friend::get(pref_name, option.cfg["default"].to_bool()));
700 
701  // A lambda alone would be more verbose because it'd need to specify all the parameters.
702  connect_signal_mouse_left_click(toggle_box, std::bind(
703  [&, pref_name]() { preferences_dialog_friend::set(pref_name, toggle_box.get_value_bool()); }
704  ));
705 
706  gui2::bind_status_label<toggle_button>(
707  main_grid, "value_toggle", default_status_value_getter<toggle_button>, "value");
708 
709  break;
710  }
711 
713  auto setter_widget = build_single_widget_instance<slider>(config {"definition", "minimal"});
714  setter_widget->set_id("setter");
715  // Maximum must be set first or this will assert
716  setter_widget->set_value_range(option.cfg["min"].to_int(), option.cfg["max"].to_int());
717  setter_widget->set_step_size(option.cfg["step"].to_int(1));
718 
719  details_grid.swap_child("setter", std::move(setter_widget), true);
720 
721  slider& slide = find_widget<slider>(&details_grid, "setter", false);
722 
723  slide.set_value(preferences_dialog_friend::get(pref_name, option.cfg["default"].to_int()));
724 
725  // A lambda alone would be more verbose because it'd need to specify all the parameters.
726  connect_signal_notify_modified(slide, std::bind(
727  [&, pref_name]() { preferences_dialog_friend::set(pref_name, slide.get_value()); }
728  ));
729 
730  gui2::bind_status_label<slider>(main_grid, "setter", default_status_value_getter<slider>, "value");
731 
732  break;
733  }
734 
736  std::vector<config> menu_data;
737  std::vector<std::string> option_ids;
738 
739  for(const config& choice : option.cfg.child_range("option")) {
740  config menu_item;
741  menu_item["label"] = choice["name"];
742  if(choice.has_attribute("description")) {
743  menu_item["details"] = std::string("<span color='#777'>") + choice["description"] + "</span>";
744  }
745  menu_data.push_back(menu_item);
746  option_ids.push_back(choice["id"]);
747  }
748 
749  // Attempt to find an initial selection
750  int selected = std::distance(option_ids.begin(), std::find(option_ids.begin(), option_ids.end(),
751  preferences_dialog_friend::get(pref_name, option.cfg["default"].str())
752  ));
753 
754  // If the saved option value was invalid, reset selection to 0.
755  if(selected < 0 || selected >= static_cast<int>(option_ids.size())) {
756  selected = 0;
757  }
758 
759  auto setter_widget = build_single_widget_instance<menu_button>();
760  setter_widget->set_id("setter");
761 
762  details_grid.swap_child("setter", std::move(setter_widget), true);
763 
764  menu_button& menu = find_widget<menu_button>(&details_grid, "setter", false);
765 
766  menu.set_use_markup(true);
767  menu.set_values(menu_data, selected);
768 
769  // A lambda alone would be more verbose because it'd need to specify all the parameters.
771  std::bind([=](widget& w) { preferences_dialog_friend::set(pref_name, option_ids[dynamic_cast<menu_button&>(w).get_value()]); }, std::placeholders::_1));
772 
773  gui2::bind_status_label<menu_button>(main_grid, "setter", default_status_value_getter<menu_button>, "value");
774 
775  break;
776  }
777 
779  //main_grid->remove_child("setter");
780 
781  auto value_widget = build_single_widget_instance<image>();
782  value_widget->set_label("icons/arrows/arrows_blank_right_25.png~CROP(3,3,18,18)");
783 
784  main_grid->swap_child("value", std::move(value_widget), true);
785 
786  break;
787  }
788  }
789  }
790 
791  connect_signal_notify_modified(advanced, std::bind(
793  this,
794  std::ref(advanced)));
795 
797 
798  //
799  // HOTKEYS PANEL
800  //
801 
802  multimenu_button& hotkey_menu = find_widget<multimenu_button>(this, "hotkey_category_menu", false);
803  connect_signal_notify_modified(hotkey_menu,
805 
807 
808  text_box& filter = find_widget<text_box>(this, "filter", false);
810 
811  // Action column
812  hotkey_list.register_translatable_sorting_option(0, [this](const int i) { return visible_hotkeys_[i]->description.str(); });
813 
814  // Hotkey column
815  hotkey_list.register_sorting_option(1, [this](const int i) { return hotkey::get_names(visible_hotkeys_[i]->id); });
816 
817  // Scope columns
818  hotkey_list.register_sorting_option(2, [this](const int i) { return !visible_hotkeys_[i]->scope[hotkey::SCOPE_GAME]; });
819  hotkey_list.register_sorting_option(3, [this](const int i) { return !visible_hotkeys_[i]->scope[hotkey::SCOPE_EDITOR]; });
820  hotkey_list.register_sorting_option(4, [this](const int i) { return !visible_hotkeys_[i]->scope[hotkey::SCOPE_MAIN_MENU]; });
821 
822  hotkey_list.set_active_sorting_option({0, sort_order::type::ascending}, true);
823 
825  find_widget<button>(this, "btn_add_hotkey", false), std::bind(
827  this,
828  std::ref(hotkey_list)));
829 
831  find_widget<button>(this, "btn_clear_hotkey", false), std::bind(
833  this,
834  std::ref(hotkey_list)));
835 
837  find_widget<button>(this, "btn_reset_hotkeys", false), std::bind(
839  this));
840 }
841 
843 {
844  widget_data row_data;
845 
846  t_string& row_icon = row_data["img_icon"]["label"];
847  t_string& row_action = row_data["lbl_desc"]["label"];
848  t_string& row_hotkey = row_data["lbl_hotkey"]["label"];
849 
850  t_string& row_is_g = row_data["lbl_is_game"]["label"];
851  t_string& row_is_e = row_data["lbl_is_editor"]["label"];
852  t_string& row_is_m = row_data["lbl_is_mainmenu"]["label"];
853 
854  listbox& hotkey_list = find_widget<listbox>(this, "list_hotkeys", false);
855 
856  hotkey_list.clear();
857  visible_hotkeys_.clear();
858  visible_categories_.clear();
859 
860  //
861  // Main hotkeys list
862  //
863 
864  // These translated initials should match those used in data/gui/window/preferences/02_hotkeys.cfg
865  const std::string gh = "<span color='#0f0'>" + _("game_hotkeys^G") + "</span>";
866  const std::string eh = "<span color='#0f0'>" + _("editor_hotkeys^E") + "</span>";
867  const std::string mh = "<span color='#0f0'>" + _("mainmenu_hotkeys^M") + "</span>";
868 
869  for(const auto& [id, hotkey_item] : hotkey::get_hotkey_commands()) {
870  if(hotkey_item.hidden) {
871  continue;
872  }
873 
874  visible_hotkeys_.push_back(&hotkey_item);
875  visible_categories_.insert(hotkey_item.category);
876 
877  if(filesystem::file_exists(game_config::path + "/images/icons/action/" + hotkey_item.id + "_25.png")) {
878  row_icon = "icons/action/" + hotkey_item.id + "_25.png~CROP(3,3,18,18)";
879  } else {
880  row_icon = "";
881  }
882 
883  row_action = hotkey_item.description;
884  row_hotkey = hotkey::get_names(hotkey_item.id);
885 
886  row_is_g = hotkey_item.scope[hotkey::SCOPE_GAME] ? gh : "";
887  row_is_e = hotkey_item.scope[hotkey::SCOPE_EDITOR] ? eh : "";
888  row_is_m = hotkey_item.scope[hotkey::SCOPE_MAIN_MENU] ? mh : "";
889 
890  hotkey_list.add_row(row_data);
891  }
892 
893  //
894  // Filter options
895  //
896 
897  std::vector<config> filter_ops;
898  for(const hotkey::HOTKEY_CATEGORY& cat : visible_categories_) {
899  filter_ops.emplace_back("label", hotkey::get_translatable_category_name(cat), "checkbox", false);
900  }
901 
902  find_widget<multimenu_button>(this, "hotkey_category_menu", false).set_values(filter_ops);
903 
904  return hotkey_list;
905 }
906 
908 {
909  int row_number = hotkeys.get_selected_row();
910  if(row_number < 0) {
911  gui2::show_transient_message("", _("No hotkey selected"));
912  return;
913  }
914 
915  const hotkey::hotkey_command& hotkey_item = *visible_hotkeys_[row_number];
916 
917  gui2::dialogs::hotkey_bind bind_dlg(hotkey_item.id);
918  bind_dlg.show();
919 
920  hotkey::hotkey_ptr newhk = bind_dlg.get_new_binding();
921  hotkey::hotkey_ptr oldhk;
922 
923  // only if not cancelled.
924  if(newhk.get() == nullptr) {
925  return;
926  }
927 
928  for(const hotkey::hotkey_ptr& hk : hotkey::get_hotkeys()) {
929  if(!hk->is_disabled() && newhk->bindings_equal(hk)) {
930  oldhk = hk;
931  }
932  }
933 
934  if(oldhk && oldhk->get_command() == hotkey_item.id) {
935  return;
936  }
937 
938  if(oldhk && oldhk->get_command() != "null") {
939  const std::string text = VGETTEXT("“<b>$hotkey_sequence|</b>” is in use by “<b>$old_hotkey_action|</b>”.\nDo you wish to reassign it to “<b>$new_hotkey_action|</b>”?", {
940  {"hotkey_sequence", oldhk->get_name()},
941  {"old_hotkey_action", hotkey::get_hotkey_command(oldhk->get_command()).description},
942  {"new_hotkey_action", hotkey::get_hotkey_command(newhk->get_command()).description}
943  });
944 
945  const int res = gui2::show_message(_("Reassign Hotkey"), text, gui2::dialogs::message::yes_no_buttons, true);
946  if(res != gui2::retval::OK) {
947  return;
948  }
949  }
950 
951  hotkey::add_hotkey(newhk);
952 
953  // We need to recalculate all hotkey names in because we might have removed a hotkey from another command.
954  for(std::size_t i = 0; i < hotkeys.get_item_count(); ++i) {
955  const hotkey::hotkey_command& hotkey_item_row = *visible_hotkeys_[i];
956  find_widget<label>(hotkeys.get_row_grid(i), "lbl_hotkey", false).set_label(hotkey::get_names(hotkey_item_row.id));
957  }
958 }
959 
961 {
962  gui2::show_transient_message(_("Hotkeys Reset"), _("All hotkeys have been reset to their default values."));
963 
965 
966  // Set up the list again and reselect the default sorting option.
968  hotkey_list.set_active_sorting_option({0, sort_order::type::ascending}, true);
969 }
970 
972 {
973  int row_number = hotkeys.get_selected_row();
974  if(row_number < 0) {
975  gui2::show_transient_message("", _("No hotkey selected"));
976  return;
977  }
978 
979  const hotkey::hotkey_command& hotkey_item = *visible_hotkeys_[row_number];
980  hotkey::clear_hotkeys(hotkey_item.id);
981  find_widget<label>(hotkeys.get_row_grid(row_number), "lbl_hotkey", false).set_label(hotkey::get_names(hotkey_item.id));
982 }
983 
985 {
986  const multimenu_button& hotkey_menu = find_widget<const multimenu_button>(this, "hotkey_category_menu", false);
987  const text_box& name_filter = find_widget<const text_box>(this, "filter", false);
988 
989  boost::dynamic_bitset<> toggle_states = hotkey_menu.get_toggle_states();
990  boost::dynamic_bitset<> res(visible_hotkeys_.size());
991 
992  std::string text = name_filter.get_value();
993 
994  // Nothing selected. It means that *all* categories are shown.
995  if(toggle_states.none()) {
996  toggle_states = ~toggle_states;
997  }
998 
999  for(std::size_t h = 0; h < visible_hotkeys_.size(); ++h) {
1000  // Default to true if there is no filter text
1001  bool found = true;
1002 
1003  if(!text.empty()) {
1004  const std::string description = visible_hotkeys_[h]->description.str();
1005 
1006  for(const auto& word : utils::split(text, ' ')) {
1007  found = translation::ci_search(description, word);
1008 
1009  // No match, we're excluding this hotkey
1010  if(!found) {
1011  break;
1012  }
1013  }
1014  }
1015 
1016  unsigned cat_index = 0;
1017 
1018  // Filter categories
1019  for(const hotkey::HOTKEY_CATEGORY& cat : visible_categories_) {
1020  if(visible_hotkeys_[h]->category == cat) {
1021  break;
1022  } else {
1023  ++cat_index;
1024  }
1025  }
1026 
1027  if(cat_index < toggle_states.size() && found) {
1028  res[h] = toggle_states[cat_index];
1029  } else {
1030  res[h] = false;
1031  }
1032  }
1033 
1034  find_widget<listbox>(this, "list_hotkeys", false).set_row_shown(res);
1035 }
1036 
1038 {
1039  const int selected_row = list.get_selected_row();
1040  const auto& pref = prefs::get().get_advanced_preferences()[selected_row];
1041 
1042  if(pref.type == preferences::option::avd_type::SPECIAL) {
1043  if(pref.field == "logging") {
1044  gui2::dialogs::log_settings::display();
1045  } else if(pref.field == "orb_color") {
1046  gui2::dialogs::select_orb_colors::display();
1047  } else {
1048  WRN_GUI_L << "Invalid or unimplemented custom advanced prefs option: " << pref.field;
1049  }
1050 
1051  // Add more options here as needed
1052  }
1053 
1054  const bool has_description = !pref.description.empty();
1055 
1056  if(has_description || (pref.type != preferences::option::avd_type::SPECIAL && pref.type != preferences::option::avd_type::TOGGLE)) {
1057  find_widget<widget>(list.get_row_grid(selected_row), "prefs_setter_grid", false)
1058  .set_visible(widget::visibility::visible);
1059  }
1060 
1061  if(last_selected_item_ != selected_row) {
1062  find_widget<widget>(list.get_row_grid(last_selected_item_), "prefs_setter_grid", false)
1063  .set_visible(widget::visibility::invisible);
1064 
1065  last_selected_item_ = selected_row;
1066  }
1067 }
1068 
1070 {
1071  //
1072  // MULTIPLAYER TABS
1073  //
1075  std::bind(&preferences_dialog::on_tab_select, this));
1076 }
1077 
1079 {
1080  set_always_save_fields(true);
1081 
1082  connect_signal_mouse_left_click(find_widget<button>(&window, "about", false), std::bind(&game_version::display<>));
1083 
1084  //
1085  // Status labels
1086  // These need to be set here in pre_show, once the fields are initialized. For some reason, this
1087  // is not the case for those in Advanced
1088  //
1089 
1090  gui2::bind_status_label<slider>(&window, "max_saves_slider");
1091  gui2::bind_status_label<slider>(&window, "turbo_slider");
1092  gui2::bind_status_label<slider>(&window, "pixel_scale_slider");
1093 
1094  //gui2::bind_status_label<slider>(&window, "scaling_slider", [](slider& s)->std::string {
1095  // return s.get_value_label() + "%";
1096  //});
1097 
1098  listbox& selector = find_widget<listbox>(&window, "selector", false);
1099  stacked_widget& pager = find_widget<stacked_widget>(&window, "pager", false);
1100 
1101  pager.set_find_in_all_layers(true);
1102 
1104  std::bind(&preferences_dialog::on_page_select, this));
1105 
1106  window.keyboard_capture(&selector);
1107 
1108  VALIDATE(selector.get_item_count() == pager.get_layer_count(),
1109  "The preferences pager and its selector listbox do not have the same number of items.");
1110 
1111  const int main_index = index_in_pager_range(initial_index_.first, pager);
1112 
1113  // Loops through each pager layer and checks if it has both a tab bar
1114  // and stack. If so, it initializes the options for the former and
1115  // selects the specified layer of the latter.
1116  for(unsigned int i = 0; i < pager.get_layer_count(); ++i) {
1117  listbox* tab_selector = find_widget<listbox>(
1118  pager.get_layer_grid(i), "tab_selector", false, false);
1119 
1120  stacked_widget* tab_pager = find_widget<stacked_widget>(
1121  pager.get_layer_grid(i), "tab_pager", false, false);
1122 
1123  if(tab_pager && tab_selector) {
1124  const int ii = static_cast<int>(i);
1125  const int tab_index = index_in_pager_range(initial_index_.second, *tab_pager);
1126  const int to_select = (ii == main_index ? tab_index : 0);
1127 
1128  // Initialize tabs for this page
1129  initialize_tabs(*tab_selector);
1130 
1131  tab_selector->select_row(to_select);
1132  tab_pager->select_layer(to_select);
1133  }
1134  }
1135 
1136  // Finally, select the initial main page
1137  selector.select_row(main_index);
1138  pager.select_layer(main_index);
1139 }
1140 
1141 void preferences_dialog::set_visible_page(unsigned int page, const std::string& pager_id)
1142 {
1143  find_widget<stacked_widget>(this, pager_id, false).select_layer(page);
1144 }
1145 
1146 // Special fullsceen callback
1148 {
1149  const bool ison = find_widget<toggle_button>(this, "fullscreen", false).get_value_bool();
1150  video::set_fullscreen(ison);
1151 
1152  menu_button& res_list = find_widget<menu_button>(this, "resolution_set", false);
1153 
1154  set_resolution_list(res_list);
1155  res_list.set_active(!ison);
1156 }
1157 
1159 {
1160  menu_button& res_list = find_widget<menu_button>(this, "resolution_set", false);
1161 
1162  if(video::set_resolution(resolutions_[res_list.get_value()])) {
1163  set_resolution_list(res_list);
1164  }
1165 }
1166 
1168 {
1169  menu_button& theme_list = find_widget<menu_button>(this, "choose_theme", false);
1170 
1171  const auto selection = theme_list.get_value();
1172  const auto& theme = themes_.at(selection);
1173  auto* display = display::get_singleton();
1174 
1175  prefs::get().set_theme(theme.id);
1176  if(display && resources::gamedata && resources::gamedata->get_theme().empty()) {
1177  display->set_theme(theme.id);
1178  }
1179 
1180 }
1181 
1183 {
1184  const int selected_row =
1185  std::max(0, find_widget<listbox>(this, "selector", false).get_selected_row());
1186  set_visible_page(static_cast<unsigned int>(selected_row), "pager");
1187 }
1188 
1190 {
1191  const int selected_row =
1192  std::max(0, find_widget<listbox>(this, "tab_selector", false).get_selected_row());
1193  set_visible_page(static_cast<unsigned int>(selected_row), "tab_pager");
1194 }
1195 
1197 {
1199 
1200  // Save new prefs to disk. This also happens on app close, but doing
1201  // it here too ensures nothing is lost in case of, say, a crash.
1203 }
1204 
1205 } // namespace dialogs
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:159
child_itors child_range(config_key_type key)
Definition: config.cpp:273
Sort-of-Singleton that many classes, both GUI and non-GUI, use to access the game data.
Definition: display.hpp:88
void set_theme(const std::string &new_theme)
Definition: display.cpp:248
static display * get_singleton()
Returns the display object if a display object exists.
Definition: display.hpp:102
std::ostringstream wrapper.
Definition: formatter.hpp:40
hotkey::hotkey_ptr get_new_binding() const
Definition: hotkey_bind.hpp:31
@ yes_no_buttons
Shows a yes and no button.
Definition: message.hpp:81
Abstract base class for all modal dialogs.
void set_always_save_fields(const bool always_save_fields)
field_integer * register_integer(const std::string &id, const bool mandatory, const std::function< int()> callback_load_value=nullptr, const std::function< void(int)> callback_save_value=nullptr)
Creates a new integer field.
bool show(const unsigned auto_close_time=0)
Shows the window.
field_bool * register_bool(const std::string &id, const bool mandatory, const std::function< bool()> callback_load_value=nullptr, const std::function< void(bool)> callback_save_value=nullptr, const std::function< void(widget &)> callback_change=nullptr, const bool initial_fire=false)
Creates a new boolean field.
void set_visible_page(unsigned int page, const std::string &pager_id)
void set_theme_list(menu_button &theme_list)
void remove_hotkey_callback(listbox &hotkeys)
const std::pair< int, int > & initial_index_
virtual void post_show(window &) override
Actions to be taken after the window has been shown.
void set_resolution_list(menu_button &res_list)
void on_advanced_prefs_list_select(listbox &tree)
virtual void pre_show(window &window) override
Actions to be taken before showing the window.
void on_page_select()
Callback for selection changes.
void on_friends_list_select(listbox &list, text_box &textbox)
void add_friend_list_entry(const bool is_friend, text_box &textbox)
std::vector< const hotkey::hotkey_command * > visible_hotkeys_
widget_data get_friends_list_row_data(const preferences::acquaintance &entry)
std::set< hotkey::HOTKEY_CATEGORY > visible_categories_
void update_friends_list_controls(listbox &list)
void handle_res_select()
Special callback functions.
void remove_friend_list_entry(listbox &friends_list, text_box &textbox)
void initialize_sound_option_group(const std::string &id_suffix)
void add_hotkey_callback(listbox &hotkeys)
group< pref_constants::lobby_joins > lobby_joins_group
Base container class.
Definition: grid.hpp:32
std::unique_ptr< widget > swap_child(const std::string &id, std::unique_ptr< widget > w, const bool recurse, widget *new_parent=nullptr)
Exchanges a child in the grid.
Definition: grid.cpp:101
void add_member(selectable_item *w, const T &value)
Adds a widget/value pair to the group map.
Definition: group.hpp:42
void set_member_states(const T &value)
Sets the toggle values for all widgets besides the one associated with the specified value to false.
Definition: group.hpp:111
void set_callback_on_value_change(std::function< void(widget &, const T)> func)
Sets a common callback function for all members.
Definition: group.hpp:121
The listbox class.
Definition: listbox.hpp:43
grid & add_row(const widget_item &item, const int index=-1)
When an item in the list is selected by the user we need to update the state.
Definition: listbox.cpp:59
const grid * get_row_grid(const unsigned row) const
Returns the grid of the wanted row.
Definition: listbox.cpp:230
bool select_row(const unsigned row, const bool select=true)
Selects a row.
Definition: listbox.cpp:243
void remove_row(const unsigned row, unsigned count=1)
Removes a row in the listbox.
Definition: listbox.cpp:79
void clear()
Removes all the rows in the listbox, clearing it.
Definition: listbox.cpp:118
int get_selected_row() const
Returns the first selected row.
Definition: listbox.cpp:268
unsigned get_item_count() const
Returns the number of items in the listbox.
Definition: listbox.cpp:124
void set_values(const std::vector<::config > &values, unsigned selected=0)
virtual unsigned get_value() const override
Inherited from selectable_item.
Definition: menu_button.hpp:55
virtual void set_active(const bool active) override
See styled_widget::set_active.
Definition: menu_button.cpp:74
boost::dynamic_bitset get_toggle_states() const
Get the current state of the menu options.
virtual void set_value(int value) override
Inherited from integer_selector.
Definition: slider.cpp:81
virtual int get_value() const override
Inherited from integer_selector.
Definition: slider.hpp:52
grid * get_layer_grid(unsigned int i)
Gets the grid for a specified layer.
unsigned int get_layer_count() const
Gets the total number of layers.
void set_find_in_all_layers(const bool do_find)
void select_layer(const int layer)
Selects and displays a particular layer.
const t_string & get_label() const
virtual void set_use_markup(bool use_markup)
std::string get_value() const
const std::string & text() const
virtual void set_value(const std::string &text)
The set_value is virtual for the password_box class.
void set_text_changed_callback(std::function< void(text_box_base *textbox, const std::string text)> cb)
Set the text_changed callback.
A widget that allows the user to input text in single line.
Definition: text_box.hpp:125
virtual void set_value(unsigned selected, bool fire_event=false) override
Inherited from selectable_item.
Base class for all widgets.
Definition: widget.hpp:53
void set_visible(const visibility visible)
Definition: widget.cpp:469
@ visible
The user sets the widget visible, that means:
@ invisible
The user set the widget invisible, that means:
@ hidden
The user sets the widget hidden, that means:
base class of top level items, the only item which needs to store the final canvases to draw on.
Definition: window.hpp:61
void keyboard_capture(widget *widget)
Definition: window.cpp:1221
const std::string & get_status() const
const std::string & get_nick() const
const std::string & get_notes() const
void set_lobby_joins(pref_constants::lobby_joins show)
bool set_music(bool ison)
void set_sound_volume(int vol)
void set_remember_password(bool remember)
bool chat_timestamping()
const std::map< std::string, preferences::acquaintance > & get_acquaintances()
bool skip_ai_moves()
void set_turbo(bool ison)
void set_animate_water(bool value)
bool show_side_colors()
void save_hotkeys()
void set_autosavemax(int value)
bool turn_bell()
void set_show_side_colors(bool value)
void set_idle_anim(const bool ison)
double turbo_speed()
void write_preferences()
int autosavemax()
bool enable_whiteboard_mode_on_start()
void set_draw_delay(int value)
void set_show_floating_labels(bool value)
bool set_ui_sound(bool ison)
bool idle_anim()
static prefs & get()
bool interrupt_when_ally_sighted()
bool show_floating_labels()
void set_turbo_speed(const double speed)
int scroll_speed()
void set_whisper_friends_only(bool v)
void set_theme(const std::string &theme)
void set_auto_pixel_scale(bool choice)
std::vector< preferences::option > & get_advanced_preferences()
void set_delete_saves(bool value)
void set_chat_lines(int lines)
void set_stop_music_in_background(bool ison)
void show_wesnothd_server_search()
int bell_volume()
bool save_replays()
bool hide_whiteboard()
bool delete_saves()
bool set_turn_bell(bool ison)
void set_chat_timestamping(bool value)
void set_music_volume(int vol)
void set_save_replays(bool value)
bool vsync()
void set_show_standing_animations(bool value)
void set_pixel_scale(const int scale)
int draw_delay()
pref_constants::lobby_joins get_lobby_joins()
bool auto_pixel_scale()
void set_disable_auto_moves(bool value)
bool grid()
bool whisper_friends_only()
void set_interrupt_when_ally_sighted(bool value)
bool set_sound(bool ison)
bool animate_map()
bool music_on()
void set_idle_anim_rate(int rate)
void set_scroll_speed(const int scroll)
bool turn_dialog()
std::pair< preferences::acquaintance *, bool > add_acquaintance(const std::string &nick, const std::string &mode, const std::string &notes)
bool ui_sound_on()
int music_volume()
bool disable_auto_moves()
int pixel_scale()
int idle_anim_rate()
void set_ui_volume(int vol)
bool turbo()
void set_hide_whiteboard(bool value)
void set_bell_volume(int vol)
void set_enable_whiteboard_mode_on_start(bool value)
void set_animate_map(bool value)
void set_skip_ai_moves(bool value)
bool animate_water()
bool remember_password()
int ui_volume()
int chat_lines()
void set_grid(bool ison)
int sound_volume()
bool sound_on()
void set_turn_dialog(bool ison)
void clear_hotkeys()
void set_vsync(bool ison)
bool show_standing_animations()
bool stop_music_in_background()
Definition: theme.hpp:43
static std::vector< theme_info > get_basic_theme_info(bool include_hidden=false)
Returns minimal info about saved themes, optionally including hidden ones.
Definition: theme.cpp:987
map_display and display: classes which take care of displaying the map and game-data on the screen.
Declarations for File-IO.
#define VGETTEXT(msgid,...)
Handy wrappers around interpolate_variables_into_string and gettext.
std::size_t i
Definition: function.cpp:968
int w
static std::string _(const char *str)
Definition: gettext.hpp:93
#define WRN_GUI_L
Definition: log.hpp:57
This file contains the window object, this object is a top level container which has the event manage...
New lexcical_cast header.
void raise_resize_event()
Definition: events.cpp:767
static bool file_exists(const bfs::path &fpath)
Definition: filesystem.cpp:319
const std::string unicode_multiplication_sign
Definition: constants.cpp:46
std::string selected
std::string path
Definition: filesystem.cpp:84
static bool sound_on()
static void set_sound_volume(int v)
static int bell_volume()
static bool set_sound(bool v)
static bool set_music(bool v)
static bool set_ui_sound(bool v)
static bool turn_bell()
static int music_volume()
static void set_bell_volume(int v)
static void set_ui_volume(int v)
static void set_music_volume(int v)
REGISTER_DIALOG(editor_edit_unit)
static bool set_turn_bell(bool v)
static int ui_volume()
static bool ui_sound_on()
static int sound_volume()
static bool music_on()
void connect_signal_mouse_left_release(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button release.
Definition: dispatcher.cpp:187
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification &signal)
Connects a signal handler for getting a notification upon modification.
Definition: dispatcher.cpp:203
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
Definition: dispatcher.cpp:177
std::map< std::string, widget_item > widget_data
Definition: widget.hpp:34
void show_transient_error_message(const std::string &message, const std::string &image, const bool message_use_markup)
Shows a transient error message to the user.
std::map< std::string, t_string > widget_item
Definition: widget.hpp:31
void show_transient_message(const std::string &title, const std::string &message, const std::string &image, const bool message_use_markup, const bool title_use_markup)
Shows a transient message to the user.
void show_message(const std::string &title, const std::string &msg, const std::string &button_caption, const bool auto_close, const bool message_use_markup, const bool title_use_markup)
Shows a message to the user.
Definition: message.cpp:150
@ OK
Dialog was closed with the OK button.
Definition: retval.hpp:35
std::pair< std::string, unsigned > item
Definition: help_impl.hpp:410
const hotkey_list & get_hotkeys()
Returns the list of hotkeys.
std::string get_names(const std::string &id)
Returns a comma-separated string of hotkey names.
std::shared_ptr< class hotkey_base > hotkey_ptr
Definition: hotkey_item.hpp:27
void clear_hotkeys(const std::string &command)
Unset the command bindings for all hotkeys matching the command.
const std::map< std::string_view, hotkey::hotkey_command > & get_hotkey_commands()
returns a container that contains all currently active hotkey_commands.
std::vector< hotkey::hotkey_ptr > hotkey_list
Definition: hotkey_item.hpp:31
void add_hotkey(hotkey_ptr item)
Add a hotkey to the list of hotkeys.
t_string get_translatable_category_name(HOTKEY_CATEGORY category)
Gets the display name for a given hotkey category.
const hotkey_command & get_hotkey_command(const std::string &command)
returns the hotkey_command with the given name
Functions to load and save images from/to disk.
game_data * gamedata
Definition: resources.cpp:22
bool ci_search(const std::string &s1, const std::string &s2)
Definition: gettext.cpp:565
std::vector< std::string > split(const config_attribute_value &val)
std::vector< point > get_available_resolutions(const bool include_current)
Returns the list of available screen resolutions.
Definition: video.cpp:704
point current_resolution()
The current window size in desktop coordinates.
Definition: video.cpp:756
void set_fullscreen(bool fullscreen)
Set the fullscreen state.
Definition: video.cpp:772
bool set_resolution(const point &resolution)
Set the window resolution.
Definition: video.cpp:801
void toggle_fullscreen()
Toggle fullscreen mode.
Definition: video.cpp:796
void update_buffers(bool autoupdate)
Update buffers to match current resolution and pixel scale settings.
Definition: video.cpp:831
std::string_view data
Definition: picture.cpp:194
Stores all information related to functions that can be bound to hotkeys.
std::string id
The unique ID.
Holds a 2D point.
Definition: point.hpp:25
static bool get(const std::string &pref, bool def)
static void set(const std::string &pref, bool value)
Definitions related to theme-support.
#define VALIDATE(cond, message)
The macro to use for the validation of WML.
#define h