/src/pidgin/libpurple/theme-manager.c
Line | Count | Source |
1 | | /* |
2 | | * Themes for libpurple |
3 | | * |
4 | | * Pidgin is the legal property of its developers, whose names are too numerous |
5 | | * to list here. Please refer to the COPYRIGHT file distributed with this |
6 | | * source distribution. |
7 | | * |
8 | | * This program is free software; you can redistribute it and/or modify |
9 | | * it under the terms of the GNU General Public License as published by |
10 | | * the Free Software Foundation; either version 2 of the License, or |
11 | | * (at your option) any later version. |
12 | | * |
13 | | * This program is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU General Public License |
19 | | * along with this program; if not, write to the Free Software |
20 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
21 | | */ |
22 | | |
23 | | #include "internal.h" |
24 | | #include "theme-manager.h" |
25 | | #include "util.h" |
26 | | |
27 | | /****************************************************************************** |
28 | | * Globals |
29 | | *****************************************************************************/ |
30 | | |
31 | | static GHashTable *theme_table = NULL; |
32 | | |
33 | | /***************************************************************************** |
34 | | * GObject Stuff |
35 | | ****************************************************************************/ |
36 | | |
37 | | GType |
38 | | purple_theme_manager_get_type(void) |
39 | 0 | { |
40 | 0 | static GType type = 0; |
41 | 0 | if (type == 0) { |
42 | 0 | static const GTypeInfo info = { |
43 | 0 | sizeof(PurpleThemeManagerClass), |
44 | 0 | NULL, /* base_init */ |
45 | 0 | NULL, /* base_finalize */ |
46 | 0 | NULL, /* class_init */ |
47 | 0 | NULL, /* class_finalize */ |
48 | 0 | NULL, /* class_data */ |
49 | 0 | sizeof(PurpleThemeManager), |
50 | 0 | 0, /* n_preallocs */ |
51 | 0 | NULL, /* instance_init */ |
52 | 0 | NULL, /* Value Table */ |
53 | 0 | }; |
54 | 0 | type = g_type_register_static(G_TYPE_OBJECT, |
55 | 0 | "PurpleThemeManager", &info, 0); |
56 | 0 | } |
57 | 0 | return type; |
58 | 0 | } |
59 | | |
60 | | /****************************************************************************** |
61 | | * Helpers |
62 | | *****************************************************************************/ |
63 | | |
64 | | /* makes a key of <type> + '/' + <name> */ |
65 | | static gchar * |
66 | | purple_theme_manager_make_key(const gchar *name, const gchar *type) |
67 | 0 | { |
68 | 0 | g_return_val_if_fail(name && *name, NULL); |
69 | 0 | g_return_val_if_fail(type && *type, NULL); |
70 | 0 | return g_strconcat(type, "/", name, NULL); |
71 | 0 | } |
72 | | |
73 | | /* returns TRUE if theme is of type "user_data" */ |
74 | | static gboolean |
75 | | purple_theme_manager_is_theme_type(gchar *key, |
76 | | gpointer value, |
77 | | gchar *user_data) |
78 | 0 | { |
79 | 0 | return g_str_has_prefix(key, g_strconcat(user_data, "/", NULL)); |
80 | 0 | } |
81 | | |
82 | | static gboolean |
83 | | purple_theme_manager_is_theme(gchar *key, |
84 | | gpointer value, |
85 | | gchar *user_data) |
86 | 0 | { |
87 | 0 | return PURPLE_IS_THEME(value); |
88 | 0 | } |
89 | | |
90 | | static void |
91 | | purple_theme_manager_function_wrapper(gchar *key, |
92 | | gpointer value, |
93 | | PTFunc user_data) |
94 | 0 | { |
95 | 0 | if (PURPLE_IS_THEME(value)) |
96 | 0 | (* user_data)(value); |
97 | 0 | } |
98 | | |
99 | | static void |
100 | | purple_theme_manager_build_dir(const gchar *root) |
101 | 0 | { |
102 | 0 | gchar *purple_dir, *theme_dir; |
103 | 0 | const gchar *name = NULL, *type = NULL; |
104 | 0 | GDir *rdir, *tdir; |
105 | 0 | PurpleThemeLoader *loader; |
106 | |
|
107 | 0 | rdir = g_dir_open(root, 0, NULL); |
108 | |
|
109 | 0 | if (!rdir) |
110 | 0 | return; |
111 | | |
112 | | /* Parses directory by root/name/purple/type */ |
113 | 0 | while ((name = g_dir_read_name(rdir))) { |
114 | 0 | purple_dir = g_build_filename(root, name, "purple", NULL); |
115 | 0 | tdir = g_dir_open(purple_dir, 0, NULL); |
116 | |
|
117 | 0 | if (!tdir) { |
118 | 0 | g_free(purple_dir); |
119 | |
|
120 | 0 | continue; |
121 | 0 | } |
122 | | |
123 | 0 | while ((type = g_dir_read_name(tdir))) { |
124 | 0 | if ((loader = g_hash_table_lookup(theme_table, type))) { |
125 | 0 | PurpleTheme *theme = NULL; |
126 | |
|
127 | 0 | theme_dir = g_build_filename(purple_dir, type, NULL); |
128 | |
|
129 | 0 | theme = purple_theme_loader_build(loader, theme_dir); |
130 | 0 | g_free(theme_dir); |
131 | |
|
132 | 0 | if (PURPLE_IS_THEME(theme)) |
133 | 0 | purple_theme_manager_add_theme(theme); |
134 | 0 | } |
135 | 0 | } |
136 | |
|
137 | 0 | g_dir_close(tdir); |
138 | 0 | g_free(purple_dir); |
139 | 0 | } |
140 | |
|
141 | 0 | g_dir_close(rdir); |
142 | 0 | } |
143 | | |
144 | | /***************************************************************************** |
145 | | * Public API functions |
146 | | *****************************************************************************/ |
147 | | |
148 | | void |
149 | | purple_theme_manager_init(void) |
150 | 0 | { |
151 | 0 | theme_table = g_hash_table_new_full(g_str_hash, |
152 | 0 | g_str_equal, g_free, g_object_unref); |
153 | 0 | } |
154 | | |
155 | | void |
156 | | purple_theme_manager_refresh(void) |
157 | 0 | { |
158 | 0 | gchar *path = NULL; |
159 | 0 | const gchar *xdg = NULL; |
160 | 0 | gint i = 0; |
161 | |
|
162 | 0 | g_hash_table_foreach_remove(theme_table, |
163 | 0 | (GHRFunc) purple_theme_manager_is_theme, NULL); |
164 | | |
165 | | /* Add themes from ~/.purple */ |
166 | 0 | path = g_build_filename(purple_user_dir(), "themes", NULL); |
167 | 0 | purple_theme_manager_build_dir(path); |
168 | 0 | g_free(path); |
169 | | |
170 | | /* look for XDG_DATA_HOME. If we don't have it use ~/.local, and add it */ |
171 | 0 | if ((xdg = g_getenv("XDG_DATA_HOME")) != NULL) |
172 | 0 | path = g_build_filename(xdg, "themes", NULL); |
173 | 0 | else |
174 | 0 | path = g_build_filename(purple_home_dir(), ".local", "themes", NULL); |
175 | |
|
176 | 0 | purple_theme_manager_build_dir(path); |
177 | 0 | g_free(path); |
178 | | |
179 | | /* now dig through XDG_DATA_DIRS and add those too */ |
180 | 0 | xdg = g_getenv("XDG_DATA_DIRS"); |
181 | 0 | if (xdg) { |
182 | 0 | gchar **xdg_dirs = g_strsplit(xdg, G_SEARCHPATH_SEPARATOR_S, 0); |
183 | |
|
184 | 0 | for (i = 0; xdg_dirs[i]; i++) { |
185 | 0 | path = g_build_filename(xdg_dirs[i], "themes", NULL); |
186 | 0 | purple_theme_manager_build_dir(path); |
187 | 0 | g_free(path); |
188 | 0 | } |
189 | |
|
190 | 0 | g_strfreev(xdg_dirs); |
191 | 0 | } |
192 | 0 | } |
193 | | |
194 | | void |
195 | | purple_theme_manager_uninit(void) |
196 | 0 | { |
197 | 0 | g_hash_table_destroy(theme_table); |
198 | 0 | } |
199 | | |
200 | | void |
201 | | purple_theme_manager_register_type(PurpleThemeLoader *loader) |
202 | 0 | { |
203 | 0 | gchar *type; |
204 | |
|
205 | 0 | g_return_if_fail(PURPLE_IS_THEME_LOADER(loader)); |
206 | | |
207 | 0 | type = g_strdup(purple_theme_loader_get_type_string(loader)); |
208 | 0 | g_return_if_fail(type); |
209 | | |
210 | | /* if something is already there do nothing */ |
211 | 0 | if (!g_hash_table_lookup(theme_table, type)) |
212 | 0 | g_hash_table_insert(theme_table, type, loader); |
213 | 0 | } |
214 | | |
215 | | void |
216 | | purple_theme_manager_unregister_type(PurpleThemeLoader *loader) |
217 | 0 | { |
218 | 0 | const gchar *type; |
219 | |
|
220 | 0 | g_return_if_fail(PURPLE_IS_THEME_LOADER(loader)); |
221 | | |
222 | 0 | type = purple_theme_loader_get_type_string(loader); |
223 | 0 | g_return_if_fail(type); |
224 | | |
225 | 0 | if (g_hash_table_lookup(theme_table, type) == loader) |
226 | 0 | { |
227 | 0 | g_hash_table_remove(theme_table, type); |
228 | |
|
229 | 0 | g_hash_table_foreach_remove(theme_table, |
230 | 0 | (GHRFunc)purple_theme_manager_is_theme_type, (gpointer)type); |
231 | 0 | } /* only free if given registered loader */ |
232 | 0 | } |
233 | | |
234 | | PurpleTheme * |
235 | | purple_theme_manager_find_theme(const gchar *name, |
236 | | const gchar *type) |
237 | 0 | { |
238 | 0 | gchar *key; |
239 | 0 | PurpleTheme *theme; |
240 | |
|
241 | 0 | key = purple_theme_manager_make_key(name, type); |
242 | |
|
243 | 0 | g_return_val_if_fail(key, NULL); |
244 | | |
245 | 0 | theme = g_hash_table_lookup(theme_table, key); |
246 | |
|
247 | 0 | g_free(key); |
248 | |
|
249 | 0 | return theme; |
250 | 0 | } |
251 | | |
252 | | void |
253 | | purple_theme_manager_add_theme(PurpleTheme *theme) |
254 | 0 | { |
255 | 0 | gchar *key; |
256 | |
|
257 | 0 | g_return_if_fail(PURPLE_IS_THEME(theme)); |
258 | | |
259 | 0 | key = purple_theme_manager_make_key(purple_theme_get_name(theme), |
260 | 0 | purple_theme_get_type_string(theme)); |
261 | |
|
262 | 0 | g_return_if_fail(key); |
263 | | |
264 | | /* if something is already there do nothing */ |
265 | 0 | if (g_hash_table_lookup(theme_table, key) == NULL) |
266 | 0 | g_hash_table_insert(theme_table, key, theme); |
267 | 0 | } |
268 | | |
269 | | void |
270 | | purple_theme_manager_remove_theme(PurpleTheme *theme) |
271 | 0 | { |
272 | 0 | gchar *key; |
273 | |
|
274 | 0 | g_return_if_fail(PURPLE_IS_THEME(theme)); |
275 | | |
276 | 0 | key = purple_theme_manager_make_key(purple_theme_get_name(theme), |
277 | 0 | purple_theme_get_type_string(theme)); |
278 | |
|
279 | 0 | g_return_if_fail(key); |
280 | | |
281 | 0 | g_hash_table_remove(theme_table, key); |
282 | |
|
283 | 0 | g_free(key); |
284 | 0 | } |
285 | | |
286 | | void |
287 | | purple_theme_manager_for_each_theme(PTFunc func) |
288 | 0 | { |
289 | 0 | g_return_if_fail(func); |
290 | | |
291 | 0 | g_hash_table_foreach(theme_table, |
292 | 0 | (GHFunc) purple_theme_manager_function_wrapper, func); |
293 | 0 | } |
294 | | |
295 | | PurpleTheme * |
296 | | purple_theme_manager_load_theme(const gchar *theme_dir, const gchar *type) |
297 | 0 | { |
298 | 0 | PurpleThemeLoader *loader; |
299 | |
|
300 | 0 | g_return_val_if_fail(theme_dir != NULL && type != NULL, NULL); |
301 | | |
302 | 0 | loader = g_hash_table_lookup(theme_table, type); |
303 | 0 | g_return_val_if_fail(PURPLE_IS_THEME_LOADER(loader), NULL); |
304 | | |
305 | 0 | return purple_theme_loader_build(loader, theme_dir); |
306 | 0 | } |