From da2988c4356d2756e86037b1c7e859f49583c109 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 8 Sep 2021 17:04:31 +0200 Subject: Load theme from file (~/.config/quickmedia/themes/.json and /usr/share/quickmedia/themes/.json) --- src/Theme.cpp | 183 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 104 insertions(+), 79 deletions(-) (limited to 'src/Theme.cpp') diff --git a/src/Theme.cpp b/src/Theme.cpp index a197848..8f52240 100644 --- a/src/Theme.cpp +++ b/src/Theme.cpp @@ -1,97 +1,122 @@ #include "../include/Theme.hpp" #include "../include/Config.hpp" -#include -#include -#include +#include "../include/Storage.hpp" #include namespace QuickMedia { - enum { - THEME_DARK, // Default theme - THEME_NORD, - - __NUM_THEMES__ // This should always be the last item - }; - - static bool themes_initialized = false; - static int current_theme = THEME_DARK; - static Theme themes[__NUM_THEMES__]; - - static void init_theme_dark() { - themes[THEME_DARK].background_color = sf::Color(18, 21, 26); - themes[THEME_DARK].text_color = sf::Color(255, 255, 255); - themes[THEME_DARK].faded_text_color = sf::Color(255, 255, 255, 179); - themes[THEME_DARK].shade_color = sf::Color(28, 32, 39); - themes[THEME_DARK].selected_color = sf::Color(55, 60, 68); - themes[THEME_DARK].card_item_background_color = sf::Color(28, 32, 39); - themes[THEME_DARK].replies_text_color = sf::Color(129, 162, 190); - themes[THEME_DARK].placeholder_text_color = sf::Color(255, 255, 255, 100); - themes[THEME_DARK].image_loading_background_color = sf::Color(52, 58, 70); - themes[THEME_DARK].attention_alert_text_color = sf::Color(255, 100, 100); - themes[THEME_DARK].cancel_button_background_color = sf::Color(41, 45, 50); - themes[THEME_DARK].confirm_button_background_color = sf::Color(31, 117, 255); - themes[THEME_DARK].loading_bar_color = sf::Color(31, 117, 255); - themes[THEME_DARK].embedded_item_border_color = sf::Color(255, 255, 255); - themes[THEME_DARK].provisional_message_color = sf::Color(255, 255, 255, 150); - themes[THEME_DARK].failed_text_color = sf::Color(255, 0, 0); - themes[THEME_DARK].timestamp_text_color = sf::Color(185, 190, 198, 100); - themes[THEME_DARK].new_items_alert_color = sf::Color(128, 50, 50); - themes[THEME_DARK].arrow_color = sf::Color(255, 255, 255, 175); - themes[THEME_DARK].url_text_color = sf::Color(35, 140, 245); - themes[THEME_DARK].loading_page_color = sf::Color(175, 180, 188); - themes[THEME_DARK].more_items_color = sf::Color(150, 175, 255, 100); - themes[THEME_DARK].blur_enabled = false; + static bool theme_initialized = false; + static Theme *theme = nullptr; + + static bool get_theme_by_name(const std::string &theme_name, Json::Value &json_root) { + Path config_path = get_storage_dir().join("themes").join(theme_name).append(".json"); + if(read_file_as_json(config_path, json_root) && json_root.isObject()) + return true; + + config_path = Path("/usr/share/quickmedia/themes/").join(theme_name).append(".json"); + if(read_file_as_json(config_path, json_root) && json_root.isObject()) + return true; + + return false; } - static void init_theme_nord() { - themes[THEME_NORD].background_color = sf::Color(46, 52, 64); - themes[THEME_NORD].text_color = sf::Color(236, 239, 244); - themes[THEME_NORD].faded_text_color = sf::Color(229, 233, 240); - themes[THEME_NORD].shade_color = sf::Color(67, 76, 94); - themes[THEME_NORD].selected_color = sf::Color(59, 66, 82); - themes[THEME_NORD].card_item_background_color = sf::Color(76, 86, 106); - themes[THEME_NORD].replies_text_color = sf::Color(136, 192, 208); - themes[THEME_NORD].placeholder_text_color = sf::Color(236, 239, 244); - themes[THEME_NORD].image_loading_background_color = sf::Color(216, 222, 233); - themes[THEME_NORD].attention_alert_text_color = sf::Color(191, 97, 106); - themes[THEME_NORD].cancel_button_background_color = sf::Color(229, 233, 240); - themes[THEME_NORD].confirm_button_background_color = sf::Color(229, 233, 240); - themes[THEME_NORD].loading_bar_color = sf::Color(136, 192, 208); - themes[THEME_NORD].embedded_item_border_color = sf::Color(216, 222, 233); - themes[THEME_NORD].provisional_message_color = sf::Color(236, 239, 244); - themes[THEME_NORD].failed_text_color = sf::Color(191, 97, 106); - themes[THEME_NORD].timestamp_text_color = sf::Color(76, 86, 106); - themes[THEME_NORD].new_items_alert_color = sf::Color(235, 203, 139); - themes[THEME_NORD].arrow_color = sf::Color(236, 239, 244); - themes[THEME_NORD].url_text_color = sf::Color(136, 192, 208); - themes[THEME_NORD].loading_page_color = sf::Color(229, 233, 240); - themes[THEME_NORD].more_items_color = sf::Color(150, 175, 255, 100); - themes[THEME_NORD].blur_enabled = false; + // Returns -1 if its not a hex value + static int get_hex_value(char c) { + if(c >= '0' && c <= '9') + return c - '0'; + else if(c >= 'a' && c <= 'f') + return 10 + (c - 'a'); + else if(c >= 'A' && c <= 'F') + return 10 + (c - 'A'); + else + return -1; } - void init_themes() { - if(themes_initialized) + static void parse_hex_set_color(const Json::Value &json_obj, const char *field_name, sf::Color &color) { + const Json::Value &json_val = json_obj[field_name]; + if(!json_val.isString()) { + fprintf(stderr, "Warning: theme variable \"%s\" does not exists or is not a string\n", field_name); return; + } - themes_initialized = true; - init_theme_dark(); - init_theme_nord(); + // #RRGGBB(AA), case insensitive hex + const char *color_str = json_val.asCString(); + if(color_str[0] != '#') { + fprintf(stderr, "Warning: theme variable \"%s\" is an invalid color value. Expected #RRGGBB or #RRGGBBAA, was: %s\n", field_name, color_str); + return; + } - const char *theme = get_config().theme.c_str(); - if(strcmp(theme, "default") == 0) - current_theme = THEME_DARK; - else if(strcmp(theme, "nord") == 0) - current_theme = THEME_NORD; - else - fprintf(stderr, "Warning: Invalid theme %s, using the default theme\n", theme); + const int color_str_len = strlen(color_str); + if(color_str_len - 1 != 6 && color_str_len - 1 != 8) { + fprintf(stderr, "Warning: theme variable \"%s\" is an invalid color value. Expected #RRGGBB or #RRGGBBAA, was: %s\n", field_name, color_str); + return; + } + + sf::Color new_color; + for(int i = 1; i < color_str_len; i += 2) { + const int c1 = get_hex_value(color_str[i + 0]); + const int c2 = get_hex_value(color_str[i + 1]); + if(c1 == -1 || c2 == -1) { + fprintf(stderr, "Warning: theme variable \"%s\" is an invalid color value. Expected #RRGGBB or #RRGGBBAA, was: %s\n", field_name, color_str); + return; + } + + // TODO: Test on big endian systems + (&new_color.r)[(i - 1)/2] = (c1 << 4) | c2; + } + color = new_color; } - void set_current_theme(int theme) { - current_theme = theme; + static void get_bool_value(const Json::Value &json_obj, const char *field_name, bool &val) { + const Json::Value &json_val = json_obj[field_name]; + if(!json_val.isBool()) { + fprintf(stderr, "Warning: theme variable \"%s\" does not exists or is not a boolean\n", field_name); + return; + } + val = json_val.asBool(); + } + + static void init_theme() { + if(theme_initialized) + return; + + theme_initialized = true; + // Wtf? can't use static non-pointer config because it causes a segfault. + // It looks like a libc bug??? crashes for both gcc and clang. + theme = new Theme(); + + Json::Value json_root; + if(!get_theme_by_name(get_config().theme, json_root)) { + fprintf(stderr, "Warning: failed to load theme: \"%s\", using \"default\" theme\n", get_config().theme.c_str()); + return; + } + + parse_hex_set_color(json_root, "background_color", theme->background_color); + parse_hex_set_color(json_root, "text_color", theme->text_color); + parse_hex_set_color(json_root, "faded_text_color", theme->faded_text_color); + parse_hex_set_color(json_root, "shade_color", theme->shade_color); + parse_hex_set_color(json_root, "selected_color", theme->selected_color); + parse_hex_set_color(json_root, "card_item_background_color", theme->card_item_background_color); + parse_hex_set_color(json_root, "replies_text_color", theme->replies_text_color); + parse_hex_set_color(json_root, "placeholder_text_color", theme->placeholder_text_color); + parse_hex_set_color(json_root, "image_loading_background_color", theme->image_loading_background_color); + parse_hex_set_color(json_root, "attention_alert_text_color", theme->attention_alert_text_color); + parse_hex_set_color(json_root, "cancel_button_background_color", theme->cancel_button_background_color); + parse_hex_set_color(json_root, "confirm_button_background_color", theme->confirm_button_background_color); + parse_hex_set_color(json_root, "loading_bar_color", theme->loading_bar_color); + parse_hex_set_color(json_root, "embedded_item_border_color", theme->embedded_item_border_color); + parse_hex_set_color(json_root, "provisional_message_color", theme->provisional_message_color); + parse_hex_set_color(json_root, "failed_text_color", theme->failed_text_color); + parse_hex_set_color(json_root, "timestamp_text_color", theme->timestamp_text_color); + parse_hex_set_color(json_root, "new_items_alert_color", theme->new_items_alert_color); + parse_hex_set_color(json_root, "arrow_color", theme->arrow_color); + parse_hex_set_color(json_root, "url_text_color", theme->url_text_color); + parse_hex_set_color(json_root, "loading_page_color", theme->loading_page_color); + parse_hex_set_color(json_root, "more_items_color", theme->more_items_color); + get_bool_value(json_root, "drop_shadow", theme->drop_shadow); } - const Theme& get_current_theme() { - assert(themes_initialized); - return themes[current_theme]; + const Theme& get_theme() { + init_theme(); + return *theme; } } -- cgit v1.2.3