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 * it 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
30 #include "gtkdialogs.h"
32 #include "gtkwebview.h"
33 #include "pidginstock.h"
35 #ifdef ENABLE_GLIBTRACE
39 #include <gdk/gdkkeysyms.h>
41 #include "gtk3compat.h"
43 #include "gtkdebug.html.h"
50 GtkWidget
*expression
;
51 GtkWidget
*filterlevel
;
61 static DebugWindow
*debug_win
= NULL
;
62 static guint debug_enabled_timer
= 0;
65 debug_window_destroy(GtkWidget
*w
, GdkEvent
*event
, void *unused
)
67 purple_prefs_disconnect_by_handle(pidgin_debug_get_handle());
69 if(debug_win
->timer
!= 0) {
72 purple_timeout_remove(debug_win
->timer
);
74 text
= gtk_entry_get_text(GTK_ENTRY(debug_win
->expression
));
75 purple_prefs_set_string(PIDGIN_PREFS_ROOT
"/debug/regex", text
);
77 if (debug_win
->regex
!= NULL
)
78 g_regex_unref(debug_win
->regex
);
80 /* If the "Save Log" dialog is open then close it */
81 purple_request_close_with_handle(debug_win
);
86 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/debug/enabled", FALSE
);
92 configure_cb(GtkWidget
*w
, GdkEventConfigure
*event
, DebugWindow
*win
)
94 if (gtk_widget_get_visible(w
)) {
95 purple_prefs_set_int(PIDGIN_PREFS_ROOT
"/debug/width", event
->width
);
96 purple_prefs_set_int(PIDGIN_PREFS_ROOT
"/debug/height", event
->height
);
103 save_writefile_cb(void *user_data
, const char *filename
)
105 DebugWindow
*win
= (DebugWindow
*)user_data
;
109 if ((fp
= g_fopen(filename
, "w+")) == NULL
) {
110 purple_notify_error(win
, NULL
, _("Unable to open file."), NULL
, NULL
);
114 tmp
= pidgin_webview_get_body_text(PIDGIN_WEBVIEW(win
->text
));
115 fprintf(fp
, "Pidgin Debug Log : %s\n", purple_date_format_full(NULL
));
116 fprintf(fp
, "%s", tmp
);
123 save_cb(GtkWidget
*w
, DebugWindow
*win
)
125 purple_request_file(win
, _("Save Debug Log"), "purple-debug.log", TRUE
,
126 G_CALLBACK(save_writefile_cb
), NULL
, NULL
, win
);
130 clear_cb(GtkWidget
*w
, DebugWindow
*win
)
132 pidgin_webview_safe_execute_script(PIDGIN_WEBVIEW(win
->text
), "clear();");
136 pause_cb(GtkWidget
*w
, DebugWindow
*win
)
138 win
->paused
= gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(w
));
141 pidgin_webview_safe_execute_script(PIDGIN_WEBVIEW(win
->text
), "pauseOutput();");
143 pidgin_webview_safe_execute_script(PIDGIN_WEBVIEW(win
->text
), "resumeOutput();");
146 /******************************************************************************
148 *****************************************************************************/
150 regex_clear_color(GtkWidget
*w
) {
151 GtkStyleContext
*context
= gtk_widget_get_style_context(w
);
152 gtk_style_context_remove_class(context
, "good-filter");
153 gtk_style_context_remove_class(context
, "bad-filter");
157 regex_change_color(GtkWidget
*w
, gboolean success
) {
158 GtkStyleContext
*context
= gtk_widget_get_style_context(w
);
161 gtk_style_context_add_class(context
, "good-filter");
162 gtk_style_context_remove_class(context
, "bad-filter");
164 gtk_style_context_add_class(context
, "bad-filter");
165 gtk_style_context_remove_class(context
, "good-filter");
170 regex_toggle_filter(DebugWindow
*win
, gboolean filter
)
172 pidgin_webview_safe_execute_script(PIDGIN_WEBVIEW(win
->text
), "regex.clear();");
179 text
= gtk_entry_get_text(GTK_ENTRY(win
->expression
));
180 regex
= pidgin_webview_quote_js_string(text
);
181 script
= g_strdup_printf("regex.filterAll(%s, %s, %s);",
183 win
->invert
? "true" : "false",
184 win
->highlight
? "true" : "false");
185 pidgin_webview_safe_execute_script(PIDGIN_WEBVIEW(win
->text
), script
);
192 regex_pref_filter_cb(const gchar
*name
, PurplePrefType type
,
193 gconstpointer val
, gpointer data
)
195 DebugWindow
*win
= (DebugWindow
*)data
;
196 gboolean active
= GPOINTER_TO_INT(val
), current
;
198 if (!win
|| !win
->window
)
201 current
= gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win
->filter
));
202 if (active
!= current
)
203 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(win
->filter
), active
);
207 regex_pref_expression_cb(const gchar
*name
, PurplePrefType type
,
208 gconstpointer val
, gpointer data
)
210 DebugWindow
*win
= (DebugWindow
*)data
;
211 const gchar
*exp
= (const gchar
*)val
;
213 gtk_entry_set_text(GTK_ENTRY(win
->expression
), exp
);
217 regex_pref_invert_cb(const gchar
*name
, PurplePrefType type
,
218 gconstpointer val
, gpointer data
)
220 DebugWindow
*win
= (DebugWindow
*)data
;
221 gboolean active
= GPOINTER_TO_INT(val
);
223 win
->invert
= active
;
225 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win
->filter
)))
226 regex_toggle_filter(win
, TRUE
);
230 regex_pref_highlight_cb(const gchar
*name
, PurplePrefType type
,
231 gconstpointer val
, gpointer data
)
233 DebugWindow
*win
= (DebugWindow
*)data
;
234 gboolean active
= GPOINTER_TO_INT(val
);
236 win
->highlight
= active
;
238 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win
->filter
)))
239 regex_toggle_filter(win
, TRUE
);
243 regex_timer_cb(DebugWindow
*win
) {
246 text
= gtk_entry_get_text(GTK_ENTRY(win
->expression
));
247 purple_prefs_set_string(PIDGIN_PREFS_ROOT
"/debug/regex", text
);
255 regex_changed_cb(GtkWidget
*w
, DebugWindow
*win
) {
258 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(win
->filter
))) {
259 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(win
->filter
),
264 win
->timer
= purple_timeout_add_seconds(5, (GSourceFunc
)regex_timer_cb
, win
);
266 text
= gtk_entry_get_text(GTK_ENTRY(win
->expression
));
268 if (text
== NULL
|| *text
== '\0') {
269 regex_clear_color(win
->expression
);
270 gtk_widget_set_sensitive(win
->filter
, FALSE
);
275 g_regex_unref(win
->regex
);
277 win
->regex
= g_regex_new(text
, G_REGEX_CASELESS
|G_REGEX_JAVASCRIPT_COMPAT
, 0, NULL
);
279 if (win
->regex
== NULL
) {
280 /* failed to compile */
281 regex_change_color(win
->expression
, FALSE
);
282 gtk_widget_set_sensitive(win
->filter
, FALSE
);
284 /* compiled successfully */
285 regex_change_color(win
->expression
, TRUE
);
286 gtk_widget_set_sensitive(win
->filter
, TRUE
);
291 regex_key_release_cb(GtkWidget
*w
, GdkEventKey
*e
, DebugWindow
*win
) {
292 if (gtk_widget_is_sensitive(win
->filter
)) {
293 GtkToggleToolButton
*tb
= GTK_TOGGLE_TOOL_BUTTON(win
->filter
);
294 if ((e
->keyval
== GDK_KEY_Return
|| e
->keyval
== GDK_KEY_KP_Enter
) &&
295 !gtk_toggle_tool_button_get_active(tb
))
297 gtk_toggle_tool_button_set_active(tb
, TRUE
);
299 if (e
->keyval
== GDK_KEY_Escape
&&
300 gtk_toggle_tool_button_get_active(tb
))
302 gtk_toggle_tool_button_set_active(tb
, FALSE
);
308 regex_menu_cb(GtkWidget
*item
, const gchar
*pref
) {
311 active
= gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item
));
313 purple_prefs_set_bool(pref
, active
);
317 regex_popup_cb(GtkEntry
*entry
, GtkWidget
*menu
, DebugWindow
*win
) {
318 pidgin_separator(menu
);
319 pidgin_new_check_item(menu
, _("Invert"),
320 G_CALLBACK(regex_menu_cb
),
321 PIDGIN_PREFS_ROOT
"/debug/invert", win
->invert
);
322 pidgin_new_check_item(menu
, _("Highlight matches"),
323 G_CALLBACK(regex_menu_cb
),
324 PIDGIN_PREFS_ROOT
"/debug/highlight", win
->highlight
);
328 regex_filter_toggled_cb(GtkToggleToolButton
*button
, DebugWindow
*win
)
332 active
= gtk_toggle_tool_button_get_active(button
);
334 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/debug/filter", active
);
336 if (!PIDGIN_IS_WEBVIEW(win
->text
))
339 regex_toggle_filter(win
, active
);
343 filter_level_pref_changed(const char *name
, PurplePrefType type
, gconstpointer value
, gpointer data
)
345 DebugWindow
*win
= data
;
346 int level
= GPOINTER_TO_INT(value
);
349 if (level
!= gtk_combo_box_get_active(GTK_COMBO_BOX(win
->filterlevel
)))
350 gtk_combo_box_set_active(GTK_COMBO_BOX(win
->filterlevel
), level
);
352 tmp
= g_strdup_printf("setFilterLevel('%d');", level
);
353 pidgin_webview_safe_execute_script(PIDGIN_WEBVIEW(win
->text
), tmp
);
358 filter_level_changed_cb(GtkWidget
*combo
, gpointer null
)
360 purple_prefs_set_int(PIDGIN_PREFS_ROOT
"/debug/filterlevel",
361 gtk_combo_box_get_active(GTK_COMBO_BOX(combo
)));
365 toolbar_style_pref_changed_cb(const char *name
, PurplePrefType type
, gconstpointer value
, gpointer data
)
367 gtk_toolbar_set_style(GTK_TOOLBAR(data
), GPOINTER_TO_INT(value
));
371 toolbar_icon_pref_changed(GtkWidget
*item
, GtkWidget
*toolbar
)
373 int style
= GPOINTER_TO_INT(g_object_get_data(G_OBJECT(item
), "user_data"));
374 purple_prefs_set_int(PIDGIN_PREFS_ROOT
"/debug/style", style
);
378 toolbar_context(GtkWidget
*toolbar
, GdkEventButton
*event
, gpointer null
)
380 GtkWidget
*menu
, *item
;
382 GtkToolbarStyle value
[3];
385 if (!(event
->button
== 3 && event
->type
== GDK_BUTTON_PRESS
))
388 text
[0] = _("_Icon Only"); value
[0] = GTK_TOOLBAR_ICONS
;
389 text
[1] = _("_Text Only"); value
[1] = GTK_TOOLBAR_TEXT
;
390 text
[2] = _("_Both Icon & Text"); value
[2] = GTK_TOOLBAR_BOTH_HORIZ
;
392 menu
= gtk_menu_new();
394 for (i
= 0; i
< 3; i
++) {
395 item
= gtk_check_menu_item_new_with_mnemonic(text
[i
]);
396 g_object_set_data(G_OBJECT(item
), "user_data", GINT_TO_POINTER(value
[i
]));
397 g_signal_connect(G_OBJECT(item
), "activate", G_CALLBACK(toolbar_icon_pref_changed
), toolbar
);
398 if (value
[i
] == (GtkToolbarStyle
)purple_prefs_get_int(PIDGIN_PREFS_ROOT
"/debug/style"))
399 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item
), TRUE
);
400 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
403 gtk_widget_show_all(menu
);
405 gtk_menu_popup(GTK_MENU(menu
), NULL
, NULL
, NULL
, NULL
, 3, event
->time
);
410 debug_window_new(void)
419 GtkStyleContext
*context
;
420 GtkCssProvider
*filter_css
;
421 const gchar filter_style
[] =
423 "color: @error_fg_color;"
424 "text-shadow: 0 1px @error_text_shadow;"
425 "background-image: none;"
426 "background-color: @error_bg_color;"
429 "color: @question_fg_color;"
430 "text-shadow: 0 1px @question_text_shadow;"
431 "background-image: none;"
432 "background-color: @success_color;"
435 win
= g_new0(DebugWindow
, 1);
437 width
= purple_prefs_get_int(PIDGIN_PREFS_ROOT
"/debug/width");
438 height
= purple_prefs_get_int(PIDGIN_PREFS_ROOT
"/debug/height");
440 win
->window
= pidgin_create_window(_("Debug Window"), 0, "debug", TRUE
);
441 purple_debug_info("gtkdebug", "Setting dimensions to %d, %d\n",
444 gtk_window_set_default_size(GTK_WINDOW(win
->window
), width
, height
);
446 g_signal_connect(G_OBJECT(win
->window
), "delete_event",
447 G_CALLBACK(debug_window_destroy
), NULL
);
448 g_signal_connect(G_OBJECT(win
->window
), "configure_event",
449 G_CALLBACK(configure_cb
), win
);
451 handle
= pidgin_debug_get_handle();
454 vbox
= gtk_box_new(GTK_ORIENTATION_VERTICAL
, 0);
455 gtk_container_add(GTK_CONTAINER(win
->window
), vbox
);
457 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/debug/toolbar")) {
458 /* Setup our top button bar thingie. */
459 toolbar
= gtk_toolbar_new();
460 gtk_toolbar_set_show_arrow(GTK_TOOLBAR(toolbar
), TRUE
);
461 g_signal_connect(G_OBJECT(toolbar
), "button-press-event", G_CALLBACK(toolbar_context
), win
);
463 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar
),
464 purple_prefs_get_int(PIDGIN_PREFS_ROOT
"/debug/style"));
465 purple_prefs_connect_callback(handle
, PIDGIN_PREFS_ROOT
"/debug/style",
466 toolbar_style_pref_changed_cb
, toolbar
);
467 gtk_toolbar_set_icon_size(GTK_TOOLBAR(toolbar
),
468 GTK_ICON_SIZE_SMALL_TOOLBAR
);
470 gtk_box_pack_start(GTK_BOX(vbox
), toolbar
, FALSE
, FALSE
, 0);
473 item
= gtk_tool_button_new_from_stock(GTK_STOCK_SAVE
);
474 gtk_tool_item_set_is_important(item
, TRUE
);
475 gtk_tool_item_set_tooltip_text(item
, _("Save"));
476 g_signal_connect(G_OBJECT(item
), "clicked", G_CALLBACK(save_cb
), win
);
477 gtk_container_add(GTK_CONTAINER(toolbar
), GTK_WIDGET(item
));
480 item
= gtk_tool_button_new_from_stock(GTK_STOCK_CLEAR
);
481 gtk_tool_item_set_is_important(item
, TRUE
);
482 gtk_tool_item_set_tooltip_text(item
, _("Clear"));
483 g_signal_connect(G_OBJECT(item
), "clicked", G_CALLBACK(clear_cb
), win
);
484 gtk_container_add(GTK_CONTAINER(toolbar
), GTK_WIDGET(item
));
486 item
= gtk_separator_tool_item_new();
487 gtk_container_add(GTK_CONTAINER(toolbar
), GTK_WIDGET(item
));
490 item
= gtk_toggle_tool_button_new_from_stock(PIDGIN_STOCK_PAUSE
);
491 gtk_tool_item_set_is_important(item
, TRUE
);
492 gtk_tool_item_set_tooltip_text(item
, _("Pause"));
493 g_signal_connect(G_OBJECT(item
), "clicked", G_CALLBACK(pause_cb
), win
);
494 gtk_container_add(GTK_CONTAINER(toolbar
), GTK_WIDGET(item
));
497 item
= gtk_separator_tool_item_new();
498 gtk_container_add(GTK_CONTAINER(toolbar
), GTK_WIDGET(item
));
500 /* regex toggle button */
501 item
= gtk_toggle_tool_button_new_from_stock(GTK_STOCK_FIND
);
502 gtk_tool_item_set_is_important(item
, TRUE
);
503 win
->filter
= GTK_WIDGET(item
);
504 gtk_tool_button_set_label(GTK_TOOL_BUTTON(win
->filter
), _("Filter"));
505 gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(win
->filter
), _("Filter"));
506 g_signal_connect(G_OBJECT(win
->filter
), "clicked", G_CALLBACK(regex_filter_toggled_cb
), win
);
507 gtk_container_add(GTK_CONTAINER(toolbar
), GTK_WIDGET(win
->filter
));
509 /* we purposely disable the toggle button here in case
510 * /purple/gtk/debug/expression has an empty string. If it does not have
511 * an empty string, the change signal will get called and make the
512 * toggle button sensitive.
514 gtk_widget_set_sensitive(win
->filter
, FALSE
);
515 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(win
->filter
),
516 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/debug/filter"));
517 purple_prefs_connect_callback(handle
, PIDGIN_PREFS_ROOT
"/debug/filter",
518 regex_pref_filter_cb
, win
);
521 win
->expression
= gtk_entry_new();
522 item
= gtk_tool_item_new();
523 gtk_widget_set_tooltip_text(win
->expression
, _("Right click for more options."));
524 gtk_container_add(GTK_CONTAINER(item
), GTK_WIDGET(win
->expression
));
525 gtk_container_add(GTK_CONTAINER(toolbar
), GTK_WIDGET(item
));
527 filter_css
= gtk_css_provider_new();
528 gtk_css_provider_load_from_data(filter_css
, filter_style
, -1, NULL
);
529 context
= gtk_widget_get_style_context(win
->expression
);
530 gtk_style_context_add_provider(context
,
531 GTK_STYLE_PROVIDER(filter_css
),
532 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION
);
534 /* this needs to be before the text is set from the pref if we want it
535 * to colorize a stored expression.
537 g_signal_connect(G_OBJECT(win
->expression
), "changed",
538 G_CALLBACK(regex_changed_cb
), win
);
539 gtk_entry_set_text(GTK_ENTRY(win
->expression
),
540 purple_prefs_get_string(PIDGIN_PREFS_ROOT
"/debug/regex"));
541 g_signal_connect(G_OBJECT(win
->expression
), "populate-popup",
542 G_CALLBACK(regex_popup_cb
), win
);
543 g_signal_connect(G_OBJECT(win
->expression
), "key-release-event",
544 G_CALLBACK(regex_key_release_cb
), win
);
545 purple_prefs_connect_callback(handle
, PIDGIN_PREFS_ROOT
"/debug/regex",
546 regex_pref_expression_cb
, win
);
548 /* connect the rest of our pref callbacks */
549 win
->invert
= purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/debug/invert");
550 purple_prefs_connect_callback(handle
, PIDGIN_PREFS_ROOT
"/debug/invert",
551 regex_pref_invert_cb
, win
);
553 win
->highlight
= purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/debug/highlight");
554 purple_prefs_connect_callback(handle
, PIDGIN_PREFS_ROOT
"/debug/highlight",
555 regex_pref_highlight_cb
, win
);
557 item
= gtk_separator_tool_item_new();
558 gtk_container_add(GTK_CONTAINER(toolbar
), GTK_WIDGET(item
));
560 item
= gtk_tool_item_new();
561 gtk_container_add(GTK_CONTAINER(item
), gtk_label_new(_("Level ")));
562 gtk_container_add(GTK_CONTAINER(toolbar
), GTK_WIDGET(item
));
564 win
->filterlevel
= gtk_combo_box_text_new();
565 item
= gtk_tool_item_new();
566 gtk_widget_set_tooltip_text(win
->filterlevel
, _("Select the debug filter level."));
567 gtk_container_add(GTK_CONTAINER(item
), win
->filterlevel
);
568 gtk_container_add(GTK_CONTAINER(toolbar
), GTK_WIDGET(item
));
570 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win
->filterlevel
), _("All"));
571 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win
->filterlevel
), _("Misc"));
572 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win
->filterlevel
), _("Info"));
573 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win
->filterlevel
), _("Warning"));
574 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win
->filterlevel
), _("Error "));
575 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win
->filterlevel
), _("Fatal Error"));
576 gtk_combo_box_set_active(GTK_COMBO_BOX(win
->filterlevel
),
577 purple_prefs_get_int(PIDGIN_PREFS_ROOT
"/debug/filterlevel"));
579 purple_prefs_connect_callback(handle
, PIDGIN_PREFS_ROOT
"/debug/filterlevel",
580 filter_level_pref_changed
, win
);
581 g_signal_connect(G_OBJECT(win
->filterlevel
), "changed",
582 G_CALLBACK(filter_level_changed_cb
), NULL
);
585 /* Add the gtkwebview */
586 frame
= pidgin_create_webview(FALSE
, &win
->text
, NULL
);
587 pidgin_webview_set_format_functions(PIDGIN_WEBVIEW(win
->text
),
588 PIDGIN_WEBVIEW_ALL
^ PIDGIN_WEBVIEW_SMILEY
^ PIDGIN_WEBVIEW_IMAGE
);
589 pidgin_webview_load_html_string(PIDGIN_WEBVIEW(win
->text
), gtkdebug_html
);
590 gtk_box_pack_start(GTK_BOX(vbox
), frame
, TRUE
, TRUE
, 0);
591 gtk_widget_show(frame
);
595 gtk_widget_show_all(win
->window
);
601 debug_enabled_timeout_cb(gpointer data
)
603 debug_enabled_timer
= 0;
606 pidgin_debug_window_show();
608 pidgin_debug_window_hide();
614 debug_enabled_cb(const char *name
, PurplePrefType type
,
615 gconstpointer value
, gpointer data
)
617 debug_enabled_timer
= g_timeout_add(0, debug_enabled_timeout_cb
, GINT_TO_POINTER(GPOINTER_TO_INT(value
)));
621 pidgin_glib_log_handler(const gchar
*domain
, GLogLevelFlags flags
,
622 const gchar
*msg
, gpointer user_data
)
624 PurpleDebugLevel level
;
625 char *new_msg
= NULL
;
626 char *new_domain
= NULL
;
628 if ((flags
& G_LOG_LEVEL_ERROR
) == G_LOG_LEVEL_ERROR
)
629 level
= PURPLE_DEBUG_ERROR
;
630 else if ((flags
& G_LOG_LEVEL_CRITICAL
) == G_LOG_LEVEL_CRITICAL
)
631 level
= PURPLE_DEBUG_FATAL
;
632 else if ((flags
& G_LOG_LEVEL_WARNING
) == G_LOG_LEVEL_WARNING
)
633 level
= PURPLE_DEBUG_WARNING
;
634 else if ((flags
& G_LOG_LEVEL_MESSAGE
) == G_LOG_LEVEL_MESSAGE
)
635 level
= PURPLE_DEBUG_INFO
;
636 else if ((flags
& G_LOG_LEVEL_INFO
) == G_LOG_LEVEL_INFO
)
637 level
= PURPLE_DEBUG_INFO
;
638 else if ((flags
& G_LOG_LEVEL_DEBUG
) == G_LOG_LEVEL_DEBUG
)
639 level
= PURPLE_DEBUG_MISC
;
642 purple_debug_warning("gtkdebug",
643 "Unknown glib logging level in %d\n", flags
);
645 level
= PURPLE_DEBUG_MISC
; /* This will never happen. */
649 new_msg
= purple_utf8_try_convert(msg
);
652 new_domain
= purple_utf8_try_convert(domain
);
656 #ifdef ENABLE_GLIBTRACE
660 bt_size
= backtrace(bt_buff
, 20);
661 fprintf(stderr
, "\nBacktrace for \"%s\" (%s):\n", new_msg
,
662 new_domain
!= NULL
? new_domain
: "g_log");
663 backtrace_symbols_fd(bt_buff
, bt_size
, STDERR_FILENO
);
664 fprintf(stderr
, "\n");
667 purple_debug(level
, (new_domain
!= NULL
? new_domain
: "g_log"),
678 pidgin_glib_dummy_print_handler(const gchar
*string
)
684 pidgin_debug_init(void)
686 /* Debug window preferences. */
688 * NOTE: This must be set before prefs are loaded, and the callbacks
689 * set after they are loaded, since prefs sets the enabled
690 * preference here and that loads the window, which calls the
691 * configure event, which overrides the width and height! :P
694 purple_prefs_add_none(PIDGIN_PREFS_ROOT
"/debug");
696 /* Controls printing to the debug window */
697 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/debug/enabled", FALSE
);
698 purple_prefs_add_int(PIDGIN_PREFS_ROOT
"/debug/filterlevel", PURPLE_DEBUG_ALL
);
699 purple_prefs_add_int(PIDGIN_PREFS_ROOT
"/debug/style", GTK_TOOLBAR_BOTH_HORIZ
);
701 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/debug/toolbar", TRUE
);
702 purple_prefs_add_int(PIDGIN_PREFS_ROOT
"/debug/width", 450);
703 purple_prefs_add_int(PIDGIN_PREFS_ROOT
"/debug/height", 250);
705 purple_prefs_add_string(PIDGIN_PREFS_ROOT
"/debug/regex", "");
706 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/debug/filter", FALSE
);
707 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/debug/invert", FALSE
);
708 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/debug/case_insensitive", FALSE
);
709 purple_prefs_add_bool(PIDGIN_PREFS_ROOT
"/debug/highlight", FALSE
);
711 purple_prefs_connect_callback(NULL
, PIDGIN_PREFS_ROOT
"/debug/enabled",
712 debug_enabled_cb
, NULL
);
714 #define REGISTER_G_LOG_HANDLER(name) \
715 g_log_set_handler((name), G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL \
716 | G_LOG_FLAG_RECURSION, \
717 pidgin_glib_log_handler, NULL)
719 /* Register the glib/gtk log handlers. */
720 REGISTER_G_LOG_HANDLER(NULL
);
721 REGISTER_G_LOG_HANDLER("Gdk");
722 REGISTER_G_LOG_HANDLER("Gtk");
723 REGISTER_G_LOG_HANDLER("GdkPixbuf");
724 REGISTER_G_LOG_HANDLER("GLib");
725 REGISTER_G_LOG_HANDLER("GModule");
726 REGISTER_G_LOG_HANDLER("GLib-GObject");
727 REGISTER_G_LOG_HANDLER("GThread");
728 REGISTER_G_LOG_HANDLER("Json");
730 REGISTER_G_LOG_HANDLER("GStreamer");
734 if (!purple_debug_is_enabled())
735 g_set_print_handler(pidgin_glib_dummy_print_handler
);
740 pidgin_debug_uninit(void)
742 purple_debug_set_ui_ops(NULL
);
744 if (debug_enabled_timer
!= 0)
745 g_source_remove(debug_enabled_timer
);
749 pidgin_debug_window_show(void)
751 if (debug_win
== NULL
)
752 debug_win
= debug_window_new();
754 gtk_widget_show(debug_win
->window
);
756 purple_prefs_set_bool(PIDGIN_PREFS_ROOT
"/debug/enabled", TRUE
);
760 pidgin_debug_window_hide(void)
762 if (debug_win
!= NULL
) {
763 gtk_widget_destroy(debug_win
->window
);
764 debug_window_destroy(NULL
, NULL
, NULL
);
769 pidgin_debug_print(PurpleDebugLevel level
, const char *category
,
777 if (debug_win
== NULL
)
779 if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/debug/enabled"))
783 mdate
= purple_utf8_strftime("%H:%M:%S", localtime(&mtime
));
785 esc_s
= purple_escape_js(arg_s
);
787 js
= g_strdup_printf("append(%d, '%s', '%s', %s);",
788 level
, mdate
, category
? category
: "", esc_s
);
791 pidgin_webview_safe_execute_script(PIDGIN_WEBVIEW(debug_win
->text
), js
);
796 pidgin_debug_is_enabled(PurpleDebugLevel level
, const char *category
)
798 return (debug_win
!= NULL
&&
799 purple_prefs_get_bool(PIDGIN_PREFS_ROOT
"/debug/enabled"));
802 static PurpleDebugUiOps ops
=
805 pidgin_debug_is_enabled
,
813 pidgin_debug_get_ui_ops(void)
819 pidgin_debug_get_handle() {