Mercurial > pidgin
comparison src/gtkdebug.c @ 11033:50224ac8184d
[gaim-migrate @ 12919]
Ok, this is debug window filtering. Sadrul was going to do this with a text entry, but I like this better, feel free to disagree with me. It's not the prettiest in a couple places, most notable gtkmain.c where a bunch of categories that don't currently have a home get registered. I added some plugin_(un)load functions to some plugins to place the (un)register functions. Though I didn't do that for the prpls. Comments and cleanups welcome. (Oh, I've been seeing some crashes on quit, but I haven't been able to get it to happen reliably so I'm not sure if it's my code or some transient HEAD oscar/other crash.)
committer: Tailor Script <tailor@pidgin.im>
author | Etan Reisner <pidgin@unreliablesource.net> |
---|---|
date | Tue, 28 Jun 2005 06:13:07 +0000 |
parents | 42dbc4ba1325 |
children | ba506d2e6a8e |
comparison
equal
deleted
inserted
replaced
11032:31c1c48daba1 | 11033:50224ac8184d |
---|---|
40 { | 40 { |
41 GtkWidget *window; | 41 GtkWidget *window; |
42 GtkWidget *text; | 42 GtkWidget *text; |
43 GtkWidget *find; | 43 GtkWidget *find; |
44 | 44 |
45 /* The category filter tree view. */ | |
46 GtkWidget *treeview; | |
47 | |
45 gboolean timestamps; | 48 gboolean timestamps; |
46 gboolean paused; | 49 gboolean paused; |
47 | 50 |
48 } DebugWindow; | 51 } DebugWindow; |
49 | 52 |
55 "#FF0000", /**< Errors. */ | 58 "#FF0000", /**< Errors. */ |
56 "#FF0000", /**< Fatal errors. */ | 59 "#FF0000", /**< Fatal errors. */ |
57 }; | 60 }; |
58 | 61 |
59 static DebugWindow *debug_win = NULL; | 62 static DebugWindow *debug_win = NULL; |
63 | |
64 static GHashTable *debug_categories = NULL; | |
65 static gboolean filter_enabled = FALSE; | |
60 | 66 |
61 struct _find { | 67 struct _find { |
62 DebugWindow *window; | 68 DebugWindow *window; |
63 GtkWidget *entry; | 69 GtkWidget *entry; |
64 }; | 70 }; |
218 gpointer data) | 224 gpointer data) |
219 { | 225 { |
220 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data), GPOINTER_TO_INT(value)); | 226 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data), GPOINTER_TO_INT(value)); |
221 } | 227 } |
222 | 228 |
229 static void | |
230 filter_cb(GtkToggleButton *button, DebugWindow *win) | |
231 { | |
232 if (gtk_toggle_button_get_active(button)) { | |
233 filter_enabled = TRUE; | |
234 } else { | |
235 filter_enabled = FALSE; | |
236 } | |
237 } | |
238 | |
239 static void | |
240 debug_liststore_append(gpointer key, gpointer value, gpointer user_data) | |
241 { | |
242 GtkTreeIter iter; | |
243 GtkListStore **liststore = (GtkListStore **)user_data; | |
244 | |
245 gtk_list_store_append(*liststore, &iter); | |
246 gtk_list_store_set(*liststore, &iter, 0, key, -1); | |
247 } | |
248 | |
223 static DebugWindow * | 249 static DebugWindow * |
224 debug_window_new(void) | 250 debug_window_new(void) |
225 { | 251 { |
226 DebugWindow *win; | 252 DebugWindow *win; |
227 GtkWidget *vbox; | 253 GtkWidget *vbox; |
228 GtkWidget *toolbar; | 254 GtkWidget *toolbar; |
229 GtkWidget *frame; | 255 GtkWidget *frame; |
230 GtkWidget *button; | 256 GtkWidget *button; |
231 GtkWidget *image; | 257 GtkWidget *image; |
258 GtkListStore *liststore = NULL; | |
259 GtkCellRenderer *renderer = NULL; | |
260 GtkTreeSelection *selection = NULL; | |
261 GtkTreeViewColumn *column = NULL; | |
232 int width, height; | 262 int width, height; |
233 | 263 |
234 win = g_new0(DebugWindow, 1); | 264 win = g_new0(DebugWindow, 1); |
235 | 265 |
236 width = gaim_prefs_get_int("/gaim/gtk/debug/width"); | 266 width = gaim_prefs_get_int("/gaim/gtk/debug/width"); |
237 height = gaim_prefs_get_int("/gaim/gtk/debug/height"); | 267 height = gaim_prefs_get_int("/gaim/gtk/debug/height"); |
238 | 268 |
239 GAIM_DIALOG(win->window); | 269 GAIM_DIALOG(win->window); |
240 gaim_debug_info("gtkdebug", "Setting dimensions to %d, %d\n", | 270 gaim_debug_info("gtkdebug", "Setting dimensions to %d, %d\n", |
241 width, height); | 271 width, height); |
242 | 272 |
243 gtk_window_set_default_size(GTK_WINDOW(win->window), width, height); | 273 gtk_window_set_default_size(GTK_WINDOW(win->window), width, height); |
244 gtk_window_set_role(GTK_WINDOW(win->window), "debug"); | 274 gtk_window_set_role(GTK_WINDOW(win->window), "debug"); |
245 gtk_window_set_title(GTK_WINDOW(win->window), _("Debug Window")); | 275 gtk_window_set_title(GTK_WINDOW(win->window), _("Debug Window")); |
246 | 276 |
247 g_signal_connect(G_OBJECT(win->window), "delete_event", | 277 g_signal_connect(G_OBJECT(win->window), "delete_event", |
248 G_CALLBACK(debug_window_destroy), NULL); | 278 G_CALLBACK(debug_window_destroy), NULL); |
249 g_signal_connect(G_OBJECT(win->window), "configure_event", | 279 g_signal_connect(G_OBJECT(win->window), "configure_event", |
250 G_CALLBACK(configure_cb), win); | 280 G_CALLBACK(configure_cb), win); |
251 | 281 |
252 /* Setup the vbox */ | 282 /* Setup the vbox */ |
253 vbox = gtk_vbox_new(FALSE, 0); | 283 vbox = gtk_vbox_new(FALSE, 0); |
254 gtk_container_add(GTK_CONTAINER(win->window), vbox); | 284 gtk_container_add(GTK_CONTAINER(win->window), vbox); |
255 | 285 |
256 if (gaim_prefs_get_bool("/gaim/gtk/debug/toolbar")) { | 286 if (gaim_prefs_get_bool("/gaim/gtk/debug/toolbar")) { |
257 /* Setup our top button bar thingie. */ | 287 /* Setup our top button bar thingie. */ |
258 toolbar = gtk_toolbar_new(); | 288 toolbar = gtk_toolbar_new(); |
259 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_BOTH_HORIZ); | 289 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), |
290 GTK_TOOLBAR_BOTH_HORIZ); | |
260 gtk_toolbar_set_icon_size(GTK_TOOLBAR(toolbar), | 291 gtk_toolbar_set_icon_size(GTK_TOOLBAR(toolbar), |
261 GTK_ICON_SIZE_SMALL_TOOLBAR); | 292 GTK_ICON_SIZE_SMALL_TOOLBAR); |
262 | 293 |
263 gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); | 294 gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); |
264 | 295 |
265 /* Find button */ | 296 /* Find button */ |
266 gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_FIND, | 297 gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_FIND, |
267 NULL, NULL, G_CALLBACK(find_cb), win, -1); | 298 NULL, NULL, G_CALLBACK(find_cb), |
299 win, -1); | |
268 | 300 |
269 /* Save */ | 301 /* Save */ |
270 gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_SAVE, | 302 gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_SAVE, |
271 NULL, NULL, G_CALLBACK(save_cb), win, -1); | 303 NULL, NULL, G_CALLBACK(save_cb), |
304 win, -1); | |
272 | 305 |
273 /* Clear button */ | 306 /* Clear button */ |
274 gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_CLEAR, | 307 gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_CLEAR, |
275 NULL, NULL, G_CALLBACK(clear_cb), win, -1); | 308 NULL, NULL, G_CALLBACK(clear_cb), |
309 win, -1); | |
276 | 310 |
277 gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1); | 311 gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1); |
278 | 312 |
279 /* Pause */ | 313 /* Pause */ |
280 image = gtk_image_new_from_stock(GAIM_STOCK_PAUSE, GTK_ICON_SIZE_MENU); | 314 image = gtk_image_new_from_stock(GAIM_STOCK_PAUSE, GTK_ICON_SIZE_MENU); |
281 button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), | 315 button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), |
282 GTK_TOOLBAR_CHILD_TOGGLEBUTTON, | 316 GTK_TOOLBAR_CHILD_TOGGLEBUTTON, |
283 NULL, _("Pause"), NULL, NULL, | 317 NULL, _("Pause"), NULL, |
284 image, G_CALLBACK(pause_cb), win); | 318 NULL, image, |
319 G_CALLBACK(pause_cb), win); | |
285 | 320 |
286 /* Timestamps */ | 321 /* Timestamps */ |
287 button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), | 322 button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), |
288 GTK_TOOLBAR_CHILD_TOGGLEBUTTON, | 323 GTK_TOOLBAR_CHILD_TOGGLEBUTTON, |
289 NULL, _("Timestamps"), NULL, NULL, | 324 NULL, _("Timestamps"), |
290 NULL, G_CALLBACK(timestamps_cb), | 325 NULL, NULL, NULL, |
291 win); | 326 G_CALLBACK(timestamps_cb), |
327 win); | |
292 | 328 |
293 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), | 329 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), |
294 gaim_prefs_get_bool("/core/debug/timestamps")); | 330 gaim_prefs_get_bool("/core/debug/timestamps")); |
295 | 331 |
296 gaim_prefs_connect_callback(gaim_gtk_debug_get_handle(), "/core/debug/timestamps", | 332 gaim_prefs_connect_callback(gaim_gtk_debug_get_handle(), |
297 timestamps_pref_cb, button); | 333 "/core/debug/timestamps", |
334 timestamps_pref_cb, button); | |
335 | |
336 button = gtk_check_button_new_with_label(_("Filter")); | |
337 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(filter_cb), win); | |
338 button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), | |
339 GTK_TOOLBAR_CHILD_WIDGET, | |
340 button, NULL, NULL, NULL, | |
341 NULL, NULL, NULL); | |
342 | |
343 button = gtk_scrolled_window_new(NULL, NULL); | |
344 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(button), | |
345 GTK_POLICY_NEVER, | |
346 GTK_POLICY_AUTOMATIC); | |
347 | |
348 liststore = gtk_list_store_new(1, G_TYPE_STRING); | |
349 win->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(liststore)); | |
350 renderer = gtk_cell_renderer_text_new(); | |
351 column = gtk_tree_view_column_new_with_attributes(_("Filter"), renderer, "text", 0, NULL); | |
352 | |
353 gtk_tree_view_append_column(GTK_TREE_VIEW(win->treeview), column); | |
354 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(win->treeview), FALSE); | |
355 gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW(win->treeview), TRUE); | |
356 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(liststore), 0, GTK_SORT_ASCENDING); | |
357 | |
358 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(win->treeview)); | |
359 gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); | |
360 | |
361 g_hash_table_foreach(debug_categories, (GHFunc)debug_liststore_append, &liststore); | |
362 | |
363 gtk_container_add(GTK_CONTAINER(button), win->treeview); | |
364 button = gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), | |
365 GTK_TOOLBAR_CHILD_WIDGET, | |
366 button, NULL, NULL, | |
367 NULL, NULL, NULL, NULL); | |
298 } | 368 } |
299 | 369 |
300 /* Add the gtkimhtml */ | 370 /* Add the gtkimhtml */ |
301 frame = gaim_gtk_create_imhtml(FALSE, &win->text, NULL); | 371 frame = gaim_gtk_create_imhtml(FALSE, &win->text, NULL); |
302 gtk_imhtml_set_format_functions(GTK_IMHTML(win->text), | 372 gtk_imhtml_set_format_functions(GTK_IMHTML(win->text), |
373 #endif | 443 #endif |
374 | 444 |
375 void | 445 void |
376 gaim_gtk_debug_init(void) | 446 gaim_gtk_debug_init(void) |
377 { | 447 { |
448 gaim_debug_register_category("gtkdebug"); | |
449 | |
378 /* Debug window preferences. */ | 450 /* Debug window preferences. */ |
379 /* | 451 /* |
380 * NOTE: This must be set before prefs are loaded, and the callbacks | 452 * NOTE: This must be set before prefs are loaded, and the callbacks |
381 * set after they are loaded, since prefs sets the enabled | 453 * set after they are loaded, since prefs sets the enabled |
382 * preference here and that loads the window, which calls the | 454 * preference here and that loads the window, which calls the |
415 g_set_print_handler(gaim_glib_dummy_print_handler); | 487 g_set_print_handler(gaim_glib_dummy_print_handler); |
416 #endif | 488 #endif |
417 } | 489 } |
418 | 490 |
419 void | 491 void |
492 gaim_gtk_debug_uninit(void) | |
493 { | |
494 gaim_debug_unregister_category("gtkdebug"); | |
495 | |
496 gaim_debug_set_ui_ops(NULL); | |
497 } | |
498 | |
499 void | |
420 gaim_gtk_debug_window_show(void) | 500 gaim_gtk_debug_window_show(void) |
421 { | 501 { |
422 if (debug_win == NULL) | 502 if (debug_win == NULL) |
423 debug_win = debug_window_new(); | 503 debug_win = debug_window_new(); |
424 | 504 |
435 debug_window_destroy(NULL, NULL, NULL); | 515 debug_window_destroy(NULL, NULL, NULL); |
436 } | 516 } |
437 } | 517 } |
438 | 518 |
439 static void | 519 static void |
520 create_debug_selected_categories(GtkTreeModel *model, GtkTreePath *path, | |
521 GtkTreeIter *iter, gpointer data) | |
522 { | |
523 GHashTable **hashtable = (GHashTable **)data; | |
524 char *text = NULL; | |
525 | |
526 gtk_tree_model_get(model, iter, 0, &text, -1); | |
527 | |
528 g_hash_table_insert(*hashtable, text, NULL); | |
529 } | |
530 | |
531 static gboolean | |
532 debug_is_filtered_out(const char *category) | |
533 { | |
534 GtkTreeSelection *selection = NULL; | |
535 GHashTable *hashtable = NULL; | |
536 gboolean found = FALSE; | |
537 | |
538 if (category == NULL) | |
539 return FALSE; | |
540 | |
541 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(debug_win->treeview)); | |
542 hashtable = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, | |
543 NULL); | |
544 | |
545 gtk_tree_selection_selected_foreach(selection, | |
546 create_debug_selected_categories, | |
547 &hashtable); | |
548 | |
549 if (filter_enabled) { | |
550 if (g_hash_table_lookup_extended(hashtable, category, NULL, NULL)) | |
551 found = FALSE; | |
552 else | |
553 found = TRUE; | |
554 } | |
555 | |
556 g_hash_table_destroy(hashtable); | |
557 return found; | |
558 } | |
559 | |
560 static void | |
440 gaim_gtk_debug_print(GaimDebugLevel level, const char *category, | 561 gaim_gtk_debug_print(GaimDebugLevel level, const char *category, |
441 const char *format, va_list args) | 562 const char *format, va_list args) |
442 { | 563 { |
443 gboolean timestamps; | 564 gboolean timestamps; |
444 gchar *arg_s, *ts_s; | 565 gchar *arg_s, *ts_s; |
445 gchar *esc_s, *cat_s, *tmp, *s; | 566 gchar *esc_s, *cat_s, *tmp, *s; |
446 | 567 |
447 if (!gaim_prefs_get_bool("/gaim/gtk/debug/enabled") || | 568 if (!gaim_prefs_get_bool("/gaim/gtk/debug/enabled") || |
448 (debug_win == NULL) || debug_win->paused) { | 569 (debug_win == NULL) || debug_win->paused || |
570 debug_is_filtered_out(category)) { | |
449 return; | 571 return; |
450 } | 572 } |
451 | 573 |
452 timestamps = gaim_prefs_get_bool("/core/debug/timestamps"); | 574 timestamps = gaim_prefs_get_bool("/core/debug/timestamps"); |
453 | 575 |
454 arg_s = g_strdup_vprintf(format, args); | 576 arg_s = g_strdup_vprintf(format, args); |
455 | 577 |
456 /* | 578 /* |
457 * For some reason we only print the timestamp if category is | 579 * For some reason we only print the timestamp if category is |
458 * not NULL. Why the hell do we do that? --Mark | 580 * not NULL. Why the hell do we do that? --Mark |
459 */ | 581 */ |
460 if ((category != NULL) && (timestamps)) { | 582 if ((category != NULL) && (timestamps)) { |
461 gchar mdate[64]; | 583 gchar mdate[64]; |
462 | 584 |
463 time_t mtime = time(NULL); | 585 time_t mtime = time(NULL); |
496 gtk_imhtml_append_text(GTK_IMHTML(debug_win->text), s, 0); | 618 gtk_imhtml_append_text(GTK_IMHTML(debug_win->text), s, 0); |
497 | 619 |
498 g_free(s); | 620 g_free(s); |
499 } | 621 } |
500 | 622 |
623 static void | |
624 gaim_gtk_debug_register_category(const char *category) | |
625 { | |
626 /* XXX I'd like to be able to put this creation in _init, but that | |
627 * would require that this be init:ed before anything that wants to | |
628 * register a category, and I'm not sure I can count on this coming | |
629 * first */ | |
630 if (debug_categories == NULL) | |
631 debug_categories = g_hash_table_new_full(g_str_hash, | |
632 g_str_equal, | |
633 g_free, NULL); | |
634 | |
635 if (!g_hash_table_lookup_extended(debug_categories, category, NULL, NULL)) { | |
636 g_hash_table_insert(debug_categories, g_strdup(category), NULL); | |
637 | |
638 if (debug_win != NULL && debug_win->treeview != NULL) { | |
639 GtkTreeModel *model = NULL; | |
640 GtkTreeIter iter; | |
641 | |
642 model = gtk_tree_view_get_model(GTK_TREE_VIEW(debug_win->treeview)); | |
643 | |
644 gtk_list_store_append(GTK_LIST_STORE(model), &iter); | |
645 gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, | |
646 category, -1); | |
647 } | |
648 } | |
649 } | |
650 | |
651 static gboolean | |
652 find_and_remove_category(GtkTreeModel *model, GtkTreePath *path, | |
653 GtkTreeIter *iter, gpointer data) | |
654 { | |
655 GValue value = {0}; | |
656 | |
657 gtk_tree_model_get_value(model, iter, 0, &value); | |
658 | |
659 if (strcmp(g_value_get_string(&value), data) == 0) { | |
660 gtk_list_store_remove(GTK_LIST_STORE(model), iter); | |
661 | |
662 return TRUE; | |
663 } | |
664 | |
665 return FALSE; | |
666 } | |
667 | |
668 static void | |
669 gaim_gtk_debug_unregister_category(const char *category) | |
670 { | |
671 GtkTreeModel *model = NULL; | |
672 | |
673 model = gtk_tree_view_get_model(GTK_TREE_VIEW(debug_win->treeview)); | |
674 | |
675 gtk_tree_model_foreach(model, | |
676 (GtkTreeModelForeachFunc)find_and_remove_category, | |
677 (char *)category); | |
678 | |
679 g_hash_table_remove(debug_categories, category); | |
680 } | |
681 | |
501 static GaimDebugUiOps ops = | 682 static GaimDebugUiOps ops = |
502 { | 683 { |
503 gaim_gtk_debug_print | 684 gaim_gtk_debug_print, |
685 gaim_gtk_debug_register_category, | |
686 gaim_gtk_debug_unregister_category | |
504 }; | 687 }; |
505 | 688 |
506 GaimDebugUiOps * | 689 GaimDebugUiOps * |
507 gaim_gtk_debug_get_ui_ops(void) | 690 gaim_gtk_debug_get_ui_ops(void) |
508 { | 691 { |