pidgin/gtkutils.c

changeset 18178
d461ccafa1fb
parent 17707
b5f042209c68
parent 18121
2d8ea56b9097
child 18185
d4f1719d812b
child 18191
087e7ed44d3d
equal deleted inserted replaced
17755:ed70e92f7c28 18178:d461ccafa1fb
128 pango_font_description_free(desc); 128 pango_font_description_free(desc);
129 } 129 }
130 } 130 }
131 131
132 GtkWidget * 132 GtkWidget *
133 pidgin_create_window(const char *title, guint border_width, const char *role, gboolean resizable)
134 {
135 GtkWindow *wnd = NULL;
136
137 wnd = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
138 if (title)
139 gtk_window_set_title(wnd, title);
140 gtk_container_set_border_width(GTK_CONTAINER(wnd), border_width);
141 if (role)
142 gtk_window_set_role(wnd, role);
143 gtk_window_set_resizable(wnd, resizable);
144
145 return GTK_WIDGET(wnd);
146 }
147
148 GtkWidget *
133 pidgin_create_imhtml(gboolean editable, GtkWidget **imhtml_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret) 149 pidgin_create_imhtml(gboolean editable, GtkWidget **imhtml_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret)
134 { 150 {
135 GtkWidget *frame; 151 GtkWidget *frame;
136 GtkWidget *imhtml; 152 GtkWidget *imhtml;
137 GtkWidget *sep; 153 GtkWidget *sep;
243 gtk_widget_hide(to_toggle); 259 gtk_widget_hide(to_toggle);
244 else 260 else
245 gtk_widget_show(to_toggle); 261 gtk_widget_show(to_toggle);
246 } 262 }
247 263
248 void pidgin_separator(GtkWidget *menu) 264 GtkWidget *pidgin_separator(GtkWidget *menu)
249 { 265 {
250 GtkWidget *menuitem; 266 GtkWidget *menuitem;
251 267
252 menuitem = gtk_separator_menu_item_new(); 268 menuitem = gtk_separator_menu_item_new();
253 gtk_widget_show(menuitem); 269 gtk_widget_show(menuitem);
254 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); 270 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
271 return menuitem;
255 } 272 }
256 273
257 GtkWidget *pidgin_new_item(GtkWidget *menu, const char *str) 274 GtkWidget *pidgin_new_item(GtkWidget *menu, const char *str)
258 { 275 {
259 GtkWidget *menuitem; 276 GtkWidget *menuitem;
460 ((void (*)(GtkWidget *, gpointer, gpointer))cb)(item, per_item_data, g_object_get_data(G_OBJECT(optmenu), "user_data")); 477 ((void (*)(GtkWidget *, gpointer, gpointer))cb)(item, per_item_data, g_object_get_data(G_OBJECT(optmenu), "user_data"));
461 } 478 }
462 } 479 }
463 480
464 static GtkWidget * 481 static GtkWidget *
465 aop_menu_item_new(GtkSizeGroup *sg, GdkPixbuf *pixbuf, const char *lbl, gpointer per_item_data) 482 aop_menu_item_new(GtkSizeGroup *sg, GdkPixbuf *pixbuf, const char *lbl, gpointer per_item_data, const char *data)
466 { 483 {
467 GtkWidget *item; 484 GtkWidget *item;
468 GtkWidget *hbox; 485 GtkWidget *hbox;
469 GtkWidget *image; 486 GtkWidget *image;
470 GtkWidget *label; 487 GtkWidget *label;
493 510
494 gtk_container_add(GTK_CONTAINER(item), hbox); 511 gtk_container_add(GTK_CONTAINER(item), hbox);
495 gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); 512 gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
496 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); 513 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
497 514
515 g_object_set_data(G_OBJECT (item), data, per_item_data);
498 g_object_set_data(G_OBJECT (item), "aop_per_item_data", per_item_data); 516 g_object_set_data(G_OBJECT (item), "aop_per_item_data", per_item_data);
499 517
500 pidgin_set_accessible_label(item, label); 518 pidgin_set_accessible_label(item, label);
501 519
502 return item; 520 return item;
521 }
522
523 static GdkPixbuf *
524 pidgin_create_prpl_icon_from_prpl(PurplePlugin *prpl, PidginPrplIconSize size, PurpleAccount *account)
525 {
526 PurplePluginProtocolInfo *prpl_info;
527 const char *protoname = NULL;
528 char buf[MAXPATHLEN];
529 char *filename = NULL;
530 GdkPixbuf *pixbuf;
531
532 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
533 if (prpl_info->list_icon == NULL)
534 return NULL;
535
536 protoname = prpl_info->list_icon(account, NULL);
537 if (protoname == NULL)
538 return NULL;
539
540 /*
541 * Status icons will be themeable too, and then it will look up
542 * protoname from the theme
543 */
544 g_snprintf(buf, sizeof(buf), "%s.png", protoname);
545
546 filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
547 size == PIDGIN_PRPL_ICON_SMALL ? "16" :
548 size == PIDGIN_PRPL_ICON_MEDIUM ? "22" : "48",
549 buf, NULL);
550 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
551 g_free(filename);
552
553 return pixbuf;
503 } 554 }
504 555
505 static GtkWidget * 556 static GtkWidget *
506 aop_option_menu_new(AopMenu *aop_menu, GCallback cb, gpointer user_data) 557 aop_option_menu_new(AopMenu *aop_menu, GCallback cb, gpointer user_data)
507 { 558 {
548 if (data == g_object_get_data(G_OBJECT(llItr->data), "aop_per_item_data")) { 599 if (data == g_object_get_data(G_OBJECT(llItr->data), "aop_per_item_data")) {
549 gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), idx); 600 gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), idx);
550 break; 601 break;
551 } 602 }
552 } 603 }
553 }
554
555 static GdkPixbuf *
556 get_prpl_pixbuf(PurplePluginProtocolInfo *prpl_info)
557 {
558 const char *proto_name;
559 GdkPixbuf *pixbuf = NULL;
560 char *filename;
561 char buf[256];
562
563 proto_name = prpl_info->list_icon(NULL, NULL);
564 g_return_val_if_fail(proto_name != NULL, NULL);
565
566 g_snprintf(buf, sizeof(buf), "%s.png", proto_name);
567 filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "16", buf, NULL);
568 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
569 g_free(filename);
570
571 return pixbuf;
572 } 604 }
573 605
574 static AopMenu * 606 static AopMenu *
575 create_protocols_menu(const char *default_proto_id) 607 create_protocols_menu(const char *default_proto_id)
576 { 608 {
600 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); 632 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
601 633
602 if (gtalk_name && strcmp(gtalk_name, plugin->info->name) < 0) { 634 if (gtalk_name && strcmp(gtalk_name, plugin->info->name) < 0) {
603 char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", 635 char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
604 "16", "google-talk.png", NULL); 636 "16", "google-talk.png", NULL);
637 GtkWidget *item;
638
605 pixbuf = gdk_pixbuf_new_from_file(filename, NULL); 639 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
606 g_free(filename); 640 g_free(filename);
607 641
608 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), 642 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
609 aop_menu_item_new(sg, pixbuf, gtalk_name, "prpl-jabber")); 643 item = aop_menu_item_new(sg, pixbuf, gtalk_name, "prpl-jabber", "protocol"));
644 g_object_set_data(G_OBJECT(item), "fake", GINT_TO_POINTER(1));
610 645
611 if (pixbuf) 646 if (pixbuf)
612 g_object_unref(pixbuf); 647 g_object_unref(pixbuf);
613 648
614 gtalk_name = NULL; 649 gtalk_name = NULL;
615 i++; 650 i++;
616 } 651 }
617 652
618 pixbuf = get_prpl_pixbuf(prpl_info); 653 pixbuf = pidgin_create_prpl_icon_from_prpl(plugin, PIDGIN_PRPL_ICON_SMALL, NULL);
619 654
620 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), 655 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
621 aop_menu_item_new(sg, pixbuf, plugin->info->name, plugin->info->id)); 656 aop_menu_item_new(sg, pixbuf, plugin->info->name, plugin->info->id, "protocol"));
622 657
623 if (pixbuf) 658 if (pixbuf)
624 g_object_unref(pixbuf); 659 g_object_unref(pixbuf);
625 660
626 if (default_proto_id != NULL && !strcmp(plugin->info->id, default_proto_id)) 661 if (default_proto_id != NULL && !strcmp(plugin->info->id, default_proto_id))
650 PurpleFilterAccountFunc filter_func, gboolean show_all) 685 PurpleFilterAccountFunc filter_func, gboolean show_all)
651 { 686 {
652 AopMenu *aop_menu = NULL; 687 AopMenu *aop_menu = NULL;
653 PurpleAccount *account; 688 PurpleAccount *account;
654 GdkPixbuf *pixbuf = NULL; 689 GdkPixbuf *pixbuf = NULL;
655 GList *list; 690 const GList *list;
656 GList *p; 691 const GList *p;
657 GtkSizeGroup *sg; 692 GtkSizeGroup *sg;
658 int i; 693 int i;
659 char buf[256]; 694 char buf[256];
660 695
661 if (show_all) 696 if (show_all)
668 aop_menu->menu = gtk_menu_new(); 703 aop_menu->menu = gtk_menu_new();
669 gtk_widget_show(aop_menu->menu); 704 gtk_widget_show(aop_menu->menu);
670 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); 705 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
671 706
672 for (p = list, i = 0; p != NULL; p = p->next, i++) { 707 for (p = list, i = 0; p != NULL; p = p->next, i++) {
673 PurplePluginProtocolInfo *prpl_info = NULL;
674 PurplePlugin *plugin; 708 PurplePlugin *plugin;
675 709
676 if (show_all) 710 if (show_all)
677 account = (PurpleAccount *)p->data; 711 account = (PurpleAccount *)p->data;
678 else { 712 else {
686 continue; 720 continue;
687 } 721 }
688 722
689 plugin = purple_find_prpl(purple_account_get_protocol_id(account)); 723 plugin = purple_find_prpl(purple_account_get_protocol_id(account));
690 724
691 if (plugin) 725 pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
692 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); 726
693 727 if (pixbuf) {
694 /* Load the image. */ 728 if (purple_account_is_disconnected(account) && show_all &&
695 if (prpl_info) { 729 purple_connections_get_all())
696 pixbuf = get_prpl_pixbuf(prpl_info); 730 gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
697
698 if (pixbuf) {
699 if (purple_account_is_disconnected(account) && show_all &&
700 purple_connections_get_all())
701 gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
702 }
703 } 731 }
704 732
705 if (purple_account_get_alias(account)) { 733 if (purple_account_get_alias(account)) {
706 g_snprintf(buf, sizeof(buf), "%s (%s) (%s)", 734 g_snprintf(buf, sizeof(buf), "%s (%s) (%s)",
707 purple_account_get_username(account), 735 purple_account_get_username(account),
712 purple_account_get_username(account), 740 purple_account_get_username(account),
713 purple_account_get_protocol_name(account)); 741 purple_account_get_protocol_name(account));
714 } 742 }
715 743
716 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), 744 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
717 aop_menu_item_new(sg, pixbuf, buf, account)); 745 aop_menu_item_new(sg, pixbuf, buf, account, "account"));
718 746
719 if (pixbuf) 747 if (pixbuf)
720 g_object_unref(pixbuf); 748 g_object_unref(pixbuf);
721 749
722 if (default_account && account == default_account) 750 if (default_account && account == default_account)
881 "accels", NULL); 909 "accels", NULL);
882 gtk_accel_map_load(filename); 910 gtk_accel_map_load(filename);
883 g_free(filename); 911 g_free(filename);
884 } 912 }
885 913
914 void pidgin_retrieve_user_info(PurpleConnection *conn, const char *name)
915 {
916 PurpleNotifyUserInfo *info = purple_notify_user_info_new();
917 purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving..."));
918 purple_notify_userinfo(conn, name, info, NULL, NULL);
919 purple_notify_user_info_destroy(info);
920 serv_get_info(conn, name);
921 }
922
886 gboolean 923 gboolean
887 pidgin_parse_x_im_contact(const char *msg, gboolean all_accounts, 924 pidgin_parse_x_im_contact(const char *msg, gboolean all_accounts,
888 PurpleAccount **ret_account, char **ret_protocol, 925 PurpleAccount **ret_account, char **ret_protocol,
889 char **ret_username, char **ret_alias) 926 char **ret_username, char **ret_alias)
890 { 927 {
956 *ret_alias = alias; 993 *ret_alias = alias;
957 994
958 /* Check for a compatible account. */ 995 /* Check for a compatible account. */
959 if (ret_account != NULL) 996 if (ret_account != NULL)
960 { 997 {
961 GList *list; 998 const GList *list;
962 PurpleAccount *account = NULL; 999 PurpleAccount *account = NULL;
963 GList *l; 1000 const GList *l;
964 const char *protoname; 1001 const char *protoname;
965 1002
966 if (all_accounts) 1003 if (all_accounts)
967 list = purple_accounts_get_all(); 1004 list = purple_accounts_get_all();
968 else 1005 else
1581 1618
1582 GdkPixbuf * 1619 GdkPixbuf *
1583 pidgin_create_prpl_icon(PurpleAccount *account, PidginPrplIconSize size) 1620 pidgin_create_prpl_icon(PurpleAccount *account, PidginPrplIconSize size)
1584 { 1621 {
1585 PurplePlugin *prpl; 1622 PurplePlugin *prpl;
1586 PurplePluginProtocolInfo *prpl_info;
1587 const char *protoname = NULL;
1588 char buf[256]; /* TODO: We should use a define for max file length */
1589 char *filename = NULL;
1590 GdkPixbuf *pixbuf;
1591 1623
1592 g_return_val_if_fail(account != NULL, NULL); 1624 g_return_val_if_fail(account != NULL, NULL);
1593 1625
1594 prpl = purple_find_prpl(purple_account_get_protocol_id(account)); 1626 prpl = purple_find_prpl(purple_account_get_protocol_id(account));
1595 if (prpl == NULL) 1627 if (prpl == NULL)
1596 return NULL; 1628 return NULL;
1597 1629 return pidgin_create_prpl_icon_from_prpl(prpl, size, account);
1598 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
1599 if (prpl_info->list_icon == NULL)
1600 return NULL;
1601
1602 protoname = prpl_info->list_icon(account, NULL);
1603 if (protoname == NULL)
1604 return NULL;
1605
1606 /*
1607 * Status icons will be themeable too, and then it will look up
1608 * protoname from the theme
1609 */
1610 g_snprintf(buf, sizeof(buf), "%s.png", protoname);
1611
1612 filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
1613 size == PIDGIN_PRPL_ICON_SMALL ? "16" :
1614 size == PIDGIN_PRPL_ICON_MEDIUM ? "22" : "48",
1615 buf, NULL);
1616 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
1617 g_free(filename);
1618
1619 return pixbuf;
1620 } 1630 }
1621 1631
1622 static void 1632 static void
1623 menu_action_cb(GtkMenuItem *item, gpointer object) 1633 menu_action_cb(GtkMenuItem *item, gpointer object)
1624 { 1634 {
1630 1640
1631 if (callback) 1641 if (callback)
1632 callback(object, data); 1642 callback(object, data);
1633 } 1643 }
1634 1644
1635 void 1645 GtkWidget *
1636 pidgin_append_menu_action(GtkWidget *menu, PurpleMenuAction *act, 1646 pidgin_append_menu_action(GtkWidget *menu, PurpleMenuAction *act,
1637 gpointer object) 1647 gpointer object)
1638 { 1648 {
1649 GtkWidget *menuitem;
1650
1639 if (act == NULL) { 1651 if (act == NULL) {
1640 pidgin_separator(menu); 1652 return pidgin_separator(menu);
1653 }
1654
1655 if (act->children == NULL) {
1656 menuitem = gtk_menu_item_new_with_mnemonic(act->label);
1657
1658 if (act->callback != NULL) {
1659 g_object_set_data(G_OBJECT(menuitem),
1660 "purplecallback",
1661 act->callback);
1662 g_object_set_data(G_OBJECT(menuitem),
1663 "purplecallbackdata",
1664 act->data);
1665 g_signal_connect(G_OBJECT(menuitem), "activate",
1666 G_CALLBACK(menu_action_cb),
1667 object);
1668 } else {
1669 gtk_widget_set_sensitive(menuitem, FALSE);
1670 }
1671
1672 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1641 } else { 1673 } else {
1642 GtkWidget *menuitem; 1674 GList *l = NULL;
1643 1675 GtkWidget *submenu = NULL;
1644 if (act->children == NULL) { 1676 GtkAccelGroup *group;
1645 menuitem = gtk_menu_item_new_with_mnemonic(act->label); 1677
1646 1678 menuitem = gtk_menu_item_new_with_mnemonic(act->label);
1647 if (act->callback != NULL) { 1679 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1648 g_object_set_data(G_OBJECT(menuitem), 1680
1649 "purplecallback", 1681 submenu = gtk_menu_new();
1650 act->callback); 1682 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
1651 g_object_set_data(G_OBJECT(menuitem), 1683
1652 "purplecallbackdata", 1684 group = gtk_menu_get_accel_group(GTK_MENU(menu));
1653 act->data); 1685 if (group) {
1654 g_signal_connect(G_OBJECT(menuitem), "activate", 1686 char *path = g_strdup_printf("%s/%s", GTK_MENU_ITEM(menuitem)->accel_path, act->label);
1655 G_CALLBACK(menu_action_cb), 1687 gtk_menu_set_accel_path(GTK_MENU(submenu), path);
1656 object); 1688 g_free(path);
1657 } else { 1689 gtk_menu_set_accel_group(GTK_MENU(submenu), group);
1658 gtk_widget_set_sensitive(menuitem, FALSE); 1690 }
1659 } 1691
1660 1692 for (l = act->children; l; l = l->next) {
1661 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); 1693 PurpleMenuAction *act = (PurpleMenuAction *)l->data;
1662 } else { 1694
1663 GList *l = NULL; 1695 pidgin_append_menu_action(submenu, act, object);
1664 GtkWidget *submenu = NULL; 1696 }
1665 GtkAccelGroup *group; 1697 g_list_free(act->children);
1666 1698 act->children = NULL;
1667 menuitem = gtk_menu_item_new_with_mnemonic(act->label); 1699 }
1668 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); 1700 purple_menu_action_free(act);
1669 1701 return menuitem;
1670 submenu = gtk_menu_new();
1671 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
1672
1673 group = gtk_menu_get_accel_group(GTK_MENU(menu));
1674 if (group) {
1675 char *path = g_strdup_printf("%s/%s", GTK_MENU_ITEM(menuitem)->accel_path, act->label);
1676 gtk_menu_set_accel_path(GTK_MENU(submenu), path);
1677 g_free(path);
1678 gtk_menu_set_accel_group(GTK_MENU(submenu), group);
1679 }
1680
1681 for (l = act->children; l; l = l->next) {
1682 PurpleMenuAction *act = (PurpleMenuAction *)l->data;
1683
1684 pidgin_append_menu_action(submenu, act, object);
1685 }
1686 g_list_free(act->children);
1687 act->children = NULL;
1688 }
1689 purple_menu_action_free(act);
1690 }
1691 } 1702 }
1692 1703
1693 #if GTK_CHECK_VERSION(2,3,0) 1704 #if GTK_CHECK_VERSION(2,3,0)
1694 # define NEW_STYLE_COMPLETION 1705 # define NEW_STYLE_COMPLETION
1695 #endif 1706 #endif

mercurial