3 * Pidgin is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
7 * This program is free software; you can redistribute it and/or modify
8 * under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
25 #include "image-store.h"
29 #include "pidginstock.h"
30 #include "smiley-custom.h"
31 #include "smiley-list.h"
35 #include "gtkdialogs.h"
36 #include "gtkwebviewtoolbar.h"
37 #include "gtksmiley-manager.h"
38 #include "gtksmiley-theme.h"
41 #include <gdk/gdkkeysyms.h>
43 #include "gtk3compat.h"
45 #define PIDGIN_WEBVIEWTOOLBAR_DEFAULT_FONT "sans-serif"
46 #define PIDGIN_WEBVIEWTOOLBAR_DEFAULT_BGCOLOR "inherit"
47 #define PIDGIN_WEBVIEWTOOLBAR_DEFAULT_FGCOLOR "#000000"
49 /******************************************************************************
51 *****************************************************************************/
53 typedef struct _PidginWebViewToolbarPrivate
{
54 PurpleConversation
*active_conv
;
59 GtkWidget
*font_label
;
67 GtkAction
*larger_size
;
69 GtkAction
*normal_size
;
71 GtkAction
*smaller_size
;
79 GtkWidget
*insert_menu
;
87 GtkWidget
*font_dialog
;
88 GtkWidget
*fgcolor_dialog
;
89 GtkWidget
*bgcolor_dialog
;
90 GtkWidget
*link_dialog
;
91 GtkWidget
*smiley_dialog
;
92 GtkWidget
*image_dialog
;
94 gboolean allow_smileys
;
95 } PidginWebViewToolbarPrivate
;
97 /******************************************************************************
99 *****************************************************************************/
101 G_DEFINE_TYPE_WITH_PRIVATE(PidginWebViewToolbar
, pidgin_webviewtoolbar
,
104 /******************************************************************************
106 *****************************************************************************/
109 toggle_action_set_active_block(GtkToggleAction
*action
, gboolean is_active
,
110 PidginWebViewToolbar
*toolbar
);
112 /******************************************************************************
114 *****************************************************************************/
117 pidgin_color_parse(const gchar
*str
, GdkRGBA
*color
)
124 while (isspace(str
[0]))
131 color
= &dummy_color
;
133 if (strcmp(str
, "inherit") == 0) {
137 if (!gdk_rgba_parse(color
, str
)) {
141 /* FALSE for fully transparent color (same behavior as with "inherit") */
142 return color
->alpha
> 0;
146 pidgin_color_to_str(GdkRGBA
*color
)
148 return g_strdup_printf("#%02X%02X%02X",
149 (unsigned int)(color
->red
* 255),
150 (unsigned int)(color
->green
* 255),
151 (unsigned int)(color
->blue
* 255));
155 do_bold(GtkAction
*bold
, PidginWebViewToolbar
*toolbar
)
157 g_return_if_fail(toolbar
!= NULL
);
158 pidgin_webview_toggle_bold(PIDGIN_WEBVIEW(toolbar
->webview
));
159 gtk_widget_grab_focus(toolbar
->webview
);
163 do_italic(GtkAction
*italic
, PidginWebViewToolbar
*toolbar
)
165 g_return_if_fail(toolbar
!= NULL
);
166 pidgin_webview_toggle_italic(PIDGIN_WEBVIEW(toolbar
->webview
));
167 gtk_widget_grab_focus(toolbar
->webview
);
171 do_underline(GtkAction
*underline
, PidginWebViewToolbar
*toolbar
)
173 g_return_if_fail(toolbar
!= NULL
);
174 pidgin_webview_toggle_underline(PIDGIN_WEBVIEW(toolbar
->webview
));
175 gtk_widget_grab_focus(toolbar
->webview
);
179 do_strikethrough(GtkAction
*strikethrough
, PidginWebViewToolbar
*toolbar
)
181 g_return_if_fail(toolbar
!= NULL
);
182 pidgin_webview_toggle_strike(PIDGIN_WEBVIEW(toolbar
->webview
));
183 gtk_widget_grab_focus(toolbar
->webview
);
187 do_small(GtkAction
*small
, PidginWebViewToolbar
*toolbar
)
189 g_return_if_fail(toolbar
!= NULL
);
190 pidgin_webview_font_shrink(PIDGIN_WEBVIEW(toolbar
->webview
));
191 gtk_widget_grab_focus(toolbar
->webview
);
195 do_big(GtkAction
*large
, PidginWebViewToolbar
*toolbar
)
197 g_return_if_fail(toolbar
);
198 pidgin_webview_font_grow(PIDGIN_WEBVIEW(toolbar
->webview
));
199 gtk_widget_grab_focus(toolbar
->webview
);
203 destroy_toolbar_font(PidginWebViewToolbar
*toolbar
)
205 PidginWebViewToolbarPrivate
*priv
=
206 pidgin_webviewtoolbar_get_instance_private(toolbar
);
208 if (priv
->font_dialog
!= NULL
)
210 gtk_widget_destroy(priv
->font_dialog
);
211 priv
->font_dialog
= NULL
;
216 apply_font(GtkDialog
*dialog
, gint response
, PidginWebViewToolbar
*toolbar
)
218 /* this could be expanded to include font size, weight, etc.
219 but for now only works with font face */
220 gchar
*fontname
= NULL
;
222 if (response
== GTK_RESPONSE_OK
)
223 fontname
= gtk_font_chooser_get_font(GTK_FONT_CHOOSER(dialog
));
226 PangoFontDescription
*desc
;
227 const gchar
*family_name
;
229 desc
= pango_font_description_from_string(fontname
);
230 family_name
= pango_font_description_get_family(desc
);
233 pidgin_webview_toggle_fontface(PIDGIN_WEBVIEW(toolbar
->webview
),
237 pango_font_description_free(desc
);
240 pidgin_webview_toggle_fontface(PIDGIN_WEBVIEW(toolbar
->webview
),
241 PIDGIN_WEBVIEWTOOLBAR_DEFAULT_FONT
);
244 destroy_toolbar_font(toolbar
);
248 toggle_font(GtkAction
*font
, PidginWebViewToolbar
*toolbar
)
250 PidginWebViewToolbarPrivate
*priv
=
251 pidgin_webviewtoolbar_get_instance_private(toolbar
);
253 if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(font
))) {
254 char *fontname
= pidgin_webview_get_current_fontface(PIDGIN_WEBVIEW(toolbar
->webview
));
256 if (!priv
->font_dialog
) {
258 window
= GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(toolbar
)));
259 priv
->font_dialog
= gtk_font_chooser_dialog_new(_("Select Font"), window
);
262 char *fonttif
= g_strdup_printf("%s 12", fontname
);
263 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(priv
->font_dialog
),
267 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(priv
->font_dialog
),
268 PIDGIN_DEFAULT_FONT_FACE
);
271 g_signal_connect(G_OBJECT(priv
->font_dialog
), "response",
272 G_CALLBACK(apply_font
), toolbar
);
275 gtk_window_present(GTK_WINDOW(priv
->font_dialog
));
279 pidgin_webview_toggle_fontface(PIDGIN_WEBVIEW(toolbar
->webview
),
280 PIDGIN_WEBVIEWTOOLBAR_DEFAULT_FONT
);
281 destroy_toolbar_font(toolbar
);
284 gtk_widget_grab_focus(toolbar
->webview
);
288 destroy_toolbar_fgcolor(GtkWidget
*widget
, GdkEvent
*event
,
289 PidginWebViewToolbar
*toolbar
)
291 PidginWebViewToolbarPrivate
*priv
=
292 pidgin_webviewtoolbar_get_instance_private(toolbar
);
294 if (widget
!= NULL
) {
295 pidgin_webview_toggle_forecolor(
296 PIDGIN_WEBVIEW(toolbar
->webview
),
297 PIDGIN_WEBVIEWTOOLBAR_DEFAULT_FGCOLOR
);
300 if (priv
->fgcolor_dialog
!= NULL
) {
301 gtk_widget_destroy(priv
->fgcolor_dialog
);
302 priv
->fgcolor_dialog
= NULL
;
309 do_fgcolor(GtkDialog
*dialog
, gint response
, gpointer _toolbar
)
311 PidginWebViewToolbar
*toolbar
= _toolbar
;
315 if (response
!= GTK_RESPONSE_OK
) {
316 destroy_toolbar_fgcolor(GTK_WIDGET(toolbar
), NULL
, toolbar
);
320 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog
), &text_color
);
321 open_tag
= pidgin_color_to_str(&text_color
);
322 pidgin_webview_toggle_forecolor(PIDGIN_WEBVIEW(toolbar
->webview
),
326 destroy_toolbar_fgcolor(NULL
, NULL
, toolbar
);
330 toggle_fg_color(GtkAction
*color
, PidginWebViewToolbar
*toolbar
)
332 PidginWebViewToolbarPrivate
*priv
=
333 pidgin_webviewtoolbar_get_instance_private(toolbar
);
335 if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(color
))) {
337 gchar
*color
= pidgin_webview_get_current_forecolor(
338 PIDGIN_WEBVIEW(toolbar
->webview
));
340 if (!priv
->fgcolor_dialog
) {
341 priv
->fgcolor_dialog
= gtk_color_chooser_dialog_new(
342 _("Select Text Color"), GTK_WINDOW(
343 gtk_widget_get_ancestor(toolbar
->webview
,
345 gtk_color_chooser_set_use_alpha(
346 GTK_COLOR_CHOOSER(priv
->fgcolor_dialog
), FALSE
);
348 if (pidgin_color_parse(color
, &fgcolor
)) {
349 gtk_color_chooser_set_rgba(
350 GTK_COLOR_CHOOSER(priv
->fgcolor_dialog
),
354 g_signal_connect(G_OBJECT(priv
->fgcolor_dialog
),
356 G_CALLBACK(destroy_toolbar_fgcolor
), toolbar
);
358 g_signal_connect(G_OBJECT(priv
->fgcolor_dialog
),
359 "response", G_CALLBACK(do_fgcolor
), toolbar
);
364 gtk_window_present(GTK_WINDOW(priv
->fgcolor_dialog
));
366 destroy_toolbar_fgcolor(GTK_WIDGET(toolbar
), NULL
, toolbar
);
369 gtk_widget_grab_focus(toolbar
->webview
);
373 destroy_toolbar_bgcolor(GtkWidget
*widget
, GdkEvent
*event
,
374 PidginWebViewToolbar
*toolbar
)
376 PidginWebViewToolbarPrivate
*priv
=
377 pidgin_webviewtoolbar_get_instance_private(toolbar
);
378 if (widget
!= NULL
) {
379 pidgin_webview_toggle_backcolor(
380 PIDGIN_WEBVIEW(toolbar
->webview
),
381 PIDGIN_WEBVIEWTOOLBAR_DEFAULT_BGCOLOR
);
384 if (priv
->bgcolor_dialog
!= NULL
) {
385 gtk_widget_destroy(priv
->bgcolor_dialog
);
386 priv
->bgcolor_dialog
= NULL
;
393 do_bgcolor(GtkDialog
*dialog
, gint response
, gpointer _toolbar
)
395 PidginWebViewToolbar
*toolbar
= _toolbar
;
399 if (response
!= GTK_RESPONSE_OK
) {
400 destroy_toolbar_bgcolor(GTK_WIDGET(toolbar
), NULL
, toolbar
);
404 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog
), &text_color
);
405 open_tag
= pidgin_color_to_str(&text_color
);
406 pidgin_webview_toggle_backcolor(PIDGIN_WEBVIEW(toolbar
->webview
),
410 destroy_toolbar_bgcolor(NULL
, NULL
, toolbar
);
414 toggle_bg_color(GtkAction
*color
, PidginWebViewToolbar
*toolbar
)
416 PidginWebViewToolbarPrivate
*priv
=
417 pidgin_webviewtoolbar_get_instance_private(toolbar
);
419 if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(color
))) {
421 gchar
*color
= pidgin_webview_get_current_backcolor(
422 PIDGIN_WEBVIEW(toolbar
->webview
));
424 if (!priv
->bgcolor_dialog
) {
425 priv
->bgcolor_dialog
= gtk_color_chooser_dialog_new(
426 _("Select Background Color"), GTK_WINDOW(
427 gtk_widget_get_ancestor(toolbar
->webview
,
429 gtk_color_chooser_set_use_alpha(
430 GTK_COLOR_CHOOSER(priv
->bgcolor_dialog
), FALSE
);
432 if (pidgin_color_parse(color
, &bgcolor
)) {
433 gtk_color_chooser_set_rgba(
434 GTK_COLOR_CHOOSER(priv
->bgcolor_dialog
),
438 g_signal_connect(G_OBJECT(priv
->bgcolor_dialog
),
440 G_CALLBACK(destroy_toolbar_bgcolor
), toolbar
);
441 g_signal_connect(G_OBJECT(priv
->bgcolor_dialog
),
442 "response", G_CALLBACK(do_bgcolor
), toolbar
);
446 gtk_window_present(GTK_WINDOW(priv
->bgcolor_dialog
));
448 destroy_toolbar_bgcolor(GTK_WIDGET(toolbar
), NULL
, toolbar
);
451 gtk_widget_grab_focus(toolbar
->webview
);
455 clear_formatting_cb(GtkAction
*clear
, PidginWebViewToolbar
*toolbar
)
457 pidgin_webview_clear_formatting(PIDGIN_WEBVIEW(toolbar
->webview
));
458 gtk_widget_grab_focus(toolbar
->webview
);
462 cancel_link_cb(PidginWebViewToolbar
*toolbar
, PurpleRequestFields
*fields
)
464 PidginWebViewToolbarPrivate
*priv
=
465 pidgin_webviewtoolbar_get_instance_private(toolbar
);
466 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(priv
->link
), FALSE
);
468 priv
->link_dialog
= NULL
;
472 close_link_dialog(PidginWebViewToolbar
*toolbar
)
474 PidginWebViewToolbarPrivate
*priv
=
475 pidgin_webviewtoolbar_get_instance_private(toolbar
);
476 if (priv
->link_dialog
!= NULL
)
478 purple_request_close(PURPLE_REQUEST_FIELDS
, priv
->link_dialog
);
479 priv
->link_dialog
= NULL
;
484 do_insert_link_cb(PidginWebViewToolbar
*toolbar
, PurpleRequestFields
*fields
)
486 PidginWebViewToolbarPrivate
*priv
=
487 pidgin_webviewtoolbar_get_instance_private(toolbar
);
488 const char *url
, *description
;
490 url
= purple_request_fields_get_string(fields
, "url");
491 if (pidgin_webview_get_format_functions(PIDGIN_WEBVIEW(toolbar
->webview
)) & PIDGIN_WEBVIEW_LINKDESC
)
492 description
= purple_request_fields_get_string(fields
, "description");
496 pidgin_webview_insert_link(PIDGIN_WEBVIEW(toolbar
->webview
), url
, description
);
498 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(priv
->link
), FALSE
);
500 priv
->link_dialog
= NULL
;
504 insert_link_cb(GtkAction
*action
, PidginWebViewToolbar
*toolbar
)
506 PidginWebViewToolbarPrivate
*priv
=
507 pidgin_webviewtoolbar_get_instance_private(toolbar
);
509 if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(priv
->link
))) {
510 PurpleRequestFields
*fields
;
511 PurpleRequestFieldGroup
*group
;
512 PurpleRequestField
*field
;
516 fields
= purple_request_fields_new();
518 group
= purple_request_field_group_new(NULL
);
519 purple_request_fields_add_group(fields
, group
);
521 field
= purple_request_field_string_new("url", _("_URL"), NULL
, FALSE
);
522 purple_request_field_set_required(field
, TRUE
);
523 purple_request_field_group_add_field(group
, field
);
525 if (pidgin_webview_get_format_functions(PIDGIN_WEBVIEW(toolbar
->webview
)) & PIDGIN_WEBVIEW_LINKDESC
) {
526 desc
= pidgin_webview_get_selected_text(PIDGIN_WEBVIEW(toolbar
->webview
));
527 field
= purple_request_field_string_new("description", _("_Description"),
529 purple_request_field_group_add_field(group
, field
);
530 msg
= g_strdup(_("Please enter the URL and description of the "
531 "link that you want to insert. The description "
534 msg
= g_strdup(_("Please enter the URL of the "
535 "link that you want to insert."));
539 purple_request_fields(toolbar
, _("Insert Link"), NULL
,
540 msg
, fields
, _("_Insert"),
541 G_CALLBACK(do_insert_link_cb
), _("Cancel"),
542 G_CALLBACK(cancel_link_cb
), NULL
, toolbar
);
546 close_link_dialog(toolbar
);
549 gtk_widget_grab_focus(toolbar
->webview
);
553 insert_hr_cb(GtkAction
*action
, PidginWebViewToolbar
*toolbar
)
555 pidgin_webview_insert_hr(PIDGIN_WEBVIEW(toolbar
->webview
));
559 do_insert_image_cb(GtkWidget
*widget
, int response
, PidginWebViewToolbar
*toolbar
)
561 PidginWebViewToolbarPrivate
*priv
=
562 pidgin_webviewtoolbar_get_instance_private(toolbar
);
563 gchar
*filename
= NULL
;
566 if (response
== GTK_RESPONSE_ACCEPT
)
567 filename
= gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget
));
569 /* The following triggers a callback that closes the widget */
570 gtk_action_activate(priv
->image
);
572 if (filename
== NULL
)
575 img
= purple_image_new_from_file(filename
, NULL
);
578 gchar
*buf
= g_strdup_printf(_("Failed to store image: %s"),
581 purple_notify_error(NULL
, NULL
, buf
, NULL
, NULL
);
591 pidgin_webview_insert_image(PIDGIN_WEBVIEW(toolbar
->webview
), img
);
592 /* TODO: do it after passing an image to protocol, not before
593 * g_object_unref(img);
598 insert_image_cb(GtkAction
*action
, PidginWebViewToolbar
*toolbar
)
600 PidginWebViewToolbarPrivate
*priv
=
601 pidgin_webviewtoolbar_get_instance_private(toolbar
);
604 if (!priv
->image_dialog
) {
605 window
= gtk_file_chooser_dialog_new(_("Insert Image"), NULL
,
606 GTK_FILE_CHOOSER_ACTION_OPEN
,
607 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
608 GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
,
610 gtk_dialog_set_default_response(GTK_DIALOG(window
), GTK_RESPONSE_ACCEPT
);
611 g_signal_connect(G_OBJECT(window
), "response",
612 G_CALLBACK(do_insert_image_cb
), toolbar
);
614 gtk_widget_show(window
);
615 priv
->image_dialog
= window
;
617 gtk_widget_destroy(priv
->image_dialog
);
618 priv
->image_dialog
= NULL
;
621 gtk_widget_grab_focus(toolbar
->webview
);
625 destroy_smiley_dialog(PidginWebViewToolbar
*toolbar
)
627 PidginWebViewToolbarPrivate
*priv
=
628 pidgin_webviewtoolbar_get_instance_private(toolbar
);
629 if (priv
->smiley_dialog
!= NULL
)
631 gtk_widget_destroy(priv
->smiley_dialog
);
632 priv
->smiley_dialog
= NULL
;
637 close_smiley_dialog(PidginWebViewToolbar
*toolbar
)
639 PidginWebViewToolbarPrivate
*priv
=
640 pidgin_webviewtoolbar_get_instance_private(toolbar
);
641 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(priv
->smiley
), FALSE
);
646 insert_smiley_text(GtkWidget
*widget
, PidginWebViewToolbar
*toolbar
)
648 PurpleSmiley
*smiley
;
650 gchar
*escaped_smiley
, *smiley_html
;
651 const gchar
*smiley_class
;
653 smiley
= g_object_get_data(G_OBJECT(widget
), "smiley");
654 smiley_class
= g_object_get_data(G_OBJECT(widget
), "smiley-class");
655 image_id
= purple_image_store_add(PURPLE_IMAGE(smiley
));
657 escaped_smiley
= g_markup_escape_text(
658 purple_smiley_get_shortcut(smiley
), -1);
659 smiley_html
= g_strdup_printf("<img src=\"" PURPLE_IMAGE_STORE_PROTOCOL
660 "%u\" class=\"emoticon %s-emoticon\" alt=\"%s\" title=\"%s\">",
661 image_id
, smiley_class
, escaped_smiley
, escaped_smiley
);
663 g_free(escaped_smiley
);
665 pidgin_webview_append_html(PIDGIN_WEBVIEW(toolbar
->webview
),
670 close_smiley_dialog(toolbar
);
674 smiley_dialog_input_cb(GtkWidget
*dialog
, GdkEvent
*event
,
675 PidginWebViewToolbar
*toolbar
)
677 if ((event
->type
== GDK_KEY_PRESS
&& event
->key
.keyval
== GDK_KEY_Escape
) ||
678 (event
->type
== GDK_BUTTON_PRESS
&& event
->button
.button
== GDK_BUTTON_PRIMARY
))
680 close_smiley_dialog(toolbar
);
687 /* returns: total width */
689 smileys_load_button_thumbs(GList
*smileys
)
692 gulong total_width
= 0;
694 for (it
= smileys
; it
; it
= g_list_next(it
)) {
695 PurpleSmiley
*smiley
= it
->data
;
699 width
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(smiley
),
700 "pidgin-webviewtoolbar-button-width"));
702 /* smiley is already loaded */
704 total_width
+= width
;
708 pixbuf
= pidgin_pixbuf_from_image(PURPLE_IMAGE(smiley
));
709 pixbuf
= pidgin_pixbuf_scale_down(pixbuf
,
710 24, 24, GDK_INTERP_BILINEAR
, TRUE
);
713 width
= gdk_pixbuf_get_width(pixbuf
);
717 /* XXX: a padding for the button */
720 g_object_set_data(G_OBJECT(smiley
),
721 "pidgin-webviewtoolbar-button-width",
722 GINT_TO_POINTER(width
));
723 g_object_set_data_full(G_OBJECT(smiley
),
724 "pidgin-webviewtoolbar-button-image",
725 pixbuf
, g_object_unref
);
727 total_width
+= width
;
734 add_smiley_list(PidginWebViewToolbar
*toolbar
, GtkWidget
*container
,
735 GList
*smileys
, int max_width
, PurpleSmileyList
*shadow_smileys
,
736 const gchar
*smiley_class
)
745 /* TODO: sort smileys by their position in theme */
747 line
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 0);
748 gtk_box_pack_start(GTK_BOX(container
), line
, FALSE
, FALSE
, 0);
749 for (it
= smileys
; it
; it
= g_list_next(it
)) {
750 PurpleSmiley
*smiley
= it
->data
;
755 const gchar
*smiley_shortcut
;
757 smiley_shortcut
= purple_smiley_get_shortcut(smiley
);
759 width
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(smiley
),
760 "pidgin-webviewtoolbar-button-width"));
761 pixbuf
= g_object_get_data(G_OBJECT(smiley
),
762 "pidgin-webviewtoolbar-button-image");
764 purple_debug_warning("gtkwebviewtoolbar", "Smiley does "
765 "not exists: %s", smiley_shortcut
);
769 image
= GTK_IMAGE(gtk_image_new_from_pixbuf(pixbuf
));
771 button
= gtk_button_new();
772 gtk_container_add(GTK_CONTAINER(button
), GTK_WIDGET(image
));
774 g_object_ref(smiley
);
775 g_object_set_data_full(G_OBJECT(button
), "smiley",
776 smiley
, g_object_unref
);
777 g_object_set_data(G_OBJECT(button
),
778 "smiley-class", (gpointer
)smiley_class
);
780 g_signal_connect(G_OBJECT(button
), "clicked",
781 G_CALLBACK(insert_smiley_text
), toolbar
);
782 gtk_widget_set_tooltip_text(button
, smiley_shortcut
);
783 gtk_button_set_relief(GTK_BUTTON(button
), GTK_RELIEF_NONE
);
785 /* Disable theme smileys shadowed by custom smileys.
786 * There is a case, when a theme smiley have another,
787 * non-shadowed shortcut. But we won't handle it.
789 if (shadow_smileys
&& purple_smiley_list_get_by_shortcut(
790 shadow_smileys
, smiley_shortcut
))
793 g_snprintf(tip
, sizeof(tip
), _("This smiley is "
794 "disabled because a custom smiley exists for "
795 "this shortcut:\n %s"), smiley_shortcut
);
796 gtk_widget_set_tooltip_text(button
, tip
);
797 gtk_widget_set_sensitive(button
, FALSE
);
800 gtk_box_pack_start(GTK_BOX(line
), button
, FALSE
, FALSE
, 0);
801 gtk_widget_show(button
);
804 if (line_width
>= max_width
&& g_list_next(it
)) {
806 line
= gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, 0);
807 gtk_box_pack_start(GTK_BOX(container
), line
, FALSE
, FALSE
, 0);
814 insert_smiley_manage_cb(GtkButton
*button
, gpointer _dialog
)
816 GtkWidget
*dialog
= _dialog
;
818 gtk_widget_destroy(dialog
);
819 pidgin_smiley_manager_show();
823 insert_smiley_cb(GtkAction
*smiley
, PidginWebViewToolbar
*toolbar
)
825 PidginWebViewToolbarPrivate
*priv
=
826 pidgin_webviewtoolbar_get_instance_private(toolbar
);
827 PurpleSmileyList
*smileys_from_theme
, *smileys_from_custom
= NULL
;
828 GList
*theme_smileys
= NULL
, *custom_smileys
= NULL
, *it
, *it_next
;
829 PidginWebViewButtons webview_format
;
831 GtkWidget
*dialog
, *vbox
;
832 GtkWidget
*smiley_table
= NULL
;
833 gboolean supports_custom
= FALSE
;
835 GtkWidget
*scrolled
, *viewport
;
837 if (!gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(smiley
))) {
838 destroy_smiley_dialog(toolbar
);
839 gtk_widget_grab_focus(toolbar
->webview
);
843 webview_format
= pidgin_webview_get_format_functions(
844 PIDGIN_WEBVIEW(toolbar
->webview
));
846 smileys_from_theme
= pidgin_smiley_theme_for_conv(priv
->active_conv
);
847 if (smileys_from_theme
) {
848 theme_smileys
= purple_smiley_list_get_unique(
852 /* remove hidden theme smileys */
853 for (it
= theme_smileys
; it
; it
= it_next
) {
854 PurpleSmiley
*smiley
= it
->data
;
855 it_next
= g_list_next(it
);
857 if (!g_object_get_data(G_OBJECT(smiley
),
858 "pidgin-smiley-hidden"))
863 theme_smileys
= g_list_delete_link(theme_smileys
, it
);
866 supports_custom
= (webview_format
& PIDGIN_WEBVIEW_CUSTOM_SMILEY
);
867 if (supports_custom
) {
868 smileys_from_custom
= purple_smiley_custom_get_list();
869 custom_smileys
= purple_smiley_list_get_all(
870 smileys_from_custom
);
873 dialog
= pidgin_create_dialog(_("Smile!"), 0, "smiley_dialog", FALSE
);
874 gtk_window_set_position(GTK_WINDOW(dialog
), GTK_WIN_POS_MOUSE
);
875 vbox
= pidgin_dialog_get_vbox_with_properties(
876 GTK_DIALOG(dialog
), FALSE
, 0);
878 if (theme_smileys
!= NULL
|| custom_smileys
!= NULL
) {
879 guint max_line_width
, num_lines
, button_width
= 0;
881 /* Fill the cache (images and their widths). */
882 max_line_width
= smileys_load_button_thumbs(theme_smileys
);
883 max_line_width
+= smileys_load_button_thumbs(custom_smileys
);
884 num_lines
= sqrt(g_list_length(theme_smileys
) +
885 g_list_length(custom_smileys
));
886 max_line_width
/= num_lines
;
888 /* We use hboxes packed in a vbox. */
889 smiley_table
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 0);
891 /* Custom smileys manager button. */
892 if (supports_custom
) {
893 GtkWidget
*manage
= gtk_button_new_with_mnemonic(
894 _("_Manage custom smileys"));
896 g_signal_connect(G_OBJECT(manage
), "clicked",
897 G_CALLBACK(insert_smiley_manage_cb
), dialog
);
898 gtk_box_pack_end(GTK_BOX(vbox
), manage
, FALSE
, TRUE
, 0);
899 gtk_widget_get_preferred_size(manage
, NULL
, &req
);
900 button_width
= req
.width
;
901 max_line_width
= MAX(button_width
, max_line_width
);
903 max_line_width
= MAX(max_line_width
, 100);
906 /* Add buttons for smileys. */
908 add_smiley_list(toolbar
, smiley_table
, theme_smileys
,
909 max_line_width
, smileys_from_custom
, "theme");
911 if (theme_smileys
&& custom_smileys
) {
912 gtk_box_pack_start(GTK_BOX(smiley_table
),
913 gtk_separator_new(GTK_ORIENTATION_HORIZONTAL
),
916 if (custom_smileys
) {
917 add_smiley_list(toolbar
, smiley_table
, custom_smileys
,
918 max_line_width
, NULL
, "custom");
921 gtk_widget_add_events(dialog
, GDK_KEY_PRESS_MASK
);
923 smiley_table
= gtk_label_new(_("This theme has no available smileys."));
924 gtk_widget_add_events(dialog
, GDK_KEY_PRESS_MASK
| GDK_BUTTON_PRESS_MASK
);
925 g_signal_connect(G_OBJECT(dialog
), "button-press-event", (GCallback
)smiley_dialog_input_cb
, toolbar
);
928 g_list_free(theme_smileys
);
929 g_list_free(custom_smileys
);
931 scrolled
= pidgin_make_scrollable(smiley_table
, GTK_POLICY_NEVER
, GTK_POLICY_NEVER
, GTK_SHADOW_NONE
, -1, -1);
932 gtk_box_pack_start(GTK_BOX(vbox
), scrolled
, TRUE
, TRUE
, 0);
933 gtk_widget_show(smiley_table
);
935 viewport
= gtk_widget_get_parent(smiley_table
);
936 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport
), GTK_SHADOW_NONE
);
938 /* connect signals */
939 g_signal_connect_swapped(G_OBJECT(dialog
), "destroy", G_CALLBACK(close_smiley_dialog
), toolbar
);
940 g_signal_connect(G_OBJECT(dialog
), "key-press-event", G_CALLBACK(smiley_dialog_input_cb
), toolbar
);
942 gtk_window_set_transient_for(GTK_WINDOW(dialog
),
943 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(toolbar
))));
945 /* show everything */
946 gtk_widget_show_all(dialog
);
948 gtk_widget_get_preferred_size(viewport
, NULL
, &req
);
949 gtk_widget_set_size_request(scrolled
, MIN(300, req
.width
), MIN(290, req
.height
));
951 /* The window has to be made resizable, and the scrollbars in the scrolled window
952 * enabled only after setting the desired size of the window. If we do either of
953 * these tasks before now, GTK+ miscalculates the required size, and erronously
954 * makes one or both scrollbars visible (sometimes).
955 * I too think this hack is gross. But I couldn't find a better way -- sadrul */
956 gtk_window_set_resizable(GTK_WINDOW(dialog
), TRUE
);
957 g_object_set(G_OBJECT(scrolled
),
958 "hscrollbar-policy", GTK_POLICY_AUTOMATIC
,
959 "vscrollbar-policy", GTK_POLICY_AUTOMATIC
,
963 winpidgin_ensure_onscreen(dialog
);
966 priv
->smiley_dialog
= dialog
;
968 gtk_widget_grab_focus(toolbar
->webview
);
972 update_smiley_button(PidginWebViewToolbar
*toolbar
)
974 PidginWebViewToolbarPrivate
*priv
=
975 pidgin_webviewtoolbar_get_instance_private(toolbar
);
976 PurpleSmileyList
*sl
;
977 gboolean any_smileys
;
978 PidginWebViewButtons webview_format
= 0;
980 g_return_if_fail(priv
!= NULL
);
982 if (toolbar
->webview
) {
983 webview_format
= pidgin_webview_get_format_functions(
984 PIDGIN_WEBVIEW(toolbar
->webview
));
987 if (!priv
->allow_smileys
) {
988 gtk_action_set_sensitive(priv
->smiley
, FALSE
);
992 sl
= pidgin_smiley_theme_for_conv(priv
->active_conv
);
993 /* it's possible, that all theme smileys are hidden,
994 * but we won't handle it */
995 any_smileys
= (sl
? !purple_smiley_list_is_empty(sl
) : FALSE
);
997 if (!any_smileys
&& (webview_format
& PIDGIN_WEBVIEW_CUSTOM_SMILEY
)) {
998 sl
= purple_smiley_custom_get_list();
999 any_smileys
= (sl
? !purple_smiley_list_is_empty(sl
) : FALSE
);
1002 gtk_action_set_sensitive(priv
->smiley
, any_smileys
);
1006 send_attention_cb(GtkAction
*attention
, PidginWebViewToolbar
*toolbar
)
1008 PidginWebViewToolbarPrivate
*priv
=
1009 pidgin_webviewtoolbar_get_instance_private(toolbar
);
1010 PurpleConversation
*conv
= priv
->active_conv
;
1011 const gchar
*who
= purple_conversation_get_name(conv
);
1012 PurpleConnection
*gc
= purple_conversation_get_connection(conv
);
1014 purple_protocol_send_attention(gc
, who
, 0);
1015 gtk_widget_grab_focus(toolbar
->webview
);
1019 update_buttons_cb(PidginWebView
*webview
, PidginWebViewButtons buttons
,
1020 PidginWebViewToolbar
*toolbar
)
1022 PidginWebViewToolbarPrivate
*priv
=
1023 pidgin_webviewtoolbar_get_instance_private(toolbar
);
1025 gtk_action_set_sensitive(priv
->bold
, buttons
& PIDGIN_WEBVIEW_BOLD
);
1026 gtk_action_set_sensitive(priv
->italic
, buttons
& PIDGIN_WEBVIEW_ITALIC
);
1027 gtk_action_set_sensitive(priv
->underline
, buttons
& PIDGIN_WEBVIEW_UNDERLINE
);
1028 gtk_action_set_sensitive(priv
->strike
, buttons
& PIDGIN_WEBVIEW_STRIKE
);
1030 gtk_action_set_sensitive(priv
->larger_size
, buttons
& PIDGIN_WEBVIEW_GROW
);
1031 gtk_action_set_sensitive(priv
->smaller_size
, buttons
& PIDGIN_WEBVIEW_SHRINK
);
1033 gtk_action_set_sensitive(priv
->font
, buttons
& PIDGIN_WEBVIEW_FACE
);
1034 gtk_action_set_sensitive(priv
->fgcolor
, buttons
& PIDGIN_WEBVIEW_FORECOLOR
);
1035 gtk_action_set_sensitive(priv
->bgcolor
, buttons
& PIDGIN_WEBVIEW_BACKCOLOR
);
1037 gtk_action_set_sensitive(priv
->clear
,
1038 (buttons
& PIDGIN_WEBVIEW_BOLD
||
1039 buttons
& PIDGIN_WEBVIEW_ITALIC
||
1040 buttons
& PIDGIN_WEBVIEW_UNDERLINE
||
1041 buttons
& PIDGIN_WEBVIEW_STRIKE
||
1042 buttons
& PIDGIN_WEBVIEW_GROW
||
1043 buttons
& PIDGIN_WEBVIEW_SHRINK
||
1044 buttons
& PIDGIN_WEBVIEW_FACE
||
1045 buttons
& PIDGIN_WEBVIEW_FORECOLOR
||
1046 buttons
& PIDGIN_WEBVIEW_BACKCOLOR
));
1048 gtk_action_set_sensitive(priv
->image
, buttons
& PIDGIN_WEBVIEW_IMAGE
);
1049 gtk_action_set_sensitive(priv
->link
, buttons
& PIDGIN_WEBVIEW_LINK
);
1051 priv
->allow_smileys
= !!(buttons
& PIDGIN_WEBVIEW_SMILEY
);
1052 update_smiley_button(toolbar
);
1055 /* we call this when we want to _set_active the toggle button, it'll
1056 * block the callback that's connected to the button so we don't have to
1057 * do the double toggling hack
1060 toggle_action_set_active_block(GtkToggleAction
*action
, gboolean is_active
,
1061 PidginWebViewToolbar
*toolbar
)
1064 g_return_if_fail(toolbar
);
1066 object
= g_object_ref(G_OBJECT(action
));
1067 g_signal_handlers_block_matched(object
, G_SIGNAL_MATCH_DATA
,
1068 0, 0, NULL
, NULL
, toolbar
);
1070 gtk_toggle_action_set_active(action
, is_active
);
1071 g_signal_handlers_unblock_matched(object
, G_SIGNAL_MATCH_DATA
,
1072 0, 0, NULL
, NULL
, toolbar
);
1073 g_object_unref(object
);
1077 update_buttons(PidginWebViewToolbar
*toolbar
)
1079 PidginWebViewToolbarPrivate
*priv
=
1080 pidgin_webviewtoolbar_get_instance_private(toolbar
);
1081 gboolean bold
, italic
, underline
, strike
;
1082 char *tmp
, *color_str
;
1086 label
= g_strdup(_("_Font"));
1088 pidgin_webview_get_current_format(PIDGIN_WEBVIEW(toolbar
->webview
),
1089 &bold
, &italic
, &underline
, &strike
);
1091 if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(priv
->bold
)) != bold
)
1092 toggle_action_set_active_block(GTK_TOGGLE_ACTION(priv
->bold
), bold
,
1094 if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(priv
->italic
)) != italic
)
1095 toggle_action_set_active_block(GTK_TOGGLE_ACTION(priv
->italic
), italic
,
1097 if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(priv
->underline
)) != underline
)
1098 toggle_action_set_active_block(GTK_TOGGLE_ACTION(priv
->underline
),
1099 underline
, toolbar
);
1100 if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(priv
->strike
)) != strike
)
1101 toggle_action_set_active_block(GTK_TOGGLE_ACTION(priv
->strike
), strike
,
1105 gchar
*markup
= g_strdup_printf("<b>%s</b>", label
);
1110 gchar
*markup
= g_strdup_printf("<i>%s</i>", label
);
1115 gchar
*markup
= g_strdup_printf("<u>%s</u>", label
);
1120 gchar
*markup
= g_strdup_printf("<s>%s</s>", label
);
1125 tmp
= pidgin_webview_get_current_fontface(PIDGIN_WEBVIEW(toolbar
->webview
));
1126 if (tmp
&& tmp
[0] == '\0')
1128 if (g_strcmp0(tmp
, PIDGIN_WEBVIEWTOOLBAR_DEFAULT_FONT
) == 0)
1130 toggle_action_set_active_block(GTK_TOGGLE_ACTION(priv
->font
),
1131 (tmp
&& *tmp
), toolbar
);
1133 gchar
*markup
= g_strdup_printf("<span face=\"%s\">%s</span>",
1140 tmp
= pidgin_webview_get_current_forecolor(
1141 PIDGIN_WEBVIEW(toolbar
->webview
));
1143 if (pidgin_color_parse(tmp
, &color
) &&
1144 (color
.red
> 0 || color
.green
> 0 || color
.blue
> 0))
1146 color_str
= pidgin_color_to_str(&color
);
1150 toggle_action_set_active_block(GTK_TOGGLE_ACTION(priv
->fgcolor
),
1151 color_str
!= NULL
, toolbar
);
1153 gchar
*markup
= g_strdup_printf(
1154 "<span foreground=\"%s\">%s</span>", color_str
, label
);
1160 tmp
= pidgin_webview_get_current_backcolor(
1161 PIDGIN_WEBVIEW(toolbar
->webview
));
1163 if (pidgin_color_parse(tmp
, &color
))
1165 color_str
= pidgin_color_to_str(&color
);
1169 toggle_action_set_active_block(GTK_TOGGLE_ACTION(priv
->bgcolor
),
1170 color_str
!= NULL
, toolbar
);
1172 gchar
*markup
= g_strdup_printf(
1173 "<span background=\"%s\">%s</span>", color_str
, label
);
1179 gtk_label_set_markup_with_mnemonic(GTK_LABEL(priv
->font_label
), label
);
1183 toggle_button_cb(PidginWebView
*webview
, PidginWebViewButtons buttons
,
1184 PidginWebViewToolbar
*toolbar
)
1186 update_buttons(toolbar
);
1190 update_format_cb(PidginWebView
*webview
, PidginWebViewToolbar
*toolbar
)
1192 update_buttons(toolbar
);
1196 mark_set_cb(PidginWebView
*webview
, PidginWebViewToolbar
*toolbar
)
1198 update_buttons(toolbar
);
1201 #if GTK_CHECK_VERSION(3,22,0)
1204 pidgin_menu_clicked(GtkWidget
*button
, GtkMenu
*menu
)
1206 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(button
))) {
1207 gtk_widget_show_all(GTK_WIDGET(menu
));
1208 gtk_menu_popup_at_widget(menu
, button
, GDK_GRAVITY_SOUTH_WEST
, GDK_GRAVITY_NORTH_WEST
, NULL
);
1212 #else /* GTK+ 3.22.0 */
1214 /* This comes from gtkmenutoolbutton.c from gtk+
1215 * Copyright (C) 2003 Ricardo Fernandez Pascual
1216 * Copyright (C) 2004 Paolo Borelli
1219 menu_position_func(GtkMenu
*menu
,
1225 GtkWidget
*widget
= GTK_WIDGET(data
);
1226 GtkAllocation allocation
;
1229 gtk_widget_get_allocation(widget
, &allocation
);
1230 gdk_window_get_origin(gtk_widget_get_window(widget
), x
, y
);
1232 *y
+= allocation
.y
+ allocation
.height
;
1235 pidgin_menu_position_func_helper(menu
, x
, y
, push_in
, data
);
1238 *y
-= allocation
.height
;
1242 pidgin_menu_clicked(GtkWidget
*button
, GtkMenu
*menu
)
1244 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(button
))) {
1245 gtk_widget_show_all(GTK_WIDGET(menu
));
1246 gtk_menu_popup(menu
, NULL
, NULL
, menu_position_func
, button
, 0, gtk_get_current_event_time());
1250 #endif /* GTK+ 3.22.0 */
1253 pidgin_menu_deactivate(GtkWidget
*menu
, GtkToggleButton
*button
)
1255 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(button
), FALSE
);
1259 switch_toolbar_view(GtkWidget
*item
, PidginWebViewToolbar
*toolbar
)
1261 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/conversations/toolbar/wide",
1262 !purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/conversations/toolbar/wide"));
1266 pidgin_webviewtoolbar_popup_menu(GtkWidget
*widget
, GdkEventButton
*event
,
1267 PidginWebViewToolbar
*toolbar
)
1269 PidginWebViewToolbarPrivate
*priv
=
1270 pidgin_webviewtoolbar_get_instance_private(toolbar
);
1275 if (!gdk_event_triggers_context_menu((GdkEvent
*)event
))
1278 wide
= gtk_widget_get_visible(priv
->wide_view
);
1280 menu
= gtk_menu_new();
1281 item
= gtk_menu_item_new_with_mnemonic(wide
? _("Group Items") : _("Ungroup Items"));
1282 g_signal_connect(G_OBJECT(item
), "activate", G_CALLBACK(switch_toolbar_view
), toolbar
);
1283 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
1284 gtk_widget_show(item
);
1286 gtk_menu_popup_at_pointer(GTK_MENU(menu
), (GdkEvent
*)event
);
1292 enable_markup(GtkWidget
*widget
, gpointer null
)
1295 label
= gtk_bin_get_child(GTK_BIN(widget
));
1296 if (GTK_IS_LABEL(label
))
1297 g_object_set(G_OBJECT(label
), "use-markup", TRUE
, NULL
);
1301 webviewtoolbar_view_pref_changed(const char *name
, PurplePrefType type
,
1302 gconstpointer value
, gpointer toolbar
)
1304 PidginWebViewToolbarPrivate
*priv
=
1305 pidgin_webviewtoolbar_get_instance_private(toolbar
);
1307 gtk_widget_hide(priv
->lean_view
);
1308 gtk_widget_show_all(priv
->wide_view
);
1310 gtk_widget_hide(priv
->wide_view
);
1311 gtk_widget_show_all(priv
->lean_view
);
1315 /******************************************************************************
1317 *****************************************************************************/
1320 pidgin_webviewtoolbar_finalize(GObject
*object
)
1322 PidginWebViewToolbar
*toolbar
= PIDGIN_WEBVIEWTOOLBAR(object
);
1323 PidginWebViewToolbarPrivate
*priv
=
1324 pidgin_webviewtoolbar_get_instance_private(toolbar
);
1326 if (priv
->image_dialog
!= NULL
)
1328 gtk_widget_destroy(priv
->image_dialog
);
1329 priv
->image_dialog
= NULL
;
1332 destroy_toolbar_font(toolbar
);
1333 if (priv
->smiley_dialog
!= NULL
) {
1334 g_signal_handlers_disconnect_by_func(G_OBJECT(priv
->smiley_dialog
), close_smiley_dialog
, toolbar
);
1335 destroy_smiley_dialog(toolbar
);
1337 destroy_toolbar_bgcolor(NULL
, NULL
, toolbar
);
1338 destroy_toolbar_fgcolor(NULL
, NULL
, toolbar
);
1339 close_link_dialog(toolbar
);
1340 if (toolbar
->webview
) {
1341 g_signal_handlers_disconnect_matched(toolbar
->webview
,
1342 G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
,
1345 g_signal_handlers_disconnect_matched(PIDGIN_WEBVIEW(toolbar
->webview
)->text_buffer
,
1346 G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
,
1351 if (priv
->font_menu
)
1352 gtk_widget_destroy(priv
->font_menu
);
1353 if (priv
->insert_menu
)
1354 gtk_widget_destroy(priv
->insert_menu
);
1356 purple_prefs_disconnect_by_handle(object
);
1358 G_OBJECT_CLASS(pidgin_webviewtoolbar_parent_class
)->finalize(object
);
1362 pidgin_webviewtoolbar_class_init(PidginWebViewToolbarClass
*klass
)
1364 G_OBJECT_CLASS(klass
)->finalize
= pidgin_webviewtoolbar_finalize
;
1366 purple_prefs_add_none(PIDGIN_PREFS_ROOT
"/conversations/toolbar");
1367 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/conversations/toolbar/wide", FALSE
);
1371 pidgin_webviewtoolbar_create_actions(PidginWebViewToolbar
*toolbar
)
1373 PidginWebViewToolbarPrivate
*priv
=
1374 pidgin_webviewtoolbar_get_instance_private(toolbar
);
1375 GtkActionGroup
*action_group
;
1386 {&priv
->bold
, "ToggleBold", GTK_STOCK_BOLD
, N_("<b>_Bold</b>"), N_("Bold"), do_bold
, TRUE
},
1387 {&priv
->italic
, "ToggleItalic", GTK_STOCK_ITALIC
, N_("<i>_Italic</i>"), N_("Italic"), do_italic
, TRUE
},
1388 {&priv
->underline
, "ToggleUnderline", GTK_STOCK_UNDERLINE
, N_("<u>_Underline</u>"), N_("Underline"), do_underline
, TRUE
},
1389 {&priv
->strike
, "ToggleStrike", GTK_STOCK_STRIKETHROUGH
, N_("<span strikethrough='true'>Strikethrough</span>"), N_("Strikethrough"), do_strikethrough
, TRUE
},
1390 {&priv
->larger_size
, "ToggleLarger", PIDGIN_STOCK_TOOLBAR_TEXT_LARGER
, N_("<span size='larger'>Larger</span>"), N_("Increase Font Size"), do_big
, FALSE
},
1392 {&priv
->normal_size
, "ToggleNormal", NULL
, N_("Normal"), N_("Normal Font Size"), NULL
, FALSE
},
1394 {&priv
->smaller_size
, "ToggleSmaller", PIDGIN_STOCK_TOOLBAR_TEXT_SMALLER
, N_("<span size='smaller'>Smaller</span>"), N_("Decrease Font Size"), do_small
, FALSE
},
1395 {&priv
->font
, "ToggleFontFace", PIDGIN_STOCK_TOOLBAR_FONT_FACE
, N_("_Font face"), N_("Font Face"), toggle_font
, TRUE
},
1396 {&priv
->fgcolor
, "ToggleFG", PIDGIN_STOCK_TOOLBAR_FGCOLOR
, N_("Foreground _color"), N_("Foreground Color"), toggle_fg_color
, TRUE
},
1397 {&priv
->bgcolor
, "ToggleBG", PIDGIN_STOCK_TOOLBAR_BGCOLOR
, N_("Bac_kground color"), N_("Background Color"), toggle_bg_color
, TRUE
},
1398 {&priv
->clear
, "ResetFormat", PIDGIN_STOCK_CLEAR
, N_("_Reset formatting"), N_("Reset Formatting"), clear_formatting_cb
, FALSE
},
1399 {&priv
->image
, "InsertImage", PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE
, N_("_Image"), N_("Insert IM Image"), insert_image_cb
, FALSE
},
1400 {&priv
->link
, "InsertLink", PIDGIN_STOCK_TOOLBAR_INSERT_LINK
, N_("_Link"), N_("Insert Link"), insert_link_cb
, TRUE
},
1401 {&priv
->hr
, "InsertHR", NULL
, N_("_Horizontal rule"), N_("Insert Horizontal rule"), insert_hr_cb
, FALSE
},
1402 {&priv
->smiley
, "InsertSmiley", PIDGIN_STOCK_TOOLBAR_SMILEY
, N_("_Smile!"), N_("Insert Smiley"), insert_smiley_cb
, TRUE
},
1403 {&priv
->attention
, "SendAttention", PIDGIN_STOCK_TOOLBAR_SEND_ATTENTION
, N_("_Attention!"), N_("Get Attention"), send_attention_cb
, FALSE
},
1406 action_group
= gtk_action_group_new("PidginWebViewToolbar");
1407 gtk_action_group_set_translation_domain(action_group
, PACKAGE
);
1409 for (i
= 0; i
< G_N_ELEMENTS(actions
); i
++) {
1411 if (actions
[i
].toggle
) {
1412 action
= GTK_ACTION(gtk_toggle_action_new(
1413 actions
[i
].name
, _(actions
[i
].label
),
1414 _(actions
[i
].tooltip
), actions
[i
].stock
));
1416 action
= gtk_action_new(actions
[i
].name
,
1417 _(actions
[i
].label
), _(actions
[i
].tooltip
),
1420 gtk_action_set_is_important(action
, TRUE
);
1421 gtk_action_group_add_action(action_group
, action
);
1422 g_signal_connect(G_OBJECT(action
), "activate", actions
[i
].cb
, toolbar
);
1423 *(actions
[i
].action
) = action
;
1428 pidgin_webviewtoolbar_create_wide_view(PidginWebViewToolbar
*toolbar
)
1430 PidginWebViewToolbarPrivate
*priv
=
1431 pidgin_webviewtoolbar_get_instance_private(toolbar
);
1432 GtkAction
*layout
[] = {
1459 priv
->wide_view
= gtk_toolbar_new();
1460 gtk_toolbar_set_icon_size(GTK_TOOLBAR(priv
->wide_view
),
1461 gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL
));
1462 gtk_toolbar_set_style(GTK_TOOLBAR(priv
->wide_view
), GTK_TOOLBAR_ICONS
);
1464 for (i
= 0; i
< G_N_ELEMENTS(layout
); i
++) {
1466 item
= GTK_TOOL_ITEM(gtk_action_create_tool_item(layout
[i
]));
1467 g_object_set_data(G_OBJECT(item
), "action", layout
[i
]);
1469 item
= gtk_separator_tool_item_new();
1470 gtk_toolbar_insert(GTK_TOOLBAR(priv
->wide_view
), item
, -1);
1475 lean_view_add_menu_item(GtkWidget
*menu
, GtkAction
*action
)
1477 GtkWidget
*menuitem
;
1479 menuitem
= gtk_action_create_menu_item(action
);
1480 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), menuitem
);
1481 g_object_set_data(G_OBJECT(menuitem
), "action", action
);
1485 pidgin_webviewtoolbar_create_lean_view(PidginWebViewToolbar
*toolbar
)
1487 PidginWebViewToolbarPrivate
*priv
=
1488 pidgin_webviewtoolbar_get_instance_private(toolbar
);
1491 GtkToolItem
*font_button
;
1492 GtkWidget
*font_menu
;
1493 GtkToolItem
*insert_button
;
1494 GtkWidget
*insert_menu
;
1495 GtkWidget
*smiley_button
;
1496 GtkWidget
*attention_button
;
1498 priv
->lean_view
= gtk_toolbar_new();
1499 gtk_toolbar_set_icon_size(GTK_TOOLBAR(priv
->lean_view
),
1500 gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL
));
1501 gtk_toolbar_set_style(GTK_TOOLBAR(priv
->lean_view
), GTK_TOOLBAR_BOTH_HORIZ
);
1504 font_button
= gtk_toggle_tool_button_new();
1505 g_object_set_data_full(G_OBJECT(font_button
), "menu-name",
1506 g_strdup("font"), g_free
);
1507 gtk_toolbar_insert(GTK_TOOLBAR(priv
->lean_view
), font_button
, -1);
1508 gtk_tool_item_set_is_important(font_button
, TRUE
);
1509 gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(font_button
), GTK_STOCK_BOLD
);
1510 priv
->font_label
= label
= gtk_label_new_with_mnemonic(_("_Font"));
1511 gtk_label_set_use_markup(GTK_LABEL(label
), TRUE
);
1512 gtk_tool_button_set_label_widget(GTK_TOOL_BUTTON(font_button
), label
);
1514 priv
->font_menu
= font_menu
= gtk_menu_new();
1515 g_object_set_data(G_OBJECT(font_button
), "menu", font_menu
);
1517 lean_view_add_menu_item(font_menu
, priv
->bold
);
1518 lean_view_add_menu_item(font_menu
, priv
->italic
);
1519 lean_view_add_menu_item(font_menu
, priv
->underline
);
1520 lean_view_add_menu_item(font_menu
, priv
->strike
);
1521 lean_view_add_menu_item(font_menu
, priv
->larger_size
);
1523 lean_view_add_menu_item(font_menu
, priv
->normal_size
);
1525 lean_view_add_menu_item(font_menu
, priv
->smaller_size
);
1526 lean_view_add_menu_item(font_menu
, priv
->font
);
1527 lean_view_add_menu_item(font_menu
, priv
->fgcolor
);
1528 lean_view_add_menu_item(font_menu
, priv
->bgcolor
);
1529 lean_view_add_menu_item(font_menu
, priv
->clear
);
1531 g_signal_connect(G_OBJECT(font_button
), "toggled",
1532 G_CALLBACK(pidgin_menu_clicked
), font_menu
);
1533 g_signal_connect_object(G_OBJECT(font_menu
), "deactivate",
1534 G_CALLBACK(pidgin_menu_deactivate
), font_button
, 0);
1536 gtk_container_foreach(GTK_CONTAINER(font_menu
), enable_markup
, NULL
);
1539 sep
= gtk_separator_tool_item_new();
1540 gtk_toolbar_insert(GTK_TOOLBAR(priv
->lean_view
), sep
, -1);
1543 insert_button
= gtk_toggle_tool_button_new();
1544 g_object_set_data_full(G_OBJECT(insert_button
), "menu-name",
1545 g_strdup("insert"), g_free
);
1546 gtk_toolbar_insert(GTK_TOOLBAR(priv
->lean_view
), insert_button
, -1);
1547 gtk_tool_item_set_is_important(insert_button
, TRUE
);
1548 gtk_tool_button_set_stock_id(GTK_TOOL_BUTTON(insert_button
),
1549 PIDGIN_STOCK_TOOLBAR_INSERT
);
1550 label
= gtk_label_new_with_mnemonic(_("_Insert"));
1551 gtk_tool_button_set_label_widget(GTK_TOOL_BUTTON(insert_button
), label
);
1553 priv
->insert_menu
= insert_menu
= gtk_menu_new();
1554 g_object_set_data(G_OBJECT(insert_button
), "menu", insert_menu
);
1556 lean_view_add_menu_item(insert_menu
, priv
->image
);
1557 lean_view_add_menu_item(insert_menu
, priv
->link
);
1558 lean_view_add_menu_item(insert_menu
, priv
->hr
);
1560 g_signal_connect(G_OBJECT(insert_button
), "toggled",
1561 G_CALLBACK(pidgin_menu_clicked
), insert_menu
);
1562 g_signal_connect_object(G_OBJECT(insert_menu
), "deactivate",
1563 G_CALLBACK(pidgin_menu_deactivate
), insert_button
, 0);
1566 sep
= gtk_separator_tool_item_new();
1567 gtk_toolbar_insert(GTK_TOOLBAR(priv
->lean_view
), sep
, -1);
1570 smiley_button
= gtk_action_create_tool_item(priv
->smiley
);
1571 g_object_set_data(G_OBJECT(smiley_button
), "action", priv
->smiley
);
1572 gtk_toolbar_insert(GTK_TOOLBAR(priv
->lean_view
),
1573 GTK_TOOL_ITEM(smiley_button
), -1);
1576 sep
= gtk_separator_tool_item_new();
1577 gtk_toolbar_insert(GTK_TOOLBAR(priv
->lean_view
), sep
, -1);
1580 attention_button
= gtk_action_create_tool_item(priv
->attention
);
1581 g_object_set_data(G_OBJECT(attention_button
), "action", priv
->attention
);
1582 gtk_toolbar_insert(GTK_TOOLBAR(priv
->lean_view
),
1583 GTK_TOOL_ITEM(attention_button
), -1);
1587 pidgin_webviewtoolbar_init(PidginWebViewToolbar
*toolbar
)
1589 PidginWebViewToolbarPrivate
*priv
=
1590 pidgin_webviewtoolbar_get_instance_private(toolbar
);
1591 GtkWidget
*hbox
= GTK_WIDGET(toolbar
);
1593 pidgin_webviewtoolbar_create_actions(toolbar
);
1594 pidgin_webviewtoolbar_create_wide_view(toolbar
);
1595 pidgin_webviewtoolbar_create_lean_view(toolbar
);
1597 gtk_box_pack_start(GTK_BOX(hbox
), priv
->wide_view
, TRUE
, TRUE
, 0);
1598 gtk_box_pack_start(GTK_BOX(hbox
), priv
->lean_view
, TRUE
, TRUE
, 0);
1600 /* set attention button to be greyed out until we get a conversation */
1601 gtk_action_set_sensitive(priv
->attention
, FALSE
);
1603 priv
->allow_smileys
= TRUE
;
1604 update_smiley_button(toolbar
);
1606 purple_prefs_connect_callback(toolbar
,
1607 PIDGIN_PREFS_ROOT
"/conversations/toolbar/wide",
1608 webviewtoolbar_view_pref_changed
, toolbar
);
1609 g_signal_connect_data(G_OBJECT(toolbar
), "realize",
1610 G_CALLBACK(purple_prefs_trigger_callback
),
1611 PIDGIN_PREFS_ROOT
"/conversations/toolbar/wide",
1612 NULL
, G_CONNECT_AFTER
| G_CONNECT_SWAPPED
);
1614 g_signal_connect(G_OBJECT(hbox
), "button-press-event",
1615 G_CALLBACK(pidgin_webviewtoolbar_popup_menu
), toolbar
);
1618 /******************************************************************************
1620 *****************************************************************************/
1623 pidgin_webviewtoolbar_new(void)
1625 return GTK_WIDGET(g_object_new(pidgin_webviewtoolbar_get_type(), NULL
));
1629 pidgin_webviewtoolbar_attach(PidginWebViewToolbar
*toolbar
, GtkWidget
*webview
)
1631 PidginWebViewButtons buttons
;
1633 g_return_if_fail(toolbar
!= NULL
);
1634 g_return_if_fail(PIDGIN_IS_WEBVIEWTOOLBAR(toolbar
));
1635 g_return_if_fail(webview
!= NULL
);
1636 g_return_if_fail(PIDGIN_IS_WEBVIEW(webview
));
1638 toolbar
->webview
= webview
;
1639 g_signal_connect(G_OBJECT(webview
), "allowed-formats-updated",
1640 G_CALLBACK(update_buttons_cb
), toolbar
);
1641 g_signal_connect_after(G_OBJECT(webview
), "format-toggled",
1642 G_CALLBACK(toggle_button_cb
), toolbar
);
1643 g_signal_connect_after(G_OBJECT(webview
), "format-cleared",
1644 G_CALLBACK(update_format_cb
), toolbar
);
1645 g_signal_connect(G_OBJECT(webview
), "format-updated",
1646 G_CALLBACK(update_format_cb
), toolbar
);
1647 g_signal_connect_after(G_OBJECT(webview
), "selection-changed",
1648 G_CALLBACK(mark_set_cb
), toolbar
);
1650 buttons
= pidgin_webview_get_format_functions(PIDGIN_WEBVIEW(webview
));
1651 update_buttons_cb(PIDGIN_WEBVIEW(webview
), buttons
, toolbar
);
1652 update_buttons(toolbar
);
1656 pidgin_webviewtoolbar_switch_active_conversation(PidginWebViewToolbar
*toolbar
,
1657 PurpleConversation
*conv
)
1659 PidginWebViewToolbarPrivate
*priv
=
1660 pidgin_webviewtoolbar_get_instance_private(toolbar
);
1661 PurpleConnection
*gc
= purple_conversation_get_connection(conv
);
1662 PurpleProtocol
*protocol
= purple_connection_get_protocol(gc
);
1664 priv
->active_conv
= conv
;
1666 /* gray out attention button on protocols that don't support it
1667 for the time being it is always disabled for chats */
1668 gtk_action_set_sensitive(priv
->attention
,
1669 conv
&& protocol
&& PURPLE_IS_IM_CONVERSATION(conv
) &&
1670 PURPLE_IS_PROTOCOL_ATTENTION(protocol
));
1672 update_smiley_button(toolbar
);
1676 pidgin_webviewtoolbar_activate(PidginWebViewToolbar
*toolbar
,
1677 PidginWebViewAction action
)
1679 PidginWebViewToolbarPrivate
*priv
;
1682 g_return_if_fail(toolbar
!= NULL
);
1684 priv
= pidgin_webviewtoolbar_get_instance_private(toolbar
);
1686 case PIDGIN_WEBVIEW_ACTION_BOLD
:
1690 case PIDGIN_WEBVIEW_ACTION_ITALIC
:
1694 case PIDGIN_WEBVIEW_ACTION_UNDERLINE
:
1695 act
= priv
->underline
;
1698 case PIDGIN_WEBVIEW_ACTION_STRIKE
:
1702 case PIDGIN_WEBVIEW_ACTION_LARGER
:
1703 act
= priv
->larger_size
;
1707 case PIDGIN_WEBVIEW_ACTION_NORMAL
:
1708 act
= priv
->normal_size
;
1712 case PIDGIN_WEBVIEW_ACTION_SMALLER
:
1713 act
= priv
->smaller_size
;
1716 case PIDGIN_WEBVIEW_ACTION_FONTFACE
:
1720 case PIDGIN_WEBVIEW_ACTION_FGCOLOR
:
1721 act
= priv
->fgcolor
;
1724 case PIDGIN_WEBVIEW_ACTION_BGCOLOR
:
1725 act
= priv
->bgcolor
;
1728 case PIDGIN_WEBVIEW_ACTION_CLEAR
:
1732 case PIDGIN_WEBVIEW_ACTION_IMAGE
:
1736 case PIDGIN_WEBVIEW_ACTION_LINK
:
1740 case PIDGIN_WEBVIEW_ACTION_HR
:
1744 case PIDGIN_WEBVIEW_ACTION_SMILEY
:
1748 case PIDGIN_WEBVIEW_ACTION_ATTENTION
:
1749 act
= priv
->attention
;
1753 g_return_if_reached();
1757 gtk_action_activate(act
);
1761 pidgin_webviewtoolbar_get_wide_view(PidginWebViewToolbar
*toolbar
)
1763 PidginWebViewToolbarPrivate
*priv
=
1764 pidgin_webviewtoolbar_get_instance_private(toolbar
);
1766 g_return_val_if_fail(toolbar
!= NULL
, NULL
);
1768 return priv
->wide_view
;
1772 pidgin_webviewtoolbar_get_lean_view(PidginWebViewToolbar
*toolbar
)
1774 PidginWebViewToolbarPrivate
*priv
=
1775 pidgin_webviewtoolbar_get_instance_private(toolbar
);
1777 g_return_val_if_fail(toolbar
!= NULL
, NULL
);
1779 return priv
->lean_view
;