The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
list.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2016 by Mark de Wever <[email protected]>
3  Part of the Battle for Wesnoth Project http://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 
17 #include "global.hpp"
19 
20 #include "addon/info.hpp"
21 #include "addon/state.hpp"
22 
23 #include "desktop/clipboard.hpp"
24 #include "desktop/open.hpp"
25 
26 #include "help/help.hpp"
27 #include "gettext.hpp"
28 #include "gui/auxiliary/filter.hpp"
30 #include "gui/dialogs/helper.hpp"
31 #include "gui/widgets/button.hpp"
32 #include "gui/widgets/label.hpp"
34 #include "gui/widgets/drawing.hpp"
35 #include "gui/widgets/image.hpp"
36 #ifdef GUI2_EXPERIMENTAL_LISTBOX
37 #include "gui/widgets/list.hpp"
38 #else
39 #include "gui/widgets/listbox.hpp"
40 #endif
41 #include "gui/widgets/pane.hpp"
42 #include "gui/widgets/settings.hpp"
44 #include "gui/widgets/text_box.hpp"
45 #include "gui/widgets/window.hpp"
48 #include "formula/string_utils.hpp"
49 #include "marked-up_text.hpp"
50 #include "font.hpp"
51 #include "preferences.hpp"
52 #include "strftime.hpp"
53 #include "video.hpp"
54 
55 #include "config.hpp"
56 
57 #include "utils/functional.hpp"
58 #include <sstream>
59 #include <stdexcept>
60 
61 namespace gui2
62 {
63 
64 /*WIKI
65  * @page = GUIWindowDefinitionWML
66  * @order = 2_addon_list
67  *
68  * == Addon list ==
69  *
70  * This shows the dialog with the addons to install. This dialog is under
71  * construction and only used with --new-widgets.
72  *
73  * @begin{table}{dialog_widgets}
74  *
75  * addons & & listbox & m &
76  * A listbox that will contain the info about all addons on the server. $
77  *
78  * -name & & control & o &
79  * The name of the addon. $
80  *
81  * -version & & control & o &
82  * The version number of the addon. $
83  *
84  * -author & & control & o &
85  * The author of the addon. $
86  *
87  * -downloads & & control & o &
88  * The number of times the addon has been downloaded. $
89  *
90  * -size & & control & o &
91  * The size of the addon. $
92  *
93  * @end{table}
94  */
95 
96 namespace {
97  // TODO: it would be better if we didnt have to parse the config every time.
98  bool str_up(const config* cfg, const std::string& prop_id, unsigned i1, unsigned i2)
99  {
100  return cfg->child("campaign", i1)[prop_id].str() < cfg->child("campaign", i2)[prop_id].str();
101  }
102  bool str_down(const config* cfg, const std::string& prop_id, unsigned i1, unsigned i2)
103  {
104  return cfg->child("campaign", i1)[prop_id].str() > cfg->child("campaign", i2)[prop_id].str();
105  }
106  bool num_up(const config* cfg, const std::string& prop_id, unsigned i1, unsigned i2)
107  {
108  return cfg->child("campaign", i1)[prop_id].to_int() < cfg->child("campaign", i2)[prop_id].to_int();
109  }
110  bool num_down(const config* cfg, const std::string& prop_id, unsigned i1, unsigned i2)
111  {
112  return cfg->child("campaign", i1)[prop_id].to_int() > cfg->child("campaign", i2)[prop_id].to_int();
113  }
114 
115  struct filter_transform
116  {
117  filter_transform(const std::vector<std::string>& filtertext) : filtertext_(filtertext) {}
118  bool operator()(const config& cfg) const
119  {
120  for(const auto& filter : filtertext_)
121  {
122  bool found = false;
123  for(const auto& attribute : cfg.attribute_range())
124  {
125  std::string val = attribute.second.str();
126  if(std::search(val.begin(),
127  val.end(),
128  filter.begin(),
129  filter.end(),
131  != val.end())
132  {
133  found = true;
134  break;
135  }
136  }
137  if(!found) {
138  return false;
139  }
140  }
141  return true;
142  }
143  const std::vector<std::string> filtertext_;
144  };
145 
146  /**
147  * Retrieves an element from the given associative container or dies in some
148  * way.
149  *
150  * It fails an @a assert() check or throws an exception if the requested element
151  * does not exist.
152  *
153  * @return An element from the container that is guranteed to have existed
154  * before running this function.
155  */
156  template <typename MapT>
157  typename MapT::mapped_type const& const_at(typename MapT::key_type const& key,
158  MapT const& map)
159  {
160  typename MapT::const_iterator it = map.find(key);
161  if(it == map.end()) {
162  assert(it != map.end());
163  throw std::out_of_range(
164  "const_at()"); // Shouldn't get here without disabling assert()
165  }
166  return it->second;
167  }
168 
169  inline const addon_info& addon_at(const std::string& id, const addons_list& addons)
170  {
171  addons_list::const_iterator it = addons.find(id);
172  assert(it != addons.end());
173  return it->second;
174  }
175 }
176 
177 REGISTER_DIALOG(addon_list)
178 
180  : orders_()
181  , cfg_(cfg)
182  , cfg_iterators_(cfg_.child_range("campaign"))
183  , addons_()
184  , tracking_info_()
185  , ids_()
186 {
187  read_addons_list(cfg, addons_);
188 }
189 
191 {
192  tlistbox& listbox = find_widget<tlistbox>(textbox->get_window(), "addons", true);
193  filter_transform filter(utils::split(text, ' '));
194  std::vector<bool> res;
195  res.reserve(cfg_.child_count("campaign"));
196  for(const auto& child : cfg_.child_range("campaign"))
197  {
198  res.push_back(filter(child));
199  }
200  listbox.set_row_shown(res);
201 }
202 
204 {
205  tselectable_& selectable = dynamic_cast<tselectable_&>(w);
206  for(auto& other : orders_)
207  {
208  if(other != &selectable) {
209  other->set_value(0);
210  }
211  }
212  tlistbox& listbox = find_widget<tlistbox>(&window, "addons", true);
213  switch(selectable.get_value())
214  {
215  case 0:
216  listbox.order_by(std::less<unsigned>());
217  break;
218  case 1:
219  listbox.order_by(up);
220  break;
221  case 2:
222  listbox.order_by(down);
223  break;
224  }
225 }
226 
228 {
229  tselectable_& selectable = find_widget<tselectable_>(&window, id, true);
230  orders_.push_back(&selectable);
231  selectable.set_callback_state_change(std::bind(&taddon_list::on_order_button_click, this, std::ref(window), up, down, _1));
232 }
233 
235 {
236  register_sort_button(window, id,
237  std::bind(&str_up, &cfg_, prop_id, _1, _2),
238  std::bind(&str_down, &cfg_, prop_id, _1, _2)
239  );
240 }
241 
243 {
244  register_sort_button(window, id,
245  std::bind(&num_up, &cfg_, prop_id, _1, _2),
246  std::bind(&num_down, &cfg_, prop_id, _1, _2)
247  );
248 }
249 
251  const addon_tracking_info& state, bool verbose = false)
252 {
253  std::string colorname = "";
254 
255  switch(state.state) {
256  case ADDON_NONE:
257  if(!verbose) {
258  return str;
259  }
260  colorname = "#a69275";
261  break;
262  case ADDON_INSTALLED:
263  case ADDON_NOT_TRACKED:
264  colorname = "#00ff00"; // GOOD_COLOR
265  break;
267  colorname = "#ffff00"; // YELLOW_COLOR/color_upgradable
268  break;
270  colorname = "#ff7f00"; // <255,127,0>/color_outdated
271  break;
273  colorname = "#ff0000"; // BAD_COLOR
274  break;
275  default:
276  colorname = "#777777"; // GRAY_COLOR
277  break;
278  }
279 
280  return "<span color='" + colorname + "'>" + str + "</span>";
281 }
282 
284 {
285  std::string tc, tx;
286 
287  switch(info.state) {
288  case ADDON_NONE:
289  tx = info.can_publish ? _("addon_state^Published, not installed") : _("addon_state^Not installed");
290  break;
291 
292  case ADDON_INSTALLED:
293  case ADDON_NOT_TRACKED:
294  // Consider add-ons without version information as installed
295  // for the main display. Their Description info should elaborate
296  // on their status.
297  tx = info.can_publish ? _("addon_state^Published") : _("addon_state^Installed");
298  break;
299 
301  tx = info.can_publish ? _("addon_state^Published, upgradable") : _("addon_state^Installed, upgradable");
302  break;
303 
305  tx = info.can_publish ? _("addon_state^Published, outdated on server") : _("addon_state^Installed, outdated on server");
306  break;
307 
309  tx = info.can_publish ? _("addon_state^Published, broken") : _("addon_state^Installed, broken");
310  break;
311 
312  default:
313  tx = _("addon_state^Unknown");
314  }
315 
316  return colorify_addon_state_string(tx, info, true);
317 }
318 
320 {
321  std::string s;
322 
323  utils::string_map i18n_symbols;
324  i18n_symbols["local_version"] = state.installed_version.str();
325 
326  switch(state.state) {
327  case ADDON_NONE:
328  if(!state.can_publish) {
329  s = _("addon_state^Not installed");
330  } else {
331  s = _("addon_state^Published, not installed");
332  }
333  break;
334  case ADDON_INSTALLED:
335  if(!state.can_publish) {
336  s = _("addon_state^Installed");
337  } else {
338  s = _("addon_state^Published");
339  }
340  break;
341  case ADDON_NOT_TRACKED:
342  if(!state.can_publish) {
343  s = _("addon_state^Installed, not tracking local version");
344  } else {
345  // Published add-ons often don't have local status information,
346  // hence untracked. This should be considered normal.
347  s = _("addon_state^Published, not tracking local version");
348  }
349  break;
351  const std::string vstr
352  = !state.can_publish
353  ? _("addon_state^Installed ($local_version|), "
354  "upgradable")
355  : _("addon_state^Published ($local_version| "
356  "installed), upgradable");
357  s = utils::interpolate_variables_into_string(vstr, &i18n_symbols);
358  } break;
360  const std::string vstr
361  = !state.can_publish
362  ? _("addon_state^Installed ($local_version|), "
363  "outdated on server")
364  : _("addon_state^Published ($local_version| "
365  "installed), outdated on server");
366  s = utils::interpolate_variables_into_string(vstr, &i18n_symbols);
367  } break;
369  if(!state.can_publish) {
370  s = _("addon_state^Installed, broken");
371  } else {
372  s = _("addon_state^Published, broken");
373  }
374  break;
375  default:
376  s = _("addon_state^Unknown");
377  }
378 
379  return colorify_addon_state_string(s, state);
380 }
381 
383 {
384  tlistbox& list = find_widget<tlistbox>(&window, "addons", false);
385 
386  for(const auto & c : cfg_.child_range("campaign"))
387  {
388  ids_.push_back(c["name"]);
389  const addon_info& info = addon_at(ids_.back(), addons_);
391 
392  std::map<std::string, string_map> data;
393  string_map item;
394 
395  item["label"] = info.display_icon();
396  data.insert(std::make_pair("icon", item));
397 
398  item["label"] = info.display_title();
399  data.insert(std::make_pair("name", item));
400 
401  item["label"] = describe_status_simple(tracking_info_[info.id]);
402  item["use_markup"] = "true";
403  data.insert(std::make_pair("installation_status", item));
404 
405  item["label"] = info.version.str();
406  data.insert(std::make_pair("version", item));
407 
408  item["label"] = info.author;
409  data.insert(std::make_pair("author", item));
410 
411  item["label"] = size_display_string(info.size);
412  data.insert(std::make_pair("size", item));
413 
414  item["label"] = std::to_string(info.downloads);
415  data.insert(std::make_pair("downloads", item));
416 
417  item["label"] = info.display_type();
418  data.insert(std::make_pair("type", item));
419 
420  list.add_row(data);
421 
422  tgrid* row_grid = list.get_row_grid(list.get_item_count() - 1);
423 
424  tstacked_widget& install_update_stack = find_widget<tstacked_widget>(row_grid, "install_update_stack", false);
425 
426  const bool is_updatable = tracking_info_[info.id].state == ADDON_INSTALLED_UPGRADABLE;
427  const bool is_installed = tracking_info_[info.id].state == ADDON_INSTALLED;
428 
429  install_update_stack.select_layer(is_updatable);
430 
431  if(!is_updatable) {
432  find_widget<tbutton>(row_grid, "single_install", false).set_active(!is_installed);
433  }
434 
435  find_widget<tbutton>(row_grid, "single_uninstall", false).set_active(is_installed);
436  }
437 
438  register_sort_button_alphabetical(window, "sort_name", "name");
439  register_sort_button_alphabetical(window, "sort_author", "author");
440  register_sort_button_alphabetical(window, "sort_type", "type");
441  register_sort_button_numeric(window, "sort_downloads", "downloads");
442  register_sort_button_numeric(window, "sort_size", "size");
443 
444  find_widget<ttext_box>(&window, "filter", false).set_text_changed_callback(
445  std::bind(&taddon_list::on_filtertext_changed, this, _1, _2));
446 
447 #ifdef GUI2_EXPERIMENTAL_LISTBOX
449  std::bind(&taddon_list::on_addon_select,
450  *this,
451  std::ref(window)));
452 #else
454  dialog_callback<taddon_list, &taddon_list::on_addon_select>);
455 #endif
456 
457  tbutton& url_go_button = find_widget<tbutton>(&window, "url_go", false);
458  tbutton& url_copy_button = find_widget<tbutton>(&window, "url_copy", false);
459  ttext_box& url_textbox = find_widget<ttext_box>(&window, "url", false);
460 
461  url_textbox.set_active(false);
462 
464  url_copy_button.set_active(false);
465  url_copy_button.set_tooltip(_("Clipboard support not found, contact your packager"));
466  }
467 
469  // No point in displaying the button on platforms that can't do
470  // open_object().
472  }
473 
475  url_go_button,
476  std::bind(&taddon_list::browse_url_callback, this, std::ref(url_textbox)));
477 
479  url_copy_button,
480  std::bind(&taddon_list::copy_url_callback, this, std::ref(url_textbox)));
481 
483  find_widget<tbutton>(&window, "options", false),
484  std::bind(&taddon_list::options_button_callback, this, std::ref(window)));
485 
487  find_widget<tbutton>(&window, "show_help", false),
488  std::bind(&taddon_list::show_help, this, std::ref(window)));
489 
490  on_addon_select(window);
491 }
492 
494 {
495  // TODO
496  //gui2::taddon_filter_options dlg;
497 
498  //dlg.set_displayed_status(f_.status);
499  //dlg.set_displayed_types(f_.types);
500  //dlg.set_sort(f_.sort);
501  //dlg.set_direction(f_.direction);
502 
503  //dlg.show(window.video());
504  UNUSED(window); // Remove this once the code works.
505 }
506 
508 {
509  help::show_help(window.video(), "installing_addons");
510 }
511 
513 {
514  /* TODO: ask for confirmation */
515 
516  desktop::open_object(url_box.get_value());
517 }
518 
520 {
522 }
523 
524 static std::string format_addon_time(time_t time)
525 {
526  if(time) {
527  char buf[1024] = { 0 };
528  struct std::tm* const t = std::localtime(&time);
529 
531  ? "%Y-%m-%d %I:%M %p"
532  : "%Y-%m-%d %H:%M";
533 
534  if(util::strftime(buf, sizeof(buf), format, t)) {
535  return buf;
536  }
537  }
538 
539  return utils::unicode_em_dash;
540 }
541 
543 {
544  const int index = find_widget<tlistbox>(&window, "addons", false).get_selected_row();
545 
546  if(index == -1) {
547  return;
548  }
549 
550  const addon_info& info = addon_at(ids_[index], addons_);
551 
552  find_widget<tdrawing>(&window, "image", false).set_label(info.display_icon());
553 
554  find_widget<tcontrol>(&window, "title", false).set_label(info.display_title());
555  find_widget<tcontrol>(&window, "description", false).set_label(info.description);
556  find_widget<tcontrol>(&window, "version", false).set_label(info.version.str());
557  find_widget<tcontrol>(&window, "author", false).set_label(info.author);
558  find_widget<tcontrol>(&window, "type", false).set_label(info.display_type());
559 
560  tcontrol& status = find_widget<tcontrol>(&window, "status", false);
562  status.set_use_markup(true);
563 
564  find_widget<tcontrol>(&window, "size", false).set_label(size_display_string(info.size));
565  find_widget<tcontrol>(&window, "downloads", false).set_label(std::to_string(info.downloads));
566  find_widget<tcontrol>(&window, "created", false).set_label(format_addon_time(info.created));
567  find_widget<tcontrol>(&window, "updated", false).set_label(format_addon_time(info.updated));
568 
569  const std::string& feedback_url = info.feedback_url;
570 
571  if(!feedback_url.empty()) {
572  find_widget<tstacked_widget>(&window, "feedback_stack", false).select_layer(1);
573  find_widget<ttext_box>(&window, "url", false).set_value(feedback_url);
574  } else {
575  find_widget<tstacked_widget>(&window, "feedback_stack", false).select_layer(0);
576  }
577 
578  find_widget<tbutton>(&window, "uninstall", false).set_active(tracking_info_[info.id].state == ADDON_INSTALLED);
579 }
580 
581 } // namespace gui2
int size
Definition: info.hpp:41
child_itors child_range(const std::string &key)
Definition: config.cpp:613
size_t strftime(char *str, size_t count, const std::string &format, const std::tm *time)
Definition: strftime.cpp:132
static std::string describe_status_simple(const addon_tracking_info &info)
Definition: list.cpp:283
ADDON_STATUS state
Definition: state.hpp:55
void show_help(CVideo &video, const std::string &show_topic, int xloc, int yloc)
Open the help browser, show topic with id show_topic.
Definition: help.cpp:117
void register_sort_button_alphabetical(twindow &window, const std::string &id, const std::string &prop_id)
Definition: list.cpp:234
std::string interpolate_variables_into_string(const std::string &str, const string_map *const symbols)
Function which will interpolate variables, starting with '$' in the string 'str' with the equivalent ...
void read_addons_list(const config &cfg, addons_list &dest)
Definition: info.cpp:199
void set_row_shown(const unsigned row, const bool shown)
Makes a row visible or invisible.
Definition: listbox.cpp:150
void options_button_callback(twindow &window)
Definition: list.cpp:493
virtual void set_callback_state_change(std::function< void(twidget &)> callback)=0
When the user does something to change the widget state this event is fired.
virtual unsigned get_value() const =0
Is the control selected?
bool available()
Whether wesnoth was compiled with support for a clipboard.
Definition: clipboard.cpp:61
virtual void set_active(const bool active) override
See tcontrol::set_active.
Definition: text.cpp:56
const GLfloat * c
Definition: glew.h:12741
CVideo & video()
Definition: window.hpp:411
logger & info()
Definition: log.cpp:91
std::string size_display_string(double size)
Get a human-readable representation of the specified byte count.
Definition: info.cpp:219
void connect_signal_notify_modified(tdispatcher &dispatcher, const tsignal_notification_function &signal)
Connects a signal handler for getting a notification upon modification.
Definition: dispatcher.hpp:725
Base container class.
Definition: grid.hpp:29
void register_sort_button(twindow &window, const std::string &id, const tgenerator_::torder_func &up, const tgenerator_::torder_func &down)
Definition: list.cpp:227
This file contains the window object, this object is a top level container which has the event manage...
REGISTER_DIALOG(label_settings)
std::string description
Definition: info.hpp:33
virtual void set_label(const t_string &label)
Definition: control.cpp:330
GLuint const GLfloat * val
Definition: glew.h:2614
void select_layer(const int layer)
Selects and displays a particular layer.
void connect_signal_mouse_left_click(tdispatcher &dispatcher, const tsignal_function &signal)
Connects a signal handler for a left mouse button click.
Definition: dispatcher.hpp:710
Class for a single line text area.
Definition: text_box.hpp:118
void on_addon_select(twindow &window)
Definition: list.cpp:542
std::string feedback_url
Definition: info.hpp:54
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
Definition: glew.h:1347
void browse_url_callback(ttext_box &url_box)
Definition: list.cpp:512
GLdouble GLdouble t
Definition: glew.h:1366
addons_list addons_
Definition: list.hpp:65
-file util.hpp
Definitions for the interface to Wesnoth Markup Language (WML).
Define the common filters for the gui2::tpane class.
time_t created
Definition: info.hpp:57
std::string get_value() const
Definition: text.hpp:76
std::function< bool(unsigned, unsigned)> torder_func
Definition: generator.hpp:239
version_info installed_version
Definition: state.hpp:58
No tracking information available.
Definition: state.hpp:35
void register_sort_button_numeric(twindow &window, const std::string &id, const std::string &prop_id)
Definition: list.cpp:242
Add-on is not installed.
Definition: state.hpp:24
virtual void set_value(const unsigned)=0
Select the control.
base class of top level items, the only item which needs to store the final canvases to draw on ...
Definition: window.hpp:62
void show_help(twindow &window)
Definition: list.cpp:507
A class inherited from ttext_box that displays its input as stars.
Definition: field-fwd.hpp:23
Simple push button.
Definition: button.hpp:32
The user set the widget invisible, that means:
Definition: widget.hpp:103
Desktop environment interaction functions.
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:82
Version in the server is older than local installation.
Definition: state.hpp:30
bool chars_equal_insensitive(char a, char b)
Definition: util.hpp:206
std::map< std::string, t_string > string_map
void on_order_button_click(twindow &window, const tgenerator_::torder_func &up, const tgenerator_::torder_func &down, twidget &w)
Definition: list.cpp:203
This file contains the settings handling of the widget library.
void order_by(const tgenerator_::torder_func &func)
Definition: listbox.cpp:588
unsigned get_item_count() const
Returns the number of items in the listbox.
Definition: listbox.cpp:138
void pre_show(twindow &window)
Inherited from tdialog.
Definition: list.cpp:382
void add_row(const string_map &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:74
std::string display_title() const
Get a title or automatic title for display.
Definition: info.cpp:124
std::map< std::string, addon_info > addons_list
Definition: info.hpp:26
GLubyte GLubyte GLubyte GLubyte w
Definition: glew.h:1858
void copy_url_callback(ttext_box &url_box)
Definition: list.cpp:519
std::string id
Definition: info.hpp:31
Version in the server is newer than local installation.
Definition: state.hpp:28
const config & cfg_
Config which contains the list with the campaigns.
Definition: list.hpp:58
GLenum GLuint GLsizei const char * buf
Definition: glew.h:2498
const std::string unicode_em_dash
static size_t id
Ids for the timers.
Definition: timer.cpp:39
Dependencies not satisfied.
Definition: state.hpp:33
std::map< std::string, t_string > string_map
Definition: generator.hpp:23
std::string str() const
Serializes the version number into string form.
Definition: version.cpp:90
Small abstract helper class.
Definition: selectable.hpp:32
std::string display_icon() const
Get an icon path fixed for display (e.g.
Definition: info.cpp:133
bool open_object(const std::string &path_or_url)
Opens the specified object with the default application configured for its type.
Definition: open.cpp:53
#define UNUSED(x)
Definition: global.hpp:56
GLuint res
Definition: glew.h:9258
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: glew.h:1222
static std::string colorify_addon_state_string(const std::string &str, const addon_tracking_info &state, bool verbose=false)
Definition: list.cpp:250
std::string display_type() const
Get an add-on type identifier for display in the user's language.
Definition: info.cpp:154
const_attr_itors attribute_range() const
Definition: config.cpp:984
GLuint index
Definition: glew.h:1782
The listbox class.
Definition: listbox.hpp:39
std::vector< tselectable_ * > orders_
Definition: list.hpp:48
unsigned child_count(const std::string &key) const
Definition: config.cpp:635
addons_tracking_list tracking_info_
Definition: list.hpp:67
Base class for all visible items.
Definition: control.hpp:34
const GLfloat * tc
Definition: glew.h:12749
static std::string describe_status_verbose(const addon_tracking_info &state)
Definition: list.cpp:319
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glew.h:3448
bool open_object_is_supported()
Returns whether open_object() is supported/implemented for the current platform.
Definition: open.cpp:44
void copy_to_clipboard(const std::string &text, const bool)
Copies text to the clipboard.
Definition: clipboard.cpp:40
GLenum GLint ref
Definition: glew.h:1813
void on_filtertext_changed(ttext_ *textbox, const std::string &text)
Definition: list.cpp:190
addon_tracking_info get_addon_tracking_info(const addon_info &addon)
Get information about an add-on comparing its local state with the add-ons server entry...
Definition: state.cpp:26
std::vector< std::string > ids_
Definition: list.hpp:69
config & child(const std::string &key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:658
Base class for all widgets.
Definition: widget.hpp:49
Shows the list of addons on the server.
Definition: list.hpp:35
void set_callback_value_change(const std::function< void(twidget &)> &callback)
Definition: listbox.hpp:225
static std::string format_addon_time(time_t time)
Definition: list.cpp:524
version_info version
Definition: info.hpp:37
static void set_label(twindow &window, const std::string &id, const std::string &label)
Definition: unit_attack.cpp:89
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
Stores additional status information about add-ons.
Definition: state.hpp:44
const std::vector< std::string > filtertext_
Definition: list.cpp:143
int downloads
Definition: info.hpp:42
twindow * get_window()
Get the parent window.
Definition: widget.cpp:116
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
GLdouble s
Definition: glew.h:1358
void set_visible(const tvisible::scoped_enum visible)
Definition: widget.cpp:445
GLsizei const GLcharARB ** string
Definition: glew.h:4503
bool use_twelve_hour_clock_format()
Abstract base class for text items.
Definition: text.hpp:43
std::string author
Definition: info.hpp:39
const tgrid * get_row_grid(const unsigned row) const
Returns the grid of the wanted row.
Definition: listbox.cpp:215
Version in the server matches local installation.
Definition: state.hpp:26
time_t updated
Definition: info.hpp:56