| 571 NULL); |
559 NULL); |
| 572 |
560 |
| 573 gtk_tree_path_free(path); |
561 gtk_tree_path_free(path); |
| 574 } |
562 } |
| 575 |
563 |
| 576 |
|
| 577 static void dnd_image_ok_callback(_DndData *data, int choice) |
|
| 578 { |
|
| 579 const gchar *shortname; |
|
| 580 gchar *filedata; |
|
| 581 size_t size; |
|
| 582 GStatBuf st; |
|
| 583 GError *err = NULL; |
|
| 584 PurpleBuddy *buddy; |
|
| 585 PurpleContact *contact; |
|
| 586 PurpleImage *img; |
|
| 587 |
|
| 588 switch (choice) { |
|
| 589 case DND_BUDDY_ICON: |
|
| 590 if (g_stat(data->filename, &st)) { |
|
| 591 char *str; |
|
| 592 |
|
| 593 str = g_strdup_printf(_("The following error has occurred loading %s: %s"), |
|
| 594 data->filename, g_strerror(errno)); |
|
| 595 purple_notify_error(NULL, NULL, |
|
| 596 _("Failed to load image"), str, NULL); |
|
| 597 g_free(str); |
|
| 598 |
|
| 599 break; |
|
| 600 } |
|
| 601 |
|
| 602 buddy = purple_blist_find_buddy(data->account, data->who); |
|
| 603 if (!buddy) { |
|
| 604 purple_debug_info("custom-icon", "You can only set custom icons for people on your buddylist.\n"); |
|
| 605 break; |
|
| 606 } |
|
| 607 contact = purple_buddy_get_contact(buddy); |
|
| 608 purple_buddy_icons_node_set_custom_icon_from_file((PurpleBlistNode*)contact, data->filename); |
|
| 609 break; |
|
| 610 case DND_FILE_TRANSFER: |
|
| 611 purple_serv_send_file(purple_account_get_connection(data->account), data->who, data->filename); |
|
| 612 break; |
|
| 613 case DND_IM_IMAGE: |
|
| 614 if (!g_file_get_contents(data->filename, &filedata, &size, |
|
| 615 &err)) { |
|
| 616 char *str; |
|
| 617 |
|
| 618 str = g_strdup_printf(_("The following error has occurred loading %s: %s"), data->filename, err->message); |
|
| 619 purple_notify_error(NULL, NULL, |
|
| 620 _("Failed to load image"), str, NULL); |
|
| 621 |
|
| 622 g_error_free(err); |
|
| 623 g_free(str); |
|
| 624 |
|
| 625 break; |
|
| 626 } |
|
| 627 shortname = strrchr(data->filename, G_DIR_SEPARATOR); |
|
| 628 shortname = shortname ? shortname + 1 : data->filename; |
|
| 629 img = purple_image_new_from_data((guint8 *)filedata, size); |
|
| 630 purple_image_set_friendly_filename(img, shortname); |
|
| 631 |
|
| 632 # warning fix this when talkatu has a way to programmatically insert an image |
|
| 633 // pidgin_webview_insert_image(PIDGIN_WEBVIEW(gtkconv->entry), img); |
|
| 634 g_object_unref(img); |
|
| 635 |
|
| 636 break; |
|
| 637 } |
|
| 638 g_free(data->filename); |
|
| 639 g_free(data->who); |
|
| 640 g_free(data); |
|
| 641 } |
|
| 642 |
|
| 643 static void dnd_image_cancel_callback(_DndData *data, int choice) |
|
| 644 { |
|
| 645 g_free(data->filename); |
|
| 646 g_free(data->who); |
|
| 647 g_free(data); |
|
| 648 } |
|
| 649 |
|
| 650 static void dnd_set_icon_ok_cb(_DndData *data) |
|
| 651 { |
|
| 652 dnd_image_ok_callback(data, DND_BUDDY_ICON); |
|
| 653 } |
|
| 654 |
|
| 655 static void dnd_set_icon_cancel_cb(_DndData *data) |
|
| 656 { |
|
| 657 g_free(data->filename); |
|
| 658 g_free(data->who); |
|
| 659 g_free(data); |
|
| 660 } |
|
| 661 |
|
| 662 static void |
|
| 663 pidgin_dnd_file_send_image(PurpleAccount *account, const gchar *who, |
|
| 664 const gchar *filename) |
|
| 665 { |
|
| 666 PurpleConnection *gc = purple_account_get_connection(account); |
|
| 667 PurpleProtocol *protocol = NULL; |
|
| 668 _DndData *data = g_new0(_DndData, 1); |
|
| 669 gboolean ft = FALSE, im = FALSE; |
|
| 670 |
|
| 671 data->who = g_strdup(who); |
|
| 672 data->filename = g_strdup(filename); |
|
| 673 data->account = account; |
|
| 674 |
|
| 675 if (gc) |
|
| 676 protocol = purple_connection_get_protocol(gc); |
|
| 677 |
|
| 678 if (!(purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_NO_IMAGES)) |
|
| 679 im = TRUE; |
|
| 680 |
|
| 681 if (protocol && PURPLE_IS_PROTOCOL_XFER(protocol)) { |
|
| 682 PurpleProtocolXferInterface *iface = |
|
| 683 PURPLE_PROTOCOL_XFER_GET_IFACE(protocol); |
|
| 684 |
|
| 685 if(iface->can_receive) { |
|
| 686 ft = purple_protocol_xfer_can_receive( |
|
| 687 PURPLE_PROTOCOL_XFER(protocol), |
|
| 688 gc, who); |
|
| 689 } else { |
|
| 690 ft = (iface->send_file) ? TRUE : FALSE; |
|
| 691 } |
|
| 692 } |
|
| 693 |
|
| 694 if (im && ft) { |
|
| 695 purple_request_choice(NULL, NULL, |
|
| 696 _("You have dragged an image"), |
|
| 697 _("You can send this image as a file " |
|
| 698 "transfer, embed it into this message, " |
|
| 699 "or use it as the buddy icon for this user."), |
|
| 700 (gpointer)DND_FILE_TRANSFER, _("OK"), |
|
| 701 (GCallback)dnd_image_ok_callback, _("Cancel"), |
|
| 702 (GCallback)dnd_image_cancel_callback, |
|
| 703 purple_request_cpar_from_account(account), data, |
|
| 704 _("Set as buddy icon"), DND_BUDDY_ICON, |
|
| 705 _("Send image file"), DND_FILE_TRANSFER, |
|
| 706 _("Insert in message"), DND_IM_IMAGE, |
|
| 707 NULL); |
|
| 708 } else if (!(im || ft)) { |
|
| 709 purple_request_yes_no(NULL, NULL, _("You have dragged an image"), |
|
| 710 _("Would you like to set it as the buddy icon for this user?"), |
|
| 711 PURPLE_DEFAULT_ACTION_NONE, |
|
| 712 purple_request_cpar_from_account(account), |
|
| 713 data, (GCallback)dnd_set_icon_ok_cb, (GCallback)dnd_set_icon_cancel_cb); |
|
| 714 } else { |
|
| 715 purple_request_choice(NULL, NULL, |
|
| 716 _("You have dragged an image"), |
|
| 717 (ft ? _("You can send this image as a file transfer, or use it as the buddy icon for this user.") : |
|
| 718 _("You can insert this image into this message, or use it as the buddy icon for this user")), |
|
| 719 GINT_TO_POINTER(ft ? DND_FILE_TRANSFER : DND_IM_IMAGE), |
|
| 720 _("OK"), (GCallback)dnd_image_ok_callback, |
|
| 721 _("Cancel"), (GCallback)dnd_image_cancel_callback, |
|
| 722 purple_request_cpar_from_account(account), |
|
| 723 data, |
|
| 724 _("Set as buddy icon"), DND_BUDDY_ICON, |
|
| 725 (ft ? _("Send image file") : _("Insert in message")), (ft ? DND_FILE_TRANSFER : DND_IM_IMAGE), |
|
| 726 NULL); |
|
| 727 } |
|
| 728 |
|
| 729 } |
|
| 730 |
|
| 731 #ifndef _WIN32 |
|
| 732 static void |
|
| 733 pidgin_dnd_file_send_desktop(PurpleAccount *account, const gchar *who, |
|
| 734 const gchar *filename) |
|
| 735 { |
|
| 736 gchar *name; |
|
| 737 gchar *type; |
|
| 738 gchar *url; |
|
| 739 GKeyFile *desktop_file; |
|
| 740 PurpleConversation *conv; |
|
| 741 PidginConversation *gtkconv; |
|
| 742 GError *error = NULL; |
|
| 743 |
|
| 744 desktop_file = g_key_file_new(); |
|
| 745 |
|
| 746 if (!g_key_file_load_from_file(desktop_file, filename, G_KEY_FILE_NONE, &error)) { |
|
| 747 if (error) { |
|
| 748 purple_debug_warning("D&D", "Failed to load %s: %s\n", |
|
| 749 filename, error->message); |
|
| 750 g_error_free(error); |
|
| 751 } |
|
| 752 return; |
|
| 753 } |
|
| 754 |
|
| 755 name = g_key_file_get_string(desktop_file, G_KEY_FILE_DESKTOP_GROUP, |
|
| 756 G_KEY_FILE_DESKTOP_KEY_NAME, &error); |
|
| 757 if (error) { |
|
| 758 purple_debug_warning("D&D", "Failed to read the Name from a desktop file: %s\n", |
|
| 759 error->message); |
|
| 760 g_error_free(error); |
|
| 761 |
|
| 762 } |
|
| 763 |
|
| 764 type = g_key_file_get_string(desktop_file, G_KEY_FILE_DESKTOP_GROUP, |
|
| 765 G_KEY_FILE_DESKTOP_KEY_TYPE, &error); |
|
| 766 if (error) { |
|
| 767 purple_debug_warning("D&D", "Failed to read the Type from a desktop file: %s\n", |
|
| 768 error->message); |
|
| 769 g_error_free(error); |
|
| 770 |
|
| 771 } |
|
| 772 |
|
| 773 url = g_key_file_get_string(desktop_file, G_KEY_FILE_DESKTOP_GROUP, |
|
| 774 G_KEY_FILE_DESKTOP_KEY_URL, &error); |
|
| 775 if (error) { |
|
| 776 purple_debug_warning("D&D", "Failed to read the Type from a desktop file: %s\n", |
|
| 777 error->message); |
|
| 778 g_error_free(error); |
|
| 779 |
|
| 780 } |
|
| 781 |
|
| 782 |
|
| 783 /* If any of this is null, do nothing. */ |
|
| 784 if (!name || !type || !url) { |
|
| 785 g_free(type); |
|
| 786 g_free(name); |
|
| 787 g_free(url); |
|
| 788 |
|
| 789 return; |
|
| 790 } |
|
| 791 |
|
| 792 /* I don't know if we really want to do anything here. Most of |
|
| 793 * the desktop item types are crap like "MIME Type" (I have no |
|
| 794 * clue how that would be a desktop item) and "Comment"... |
|
| 795 * nothing we can really send. The only logical one is |
|
| 796 * "Application," but do we really want to send a binary and |
|
| 797 * nothing else? Probably not. I'll just give an error and |
|
| 798 * return. */ |
|
| 799 /* The original patch sent the icon used by the launcher. That's probably wrong */ |
|
| 800 if (purple_strequal(type, "Link")) { |
|
| 801 purple_notify_error(NULL, NULL, _("Cannot send launcher"), |
|
| 802 _("You dragged a desktop launcher. Most " |
|
| 803 "likely you wanted to send the target " |
|
| 804 "of this launcher instead of this " |
|
| 805 "launcher itself."), NULL); |
|
| 806 |
|
| 807 } else { |
|
| 808 GtkTextBuffer *buffer = NULL; |
|
| 809 GtkTextMark *mark = NULL; |
|
| 810 GtkTextIter iter; |
|
| 811 |
|
| 812 conv = PURPLE_CONVERSATION(purple_im_conversation_new(account, who)); |
|
| 813 gtkconv = PIDGIN_CONVERSATION(conv); |
|
| 814 |
|
| 815 buffer = talkatu_editor_get_buffer(TALKATU_EDITOR(gtkconv->editor)); |
|
| 816 mark = gtk_text_buffer_get_insert(buffer); |
|
| 817 |
|
| 818 gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark); |
|
| 819 |
|
| 820 talkatu_buffer_insert_link(TALKATU_BUFFER(buffer), &iter, name, url); |
|
| 821 } |
|
| 822 |
|
| 823 g_free(type); |
|
| 824 g_free(name); |
|
| 825 g_free(url); |
|
| 826 } |
|
| 827 #endif /* _WIN32 */ |
|
| 828 |
|
| 829 void |
|
| 830 pidgin_dnd_file_manage(GtkSelectionData *sd, PurpleAccount *account, const char *who) |
|
| 831 { |
|
| 832 GdkPixbuf *pb; |
|
| 833 GList *files = purple_uri_list_extract_filenames((const gchar *) gtk_selection_data_get_data(sd)); |
|
| 834 PurpleConnection *gc = purple_account_get_connection(account); |
|
| 835 gchar *filename = NULL; |
|
| 836 gchar *basename = NULL; |
|
| 837 |
|
| 838 g_return_if_fail(account != NULL); |
|
| 839 g_return_if_fail(who != NULL); |
|
| 840 |
|
| 841 for ( ; files; files = g_list_delete_link(files, files)) { |
|
| 842 g_free(filename); |
|
| 843 g_free(basename); |
|
| 844 |
|
| 845 filename = files->data; |
|
| 846 basename = g_path_get_basename(filename); |
|
| 847 |
|
| 848 /* XXX - Make ft API support creating a transfer with more than one file */ |
|
| 849 if (!g_file_test(filename, G_FILE_TEST_EXISTS)) { |
|
| 850 continue; |
|
| 851 } |
|
| 852 |
|
| 853 /* XXX - make ft api suupport sending a directory */ |
|
| 854 /* Are we dealing with a directory? */ |
|
| 855 if (g_file_test(filename, G_FILE_TEST_IS_DIR)) { |
|
| 856 char *str, *str2; |
|
| 857 |
|
| 858 str = g_strdup_printf(_("Cannot send folder %s."), basename); |
|
| 859 str2 = g_strdup_printf(_("%s cannot transfer a folder. You will need to send the files within individually."), PIDGIN_NAME); |
|
| 860 |
|
| 861 purple_notify_error(NULL, NULL, str, str2, |
|
| 862 purple_request_cpar_from_connection(gc)); |
|
| 863 |
|
| 864 g_free(str); |
|
| 865 g_free(str2); |
|
| 866 continue; |
|
| 867 } |
|
| 868 |
|
| 869 /* Are we dealing with an image? */ |
|
| 870 pb = pidgin_pixbuf_new_from_file(filename); |
|
| 871 if (pb) { |
|
| 872 pidgin_dnd_file_send_image(account, who, filename); |
|
| 873 |
|
| 874 g_object_unref(G_OBJECT(pb)); |
|
| 875 |
|
| 876 continue; |
|
| 877 } |
|
| 878 |
|
| 879 #ifndef _WIN32 |
|
| 880 /* Are we trying to send a .desktop file? */ |
|
| 881 else if (g_str_has_suffix(basename, ".desktop")) { |
|
| 882 pidgin_dnd_file_send_desktop(account, who, filename); |
|
| 883 |
|
| 884 continue; |
|
| 885 } |
|
| 886 #endif /* _WIN32 */ |
|
| 887 |
|
| 888 /* Everything is fine, let's send */ |
|
| 889 purple_serv_send_file(gc, who, filename); |
|
| 890 } |
|
| 891 |
|
| 892 g_free(filename); |
|
| 893 g_free(basename); |
|
| 894 } |
|
| 895 |
564 |
| 896 void pidgin_buddy_icon_get_scale_size(GdkPixbuf *buf, PurpleBuddyIconSpec *spec, PurpleBuddyIconScaleFlags rules, int *width, int *height) |
565 void pidgin_buddy_icon_get_scale_size(GdkPixbuf *buf, PurpleBuddyIconSpec *spec, PurpleBuddyIconScaleFlags rules, int *width, int *height) |
| 897 { |
566 { |
| 898 *width = gdk_pixbuf_get_width(buf); |
567 *width = gdk_pixbuf_get_width(buf); |
| 899 *height = gdk_pixbuf_get_height(buf); |
568 *height = gdk_pixbuf_get_height(buf); |