The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
achievements_dialog.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2003 - 2025
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
21#include "gettext.hpp"
23#include "gui/widgets/grid.hpp"
24#include "gui/widgets/label.hpp"
27#include "log.hpp"
30
31static lg::log_domain log_config("config");
32#define ERR_CONFIG LOG_STREAM(err, log_config)
33
34constexpr int sub_achievements_limit = 28;
35
37{
38
40
42 : modal_dialog(window_id())
43 , last_selected_(prefs::get().selected_achievement_group())
44 , achievements_box_(nullptr)
45 , content_names_(nullptr)
46{
47}
48
50{
51 std::vector<config> content_list;
52 content_names_ = &find_widget<menu_button>("selected_achievements_list");
53 connect_signal_notify_modified(*content_names_, std::bind(&achievements_dialog::set_achievements_row, this));
54
55 achievements_box_ = find_widget<listbox>("achievements_list", false, true);
56 int selected = 0;
57
58 for(const auto& list : game_config_manager::get()->get_achievements()) {
59 // only display the achievements for the first dropdown option on first showing the dialog
60 if(list.content_for_ == last_selected_ || last_selected_ == "") {
61 selected = content_list.size();
62 }
63
64 // populate all possibilities into the dropdown
65 content_list.emplace_back("label", list.display_name_);
66 }
67
68 if(content_list.size() > 0) {
69 content_names_->set_values(content_list);
70 content_names_->set_selected(selected, false);
72 }
73}
74
76{
77 prefs::get().set_selected_achievement_group(last_selected_);
78}
79
81{
85 int achieved_count = 0;
86
87 for(const auto& ach : list.achievements_) {
88 if(ach.achieved_) {
89 achieved_count++;
90 } else if(ach.hidden_ && !ach.achieved_) {
91 continue;
92 }
93
94 const bool in_progress = ach.max_progress_ != 0 && ach.current_progress_ != -1;
95 const auto in_progress_name = !in_progress
96 ? ach.name_
97 : t_string(VGETTEXT("$title ($count/$total)", {{
98 {"title", ach.name_},
99 {"count", std::to_string(ach.current_progress_)},
100 {"total", std::to_string(ach.max_progress_)}
101 }}));
102
104 { "icon", {
105 { "label", ach.achieved_
106 ? ach.icon_completed_
107 : ach.icon_
108 }
109 }},
110 { "name", {
111 { "label", ach.achieved_
112 ? ach.name_completed_
113 : in_progress_name
114 }
115 }},
116 { "description", {
117 { "label", ach.achieved_
118 ? t_string(markup::span_color("green", ach.description_completed_))
119 : ach.description_
120 }
121 }}
122 });
123
124 auto achievement_progress = static_cast<progress_bar*>(newrow.find("achievement_progress", false));
125 if(in_progress) {
126 achievement_progress->set_percentage((ach.current_progress_ / double(ach.max_progress_)) * 100);
127 } else {
128 achievement_progress->set_visible(gui2::widget::visibility::invisible);
129 }
130
131 auto name = static_cast<styled_widget*>(newrow.find("name", false));
132 name->get_canvas(0).set_variable("achieved", wfl::variant(ach.achieved_));
133
134 set_sub_achievements(newrow, ach);
135 }
136
137 auto& achieved_label = find_widget<label>("achievement_count");
138 achieved_label.set_label(VGETTEXT("Completed $count/$total", {
139 {"count", std::to_string(achieved_count)} ,
140 {"total", std::to_string(list.achievements_.size())}
141 }));
142}
143
145{
146 int i = 0;
147
148 // set any sub achievements
149 for(const sub_achievement& sub_ach : ach.sub_achievements_)
150 {
152 ERR_CONFIG << "Too many sub achievements";
153 break;
154 } else {
155 drawing* img = static_cast<drawing*>(newrow.find("sub_icon" + std::to_string(i), false));
156 img->set_label(sub_ach.achieved_ ? sub_ach.icon_completed_ : sub_ach.icon_);
157 img->set_tooltip(sub_ach.description_);
158 }
159 i++;
160 }
161
162 // if an achievement hasn't defined the maximum possible sub-achievements, hide the [image]s for the rest
163 for(; i < sub_achievements_limit; i++)
164 {
165 newrow.find("sub_icon" + std::to_string(i), false)->set_visible(visibility::invisible);
166 }
167}
168
169} // namespace gui2::dialogs
#define ERR_CONFIG
constexpr int sub_achievements_limit
static lg::log_domain log_config("config")
static game_config_manager * get()
std::vector< achievement_group > & get_achievements()
void set_variable(const std::string &key, wfl::variant &&value)
Definition canvas.hpp:165
virtual void post_show() override
Actions to be taken after the window has been shown.
virtual void pre_show() override
Actions to be taken before showing the window.
void set_sub_achievements(grid &newrow, const achievement &ach)
Abstract base class for all modal dialogs.
Base container class.
Definition grid.hpp:32
widget * find(const std::string_view id, const bool must_be_active) override
See widget::find.
Definition grid.cpp:645
grid & add_row(const widget_item &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:92
void clear()
Removes all the rows in the listbox, clearing it.
Definition listbox.cpp:147
void set_selected(unsigned selected, bool fire_event=true)
void set_values(const std::vector<::config > &values, unsigned selected=0)
virtual unsigned get_value() const override
Inherited from selectable_item.
void set_percentage(unsigned percentage)
canvas & get_canvas(const unsigned index)
void set_visible(const visibility visible)
Definition widget.cpp:479
@ invisible
The user set the widget invisible, that means:
static prefs & get()
#define VGETTEXT(msgid,...)
Handy wrappers around interpolate_variables_into_string and gettext.
This file contains the window object, this object is a top level container which has the event manage...
Standard logging facilities (interface).
#define REGISTER_DIALOG(window_id)
Wrapper for REGISTER_DIALOG2.
std::map< std::string, widget_item > widget_data
Definition widget.hpp:36
std::string span_color(const color_t &color, Args &&... data)
Applies Pango markup to the input specifying its display color.
Definition markup.hpp:110
A set of achievements tied to a particular content.
std::string content_for_
The internal ID used for this content.
std::vector< achievement > achievements_
The achievements associated to this content.
Represents a single achievement and its data.
std::vector< sub_achievement > sub_achievements_
The list of distinct sub-achievements for this achievement.
Represents a distinct sub-achievement within another achievement.
#define i