pidgin/pidginstock.c

changeset 26378
e85d894af8a5
parent 25888
d0fdd378a635
child 26047
a7c475364465
child 26337
ec2fc1bc9024
equal deleted inserted replaced
26377:9124a345ed3a 26378:e85d894af8a5
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA 24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
25 * 25 *
26 */ 26 */
27 #include "internal.h" 27 #include "internal.h"
28 #include "pidgin.h" 28 #include "pidgin.h"
29 #include "prefs.h"
30
31 #include "gtkicon-theme-loader.h"
32 #include "theme-manager.h"
29 33
30 #include "pidginstock.h" 34 #include "pidginstock.h"
35
36 /**************************************************************************
37 * Globals
38 **************************************************************************/
39
40 static gboolean stock_initted = FALSE;
41 static GtkIconSize microscopic, extra_small, small, medium, large, huge;
42
43 /**************************************************************************
44 * Structures
45 **************************************************************************/
31 46
32 static struct StockIcon 47 static struct StockIcon
33 { 48 {
34 const char *name; 49 const char *name;
35 const char *dir; 50 const char *dir;
36 const char *filename; 51 const char *filename;
37 52
38 } const stock_icons[] = 53 } const stock_icons[] = {
39 { 54
40 { PIDGIN_STOCK_ACTION, NULL, GTK_STOCK_EXECUTE }, 55 { PIDGIN_STOCK_ACTION, NULL, GTK_STOCK_EXECUTE },
41 #if GTK_CHECK_VERSION(2,6,0) 56 #if GTK_CHECK_VERSION(2,6,0)
42 { PIDGIN_STOCK_ALIAS, NULL, GTK_STOCK_EDIT }, 57 { PIDGIN_STOCK_ALIAS, NULL, GTK_STOCK_EDIT },
43 #else 58 #else
44 { PIDGIN_STOCK_ALIAS, "buttons", "edit.png" }, 59 { PIDGIN_STOCK_ALIAS, "buttons", "edit.png" },
96 { PIDGIN_STOCK_OPEN_MAIL, N_("_Open Mail"), 0, 0, NULL }, 111 { PIDGIN_STOCK_OPEN_MAIL, N_("_Open Mail"), 0, 0, NULL },
97 { PIDGIN_STOCK_PAUSE, N_("_Pause"), 0, 0, NULL }, 112 { PIDGIN_STOCK_PAUSE, N_("_Pause"), 0, 0, NULL },
98 { PIDGIN_STOCK_EDIT, N_("_Edit"), 0, 0, NULL } 113 { PIDGIN_STOCK_EDIT, N_("_Edit"), 0, 0, NULL }
99 }; 114 };
100 115
101 static struct SizedStockIcon { 116 typedef struct {
102 const char *name; 117 const char *name;
103 const char *dir; 118 const char *dir;
104 const char *filename; 119 const char *filename;
105 gboolean microscopic; 120 gboolean microscopic;
106 gboolean extra_small; 121 gboolean extra_small;
108 gboolean medium; 123 gboolean medium;
109 gboolean large; 124 gboolean large;
110 gboolean huge; 125 gboolean huge;
111 gboolean rtl; 126 gboolean rtl;
112 const char *translucent_name; 127 const char *translucent_name;
113 } const sized_stock_icons [] = { 128 } SizedStockIcon;
114 { PIDGIN_STOCK_STATUS_AVAILABLE, "status", "available.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_AVAILABLE_I }, 129
115 { PIDGIN_STOCK_STATUS_AWAY, "status", "away.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_AWAY_I }, 130 const SizedStockIcon sized_stock_icons [] = {
116 { PIDGIN_STOCK_STATUS_BUSY, "status", "busy.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_BUSY_I }, 131
117 { PIDGIN_STOCK_STATUS_CHAT, "status", "chat.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
118 { PIDGIN_STOCK_STATUS_INVISIBLE,"status", "invisible.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
119 { PIDGIN_STOCK_STATUS_XA, "status", "extended-away.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, PIDGIN_STOCK_STATUS_XA_I },
120 { PIDGIN_STOCK_STATUS_LOGIN, "status", "log-in.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, NULL },
121 { PIDGIN_STOCK_STATUS_LOGOUT, "status", "log-out.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, NULL },
122 { PIDGIN_STOCK_STATUS_OFFLINE, "status", "offline.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_OFFLINE_I },
123 { PIDGIN_STOCK_STATUS_PERSON, "status", "person.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
124 { PIDGIN_STOCK_STATUS_MESSAGE, "toolbar", "message-new.png", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
125
126 { PIDGIN_STOCK_STATUS_IGNORED, "emblems", "blocked.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 132 { PIDGIN_STOCK_STATUS_IGNORED, "emblems", "blocked.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
127 { PIDGIN_STOCK_STATUS_FOUNDER, "emblems", "founder.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 133 { PIDGIN_STOCK_STATUS_FOUNDER, "emblems", "founder.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
128 { PIDGIN_STOCK_STATUS_OPERATOR, "emblems", "operator.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 134 { PIDGIN_STOCK_STATUS_OPERATOR, "emblems", "operator.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
129 { PIDGIN_STOCK_STATUS_HALFOP, "emblems", "half-operator.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 135 { PIDGIN_STOCK_STATUS_HALFOP, "emblems", "half-operator.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
130 { PIDGIN_STOCK_STATUS_VOICE, "emblems", "voice.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 136 { PIDGIN_STOCK_STATUS_VOICE, "emblems", "voice.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
173 { PIDGIN_STOCK_ANIMATION_TYPING2, "animations", "typing2.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 179 { PIDGIN_STOCK_ANIMATION_TYPING2, "animations", "typing2.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
174 { PIDGIN_STOCK_ANIMATION_TYPING3, "animations", "typing3.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 180 { PIDGIN_STOCK_ANIMATION_TYPING3, "animations", "typing3.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
175 { PIDGIN_STOCK_ANIMATION_TYPING4, "animations", "typing4.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 181 { PIDGIN_STOCK_ANIMATION_TYPING4, "animations", "typing4.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
176 { PIDGIN_STOCK_ANIMATION_TYPING5, "animations", "typing5.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 182 { PIDGIN_STOCK_ANIMATION_TYPING5, "animations", "typing5.png",FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
177 183
178 { PIDGIN_STOCK_TOOLBAR_BGCOLOR, "toolbar", "change-bgcolor.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 184 { PIDGIN_STOCK_TOOLBAR_BGCOLOR, "toolbar", "change-bgcolor.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
179 { PIDGIN_STOCK_TOOLBAR_BLOCK, "emblems", "blocked.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 185 { PIDGIN_STOCK_TOOLBAR_BLOCK, "emblems", "blocked.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
180 { PIDGIN_STOCK_TOOLBAR_FGCOLOR, "toolbar", "change-fgcolor.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 186 { PIDGIN_STOCK_TOOLBAR_FGCOLOR, "toolbar", "change-fgcolor.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
181 { PIDGIN_STOCK_TOOLBAR_SMILEY, "toolbar", "emote-select.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 187 { PIDGIN_STOCK_TOOLBAR_SMILEY, "toolbar", "emote-select.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
182 { PIDGIN_STOCK_TOOLBAR_FONT_FACE, "toolbar", "font-face.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 188 { PIDGIN_STOCK_TOOLBAR_FONT_FACE, "toolbar", "font-face.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
183 { PIDGIN_STOCK_TOOLBAR_TEXT_SMALLER, "toolbar", "font-size-down.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 189 { PIDGIN_STOCK_TOOLBAR_TEXT_SMALLER, "toolbar", "font-size-down.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
184 { PIDGIN_STOCK_TOOLBAR_TEXT_LARGER, "toolbar", "font-size-up.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 190 { PIDGIN_STOCK_TOOLBAR_TEXT_LARGER, "toolbar", "font-size-up.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
185 { PIDGIN_STOCK_TOOLBAR_INSERT, "toolbar", "insert.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 191 { PIDGIN_STOCK_TOOLBAR_INSERT, "toolbar", "insert.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
186 { PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE, "toolbar", "insert-image.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 192 { PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE, "toolbar", "insert-image.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
187 { PIDGIN_STOCK_TOOLBAR_INSERT_LINK, "toolbar", "insert-link.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 193 { PIDGIN_STOCK_TOOLBAR_INSERT_LINK, "toolbar", "insert-link.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
188 { PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, "toolbar", "message-new.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 194 { PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, "toolbar", "message-new.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
189 { PIDGIN_STOCK_TOOLBAR_PENDING, "tray", "tray-new-im.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 195 { PIDGIN_STOCK_TOOLBAR_PENDING, "toolbar", "message-new.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
190 { PIDGIN_STOCK_TOOLBAR_PLUGINS, "toolbar", "plugins.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 196 { PIDGIN_STOCK_TOOLBAR_PLUGINS, "toolbar", "plugins.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
191 { PIDGIN_STOCK_TOOLBAR_UNBLOCK, "toolbar", "unblock.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 197 { PIDGIN_STOCK_TOOLBAR_UNBLOCK, "toolbar", "unblock.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
192 { PIDGIN_STOCK_TOOLBAR_SELECT_AVATAR, "toolbar", "select-avatar.png", FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, NULL }, 198 { PIDGIN_STOCK_TOOLBAR_SELECT_AVATAR, "toolbar", "select-avatar.png", FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, NULL },
193 { PIDGIN_STOCK_TOOLBAR_SEND_FILE, "toolbar", "send-file.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 199 { PIDGIN_STOCK_TOOLBAR_SEND_FILE, "toolbar", "send-file.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
194 { PIDGIN_STOCK_TOOLBAR_TRANSFER, "toolbar", "transfer.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }, 200 { PIDGIN_STOCK_TOOLBAR_TRANSFER, "toolbar", "transfer.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL }
195
196 { PIDGIN_STOCK_TRAY_AVAILABLE, "tray", "tray-online.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
197 { PIDGIN_STOCK_TRAY_INVISIBLE, "tray", "tray-invisible.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
198 { PIDGIN_STOCK_TRAY_AWAY, "tray", "tray-away.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
199 { PIDGIN_STOCK_TRAY_BUSY, "tray", "tray-busy.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
200 { PIDGIN_STOCK_TRAY_XA, "tray", "tray-extended-away.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
201 { PIDGIN_STOCK_TRAY_OFFLINE, "tray", "tray-offline.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
202 { PIDGIN_STOCK_TRAY_CONNECT, "tray", "tray-connecting.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
203 { PIDGIN_STOCK_TRAY_PENDING, "tray", "tray-new-im.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
204 { PIDGIN_STOCK_TRAY_EMAIL, "tray", "tray-message.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }
205 }; 201 };
206 202
207 static void 203 const SizedStockIcon sized_status_icons [] = {
208 add_sized_icon_common(GtkIconSet *iconset, GtkIconSize sizeid, const char *dir, 204
209 gboolean rtl, const char *size, const char *file, 205 { PIDGIN_STOCK_STATUS_AVAILABLE, "status", "available.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_AVAILABLE_I },
210 gboolean translucent); 206 { PIDGIN_STOCK_STATUS_AWAY, "status", "away.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_AWAY_I },
207 { PIDGIN_STOCK_STATUS_BUSY, "status", "busy.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_BUSY_I },
208 { PIDGIN_STOCK_STATUS_CHAT, "status", "chat.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
209 { PIDGIN_STOCK_STATUS_INVISIBLE, "status", "invisible.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
210 { PIDGIN_STOCK_STATUS_XA, "status", "extended-away.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, PIDGIN_STOCK_STATUS_XA_I },
211 { PIDGIN_STOCK_STATUS_LOGIN, "status", "log-in.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, NULL },
212 { PIDGIN_STOCK_STATUS_LOGOUT, "status", "log-out.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, NULL },
213 { PIDGIN_STOCK_STATUS_OFFLINE, "status", "offline.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_OFFLINE_I },
214 { PIDGIN_STOCK_STATUS_PERSON, "status", "person.png", TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
215 { PIDGIN_STOCK_STATUS_MESSAGE, "toolbar", "message-new.png", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
216
217 { PIDGIN_STOCK_TRAY_AVAILABLE, "tray", "tray-online.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
218 { PIDGIN_STOCK_TRAY_INVISIBLE, "tray", "tray-invisible.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
219 { PIDGIN_STOCK_TRAY_AWAY, "tray", "tray-away.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
220 { PIDGIN_STOCK_TRAY_BUSY, "tray", "tray-busy.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
221 { PIDGIN_STOCK_TRAY_XA, "tray", "tray-extended-away.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
222 { PIDGIN_STOCK_TRAY_OFFLINE, "tray", "tray-offline.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
223 { PIDGIN_STOCK_TRAY_CONNECT, "tray", "tray-connecting.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
224 { PIDGIN_STOCK_TRAY_PENDING, "tray", "tray-new-im.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
225 { PIDGIN_STOCK_TRAY_EMAIL, "tray", "tray-message.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }
226 };
227
228 /*****************************************************************************
229 * Private functions
230 *****************************************************************************/
211 231
212 static gchar * 232 static gchar *
213 find_file_common(const char *name) 233 find_file_common(const char *name)
214 { 234 {
215 gchar *filename; 235 gchar *filename;
255 ret = find_file_common(filename); 275 ret = find_file_common(filename);
256 g_free(filename); 276 g_free(filename);
257 return ret; 277 return ret;
258 } 278 }
259 279
260 static void
261 add_sized_icon(GtkIconSet *iconset, GtkIconSize sizeid, const char *dir,
262 gboolean rtl, const char *size, const char *file)
263 {
264 add_sized_icon_common(iconset, sizeid, dir, rtl, size, file, FALSE);
265 }
266 280
267 /* Altered from do_colorshift in gnome-panel */ 281 /* Altered from do_colorshift in gnome-panel */
268 static void 282 static void
269 do_alphashift (GdkPixbuf *dest, GdkPixbuf *src) 283 do_alphashift(GdkPixbuf *dest, GdkPixbuf *src)
270 { 284 {
271 gint i, j; 285 gint i, j;
272 gint width, height, has_alpha, srcrowstride, destrowstride; 286 gint width, height, has_alpha, srcrowstride, destrowstride;
273 guchar *target_pixels; 287 guchar *target_pixels;
274 guchar *original_pixels; 288 guchar *original_pixels;
298 *(pixdest++) = a / 2; 312 *(pixdest++) = a / 2;
299 } 313 }
300 } 314 }
301 } 315 }
302 316
317 static gchar *
318 find_icon_file(PidginStatusIconTheme *theme, const gchar *size, SizedStockIcon sized_icon, gboolean rtl)
319 {
320 const gchar *file, *dir;
321 gchar *file_full = NULL;
322 gchar *tmp;
323
324 if (theme != NULL) {
325 file = pidgin_icon_theme_get_icon(PIDGIN_ICON_THEME(theme), sized_icon.name);
326 dir = purple_theme_get_dir(PURPLE_THEME(theme));
327
328 if (rtl)
329 file_full = g_build_filename(dir, size, "rtl", file, NULL);
330 else
331 file_full = g_build_filename(dir, size, file, NULL);
332
333 if (g_file_test(file_full, G_FILE_TEST_IS_REGULAR))
334 return file_full;
335
336 g_free(file_full);
337 }
338
339 if (rtl)
340 tmp = g_build_filename("pixmaps", "pidgin", sized_icon.dir, size, "rtl", sized_icon.filename, NULL);
341 else
342 tmp = g_build_filename("pixmaps", "pidgin", sized_icon.dir, size, sized_icon.filename, NULL);
343
344 file_full = find_file_common(tmp);
345 g_free(tmp);
346 return file_full;
347 }
348
303 static void 349 static void
304 add_translucent_sized_icon(GtkIconSet *iconset, GtkIconSize sizeid, const char *dir, 350 add_sized_icon(GtkIconSet *iconset, GtkIconSize sizeid, PidginStatusIconTheme *theme,
305 gboolean rtl, const char *size, const char *file) 351 const char *size, SizedStockIcon sized_icon, gboolean translucent)
306 { 352 {
307 add_sized_icon_common(iconset, sizeid, dir, rtl, size, file, TRUE); 353 char *filename;
308 }
309
310 static void
311 add_sized_icon_common(GtkIconSet *iconset, GtkIconSize sizeid, const char *dir,
312 gboolean rtl, const char *size, const char *file,
313 gboolean translucent)
314 {
315 char *filename, *subpath;
316 GtkIconSource *source; 354 GtkIconSource *source;
317 GdkPixbuf *pixbuf; 355 GdkPixbuf *pixbuf;
318 356
319 subpath = g_build_filename("pixmaps", "pidgin", dir, size, file, NULL); 357 filename = find_icon_file(theme, size, sized_icon, FALSE);
320 filename = find_file_common(subpath); 358 g_return_if_fail(filename != NULL);
321 g_free(subpath);
322 if (!filename)
323 return;
324
325 pixbuf = gdk_pixbuf_new_from_file(filename, NULL); 359 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
326 if (translucent) 360 if (translucent)
327 do_alphashift(pixbuf, pixbuf); 361 do_alphashift(pixbuf, pixbuf);
328 362
329 source = gtk_icon_source_new(); 363 source = gtk_icon_source_new();
330 gtk_icon_source_set_pixbuf(source, pixbuf); 364 gtk_icon_source_set_pixbuf(source, pixbuf);
331 gtk_icon_source_set_direction(source, GTK_TEXT_DIR_LTR); 365 gtk_icon_source_set_direction(source, GTK_TEXT_DIR_LTR);
332 gtk_icon_source_set_direction_wildcarded(source, !rtl); 366 gtk_icon_source_set_direction_wildcarded(source, !sized_icon.rtl);
333 gtk_icon_source_set_size(source, sizeid); 367 gtk_icon_source_set_size(source, sizeid);
334 gtk_icon_source_set_size_wildcarded(source, FALSE); 368 gtk_icon_source_set_size_wildcarded(source, FALSE);
335 gtk_icon_source_set_state_wildcarded(source, TRUE); 369 gtk_icon_source_set_state_wildcarded(source, TRUE);
336 gtk_icon_set_add_source(iconset, source); 370 gtk_icon_set_add_source(iconset, source);
337 gtk_icon_source_free(source); 371 gtk_icon_source_free(source);
347 gtk_icon_source_free(source); 381 gtk_icon_source_free(source);
348 } 382 }
349 g_free(filename); 383 g_free(filename);
350 g_object_unref(pixbuf); 384 g_object_unref(pixbuf);
351 385
352 if (rtl) { 386 if (sized_icon.rtl) {
353 subpath = g_build_filename("pixmaps", "pidgin", dir, size, "rtl", file, NULL); 387 filename = find_icon_file(theme, size, sized_icon, TRUE);
354 filename = find_file_common(subpath); 388 g_return_if_fail(filename != NULL);
355 g_free(subpath);
356 if (!filename)
357 return;
358 pixbuf = gdk_pixbuf_new_from_file(filename, NULL); 389 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
359 if (translucent) 390 if (translucent)
360 do_alphashift(pixbuf, pixbuf); 391 do_alphashift(pixbuf, pixbuf);
392
361 source = gtk_icon_source_new(); 393 source = gtk_icon_source_new();
362 gtk_icon_source_set_pixbuf(source, pixbuf); 394 gtk_icon_source_set_pixbuf(source, pixbuf);
395 gtk_icon_source_set_filename(source, filename);
363 gtk_icon_source_set_direction(source, GTK_TEXT_DIR_RTL); 396 gtk_icon_source_set_direction(source, GTK_TEXT_DIR_RTL);
364 gtk_icon_source_set_size(source, sizeid); 397 gtk_icon_source_set_size(source, sizeid);
365 gtk_icon_source_set_size_wildcarded(source, FALSE); 398 gtk_icon_source_set_size_wildcarded(source, FALSE);
366 gtk_icon_source_set_state_wildcarded(source, TRUE); 399 gtk_icon_source_set_state_wildcarded(source, TRUE);
367 gtk_icon_set_add_source(iconset, source); 400 gtk_icon_set_add_source(iconset, source);
369 g_object_unref(pixbuf); 402 g_object_unref(pixbuf);
370 gtk_icon_source_free(source); 403 gtk_icon_source_free(source);
371 } 404 }
372 } 405 }
373 406
407 /*****************************************************************************
408 * Public API functions
409 *****************************************************************************/
410
411 void
412 pidgin_stock_load_status_icon_theme(PidginStatusIconTheme *theme)
413 {
414 GtkIconFactory *icon_factory;
415 gint i;
416 GtkIconSet *normal;
417 GtkIconSet *translucent = NULL;
418 GtkWidget *win;
419
420 if (theme != NULL) {
421 purple_prefs_set_string(PIDGIN_PREFS_ROOT "/status/icon-theme",
422 purple_theme_get_name(PURPLE_THEME(theme)));
423 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/status/icon-theme-dir",
424 purple_theme_get_dir(PURPLE_THEME(theme)));
425 }
426 else {
427 purple_prefs_set_string(PIDGIN_PREFS_ROOT "/status/icon-theme", "");
428 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/status/icon-theme-dir", "");
429 }
430
431 icon_factory = gtk_icon_factory_new();
432
433 gtk_icon_factory_add_default(icon_factory);
434
435 win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
436 gtk_widget_realize(win);
437
438 for (i = 0; i < G_N_ELEMENTS(sized_status_icons); i++)
439 {
440 normal = gtk_icon_set_new();
441 if (sized_status_icons[i].translucent_name)
442 translucent = gtk_icon_set_new();
443
444 #define ADD_SIZED_ICON(name, size) if (sized_status_icons[i].name) { \
445 add_sized_icon(normal, name, theme, size, sized_status_icons[i], FALSE); \
446 if (sized_status_icons[i].translucent_name) \
447 add_sized_icon(translucent, name, theme, size, sized_status_icons[i], TRUE); \
448 }
449 ADD_SIZED_ICON(microscopic, "11");
450 ADD_SIZED_ICON(extra_small, "16");
451 ADD_SIZED_ICON(small, "22");
452 ADD_SIZED_ICON(medium, "32");
453 ADD_SIZED_ICON(large, "48");
454 ADD_SIZED_ICON(huge, "64");
455 #undef ADD_SIZED_ICON
456
457 gtk_icon_factory_add(icon_factory, sized_status_icons[i].name, normal);
458 gtk_icon_set_unref(normal);
459
460 if (sized_status_icons[i].translucent_name) {
461 gtk_icon_factory_add(icon_factory, sized_status_icons[i].translucent_name, translucent);
462 gtk_icon_set_unref(translucent);
463 }
464 }
465
466
467 gtk_widget_destroy(win);
468 g_object_unref(G_OBJECT(icon_factory));
469 }
470
374 void 471 void
375 pidgin_stock_init(void) 472 pidgin_stock_init(void)
376 { 473 {
377 static gboolean stock_initted = FALSE;
378 GtkIconFactory *icon_factory; 474 GtkIconFactory *icon_factory;
379 size_t i; 475 size_t i;
380 GtkWidget *win; 476 GtkWidget *win;
381 GtkIconSize microscopic, extra_small, small, medium, large, huge; 477 PidginIconThemeLoader *loader;
478 const gchar *path = NULL;
382 479
383 if (stock_initted) 480 if (stock_initted)
384 return; 481 return;
385 482
386 stock_initted = TRUE; 483 stock_initted = TRUE;
484
485 /* Setup the status icon theme */
486 loader = g_object_new(PIDGIN_TYPE_ICON_THEME_LOADER, "type", "status-icon", NULL);
487 purple_theme_manager_register_type(PURPLE_THEME_LOADER(loader));
488 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/status/icon-theme", "");
489 purple_prefs_add_path(PIDGIN_PREFS_ROOT "/status/icon-theme-dir", "");
387 490
388 /* Setup the icon factory. */ 491 /* Setup the icon factory. */
389 icon_factory = gtk_icon_factory_new(); 492 icon_factory = gtk_icon_factory_new();
390 493
391 gtk_icon_factory_add_default(icon_factory); 494 gtk_icon_factory_add_default(icon_factory);
392 495
393 /* Er, yeah, a hack, but it works. :) */ 496 /* Er, yeah, a hack, but it works. :) */
394 win = gtk_window_new(GTK_WINDOW_TOPLEVEL); 497 win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
395 gtk_widget_realize(win); 498 gtk_widget_realize(win);
396 499
500 /* All non-sized icons */
397 for (i = 0; i < G_N_ELEMENTS(stock_icons); i++) 501 for (i = 0; i < G_N_ELEMENTS(stock_icons); i++)
398 { 502 {
399 GtkIconSource *source; 503 GtkIconSource *source;
400 GtkIconSet *iconset; 504 GtkIconSet *iconset;
401 gchar *filename; 505 gchar *filename;
430 534
431 gtk_icon_set_unref(iconset); 535 gtk_icon_set_unref(iconset);
432 } 536 }
433 537
434 /* register custom icon sizes */ 538 /* register custom icon sizes */
435
436 microscopic = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC, 11, 11); 539 microscopic = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC, 11, 11);
437 extra_small = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL, 16, 16); 540 extra_small = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL, 16, 16);
438 small = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_SMALL, 22, 22); 541 small = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_SMALL, 22, 22);
439 medium = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_MEDIUM, 32, 32); 542 medium = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_MEDIUM, 32, 32);
440 large = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_LARGE, 48, 48); 543 large = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_LARGE, 48, 48);
441 huge = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_HUGE, 64, 64); 544 huge = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_HUGE, 64, 64);
442 545
546 /* All non-status sized icons */
443 for (i = 0; i < G_N_ELEMENTS(sized_stock_icons); i++) 547 for (i = 0; i < G_N_ELEMENTS(sized_stock_icons); i++)
444 { 548 {
445 GtkIconSet *iconset; 549 GtkIconSet *iconset = gtk_icon_set_new();
446 550
447 iconset = gtk_icon_set_new(); 551 #define ADD_SIZED_ICON(name, size) if (sized_stock_icons[i].name) \
448 552 add_sized_icon(iconset, name, NULL, size, sized_stock_icons[i], FALSE);
449 #define ADD_SIZED_ICON(name, size) do { \
450 if (sized_stock_icons[i].name) \
451 add_sized_icon(iconset, name, \
452 sized_stock_icons[i].dir, sized_stock_icons[i].rtl, \
453 size, sized_stock_icons[i].filename); \
454 } while (0)
455 ADD_SIZED_ICON(microscopic, "11"); 553 ADD_SIZED_ICON(microscopic, "11");
456 ADD_SIZED_ICON(extra_small, "16"); 554 ADD_SIZED_ICON(extra_small, "16");
457 ADD_SIZED_ICON(small, "22"); 555 ADD_SIZED_ICON(small, "22");
458 ADD_SIZED_ICON(medium, "32"); 556 ADD_SIZED_ICON(medium, "32");
459 ADD_SIZED_ICON(large, "48"); 557 ADD_SIZED_ICON(large, "48");
460 ADD_SIZED_ICON(huge, "64"); 558 ADD_SIZED_ICON(huge, "64");
461 #undef ADD_SIZED_ICON 559 #undef ADD_SIZED_ICON
462 560
463 gtk_icon_factory_add(icon_factory, sized_stock_icons[i].name, iconset); 561 gtk_icon_factory_add(icon_factory, sized_stock_icons[i].name, iconset);
464 gtk_icon_set_unref(iconset); 562 gtk_icon_set_unref(iconset);
465
466 if (sized_stock_icons[i].translucent_name) {
467 iconset = gtk_icon_set_new();
468
469 #define ADD_TRANS_ICON(name, size) do { \
470 if (sized_stock_icons[i].name) \
471 add_translucent_sized_icon(iconset, name, \
472 sized_stock_icons[i].dir, sized_stock_icons[i].rtl, \
473 size, sized_stock_icons[i].filename); \
474 } while (0)
475 ADD_TRANS_ICON(microscopic, "11");
476 ADD_TRANS_ICON(extra_small, "16");
477 ADD_TRANS_ICON(small, "22");
478 ADD_TRANS_ICON(medium, "32");
479 ADD_TRANS_ICON(large, "48");
480 ADD_TRANS_ICON(huge, "64");
481 #undef ADD_TRANS_ICON
482
483 gtk_icon_factory_add(icon_factory, sized_stock_icons[i].translucent_name, iconset);
484 gtk_icon_set_unref(iconset);
485 }
486 } 563 }
487 564
488 gtk_widget_destroy(win); 565 gtk_widget_destroy(win);
489 g_object_unref(G_OBJECT(icon_factory)); 566 g_object_unref(G_OBJECT(icon_factory));
490 567
568 /* Pre-load Status icon theme - this avoids a bug with displaying the correct icon in the tray, theme is destroyed after*/
569 if (purple_prefs_get_string(PIDGIN_PREFS_ROOT "/icon/status/theme") &&
570 (path = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/status/icon-theme-dir"))) {
571
572 PidginStatusIconTheme *theme = PIDGIN_STATUS_ICON_THEME(purple_theme_loader_build(PURPLE_THEME_LOADER(loader), path));
573 pidgin_stock_load_status_icon_theme(theme);
574 g_object_unref(G_OBJECT(theme));
575
576 } else pidgin_stock_load_status_icon_theme(NULL);
577
491 /* Register the stock items. */ 578 /* Register the stock items. */
492 gtk_stock_add_static(stock_items, G_N_ELEMENTS(stock_items)); 579 gtk_stock_add_static(stock_items, G_N_ELEMENTS(stock_items));
493 } 580 }

mercurial