pidgin/gtkutils.c

changeset 18545
5af898e91ec2
parent 18417
88a1c65eaad3
child 18672
da4db1be5d98
equal deleted inserted replaced
17398:1edf059a4a26 18545:5af898e91ec2
92 }; 92 };
93 93
94 void 94 void
95 pidgin_setup_imhtml(GtkWidget *imhtml) 95 pidgin_setup_imhtml(GtkWidget *imhtml)
96 { 96 {
97 PangoFontDescription *desc = NULL;
97 g_return_if_fail(imhtml != NULL); 98 g_return_if_fail(imhtml != NULL);
98 g_return_if_fail(GTK_IS_IMHTML(imhtml)); 99 g_return_if_fail(GTK_IS_IMHTML(imhtml));
99 100
100 g_signal_connect(G_OBJECT(imhtml), "url_clicked", 101 g_signal_connect(G_OBJECT(imhtml), "url_clicked",
101 G_CALLBACK(url_clicked_cb), NULL); 102 G_CALLBACK(url_clicked_cb), NULL);
102 103
103 pidgin_themes_smiley_themeize(imhtml); 104 pidgin_themes_smiley_themeize(imhtml);
104 105
105 gtk_imhtml_set_funcs(GTK_IMHTML(imhtml), &gtkimhtml_cbs); 106 gtk_imhtml_set_funcs(GTK_IMHTML(imhtml), &gtkimhtml_cbs);
106 107
107 /* Use the GNOME "document" font, if applicable */ 108 if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/use_theme_font")) {
108 if (purple_running_gnome()) { 109 const char *font = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/custom_font");
110 desc = pango_font_description_from_string(font);
111 } else if (purple_running_gnome()) {
112 /* Use the GNOME "document" font, if applicable */
109 char *path, *font; 113 char *path, *font;
110 PangoFontDescription *desc = NULL;
111 114
112 if ((path = g_find_program_in_path("gconftool-2"))) { 115 if ((path = g_find_program_in_path("gconftool-2"))) {
113 g_free(path); 116 g_free(path);
114 if (!g_spawn_command_line_sync( 117 if (!g_spawn_command_line_sync(
115 "gconftool-2 -g /desktop/gnome/interface/document_font_name", 118 "gconftool-2 -g /desktop/gnome/interface/document_font_name",
116 &font, NULL, NULL, NULL)) 119 &font, NULL, NULL, NULL))
117 return; 120 return;
118 } 121 }
119 desc = pango_font_description_from_string(font); 122 desc = pango_font_description_from_string(font);
120 g_free(font); 123 g_free(font);
121 124 }
122 if (desc) { 125
123 gtk_widget_modify_font(imhtml, desc); 126 if (desc) {
124 pango_font_description_free(desc); 127 gtk_widget_modify_font(imhtml, desc);
125 } 128 pango_font_description_free(desc);
126 } 129 }
130 }
131
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);
127 } 146 }
128 147
129 GtkWidget * 148 GtkWidget *
130 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)
131 { 150 {
155 gtk_widget_show(sep); 174 gtk_widget_show(sep);
156 } 175 }
157 176
158 sw = gtk_scrolled_window_new(NULL, NULL); 177 sw = gtk_scrolled_window_new(NULL, NULL);
159 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), 178 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
160 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); 179 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
161 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); 180 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
162 gtk_widget_show(sw); 181 gtk_widget_show(sw);
163 182
164 imhtml = gtk_imhtml_new(NULL, NULL); 183 imhtml = gtk_imhtml_new(NULL, NULL);
165 gtk_imhtml_set_editable(GTK_IMHTML(imhtml), editable); 184 gtk_imhtml_set_editable(GTK_IMHTML(imhtml), editable);
240 gtk_widget_hide(to_toggle); 259 gtk_widget_hide(to_toggle);
241 else 260 else
242 gtk_widget_show(to_toggle); 261 gtk_widget_show(to_toggle);
243 } 262 }
244 263
245 void pidgin_separator(GtkWidget *menu) 264 GtkWidget *pidgin_separator(GtkWidget *menu)
246 { 265 {
247 GtkWidget *menuitem; 266 GtkWidget *menuitem;
248 267
249 menuitem = gtk_separator_menu_item_new(); 268 menuitem = gtk_separator_menu_item_new();
250 gtk_widget_show(menuitem); 269 gtk_widget_show(menuitem);
251 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); 270 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
271 return menuitem;
252 } 272 }
253 273
254 GtkWidget *pidgin_new_item(GtkWidget *menu, const char *str) 274 GtkWidget *pidgin_new_item(GtkWidget *menu, const char *str)
255 { 275 {
256 GtkWidget *menuitem; 276 GtkWidget *menuitem;
457 ((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"));
458 } 478 }
459 } 479 }
460 480
461 static GtkWidget * 481 static GtkWidget *
462 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)
463 { 483 {
464 GtkWidget *item; 484 GtkWidget *item;
465 GtkWidget *hbox; 485 GtkWidget *hbox;
466 GtkWidget *image; 486 GtkWidget *image;
467 GtkWidget *label; 487 GtkWidget *label;
490 510
491 gtk_container_add(GTK_CONTAINER(item), hbox); 511 gtk_container_add(GTK_CONTAINER(item), hbox);
492 gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); 512 gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
493 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); 513 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
494 514
515 g_object_set_data(G_OBJECT (item), data, per_item_data);
495 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);
496 517
497 pidgin_set_accessible_label(item, label); 518 pidgin_set_accessible_label(item, label);
498 519
499 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 *tmp;
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 tmp = g_strconcat(protoname, ".png", NULL);
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 tmp, NULL);
550 g_free(tmp);
551
552 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
553 g_free(filename);
554
555 return pixbuf;
500 } 556 }
501 557
502 static GtkWidget * 558 static GtkWidget *
503 aop_option_menu_new(AopMenu *aop_menu, GCallback cb, gpointer user_data) 559 aop_option_menu_new(AopMenu *aop_menu, GCallback cb, gpointer user_data)
504 { 560 {
545 if (data == g_object_get_data(G_OBJECT(llItr->data), "aop_per_item_data")) { 601 if (data == g_object_get_data(G_OBJECT(llItr->data), "aop_per_item_data")) {
546 gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), idx); 602 gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), idx);
547 break; 603 break;
548 } 604 }
549 } 605 }
550 }
551
552 static GdkPixbuf *
553 get_prpl_pixbuf(PurplePluginProtocolInfo *prpl_info)
554 {
555 const char *proto_name;
556 GdkPixbuf *pixbuf = NULL;
557 char *filename;
558 char buf[256];
559
560 proto_name = prpl_info->list_icon(NULL, NULL);
561 g_return_val_if_fail(proto_name != NULL, NULL);
562
563 g_snprintf(buf, sizeof(buf), "%s.png", proto_name);
564 filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "16", buf, NULL);
565 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
566 g_free(filename);
567
568 return pixbuf;
569 } 606 }
570 607
571 static AopMenu * 608 static AopMenu *
572 create_protocols_menu(const char *default_proto_id) 609 create_protocols_menu(const char *default_proto_id)
573 { 610 {
597 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); 634 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
598 635
599 if (gtalk_name && strcmp(gtalk_name, plugin->info->name) < 0) { 636 if (gtalk_name && strcmp(gtalk_name, plugin->info->name) < 0) {
600 char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", 637 char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
601 "16", "google-talk.png", NULL); 638 "16", "google-talk.png", NULL);
639 GtkWidget *item;
640
602 pixbuf = gdk_pixbuf_new_from_file(filename, NULL); 641 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
603 g_free(filename); 642 g_free(filename);
604 643
605 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), 644 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
606 aop_menu_item_new(sg, pixbuf, gtalk_name, "prpl-jabber")); 645 item = aop_menu_item_new(sg, pixbuf, gtalk_name, "prpl-jabber", "protocol"));
646 g_object_set_data(G_OBJECT(item), "fake", GINT_TO_POINTER(1));
607 647
608 if (pixbuf) 648 if (pixbuf)
609 g_object_unref(pixbuf); 649 g_object_unref(pixbuf);
610 650
611 gtalk_name = NULL; 651 gtalk_name = NULL;
612 } 652 i++;
613 653 }
614 pixbuf = get_prpl_pixbuf(prpl_info); 654
655 pixbuf = pidgin_create_prpl_icon_from_prpl(plugin, PIDGIN_PRPL_ICON_SMALL, NULL);
615 656
616 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), 657 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
617 aop_menu_item_new(sg, pixbuf, plugin->info->name, plugin->info->id)); 658 aop_menu_item_new(sg, pixbuf, plugin->info->name, plugin->info->id, "protocol"));
618 659
619 if (pixbuf) 660 if (pixbuf)
620 g_object_unref(pixbuf); 661 g_object_unref(pixbuf);
621 662
622 if (default_proto_id != NULL && !strcmp(plugin->info->id, default_proto_id)) 663 if (default_proto_id != NULL && !strcmp(plugin->info->id, default_proto_id))
664 aop_menu->menu = gtk_menu_new(); 705 aop_menu->menu = gtk_menu_new();
665 gtk_widget_show(aop_menu->menu); 706 gtk_widget_show(aop_menu->menu);
666 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); 707 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
667 708
668 for (p = list, i = 0; p != NULL; p = p->next, i++) { 709 for (p = list, i = 0; p != NULL; p = p->next, i++) {
669 PurplePluginProtocolInfo *prpl_info = NULL;
670 PurplePlugin *plugin; 710 PurplePlugin *plugin;
671 711
672 if (show_all) 712 if (show_all)
673 account = (PurpleAccount *)p->data; 713 account = (PurpleAccount *)p->data;
674 else { 714 else {
682 continue; 722 continue;
683 } 723 }
684 724
685 plugin = purple_find_prpl(purple_account_get_protocol_id(account)); 725 plugin = purple_find_prpl(purple_account_get_protocol_id(account));
686 726
687 if (plugin) 727 pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL);
688 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); 728
689 729 if (pixbuf) {
690 /* Load the image. */ 730 if (purple_account_is_disconnected(account) && show_all &&
691 if (prpl_info) { 731 purple_connections_get_all())
692 pixbuf = get_prpl_pixbuf(prpl_info); 732 gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
693
694 if (pixbuf) {
695 if (purple_account_is_disconnected(account) && show_all &&
696 purple_connections_get_all())
697 gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
698 }
699 } 733 }
700 734
701 if (purple_account_get_alias(account)) { 735 if (purple_account_get_alias(account)) {
702 g_snprintf(buf, sizeof(buf), "%s (%s) (%s)", 736 g_snprintf(buf, sizeof(buf), "%s (%s) (%s)",
703 purple_account_get_username(account), 737 purple_account_get_username(account),
708 purple_account_get_username(account), 742 purple_account_get_username(account),
709 purple_account_get_protocol_name(account)); 743 purple_account_get_protocol_name(account));
710 } 744 }
711 745
712 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), 746 gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
713 aop_menu_item_new(sg, pixbuf, buf, account)); 747 aop_menu_item_new(sg, pixbuf, buf, account, "account"));
714 748
715 if (pixbuf) 749 if (pixbuf)
716 g_object_unref(pixbuf); 750 g_object_unref(pixbuf);
717 751
718 if (default_account && account == default_account) 752 if (default_account && account == default_account)
877 "accels", NULL); 911 "accels", NULL);
878 gtk_accel_map_load(filename); 912 gtk_accel_map_load(filename);
879 g_free(filename); 913 g_free(filename);
880 } 914 }
881 915
916 static void
917 show_retrieveing_info(PurpleConnection *conn, const char *name)
918 {
919 PurpleNotifyUserInfo *info = purple_notify_user_info_new();
920 purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving..."));
921 purple_notify_userinfo(conn, name, info, NULL, NULL);
922 purple_notify_user_info_destroy(info);
923 }
924
925 void pidgin_retrieve_user_info(PurpleConnection *conn, const char *name)
926 {
927 show_retrieveing_info(conn, name);
928 serv_get_info(conn, name);
929 }
930
931 void pidgin_retrieve_user_info_in_chat(PurpleConnection *conn, const char *name, int chat)
932 {
933 char *who = NULL;
934 PurplePluginProtocolInfo *prpl_info = NULL;
935
936 if (chat < 0) {
937 pidgin_retrieve_user_info(conn, name);
938 return;
939 }
940
941 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(conn->prpl);
942 if (prpl_info == NULL || prpl_info->get_cb_info == NULL) {
943 pidgin_retrieve_user_info(conn, name);
944 return;
945 }
946
947 if (prpl_info->get_cb_real_name)
948 who = prpl_info->get_cb_real_name(conn, chat, name);
949 show_retrieveing_info(conn, who ? who : name);
950 prpl_info->get_cb_info(conn, chat, name);
951 g_free(who);
952 }
953
882 gboolean 954 gboolean
883 pidgin_parse_x_im_contact(const char *msg, gboolean all_accounts, 955 pidgin_parse_x_im_contact(const char *msg, gboolean all_accounts,
884 PurpleAccount **ret_account, char **ret_protocol, 956 PurpleAccount **ret_account, char **ret_protocol,
885 char **ret_username, char **ret_alias) 957 char **ret_username, char **ret_alias)
886 { 958 {
1073 const gchar *existing_name; 1145 const gchar *existing_name;
1074 1146
1075 acc = gtk_widget_get_accessible (w); 1147 acc = gtk_widget_get_accessible (w);
1076 label = gtk_widget_get_accessible (l); 1148 label = gtk_widget_get_accessible (l);
1077 1149
1150 /* Make sure mnemonics work */
1151 gtk_label_set_mnemonic_widget(GTK_LABEL(l), w);
1152
1078 /* If this object has no name, set it's name with the label text */ 1153 /* If this object has no name, set it's name with the label text */
1079 existing_name = atk_object_get_name (acc); 1154 existing_name = atk_object_get_name (acc);
1080 if (!existing_name) { 1155 if (!existing_name) {
1081 label_text = gtk_label_get_text (GTK_LABEL(l)); 1156 label_text = gtk_label_get_text (GTK_LABEL(l));
1082 if (label_text) 1157 if (label_text)
1096 relation = atk_relation_new (rel_obj, 1, ATK_RELATION_LABEL_FOR); 1171 relation = atk_relation_new (rel_obj, 1, ATK_RELATION_LABEL_FOR);
1097 atk_relation_set_add (set, relation); 1172 atk_relation_set_add (set, relation);
1098 g_object_unref (relation); 1173 g_object_unref (relation);
1099 } 1174 }
1100 1175
1101 #if GTK_CHECK_VERSION(2,2,0) 1176 void
1102 static void 1177 pidgin_menu_position_func_helper(GtkMenu *menu,
1103 pidgin_menu_position_func(GtkMenu *menu,
1104 gint *x, 1178 gint *x,
1105 gint *y, 1179 gint *y,
1106 gboolean *push_in, 1180 gboolean *push_in,
1107 gpointer data) 1181 gpointer data)
1108 { 1182 {
1183 #if GTK_CHECK_VERSION(2,2,0)
1109 GtkWidget *widget; 1184 GtkWidget *widget;
1110 GtkRequisition requisition; 1185 GtkRequisition requisition;
1111 GdkScreen *screen; 1186 GdkScreen *screen;
1112 GdkRectangle monitor; 1187 GdkRectangle monitor;
1113 gint monitor_num; 1188 gint monitor_num;
1244 } 1319 }
1245 else 1320 else
1246 { 1321 {
1247 *y = monitor.y; 1322 *y = monitor.y;
1248 } 1323 }
1249 }
1250
1251 #endif 1324 #endif
1325 }
1326
1252 1327
1253 void 1328 void
1254 pidgin_treeview_popup_menu_position_func(GtkMenu *menu, 1329 pidgin_treeview_popup_menu_position_func(GtkMenu *menu,
1255 gint *x, 1330 gint *x,
1256 gint *y, 1331 gint *y,
1268 gtk_tree_view_get_cursor (tv, &path, &col); 1343 gtk_tree_view_get_cursor (tv, &path, &col);
1269 gtk_tree_view_get_cell_area (tv, path, col, &rect); 1344 gtk_tree_view_get_cell_area (tv, path, col, &rect);
1270 1345
1271 *x += rect.x+rect.width; 1346 *x += rect.x+rect.width;
1272 *y += rect.y+rect.height+ythickness; 1347 *y += rect.y+rect.height+ythickness;
1273 #if GTK_CHECK_VERSION(2,2,0) 1348 pidgin_menu_position_func_helper(menu, x, y, push_in, data);
1274 pidgin_menu_position_func (menu, x, y, push_in, data);
1275 #endif
1276 } 1349 }
1277 1350
1278 enum { 1351 enum {
1279 DND_FILE_TRANSFER, 1352 DND_FILE_TRANSFER,
1280 DND_IM_IMAGE, 1353 DND_IM_IMAGE,
1452 account, who, NULL, 1525 account, who, NULL,
1453 data, (GCallback)dnd_set_icon_ok_cb, (GCallback)dnd_set_icon_cancel_cb); 1526 data, (GCallback)dnd_set_icon_ok_cb, (GCallback)dnd_set_icon_cancel_cb);
1454 else 1527 else
1455 purple_request_choice(NULL, NULL, 1528 purple_request_choice(NULL, NULL,
1456 _("You have dragged an image"), 1529 _("You have dragged an image"),
1457 (ft ? _("You can send this image as a file transfer or " 1530 (ft ? _("You can send this image as a file transfer, or use it as the buddy icon for this user.") :
1458 "embed it into this message, or use it as the buddy icon for this user.") :
1459 _("You can insert this image into this message, or use it as the buddy icon for this user")), 1531 _("You can insert this image into this message, or use it as the buddy icon for this user")),
1460 (ft ? DND_FILE_TRANSFER : DND_IM_IMAGE), 1532 (ft ? DND_FILE_TRANSFER : DND_IM_IMAGE),
1461 "OK", (GCallback)dnd_image_ok_callback, 1533 "OK", (GCallback)dnd_image_ok_callback,
1462 "Cancel", (GCallback)dnd_image_cancel_callback, 1534 "Cancel", (GCallback)dnd_image_cancel_callback,
1463 account, who, NULL, 1535 account, who, NULL,
1578 1650
1579 GdkPixbuf * 1651 GdkPixbuf *
1580 pidgin_create_prpl_icon(PurpleAccount *account, PidginPrplIconSize size) 1652 pidgin_create_prpl_icon(PurpleAccount *account, PidginPrplIconSize size)
1581 { 1653 {
1582 PurplePlugin *prpl; 1654 PurplePlugin *prpl;
1583 PurplePluginProtocolInfo *prpl_info;
1584 const char *protoname = NULL;
1585 char buf[256]; /* TODO: We should use a define for max file length */
1586 char *filename = NULL;
1587 GdkPixbuf *pixbuf;
1588 1655
1589 g_return_val_if_fail(account != NULL, NULL); 1656 g_return_val_if_fail(account != NULL, NULL);
1590 1657
1591 prpl = purple_find_prpl(purple_account_get_protocol_id(account)); 1658 prpl = purple_find_prpl(purple_account_get_protocol_id(account));
1592 if (prpl == NULL) 1659 if (prpl == NULL)
1593 return NULL; 1660 return NULL;
1594 1661 return pidgin_create_prpl_icon_from_prpl(prpl, size, account);
1595 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
1596 if (prpl_info->list_icon == NULL)
1597 return NULL;
1598
1599 protoname = prpl_info->list_icon(account, NULL);
1600 if (protoname == NULL)
1601 return NULL;
1602
1603 /*
1604 * Status icons will be themeable too, and then it will look up
1605 * protoname from the theme
1606 */
1607 g_snprintf(buf, sizeof(buf), "%s.png", protoname);
1608
1609 filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
1610 size == PIDGIN_PRPL_ICON_SMALL ? "16" :
1611 size == PIDGIN_PRPL_ICON_MEDIUM ? "22" : "48",
1612 buf, NULL);
1613 pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
1614 g_free(filename);
1615
1616 return pixbuf;
1617 } 1662 }
1618 1663
1619 static void 1664 static void
1620 menu_action_cb(GtkMenuItem *item, gpointer object) 1665 menu_action_cb(GtkMenuItem *item, gpointer object)
1621 { 1666 {
1627 1672
1628 if (callback) 1673 if (callback)
1629 callback(object, data); 1674 callback(object, data);
1630 } 1675 }
1631 1676
1632 void 1677 GtkWidget *
1633 pidgin_append_menu_action(GtkWidget *menu, PurpleMenuAction *act, 1678 pidgin_append_menu_action(GtkWidget *menu, PurpleMenuAction *act,
1634 gpointer object) 1679 gpointer object)
1635 { 1680 {
1681 GtkWidget *menuitem;
1682
1636 if (act == NULL) { 1683 if (act == NULL) {
1637 pidgin_separator(menu); 1684 return pidgin_separator(menu);
1685 }
1686
1687 if (act->children == NULL) {
1688 menuitem = gtk_menu_item_new_with_mnemonic(act->label);
1689
1690 if (act->callback != NULL) {
1691 g_object_set_data(G_OBJECT(menuitem),
1692 "purplecallback",
1693 act->callback);
1694 g_object_set_data(G_OBJECT(menuitem),
1695 "purplecallbackdata",
1696 act->data);
1697 g_signal_connect(G_OBJECT(menuitem), "activate",
1698 G_CALLBACK(menu_action_cb),
1699 object);
1700 } else {
1701 gtk_widget_set_sensitive(menuitem, FALSE);
1702 }
1703
1704 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1638 } else { 1705 } else {
1639 GtkWidget *menuitem; 1706 GList *l = NULL;
1640 1707 GtkWidget *submenu = NULL;
1641 if (act->children == NULL) { 1708 GtkAccelGroup *group;
1642 menuitem = gtk_menu_item_new_with_mnemonic(act->label); 1709
1643 1710 menuitem = gtk_menu_item_new_with_mnemonic(act->label);
1644 if (act->callback != NULL) { 1711 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1645 g_object_set_data(G_OBJECT(menuitem), 1712
1646 "purplecallback", 1713 submenu = gtk_menu_new();
1647 act->callback); 1714 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
1648 g_object_set_data(G_OBJECT(menuitem), 1715
1649 "purplecallbackdata", 1716 group = gtk_menu_get_accel_group(GTK_MENU(menu));
1650 act->data); 1717 if (group) {
1651 g_signal_connect(G_OBJECT(menuitem), "activate", 1718 char *path = g_strdup_printf("%s/%s", GTK_MENU_ITEM(menuitem)->accel_path, act->label);
1652 G_CALLBACK(menu_action_cb), 1719 gtk_menu_set_accel_path(GTK_MENU(submenu), path);
1653 object); 1720 g_free(path);
1654 } else { 1721 gtk_menu_set_accel_group(GTK_MENU(submenu), group);
1655 gtk_widget_set_sensitive(menuitem, FALSE); 1722 }
1656 } 1723
1657 1724 for (l = act->children; l; l = l->next) {
1658 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); 1725 PurpleMenuAction *act = (PurpleMenuAction *)l->data;
1659 } else { 1726
1660 GList *l = NULL; 1727 pidgin_append_menu_action(submenu, act, object);
1661 GtkWidget *submenu = NULL; 1728 }
1662 GtkAccelGroup *group; 1729 g_list_free(act->children);
1663 1730 act->children = NULL;
1664 menuitem = gtk_menu_item_new_with_mnemonic(act->label); 1731 }
1665 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); 1732 purple_menu_action_free(act);
1666 1733 return menuitem;
1667 submenu = gtk_menu_new();
1668 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
1669
1670 group = gtk_menu_get_accel_group(GTK_MENU(menu));
1671 if (group) {
1672 char *path = g_strdup_printf("%s/%s", GTK_MENU_ITEM(menuitem)->accel_path, act->label);
1673 gtk_menu_set_accel_path(GTK_MENU(submenu), path);
1674 g_free(path);
1675 gtk_menu_set_accel_group(GTK_MENU(submenu), group);
1676 }
1677
1678 for (l = act->children; l; l = l->next) {
1679 PurpleMenuAction *act = (PurpleMenuAction *)l->data;
1680
1681 pidgin_append_menu_action(submenu, act, object);
1682 }
1683 g_list_free(act->children);
1684 act->children = NULL;
1685 }
1686 purple_menu_action_free(act);
1687 }
1688 } 1734 }
1689 1735
1690 #if GTK_CHECK_VERSION(2,3,0) 1736 #if GTK_CHECK_VERSION(2,3,0)
1691 # define NEW_STYLE_COMPLETION 1737 # define NEW_STYLE_COMPLETION
1692 #endif 1738 #endif
2033 #endif 2079 #endif
2034 2080
2035 static void 2081 static void
2036 screenname_autocomplete_destroyed_cb(GtkWidget *widget, gpointer data) 2082 screenname_autocomplete_destroyed_cb(GtkWidget *widget, gpointer data)
2037 { 2083 {
2084 g_free(data);
2038 purple_signals_disconnect_by_handle(widget); 2085 purple_signals_disconnect_by_handle(widget);
2039 } 2086 }
2040 2087
2041 static void 2088 static void
2042 repopulate_autocomplete(gpointer something, gpointer data) 2089 repopulate_autocomplete(gpointer something, gpointer data)
2114 purple_signal_connect(purple_accounts_get_handle(), "account-added", entry, 2161 purple_signal_connect(purple_accounts_get_handle(), "account-added", entry,
2115 PURPLE_CALLBACK(repopulate_autocomplete), cb_data); 2162 PURPLE_CALLBACK(repopulate_autocomplete), cb_data);
2116 purple_signal_connect(purple_accounts_get_handle(), "account-removed", entry, 2163 purple_signal_connect(purple_accounts_get_handle(), "account-removed", entry,
2117 PURPLE_CALLBACK(repopulate_autocomplete), cb_data); 2164 PURPLE_CALLBACK(repopulate_autocomplete), cb_data);
2118 2165
2119 g_signal_connect(G_OBJECT(entry), "destroy", G_CALLBACK(screenname_autocomplete_destroyed_cb), NULL); 2166 g_signal_connect(G_OBJECT(entry), "destroy", G_CALLBACK(screenname_autocomplete_destroyed_cb), data);
2120 } 2167 }
2121 2168
2122 void pidgin_set_cursor(GtkWidget *widget, GdkCursorType cursor_type) 2169 void pidgin_set_cursor(GtkWidget *widget, GdkCursorType cursor_type)
2123 { 2170 {
2124 GdkCursor *cursor; 2171 GdkCursor *cursor;
3029 rowstride = gdk_pixbuf_get_rowstride (pixbuf); 3076 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
3030 pixels = gdk_pixbuf_get_pixels (pixbuf); 3077 pixels = gdk_pixbuf_get_pixels (pixbuf);
3031 3078
3032 row = pixels; 3079 row = pixels;
3033 for (i = 3; i < rowstride; i+=4) { 3080 for (i = 3; i < rowstride; i+=4) {
3034 if (row[i] != 0xff) 3081 if (row[i] < 0xfe)
3035 return FALSE; 3082 return FALSE;
3036 } 3083 }
3037 3084
3038 for (i = 1; i < height - 1; i++) { 3085 for (i = 1; i < height - 1; i++) {
3039 row = pixels + (i*rowstride); 3086 row = pixels + (i*rowstride);
3040 if (row[3] != 0xff || row[rowstride-1] != 0xff) { 3087 if (row[3] < 0xfe || row[rowstride-1] < 0xfe) {
3041 return FALSE; 3088 return FALSE;
3042 } 3089 }
3043 } 3090 }
3044 3091
3045 row = pixels + ((height-1) * rowstride); 3092 row = pixels + ((height-1) * rowstride);
3046 for (i = 3; i < rowstride; i+=4) { 3093 for (i = 3; i < rowstride; i+=4) {
3047 if (row[i] != 0xff) 3094 if (row[i] < 0xfe)
3048 return FALSE; 3095 return FALSE;
3049 } 3096 }
3050 3097
3051 return TRUE; 3098 return TRUE;
3099 }
3100
3101 void pidgin_gdk_pixbuf_make_round(GdkPixbuf *pixbuf) {
3102 int width, height, rowstride;
3103 guchar *pixels;
3104 if (!gdk_pixbuf_get_has_alpha(pixbuf))
3105 return;
3106 width = gdk_pixbuf_get_width(pixbuf);
3107 height = gdk_pixbuf_get_height(pixbuf);
3108 rowstride = gdk_pixbuf_get_rowstride(pixbuf);
3109 pixels = gdk_pixbuf_get_pixels(pixbuf);
3110
3111 if (width < 6 || height < 6)
3112 return;
3113 /* Top left */
3114 pixels[3] = 0;
3115 pixels[7] = 0x80;
3116 pixels[11] = 0xC0;
3117 pixels[rowstride + 3] = 0x80;
3118 pixels[rowstride * 2 + 3] = 0xC0;
3119
3120 /* Top right */
3121 pixels[width * 4 - 1] = 0;
3122 pixels[width * 4 - 5] = 0x80;
3123 pixels[width * 4 - 9] = 0xC0;
3124 pixels[rowstride + (width * 4) - 1] = 0x80;
3125 pixels[(2 * rowstride) + (width * 4) - 1] = 0xC0;
3126
3127 /* Bottom left */
3128 pixels[(height - 1) * rowstride + 3] = 0;
3129 pixels[(height - 1) * rowstride + 7] = 0x80;
3130 pixels[(height - 1) * rowstride + 11] = 0xC0;
3131 pixels[(height - 2) * rowstride + 3] = 0x80;
3132 pixels[(height - 3) * rowstride + 3] = 0xC0;
3133
3134 /* Bottom right */
3135 pixels[height * rowstride - 1] = 0;
3136 pixels[(height - 1) * rowstride - 1] = 0x80;
3137 pixels[(height - 2) * rowstride - 1] = 0xC0;
3138 pixels[height * rowstride - 5] = 0x80;
3139 pixels[height * rowstride - 9] = 0xC0;
3140 }
3141
3142 const char *pidgin_get_dim_grey_string(GtkWidget *widget) {
3143 static char dim_grey_string[8] = "";
3144 GtkStyle *style;
3145
3146 if (!widget)
3147 return "dim grey";
3148
3149 style = gtk_widget_get_style(widget);
3150 if (!style)
3151 return "dim grey";
3152
3153 snprintf(dim_grey_string, sizeof(dim_grey_string), "#%02x%02x%02x",
3154 style->text_aa[GTK_STATE_NORMAL].red >> 8,
3155 style->text_aa[GTK_STATE_NORMAL].green >> 8,
3156 style->text_aa[GTK_STATE_NORMAL].blue >> 8);
3157 return dim_grey_string;
3052 } 3158 }
3053 3159
3054 #if !GTK_CHECK_VERSION(2,2,0) 3160 #if !GTK_CHECK_VERSION(2,2,0)
3055 GtkTreePath * 3161 GtkTreePath *
3056 gtk_tree_path_new_from_indices (gint first_index, ...) 3162 gtk_tree_path_new_from_indices (gint first_index, ...)
3073 va_end (args); 3179 va_end (args);
3074 3180
3075 return path; 3181 return path;
3076 } 3182 }
3077 #endif 3183 #endif
3184

mercurial