comparison pidgin/gtkutils.c @ 32665:a92f4cb593a4

propagate from branch 'im.pidgin.pidgin' (head c0e633bbd723352b9614b1bfcfab551e416a29dc) to branch 'im.pidgin.cpw.qulogic.gtk3' (head 1887cd5f7ea1e4bc0950747da36d56d618ecd105)
author Marcus Lundblad <ml@update.uu.se>
date Wed, 02 Feb 2011 23:26:42 +0000
parents a7397a3d67ef 3cec1e97e698
children 974722699032
comparison
equal deleted inserted replaced
32648:a7397a3d67ef 32665:a92f4cb593a4
524 524
525 return vbox; 525 return vbox;
526 } 526 }
527 527
528 static gpointer 528 static gpointer
529 aop_option_menu_get_selected(GtkWidget *optmenu) 529 aop_option_menu_get_selected(GtkWidget *optmenu, GtkWidget **p_item)
530 { 530 {
531 gpointer data = NULL; 531 GtkWidget *menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu));
532 GtkTreeIter iter; 532 GtkWidget *item = gtk_menu_get_active(GTK_MENU(menu));
533 533 if (p_item)
534 g_return_val_if_fail(optmenu != NULL, NULL); 534 (*p_item) = item;
535 535 return item ? g_object_get_data(G_OBJECT(item), "aop_per_item_data") : NULL;
536 if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(optmenu), &iter))
537 gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(optmenu)), &iter, 2, &data, -1);
538
539 return data;
540 } 536 }
541 537
542 static void 538 static void
543 aop_menu_cb(GtkWidget *optmenu, GCallback cb) 539 aop_menu_cb(GtkWidget *optmenu, GCallback cb)
544 { 540 {
541 GtkWidget *item;
542 gpointer per_item_data;
543
544 per_item_data = aop_option_menu_get_selected(optmenu, &item);
545
545 if (cb != NULL) { 546 if (cb != NULL) {
546 ((void (*)(GtkWidget *, gpointer, gpointer))cb)(optmenu, 547 ((void (*)(GtkWidget *, gpointer, gpointer))cb)(item, per_item_data, g_object_get_data(G_OBJECT(optmenu), "user_data"));
547 aop_option_menu_get_selected(optmenu), 548 }
548 g_object_get_data(G_OBJECT(optmenu), "user_data")); 549 }
549 } 550
550 } 551 static GtkWidget *
551 552 aop_menu_item_new(GtkSizeGroup *sg, GdkPixbuf *pixbuf, const char *lbl, gpointer per_item_data, const char *data)
552 static void 553 {
553 aop_option_menu_replace_menu(GtkWidget *optmenu, AopMenu *new_aop_menu) 554 GtkWidget *item;
554 { 555 GtkWidget *hbox;
555 gtk_combo_box_set_model(GTK_COMBO_BOX(optmenu), new_aop_menu->model); 556 GtkWidget *image;
556 gtk_combo_box_set_active(GTK_COMBO_BOX(optmenu), new_aop_menu->default_item); 557 GtkWidget *label;
557 g_object_set_data_full(G_OBJECT(optmenu), "aop_menu", new_aop_menu, (GDestroyNotify)g_free); 558
559 item = gtk_menu_item_new();
560 gtk_widget_show(item);
561
562 hbox = gtk_hbox_new(FALSE, 4);
563 gtk_widget_show(hbox);
564
565 /* Create the image */
566 if (pixbuf == NULL)
567 image = gtk_image_new();
568 else
569 image = gtk_image_new_from_pixbuf(pixbuf);
570 gtk_widget_show(image);
571
572 if (sg)
573 gtk_size_group_add_widget(sg, image);
574
575 /* Create the label */
576 label = gtk_label_new (lbl);
577 gtk_widget_show (label);
578 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
579 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
580
581 gtk_container_add(GTK_CONTAINER(item), hbox);
582 gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
583 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
584
585 g_object_set_data(G_OBJECT (item), data, per_item_data);
586 g_object_set_data(G_OBJECT (item), "aop_per_item_data", per_item_data);
587
588 pidgin_set_accessible_label(item, label);
589
590 return item;
558 } 591 }
559 592
560 static GdkPixbuf * 593 static GdkPixbuf *
561 pidgin_create_prpl_icon_from_prpl(PurplePlugin *prpl, PidginPrplIconSize size, PurpleAccount *account) 594 pidgin_create_prpl_icon_from_prpl(PurplePlugin *prpl, PidginPrplIconSize size, PurpleAccount *account)
562 { 595 {
593 } 626 }
594 627
595 static GtkWidget * 628 static GtkWidget *
596 aop_option_menu_new(AopMenu *aop_menu, GCallback cb, gpointer user_data) 629 aop_option_menu_new(AopMenu *aop_menu, GCallback cb, gpointer user_data)
597 { 630 {
598 GtkWidget *optmenu = NULL; 631 GtkWidget *optmenu;
599 GtkCellRenderer *cr = NULL; 632
600 633 optmenu = gtk_option_menu_new();
601 optmenu = gtk_combo_box_new();
602 gtk_widget_show(optmenu); 634 gtk_widget_show(optmenu);
603 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(optmenu), cr = gtk_cell_renderer_pixbuf_new(), FALSE); 635 gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), aop_menu->menu);
604 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(optmenu), cr, "pixbuf", 0); 636
605 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(optmenu), cr = gtk_cell_renderer_text_new(), TRUE); 637 if (aop_menu->default_item != -1)
606 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(optmenu), cr, "text", 1); 638 gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), aop_menu->default_item);
607 639
608 aop_option_menu_replace_menu(optmenu, aop_menu); 640 g_object_set_data_full(G_OBJECT(optmenu), "aop_menu", aop_menu, (GDestroyNotify)g_free);
609 if (aop_menu->default_item == -1)
610 gtk_combo_box_set_active(GTK_COMBO_BOX(optmenu), 0);
611 g_object_set_data(G_OBJECT(optmenu), "user_data", user_data); 641 g_object_set_data(G_OBJECT(optmenu), "user_data", user_data);
612 642
613 g_signal_connect(G_OBJECT(optmenu), "changed", G_CALLBACK(aop_menu_cb), cb); 643 g_signal_connect(G_OBJECT(optmenu), "changed", G_CALLBACK(aop_menu_cb), cb);
614 644
615 return optmenu; 645 return optmenu;
646 }
647
648 static void
649 aop_option_menu_replace_menu(GtkWidget *optmenu, AopMenu *new_aop_menu)
650 {
651 if (gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu)))
652 gtk_option_menu_remove_menu(GTK_OPTION_MENU(optmenu));
653
654 gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), new_aop_menu->menu);
655
656 if (new_aop_menu->default_item != -1)
657 gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), new_aop_menu->default_item);
658
659 g_object_set_data_full(G_OBJECT(optmenu), "aop_menu", new_aop_menu, (GDestroyNotify)g_free);
616 } 660 }
617 661
618 static void 662 static void
619 aop_option_menu_select_by_data(GtkWidget *optmenu, gpointer data) 663 aop_option_menu_select_by_data(GtkWidget *optmenu, gpointer data)
620 { 664 {
621 GtkTreeModel *model; 665 guint idx;
622 GtkTreeIter iter; 666 GList *llItr = NULL;
623 gpointer iter_data; 667
624 model = gtk_combo_box_get_model(GTK_COMBO_BOX(optmenu)); 668 for (idx = 0, llItr = GTK_MENU_SHELL(gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu)))->children;
625 if (gtk_tree_model_get_iter_first(model, &iter)) { 669 llItr != NULL;
626 do { 670 llItr = llItr->next, idx++) {
627 gtk_tree_model_get(model, &iter, 2, &iter_data, -1); 671 if (data == g_object_get_data(G_OBJECT(llItr->data), "aop_per_item_data")) {
628 if (iter_data == data) { 672 gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), idx);
629 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(optmenu), &iter); 673 break;
630 return; 674 }
631 }
632 } while (gtk_tree_model_iter_next(model, &iter));
633 } 675 }
634 } 676 }
635 677
636 static AopMenu * 678 static AopMenu *
637 create_protocols_menu(const char *default_proto_id) 679 create_protocols_menu(const char *default_proto_id)
638 { 680 {
639 AopMenu *aop_menu = NULL; 681 AopMenu *aop_menu = NULL;
640 PurplePlugin *plugin; 682 PurplePlugin *plugin;
641 GdkPixbuf *pixbuf = NULL; 683 GdkPixbuf *pixbuf = NULL;
642 GtkTreeIter iter; 684 GtkSizeGroup *sg;
643 GtkListStore *ls;
644 GList *p; 685 GList *p;
645 const char *gtalk_name = NULL, *facebook_name = NULL; 686 const char *gtalk_name = NULL, *facebook_name = NULL;
646 int i; 687 int i;
647 688
648 ls = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER);
649
650 aop_menu = g_malloc0(sizeof(AopMenu)); 689 aop_menu = g_malloc0(sizeof(AopMenu));
651 aop_menu->default_item = -1; 690 aop_menu->default_item = -1;
652 aop_menu->model = GTK_TREE_MODEL(ls); 691 aop_menu->menu = gtk_menu_new();
692 gtk_widget_show(aop_menu->menu);
693 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
653 694
654 if (purple_find_prpl("prpl-jabber")) { 695 if (purple_find_prpl("prpl-jabber")) {
655 gtalk_name = _("Google Talk"); 696 gtalk_name = _("Google Talk");
656 facebook_name = _("Facebook (XMPP)"); 697 facebook_name = _("Facebook (XMPP)");
657 } 698 }
663 plugin = (PurplePlugin *)p->data; 704 plugin = (PurplePlugin *)p->data;
664 705
665 if (gtalk_name && strcmp(gtalk_name, plugin->info->name) < 0) { 706 if (gtalk_name && strcmp(gtalk_name, plugin->info->name) < 0) {
666 char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", 707 char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
667 "16", "google-talk.png", NULL); 708 "16", "google-talk.png", NULL);
709 GtkWidget *item;
710
668 pixbuf = gdk_pixbuf_new_from_file(filename, NULL); 711 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
669 g_free(filename); 712 g_free(filename);
670 713
671 gtk_list_store_append(ls, &iter); 714 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
672 gtk_list_store_set(ls, &iter, 0, pixbuf, 1, gtalk_name, 2, "prpl-jabber", -1); 715 item = aop_menu_item_new(sg, pixbuf, gtalk_name, "prpl-jabber", "protocol"));
716 g_object_set_data(G_OBJECT(item), "fakegoogle", GINT_TO_POINTER(1));
673 717
674 if (pixbuf) 718 if (pixbuf)
675 g_object_unref(pixbuf); 719 g_object_unref(pixbuf);
676 720
677 gtalk_name = NULL; 721 gtalk_name = NULL;
684 GtkWidget *item; 728 GtkWidget *item;
685 729
686 pixbuf = gdk_pixbuf_new_from_file(filename, NULL); 730 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
687 g_free(filename); 731 g_free(filename);
688 732
689 gtk_list_store_append(ls, &iter); 733 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
690 gtk_list_store_set(ls, &iter, 0, pixbuf, 1, facebook_name, 2, "prpl-jabber", -1); 734 item = aop_menu_item_new(sg, pixbuf, facebook_name, "prpl-jabber", "protocol"));
735 g_object_set_data(G_OBJECT(item), "fakefacebook", GINT_TO_POINTER(1));
691 736
692 if (pixbuf) 737 if (pixbuf)
693 g_object_unref(pixbuf); 738 g_object_unref(pixbuf);
694 739
695 facebook_name = NULL; 740 facebook_name = NULL;
696 i++; 741 i++;
697 } 742 }
698 743
699 pixbuf = pidgin_create_prpl_icon_from_prpl(plugin, PIDGIN_PRPL_ICON_SMALL, NULL); 744 pixbuf = pidgin_create_prpl_icon_from_prpl(plugin, PIDGIN_PRPL_ICON_SMALL, NULL);
700 745
701 gtk_list_store_append(ls, &iter); 746 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
702 gtk_list_store_set(ls, &iter, 0, pixbuf, 1, plugin->info->name, 2, plugin->info->id, -1); 747 aop_menu_item_new(sg, pixbuf, plugin->info->name, plugin->info->id, "protocol"));
703 748
704 if (pixbuf) 749 if (pixbuf)
705 g_object_unref(pixbuf); 750 g_object_unref(pixbuf);
706 751
707 if (default_proto_id != NULL && !strcmp(plugin->info->id, default_proto_id)) 752 if (default_proto_id != NULL && !strcmp(plugin->info->id, default_proto_id))
708 aop_menu->default_item = i; 753 aop_menu->default_item = i;
709 } 754 }
755
756 g_object_unref(sg);
757
710 return aop_menu; 758 return aop_menu;
711 } 759 }
712 760
713 GtkWidget * 761 GtkWidget *
714 pidgin_protocol_option_menu_new(const char *id, GCallback cb, 762 pidgin_protocol_option_menu_new(const char *id, GCallback cb,
718 } 766 }
719 767
720 const char * 768 const char *
721 pidgin_protocol_option_menu_get_selected(GtkWidget *optmenu) 769 pidgin_protocol_option_menu_get_selected(GtkWidget *optmenu)
722 { 770 {
723 return (const char *)aop_option_menu_get_selected(optmenu); 771 return (const char *)aop_option_menu_get_selected(optmenu, NULL);
724 } 772 }
725 773
726 PurpleAccount * 774 PurpleAccount *
727 pidgin_account_option_menu_get_selected(GtkWidget *optmenu) 775 pidgin_account_option_menu_get_selected(GtkWidget *optmenu)
728 { 776 {
729 return (PurpleAccount *)aop_option_menu_get_selected(optmenu); 777 return (PurpleAccount *)aop_option_menu_get_selected(optmenu, NULL);
730 } 778 }
731 779
732 static AopMenu * 780 static AopMenu *
733 create_account_menu(PurpleAccount *default_account, 781 create_account_menu(PurpleAccount *default_account,
734 PurpleFilterAccountFunc filter_func, gboolean show_all) 782 PurpleFilterAccountFunc filter_func, gboolean show_all)
736 AopMenu *aop_menu = NULL; 784 AopMenu *aop_menu = NULL;
737 PurpleAccount *account; 785 PurpleAccount *account;
738 GdkPixbuf *pixbuf = NULL; 786 GdkPixbuf *pixbuf = NULL;
739 GList *list; 787 GList *list;
740 GList *p; 788 GList *p;
741 GtkListStore *ls; 789 GtkSizeGroup *sg;
742 GtkTreeIter iter;
743 int i; 790 int i;
744 char buf[256]; 791 char buf[256];
745 792
746 if (show_all) 793 if (show_all)
747 list = purple_accounts_get_all(); 794 list = purple_accounts_get_all();
748 else 795 else
749 list = purple_connections_get_all(); 796 list = purple_connections_get_all();
750 797
751 ls = gtk_list_store_new(3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER);
752
753 aop_menu = g_malloc0(sizeof(AopMenu)); 798 aop_menu = g_malloc0(sizeof(AopMenu));
754 aop_menu->default_item = -1; 799 aop_menu->default_item = -1;
755 aop_menu->model = GTK_TREE_MODEL(ls); 800 aop_menu->menu = gtk_menu_new();
801 gtk_widget_show(aop_menu->menu);
802 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
756 803
757 for (p = list, i = 0; p != NULL; p = p->next, i++) { 804 for (p = list, i = 0; p != NULL; p = p->next, i++) {
758 if (show_all) 805 if (show_all)
759 account = (PurpleAccount *)p->data; 806 account = (PurpleAccount *)p->data;
760 else { 807 else {
785 g_snprintf(buf, sizeof(buf), "%s (%s)", 832 g_snprintf(buf, sizeof(buf), "%s (%s)",
786 purple_account_get_username(account), 833 purple_account_get_username(account),
787 purple_account_get_protocol_name(account)); 834 purple_account_get_protocol_name(account));
788 } 835 }
789 836
790 gtk_list_store_append(ls, &iter); 837 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
791 gtk_list_store_set(ls, &iter, 0, pixbuf, 1, buf, 2, account, -1); 838 aop_menu_item_new(sg, pixbuf, buf, account, "account"));
792 839
793 if (pixbuf) 840 if (pixbuf)
794 g_object_unref(pixbuf); 841 g_object_unref(pixbuf);
795 842
796 if (default_account && account == default_account) 843 if (default_account && account == default_account)
797 aop_menu->default_item = i; 844 aop_menu->default_item = i;
798 } 845 }
846
847 g_object_unref(sg);
848
799 return aop_menu; 849 return aop_menu;
800 } 850 }
801 851
802 static void 852 static void
803 regenerate_account_menu(GtkWidget *optmenu) 853 regenerate_account_menu(GtkWidget *optmenu)
804 { 854 {
805 gboolean show_all; 855 gboolean show_all;
806 PurpleAccount *account; 856 PurpleAccount *account;
807 PurpleFilterAccountFunc filter_func; 857 PurpleFilterAccountFunc filter_func;
808 858
809 account = (PurpleAccount *)aop_option_menu_get_selected(optmenu); 859 account = (PurpleAccount *)aop_option_menu_get_selected(optmenu, NULL);
810 show_all = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(optmenu), "show_all")); 860 show_all = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(optmenu), "show_all"));
811 filter_func = g_object_get_data(G_OBJECT(optmenu), "filter_func"); 861 filter_func = g_object_get_data(G_OBJECT(optmenu), "filter_func");
812 862
813 aop_option_menu_replace_menu(optmenu, create_account_menu(account, filter_func, show_all)); 863 aop_option_menu_replace_menu(optmenu, create_account_menu(account, filter_func, show_all));
814 } 864 }
872 g_object_set_data(G_OBJECT(optmenu), "user_data", user_data); 922 g_object_set_data(G_OBJECT(optmenu), "user_data", user_data);
873 g_object_set_data(G_OBJECT(optmenu), "show_all", GINT_TO_POINTER(show_all)); 923 g_object_set_data(G_OBJECT(optmenu), "show_all", GINT_TO_POINTER(show_all));
874 g_object_set_data(G_OBJECT(optmenu), "filter_func", filter_func); 924 g_object_set_data(G_OBJECT(optmenu), "filter_func", filter_func);
875 925
876 return optmenu; 926 return optmenu;
927 }
928
929 gboolean
930 pidgin_check_if_dir(const char *path, GtkFileSelection *filesel)
931 {
932 char *dirname = NULL;
933
934 if (g_file_test(path, G_FILE_TEST_IS_DIR)) {
935 /* append a / if needed */
936 if (path[strlen(path) - 1] != G_DIR_SEPARATOR) {
937 dirname = g_strconcat(path, G_DIR_SEPARATOR_S, NULL);
938 }
939 gtk_file_selection_set_filename(filesel, (dirname != NULL) ? dirname : path);
940 g_free(dirname);
941 return TRUE;
942 }
943
944 return FALSE;
877 } 945 }
878 946
879 void 947 void
880 pidgin_setup_gtkspell(GtkTextView *textview) 948 pidgin_setup_gtkspell(GtkTextView *textview)
881 { 949 {
1392 char *who; 1460 char *who;
1393 } _DndData; 1461 } _DndData;
1394 1462
1395 static void dnd_image_ok_callback(_DndData *data, int choice) 1463 static void dnd_image_ok_callback(_DndData *data, int choice)
1396 { 1464 {
1465 const gchar *shortname;
1397 gchar *filedata; 1466 gchar *filedata;
1398 size_t size; 1467 size_t size;
1399 struct stat st; 1468 struct stat st;
1400 GError *err = NULL; 1469 GError *err = NULL;
1401 PurpleConversation *conv; 1470 PurpleConversation *conv;
1446 g_error_free(err); 1515 g_error_free(err);
1447 g_free(str); 1516 g_free(str);
1448 1517
1449 break; 1518 break;
1450 } 1519 }
1451 id = purple_imgstore_add_with_id(filedata, size, data->filename); 1520 shortname = strrchr(data->filename, G_DIR_SEPARATOR);
1521 shortname = shortname ? shortname + 1 : data->filename;
1522 id = purple_imgstore_add_with_id(filedata, size, shortname);
1452 1523
1453 gtk_text_buffer_get_iter_at_mark(GTK_IMHTML(gtkconv->entry)->text_buffer, &iter, 1524 gtk_text_buffer_get_iter_at_mark(GTK_IMHTML(gtkconv->entry)->text_buffer, &iter,
1454 gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer)); 1525 gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer));
1455 gtk_imhtml_insert_image_at_iter(GTK_IMHTML(gtkconv->entry), id, &iter); 1526 gtk_imhtml_insert_image_at_iter(GTK_IMHTML(gtkconv->entry), id, &iter);
1456 purple_imgstore_unref_by_id(id); 1527 purple_imgstore_unref_by_id(id);