| 65 static void pidgin_status_box_changed(PidginStatusBox *box); |
65 static void pidgin_status_box_changed(PidginStatusBox *box); |
| 66 static void pidgin_status_box_get_preferred_height (GtkWidget *widget, |
66 static void pidgin_status_box_get_preferred_height (GtkWidget *widget, |
| 67 gint *minimum_height, gint *natural_height); |
67 gint *minimum_height, gint *natural_height); |
| 68 static gboolean pidgin_status_box_draw (GtkWidget *widget, cairo_t *cr); |
68 static gboolean pidgin_status_box_draw (GtkWidget *widget, cairo_t *cr); |
| 69 static void pidgin_status_box_size_allocate (GtkWidget *widget, GtkAllocation *allocation); |
69 static void pidgin_status_box_size_allocate (GtkWidget *widget, GtkAllocation *allocation); |
| 70 static void pidgin_status_box_redisplay_buddy_icon(PidginStatusBox *status_box); |
|
| 71 static void pidgin_status_box_forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data); |
70 static void pidgin_status_box_forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data); |
| 72 static void pidgin_status_box_popup(PidginStatusBox *box, GdkEvent *event); |
71 static void pidgin_status_box_popup(PidginStatusBox *box, GdkEvent *event); |
| 73 static void pidgin_status_box_popdown(PidginStatusBox *box, GdkEvent *event); |
72 static void pidgin_status_box_popdown(PidginStatusBox *box, GdkEvent *event); |
| 74 |
|
| 75 static void do_colorshift (GdkPixbuf *dest, GdkPixbuf *src, int shift); |
|
| 76 static void icon_choose_cb(const char *filename, gpointer data); |
|
| 77 static void remove_buddy_icon_cb(GtkWidget *w, PidginStatusBox *box); |
|
| 78 static void choose_buddy_icon_cb(GtkWidget *w, PidginStatusBox *box); |
|
| 79 |
73 |
| 80 enum { |
74 enum { |
| 81 /* A PidginStatusBoxItemType */ |
75 /* A PidginStatusBoxItemType */ |
| 82 TYPE_COLUMN, |
76 TYPE_COLUMN, |
| 83 |
77 |
| 289 update_to_reflect_account_status(status_box, account, newstatus); |
279 update_to_reflect_account_status(status_box, account, newstatus); |
| 290 else if (status_box->token_status_account == account) |
280 else if (status_box->token_status_account == account) |
| 291 status_menu_refresh_iter(status_box, TRUE); |
281 status_menu_refresh_iter(status_box, TRUE); |
| 292 } |
282 } |
| 293 |
283 |
| 294 static gboolean |
|
| 295 icon_box_press_cb(GtkWidget *widget, GdkEventButton *event, PidginStatusBox *box) |
|
| 296 { |
|
| 297 if (gdk_event_triggers_context_menu((GdkEvent *)event)) { |
|
| 298 GtkWidget *menu_item; |
|
| 299 const char *path; |
|
| 300 |
|
| 301 if (box->icon_box_menu) |
|
| 302 gtk_widget_destroy(box->icon_box_menu); |
|
| 303 |
|
| 304 box->icon_box_menu = gtk_menu_new(); |
|
| 305 |
|
| 306 pidgin_new_menu_item(box->icon_box_menu, |
|
| 307 _("Select Buddy Icon"), GTK_STOCK_ADD, |
|
| 308 G_CALLBACK(choose_buddy_icon_cb), box); |
|
| 309 |
|
| 310 menu_item = pidgin_new_menu_item(box->icon_box_menu, _("Remove"), GTK_STOCK_REMOVE, |
|
| 311 G_CALLBACK(remove_buddy_icon_cb), box); |
|
| 312 if (!(path = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon")) |
|
| 313 || !*path) |
|
| 314 gtk_widget_set_sensitive(menu_item, FALSE); |
|
| 315 |
|
| 316 gtk_menu_popup_at_pointer(GTK_MENU(box->icon_box_menu), (GdkEvent *)event); |
|
| 317 |
|
| 318 } else { |
|
| 319 choose_buddy_icon_cb(widget, box); |
|
| 320 } |
|
| 321 return FALSE; |
|
| 322 } |
|
| 323 |
|
| 324 static void |
|
| 325 icon_box_dnd_cb(GtkWidget *widget, GdkDragContext *dc, gint x, gint y, |
|
| 326 GtkSelectionData *sd, guint info, guint t, PidginStatusBox *box) |
|
| 327 { |
|
| 328 gchar *name = (gchar *) gtk_selection_data_get_data(sd); |
|
| 329 |
|
| 330 if ((gtk_selection_data_get_length(sd) >= 0) |
|
| 331 && (gtk_selection_data_get_format(sd) == 8)) { |
|
| 332 /* Well, it looks like the drag event was cool. |
|
| 333 * Let's do something with it */ |
|
| 334 if (!g_ascii_strncasecmp(name, "file://", 7)) { |
|
| 335 GError *converr = NULL; |
|
| 336 gchar *tmp, *rtmp; |
|
| 337 |
|
| 338 if(!(tmp = g_filename_from_uri(name, NULL, &converr))) { |
|
| 339 purple_debug(PURPLE_DEBUG_ERROR, "buddyicon", "%s\n", |
|
| 340 (converr ? converr->message : |
|
| 341 "g_filename_from_uri error")); |
|
| 342 return; |
|
| 343 } |
|
| 344 if ((rtmp = strchr(tmp, '\r')) || (rtmp = strchr(tmp, '\n'))) |
|
| 345 *rtmp = '\0'; |
|
| 346 icon_choose_cb(tmp, box); |
|
| 347 g_free(tmp); |
|
| 348 } |
|
| 349 gtk_drag_finish(dc, TRUE, FALSE, t); |
|
| 350 } |
|
| 351 gtk_drag_finish(dc, FALSE, FALSE, t); |
|
| 352 } |
|
| 353 |
|
| 354 static gboolean |
|
| 355 icon_box_enter_cb(GtkWidget *widget, GdkEventCrossing *event, PidginStatusBox *box) |
|
| 356 { |
|
| 357 gdk_window_set_cursor(gtk_widget_get_window(widget), box->hand_cursor); |
|
| 358 gtk_image_set_from_pixbuf(GTK_IMAGE(box->icon), box->buddy_icon_hover); |
|
| 359 return FALSE; |
|
| 360 } |
|
| 361 |
|
| 362 static gboolean |
|
| 363 icon_box_leave_cb(GtkWidget *widget, GdkEventCrossing *event, PidginStatusBox *box) |
|
| 364 { |
|
| 365 gdk_window_set_cursor(gtk_widget_get_window(widget), box->arrow_cursor); |
|
| 366 gtk_image_set_from_pixbuf(GTK_IMAGE(box->icon), box->buddy_icon) ; |
|
| 367 return FALSE; |
|
| 368 } |
|
| 369 |
|
| 370 |
|
| 371 static const GtkTargetEntry dnd_targets[] = { |
|
| 372 {"text/plain", 0, 0}, |
|
| 373 {"text/uri-list", 0, 1}, |
|
| 374 {"STRING", 0, 2} |
|
| 375 }; |
|
| 376 |
|
| 377 static void |
|
| 378 setup_icon_box(PidginStatusBox *status_box) |
|
| 379 { |
|
| 380 GdkDisplay *display; |
|
| 381 |
|
| 382 if (status_box->icon_box != NULL) |
|
| 383 return; |
|
| 384 |
|
| 385 status_box->icon = gtk_image_new(); |
|
| 386 status_box->icon_box = gtk_event_box_new(); |
|
| 387 gtk_widget_set_parent(status_box->icon_box, GTK_WIDGET(status_box)); |
|
| 388 gtk_widget_show(status_box->icon_box); |
|
| 389 |
|
| 390 gtk_widget_set_tooltip_text(status_box->icon_box, |
|
| 391 status_box->account ? _("Click to change your buddyicon for this account.") : |
|
| 392 _("Click to change your buddyicon for all accounts.")); |
|
| 393 |
|
| 394 if (status_box->account && |
|
| 395 !purple_account_get_bool(status_box->account, "use-global-buddyicon", TRUE)) |
|
| 396 { |
|
| 397 PurpleImage *img = purple_buddy_icons_find_account_icon(status_box->account); |
|
| 398 pidgin_status_box_set_buddy_icon(status_box, img); |
|
| 399 g_object_unref(img); |
|
| 400 } |
|
| 401 else |
|
| 402 { |
|
| 403 const char *filename = purple_prefs_get_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon"); |
|
| 404 PurpleImage *img = NULL; |
|
| 405 |
|
| 406 if (filename && *filename) |
|
| 407 img = purple_image_new_from_file(filename, NULL); |
|
| 408 |
|
| 409 pidgin_status_box_set_buddy_icon(status_box, img); |
|
| 410 if (img) |
|
| 411 g_object_unref(img); |
|
| 412 } |
|
| 413 |
|
| 414 display = gtk_widget_get_display(status_box->icon_box); |
|
| 415 status_box->hand_cursor = gdk_cursor_new_for_display(display, GDK_HAND2); |
|
| 416 status_box->arrow_cursor = gdk_cursor_new_for_display(display, GDK_LEFT_PTR); |
|
| 417 |
|
| 418 /* Set up DND */ |
|
| 419 gtk_drag_dest_set(status_box->icon_box, |
|
| 420 GTK_DEST_DEFAULT_MOTION | |
|
| 421 GTK_DEST_DEFAULT_DROP, |
|
| 422 dnd_targets, |
|
| 423 sizeof(dnd_targets) / sizeof(GtkTargetEntry), |
|
| 424 GDK_ACTION_COPY); |
|
| 425 |
|
| 426 g_signal_connect(G_OBJECT(status_box->icon_box), "drag_data_received", G_CALLBACK(icon_box_dnd_cb), status_box); |
|
| 427 g_signal_connect(G_OBJECT(status_box->icon_box), "enter-notify-event", G_CALLBACK(icon_box_enter_cb), status_box); |
|
| 428 g_signal_connect(G_OBJECT(status_box->icon_box), "leave-notify-event", G_CALLBACK(icon_box_leave_cb), status_box); |
|
| 429 g_signal_connect(G_OBJECT(status_box->icon_box), "button-press-event", G_CALLBACK(icon_box_press_cb), status_box); |
|
| 430 |
|
| 431 gtk_container_add(GTK_CONTAINER(status_box->icon_box), status_box->icon); |
|
| 432 gtk_widget_show(status_box->icon); |
|
| 433 } |
|
| 434 |
|
| 435 static void |
|
| 436 destroy_icon_box(PidginStatusBox *statusbox) |
|
| 437 { |
|
| 438 g_clear_pointer(&statusbox->icon_box, gtk_widget_destroy); |
|
| 439 |
|
| 440 g_clear_object(&statusbox->hand_cursor); |
|
| 441 g_clear_object(&statusbox->arrow_cursor); |
|
| 442 |
|
| 443 g_clear_object(&statusbox->buddy_icon_img); |
|
| 444 |
|
| 445 g_clear_object(&statusbox->buddy_icon); |
|
| 446 g_clear_object(&statusbox->buddy_icon_hover); |
|
| 447 |
|
| 448 g_clear_object(&statusbox->buddy_icon_sel); |
|
| 449 |
|
| 450 g_clear_pointer(&statusbox->icon_box_menu, gtk_widget_destroy); |
|
| 451 |
|
| 452 statusbox->icon = NULL; |
|
| 453 } |
|
| 454 |
|
| 455 static void |
284 static void |
| 456 pidgin_status_box_set_property(GObject *object, guint param_id, |
285 pidgin_status_box_set_property(GObject *object, guint param_id, |
| 457 const GValue *value, GParamSpec *pspec) |
286 const GValue *value, GParamSpec *pspec) |
| 458 { |
287 { |
| 459 PidginStatusBox *statusbox = PIDGIN_STATUS_BOX(object); |
288 PidginStatusBox *statusbox = PIDGIN_STATUS_BOX(object); |
| 460 |
289 |
| 461 switch (param_id) { |
290 switch (param_id) { |
| 462 case PROP_ICON_SEL: |
|
| 463 if (g_value_get_boolean(value)) { |
|
| 464 if (statusbox->account) { |
|
| 465 PurpleBuddyIconSpec *icon_spec = NULL; |
|
| 466 PurpleProtocol *protocol = |
|
| 467 purple_protocols_find(purple_account_get_protocol_id(statusbox->account)); |
|
| 468 if (protocol) |
|
| 469 icon_spec = purple_protocol_get_icon_spec(protocol); |
|
| 470 if (icon_spec && icon_spec->format != NULL) |
|
| 471 setup_icon_box(statusbox); |
|
| 472 } else { |
|
| 473 setup_icon_box(statusbox); |
|
| 474 } |
|
| 475 } else { |
|
| 476 destroy_icon_box(statusbox); |
|
| 477 } |
|
| 478 break; |
|
| 479 case PROP_ACCOUNT: |
291 case PROP_ACCOUNT: |
| 480 statusbox->account = g_value_get_pointer(value); |
292 statusbox->account = g_value_get_pointer(value); |
| 481 if (statusbox->account) |
293 if (statusbox->account) |
| 482 statusbox->token_status_account = NULL; |
294 statusbox->token_status_account = NULL; |
| 483 else |
295 else |
| 1317 if (!box->popup_in_progress) |
1110 if (!box->popup_in_progress) |
| 1318 pidgin_status_box_popup(box, (GdkEvent *)event); |
1111 pidgin_status_box_popup(box, (GdkEvent *)event); |
| 1319 else |
1112 else |
| 1320 pidgin_status_box_popdown(box, (GdkEvent *)event); |
1113 pidgin_status_box_popdown(box, (GdkEvent *)event); |
| 1321 return TRUE; |
1114 return TRUE; |
| 1322 } |
|
| 1323 |
|
| 1324 static void |
|
| 1325 buddy_icon_set_cb(const char *filename, PidginStatusBox *box) |
|
| 1326 { |
|
| 1327 PurpleImage *img = NULL; |
|
| 1328 PurpleBuddyIconSpec *icon_spec = NULL; |
|
| 1329 |
|
| 1330 if (box->account) { |
|
| 1331 PurpleProtocol *protocol = |
|
| 1332 purple_protocols_find(purple_account_get_protocol_id(box->account)); |
|
| 1333 if (protocol) |
|
| 1334 icon_spec = purple_protocol_get_icon_spec(protocol); |
|
| 1335 if (icon_spec && icon_spec->format) { |
|
| 1336 gpointer data = NULL; |
|
| 1337 size_t len = 0; |
|
| 1338 if (filename) |
|
| 1339 data = pidgin_convert_buddy_icon(protocol, filename, &len); |
|
| 1340 img = purple_buddy_icons_set_account_icon(box->account, data, len); |
|
| 1341 if (img) { |
|
| 1342 /* |
|
| 1343 * set_account_icon doesn't give us a reference, but we |
|
| 1344 * unref one below (for the other code path) |
|
| 1345 */ |
|
| 1346 g_object_ref(img); |
|
| 1347 } |
|
| 1348 |
|
| 1349 purple_account_set_buddy_icon_path(box->account, filename); |
|
| 1350 |
|
| 1351 purple_account_set_bool(box->account, "use-global-buddyicon", (filename != NULL)); |
|
| 1352 } |
|
| 1353 } else { |
|
| 1354 GList *accounts; |
|
| 1355 for (accounts = purple_accounts_get_all(); accounts != NULL; accounts = accounts->next) { |
|
| 1356 PurpleAccount *account = accounts->data; |
|
| 1357 PurpleProtocol *protocol = |
|
| 1358 purple_protocols_find(purple_account_get_protocol_id(account)); |
|
| 1359 if (protocol) |
|
| 1360 icon_spec = purple_protocol_get_icon_spec(protocol); |
|
| 1361 if (icon_spec && icon_spec->format && |
|
| 1362 purple_account_get_bool(account, "use-global-buddyicon", TRUE)) { |
|
| 1363 gpointer data = NULL; |
|
| 1364 size_t len = 0; |
|
| 1365 if (filename) |
|
| 1366 data = pidgin_convert_buddy_icon(protocol, filename, &len); |
|
| 1367 purple_buddy_icons_set_account_icon(account, data, len); |
|
| 1368 purple_account_set_buddy_icon_path(account, filename); |
|
| 1369 } |
|
| 1370 } |
|
| 1371 |
|
| 1372 /* Even if no accounts were processed, load the icon that was set. */ |
|
| 1373 if (filename != NULL) |
|
| 1374 img = purple_image_new_from_file(filename, NULL); |
|
| 1375 } |
|
| 1376 |
|
| 1377 pidgin_status_box_set_buddy_icon(box, img); |
|
| 1378 if (img) |
|
| 1379 g_object_unref(img); |
|
| 1380 } |
|
| 1381 |
|
| 1382 static void |
|
| 1383 remove_buddy_icon_cb(GtkWidget *w, PidginStatusBox *box) |
|
| 1384 { |
|
| 1385 if (box->account == NULL) |
|
| 1386 /* The pref-connect callback does the actual work */ |
|
| 1387 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon", NULL); |
|
| 1388 else |
|
| 1389 buddy_icon_set_cb(NULL, box); |
|
| 1390 |
|
| 1391 gtk_widget_destroy(box->icon_box_menu); |
|
| 1392 box->icon_box_menu = NULL; |
|
| 1393 } |
|
| 1394 |
|
| 1395 static void |
|
| 1396 choose_buddy_icon_cb(GtkWidget *w, PidginStatusBox *box) |
|
| 1397 { |
|
| 1398 if (box->buddy_icon_sel == NULL) { |
|
| 1399 box->buddy_icon_sel = pidgin_buddy_icon_chooser_new(GTK_WINDOW(gtk_widget_get_toplevel(w)), icon_choose_cb, box); |
|
| 1400 } |
|
| 1401 gtk_native_dialog_show(GTK_NATIVE_DIALOG(box->buddy_icon_sel)); |
|
| 1402 } |
|
| 1403 |
|
| 1404 static void |
|
| 1405 icon_choose_cb(const char *filename, gpointer data) |
|
| 1406 { |
|
| 1407 PidginStatusBox *box = data; |
|
| 1408 if (filename) { |
|
| 1409 if (box->account == NULL) |
|
| 1410 /* The pref-connect callback does the actual work */ |
|
| 1411 purple_prefs_set_path(PIDGIN_PREFS_ROOT "/accounts/buddyicon", filename); |
|
| 1412 else |
|
| 1413 buddy_icon_set_cb(filename, box); |
|
| 1414 } |
|
| 1415 |
|
| 1416 g_clear_object(&box->buddy_icon_sel); |
|
| 1417 } |
|
| 1418 |
|
| 1419 static void |
|
| 1420 update_buddyicon_cb(const char *name, PurplePrefType type, |
|
| 1421 gconstpointer value, gpointer data) |
|
| 1422 { |
|
| 1423 buddy_icon_set_cb(value, (PidginStatusBox*) data); |
|
| 1424 } |
1115 } |
| 1425 |
1116 |
| 1426 static void |
1117 static void |
| 1427 treeview_activate_current_selection(PidginStatusBox *status_box, GtkTreePath *path, GdkEvent *event) |
1118 treeview_activate_current_selection(PidginStatusBox *status_box, GtkTreePath *path, GdkEvent *event) |
| 1428 { |
1119 { |
| 1806 if (box_nat_height > 1) |
1494 if (box_nat_height > 1) |
| 1807 *natural_height += box_nat_height + border_width * 2; |
1495 *natural_height += box_nat_height + border_width * 2; |
| 1808 } |
1496 } |
| 1809 } |
1497 } |
| 1810 |
1498 |
| 1811 /* From gnome-panel */ |
|
| 1812 static void |
|
| 1813 do_colorshift (GdkPixbuf *dest, GdkPixbuf *src, int shift) |
|
| 1814 { |
|
| 1815 gint i, j; |
|
| 1816 gint width, height, has_alpha, srcrowstride, destrowstride; |
|
| 1817 guchar *target_pixels; |
|
| 1818 guchar *original_pixels; |
|
| 1819 guchar *pixsrc; |
|
| 1820 guchar *pixdest; |
|
| 1821 int val; |
|
| 1822 guchar r,g,b; |
|
| 1823 |
|
| 1824 has_alpha = gdk_pixbuf_get_has_alpha (src); |
|
| 1825 width = gdk_pixbuf_get_width (src); |
|
| 1826 height = gdk_pixbuf_get_height (src); |
|
| 1827 srcrowstride = gdk_pixbuf_get_rowstride (src); |
|
| 1828 destrowstride = gdk_pixbuf_get_rowstride (dest); |
|
| 1829 target_pixels = gdk_pixbuf_get_pixels (dest); |
|
| 1830 original_pixels = gdk_pixbuf_get_pixels (src); |
|
| 1831 |
|
| 1832 for (i = 0; i < height; i++) { |
|
| 1833 pixdest = target_pixels + i*destrowstride; |
|
| 1834 pixsrc = original_pixels + i*srcrowstride; |
|
| 1835 for (j = 0; j < width; j++) { |
|
| 1836 r = *(pixsrc++); |
|
| 1837 g = *(pixsrc++); |
|
| 1838 b = *(pixsrc++); |
|
| 1839 val = r + shift; |
|
| 1840 *(pixdest++) = CLAMP(val, 0, 255); |
|
| 1841 val = g + shift; |
|
| 1842 *(pixdest++) = CLAMP(val, 0, 255); |
|
| 1843 val = b + shift; |
|
| 1844 *(pixdest++) = CLAMP(val, 0, 255); |
|
| 1845 if (has_alpha) |
|
| 1846 *(pixdest++) = *(pixsrc++); |
|
| 1847 } |
|
| 1848 } |
|
| 1849 } |
|
| 1850 |
|
| 1851 static void |
1499 static void |
| 1852 pidgin_status_box_size_allocate(GtkWidget *widget, |
1500 pidgin_status_box_size_allocate(GtkWidget *widget, |
| 1853 GtkAllocation *allocation) |
1501 GtkAllocation *allocation) |
| 1854 { |
1502 { |
| 1855 PidginStatusBox *status_box = PIDGIN_STATUS_BOX(widget); |
1503 PidginStatusBox *status_box = PIDGIN_STATUS_BOX(widget); |
| 1856 GtkRequisition req = {0,0}; |
1504 GtkRequisition req = {0,0}; |
| 1857 GtkAllocation parent_alc, box_alc, icon_alc; |
1505 GtkAllocation parent_alc, box_alc; |
| 1858 gint border_width = gtk_container_get_border_width(GTK_CONTAINER (widget)); |
1506 gint border_width = gtk_container_get_border_width(GTK_CONTAINER (widget)); |
| 1859 |
1507 |
| 1860 gtk_widget_get_preferred_size(status_box->toggle_button, NULL, &req); |
1508 gtk_widget_get_preferred_size(status_box->toggle_button, NULL, &req); |
| 1861 /* Make this icon the same size as other buddy icons in the list; unless it already wants to be bigger */ |
1509 /* Make this icon the same size as other buddy icons in the list; unless it already wants to be bigger */ |
| 1862 |
1510 |
| 2062 return; |
1678 return; |
| 2063 status_box->connecting = connecting; |
1679 status_box->connecting = connecting; |
| 2064 pidgin_status_box_refresh(status_box); |
1680 pidgin_status_box_refresh(status_box); |
| 2065 } |
1681 } |
| 2066 |
1682 |
| 2067 static void |
|
| 2068 pixbuf_size_prepared_cb(GdkPixbufLoader *loader, int width, int height, gpointer data) |
|
| 2069 { |
|
| 2070 int w, h; |
|
| 2071 GtkIconSize icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MEDIUM); |
|
| 2072 gtk_icon_size_lookup(icon_size, &w, &h); |
|
| 2073 if (height > width) |
|
| 2074 w = width * h / height; |
|
| 2075 else if (width > height) |
|
| 2076 h = height * w / width; |
|
| 2077 gdk_pixbuf_loader_set_size(loader, w, h); |
|
| 2078 } |
|
| 2079 |
|
| 2080 static void |
|
| 2081 pidgin_status_box_redisplay_buddy_icon(PidginStatusBox *status_box) |
|
| 2082 { |
|
| 2083 |
|
| 2084 /* This is sometimes called before the box is shown, and we will not have a size */ |
|
| 2085 if (status_box->icon_size <= 0) |
|
| 2086 return; |
|
| 2087 |
|
| 2088 if (status_box->buddy_icon) |
|
| 2089 g_object_unref(status_box->buddy_icon); |
|
| 2090 if (status_box->buddy_icon_hover) |
|
| 2091 g_object_unref(status_box->buddy_icon_hover); |
|
| 2092 status_box->buddy_icon = NULL; |
|
| 2093 status_box->buddy_icon_hover = NULL; |
|
| 2094 |
|
| 2095 if (status_box->buddy_icon_img != NULL) |
|
| 2096 { |
|
| 2097 GdkPixbufLoader *loader; |
|
| 2098 GError *error = NULL; |
|
| 2099 |
|
| 2100 loader = gdk_pixbuf_loader_new(); |
|
| 2101 |
|
| 2102 g_signal_connect(G_OBJECT(loader), "size-prepared", G_CALLBACK(pixbuf_size_prepared_cb), NULL); |
|
| 2103 if (!gdk_pixbuf_loader_write(loader, |
|
| 2104 purple_image_get_data(status_box->buddy_icon_img), |
|
| 2105 purple_image_get_data_size(status_box->buddy_icon_img), |
|
| 2106 &error) || error) |
|
| 2107 { |
|
| 2108 purple_debug_warning("gtkstatusbox", |
|
| 2109 "gdk_pixbuf_loader_write() failed with size=%" |
|
| 2110 G_GSIZE_FORMAT ": %s", purple_image_get_data_size( |
|
| 2111 status_box->buddy_icon_img), |
|
| 2112 error ? error->message : "(no error message)"); |
|
| 2113 if (error) |
|
| 2114 g_error_free(error); |
|
| 2115 } else if (!gdk_pixbuf_loader_close(loader, &error) || error) { |
|
| 2116 purple_debug_warning("gtkstatusbox", |
|
| 2117 "gdk_pixbuf_loader_close() failed for image of " |
|
| 2118 "size %" G_GSIZE_FORMAT ": %s", |
|
| 2119 purple_image_get_data_size(status_box->buddy_icon_img), |
|
| 2120 error ? error->message : "(no error message)"); |
|
| 2121 if (error) |
|
| 2122 g_error_free(error); |
|
| 2123 } else { |
|
| 2124 GdkPixbuf *buf, *scale; |
|
| 2125 int scale_width, scale_height; |
|
| 2126 |
|
| 2127 buf = gdk_pixbuf_loader_get_pixbuf(loader); |
|
| 2128 scale_width = gdk_pixbuf_get_width(buf); |
|
| 2129 scale_height = gdk_pixbuf_get_height(buf); |
|
| 2130 scale = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, scale_width, scale_height); |
|
| 2131 gdk_pixbuf_fill(scale, 0x00000000); |
|
| 2132 gdk_pixbuf_copy_area(buf, 0, 0, scale_width, scale_height, scale, 0, 0); |
|
| 2133 if (pidgin_gdk_pixbuf_is_opaque(scale)) |
|
| 2134 pidgin_gdk_pixbuf_make_round(scale); |
|
| 2135 status_box->buddy_icon = scale; |
|
| 2136 } |
|
| 2137 |
|
| 2138 g_object_unref(loader); |
|
| 2139 } |
|
| 2140 |
|
| 2141 if (status_box->buddy_icon == NULL) |
|
| 2142 { |
|
| 2143 /* Show a placeholder icon */ |
|
| 2144 GtkIconSize icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_SMALL); |
|
| 2145 status_box->buddy_icon = gtk_widget_render_icon(GTK_WIDGET(status_box), |
|
| 2146 PIDGIN_STOCK_TOOLBAR_SELECT_AVATAR, |
|
| 2147 icon_size, "PidginStatusBox"); |
|
| 2148 } |
|
| 2149 |
|
| 2150 if (status_box->buddy_icon != NULL) { |
|
| 2151 status_box->icon_opaque = pidgin_gdk_pixbuf_is_opaque(status_box->buddy_icon); |
|
| 2152 gtk_image_set_from_pixbuf(GTK_IMAGE(status_box->icon), status_box->buddy_icon); |
|
| 2153 status_box->buddy_icon_hover = gdk_pixbuf_copy(status_box->buddy_icon); |
|
| 2154 do_colorshift(status_box->buddy_icon_hover, status_box->buddy_icon_hover, 32); |
|
| 2155 gtk_widget_queue_resize(GTK_WIDGET(status_box)); |
|
| 2156 } |
|
| 2157 } |
|
| 2158 |
|
| 2159 void |
|
| 2160 pidgin_status_box_set_buddy_icon(PidginStatusBox *status_box, PurpleImage *img) |
|
| 2161 { |
|
| 2162 if (status_box->buddy_icon_img) |
|
| 2163 g_object_unref(status_box->buddy_icon_img); |
|
| 2164 status_box->buddy_icon_img = img; |
|
| 2165 if (status_box->buddy_icon_img != NULL) |
|
| 2166 g_object_ref(status_box->buddy_icon_img); |
|
| 2167 |
|
| 2168 pidgin_status_box_redisplay_buddy_icon(status_box); |
|
| 2169 } |
|
| 2170 |
|
| 2171 void |
1683 void |
| 2172 pidgin_status_box_pulse_connecting(PidginStatusBox *status_box) |
1684 pidgin_status_box_pulse_connecting(PidginStatusBox *status_box) |
| 2173 { |
1685 { |
| 2174 if (!status_box) |
1686 if (!status_box) |
| 2175 return; |
1687 return; |