The Battle for Wesnoth  1.17.0-dev
wml_error.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2018 by Iris Morelle <shadowm2006@gmail.com>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
18 
19 #include "addon/info.hpp"
20 // Needs the full path to avoid confusion with gui/dialogs/addon/manager.hpp.
21 #include "../../addon/manager.hpp"
22 #include "desktop/clipboard.hpp"
23 #include "filesystem.hpp"
25 #include "gui/widgets/button.hpp"
27 #include "gui/widgets/settings.hpp"
28 #include "gui/widgets/window.hpp"
30 
31 #include "gettext.hpp"
32 
33 #include <functional>
34 
35 namespace
36 {
37 
38 void strip_trailing_dir_separators(std::string& str)
39 {
40  while(filesystem::is_path_sep(str.back())) {
41  str.erase(str.size() - 1);
42  }
43 }
44 
45 std::string format_file_list(const std::vector<std::string>& files_original)
46 {
47  if(files_original.empty()) {
48  return "";
49  }
50 
51  const std::string& addons_path = filesystem::get_addons_dir();
52  std::vector<std::string> files(files_original);
53 
54  for(std::string & file : files)
55  {
56  std::string base;
57  std::string filename = filesystem::base_name(file);
58  std::string parent_path;
59 
60  const bool is_main_cfg = filename == "_main.cfg";
61 
62  if(is_main_cfg) {
63  parent_path = filesystem::directory_name(file) + "/..";
64  } else {
65  parent_path = filesystem::directory_name(file);
66  }
67 
68  // Only proceed to pretty-format the filename if it's from the add-ons
69  // directory.
70  if(filesystem::normalize_path(parent_path) != filesystem::normalize_path(addons_path)) {
71  continue;
72  }
73 
74  if(is_main_cfg) {
75  base = filesystem::directory_name(file);
76  // HACK: fool filesystem::base_name() into giving us the parent directory name
77  // alone by making base seem not like a directory path,
78  // otherwise it returns an empty string.
79  strip_trailing_dir_separators(base);
80  base = filesystem::base_name(base);
81  } else {
82  base = filename;
83  }
84 
85  if(base.empty()) {
86  // We did something wrong. In the interest of not messing up the
87  // report, leave the original filename intact.
88  continue;
89  }
90 
91  //
92  // Display the name as an add-on name instead of a filename.
93  //
94 
95  if(!is_main_cfg) {
96  // Remove the file extension first.
97  static const std::string wml_suffix = ".cfg";
98 
99  if(base.size() > wml_suffix.size()) {
100  const std::size_t suffix_pos = base.size() - wml_suffix.size();
101  if(base.substr(suffix_pos) == wml_suffix) {
102  base.erase(suffix_pos);
103  }
104  }
105  }
106 
107  if(have_addon_install_info(base)) {
108  // _info.cfg may have the add-on's title starting with 1.11.7,
109  // if the add-on was downloaded using the revised _info.cfg writer.
110  config info_cfg;
111  get_addon_install_info(base, info_cfg);
112 
113  if(!info_cfg.empty() && !info_cfg["title"].empty()) {
114  file = info_cfg["title"].str();
115  continue;
116  }
117  }
118 
119  // Fallback to using a synthetic title with underscores replaced with
120  // whitespace.
121  file = make_addon_title(base);
122  }
123 
124  if(files.size() == 1) {
125  return utils::indent(files.front());
126  }
127 
128  return utils::bullet_list(files);
129 }
130 }
131 
132 namespace gui2::dialogs
133 {
134 
135 REGISTER_DIALOG(wml_error)
136 
137 wml_error::wml_error(const std::string& summary,
138  const std::string& post_summary,
139  const std::vector<std::string>& files,
140  const std::string& details)
141  : have_files_(!files.empty())
142  , have_post_summary_(!post_summary.empty())
143  , report_()
144 {
145  set_restore(true);
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
bool available()
Whether wesnoth was compiled with support for a clipboard.
Definition: clipboard.cpp:54
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:92
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:92
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:87
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:34
void set_visible(const visibility visible)
Definition: widget.cpp:475
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:171
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:319
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:62
void copy_to_clipboard(const std::string &text, const bool)
Copies text to the clipboard.
Definition: clipboard.cpp:33
std::string get_addons_dir()
virtual void pre_show(window &window) override
Actions to be taken before showing the window.
Definition: wml_error.cpp:172
std::string indent(const std::string &string, std::size_t indent_size)
Indent a block of text.
Simple push button.
Definition: button.hpp:35
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
base class of top level items, the only item which needs to store the final canvases to draw on...
Definition: window.hpp:64
bool empty() const
Definition: config.cpp:921
std::string directory_name(const std::string &file)
Returns the directory name of a file, with filename stripped.