1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#include "../include/Theme.hpp"
#include "../include/Config.hpp"
#include "../include/Storage.hpp"
#include <json/value.h>
#include <assert.h>
namespace QuickMedia {
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;
}
// 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;
}
static void parse_hex_set_color(const Json::Value &json_obj, const char *field_name, mgl::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;
}
// #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 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;
}
mgl::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;
}
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;
setlocale(LC_ALL, "C"); // Sigh... stupid C
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_theme() {
init_theme();
return *theme;
}
}
|