comparison pidgin/pidginstock.c @ 29671:b98519a42e53

propagate from branch 'im.pidgin.pidgin' (head 431618de0f30a6938f7e14d2d61ee5d7738acd59) to branch 'im.pidgin.cpw.attention_ui' (head 152f22112dfd920caedfff2893c8ffd449c1083c)
author Marcus Lundblad <ml@update.uu.se>
date Mon, 02 Mar 2009 22:07:59 +0000
parents a0fd6a41d127 584063555949
children 68f6de7d1408
comparison
equal deleted inserted replaced
29670:a0668fbf2483 29671:b98519a42e53
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 { PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION, "toolbar", "get-attention.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
196
197 { PIDGIN_STOCK_TRAY_AVAILABLE, "tray", "tray-online.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
198 { PIDGIN_STOCK_TRAY_INVISIBLE, "tray", "tray-invisible.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
199 { PIDGIN_STOCK_TRAY_AWAY, "tray", "tray-away.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
200 { PIDGIN_STOCK_TRAY_BUSY, "tray", "tray-busy.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
201 { PIDGIN_STOCK_TRAY_XA, "tray", "tray-extended-away.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
202 { PIDGIN_STOCK_TRAY_OFFLINE, "tray", "tray-offline.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
203 { PIDGIN_STOCK_TRAY_CONNECT, "tray", "tray-connecting.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
204 { PIDGIN_STOCK_TRAY_PENDING, "tray", "tray-new-im.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
205 { PIDGIN_STOCK_TRAY_EMAIL, "tray", "tray-message.png", FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL }
206 }; 201 };
207 202
208 static void 203 const SizedStockIcon sized_status_icons [] = {
209 add_sized_icon_common(GtkIconSet *iconset, GtkIconSize sizeid, const char *dir, 204
210 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 },
211 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 *****************************************************************************/
212 231
213 static gchar * 232 static gchar *
214 find_file_common(const char *name) 233 find_file_common(const char *name)
215 { 234 {
216 gchar *filename; 235 gchar *filename;
257 g_free(filename); 276 g_free(filename);
258 return ret; 277 return ret;
259 } 278 }
260 279
261 static void 280 static void
262 add_sized_icon(GtkIconSet *iconset, GtkIconSize sizeid, const char *dir, 281 add_sized_icon(GtkIconSet *iconset, GtkIconSize sizeid, const char *dir,
263 gboolean rtl, const char *size, const char *file) 282 gboolean rtl, const char *size, const char *file)
264 { 283 {
265 add_sized_icon_common(iconset, sizeid, dir, rtl, size, file, FALSE); 284 char *filename;
285 GtkIconSource *source;
286
287 filename = g_build_filename(DATADIR, "pixmaps", "pidgin", dir, size, file, NULL);
288 source = gtk_icon_source_new();
289 gtk_icon_source_set_filename(source, filename);
290 gtk_icon_source_set_direction(source, GTK_TEXT_DIR_LTR);
291 gtk_icon_source_set_direction_wildcarded(source, !rtl);
292 gtk_icon_source_set_size(source, sizeid);
293 gtk_icon_source_set_size_wildcarded(source, FALSE);
294 gtk_icon_source_set_state_wildcarded(source, TRUE);
295 gtk_icon_set_add_source(iconset, source);
296 gtk_icon_source_free(source);
297
298 if (sizeid == gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL)) {
299 source = gtk_icon_source_new();
300 gtk_icon_source_set_filename(source, filename);
301 gtk_icon_source_set_direction_wildcarded(source, TRUE);
302 gtk_icon_source_set_size(source, GTK_ICON_SIZE_MENU);
303 gtk_icon_source_set_size_wildcarded(source, FALSE);
304 gtk_icon_source_set_state_wildcarded(source, TRUE);
305 gtk_icon_set_add_source(iconset, source);
306 gtk_icon_source_free(source);
307 }
308 g_free(filename);
309
310 if (rtl) {
311 filename = g_build_filename(DATADIR, "pixmaps", "pidgin", dir, size, "rtl", file, NULL);
312 source = gtk_icon_source_new();
313 gtk_icon_source_set_filename(source, filename);
314 gtk_icon_source_set_direction(source, GTK_TEXT_DIR_RTL);
315 gtk_icon_source_set_size(source, sizeid);
316 gtk_icon_source_set_size_wildcarded(source, FALSE);
317 gtk_icon_source_set_state_wildcarded(source, TRUE);
318 gtk_icon_set_add_source(iconset, source);
319 g_free(filename);
320 gtk_icon_source_free(source);
321 }
322
323
266 } 324 }
267 325
268 /* Altered from do_colorshift in gnome-panel */ 326 /* Altered from do_colorshift in gnome-panel */
269 static void 327 static void
270 do_alphashift (GdkPixbuf *dest, GdkPixbuf *src) 328 do_alphashift(GdkPixbuf *dest, GdkPixbuf *src)
271 { 329 {
272 gint i, j; 330 gint i, j;
273 gint width, height, has_alpha, srcrowstride, destrowstride; 331 gint width, height, has_alpha, srcrowstride, destrowstride;
274 guchar *target_pixels; 332 guchar *target_pixels;
275 guchar *original_pixels; 333 guchar *original_pixels;
299 *(pixdest++) = a / 2; 357 *(pixdest++) = a / 2;
300 } 358 }
301 } 359 }
302 } 360 }
303 361
362 static gchar *
363 find_icon_file(PidginStatusIconTheme *theme, const gchar *size, SizedStockIcon sized_icon, gboolean rtl)
364 {
365 const gchar *file, *dir;
366 gchar *file_full = NULL;
367 gchar *tmp;
368
369 if (theme != NULL) {
370 file = pidgin_icon_theme_get_icon(PIDGIN_ICON_THEME(theme), sized_icon.name);
371 dir = purple_theme_get_dir(PURPLE_THEME(theme));
372
373 if (rtl)
374 file_full = g_build_filename(dir, size, "rtl", file, NULL);
375 else
376 file_full = g_build_filename(dir, size, file, NULL);
377
378 if (g_file_test(file_full, G_FILE_TEST_IS_REGULAR))
379 return file_full;
380
381 g_free(file_full);
382 }
383
384 if (rtl)
385 tmp = g_build_filename("pixmaps", "pidgin", sized_icon.dir, size, "rtl", sized_icon.filename, NULL);
386 else
387 tmp = g_build_filename("pixmaps", "pidgin", sized_icon.dir, size, sized_icon.filename, NULL);
388
389 file_full = find_file_common(tmp);
390 g_free(tmp);
391 return file_full;
392 }
393
304 static void 394 static void
305 add_translucent_sized_icon(GtkIconSet *iconset, GtkIconSize sizeid, const char *dir, 395 add_sized_icon(GtkIconSet *iconset, GtkIconSize sizeid, PidginStatusIconTheme *theme,
306 gboolean rtl, const char *size, const char *file) 396 const char *size, SizedStockIcon sized_icon, gboolean translucent)
307 { 397 {
308 add_sized_icon_common(iconset, sizeid, dir, rtl, size, file, TRUE); 398 char *filename;
309 }
310
311 static void
312 add_sized_icon_common(GtkIconSet *iconset, GtkIconSize sizeid, const char *dir,
313 gboolean rtl, const char *size, const char *file,
314 gboolean translucent)
315 {
316 char *filename, *subpath;
317 GtkIconSource *source; 399 GtkIconSource *source;
318 GdkPixbuf *pixbuf; 400 GdkPixbuf *pixbuf;
319 401
320 subpath = g_build_filename("pixmaps", "pidgin", dir, size, file, NULL); 402 filename = find_icon_file(theme, size, sized_icon, FALSE);
321 filename = find_file_common(subpath); 403 g_return_if_fail(filename != NULL);
322 g_free(subpath);
323 if (!filename)
324 return;
325
326 pixbuf = gdk_pixbuf_new_from_file(filename, NULL); 404 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
327 if (translucent) 405 if (translucent)
328 do_alphashift(pixbuf, pixbuf); 406 do_alphashift(pixbuf, pixbuf);
329 407
330 source = gtk_icon_source_new(); 408 source = gtk_icon_source_new();
331 gtk_icon_source_set_pixbuf(source, pixbuf); 409 gtk_icon_source_set_pixbuf(source, pixbuf);
332 gtk_icon_source_set_direction(source, GTK_TEXT_DIR_LTR); 410 gtk_icon_source_set_direction(source, GTK_TEXT_DIR_LTR);
333 gtk_icon_source_set_direction_wildcarded(source, !rtl); 411 gtk_icon_source_set_direction_wildcarded(source, !sized_icon.rtl);
334 gtk_icon_source_set_size(source, sizeid); 412 gtk_icon_source_set_size(source, sizeid);
335 gtk_icon_source_set_size_wildcarded(source, FALSE); 413 gtk_icon_source_set_size_wildcarded(source, FALSE);
336 gtk_icon_source_set_state_wildcarded(source, TRUE); 414 gtk_icon_source_set_state_wildcarded(source, TRUE);
337 gtk_icon_set_add_source(iconset, source); 415 gtk_icon_set_add_source(iconset, source);
338 gtk_icon_source_free(source); 416 gtk_icon_source_free(source);
348 gtk_icon_source_free(source); 426 gtk_icon_source_free(source);
349 } 427 }
350 g_free(filename); 428 g_free(filename);
351 g_object_unref(pixbuf); 429 g_object_unref(pixbuf);
352 430
353 if (rtl) { 431 if (sized_icon.rtl) {
354 subpath = g_build_filename("pixmaps", "pidgin", dir, size, "rtl", file, NULL); 432 filename = find_icon_file(theme, size, sized_icon, TRUE);
355 filename = find_file_common(subpath); 433 g_return_if_fail(filename != NULL);
356 g_free(subpath);
357 if (!filename)
358 return;
359 pixbuf = gdk_pixbuf_new_from_file(filename, NULL); 434 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
360 if (translucent) 435 if (translucent)
361 do_alphashift(pixbuf, pixbuf); 436 do_alphashift(pixbuf, pixbuf);
437
362 source = gtk_icon_source_new(); 438 source = gtk_icon_source_new();
363 gtk_icon_source_set_pixbuf(source, pixbuf); 439 gtk_icon_source_set_pixbuf(source, pixbuf);
440 gtk_icon_source_set_filename(source, filename);
364 gtk_icon_source_set_direction(source, GTK_TEXT_DIR_RTL); 441 gtk_icon_source_set_direction(source, GTK_TEXT_DIR_RTL);
365 gtk_icon_source_set_size(source, sizeid); 442 gtk_icon_source_set_size(source, sizeid);
366 gtk_icon_source_set_size_wildcarded(source, FALSE); 443 gtk_icon_source_set_size_wildcarded(source, FALSE);
367 gtk_icon_source_set_state_wildcarded(source, TRUE); 444 gtk_icon_source_set_state_wildcarded(source, TRUE);
368 gtk_icon_set_add_source(iconset, source); 445 gtk_icon_set_add_source(iconset, source);
370 g_object_unref(pixbuf); 447 g_object_unref(pixbuf);
371 gtk_icon_source_free(source); 448 gtk_icon_source_free(source);
372 } 449 }
373 } 450 }
374 451
452 /*****************************************************************************
453 * Public API functions
454 *****************************************************************************/
455
456 void
457 pidgin_stock_load_status_icon_theme(PidginStatusIconTheme *theme)
458 {
459 GtkIconFactory *icon_factory;
460 gint i;
461 GtkIconSet *normal;
462 GtkIconSet *translucent = NULL;
463 GtkWidget *win;
464
465 if (theme != NULL) {
466 purple_prefs_set_string(PIDGIN_PREFS_ROOT "/status/icon-theme",
467 purple_theme_get_name(PURPLE_THEME(theme)));
468 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/status/icon-theme-dir",
469 purple_theme_get_dir(PURPLE_THEME(theme)));
470 }
471 else {
472 purple_prefs_set_string(PIDGIN_PREFS_ROOT "/status/icon-theme", "");
473 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/status/icon-theme-dir", "");
474 }
475
476 icon_factory = gtk_icon_factory_new();
477
478 gtk_icon_factory_add_default(icon_factory);
479
480 win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
481 gtk_widget_realize(win);
482
483 for (i = 0; i < G_N_ELEMENTS(sized_status_icons); i++)
484 {
485 normal = gtk_icon_set_new();
486 if (sized_status_icons[i].translucent_name)
487 translucent = gtk_icon_set_new();
488
489 #define ADD_SIZED_ICON(name, size) if (sized_status_icons[i].name) { \
490 add_sized_icon(normal, name, theme, size, sized_status_icons[i], FALSE); \
491 if (sized_status_icons[i].translucent_name) \
492 add_sized_icon(translucent, name, theme, size, sized_status_icons[i], TRUE); \
493 }
494 ADD_SIZED_ICON(microscopic, "11");
495 ADD_SIZED_ICON(extra_small, "16");
496 ADD_SIZED_ICON(small, "22");
497 ADD_SIZED_ICON(medium, "32");
498 ADD_SIZED_ICON(large, "48");
499 ADD_SIZED_ICON(huge, "64");
500 #undef ADD_SIZED_ICON
501
502 gtk_icon_factory_add(icon_factory, sized_status_icons[i].name, normal);
503 gtk_icon_set_unref(normal);
504
505 if (sized_status_icons[i].translucent_name) {
506 gtk_icon_factory_add(icon_factory, sized_status_icons[i].translucent_name, translucent);
507 gtk_icon_set_unref(translucent);
508 }
509 }
510
511
512 gtk_widget_destroy(win);
513 g_object_unref(G_OBJECT(icon_factory));
514 }
515
375 void 516 void
376 pidgin_stock_init(void) 517 pidgin_stock_init(void)
377 { 518 {
378 static gboolean stock_initted = FALSE;
379 GtkIconFactory *icon_factory; 519 GtkIconFactory *icon_factory;
380 size_t i; 520 size_t i;
381 GtkWidget *win; 521 GtkWidget *win;
382 GtkIconSize microscopic, extra_small, small, medium, large, huge; 522 PidginIconThemeLoader *loader;
523 const gchar *path = NULL;
383 524
384 if (stock_initted) 525 if (stock_initted)
385 return; 526 return;
386 527
387 stock_initted = TRUE; 528 stock_initted = TRUE;
529
530 /* Setup the status icon theme */
531 loader = g_object_new(PIDGIN_TYPE_ICON_THEME_LOADER, "type", "status-icon", NULL);
532 purple_theme_manager_register_type(PURPLE_THEME_LOADER(loader));
533 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/status/icon-theme", "");
534 purple_prefs_add_path(PIDGIN_PREFS_ROOT "/status/icon-theme-dir", "");
388 535
389 /* Setup the icon factory. */ 536 /* Setup the icon factory. */
390 icon_factory = gtk_icon_factory_new(); 537 icon_factory = gtk_icon_factory_new();
391 538
392 gtk_icon_factory_add_default(icon_factory); 539 gtk_icon_factory_add_default(icon_factory);
393 540
394 /* Er, yeah, a hack, but it works. :) */ 541 /* Er, yeah, a hack, but it works. :) */
395 win = gtk_window_new(GTK_WINDOW_TOPLEVEL); 542 win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
396 gtk_widget_realize(win); 543 gtk_widget_realize(win);
397 544
545 /* All non-sized icons */
398 for (i = 0; i < G_N_ELEMENTS(stock_icons); i++) 546 for (i = 0; i < G_N_ELEMENTS(stock_icons); i++)
399 { 547 {
400 GtkIconSource *source; 548 GtkIconSource *source;
401 GtkIconSet *iconset; 549 GtkIconSet *iconset;
402 gchar *filename; 550 gchar *filename;
431 579
432 gtk_icon_set_unref(iconset); 580 gtk_icon_set_unref(iconset);
433 } 581 }
434 582
435 /* register custom icon sizes */ 583 /* register custom icon sizes */
436
437 microscopic = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC, 11, 11); 584 microscopic = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC, 11, 11);
438 extra_small = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL, 16, 16); 585 extra_small = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL, 16, 16);
439 small = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_SMALL, 22, 22); 586 small = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_SMALL, 22, 22);
440 medium = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_MEDIUM, 32, 32); 587 medium = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_MEDIUM, 32, 32);
441 large = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_LARGE, 48, 48); 588 large = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_LARGE, 48, 48);
442 huge = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_HUGE, 64, 64); 589 huge = gtk_icon_size_register(PIDGIN_ICON_SIZE_TANGO_HUGE, 64, 64);
443 590
591 /* All non-status sized icons */
444 for (i = 0; i < G_N_ELEMENTS(sized_stock_icons); i++) 592 for (i = 0; i < G_N_ELEMENTS(sized_stock_icons); i++)
445 { 593 {
446 GtkIconSet *iconset; 594 GtkIconSet *iconset = gtk_icon_set_new();
447 595
448 iconset = gtk_icon_set_new(); 596 #define ADD_SIZED_ICON(name, size) if (sized_stock_icons[i].name) \
449 597 add_sized_icon(iconset, name, NULL, size, sized_stock_icons[i], FALSE);
450 #define ADD_SIZED_ICON(name, size) do { \
451 if (sized_stock_icons[i].name) \
452 add_sized_icon(iconset, name, \
453 sized_stock_icons[i].dir, sized_stock_icons[i].rtl, \
454 size, sized_stock_icons[i].filename); \
455 } while (0)
456 ADD_SIZED_ICON(microscopic, "11"); 598 ADD_SIZED_ICON(microscopic, "11");
457 ADD_SIZED_ICON(extra_small, "16"); 599 ADD_SIZED_ICON(extra_small, "16");
458 ADD_SIZED_ICON(small, "22"); 600 ADD_SIZED_ICON(small, "22");
459 ADD_SIZED_ICON(medium, "32"); 601 ADD_SIZED_ICON(medium, "32");
460 ADD_SIZED_ICON(large, "48"); 602 ADD_SIZED_ICON(large, "48");
461 ADD_SIZED_ICON(huge, "64"); 603 ADD_SIZED_ICON(huge, "64");
462 #undef ADD_SIZED_ICON 604 #undef ADD_SIZED_ICON
463 605
464 gtk_icon_factory_add(icon_factory, sized_stock_icons[i].name, iconset); 606 gtk_icon_factory_add(icon_factory, sized_stock_icons[i].name, iconset);
465 gtk_icon_set_unref(iconset); 607 gtk_icon_set_unref(iconset);
466
467 if (sized_stock_icons[i].translucent_name) {
468 iconset = gtk_icon_set_new();
469
470 #define ADD_TRANS_ICON(name, size) do { \
471 if (sized_stock_icons[i].name) \
472 add_translucent_sized_icon(iconset, name, \
473 sized_stock_icons[i].dir, sized_stock_icons[i].rtl, \
474 size, sized_stock_icons[i].filename); \
475 } while (0)
476 ADD_TRANS_ICON(microscopic, "11");
477 ADD_TRANS_ICON(extra_small, "16");
478 ADD_TRANS_ICON(small, "22");
479 ADD_TRANS_ICON(medium, "32");
480 ADD_TRANS_ICON(large, "48");
481 ADD_TRANS_ICON(huge, "64");
482 #undef ADD_TRANS_ICON
483
484 gtk_icon_factory_add(icon_factory, sized_stock_icons[i].translucent_name, iconset);
485 gtk_icon_set_unref(iconset);
486 }
487 } 608 }
488 609
489 gtk_widget_destroy(win); 610 gtk_widget_destroy(win);
490 g_object_unref(G_OBJECT(icon_factory)); 611 g_object_unref(G_OBJECT(icon_factory));
491 612
613 /* Pre-load Status icon theme - this avoids a bug with displaying the correct icon in the tray, theme is destroyed after*/
614 if (purple_prefs_get_string(PIDGIN_PREFS_ROOT "/icon/status/theme") &&
615 (path = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/status/icon-theme-dir"))) {
616
617 PidginStatusIconTheme *theme = PIDGIN_STATUS_ICON_THEME(purple_theme_loader_build(PURPLE_THEME_LOADER(loader), path));
618 pidgin_stock_load_status_icon_theme(theme);
619 g_object_unref(G_OBJECT(theme));
620
621 } else pidgin_stock_load_status_icon_theme(NULL);
622
492 /* Register the stock items. */ 623 /* Register the stock items. */
493 gtk_stock_add_static(stock_items, G_N_ELEMENTS(stock_items)); 624 gtk_stock_add_static(stock_items, G_N_ELEMENTS(stock_items));
494 } 625 }