The Battle for Wesnoth  1.19.5+dev
game_version_dialog.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2013 - 2024
3  by Iris Morelle <shadowm2006@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #define GETTEXT_DOMAIN "wesnoth-lib"
17 
19 
20 #include "build_info.hpp"
21 #include "desktop/clipboard.hpp"
22 #include "desktop/open.hpp"
23 #include "desktop/version.hpp"
24 #include "filesystem.hpp"
25 #include "formula/string_utils.hpp"
27 #include "gui/widgets/button.hpp"
29 #include "gui/widgets/listbox.hpp"
32 #include "gui/widgets/window.hpp"
33 #include "gui/dialogs/message.hpp"
35 #include "gettext.hpp"
36 #include "help/help.hpp"
37 #include "language.hpp"
38 #include "serialization/markup.hpp"
39 
40 #include <functional>
41 
42 namespace
43 {
44 
45 const std::string text_feature_on = markup::span_color("#0f0", "&#9679;");
46 const std::string text_feature_off = markup::span_color("#f00", "&#9679;");
47 
48 } // end anonymous namespace
49 
50 namespace gui2::dialogs
51 {
52 
53 REGISTER_DIALOG(game_version)
54 
55 game_version::game_version(unsigned start_page)
56  : modal_dialog(window_id())
57  , path_wid_stem_("path_")
58  , copy_wid_stem_("copy_")
59  , browse_wid_stem_("browse_")
60  , path_map_()
61  , log_path_(lg::get_log_file_path())
62  , deps_()
64  , report_()
65  , start_page_(start_page)
66 {
67  // NOTE: these path_map_ entries are referenced by the GUI2 WML
68  // definition of this dialog using preprocessor macros.
69  path_map_["datadir"] = game_config::path;
70  path_map_["userdata"] = filesystem::get_user_data_dir();
71  path_map_["saves"] = filesystem::get_saves_dir();
72  path_map_["addons"] = filesystem::get_addons_dir();
73  path_map_["cache"] = filesystem::get_cache_dir();
74  // path to logs directory
75  path_map_["logs"] = filesystem::get_logs_dir();
76  path_map_["screenshots"] = filesystem::get_screenshot_dir();
77 
78  for(unsigned k = 0; k < game_config::LIB_COUNT; ++k) {
80 
82  e[0] = game_config::library_name(lib);
83  if(e[0].empty()) {
84  continue;
85  }
88  deps_.push_back(e);
89  }
90 
91  generate_plain_text_report();
92 }
93 
95 {
96  utils::string_map i18n_syms;
97 
98  tab_container& tabs = find_widget<tab_container>("tabs");
99 
100  //
101  // General information.
102  //
103  tabs.select_tab(0);
104 
105  find_widget<styled_widget>("version").set_label(game_config::revision);
106  find_widget<styled_widget>("os").set_label(markup::italic(desktop::os_version()));
107  find_widget<styled_widget>("arch").set_label(game_config::build_arch());
108 
109  connect_signal_mouse_left_click(find_widget<button>("copy_all"),
110  std::bind(&game_version::report_copy_callback, this));
111 
112  // Bottom row buttons
113  connect_signal_mouse_left_click(find_widget<button>("credits"),
114  std::bind(&game_version::show_credits_dialog, this));
115 
116  connect_signal_mouse_left_click(find_widget<button>("license"),
117  std::bind(&game_version::show_license, this));
118 
119  connect_signal_mouse_left_click(find_widget<button>("issue"),
120  std::bind(&game_version::report_issue, this));
121 
122  connect_signal_mouse_left_click(find_widget<button>("run_migrator"),
123  std::bind(&game_version::run_migrator, this));
124 
125  connect_signal_mouse_left_click(find_widget<button>("view_manual"),
126  std::bind(&game_version::show_manual, this));
127 
128  //
129  // Game paths tab.
130  //
131  tabs.select_tab(1);
132 
133  for(const auto & path_ent : path_map_)
134  {
135  const std::string& path_id = path_ent.first;
136  const std::string& path_path = filesystem::normalize_path(path_ent.second, true);
137 
138  text_box_base& path_w = find_widget<text_box_base>(path_wid_stem_ + path_id);
139  button& copy_w = find_widget<button>(copy_wid_stem_ + path_id);
140  button& browse_w = find_widget<button>(browse_wid_stem_ + path_id);
141 
142  path_w.set_value(path_path);
143 
145  copy_w,
146  std::bind(&game_version::copy_to_clipboard_callback, this, path_path, copy_wid_stem_ + path_id));
148  browse_w,
149  std::bind(&game_version::browse_directory_callback, this, path_path));
150 
152  // No point in displaying these on platforms that can't do
153  // open_object().
155  }
156  }
157 
158  button& stderr_button = find_widget<button>("open_stderr");
159  connect_signal_mouse_left_click(stderr_button,
161  stderr_button.set_active(!log_path_.empty() && filesystem::file_exists(log_path_));
162 
163  //
164  // Build info tab.
165  //
166  tabs.select_tab(2);
167 
168  widget_data list_data;
169 
170  listbox& deps_listbox = find_widget<listbox>("deps_listbox");
171 
172  for(const auto& dep : deps_)
173  {
174  list_data["dep_name"]["label"] = dep[0];
175  list_data["dep_build_version"]["label"] = dep[1];
176  // The build version is always known, but runtime version isn't, esp.
177  // for header-only libraries like Boost for which the concept does not
178  // apply.
179  list_data["dep_rt_version"]["label"] = dep[2].empty() ? font::unicode_em_dash : dep[2];
180 
181  deps_listbox.add_row(list_data);
182  }
183 
184  deps_listbox.select_row(0);
185  list_data.clear();
186 
187  //
188  // Features tab.
189  //
190  tabs.select_tab(3);
191 
192  listbox& opts_listbox = find_widget<listbox>("opts_listbox");
193 
194  for(const auto& opt : opts_)
195  {
196  list_data["opt_name"]["label"] = opt.name;
197  list_data["opt_status"]["label"] = opt.enabled ? text_feature_on : text_feature_off;
198  list_data["opt_status"]["use_markup"] = "true";
199 
200  opts_listbox.add_row(list_data);
201  }
202 
203  opts_listbox.select_row(0);
204  list_data.clear();
205 
206  //
207  // Community tab
208  //
209  tabs.select_tab(4);
210 
211  connect_signal_mouse_left_click(find_widget<button>("forums"),
212  std::bind(&desktop::open_object, "https://forums.wesnoth.org/"));
213  connect_signal_mouse_left_click(find_widget<button>("discord"),
214  std::bind(&desktop::open_object, "https://discord.gg/battleforwesnoth"));
215  connect_signal_mouse_left_click(find_widget<button>("irc"),
216  std::bind(&desktop::open_object, "https://web.libera.chat/#wesnoth"));
217  connect_signal_mouse_left_click(find_widget<button>("steam"),
218  std::bind(&desktop::open_object, "https://steamcommunity.com/app/599390/discussions/"));
219  connect_signal_mouse_left_click(find_widget<button>("reddit"),
220  std::bind(&desktop::open_object, "https://www.reddit.com/r/wesnoth/"));
221  connect_signal_mouse_left_click(find_widget<button>("donate"),
222  std::bind(&desktop::open_object, "https://www.spi-inc.org/projects/wesnoth/"));
223 
224  //
225  // Set-up page stack and auxiliary controls last.
226  //
227 
228  tabs.select_tab(start_page_);
229 }
230 
232 {
234 }
235 
237 {
239 }
240 
241 void game_version::copy_to_clipboard_callback(const std::string& path, const std::string& btn_id)
242 {
244  find_widget<button>(btn_id).set_success(true);
245 }
246 
248 {
250  find_widget<button>("copy_all").set_success(true);
251 }
252 
254 {
256 }
257 
259  gui2::dialogs::end_credits::display();
260 }
261 
263  help::show_help("license");
264 }
265 
268  show_message("", _("Opening links is not supported, contact your packager"), dialogs::message::auto_close);
269  return;
270  } else {
271  desktop::open_object("https://bugs.wesnoth.org");
272  }
273 }
274 
277  std::string manual_filename = "manual." + get_language().localename + ".html";
278  std::string local_path = game_config::path + "/doc/manual/" + manual_filename;
279  if (filesystem::file_exists(local_path)) {
280  desktop::open_object("file://" + local_path);
281  } else {
282  // If a filename like manual.en_GB.html is not found, try manual.en.html
283  manual_filename = "manual." + utils::split(get_language().localename, '_')[0] + ".html";
284  std::string local_path = game_config::path + "/doc/manual/" + manual_filename;
285  if (filesystem::file_exists(local_path)) {
286  desktop::open_object("file://" + local_path);
287  } else {
288  desktop::open_object("https://www.wesnoth.org/manual/dev/" + manual_filename);
289  }
290  }
291  } else {
292  show_message("", _("Opening links is not supported, contact your packager"), dialogs::message::auto_close);
293  }
294 }
295 
296 } // namespace dialogs
Simple push button.
Definition: button.hpp:36
virtual void set_active(const bool active) override
See styled_widget::set_active.
Definition: button.cpp:64
const std::string path_wid_stem_
The display function.
void report_issue()
Open browser to report issue.
std::array< std::string, 4 > deplist_entry
void report_copy_callback()
Callback function for the dialog-wide copy-to-clipboard button.
std::map< std::string, std::string > path_map_
const std::string log_path_
path to current log file
void run_migrator()
Re-runs the version migration dialog.
void show_credits_dialog()
Show credits dialogs.
std::vector< deplist_entry > deps_
void copy_to_clipboard_callback(const std::string &path, const std::string &btn_id)
Callback function for copy-to-clipboard action buttons.
void browse_directory_callback(const std::string &path)
Callback function for browse-directory action buttons.
std::vector< game_config::optional_feature > opts_
virtual void pre_show() override
Actions to be taken before showing the window.
void show_manual()
Opens the game manual in the platform's browser.
@ auto_close
Enables auto close.
Definition: message.hpp:71
Abstract base class for all modal dialogs.
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:58
bool select_row(const unsigned row, const bool select=true)
Selects a row.
Definition: listbox.cpp:242
A container widget that shows one of its pages of widgets depending on which tab the user clicked.
void select_tab(unsigned index)
Abstract base class for text items.
virtual void set_value(const std::string &text)
The set_value is virtual for the password_box class.
void set_visible(const visibility visible)
Definition: widget.cpp:479
@ invisible
The user set the widget invisible, that means:
Platform identification and version information functions.
Declarations for File-IO.
static std::string _(const char *str)
Definition: gettext.hpp:93
This file contains the window object, this object is a top level container which has the event manage...
const language_def & get_language()
Definition: language.cpp:325
void copy_to_clipboard(const std::string &text)
Copies text to the clipboard.
Definition: clipboard.cpp:27
bool open_object([[maybe_unused]] const std::string &path_or_url)
Definition: open.cpp:46
constexpr bool open_object_is_supported()
Returns whether open_object() is supported/implemented for the current platform.
Definition: open.hpp:54
std::string os_version()
Returns a string with the running OS name and version information.
Definition: version.cpp:216
std::string get_cache_dir()
Definition: filesystem.cpp:837
std::string get_user_data_dir()
Definition: filesystem.cpp:827
static bool file_exists(const bfs::path &fpath)
Definition: filesystem.cpp:325
std::string get_saves_dir()
std::string get_screenshot_dir()
std::string get_logs_dir()
Definition: filesystem.cpp:832
std::string get_addons_dir()
std::string normalize_path(const std::string &fpath, bool normalize_separators, bool resolve_dot_entries)
Returns the absolute path of a file.
const std::string unicode_em_dash
Definition: constants.cpp:44
Game configuration data as global variables.
Definition: build_info.cpp:61
const std::string & library_name(LIBRARY_ID lib)
Retrieve the user-visible name for the given library.
Definition: build_info.cpp:387
std::string path
Definition: filesystem.cpp:90
std::string full_build_report()
Produce a bug report-style info dump.
Definition: build_info.cpp:665
std::vector< optional_feature > optional_features_table(bool localize)
Retrieve the features table.
Definition: build_info.cpp:350
const std::string & library_runtime_version(LIBRARY_ID lib)
Retrieve the runtime version number of the given library.
Definition: build_info.cpp:378
const std::string & library_build_version(LIBRARY_ID lib)
Retrieve the build-time version number of the given library.
Definition: build_info.cpp:369
std::string build_arch()
Obtain the processor architecture for this build.
Definition: build_info.cpp:316
const std::string revision
REGISTER_DIALOG(editor_edit_unit)
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:36
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:148
void show_help(const std::string &show_topic)
Open the help browser, show topic with id show_topic.
Definition: help.cpp:140
Definition: pump.hpp:41
std::string get_log_file_path()
Definition: log.cpp:283
std::string span_color(const color_t &color, Args &&... data)
Returns a Pango formatting string using the provided color_t object.
Definition: markup.hpp:68
std::string italic(Args &&... s)
Returns a Pango formatting string corresponding to italic formatting.
Definition: markup.hpp:120
std::map< std::string, t_string > string_map
std::vector< std::string > split(const config_attribute_value &val)
Desktop environment interaction functions.
std::string localename
Definition: language.hpp:53
#define e