Skip to content
API Documentation
BastionGuard™
LanguageDialog Class Reference

#include <LanguageDialog.hpp>

Inheritance diagram for LanguageDialog:

Classes

struct  LangEntry

Public Member Functions

 LanguageDialog (const std::string &configFile, const std::string &currentLang)
std::string selectedLanguage () const

Private Member Functions

void buildHeaderBar ()
void buildUI (const std::string &currentLang)
void onApply ()
bool saveLangToConfig (const std::string &lang)

Static Private Member Functions

static const std::vector< LangEntry > & availableLanguages ()

Private Attributes

std::string m_configFile
std::string m_selected
Gtk::ComboBoxText m_combo

Detailed Description

Dialogo modale per la selezione della lingua dell'interfaccia.

Salva la scelta in settings.ini (chiave "language=<locale>"). Per applicare la lingua è necessario riavviare l'applicazione: il dialogo mostra un messaggio informativo in merito.

Usa gettext/libintl: imposta LANGUAGE e chiama setlocale() + textdomain().

Definition at line 21 of file LanguageDialog.hpp.

Constructor & Destructor Documentation

◆ LanguageDialog()

LanguageDialog::LanguageDialog ( const std::string & configFile,
const std::string & currentLang )
explicit
Parameters
configFilePercorso completo di settings.ini
currentLangCodice locale attuale (es. "it_IT", "en_US", "")

Definition at line 40 of file LanguageDialog.cpp.

42 : Gtk::Dialog()
43 , m_configFile(configFile)
44 , m_selected(currentLang)
45{
46 set_default_size(400, -1);
47 set_resizable(false);
49 buildUI(currentLang);
50}
std::string m_selected
std::string m_configFile
void buildUI(const std::string &currentLang)

References buildHeaderBar(), buildUI(), m_configFile, and m_selected.

Member Function Documentation

◆ availableLanguages()

const std::vector< LanguageDialog::LangEntry > & LanguageDialog::availableLanguages ( )
staticprivate

Definition at line 21 of file LanguageDialog.cpp.

22{
23 static const std::vector<LangEntry> langs = {
24 { "", "System default" },
25 { "en_US", "English (US)" },
26 { "it_IT", "Italiano" },
27 { "de_DE", "Deutsch" },
28 { "fr_FR", "Français" },
29 { "es_ES", "Español" },
30 { "pt_BR", "Português (BR)" },
31 { "zh_CN", "中文 (简体)" },
32 { "ja_JP", "日本語" },
33 };
34 return langs;
35}

Referenced by buildUI().

◆ buildHeaderBar()

void LanguageDialog::buildHeaderBar ( )
private

Definition at line 57 of file LanguageDialog.cpp.

58{
59 auto header = Gtk::make_managed<Gtk::HeaderBar>();
60 header->set_show_title_buttons(false);
61 header->set_decoration_layout("");
62 header->get_style_context()->add_class("custom-headerbar");
63
64 // Titolo centrato
65 auto titleLabel = Gtk::make_managed<Gtk::Label>();
66 titleLabel->set_markup("<b>" + Glib::ustring(_("Seleziona lingua")) + "</b>");
67 titleLabel->get_style_context()->add_class("headerbar-title");
68 header->set_title_widget(*titleLabel);
69
70 // Pulsanti destra: minimizza + chiudi
71 auto headerRight = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 4);
72 headerRight->get_style_context()->add_class("header-right");
73
74 auto closeBtn = Gtk::make_managed<Gtk::Button>();
75 closeBtn->get_style_context()->add_class("header-button");
76 try {
77 auto pix = Gdk::Pixbuf::create_from_file(resource("icon-close.png"), 32, 32, true);
78 closeBtn->set_child(*Gtk::make_managed<Gtk::Image>(pix));
79 } catch (...) {
80 closeBtn->set_label("✕");
81 }
82 closeBtn->signal_clicked().connect([this]() { hide(); });
83 headerRight->append(*closeBtn);
84
85 header->pack_end(*headerRight);
86 set_titlebar(*header);
87}
#define _(s)
std::string resource(const std::string &rel)
Definition Resource.hpp:31

References _, and resource().

Referenced by LanguageDialog().

◆ buildUI()

void LanguageDialog::buildUI ( const std::string & currentLang)
private

Definition at line 89 of file LanguageDialog.cpp.

90{
91 auto* area = get_content_area();
92 area->set_spacing(12);
93 area->set_margin_top(16);
94 area->set_margin_bottom(4);
95 area->set_margin_start(16);
96 area->set_margin_end(16);
97
98 // Titolo interno
99 auto title = Gtk::make_managed<Gtk::Label>();
100 title->set_markup(
101 Glib::ustring("<b>") + _("Lingua dell'interfaccia") + "</b>");
102 title->set_halign(Gtk::Align::START);
103 area->append(*title);
104
105 // ComboBox con le lingue
106 for (const auto& lang : availableLanguages())
107 m_combo.append(lang.code, lang.label);
108
109 // Seleziona quella corrente
110 if (currentLang.empty())
111 m_combo.set_active_id("");
112 else
113 m_combo.set_active_id(currentLang);
114
115 if (m_combo.get_active_row_number() < 0)
116 m_combo.set_active(0); // fallback: System default
117
118 area->append(m_combo);
119
120 // Nota riavvio
121 auto note = Gtk::make_managed<Gtk::Label>(
122 _("⚠ L'applicazione verrà riavviata automaticamente per applicare la lingua."));
123 note->set_wrap(true);
124 note->set_max_width_chars(48);
125 note->set_halign(Gtk::Align::START);
126 note->get_style_context()->add_class("dim-label");
127 area->append(*note);
128
129 // Pulsanti
130 add_button(_("Annulla"), Gtk::ResponseType::CANCEL);
131 add_button(_("Applica"), Gtk::ResponseType::APPLY);
132 set_default_response(Gtk::ResponseType::APPLY);
133
134 signal_response().connect([this](int response) {
135 // Ignora risposte che non siano APPLY o CANCEL (es. DELETE_EVENT)
136 if (response == static_cast<int>(Gtk::ResponseType::APPLY)) {
137 onApply();
138 // onApply() chiama execvp — se arriviamo qui execvp è fallito
139 hide();
140 } else if (response == static_cast<int>(Gtk::ResponseType::CANCEL)) {
141 hide();
142 }
143 // Nessun hide() per altri response (evita doppio trigger)
144 });
145}
static const std::vector< LangEntry > & availableLanguages()
Gtk::ComboBoxText m_combo

References _, availableLanguages(), m_combo, and onApply().

Referenced by LanguageDialog().

◆ onApply()

void LanguageDialog::onApply ( )
private

Definition at line 150 of file LanguageDialog.cpp.

151{
152 m_selected = m_combo.get_active_id();
154 std::cerr << "[LanguageDialog] Impossibile salvare la lingua nel config\n";
155 return;
156 }
157
158 // Riavvia il processo per applicare subito la lingua.
159 // IMPORTANTE: prima di execvp puliamo LANGUAGE e LANG dall'ambiente
160 // del processo corrente — altrimenti il processo figlio erediterebbe
161 // le variabili vecchie e la lingua non cambierebbe (es. en_US → it_IT
162 // funziona, ma it_IT → en_US no perché LANGUAGE=it_IT resterebbe).
163 ::unsetenv("LANGUAGE");
164 ::unsetenv("LANG");
165 ::unsetenv("LC_ALL");
166 ::unsetenv("LC_MESSAGES");
167
168 // Imposta le nuove variabili solo se non è "System default"
169 if (!m_selected.empty()) {
170 const std::string lang_utf8 = m_selected + ".UTF-8";
171 ::setenv("LANGUAGE", m_selected.c_str(), 1);
172 ::setenv("LANG", lang_utf8.c_str(), 1);
173 ::setenv("LC_ALL", lang_utf8.c_str(), 1);
174 }
175
176 char exe[PATH_MAX];
177 ssize_t len = ::readlink("/proc/self/exe", exe, sizeof(exe) - 1);
178 if (len > 0) {
179 exe[len] = '\0';
180 char* argv[] = { exe, nullptr };
181 ::execvp(exe, argv);
182 std::perror("[LanguageDialog] execvp fallito");
183 }
184 std::exit(0);
185}
bool saveLangToConfig(const std::string &lang)

References m_combo, m_selected, and saveLangToConfig().

Referenced by buildUI().

◆ saveLangToConfig()

bool LanguageDialog::saveLangToConfig ( const std::string & lang)
private

Definition at line 187 of file LanguageDialog.cpp.

188{
189 // Leggi il file corrente (se esiste)
190 std::string content;
191 {
192 std::ifstream in(m_configFile);
193 if (in.is_open()) {
194 std::ostringstream ss;
195 ss << in.rdbuf();
196 content = ss.str();
197 }
198 }
199
200 // Rimuovi eventuale riga language= precedente
201 {
202 std::istringstream lines(content);
203 std::ostringstream out;
204 std::string line;
205 while (std::getline(lines, line)) {
206 if (line.rfind("language=", 0) == 0)
207 continue; // salta la vecchia riga
208 out << line << "\n";
209 }
210 content = out.str();
211 }
212
213 // Assicura sezione [General]
214 if (content.find("[General]") == std::string::npos)
215 content = "[General]\n" + content;
216
217 // Aggiungi la nuova riga dopo [General]
218 const std::string marker = "[General]\n";
219 auto pos = content.find(marker);
220 if (pos != std::string::npos)
221 content.insert(pos + marker.size(),
222 "language=" + lang + "\n");
223
224 // Scrivi
225 std::ofstream out(m_configFile, std::ios::trunc);
226 if (!out.is_open())
227 return false;
228 out << content;
229 return true;
230}

References m_configFile.

Referenced by onApply().

◆ selectedLanguage()

std::string LanguageDialog::selectedLanguage ( ) const
inline

Restituisce il codice locale scelto (vuoto = default di sistema).

Definition at line 32 of file LanguageDialog.hpp.

32{ return m_selected; }

References m_selected.

Member Data Documentation

◆ m_combo

Gtk::ComboBoxText LanguageDialog::m_combo
private

Definition at line 43 of file LanguageDialog.hpp.

Referenced by buildUI(), and onApply().

◆ m_configFile

std::string LanguageDialog::m_configFile
private

Definition at line 40 of file LanguageDialog.hpp.

Referenced by LanguageDialog(), and saveLangToConfig().

◆ m_selected

std::string LanguageDialog::m_selected
private

Definition at line 41 of file LanguageDialog.hpp.

Referenced by LanguageDialog(), onApply(), and selectedLanguage().


The documentation for this class was generated from the following files: