Mercurial > pidgin.yaz
comparison pidgin/gtkutils.c @ 16483:5e47b3427b28
propagate from branch 'im.pidgin.rlaager.gaim_migration' (head dcc40d46afbe3f87cc674e4fb1526ac722bc35cb)
to branch 'im.pidgin.pidgin' (head 0ef5b6c44115778e329fd628324124f872f5253b)
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Fri, 27 Apr 2007 02:14:44 +0000 |
parents | 08db93bbd798 24bbd7e46bfe |
children | 814be4aa9dc6 |
comparison
equal
deleted
inserted
replaced
16467:b2044e10915a | 16483:5e47b3427b28 |
---|---|
76 { | 76 { |
77 g_idle_add(url_clicked_idle_cb, g_strdup(uri)); | 77 g_idle_add(url_clicked_idle_cb, g_strdup(uri)); |
78 } | 78 } |
79 | 79 |
80 static GtkIMHtmlFuncs gtkimhtml_cbs = { | 80 static GtkIMHtmlFuncs gtkimhtml_cbs = { |
81 (GtkIMHtmlGetImageFunc)purple_imgstore_get, | 81 (GtkIMHtmlGetImageFunc)purple_imgstore_find_by_id, |
82 (GtkIMHtmlGetImageDataFunc)purple_imgstore_get_data, | 82 (GtkIMHtmlGetImageDataFunc)purple_imgstore_get_data, |
83 (GtkIMHtmlGetImageSizeFunc)purple_imgstore_get_size, | 83 (GtkIMHtmlGetImageSizeFunc)purple_imgstore_get_size, |
84 (GtkIMHtmlGetImageFilenameFunc)purple_imgstore_get_filename, | 84 (GtkIMHtmlGetImageFilenameFunc)purple_imgstore_get_filename, |
85 purple_imgstore_ref, | 85 purple_imgstore_ref_by_id, |
86 purple_imgstore_unref, | 86 purple_imgstore_unref_by_id, |
87 }; | 87 }; |
88 | 88 |
89 void | 89 void |
90 pidgin_setup_imhtml(GtkWidget *imhtml) | 90 pidgin_setup_imhtml(GtkWidget *imhtml) |
91 { | 91 { |
1348 g_error_free(err); | 1348 g_error_free(err); |
1349 g_free(str); | 1349 g_free(str); |
1350 | 1350 |
1351 return; | 1351 return; |
1352 } | 1352 } |
1353 id = purple_imgstore_add(filedata, size, data->filename); | 1353 id = purple_imgstore_add_with_id(filedata, size, data->filename); |
1354 g_free(filedata); | |
1355 | 1354 |
1356 gtk_text_buffer_get_iter_at_mark(GTK_IMHTML(gtkconv->entry)->text_buffer, &iter, | 1355 gtk_text_buffer_get_iter_at_mark(GTK_IMHTML(gtkconv->entry)->text_buffer, &iter, |
1357 gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer)); | 1356 gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer)); |
1358 gtk_imhtml_insert_image_at_iter(GTK_IMHTML(gtkconv->entry), id, &iter); | 1357 gtk_imhtml_insert_image_at_iter(GTK_IMHTML(gtkconv->entry), id, &iter); |
1359 purple_imgstore_unref(id); | 1358 purple_imgstore_unref_by_id(id); |
1360 | 1359 |
1361 break; | 1360 break; |
1362 } | 1361 } |
1363 free(data->filename); | 1362 free(data->filename); |
1364 free(data->who); | 1363 free(data->who); |
2416 return TRUE; | 2415 return TRUE; |
2417 return FALSE; | 2416 return FALSE; |
2418 } | 2417 } |
2419 #endif | 2418 #endif |
2420 | 2419 |
2421 char * | 2420 gpointer |
2422 pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path) | 2421 pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len) |
2423 { | 2422 { |
2424 PurplePluginProtocolInfo *prpl_info; | 2423 PurplePluginProtocolInfo *prpl_info; |
2425 #if GTK_CHECK_VERSION(2,2,0) | 2424 #if GTK_CHECK_VERSION(2,2,0) |
2426 char **prpl_formats; | 2425 char **prpl_formats; |
2427 int width, height; | 2426 int width, height; |
2428 char **pixbuf_formats = NULL; | 2427 char **pixbuf_formats = NULL; |
2429 struct stat st; | |
2430 GdkPixbufFormat *format; | 2428 GdkPixbufFormat *format; |
2431 GdkPixbuf *pixbuf; | 2429 GdkPixbuf *pixbuf; |
2432 #if !GTK_CHECK_VERSION(2,4,0) | 2430 #if !GTK_CHECK_VERSION(2,4,0) |
2433 GdkPixbufLoader *loader; | 2431 GdkPixbufLoader *loader; |
2434 #endif | 2432 #endif |
2435 #endif | 2433 #endif |
2436 gchar *contents; | 2434 gchar *contents; |
2437 gsize length; | 2435 gsize length; |
2438 const char *dirname; | |
2439 char *random; | |
2440 char *filename; | |
2441 | 2436 |
2442 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); | 2437 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); |
2443 | 2438 |
2444 g_return_val_if_fail(prpl_info->icon_spec.format != NULL, NULL); | 2439 g_return_val_if_fail(prpl_info->icon_spec.format != NULL, NULL); |
2445 | 2440 |
2446 dirname = purple_buddy_icons_get_cache_dir(); | |
2447 if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) { | |
2448 purple_debug_info("buddyicon", "Creating icon cache directory.\n"); | |
2449 | |
2450 if (g_mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0) { | |
2451 purple_debug_error("buddyicon", | |
2452 "Unable to create directory %s: %s\n", | |
2453 dirname, strerror(errno)); | |
2454 return NULL; | |
2455 } | |
2456 } | |
2457 | |
2458 random = g_strdup_printf("%x", g_random_int()); | |
2459 filename = g_build_filename(dirname, random, NULL); | |
2460 | 2441 |
2461 #if GTK_CHECK_VERSION(2,2,0) | 2442 #if GTK_CHECK_VERSION(2,2,0) |
2462 #if GTK_CHECK_VERSION(2,4,0) | 2443 #if GTK_CHECK_VERSION(2,4,0) |
2463 format = gdk_pixbuf_get_file_info(path, &width, &height); | 2444 format = gdk_pixbuf_get_file_info(path, &width, &height); |
2464 #else | 2445 #else |
2485 prpl_info->icon_spec.max_width >= width && | 2466 prpl_info->icon_spec.max_width >= width && |
2486 prpl_info->icon_spec.min_height <= height && | 2467 prpl_info->icon_spec.min_height <= height && |
2487 prpl_info->icon_spec.max_height >= height))) /* The icon is the correct size */ | 2468 prpl_info->icon_spec.max_height >= height))) /* The icon is the correct size */ |
2488 #endif | 2469 #endif |
2489 { | 2470 { |
2490 FILE *image; | |
2491 | |
2492 #if GTK_CHECK_VERSION(2,2,0) | 2471 #if GTK_CHECK_VERSION(2,2,0) |
2493 g_strfreev(prpl_formats); | 2472 g_strfreev(prpl_formats); |
2494 g_strfreev(pixbuf_formats); | 2473 g_strfreev(pixbuf_formats); |
2495 #endif | 2474 #endif |
2496 | 2475 /* We don't need to scale the image. */ |
2497 /* We don't need to scale the image, so copy it to the cache folder verbatim */ | |
2498 | 2476 |
2499 contents = NULL; | 2477 contents = NULL; |
2500 if (!g_file_get_contents(path, &contents, &length, NULL) || | 2478 if (!g_file_get_contents(path, &contents, &length, NULL)) |
2501 (image = g_fopen(filename, "wb")) == NULL) | |
2502 { | 2479 { |
2503 g_free(random); | |
2504 g_free(filename); | |
2505 g_free(contents); | 2480 g_free(contents); |
2506 #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0) | |
2507 g_object_unref(G_OBJECT(pixbuf)); | |
2508 #endif | |
2509 return NULL; | |
2510 } | |
2511 | |
2512 if (fwrite(contents, 1, length, image) != length) | |
2513 { | |
2514 fclose(image); | |
2515 g_unlink(filename); | |
2516 | |
2517 g_free(random); | |
2518 g_free(filename); | |
2519 g_free(contents); | |
2520 #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0) | |
2521 g_object_unref(G_OBJECT(pixbuf)); | |
2522 #endif | |
2523 return NULL; | |
2524 } | |
2525 fclose(image); | |
2526 g_free(contents); | |
2527 | |
2528 #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0) | 2481 #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0) |
2529 g_object_unref(G_OBJECT(pixbuf)); | 2482 g_object_unref(G_OBJECT(pixbuf)); |
2530 #endif | 2483 #endif |
2484 return NULL; | |
2485 } | |
2531 } | 2486 } |
2532 #if GTK_CHECK_VERSION(2,2,0) | 2487 #if GTK_CHECK_VERSION(2,2,0) |
2533 else | 2488 else |
2534 { | 2489 { |
2535 int i; | 2490 int i; |
2536 GError *error = NULL; | 2491 GError *error = NULL; |
2537 GdkPixbuf *scale; | 2492 GdkPixbuf *scale; |
2538 gboolean success = FALSE; | 2493 gboolean success = FALSE; |
2494 char *filename = NULL; | |
2539 | 2495 |
2540 g_strfreev(pixbuf_formats); | 2496 g_strfreev(pixbuf_formats); |
2541 | 2497 |
2542 pixbuf = gdk_pixbuf_new_from_file(path, &error); | 2498 pixbuf = gdk_pixbuf_new_from_file(path, &error); |
2543 if (error) { | 2499 if (error) { |
2544 purple_debug_error("buddyicon", "Could not open icon for conversion: %s\n", error->message); | 2500 purple_debug_error("buddyicon", "Could not open icon for conversion: %s\n", error->message); |
2545 g_error_free(error); | 2501 g_error_free(error); |
2546 g_free(random); | |
2547 g_free(filename); | |
2548 g_strfreev(prpl_formats); | 2502 g_strfreev(prpl_formats); |
2549 return NULL; | 2503 return NULL; |
2550 } | 2504 } |
2551 | 2505 |
2552 if ((prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_SEND) && | 2506 if ((prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_SEND) && |
2565 g_object_unref(G_OBJECT(pixbuf)); | 2519 g_object_unref(G_OBJECT(pixbuf)); |
2566 pixbuf = scale; | 2520 pixbuf = scale; |
2567 } | 2521 } |
2568 | 2522 |
2569 for (i = 0; prpl_formats[i]; i++) { | 2523 for (i = 0; prpl_formats[i]; i++) { |
2524 FILE *fp; | |
2525 | |
2526 g_free(filename); | |
2527 fp = purple_mkstemp(&filename, TRUE); | |
2528 if (!fp) | |
2529 { | |
2530 g_free(filename); | |
2531 return NULL; | |
2532 } | |
2533 fclose(fp); | |
2534 | |
2570 purple_debug_info("buddyicon", "Converting buddy icon to %s as %s\n", prpl_formats[i], filename); | 2535 purple_debug_info("buddyicon", "Converting buddy icon to %s as %s\n", prpl_formats[i], filename); |
2571 /* The "compression" param wasn't supported until gdk-pixbuf 2.8. | 2536 /* The "compression" param wasn't supported until gdk-pixbuf 2.8. |
2572 * Using it in previous versions causes the save to fail (and an assert message). */ | 2537 * Using it in previous versions causes the save to fail (and an assert message). */ |
2573 if ((gdk_pixbuf_major_version > 2 || (gdk_pixbuf_major_version == 2 | 2538 if ((gdk_pixbuf_major_version > 2 || (gdk_pixbuf_major_version == 2 |
2574 && gdk_pixbuf_minor_version >= 8)) | 2539 && gdk_pixbuf_minor_version >= 8)) |
2593 } | 2558 } |
2594 g_strfreev(prpl_formats); | 2559 g_strfreev(prpl_formats); |
2595 g_object_unref(G_OBJECT(pixbuf)); | 2560 g_object_unref(G_OBJECT(pixbuf)); |
2596 if (!success) { | 2561 if (!success) { |
2597 purple_debug_error("buddyicon", "Could not convert icon to usable format.\n"); | 2562 purple_debug_error("buddyicon", "Could not convert icon to usable format.\n"); |
2598 g_free(random); | 2563 return NULL; |
2564 } | |
2565 | |
2566 contents = NULL; | |
2567 if (!g_file_get_contents(filename, &contents, &length, NULL)) | |
2568 { | |
2569 purple_debug_error("buddyicon", | |
2570 "Could not read '%s', which we just wrote to disk.\n", | |
2571 filename); | |
2572 | |
2573 g_free(contents); | |
2599 g_free(filename); | 2574 g_free(filename); |
2600 return NULL; | 2575 return NULL; |
2601 } | 2576 } |
2602 } | 2577 |
2603 | 2578 g_unlink(filename); |
2604 if (g_stat(filename, &st) != 0) { | |
2605 purple_debug_error("buddyicon", | |
2606 "Could not stat '%s', which we just wrote to disk: %s\n", | |
2607 filename, strerror(errno)); | |
2608 g_free(random); | |
2609 g_free(filename); | 2579 g_free(filename); |
2610 return NULL; | 2580 } |
2611 } | 2581 |
2612 | 2582 /* Check the image size */ |
2613 /* Check the file size */ | |
2614 /* | 2583 /* |
2615 * TODO: If the file is too big, it would be cool if we checked if | 2584 * TODO: If the file is too big, it would be cool if we checked if |
2616 * the prpl supported jpeg, and then we could convert to that | 2585 * the prpl supported jpeg, and then we could convert to that |
2617 * and use a lower quality setting. | 2586 * and use a lower quality setting. |
2618 */ | 2587 */ |
2619 if ((prpl_info->icon_spec.max_filesize != 0) && | 2588 if ((prpl_info->icon_spec.max_filesize != 0) && |
2620 (st.st_size > prpl_info->icon_spec.max_filesize)) | 2589 (length > prpl_info->icon_spec.max_filesize)) |
2621 { | 2590 { |
2622 gchar *tmp; | 2591 gchar *tmp; |
2623 tmp = g_strdup_printf(_("The file '%s' is too large for %s. Please try a smaller image.\n"), | 2592 tmp = g_strdup_printf(_("The file '%s' is too large for %s. Please try a smaller image.\n"), |
2624 path, plugin->info->name); | 2593 path, plugin->info->name); |
2625 purple_notify_error(NULL, _("Icon Error"), | 2594 purple_notify_error(NULL, _("Icon Error"), |
2626 _("Could not set icon"), tmp); | 2595 _("Could not set icon"), tmp); |
2627 purple_debug_info("buddyicon", | 2596 purple_debug_info("buddyicon", |
2628 "'%s' was converted to an image which is %" G_GSIZE_FORMAT | 2597 "'%s' was converted to an image which is %" G_GSIZE_FORMAT |
2629 " bytes, but the maximum icon size for %s is %" G_GSIZE_FORMAT | 2598 " bytes, but the maximum icon size for %s is %" G_GSIZE_FORMAT |
2630 " bytes\n", path, st.st_size, plugin->info->name, | 2599 " bytes\n", path, length, plugin->info->name, |
2631 prpl_info->icon_spec.max_filesize); | 2600 prpl_info->icon_spec.max_filesize); |
2632 g_free(tmp); | 2601 g_free(tmp); |
2633 g_free(random); | |
2634 g_free(filename); | |
2635 return NULL; | 2602 return NULL; |
2636 } | 2603 } |
2637 | 2604 |
2638 g_free(filename); | 2605 if (len) |
2639 return random; | 2606 *len = length; |
2607 return contents; | |
2640 #else | 2608 #else |
2641 /* | 2609 /* |
2642 * The chosen icon wasn't the right size, and we're using | 2610 * The chosen icon wasn't the right size, and we're using |
2643 * GTK+ 2.0 so we can't scale it. | 2611 * GTK+ 2.0 so we can't scale it. |
2644 */ | 2612 */ |
2787 } | 2755 } |
2788 #endif /* ! Gtk 2.6.0 */ | 2756 #endif /* ! Gtk 2.6.0 */ |
2789 | 2757 |
2790 void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename) | 2758 void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename) |
2791 { | 2759 { |
2792 PurpleConversation *conv; | |
2793 PurpleBuddy *buddy; | 2760 PurpleBuddy *buddy; |
2794 PurpleBlistNode *node; | 2761 PurpleContact *contact; |
2795 char *path = NULL; | 2762 gpointer data = NULL; |
2763 size_t len = 0; | |
2796 | 2764 |
2797 buddy = purple_find_buddy(account, who); | 2765 buddy = purple_find_buddy(account, who); |
2798 if (!buddy) { | 2766 if (!buddy) { |
2799 purple_debug_info("custom-icon", "You can only set custom icon for someone in your buddylist.\n"); | 2767 purple_debug_info("custom-icon", "You can only set custom icon for someone in your buddylist.\n"); |
2800 return; | 2768 return; |
2801 } | 2769 } |
2802 | 2770 |
2803 node = (PurpleBlistNode*)purple_buddy_get_contact(buddy); | 2771 contact = purple_buddy_get_contact(buddy); |
2804 path = (char*)purple_blist_node_get_string(node, "custom_buddy_icon"); | |
2805 if (path) { | |
2806 struct stat st; | |
2807 if (g_stat(path, &st) == 0) | |
2808 g_unlink(path); | |
2809 path = NULL; | |
2810 } | |
2811 | 2772 |
2812 if (filename) { | 2773 if (filename) { |
2813 char *newfile; | 2774 const char *prpl_id = purple_account_get_protocol_id(account); |
2814 | 2775 PurplePlugin *prpl = purple_find_prpl(prpl_id); |
2815 newfile = pidgin_convert_buddy_icon(purple_find_prpl(purple_account_get_protocol_id(account)), | 2776 |
2816 filename); | 2777 data = pidgin_convert_buddy_icon(prpl, filename, &len); |
2817 path = purple_buddy_icons_get_full_path(newfile); | 2778 |
2818 g_free(newfile); | 2779 /* We don't want to delete the old icon if the new one didn't load. */ |
2819 } | 2780 if (data == NULL) |
2820 | 2781 return; |
2821 purple_blist_node_set_string(node, "custom_buddy_icon", path); | 2782 } |
2822 g_free(path); | 2783 |
2823 | 2784 purple_buddy_icons_set_custom_icon(contact, data, len); |
2824 /* Update the conversation */ | |
2825 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account); | |
2826 if (conv) | |
2827 purple_conversation_update(conv, PURPLE_CONV_UPDATE_ICON); | |
2828 | |
2829 /* Update the buddylist */ | |
2830 if (buddy) | |
2831 purple_blist_update_buddy_icon(buddy); | |
2832 } | 2785 } |
2833 | 2786 |
2834 char *pidgin_make_pretty_arrows(const char *str) | 2787 char *pidgin_make_pretty_arrows(const char *str) |
2835 { | 2788 { |
2836 char *ret; | 2789 char *ret; |