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 {