The Battle for Wesnoth  1.17.0-dev
depcheck.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2012 - 2018 by Boldizs√°r Lipka <lipkab@zoho.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 
16 
17 #include <algorithm>
18 
20 #include "gettext.hpp"
21 #include "log.hpp"
22 #include "utils/general.hpp"
23 
26 #include "gui/dialogs/message.hpp"
27 #include "game_config_view.hpp"
28 
29 static lg::log_domain log_mp_create_depcheck("mp/create/depcheck");
30 #define DBG_MP LOG_STREAM(debug, log_mp_create_depcheck)
31 
32 namespace
33 {
34 // helper function
35 void copy_keys(config& out, const config& in, const std::string& type, bool copy_force_key = false)
36 {
37  if(in.has_attribute("allow_" + type)) {
38  out["allow_" + type] = in["allow_" + type];
39  } else if(in.has_attribute("disallow_" + type)) {
40  out["disallow_" + type] = in["disallow_" + type];
41  }
42 
43  if(in.has_attribute("ignore_incompatible_" + type)) {
44  out["ignore_incompatible_" + type] = in["ignore_incompatible_" + type];
45  }
46 
47  if(copy_force_key) {
48  if(in.has_attribute("force_" + type)) {
49  out["force_" + type] = in["force_" + type];
50  }
51  }
52 }
53 } // anonymous namespace
54 
55 namespace ng
56 {
57 namespace depcheck
58 {
59 manager::manager(const game_config_view& gamecfg, bool mp)
60  : depinfo_()
61  , era_()
62  , scenario_()
63  , mods_()
64  , prev_era_()
65  , prev_scenario_()
66  , prev_mods_()
67 {
68  DBG_MP << "Initializing the dependency manager" << std::endl;
69 
70  for(const config& cfg : gamecfg.child_range("modification")) {
71  component_availability type = cfg["type"].to_enum<component_availability>(component_availability::HYBRID);
72 
73  if((type != component_availability::MP || mp) && (type != component_availability::SP || !mp)) {
74  config info;
75  info["id"] = cfg["id"];
76  info["name"] = cfg["name"];
77 
78  copy_keys(info, cfg, "scenario");
79  copy_keys(info, cfg, "era");
80  copy_keys(info, cfg, "modification");
81 
82  depinfo_.add_child("modification", std::move(info));
83  }
84  }
85 
86  for(const config& cfg : gamecfg.child_range("era")) {
87  component_availability type = cfg["type"].to_enum<component_availability>(component_availability::MP);
88 
89  if((type != component_availability::MP || mp) && (type != component_availability::SP || !mp)) {
90  config info;
91  info["id"] = cfg["id"];
92  info["name"] = cfg["name"];
93 
94  copy_keys(info, cfg, "scenario");
95  copy_keys(info, cfg, "modification", true);
96 
97  depinfo_.add_child("era", std::move(info));
98  }
99  }
100 
101  for(const config& cfg : gamecfg.child_range("multiplayer")) {
102  if(cfg["allow_new_game"].to_bool(true)) {
103  config info;
104  info["id"] = cfg["id"];
105  info["name"] = cfg["name"];
106 
107  copy_keys(info, cfg, "era");
108  copy_keys(info, cfg, "modification", true);
109 
110  depinfo_.add_child("scenario", std::move(info));
111  }
112  }
113 
114  for(const config& cfg : gamecfg.child_range("campaign")) {
115  config info;
116  info["id"] = cfg["id"];
117  info["name"] = cfg["name"];
118  info["allow_era_choice"] = cfg["allow_era_choice"];
119 
120  copy_keys(info, cfg, "era");
121  copy_keys(info, cfg, "modification", true);
122 
123  depinfo_.add_child("scenario", std::move(info));
124  }
125 }
126 
128 {
129  DBG_MP << "Saving current state" << std::endl;
130  prev_era_ = era_;
132  prev_mods_ = mods_;
133 }
134 
136 {
137  DBG_MP << "Restoring previous state" << std::endl;
138  era_ = prev_era_;
140  mods_ = prev_mods_;
141 }
142 
143 bool manager::exists(const elem& e) const
144 {
145  for(const config& cfg : depinfo_.child_range(e.type)) {
146  if(cfg["id"] == e.id) {
147  return true;
148  }
149  }
150 
151  return false;
152 }
153 
154 std::string manager::find_name_for(const elem& e) const
155 {
156  const config& cfg = depinfo_.find_child(e.type, "id", e.id);
157  return cfg["name"];
158 }
159 
160 std::vector<std::string> manager::get_required_not_installed(const elem& e) const
161 {
162  std::vector<std::string> result;
163 
164  std::vector<std::string> items = get_required(e);
165 
166  for(const std::string& str : items) {
167  if(!exists(elem(str, "modification"))) {
168  result.push_back(str);
169  }
170  }
171 
172  return result;
173 }
174 
175 std::vector<std::string> manager::get_required(const elem& e) const
176 {
177  std::vector<std::string> result;
178 
179  if(e.type == "modification") {
180  return result;
181  }
182 
183  config data = depinfo_.find_child(e.type, "id", e.id);
184 
185  if(data.has_attribute("force_modification")) {
186  result = utils::split(data["force_modification"].str(), ',');
187  }
188 
189  return result;
190 }
191 
192 std::vector<std::string> manager::get_required_not_enabled(const elem& e) const
193 {
194  std::vector<std::string> required = get_required(e);
195  std::vector<std::string> result;
196 
197  for(std::string str : required) {
198  if(!utils::contains(mods_, str)) {
199  result.push_back(str);
200  }
201  }
202 
203  return result;
204 }
205 
206 std::vector<std::string> manager::get_conflicting_enabled(const elem& e) const
207 {
208  std::vector<std::string> result;
209 
210  for(const std::string& mod : mods_) {
211  if(does_conflict(elem(mod, "modification"), e)) {
212  result.push_back(mod);
213  }
214  }
215 
216  return result;
217 }
218 
219 bool manager::does_conflict(const elem& elem1, const elem& elem2, bool directonly) const
220 {
221  if(elem1 == elem2) {
222  return false;
223  }
224 
225  // We ignore nonexistent elements at this point, they will generate
226  // errors in change_era()/change_scenario() anyways.
227  if(!exists(elem1) || !exists(elem2)) {
228  return false;
229  }
230 
231  config data1 = depinfo_.find_child(elem1.type, "id", elem1.id);
232  config data2 = depinfo_.find_child(elem2.type, "id", elem2.id);
233 
234  // Whether we should skip the check entirely
235  if(data1.has_attribute("ignore_incompatible_" + elem2.type)) {
236  std::vector<std::string> ignored = utils::split(data1["ignore_incompatible_" + elem2.type]);
237 
238  if(utils::contains(ignored, elem2.id)) {
239  return false;
240  }
241  }
242 
243  if(data2.has_attribute("ignore_incompatible_" + elem1.type)) {
244  std::vector<std::string> ignored = utils::split(data2["ignore_incompatible_" + elem1.type]);
245 
246  if(utils::contains(ignored, elem1.id)) {
247  return false;
248  }
249  }
250 
251  if((elem1.type == "era" && data2["allow_era_choice"].to_bool(false)) ||(elem2.type == "era" && data1["allow_era_choice"].to_bool(false))) {
252  return false;
253  }
254 
255  bool result = false;
256 
257  // Checking for direct conflicts between elem1 and elem2
258  if(data1.has_attribute("allow_" + elem2.type)) {
259  std::vector<std::string> allowed = utils::split(data1["allow_" + elem2.type]);
260 
261  result = !utils::contains(allowed, elem2.id) && !does_require(elem1, elem2);
262  } else if(data1.has_attribute("disallow_" + elem2.type)) {
263  std::vector<std::string> disallowed = utils::split(data1["disallow_" + elem2.type]);
264 
265  result = utils::contains(disallowed, elem2.id);
266  }
267 
268  if(data2.has_attribute("allow_" + elem1.type)) {
269  std::vector<std::string> allowed = utils::split(data2["allow_" + elem1.type]);
270 
271  result = result || (!utils::contains(allowed, elem1.id) && !does_require(elem2, elem1));
272  } else if(data2.has_attribute("disallow_" + elem1.type)) {
273  std::vector<std::string> disallowed = utils::split(data2["disallow_" + elem1.type]);
274 
275  result = result || utils::contains(disallowed, elem1.id);
276  }
277 
278  if(result) {
279  return true;
280  }
281 
282  // Checking for indirect conflicts (i.e. conflicts between dependencies)
283  if(!directonly) {
284  std::vector<std::string> req1 = get_required(elem1), req2 = get_required(elem2);
285 
286  for(const std::string& s : req1) {
287  elem m(s, "modification");
288 
289  if(does_conflict(elem2, m, true)) {
290  return true;
291  }
292  }
293 
294  for(const std::string& s : req2) {
295  elem m(s, "modification");
296 
297  if(does_conflict(elem1, m, true)) {
298  return true;
299  }
300  }
301 
302  for(const std::string& id1 : req1) {
303  elem m1(id1, "modification");
304 
305  for(const std::string& id2 : req2) {
306  elem m2(id2, "modification");
307 
308  if(does_conflict(m1, m2)) {
309  return true;
310  }
311  }
312  }
313  }
314 
315  return false;
316 }
317 
318 bool manager::does_require(const elem& elem1, const elem& elem2) const
319 {
320  if(elem2.type != "modification") {
321  return false;
322  }
323 
324  config data = depinfo_.find_child(elem1.type, "id", elem1.id);
325 
326  if(data.has_attribute("force_modification")) {
327  std::vector<std::string> required = utils::split(data["force_modification"]);
328 
329  return utils::contains(required, elem2.id);
330  }
331 
332  return false;
333 }
334 
335 void manager::try_era(const std::string& id, bool force)
336 {
337  save_state();
338 
339  if(force) {
340  era_ = id;
341  } else if(!change_era(id)) {
342  revert();
343  }
344 }
345 
346 void manager::try_scenario(const std::string& id, bool force)
347 {
348  save_state();
349 
350  if(force) {
351  scenario_ = id;
352  } else if(!change_scenario(id)) {
353  revert();
354  }
355 }
356 
357 void manager::try_modifications(const std::vector<std::string>& ids, bool force)
358 {
359  save_state();
360 
361  if(force) {
362  mods_ = ids;
363  } else if(!change_modifications(ids)) {
364  revert();
365  }
366 }
367 
368 void manager::try_modification_by_index(int index, bool activate, bool force)
369 {
370  std::string id = depinfo_.child("modification", index)["id"];
371  std::vector<std::string> mods_copy = mods_;
372 
373  if(activate) {
374  if(std::find(mods_copy.begin(), mods_copy.end(), id) == mods_copy.end()) {
375  mods_copy.push_back(id);
376  }
377  } else {
378  std::vector<std::string>::iterator pos = std::find(mods_copy.begin(), mods_copy.end(), id);
379  if(pos != mods_copy.end()) {
380  mods_copy.erase(pos);
381  }
382  }
383 
384  try_modifications(mods_copy, force);
385 }
386 
387 void manager::try_era_by_index(int index, bool force)
388 {
389  try_era(depinfo_.child("era", index)["id"], force);
390 }
391 
393 {
394  try_scenario(depinfo_.child("scenario", index)["id"], force);
395 }
396 
398 {
399  int result = 0;
400  for(const config& i : depinfo_.child_range("era")) {
401  if(i["id"] == era_) {
402  return result;
403  }
404 
405  result++;
406  }
407 
408  return -1;
409 }
410 
412 {
413  int result = 0;
414 
415  for(const config& i : depinfo_.child_range("scenario")) {
416  if(i["id"] == scenario_) {
417  return result;
418  }
419 
420  result++;
421  }
422 
423  return -1;
424 }
425 
427 {
428  std::string id = depinfo_.child("modification", index)["id"];
429  return std::find(mods_.begin(), mods_.end(), id) != mods_.end();
430 }
431 
432 bool manager::is_modification_active(const std::string id) const
433 {
434  return std::find(mods_.begin(), mods_.end(), id) != mods_.end();
435 }
436 
437 bool manager::enable_mods_dialog(const std::vector<std::string>& mods, const std::string& requester)
438 {
439  std::vector<std::string> items;
440  for(const std::string& mod : mods) {
441  items.push_back(depinfo_.find_child("modification", "id", mod)["name"]);
442  }
443 
444  return gui2::dialogs::depcheck_confirm_change::execute(true, items, requester);
445 }
446 
447 bool manager::disable_mods_dialog(const std::vector<std::string>& mods, const std::string& requester)
448 {
449  std::vector<std::string> items;
450  for(const std::string& mod : mods) {
451  items.push_back(depinfo_.find_child("modification", "id", mod)["name"]);
452  }
453 
454  return gui2::dialogs::depcheck_confirm_change::execute(false, items, requester);
455 }
456 
457 std::string manager::change_era_dialog(const std::vector<std::string>& eras)
458 {
459  std::vector<std::string> items;
460  for(const std::string& era : eras) {
461  items.push_back(depinfo_.find_child("era", "id", era)["name"]);
462  }
463 
465 
466  if(dialog.show()) {
467  return eras[dialog.result()];
468  }
469 
470  return "";
471 }
472 
473 std::string manager::change_scenario_dialog(const std::vector<std::string>& scenarios)
474 {
475  std::vector<std::string> items;
476  for(const std::string& scenario : scenarios) {
477  items.push_back(depinfo_.find_child("scenario", "id", scenario)["name"]);
478  }
479 
481  if(dialog.show()) {
482  return scenarios[dialog.result()];
483  }
484 
485  return "";
486 }
487 
488 void manager::failure_dialog(const std::string& msg)
489 {
490  gui2::show_message(_("Failed to resolve dependencies"), msg, _("OK"));
491 }
492 
494 {
495  std::string type_str;
496 
497  switch(type) {
498  case ERA:
499  type_str = "era";
500  break;
501  case SCENARIO:
502  type_str = "scenario";
503  break;
504  case MODIFICATION:
505  type_str = "modification";
506  }
507 
508  depinfo_.add_child_at(type_str, data, index);
509 }
510 
511 bool manager::change_scenario(const std::string& id)
512 {
513  // Checking for missing dependencies
514  if(!get_required_not_installed(elem(id, "scenario")).empty()) {
515  std::string msg = _("Scenario can't be activated. Some dependencies are missing: ");
516 
517  msg += utils::join(get_required_not_installed(elem(id, "scenario")), ", ");
518 
519  failure_dialog(msg);
520  return false;
521  }
522 
523  scenario_ = id;
524 
525  elem scen = elem(id, "scenario");
526  std::string scen_name = find_name_for(scen);
527 
528  // Firstly, we check if we have to enable/disable any mods
529  std::vector<std::string> req = get_required_not_enabled(scen);
530  std::vector<std::string> con = get_conflicting_enabled(scen);
531 
532  if(!req.empty()) {
533  if(!enable_mods_dialog(req, scen_name)) {
534  return false;
535  }
536  }
537 
538  if(!con.empty()) {
539  if(!disable_mods_dialog(con, scen_name)) {
540  return false;
541  }
542  }
543 
544  std::vector<std::string> newmods = req;
545  for(const std::string& i : mods_) {
546  if(!utils::contains(con, i)) {
547  newmods.push_back(i);
548  }
549  }
550 
551  mods_ = newmods;
552 
553  // Now checking if the currently selected era conflicts the scenario
554  // and changing era if necessary
555  if(!does_conflict(scen, elem(era_, "era"))) {
556  return true;
557  }
558 
559  std::vector<std::string> compatible;
560  for(const config& i : depinfo_.child_range("era")) {
561  if(!does_conflict(scen, elem(i["id"], "era"))) {
562  compatible.push_back(i["id"]);
563  }
564  }
565 
566  if(!compatible.empty()) {
567  era_ = change_era_dialog(compatible);
568  } else {
569  failure_dialog(_("No compatible eras found."));
570  return false;
571  }
572 
573  if(era_.empty()) {
574  return false;
575  }
576 
577  return change_era(era_);
578 }
579 
580 bool manager::change_era(const std::string& id)
581 {
582  // Checking for missing dependencies
583  if(!get_required_not_installed(elem(id, "era")).empty()) {
584  std::string msg = _("Era can't be activated. Some dependencies are missing: ");
585 
586  msg += utils::join(get_required_not_installed(elem(id, "era")), ", ");
587  failure_dialog(msg);
588  return false;
589  }
590 
591  era_ = id;
592 
593  elem era = elem(id, "era");
594  std::string era_name = find_name_for(era);
595 
596  std::vector<std::string> req = get_required_not_enabled(era);
597  std::vector<std::string> con = get_conflicting_enabled(era);
598 
599  // Firstly, we check if we have to enable/disable any mods
600  if(!req.empty()) {
601  if(!enable_mods_dialog(req, era_name)) {
602  return false;
603  }
604  }
605 
606  if(!con.empty()) {
607  if(!disable_mods_dialog(con, era_name)) {
608  return false;
609  }
610  }
611 
612  std::vector<std::string> newmods = req;
613  for(const std::string& i : mods_) {
614  if(!utils::contains(con, i)) {
615  newmods.push_back(i);
616  }
617  }
618 
619  mods_ = newmods;
620 
621  // Now checking if the currently selected scenario conflicts the era
622  // and changing scenario if necessary
623  if(!does_conflict(era, elem(scenario_, "scenario"))) {
624  return true;
625  }
626 
627  std::vector<std::string> compatible;
628  for(const config& i : depinfo_.child_range("scenario")) {
629  if(!does_conflict(era, elem(i["id"], "scenario"))) {
630  compatible.push_back(i["id"]);
631  }
632  }
633 
634  if(!compatible.empty()) {
635  scenario_ = change_scenario_dialog(compatible);
636  } else {
637  failure_dialog(_("No compatible scenarios found."));
638  return false;
639  }
640 
641  if(scenario_.empty()) {
642  return false;
643  }
644 
645  return change_scenario(scenario_);
646 }
647 
648 bool manager::change_modifications(const std::vector<std::string>& modifications)
649 {
650  // Checking if the selected combination of mods is valid at all
651  std::vector<std::string> filtered;
652  for(const std::string& i : modifications) {
653  bool ok = true;
654  elem ei(i, "modification");
655 
656  for(const std::string& j : filtered) {
657  ok = ok && !does_conflict(ei, elem(j, "modification"));
658  }
659 
660  if(ok) {
661  filtered.push_back(i);
662  }
663  }
664 
665  if(filtered.size() != modifications.size()) {
666  failure_dialog(_("Not all of the chosen modifications are compatible."
667  " Some of them will be disabled."));
668  }
669 
670  mods_ = filtered;
671 
672  // Checking if the currently selected era is compatible with the set
673  // modifications, and changing era if necessary
674  std::vector<std::string> compatible;
675  for(const config& c : depinfo_.child_range("era")) {
676  elem era(c["id"], "era");
677  bool ok = true;
678 
679  for(const std::string& s : mods_) {
680  ok = ok && !does_conflict(era, elem(s, "modification"));
681  }
682 
683  if(ok) {
684  compatible.push_back(era.id);
685  }
686  }
687 
688  if(!utils::contains(compatible, era_)) {
689  if(!compatible.empty()) {
690  era_ = change_era_dialog(compatible);
691  } else {
692  failure_dialog(_("No compatible eras found."));
693  return false;
694  }
695 
696  if(era_.empty()) {
697  return false;
698  }
699 
700  if(!change_era(era_)) {
701  return false;
702  }
703  } else {
704  if(!change_era(era_)) {
705  return false;
706  }
707  }
708 
709  compatible.clear();
710 
711  // Checking if the currently selected scenario is compatible with
712  // the set modifications, and changing scenario if necessary
713  for(const config& c : depinfo_.child_range("scenario")) {
714  elem scen(c["id"], "scenario");
715  bool ok = true;
716  for(const std::string& s : mods_) {
717  ok = ok && !does_conflict(scen, elem(s, "modification"));
718  }
719 
720  if(ok) {
721  compatible.push_back(scen.id);
722  }
723  }
724 
725  if(!utils::contains(compatible, scenario_)) {
726  if(!compatible.empty()) {
727  scenario_ = change_scenario_dialog(compatible);
728  } else {
729  failure_dialog(_("No compatible scenarios found."));
730  return false;
731  }
732 
733  if(scenario_.empty()) {
734  return false;
735  }
736 
737  return change_scenario(scenario_);
738  } else {
739  if(!change_scenario(scenario_)) {
740  return false;
741  }
742  }
743 
744  return true;
745 }
746 
747 } // namespace depcheck
748 
749 } // namespace ng
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:152
config & child(config_key_type 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:418
std::string era()
Definition: game.cpp:694
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
int get_era_index() const
Returns the selected era.
Definition: depcheck.cpp:397
void revert()
restores the lastly saved values of era_, scenarios_ and mods_
Definition: depcheck.cpp:135
config & find_child(config_key_type key, const std::string &name, const std::string &value)
Returns the first child of tag key with a name attribute containing value.
Definition: config.cpp:865
std::string change_scenario_dialog(const std::vector< std::string > &scenarios)
Display a dialog requesting the user to select a new scenario.
Definition: depcheck.cpp:473
void save_state()
saves the current values of era_, scenarios_ and mods_
Definition: depcheck.cpp:127
bool has_attribute(config_key_type key) const
Definition: config.cpp:210
logger & info()
Definition: log.cpp:88
config_array_view child_range(config_key_type key) const
bool change_modifications(const std::vector< std::string > &modifications)
Attempts to change the selected modifications.
Definition: depcheck.cpp:648
child_itors child_range(config_key_type key)
Definition: config.cpp:360
#define DBG_MP
Definition: depcheck.cpp:30
std::string change_era_dialog(const std::vector< std::string > &eras)
Display a dialog requesting the user to select a new era.
Definition: depcheck.cpp:457
void try_era(const std::string &id, bool force=false)
Tries to set the selected era.
Definition: depcheck.cpp:335
bool is_modification_active(int index) const
Tells whether a certain mod is activated.
Definition: depcheck.cpp:426
bool enable_mods_dialog(const std::vector< std::string > &mods, const std::string &requester=_("A component"))
Display a dialog requesting confirmation for enabling some modifications.
Definition: depcheck.cpp:437
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
std::vector< std::string > get_required_not_installed(const elem &e) const
Get the list of modifications which are required by a certain component, but currently unavailable on...
Definition: depcheck.cpp:160
const std::vector< std::string > items
void try_scenario_by_index(int index, bool force=false)
Tries to set the selected scenario.
Definition: depcheck.cpp:392
static std::string _(const char *str)
Definition: gettext.hpp:92
bool show(const unsigned auto_close_time=0)
Shows the window.
std::string find_name_for(const elem &e) const
Look up the name of a given component.
Definition: depcheck.cpp:154
std::vector< std::string > get_conflicting_enabled(const elem &e) const
Get the list of modifications which are conflicting a certain component and are currently enabled...
Definition: depcheck.cpp:206
void try_era_by_index(int index, bool force=false)
Tries to set the selected era.
Definition: depcheck.cpp:387
std::vector< std::string > get_required(const elem &e) const
Get the list of modifications required by a certain component.
Definition: depcheck.cpp:175
std::string scenario_
the id of the currently selected scenario
Definition: depcheck.hpp:197
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
Definition: general.hpp:75
Main entry points of multiplayer mode.
Definition: lobby_data.cpp:51
unsigned in
If equal to search_counter, the node is off the list.
bool does_require(const elem &elem1, const elem &elem2) const
Decides whether e1 requires e2.
Definition: depcheck.cpp:318
config & add_child_at(config_key_type key, const config &val, unsigned index)
Definition: config.cpp:536
static lg::log_domain log_mp_create_depcheck("mp/create/depcheck")
bool change_era(const std::string &id)
Attempts to change the selected era.
Definition: depcheck.cpp:580
std::vector< std::string > mods_
the ids of the currently selected modifications
Definition: depcheck.hpp:200
bool exists(const elem &e) const
Decides whether a certain component is installed or not.
Definition: depcheck.cpp:143
void try_modification_by_index(int index, bool activate, bool force=false)
Tries to enable/disable a specific modification.
Definition: depcheck.cpp:368
void insert_element(component_type type, const config &data, int index=0)
Adds a new element to the manager&#39;s database.
Definition: depcheck.cpp:493
bool disable_mods_dialog(const std::vector< std::string > &mods, const std::string &requester=_("A component"))
Display a dialog requesting confirmation for disabling some modifications.
Definition: depcheck.cpp:447
bool change_scenario(const std::string &id)
Attempts to change the selected scenario.
Definition: depcheck.cpp:511
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:214
int result() const
Returns the selected item.
std::size_t i
Definition: function.cpp:940
bool does_conflict(const elem &elem1, const elem &elem2, bool directonly=false) const
Decides if two components are conflicting or not.
Definition: depcheck.cpp:219
Offers a list of compatible items if a currently selected one is incompatible.
void try_modifications(const std::vector< std::string > &ids, bool force=false)
Tries to set the enabled modifications.
Definition: depcheck.cpp:357
void failure_dialog(const std::string &msg)
Shows an error message.
Definition: depcheck.cpp:488
static map_location::DIRECTION s
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:71
config & add_child(config_key_type key)
Definition: config.cpp:504
const std::vector< std::string > & modifications(bool mp)
Definition: game.cpp:724
std::vector< std::string > split(const config_attribute_value &val)
void try_scenario(const std::string &id, bool force=false)
Tries to set the selected scenario.
Definition: depcheck.cpp:346
Standard logging facilities (interface).
std::string prev_scenario_
used by save_state() and revert() to backup/restore scenario_
Definition: depcheck.hpp:206
#define e
manager(const game_config_view &gamecfg, bool mp)
Definition: depcheck.cpp:59
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
mock_char c
config depinfo_
holds all required info about the components and their dependencies
Definition: depcheck.hpp:191
std::vector< std::string > get_required_not_enabled(const elem &e) const
Get the list of modifications which are required by a certain component, but aren&#39;t currently enabled...
Definition: depcheck.cpp:192
std::vector< std::string > prev_mods_
used by save_state() and revert() to backup/restore mods_
Definition: depcheck.hpp:209
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
std::string era_
the id of the currently selected era
Definition: depcheck.hpp:194
std::string prev_era_
used by save_state() and revert() to backup/restore era_
Definition: depcheck.hpp:203
represents a component (era, modification or scenario)
Definition: depcheck.hpp:175
int get_scenario_index() const
Returns the selected scenario.
Definition: depcheck.cpp:411