The Battle for Wesnoth  1.17.17+dev
wml_error.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2023
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 "addon/info.hpp"
21 // Needs the full path to avoid confusion with gui/dialogs/addon/manager.hpp.
22 #include "../../addon/manager.hpp"
23 #include "desktop/clipboard.hpp"
24 #include "filesystem.hpp"
26 #include "gui/widgets/button.hpp"
28 #include "gui/widgets/settings.hpp"
29 #include "gui/widgets/window.hpp"
31 
32 #include "gettext.hpp"
33 
34 #include <functional>
35 
36 namespace
37 {
38 
39 void strip_trailing_dir_separators(std::string& str)
40 {
41  while(filesystem::is_path_sep(str.back())) {
42  str.erase(str.size() - 1);
43  }
44 }
45 
46 std::string format_file_list(const std::vector<std::string>& files_original)
47 {
48  if(files_original.empty()) {
49  return "";
50  }
51 
52  const std::string& addons_path = filesystem::get_addons_dir();
53  std::vector<std::string> files(files_original);
54 
55  for(std::string & file : files)
56  {
57  std::string base;
58  std::string filename = filesystem::base_name(file);
59  std::string parent_path;
60 
61  const bool is_main_cfg = filename == "_main.cfg";
62 
63  if(is_main_cfg) {
64  parent_path = filesystem::directory_name(file) + "/..";
65  } else {
66  parent_path = filesystem::directory_name(file);
67  }
68 
69  // Only proceed to pretty-format the filename if it's from the add-ons
70  // directory.
71  if(filesystem::normalize_path(parent_path) != filesystem::normalize_path(addons_path)) {
72  continue;
73  }
74 
75  if(is_main_cfg) {
76  base = filesystem::directory_name(file);
77  // HACK: fool filesystem::base_name() into giving us the parent directory name
78  // alone by making base seem not like a directory path,
79  // otherwise it returns an empty string.
80  strip_trailing_dir_separators(base);
81  base = filesystem::base_name(base);
82  } else {
83  base = filename;
84  }
85 
86  if(base.empty()) {
87  // We did something wrong. In the interest of not messing up the
88  // report, leave the original filename intact.
89  continue;
90  }
91 
92  //
93  // Display the name as an add-on name instead of a filename.
94  //
95 
96  if(!is_main_cfg) {
97  // Remove the file extension first.
98  static const std::string wml_suffix = ".cfg";
99 
100  if(base.size() > wml_suffix.size()) {
101  const std::size_t suffix_pos = base.size() - wml_suffix.size();
102  if(base.substr(suffix_pos) == wml_suffix) {
103  base.erase(suffix_pos);
104  }
105  }
106  }
107 
108  if(have_addon_install_info(base)) {
109  // _info.cfg may have the add-on's title starting with 1.11.7,
110  // if the add-on was downloaded using the revised _info.cfg writer.
111  config info_cfg;
112  get_addon_install_info(base, info_cfg);
113 
114  if(!info_cfg.empty() && !info_cfg["title"].empty()) {
115  file = info_cfg["title"].str();
116  continue;
117  }
118  }
119 
120  // Fallback to using a synthetic title with underscores replaced with
121  // whitespace.
122  file = make_addon_title(base);
123  }
124 
125  if(files.size() == 1) {
126  return utils::indent(files.front());
127  }
128 
129  return utils::bullet_list(files);
130 }
131 }
132 
133 namespace gui2::dialogs
134 {
135 
136 REGISTER_DIALOG(wml_error)
137 
138 wml_error::wml_error(const std::string& summary,
139  const std::string& post_summary,
140  const std::vector<std::string>& files,
141  const std::string& details)
142  : modal_dialog(window_id())
143  , have_files_(!files.empty())
144  , have_post_summary_(!post_summary.empty())
145  , report_()
146 {
147  const std::string& file_list_text = format_file_list(files);
148 
149  report_ = summary;
150 
151  if(!file_list_text.empty()) {
152  report_ += "\n" + file_list_text;
153  }
154 
155  if(!post_summary.empty()) {
156  report_ += "\n\n" + post_summary;
157  }
158 
159  report_ += "\n\n";
160  report_ += _("Details:");
161  report_ += "\n\n" + utils::indent(details);
162  // Since this is likely to be pasted into a text file, add a final line
163  // break for convenience, since otherwise the report ends mid-line.
164  report_ += "\n";
165 
166  register_label("summary", true, summary);
167  register_label("post_summary", true, post_summary);
168  register_label("files", true, file_list_text);
169  register_label("details", true, details);
170 }
171 
173 {
174  if(!have_files_) {
175  styled_widget& filelist = find_widget<styled_widget>(&window, "files", false);
177  }
178 
179  if(!have_post_summary_) {
180  styled_widget& post_summary
181  = find_widget<styled_widget>(&window, "post_summary", false);
183  }
184 
185  button& copy_button = find_widget<button>(&window, "copy", false);
186 
188  copy_button, std::bind(&wml_error::copy_report_callback, this));
189 
191  copy_button.set_active(false);
192  copy_button.set_tooltip(_("Clipboard support not found, contact your packager"));
193  }
194 }
195 
197 {
199 }
200 
201 } // end namespace dialogs
void get_addon_install_info(const std::string &addon_name, config &cfg)
Gets the installation info (_info.cfg) for an add-on.
Definition: manager.cpp:106
bool have_addon_install_info(const std::string &addon_name)
Returns true if there is a local installation info (_info.cfg) file for the add-on.
Definition: manager.cpp:101
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:161
bool empty() const
Definition: config.cpp:856
Simple push button.
Definition: button.hpp:37
virtual void set_active(const bool active) override
See styled_widget::set_active.
Definition: button.cpp:65
Abstract base class for all modal dialogs.
WML preprocessor/parser error report dialog.
Definition: wml_error.hpp:36
virtual void pre_show(window &window) override
Actions to be taken before showing the window.
Definition: wml_error.cpp:172
Base class for all visible items.
void set_tooltip(const t_string &tooltip)
void set_visible(const visibility visible)
Definition: widget.cpp:456
@ invisible
The user set the widget invisible, that means:
base class of top level items, the only item which needs to store the final canvases to draw on.
Definition: window.hpp:67
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...
std::string make_addon_title(const std::string &id)
Replaces underscores to dress up file or dirnames as add-on titles.
Definition: info.cpp:320
#define REGISTER_DIALOG(window_id)
Wrapper for REGISTER_DIALOG2.
void copy_to_clipboard(const std::string &text, const bool)
Copies text to the clipboard.
Definition: clipboard.cpp:34
bool available()
Whether wesnoth was compiled with support for a clipboard.
Definition: clipboard.cpp:55
std::string base_name(const std::string &file, const bool remove_extension)
Returns the base filename of a file, with directory name stripped.
std::string directory_name(const std::string &file)
Returns the directory name of a file, with filename stripped.
std::string get_addons_dir()
bool is_path_sep(char c)
Returns whether c is a path separator.
std::string normalize_path(const std::string &fpath, bool normalize_separators, bool resolve_dot_entries)
Returns the absolute path of a file.
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
Definition: dispatcher.cpp:179
std::string indent(const std::string &string, std::size_t indent_size)
Indent a block of text.
std::string bullet_list(const T &v, std::size_t indent=4, const std::string &bullet=font::unicode_bullet)
Generates a new string containing a bullet list.
This file contains the settings handling of the widget library.