The Battle for Wesnoth  1.19.18+dev
game_version_dialog.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2013 - 2025
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"
26 #include "gui/widgets/button.hpp"
28 #include "gui/widgets/listbox.hpp"
31 #include "gui/widgets/window.hpp"
32 #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 
99  //
100  // General information.
101  //
102 
103  find_widget<styled_widget>("version").set_label(game_config::revision);
104  find_widget<styled_widget>("os").set_label(markup::italic(desktop::os_version()));
105  find_widget<styled_widget>("arch").set_label(game_config::build_arch());
106 
107  connect_signal_mouse_left_click(find_widget<button>("copy_all"),
108  std::bind(&game_version::report_copy_callback, this));
109 
110  // Bottom row buttons
111  connect_signal_mouse_left_click(find_widget<button>("credits"),
112  std::bind(&game_version::show_credits_dialog, this));
113 
114  connect_signal_mouse_left_click(find_widget<button>("license"),
115  std::bind(&game_version::show_license, this));
116 
117  connect_signal_mouse_left_click(find_widget<button>("issue"),
118  std::bind(&game_version::report_issue, this));
119 
120  connect_signal_mouse_left_click(find_widget<button>("run_migrator"),
121  std::bind(&game_version::run_migrator, this));
122 
123  connect_signal_mouse_left_click(find_widget<button>("view_manual"),
124  std::bind(&game_version::show_manual, this));
125 
126  //
127  // Game paths tab.
128  //
129 
130  for(const auto & path_ent : path_map_)
131  {
132  const std::string& path_id = path_ent.first;
133  const std::string& path_path = filesystem::normalize_path(path_ent.second, true);
134 
135  text_box_base& path_w = find_widget<text_box_base>(path_wid_stem_ + path_id);
136  button& copy_w = find_widget<button>(copy_wid_stem_ + path_id);
137  button& browse_w = find_widget<button>(browse_wid_stem_ + path_id);
138 
139  path_w.set_value(path_path);
140 
142  copy_w,
143  std::bind(&game_version::copy_to_clipboard_callback, this, path_path, copy_wid_stem_ + path_id));
145  browse_w,
146  std::bind(&game_version::browse_directory_callback, this, path_path));
147 
149  // No point in displaying these on platforms that can't do
150  // open_object().
152  }
153  }
154 
155  button& stderr_button = find_widget<button>("open_stderr");
156  connect_signal_mouse_left_click(stderr_button,
158  stderr_button.set_active(!log_path_.empty() && filesystem::file_exists(log_path_));
159 
160  //
161  // Build info tab.
162  //
163 
164  listbox& deps_listbox = find_widget<listbox>("deps_listbox");
165 
166  for(const auto& dep : deps_) {
167  deps_listbox.add_row(widget_data{
168  { "dep_name", {
169  { "label", dep[0] }
170  }},
171  { "dep_build_version",{
172  { "label", dep[1] }
173  }},
174  // The build version is always known, but runtime version isn't, esp. for
175  // header-only libraries like Boost for which the concept does not apply.
176  { "dep_rt_version", {
177  { "label", dep[2].empty() ? font::unicode_em_dash : dep[2] }
178  }},
179  });
180  }
181 
182  deps_listbox.select_row(0);
183 
184  //
185  // Features tab.
186  //
187 
188  listbox& opts_listbox = find_widget<listbox>("opts_listbox");
189 
190  for(const auto& opt : opts_) {
191  opts_listbox.add_row(widget_data{
192  { "opt_name", {
193  { "label", opt.name }
194  }},
195  { "opt_status", {
196  { "label", opt.enabled ? text_feature_on : text_feature_off },
197  { "use_markup", "true" }
198  }},
199  });
200  }
201 
202  opts_listbox.select_row(0);
203 
204  //
205  // Community tab
206  //
207 
208  connect_signal_mouse_left_click(find_widget<button>("forums"),
209  std::bind(&desktop::open_object, "https://forums.wesnoth.org/"));
210  connect_signal_mouse_left_click(find_widget<button>("discord"),
211  std::bind(&desktop::open_object, "https://discord.gg/battleforwesnoth"));
212  connect_signal_mouse_left_click(find_widget<button>("irc"),
213  std::bind(&desktop::open_object, "https://web.libera.chat/#wesnoth"));
214  connect_signal_mouse_left_click(find_widget<button>("steam"),
215  std::bind(&desktop::open_object, "https://steamcommunity.com/app/599390/discussions/"));
216  connect_signal_mouse_left_click(find_widget<button>("reddit"),
217  std::bind(&desktop::open_object, "https://www.reddit.com/r/wesnoth/"));
218  connect_signal_mouse_left_click(find_widget<button>("donate"),
219  std::bind(&desktop::open_object, "https://www.spi-inc.org/projects/wesnoth/"));
220 
221  find_widget<tab_container>("tabs").select_tab(start_page_);
222 }
223 
225 {
227 }
228 
230 {
232 }
233 
234 void game_version::copy_to_clipboard_callback(const std::string& path, const std::string& btn_id)
235 {
237  find_widget<button>(btn_id).set_success(true);
238 }
239 
241 {
243  find_widget<button>("copy_all").set_success(true);
244 }
245 
247 {
249 }
250 
252  gui2::dialogs::end_credits::display();
253 }
254 
256  help::show_help("license");
257 }
258 
261  desktop::open_object("https://bugs.wesnoth.org");
262  } else {
263  show_message("", _("Opening links is not supported, contact your packager"), dialogs::message::auto_close);
264  }
265 }
266 
269  const auto& manual_path = filesystem::get_game_manual_file(get_language().localename);
270  if (manual_path) {
271  desktop::open_object(manual_path.value());
272  } else {
273  // Use web manual as a last resort
274  desktop::open_object("https://www.wesnoth.org/manual/dev/manual." + get_language().localename + ".html");
275  }
276  } else {
277  show_message("", _("Opening links is not supported, contact your packager"), dialogs::message::auto_close);
278  }
279 }
280 
281 } // 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:41
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:92
bool select_row(const unsigned row, const bool select=true)
Selects a row.
Definition: listbox.cpp:267
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:97
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:327
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:50
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:220
std::string get_cache_dir()
Definition: filesystem.cpp:885
std::string get_user_data_dir()
Definition: filesystem.cpp:875
static bool file_exists(const bfs::path &fpath)
Definition: filesystem.cpp:344
std::string get_saves_dir()
std::string get_screenshot_dir()
std::string get_logs_dir()
Definition: filesystem.cpp:880
utils::optional< std::string > get_game_manual_file(const std::string &locale_code)
location of the game manual file correponding to the given locale (default: en)
Definition: filesystem.cpp:849
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:106
std::string full_build_report()
Produce a bug report-style info dump.
Definition: build_info.cpp:666
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:163
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.
Definition: help.cpp:83
Definition: pump.hpp:41
std::string get_log_file_path()
Definition: log.cpp:317
std::string italic(Args &&... data)
Applies italic Pango markup to the input.
Definition: markup.hpp:176
std::string span_color(const color_t &color, Args &&... data)
Applies Pango markup to the input specifying its display color.
Definition: markup.hpp:110
std::map< std::string, t_string > string_map
Desktop environment interaction functions.
#define e