pidgin/gtkutils.c

changeset 16575
c7f80fead80f
parent 16545
5188ffbaeb6e
child 16643
f9a30c6f74ff
equal deleted inserted replaced
16529:1d0da9270ff9 16575:c7f80fead80f
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);
1452 purple_request_choice(NULL, NULL, 1451 purple_request_choice(NULL, NULL,
1453 _("You have dragged an image"), 1452 _("You have dragged an image"),
1454 _("You can send this image as a file transfer, " 1453 _("You can send this image as a file transfer, "
1455 "embed it into this message, or use it as the buddy icon for this user."), 1454 "embed it into this message, or use it as the buddy icon for this user."),
1456 DND_FILE_TRANSFER, "OK", (GCallback)dnd_image_ok_callback, 1455 DND_FILE_TRANSFER, "OK", (GCallback)dnd_image_ok_callback,
1457 "Cancel", (GCallback)dnd_image_cancel_callback, data, 1456 "Cancel", (GCallback)dnd_image_cancel_callback,
1458 _("Set as buddy icon"), DND_BUDDY_ICON, 1457 account, who, NULL,
1458 data,
1459 _("Set as buddy icon"), DND_BUDDY_ICON,
1459 _("Send image file"), DND_FILE_TRANSFER, 1460 _("Send image file"), DND_FILE_TRANSFER,
1460 _("Insert in message"), DND_IM_IMAGE, NULL); 1461 _("Insert in message"), DND_IM_IMAGE,
1462 NULL);
1461 else if (!(im || ft)) 1463 else if (!(im || ft))
1462 purple_request_yes_no(NULL, NULL, _("You have dragged an image"), 1464 purple_request_yes_no(NULL, NULL, _("You have dragged an image"),
1463 _("Would you like to set it as the buddy icon for this user?"), 1465 _("Would you like to set it as the buddy icon for this user?"),
1464 0, data, (GCallback)dnd_set_icon_ok_cb, (GCallback)dnd_set_icon_cancel_cb); 1466 0,
1467 account, who, NULL,
1468 data, (GCallback)dnd_set_icon_ok_cb, (GCallback)dnd_set_icon_cancel_cb);
1465 else 1469 else
1466 purple_request_choice(NULL, NULL, 1470 purple_request_choice(NULL, NULL,
1467 _("You have dragged an image"), 1471 _("You have dragged an image"),
1468 ft ? _("You can send this image as a file transfer or " 1472 (ft ? _("You can send this image as a file transfer or "
1469 "embed it into this message, or use it as the buddy icon for this user.") : 1473 "embed it into this message, or use it as the buddy icon for this user.") :
1470 _("You can insert this image into this message, or use it as the buddy icon for this user"), 1474 _("You can insert this image into this message, or use it as the buddy icon for this user")),
1471 ft ? DND_FILE_TRANSFER : DND_IM_IMAGE, "OK", (GCallback)dnd_image_ok_callback, 1475 (ft ? DND_FILE_TRANSFER : DND_IM_IMAGE),
1472 "Cancel", (GCallback)dnd_image_cancel_callback, data, 1476 "OK", (GCallback)dnd_image_ok_callback,
1477 "Cancel", (GCallback)dnd_image_cancel_callback,
1478 account, who, NULL,
1479 data,
1473 _("Set as buddy icon"), DND_BUDDY_ICON, 1480 _("Set as buddy icon"), DND_BUDDY_ICON,
1474 ft ? _("Send image file") : _("Insert in message"), ft ? DND_FILE_TRANSFER : DND_IM_IMAGE, NULL); 1481 (ft ? _("Send image file") : _("Insert in message")), (ft ? DND_FILE_TRANSFER : DND_IM_IMAGE),
1482 NULL);
1475 return; 1483 return;
1476 } 1484 }
1477 1485
1478 #ifndef _WIN32 1486 #ifndef _WIN32
1479 /* Are we trying to send a .desktop file? */ 1487 /* Are we trying to send a .desktop file? */
2407 return TRUE; 2415 return TRUE;
2408 return FALSE; 2416 return FALSE;
2409 } 2417 }
2410 #endif 2418 #endif
2411 2419
2412 char * 2420 gpointer
2413 pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path) 2421 pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len)
2414 { 2422 {
2415 PurplePluginProtocolInfo *prpl_info; 2423 PurplePluginProtocolInfo *prpl_info;
2416 #if GTK_CHECK_VERSION(2,2,0) 2424 #if GTK_CHECK_VERSION(2,2,0)
2417 char **prpl_formats; 2425 char **prpl_formats;
2418 int width, height; 2426 int width, height;
2419 char **pixbuf_formats = NULL; 2427 char **pixbuf_formats = NULL;
2420 struct stat st;
2421 GdkPixbufFormat *format; 2428 GdkPixbufFormat *format;
2422 GdkPixbuf *pixbuf; 2429 GdkPixbuf *pixbuf;
2423 #if !GTK_CHECK_VERSION(2,4,0) 2430 #if !GTK_CHECK_VERSION(2,4,0)
2424 GdkPixbufLoader *loader; 2431 GdkPixbufLoader *loader;
2425 #endif 2432 #endif
2426 #endif 2433 #endif
2427 gchar *contents; 2434 gchar *contents;
2428 gsize length; 2435 gsize length;
2429 const char *dirname;
2430 char *random;
2431 char *filename;
2432 2436
2433 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); 2437 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
2434 2438
2435 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);
2436 2440
2437 dirname = purple_buddy_icons_get_cache_dir();
2438 if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) {
2439 purple_debug_info("buddyicon", "Creating icon cache directory.\n");
2440
2441 if (g_mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR) < 0) {
2442 purple_debug_error("buddyicon",
2443 "Unable to create directory %s: %s\n",
2444 dirname, strerror(errno));
2445 return NULL;
2446 }
2447 }
2448
2449 random = g_strdup_printf("%x", g_random_int());
2450 filename = g_build_filename(dirname, random, NULL);
2451 2441
2452 #if GTK_CHECK_VERSION(2,2,0) 2442 #if GTK_CHECK_VERSION(2,2,0)
2453 #if GTK_CHECK_VERSION(2,4,0) 2443 #if GTK_CHECK_VERSION(2,4,0)
2454 format = gdk_pixbuf_get_file_info(path, &width, &height); 2444 format = gdk_pixbuf_get_file_info(path, &width, &height);
2455 #else 2445 #else
2476 prpl_info->icon_spec.max_width >= width && 2466 prpl_info->icon_spec.max_width >= width &&
2477 prpl_info->icon_spec.min_height <= height && 2467 prpl_info->icon_spec.min_height <= height &&
2478 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 */
2479 #endif 2469 #endif
2480 { 2470 {
2481 FILE *image;
2482
2483 #if GTK_CHECK_VERSION(2,2,0) 2471 #if GTK_CHECK_VERSION(2,2,0)
2484 g_strfreev(prpl_formats); 2472 g_strfreev(prpl_formats);
2485 g_strfreev(pixbuf_formats); 2473 g_strfreev(pixbuf_formats);
2486 #endif 2474 #endif
2487 2475 /* We don't need to scale the image. */
2488 /* We don't need to scale the image, so copy it to the cache folder verbatim */
2489 2476
2490 contents = NULL; 2477 contents = NULL;
2491 if (!g_file_get_contents(path, &contents, &length, NULL) || 2478 if (!g_file_get_contents(path, &contents, &length, NULL))
2492 (image = g_fopen(filename, "wb")) == NULL)
2493 { 2479 {
2494 g_free(random);
2495 g_free(filename);
2496 g_free(contents); 2480 g_free(contents);
2497 #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0)
2498 g_object_unref(G_OBJECT(pixbuf));
2499 #endif
2500 return NULL;
2501 }
2502
2503 if (fwrite(contents, 1, length, image) != length)
2504 {
2505 fclose(image);
2506 g_unlink(filename);
2507
2508 g_free(random);
2509 g_free(filename);
2510 g_free(contents);
2511 #if GTK_CHECK_VERSION(2,2,0) && !GTK_CHECK_VERSION(2,4,0)
2512 g_object_unref(G_OBJECT(pixbuf));
2513 #endif
2514 return NULL;
2515 }
2516 fclose(image);
2517 g_free(contents);
2518
2519 #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)
2520 g_object_unref(G_OBJECT(pixbuf)); 2482 g_object_unref(G_OBJECT(pixbuf));
2521 #endif 2483 #endif
2484 return NULL;
2485 }
2522 } 2486 }
2523 #if GTK_CHECK_VERSION(2,2,0) 2487 #if GTK_CHECK_VERSION(2,2,0)
2524 else 2488 else
2525 { 2489 {
2526 int i; 2490 int i;
2527 GError *error = NULL; 2491 GError *error = NULL;
2528 GdkPixbuf *scale; 2492 GdkPixbuf *scale;
2529 gboolean success = FALSE; 2493 gboolean success = FALSE;
2494 char *filename = NULL;
2530 2495
2531 g_strfreev(pixbuf_formats); 2496 g_strfreev(pixbuf_formats);
2532 2497
2533 pixbuf = gdk_pixbuf_new_from_file(path, &error); 2498 pixbuf = gdk_pixbuf_new_from_file(path, &error);
2534 if (error) { 2499 if (error) {
2535 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);
2536 g_error_free(error); 2501 g_error_free(error);
2537 g_free(random);
2538 g_free(filename);
2539 g_strfreev(prpl_formats); 2502 g_strfreev(prpl_formats);
2540 return NULL; 2503 return NULL;
2541 } 2504 }
2542 2505
2543 if ((prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_SEND) && 2506 if ((prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_SEND) &&
2556 g_object_unref(G_OBJECT(pixbuf)); 2519 g_object_unref(G_OBJECT(pixbuf));
2557 pixbuf = scale; 2520 pixbuf = scale;
2558 } 2521 }
2559 2522
2560 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
2561 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);
2562 /* The "compression" param wasn't supported until gdk-pixbuf 2.8. 2536 /* The "compression" param wasn't supported until gdk-pixbuf 2.8.
2563 * 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). */
2564 if ((gdk_pixbuf_major_version > 2 || (gdk_pixbuf_major_version == 2 2538 if ((gdk_pixbuf_major_version > 2 || (gdk_pixbuf_major_version == 2
2565 && gdk_pixbuf_minor_version >= 8)) 2539 && gdk_pixbuf_minor_version >= 8))
2584 } 2558 }
2585 g_strfreev(prpl_formats); 2559 g_strfreev(prpl_formats);
2586 g_object_unref(G_OBJECT(pixbuf)); 2560 g_object_unref(G_OBJECT(pixbuf));
2587 if (!success) { 2561 if (!success) {
2588 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");
2589 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);
2590 g_free(filename); 2574 g_free(filename);
2591 return NULL; 2575 return NULL;
2592 } 2576 }
2593 } 2577
2594 2578 g_unlink(filename);
2595 if (g_stat(filename, &st) != 0) {
2596 purple_debug_error("buddyicon",
2597 "Could not stat '%s', which we just wrote to disk: %s\n",
2598 filename, strerror(errno));
2599 g_free(random);
2600 g_free(filename); 2579 g_free(filename);
2601 return NULL; 2580 }
2602 } 2581
2603 2582 /* Check the image size */
2604 /* Check the file size */
2605 /* 2583 /*
2606 * 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
2607 * the prpl supported jpeg, and then we could convert to that 2585 * the prpl supported jpeg, and then we could convert to that
2608 * and use a lower quality setting. 2586 * and use a lower quality setting.
2609 */ 2587 */
2610 if ((prpl_info->icon_spec.max_filesize != 0) && 2588 if ((prpl_info->icon_spec.max_filesize != 0) &&
2611 (st.st_size > prpl_info->icon_spec.max_filesize)) 2589 (length > prpl_info->icon_spec.max_filesize))
2612 { 2590 {
2613 gchar *tmp; 2591 gchar *tmp;
2614 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"),
2615 path, plugin->info->name); 2593 path, plugin->info->name);
2616 purple_notify_error(NULL, _("Icon Error"), 2594 purple_notify_error(NULL, _("Icon Error"),
2617 _("Could not set icon"), tmp); 2595 _("Could not set icon"), tmp);
2618 purple_debug_info("buddyicon", 2596 purple_debug_info("buddyicon",
2619 "'%s' was converted to an image which is %" G_GSIZE_FORMAT 2597 "'%s' was converted to an image which is %" G_GSIZE_FORMAT
2620 " 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
2621 " bytes\n", path, st.st_size, plugin->info->name, 2599 " bytes\n", path, length, plugin->info->name,
2622 prpl_info->icon_spec.max_filesize); 2600 prpl_info->icon_spec.max_filesize);
2623 g_free(tmp); 2601 g_free(tmp);
2624 g_free(random);
2625 g_free(filename);
2626 return NULL; 2602 return NULL;
2627 } 2603 }
2628 2604
2629 g_free(filename); 2605 if (len)
2630 return random; 2606 *len = length;
2607 return contents;
2631 #else 2608 #else
2632 /* 2609 /*
2633 * 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
2634 * GTK+ 2.0 so we can't scale it. 2611 * GTK+ 2.0 so we can't scale it.
2635 */ 2612 */
2778 } 2755 }
2779 #endif /* ! Gtk 2.6.0 */ 2756 #endif /* ! Gtk 2.6.0 */
2780 2757
2781 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)
2782 { 2759 {
2783 PurpleConversation *conv;
2784 PurpleBuddy *buddy; 2760 PurpleBuddy *buddy;
2785 PurpleBlistNode *node; 2761 PurpleContact *contact;
2786 char *path = NULL; 2762 gpointer data = NULL;
2763 size_t len = 0;
2787 2764
2788 buddy = purple_find_buddy(account, who); 2765 buddy = purple_find_buddy(account, who);
2789 if (!buddy) { 2766 if (!buddy) {
2790 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");
2791 return; 2768 return;
2792 } 2769 }
2793 2770
2794 node = (PurpleBlistNode*)purple_buddy_get_contact(buddy); 2771 contact = purple_buddy_get_contact(buddy);
2795 path = (char*)purple_blist_node_get_string(node, "custom_buddy_icon");
2796 if (path) {
2797 struct stat st;
2798 if (g_stat(path, &st) == 0)
2799 g_unlink(path);
2800 path = NULL;
2801 }
2802 2772
2803 if (filename) { 2773 if (filename) {
2804 char *newfile; 2774 const char *prpl_id = purple_account_get_protocol_id(account);
2805 2775 PurplePlugin *prpl = purple_find_prpl(prpl_id);
2806 newfile = pidgin_convert_buddy_icon(purple_find_prpl(purple_account_get_protocol_id(account)), 2776
2807 filename); 2777 data = pidgin_convert_buddy_icon(prpl, filename, &len);
2808 path = purple_buddy_icons_get_full_path(newfile); 2778
2809 g_free(newfile); 2779 /* We don't want to delete the old icon if the new one didn't load. */
2810 } 2780 if (data == NULL)
2811 2781 return;
2812 purple_blist_node_set_string(node, "custom_buddy_icon", path); 2782 }
2813 g_free(path); 2783
2814 2784 purple_buddy_icons_set_custom_icon(contact, data, len);
2815 /* Update the conversation */
2816 conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account);
2817 if (conv)
2818 purple_conversation_update(conv, PURPLE_CONV_UPDATE_ICON);
2819
2820 /* Update the buddylist */
2821 if (buddy)
2822 purple_blist_update_buddy_icon(buddy);
2823 } 2785 }
2824 2786
2825 char *pidgin_make_pretty_arrows(const char *str) 2787 char *pidgin_make_pretty_arrows(const char *str)
2826 { 2788 {
2827 char *ret; 2789 char *ret;

mercurial