1 /*
2    Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
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 #include "about.hpp"
16 
17 #include "config.hpp"
18 #include "gettext.hpp"
19 #include "serialization/string_utils.hpp"
20 
21 #include <map>
22 
23 /**
24  * @namespace about
25  * Display credits %about all contributors.
26  */
27 namespace about
28 {
29 namespace
30 {
31 credits_data parsed_credits_data;
32 std::map<std::string, std::vector<std::string>> images_campaigns;
33 std::vector<std::string> images_general;
34 
gather_images(const config & from,std::vector<std::string> & to)35 void gather_images(const config& from, std::vector<std::string>& to)
36 {
37 	const auto& im = utils::parenthetical_split(from["images"], ',');
38 	if(!im.empty()) {
39 		to.insert(to.end(), im.begin(), im.end());
40 	}
41 }
42 
43 } // end anon namespace
44 
credits_group(const config & cfg,bool is_campaign_credits)45 credits_group::credits_group(const config& cfg, bool is_campaign_credits)
46 	: sections()
47 	, id()
48 	, header()
49 {
50 	if(is_campaign_credits) {
51 		id = cfg["id"].str();
52 		header = cfg["name"].t_str();
53 	}
54 
55 	sections.reserve(cfg.child_count("about"));
56 
57 	for(const config& about : cfg.child_range("about")) {
58 		if(!about.has_child("entry")) {
59 			continue;
60 		}
61 
62 		sections.emplace_back(about);
63 
64 		if(is_campaign_credits) {
65 			gather_images(about, images_campaigns[id]);
66 		} else {
67 			gather_images(about, images_general);
68 		}
69 	}
70 
71 	if(cfg["sort"].to_bool(false)) {
72 		std::sort(sections.begin(), sections.end());
73 	}
74 }
75 
about_group(const config & cfg)76 credits_group::about_group::about_group(const config& cfg)
77 	: names()
78 	, title(cfg["title"].t_str())
79 {
80 	names.reserve(cfg.child_count("entry"));
81 
82 	for(const config& entry : cfg.child_range("entry")) {
83 		names.push_back(entry["name"].str());
84 	}
85 }
86 
operator <(const about_group & o) const87 bool credits_group::about_group::operator<(const about_group& o) const
88 {
89 	return translation::compare(title.str(), o.title.str()) < 0;
90 }
91 
get_credits_data()92 const credits_data& get_credits_data()
93 {
94 	return parsed_credits_data;
95 }
96 
get_background_images(const std::string & campaign)97 std::vector<std::string> get_background_images(const std::string& campaign)
98 {
99 	if(!campaign.empty() && !images_campaigns[campaign].empty()){
100 		return images_campaigns[campaign];
101 	}
102 
103 	return images_general;
104 }
105 
set_about(const config & cfg)106 void set_about(const config& cfg)
107 {
108 	parsed_credits_data.clear();
109 
110 	// TODO: should we reserve space in parsed_credits_data here?
111 
112 	images_campaigns.clear();
113 	images_general.clear();
114 
115 	//
116 	// Parse all [credits_group] tags
117 	//
118 	for(const config& group : cfg.child_range("credits_group")) {
119 		if(group.has_child("about")) {
120 			parsed_credits_data.emplace_back(group, false);
121 
122 			// Not in the credits_group since we don't want to inadvertently
123 			// pick up images from campaigns.
124 			gather_images(group, images_general);
125 		}
126 	}
127 
128 	//
129 	// Parse all toplevel [about] tags.
130 	//
131 	config misc;
132 	for(const config& about : cfg.child_range("about")) {
133 		misc.add_child("about", about);
134 	}
135 
136 	if(!misc.empty()) {
137 		parsed_credits_data.emplace_back(misc, false);
138 	}
139 
140 	//
141 	// Parse all campaign [about] tags.
142 	//
143 	for(const config& campaign : cfg.child_range("campaign")) {
144 		if(campaign.has_child("about")) {
145 			parsed_credits_data.emplace_back(campaign, true);
146 		}
147 	}
148 }
149 
150 } // end namespace about
151