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
125
126
127
128
129
130
131
|
#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.isNull())
return;
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.isNull())
return;
if(!json_val.isBool()) {
fprintf(stderr, "Warning: theme variable \"%s\" 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;
}
}
|