The Battle for Wesnoth  1.19.10+dev
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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  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  listbox& deps_listbox = find_widget<listbox>("deps_listbox");
169 
170  for(const auto& dep : deps_) {
171  deps_listbox.add_row(widget_data{
172  { "dep_name", {
173  { "label", dep[0] }
174  }},
175  { "dep_build_version",{
176  { "label", dep[1] }
177  }},
178  // The build version is always known, but runtime version isn't, esp. for
179  // header-only libraries like Boost for which the concept does not apply.
180  { "dep_rt_version", {
181  { "label", dep[2].empty() ? font::unicode_em_dash : dep[2] }
182  }},
183  });
184  }
185 
186  deps_listbox.select_row(0);
187 
188  //
189  // Features tab.
190  //
191  tabs.select_tab(3);
192 
193  listbox& opts_listbox = find_widget<listbox>("opts_listbox");
194 
195  for(const auto& opt : opts_) {
196  opts_listbox.add_row(widget_data{
197  { "opt_name", {
198  { "label", opt.name }
199  }},
200  { "opt_status", {
201  { "label", opt.enabled ? text_feature_on : text_feature_off },
202  { "use_markup", "true" }
203  }},
204  });
205  }
206 
207  opts_listbox.select_row(0);
208 
209  //
210  // Community tab
211  //
212  tabs.select_tab(4);
213 
214  connect_signal_mouse_left_click(find_widget<button>("forums"),
215  std::bind(&desktop::open_object, "https://forums.wesnoth.org/"));
216  connect_signal_mouse_left_click(find_widget<button>("discord"),
217  std::bind(&desktop::open_object, "https://discord.gg/battleforwesnoth"));
218  connect_signal_mouse_left_click(find_widget<button>("irc"),
219  std::bind(&desktop::open_object, "https://web.libera.chat/#wesnoth"));
220  connect_signal_mouse_left_click(find_widget<button>("steam"),
221  std::bind(&desktop::open_object, "https://steamcommunity.com/app/599390/discussions/"));
222  connect_signal_mouse_left_click(find_widget<button>("reddit"),
223  std::bind(&desktop::open_object, "https://www.reddit.com/r/wesnoth/"));
224  connect_signal_mouse_left_click(find_widget<button>("donate"),
225  std::bind(&desktop::open_object, "https://www.spi-inc.org/projects/wesnoth/"));
226 
227  //
228  // Set-up page stack and auxiliary controls last.
229  //
230 
231  tabs.select_tab(start_page_);
232 }
233 
235 {
237 }
238 
240 {
242 }
243 
244 void game_version::copy_to_clipboard_callback(const std::string& path, const std::string& btn_id)
245 {
247  find_widget<button>(btn_id).set_success(true);
248 }
249 
251 {
253  find_widget<button>("copy_all").set_success(true);
254 }
255 
257 {
259 }
260 
262  gui2::dialogs::end_credits::display();
263 }
264 
266  help::show_help("license");
267 }
268 
271  desktop::open_object("https://bugs.wesnoth.org");
272  } else {
273  show_message("", _("Opening links is not supported, contact your packager"), dialogs::message::auto_close);
274  }
275 }
276 
279  const auto& manual_path = filesystem::get_game_manual_file(get_language().localename);
280  if (manual_path) {
281  desktop::open_object(manual_path.value());
282  } else {
283  // Use web manual as a last resort
284  desktop::open_object("https://www.wesnoth.org/manual/dev/manual." + get_language().localename + ".html");
285  }
286  } else {
287  show_message("", _("Opening links is not supported, contact your packager"), dialogs::message::auto_close);
288  }
289 }
290 
291 } // 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:280
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: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: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:866
std::string get_user_data_dir()
Definition: filesystem.cpp:856
static bool file_exists(const bfs::path &fpath)
Definition: filesystem.cpp:328
std::string get_saves_dir()
std::string get_screenshot_dir()
std::string get_logs_dir()
Definition: filesystem.cpp:861
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:830
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:93
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, show topic with id show_topic.
Definition: help.cpp:140
Definition: pump.hpp:41
std::string get_log_file_path()
Definition: log.cpp:284
std::string italic(Args &&... data)
Applies italic Pango markup to the input.
Definition: markup.hpp:182
std::string span_color(const color_t &color, Args &&... data)
Applies Pango markup to the input specifying its display color.
Definition: markup.hpp:116
std::map< std::string, t_string > string_map
Desktop environment interaction functions.
#define e