The Battle for Wesnoth  1.17.0-dev
wml_error.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2021
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  : have_files_(!files.empty())
143  , have_post_summary_(!post_summary.empty())
144  , report_()
145 {
146  set_restore(true);
147 
148  const std::string& file_list_text = format_file_list(files);
149 
150  report_ = summary;
151 
152  if(!file_list_text.empty()) {
153  report_ += "\n" + file_list_text;
154  }
155 
156  if(!post_summary.empty()) {
157  report_ += "\n\n" + post_summary;
158  }
159 
160  report_ += "\n\n";
161  report_ += _("Details:");
162  report_ += "\n\n" + utils::indent(details);
163  // Since this is likely to be pasted into a text file, add a final line
164  // break for convenience, since otherwise the report ends mid-line.
165  report_ += "\n";
166 
167  register_label("summary", true, summary);
168  register_label("post_summary", true, post_summary);
169  register_label("files", true, file_list_text);
170  register_label("details", true, details);
171 }
172 
174 {
175  if(!have_files_) {
176  styled_widget& filelist = find_widget<styled_widget>(&window, "files", false);
178  }
179 
180  if(!have_post_summary_) {
181  styled_widget& post_summary
182  = find_widget<styled_widget>(&window, "post_summary", false);
184  }
185 
186  button& copy_button = find_widget<button>(&window, "copy", false);
187 
189  copy_button, std::bind(&wml_error::copy_report_callback, this));
190 
192  copy_button.set_active(false);
193  copy_button.set_tooltip(_("Clipboard support not found, contact your packager"));
194  }
195 }
196 
198 {
200 }
201 
202 } // end namespace dialogs
bool available()
Whether wesnoth was compiled with support for a clipboard.
Definition: clipboard.cpp:55
This file contains the window object, this object is a top level container which has the event manage...
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:93
STL namespace.
std::string normalize_path(const std::string &fpath, bool normalize_separators, bool resolve_dot_entries)
Returns the absolute path of a file.
static std::string _(const char *str)
Definition: gettext.hpp:93
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:88
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.
void set_tooltip(const t_string &tooltip)
This file contains the settings handling of the widget library.
WML preprocessor/parser error report dialog.
Definition: wml_error.hpp:35
void set_visible(const visibility visible)
Definition: widget.cpp:476
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal_function &signal)
Connects a signal handler for a left mouse button click.
Definition: dispatcher.cpp:172
bool is_path_sep(char c)
Returns whether c is a path separator.
The user set the widget invisible, that means:
Declarations for File-IO.
Base class for all visible items.
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
std::string base_name(const std::string &file, const bool remove_extension)
Returns the base filename of a file, with directory name stripped.
virtual void set_active(const bool active) override
See styled_widget::set_active.
Definition: button.cpp:63
void copy_to_clipboard(const std::string &text, const bool)
Copies text to the clipboard.
Definition: clipboard.cpp:34
std::string get_addons_dir()
virtual void pre_show(window &window) override
Actions to be taken before showing the window.
Definition: wml_error.cpp:173
std::string indent(const std::string &string, std::size_t indent_size)
Indent a block of text.
Simple push button.
Definition: button.hpp:36
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:61
base class of top level items, the only item which needs to store the final canvases to draw on...
Definition: window.hpp:65
bool empty() const
Definition: config.cpp:941
std::string directory_name(const std::string &file)
Returns the directory name of a file, with filename stripped.