Files
gKeyMapper/src/settings.cpp
2026-10-18 18:26:06 +02:00

96 lines
3.2 KiB
C++

// gKeyMapper - GUI options that are not part of the mapping format.
#include "settings.h"
#include <clocale>
#include <cstdlib>
#include <glib.h>
namespace gkeymapper {
namespace {
// Same shape as the mapping file next to it: a group and one key per option.
const char* kGroup = "gui";
const char* kMinimizeToTray = "minimize-to-tray";
const char* kLanguage = "language";
// What the session had in LANGUAGE before this program touched it, so choosing
// "follow the session" can put it back exactly.
std::string sessionLanguage;
bool sessionLanguageTaken = false;
} // namespace
std::string default_gui_config_path() {
const char* home = std::getenv("HOME");
return std::string(home ? home : "") + "/.config/gKeyMapper/gui.conf";
}
GuiSettings load_gui_settings() {
GuiSettings settings;
GKeyFile* file = g_key_file_new();
GError* error = nullptr;
// A missing file is the normal first start, not an error.
if (g_key_file_load_from_file(file, default_gui_config_path().c_str(), G_KEY_FILE_NONE,
&error)) {
GError* itemError = nullptr;
const gboolean value = g_key_file_get_boolean(file, kGroup, kMinimizeToTray, &itemError);
if (itemError == nullptr) {
settings.minimizeToTray = value != FALSE;
}
g_clear_error(&itemError);
g_autofree gchar* language = g_key_file_get_string(file, kGroup, kLanguage, nullptr);
if (language != nullptr) {
settings.language = language;
}
}
g_clear_error(&error);
g_key_file_unref(file);
return settings;
}
void save_gui_settings(const GuiSettings& settings) {
const std::string path = default_gui_config_path();
g_autofree gchar* directory = g_path_get_dirname(path.c_str());
g_mkdir_with_parents(directory, 0700);
GKeyFile* file = g_key_file_new();
g_key_file_set_boolean(file, kGroup, kMinimizeToTray, settings.minimizeToTray);
g_key_file_set_string(file, kGroup, kLanguage, settings.language.c_str());
GError* error = nullptr;
if (!g_key_file_save_to_file(file, path.c_str(), &error)) {
g_printerr("gkeymapper: could not write %s: %s\n", path.c_str(),
error != nullptr ? error->message : "unknown error");
g_clear_error(&error);
}
g_key_file_unref(file);
}
void apply_gui_language(const std::string& language) {
if (!sessionLanguageTaken) {
const char* current = g_getenv("LANGUAGE");
sessionLanguage = current != nullptr ? current : "";
sessionLanguageTaken = true;
}
// gettext checks LANGUAGE before the locale, so it is the one knob to turn;
// the shipped catalogs are small and the identity catalog for English means
// an explicit "en" works on a German desktop too.
if (language.empty()) {
if (sessionLanguage.empty()) {
g_unsetenv("LANGUAGE");
} else {
g_setenv("LANGUAGE", sessionLanguage.c_str(), TRUE);
}
} else {
g_setenv("LANGUAGE", language.c_str(), TRUE);
}
// setlocale re-reads the environment and bumps glibc's catalog counter, so
// the next translated string comes out of the new catalog.
setlocale(LC_ALL, "");
}
} // namespace gkeymapper