49
Collector * collector;
60
54
GtkWidget * main_window;
63
56
GtkTreeView * object_view;
64
57
GtkTreeView * callers_view;
65
58
GtkTreeView * descendants_view;
67
60
GtkWidget * start_button;
68
61
GtkWidget * profile_button;
69
62
GtkWidget * reset_button;
70
63
GtkWidget * save_as_button;
71
64
GtkWidget * dummy_button;
73
66
GtkWidget * start_item;
74
67
GtkWidget * profile_item;
75
68
GtkWidget * reset_item;
76
69
GtkWidget * save_as_item;
77
70
GtkWidget * open_item;
71
GtkWidget * screenshot_item;
72
GtkWidget * about_item;
73
GtkWidget * quit_item;
77
GtkTreeSelection * object_selection;
79
79
GtkWidget * samples_label;
80
GtkWidget * samples_hbox;
82
gboolean screenshot_window_visible;
83
GtkWidget * screenshot_textview;
84
GtkWidget * screenshot_close_button;
85
GtkWidget * screenshot_window;
82
88
ProfileDescendant * descendants;
83
89
ProfileCaller * callers;
88
int generating_profile;
92
int update_screenshot_id;
90
94
char * loaded_profile;
92
gboolean profile_from_file; /* FIXME - not10: This is a kludge. Figure out how
93
* to maintain the application model properly
95
* The fundamental issue is that the state of
96
* widgets is controlled by two different
99
* The user clicks on them, changing their
102
* The application model changes, changing their
105
* Model/View/Controller is a possibility.
107
GTimeVal latest_reset;
96
gboolean inhibit_forced_redraw;
111
show_samples_timeout (gpointer data)
99
static void update_screenshot_window (Application *app);
102
show_samples (Application *app)
113
Application *app = data;
116
107
switch (app->state)
119
label = g_strdup ("Samples: 0");
114
n_samples = collector_get_n_samples (app->collector);
124
label = g_strdup_printf ("Samples: %d", app->n_samples);
118
n_samples = profile_get_size (app->profile);
128
122
g_assert_not_reached();
126
label = g_strdup_printf ("%d", n_samples);
132
128
gtk_label_set_label (GTK_LABEL (app->samples_label), label);
134
show_samples_timeout (gpointer data)
136
Application *app = data;
136
140
app->timeout_id = 0;
223
232
gtk_widget_set_sensitive (GTK_WIDGET (app->reset_item),
224
233
sensitive_reset_button);
227
236
gtk_widget_set_sensitive (GTK_WIDGET (app->object_view), sensitive_tree_views);
228
237
gtk_widget_set_sensitive (GTK_WIDGET (app->callers_view), sensitive_tree_views);
229
238
gtk_widget_set_sensitive (GTK_WIDGET (app->descendants_view), sensitive_tree_views);
230
gtk_widget_set_sensitive (GTK_WIDGET (app->samples_label), sensitive_samples_label);
232
queue_show_samples (app);
239
gtk_widget_set_sensitive (GTK_WIDGET (app->samples_hbox), sensitive_samples_hbox);
241
if (app->screenshot_window_visible)
242
gtk_widget_show (app->screenshot_window);
244
gtk_widget_hide (app->screenshot_window);
246
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (app->screenshot_item),
247
app->screenshot_window_visible);
236
set_busy (GtkWidget *widget, gboolean busy)
253
set_busy (GtkWidget *widget,
238
256
GdkCursor *cursor;
241
260
cursor = gdk_cursor_new (GDK_WATCH);
245
gdk_window_set_cursor (widget->window, cursor);
264
if (GTK_IS_TEXT_VIEW (widget))
265
window = gtk_text_view_get_window (GTK_TEXT_VIEW (widget), GTK_TEXT_WINDOW_TEXT);
267
window = widget->window;
269
gdk_window_set_cursor (window, cursor);
248
272
gdk_cursor_unref (cursor);
258
char *name = g_strdup_printf ("/proc/%d/cmdline", pid);
260
if (g_file_get_contents (name, &cmdline, NULL, NULL))
263
return g_strdup ("<unknown>");
269
on_timeout (gpointer data)
271
Application *app = data;
273
int mypid = getpid();
275
pids = list_processes ();
277
for (list = pids; list != NULL; list = list->next)
279
int pid = GPOINTER_TO_INT (list->data);
284
if (get_process_state (pid) == PROCESS_RUNNING)
287
SysprofStackTrace trace;
290
if (!generate_stack_trace (pid, &trace))
295
process = process_get_from_pid (pid);
298
process_ensure_map (process, trace.pid,
299
(gulong)trace.addresses[i]);
302
g_print ("n addr: %d\n", trace.n_addresses);
303
for (i = 0; i < trace.n_addresses; ++i)
304
process_ensure_map (process, trace.pid,
305
(gulong)trace.addresses[i]);
306
g_assert (!app->generating_profile);
308
stack_stash_add_trace (
310
(gulong *)trace.addresses, trace.n_addresses, 1);
316
update_sensitivity (app);
324
timeval_to_ms (const GTimeVal *timeval)
326
return (timeval->tv_sec * G_USEC_PER_SEC + timeval->tv_usec) / 1000.0;
330
time_diff (const GTimeVal *first,
331
const GTimeVal *second)
333
double first_ms = timeval_to_ms (first);
334
double second_ms = timeval_to_ms (second);
336
return first_ms - second_ms;
339
#define RESET_DEAD_PERIOD 250
342
on_read (gpointer data)
344
Application *app = data;
345
SysprofStackTrace trace;
349
rd = read (app->input_fd, &trace, sizeof (trace));
351
if (app->state != PROFILING)
354
if (rd == -1 && errno == EWOULDBLOCK)
357
g_get_current_time (&now);
359
/* After a reset we ignore samples for a short period so that
360
* a reset will actually cause 'samples' to become 0
362
if (time_diff (&now, &app->latest_reset) < RESET_DEAD_PERIOD)
367
g_print ("pid: %d\n", trace.pid);
368
for (i=0; i < trace.n_addresses; ++i)
369
g_print ("rd: %08x\n", trace.addresses[i]);
373
if (rd > 0 && !app->generating_profile && trace.n_addresses)
375
Process *process = process_get_from_pid (trace.pid);
377
/* char *filename = NULL; */
379
/* if (*trace.filename) */
380
/* filename = trace.filename; */
382
for (i = 0; i < trace.n_addresses; ++i)
384
process_ensure_map (process, trace.pid,
385
(gulong)trace.addresses[i]);
387
g_assert (!app->generating_profile);
389
stack_stash_add_trace (
391
(gulong *)trace.addresses, trace.n_addresses, 1);
396
update_sensitivity (app);
640
433
GtkListStore *list_store;
641
434
Profile *profile = app->profile;
648
439
list_store = gtk_list_store_new (4,
654
445
objects = profile_get_objects (profile);
655
446
for (list = objects; list != NULL; list = list->next)
657
448
ProfileObject *object = list->data;
658
449
GtkTreeIter iter;
659
450
double profile_size = profile_get_size (profile);
661
452
gtk_list_store_append (list_store, &iter);
663
454
gtk_list_store_set (list_store, &iter,
664
455
OBJECT_NAME, object->name,
665
456
OBJECT_SELF, 100.0 * object->self / profile_size,
666
457
OBJECT_TOTAL, 100.0 * object->total / profile_size,
667
OBJECT_OBJECT, object,
459
OBJECT_SELF, (double)object->self,
460
OBJECT_TOTAL, (double)object->total,
462
OBJECT_OBJECT, object->name,
465
g_list_foreach (objects, (GFunc)g_free, NULL);
670
466
g_list_free (objects);
672
sort_state = save_sort_state (app->object_view);
674
gtk_tree_view_set_model (app->object_view, GTK_TREE_MODEL (list_store));
678
restore_sort_state (app->object_view, sort_state);
682
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (list_store),
684
GTK_SORT_DESCENDING);
468
tree_view_set_model_with_default_sort (app->object_view, GTK_TREE_MODEL (list_store),
469
OBJECT_TOTAL, GTK_SORT_DESCENDING);
687
471
g_object_unref (G_OBJECT (list_store));
690
474
gtk_tree_view_columns_autosize (app->object_view);
694
add_node (GtkTreeStore *store,
478
add_node (FooTreeStore *store,
696
480
const GtkTreeIter *parent,
697
481
ProfileDescendant *node)
699
483
GtkTreeIter iter;
704
gtk_tree_store_insert (store, &iter, (GtkTreeIter *)parent, 0);
488
foo_tree_store_insert (store, &iter, (GtkTreeIter *)parent, 0);
706
gtk_tree_store_set (store, &iter,
707
DESCENDANTS_NAME, node->object->name,
490
foo_tree_store_set (store, &iter,
491
DESCENDANTS_NAME, node->name,
708
492
DESCENDANTS_SELF, 100 * (node->self)/(double)size,
709
DESCENDANTS_NON_RECURSE, 100 * (node->non_recursion)/(double)size,
710
DESCENDANTS_TOTAL, 100 * (node->total)/(double)size,
711
DESCENDANTS_OBJECT, node->object,
493
DESCENDANTS_CUMULATIVE, 100 * (node->cumulative)/(double)size,
495
DESCENDANTS_SELF, (double)node->self,
496
DESCENDANTS_CUMULATIVE, (double)node->non_recursion,
498
DESCENDANTS_OBJECT, node->name,
714
501
add_node (store, size, parent, node->siblings);
715
502
add_node (store, size, &iter, node->children);
1200
977
path = gtk_tree_path_copy (path);
1201
978
gtk_tree_path_next (path);
1203
981
gtk_tree_path_free (path);
1207
985
all_paths = g_list_remove (all_paths, best_path);
987
if (!all_paths && n_rows == 1)
989
/* Always expand at least once */
990
gtk_tree_view_expand_row (GTK_TREE_VIEW (app->descendants_view),
1208
994
gtk_tree_path_free (best_path);
1211
997
for (list = all_paths; list != NULL; list = list->next)
1212
998
gtk_tree_path_free (list->data);
1214
1000
g_list_free (all_paths);
1004
get_data (GtkTreeView *view,
1014
GtkTreeModel *model = gtk_tree_view_get_model (view);
1015
gtk_tree_model_get (
1017
DESCENDANTS_NAME, name? name : &dummy1,
1018
DESCENDANTS_SELF, self? self : &dummy2,
1019
DESCENDANTS_CUMULATIVE, cumulative? cumulative : &dummy3,
1024
get_indent (GtkTreePath *path)
1026
return 2 * (gtk_tree_path_get_depth (path) - 1);
1030
compute_text_width (GtkTreeView *view,
1038
get_data (view, iter, &name, NULL, NULL);
1040
*width = MAX (g_utf8_strlen (name, -1) + get_indent (path), *width);
1052
set_monospace (GtkWidget *widget)
1054
PangoFontDescription *desc =
1055
pango_font_description_from_string ("monospace");
1057
gtk_widget_modify_font (widget, desc);
1059
pango_font_description_free (desc);
1063
add_text (GtkTreeView *view,
1068
AddTextInfo *info = data;
1075
get_data (view, iter, &name, &self, &cumulative);
1077
indent = get_indent (path);
1079
for (i = 0; i < indent; ++i)
1080
g_string_append_c (info->text, ' ');
1082
g_string_append_printf (info->text, "%-*s %6.2f%% %6.2f%%\n",
1083
info->max_width - indent, name, self, cumulative);
1089
update_screenshot_window_idle (gpointer data)
1091
Application *app = data;
1092
GtkTextBuffer *text_buffer;
1094
if (!app->screenshot_window_visible)
1098
gtk_text_view_get_buffer (GTK_TEXT_VIEW (app->screenshot_textview));
1100
gtk_text_buffer_set_text (text_buffer, "", -1);
1102
if (app->descendants)
1107
info.text = g_string_new ("");
1109
tree_view_foreach_visible (app->descendants_view,
1113
tree_view_foreach_visible (app->descendants_view,
1117
gtk_text_buffer_set_text (text_buffer, info.text->str, -1);
1119
set_monospace (app->screenshot_textview);
1121
g_string_free (info.text, TRUE);
1124
app->update_screenshot_id = 0;
1126
if (app->screenshot_window_visible)
1128
set_busy (app->screenshot_window, FALSE);
1129
set_busy (app->screenshot_textview, FALSE);
1136
update_screenshot_window (Application *app)
1138
/* We do this in an idle handler to deal with the case where
1139
* someone presses Shift-RightArrow on the root of a huge
1140
* profile. This causes a ton of 'expanded' notifications,
1141
* each of which would cause us to traverse the tree and
1142
* update the screenshot window.
1144
if (app->update_screenshot_id)
1145
g_source_remove (app->update_screenshot_id);
1147
if (app->screenshot_window_visible)
1149
/* don't swamp the X server with cursor change requests */
1150
if (!app->update_screenshot_id)
1152
set_busy (app->screenshot_window, TRUE);
1153
set_busy (app->screenshot_textview, TRUE);
1157
app->update_screenshot_id = g_idle_add (
1158
update_screenshot_window_idle, app);
1162
on_descendants_row_expanded_or_collapsed (GtkTreeView *tree,
1167
update_screenshot_window (app);
1218
1171
on_object_selection_changed (GtkTreeSelection *selection,
1221
1174
Application *app = data;
1223
1176
set_busy (app->main_window, TRUE);
1225
gdk_window_process_all_updates ();
1178
update_screenshot_window (app);
1180
if (!app->inhibit_forced_redraw)
1181
gdk_window_process_all_updates (); /* Display updated selection */
1227
1183
fill_descendants_tree (app);
1228
1184
fill_callers_list (app);
1230
1186
if (get_current_object (app))
1231
1187
expand_descendants_tree (app);
1233
1189
set_busy (app->main_window, FALSE);
1237
1193
really_goto_object (Application *app,
1238
ProfileObject *object)
1240
1196
GtkTreeModel *profile_objects;
1241
1197
GtkTreeIter iter;
1242
1198
gboolean found = FALSE;
1244
1200
profile_objects = gtk_tree_view_get_model (app->object_view);
1246
1202
if (gtk_tree_model_get_iter_first (profile_objects, &iter))
1250
ProfileObject *profile_object;
1252
1208
gtk_tree_model_get (profile_objects, &iter,
1253
OBJECT_OBJECT, &profile_object,
1209
OBJECT_OBJECT, &list_object,
1256
if (profile_object == object)
1212
if (list_object == object)
1329
1315
GdkRectangle monitor;
1330
1316
int width, height;
1331
1317
GtkWidget *widget = GTK_WIDGET (window);
1333
1319
screen = gtk_widget_get_screen (widget);
1334
1320
monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
1336
1322
gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
1338
1324
width = monitor.width * 3 / 4;
1339
1325
height = monitor.height * 3 / 4;
1341
1327
gtk_window_resize (window, width, height);
1343
1329
gtk_paned_set_position (GTK_PANED (vpaned), height / 2);
1344
gtk_paned_set_position (GTK_PANED (hpaned), width / 2);
1330
gtk_paned_set_position (GTK_PANED (hpaned), width * 3 / 8);
1332
width = monitor.width * 5 / 8;
1333
height = monitor.height * 5 / 8;
1335
gtk_window_resize (screenshot_window, width, height);
1338
#define GLADE_FILE DATADIR "/sysprof.glade"
1341
gather_widgets (Application *app)
1349
const WidgetInfo widgets[] =
1351
{ &app->main_window, "main_window" },
1352
{ &app->start_button, "start_button" },
1353
{ &app->profile_button, "profile_button" },
1354
{ &app->reset_button, "reset_button" },
1355
{ &app->save_as_button, "save_as_button" },
1356
{ &app->dummy_button, "dummy_button" },
1357
{ &app->samples_label, "samples_label" },
1358
{ &app->samples_hbox, "samples_hbox" },
1359
{ &app->start_item, "start_item" },
1360
{ &app->profile_item, "profile_item" },
1361
{ &app->reset_item, "reset_item" },
1362
{ &app->open_item, "open_item" },
1363
{ &app->save_as_item, "save_as_item" },
1364
{ &app->screenshot_item, "screenshot_item" },
1365
{ &app->quit_item, "quit" },
1366
{ &app->about_item, "about" },
1367
{ &app->object_view, "object_view" },
1368
{ &app->callers_view, "callers_view" },
1369
{ &app->descendants_view, "descendants_view" },
1370
{ &app->screenshot_window, "screenshot_window" },
1371
{ &app->screenshot_textview, "screenshot_textview" },
1372
{ &app->screenshot_close_button, "screenshot_close_button" },
1373
{ &app->vpaned, "vpaned" },
1374
{ &app->hpaned, "hpaned" },
1377
GladeXML *xml = glade_xml_new (GLADE_FILE, NULL, NULL);
1380
for (i = 0; i < G_N_ELEMENTS (widgets); ++i)
1382
const WidgetInfo *info = &(widgets[i]);
1384
*(GtkWidget **)(info->location) = glade_xml_get_widget (xml, info->name);
1386
g_assert (GTK_IS_WIDGET (*(GtkWidget **)info->location));
1389
g_object_unref (xml);
1393
connect_signals (Application *app)
1403
const SignalInfo signals[] =
1405
{ app->main_window, "delete_event", on_delete, NULL },
1406
{ app->start_button, "toggled", on_start_toggled, app },
1407
{ app->profile_button, "toggled", on_profile_toggled, app },
1408
{ app->reset_button, "clicked", on_reset_clicked, app },
1409
{ app->save_as_button, "clicked", on_save_as_clicked, app },
1410
{ app->start_item, "activate", on_menu_item_activated, app->start_button },
1411
{ app->profile_item, "activate", on_menu_item_activated, app->profile_button },
1412
{ app->reset_item, "activate", on_reset_clicked, app },
1413
{ app->open_item, "activate", on_open_clicked, app },
1414
{ app->save_as_item, "activate", on_save_as_clicked, app },
1415
{ app->screenshot_item, "activate", on_screenshot_activated, app },
1416
{ app->quit_item, "activate", on_delete, NULL },
1417
{ app->about_item, "activate", on_about_activated, app },
1418
{ app->object_selection, "changed", on_object_selection_changed, app },
1419
{ app->callers_view, "row-activated", on_callers_row_activated, app },
1420
{ app->descendants_view, "row-activated", on_descendants_row_activated, app },
1421
{ app->descendants_view, "row-expanded", on_descendants_row_expanded_or_collapsed, app },
1422
{ app->descendants_view, "row-collapsed", on_descendants_row_expanded_or_collapsed, app },
1423
{ app->screenshot_window, "delete_event", on_screenshot_window_delete, app },
1424
{ app->screenshot_close_button, "clicked", on_screenshot_close_button_clicked, app },
1429
for (i = 0; i < G_N_ELEMENTS (signals); ++i)
1431
const SignalInfo *info = &(signals[i]);
1433
g_signal_connect (info->object, info->signal, info->callback, info->data);
1454
set_icons (Application *app)
1456
const char *icon_files [] = {
1457
PIXMAPDIR "/sysprof-icon-16.png",
1458
PIXMAPDIR "/sysprof-icon-24.png",
1459
PIXMAPDIR "/sysprof-icon-32.png",
1460
PIXMAPDIR "/sysprof-icon-48.png",
1463
GList *pixbufs = NULL;
1466
for (i = 0; icon_files[i] != NULL; ++i)
1468
const char *file = icon_files[i];
1469
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (file, NULL);
1473
pixbufs = g_list_prepend (pixbufs, pixbuf);
1475
if (i == 3) /* 48 x 48 */
1476
app->icon = g_object_ref (pixbuf);
1480
g_warning ("Could not open %s\n", file);
1484
gtk_window_set_icon_list (GTK_WINDOW (app->main_window), pixbufs);
1486
g_list_foreach (pixbufs, (GFunc)g_object_unref, NULL);
1487
g_list_free (pixbufs);
1490
#define PCT_FORMAT "%.2f<span size='smaller'><span size='smaller'> </span>%%</span>"
1364
1493
build_gui (Application *app)
1367
GtkTreeSelection *selection;
1368
1495
GtkTreeViewColumn *col;
1370
1497
set_shadows ();
1372
xml = glade_xml_new (DATADIR "/sysprof.glade", NULL, NULL);
1499
if (!g_file_test (GLADE_FILE, G_FILE_TEST_EXISTS))
1502
"Sysprof was not compiled or installed correctly.\n"
1504
"Running \"make install\" may solve this problem.\n");
1509
gather_widgets (app);
1511
g_assert (app->main_window);
1374
1513
/* Main Window */
1375
app->main_window = glade_xml_get_widget (xml, "main_window");
1376
app->icon = gdk_pixbuf_new_from_file (PIXMAPDIR "/sysprof-icon.png", NULL);
1378
gtk_window_set_icon (GTK_WINDOW (app->main_window), app->icon);
1380
g_signal_connect (G_OBJECT (app->main_window), "delete_event",
1381
G_CALLBACK (on_delete), NULL);
1383
1516
gtk_widget_realize (GTK_WIDGET (app->main_window));
1384
set_sizes (GTK_WINDOW (app->main_window),
1385
glade_xml_get_widget (xml, "hpaned"),
1386
glade_xml_get_widget (xml, "vpaned"));
1388
1518
/* Tool items */
1390
app->start_button = glade_xml_get_widget (xml, "start_button");
1391
app->profile_button = glade_xml_get_widget (xml, "profile_button");
1392
app->reset_button = glade_xml_get_widget (xml, "reset_button");
1393
app->save_as_button = glade_xml_get_widget (xml, "save_as_button");
1394
app->dummy_button = glade_xml_get_widget (xml, "dummy_button");
1396
1519
gtk_toggle_tool_button_set_active (
1397
1520
GTK_TOGGLE_TOOL_BUTTON (app->profile_button), FALSE);
1399
g_signal_connect (G_OBJECT (app->start_button), "toggled",
1400
G_CALLBACK (on_start_toggled), app);
1402
g_signal_connect (G_OBJECT (app->profile_button), "toggled",
1403
G_CALLBACK (on_profile_toggled), app);
1405
g_signal_connect (G_OBJECT (app->reset_button), "clicked",
1406
G_CALLBACK (on_reset_clicked), app);
1408
g_signal_connect (G_OBJECT (app->save_as_button), "clicked",
1409
G_CALLBACK (on_save_as_clicked), app);
1412
app->samples_label = glade_xml_get_widget (xml, "samples_label");
1415
app->start_item = glade_xml_get_widget (xml, "start_item");
1416
app->profile_item = glade_xml_get_widget (xml, "profile_item");
1417
app->reset_item = glade_xml_get_widget (xml, "reset_item");
1418
app->open_item = glade_xml_get_widget (xml, "open_item");
1419
app->save_as_item = glade_xml_get_widget (xml, "save_as_item");
1421
g_assert (app->start_item);
1422
g_assert (app->profile_item);
1423
g_assert (app->save_as_item);
1424
g_assert (app->open_item);
1426
g_signal_connect (G_OBJECT (app->start_item), "activate",
1427
G_CALLBACK (on_menu_item_activated), app->start_button);
1429
g_signal_connect (G_OBJECT (app->profile_item), "activate",
1430
G_CALLBACK (on_menu_item_activated), app->profile_button);
1432
g_signal_connect (G_OBJECT (app->reset_item), "activate",
1433
G_CALLBACK (on_reset_clicked), app);
1435
g_signal_connect (G_OBJECT (app->open_item), "activate",
1436
G_CALLBACK (on_open_clicked), app);
1438
g_signal_connect (G_OBJECT (app->save_as_item), "activate",
1439
G_CALLBACK (on_save_as_clicked), app);
1441
g_signal_connect (G_OBJECT (glade_xml_get_widget (xml, "quit")), "activate",
1442
G_CALLBACK (on_delete), NULL);
1444
g_signal_connect (G_OBJECT (glade_xml_get_widget (xml, "about")), "activate",
1445
G_CALLBACK (on_about_activated), app);
1447
1522
/* TreeViews */
1449
1524
/* object view */
1450
app->object_view = (GtkTreeView *)glade_xml_get_widget (xml, "object_view");
1451
1525
gtk_tree_view_set_enable_search (app->object_view, FALSE);
1452
col = add_plain_text_column (app->object_view, _("Functions"), OBJECT_NAME);
1453
add_double_format_column (app->object_view, _("Self"), OBJECT_SELF, "%.2f ");
1454
add_double_format_column (app->object_view, _("Total"), OBJECT_TOTAL, "%.2f ");
1455
selection = gtk_tree_view_get_selection (app->object_view);
1456
g_signal_connect (selection, "changed", G_CALLBACK (on_object_selection_changed), app);
1526
col = add_plain_text_column (app->object_view, _("Functions"),
1528
add_double_format_column (app->object_view, _("Self"),
1529
OBJECT_SELF, PCT_FORMAT);
1530
add_double_format_column (app->object_view, _("Total"),
1531
OBJECT_TOTAL, PCT_FORMAT);
1532
app->object_selection = gtk_tree_view_get_selection (app->object_view);
1457
1533
gtk_tree_view_column_set_expand (col, TRUE);
1459
1535
/* callers view */
1460
app->callers_view = (GtkTreeView *)glade_xml_get_widget (xml, "callers_view");
1461
1536
gtk_tree_view_set_enable_search (app->callers_view, FALSE);
1462
col = add_plain_text_column (app->callers_view, _("Callers"), CALLERS_NAME);
1463
add_double_format_column (app->callers_view, _("Self"), CALLERS_SELF, "%.2f ");
1464
add_double_format_column (app->callers_view, _("Total"), CALLERS_TOTAL, "%.2f ");
1465
g_signal_connect (app->callers_view, "row-activated",
1466
G_CALLBACK (on_callers_row_activated), app);
1537
col = add_plain_text_column (app->callers_view, _("Callers"),
1539
add_double_format_column (app->callers_view, _("Self"),
1540
CALLERS_SELF, PCT_FORMAT);
1541
add_double_format_column (app->callers_view, _("Total"),
1542
CALLERS_TOTAL, PCT_FORMAT);
1467
1543
gtk_tree_view_column_set_expand (col, TRUE);
1469
1545
/* descendants view */
1470
app->descendants_view = (GtkTreeView *)glade_xml_get_widget (xml, "descendants_view");
1471
1546
gtk_tree_view_set_enable_search (app->descendants_view, FALSE);
1472
col = add_plain_text_column (app->descendants_view, _("Descendants"), DESCENDANTS_NAME);
1473
add_double_format_column (app->descendants_view, _("Self"), DESCENDANTS_SELF, "%.2f ");
1474
add_double_format_column (app->descendants_view, _("Cumulative"), DESCENDANTS_NON_RECURSE, "%.2f ");
1475
g_signal_connect (app->descendants_view, "row-activated",
1476
G_CALLBACK (on_descendants_row_activated), app);
1547
col = add_plain_text_column (app->descendants_view, _("Descendants"),
1549
add_double_format_column (app->descendants_view, _("Self"),
1550
DESCENDANTS_SELF, PCT_FORMAT);
1551
add_double_format_column (app->descendants_view, _("Cumulative"),
1552
DESCENDANTS_CUMULATIVE, PCT_FORMAT);
1477
1553
gtk_tree_view_column_set_expand (col, TRUE);
1479
gtk_widget_grab_focus (GTK_WIDGET (app->object_view));
1555
/* screenshot window */
1558
set_sizes (GTK_WINDOW (app->main_window),
1559
GTK_WINDOW (app->screenshot_window),
1560
app->hpaned, app->vpaned);
1562
/* hide/show widgets */
1480
1563
gtk_widget_show_all (app->main_window);
1481
1564
gtk_widget_hide (app->dummy_button);
1565
gtk_widget_hide (app->screenshot_window);
1567
gtk_widget_grab_focus (GTK_WIDGET (app->object_view));
1484
1568
queue_show_samples (app);
1570
connect_signals (app);
1576
on_new_sample (gboolean first_sample,
1579
Application *app = data;
1581
if (app->state == PROFILING && first_sample)
1582
update_sensitivity (app);
1584
queue_show_samples (app);
1487
1587
static Application *
1488
1588
application_new (void)
1490
1590
Application *app = g_new0 (Application, 1);
1492
app->stash = stack_stash_new ();
1592
app->collector = collector_new (FALSE, on_new_sample, app);
1494
1593
app->state = INITIAL;
1496
g_get_current_time (&app->latest_reset);
1514
1611
Profile *profile;
1516
1613
set_busy (app->main_window, TRUE);
1518
1615
profile = profile_load (filename, &err);
1520
set_busy (app->main_window, FALSE);
1524
1619
set_loaded_profile (app, filename, profile);
1621
gdk_window_process_all_updates ();
1622
set_busy (app->main_window, FALSE);
1626
set_busy (app->main_window, FALSE);
1528
1628
show_could_not_open (app, filename, err);
1529
1629
g_error_free (err);
1632
g_free (file_open_data);
1638
process_options (int argc,
1642
gboolean show_version = FALSE;
1643
const char *filename = NULL;
1645
for (i = 1; i < argc; ++i)
1647
char *option = argv[i];
1649
if (strcmp (option, "--version") == 0)
1651
show_version = TRUE;
1661
g_print ("%s %s\n", APPLICATION_NAME, PACKAGE_VERSION);
1670
apply_workarounds (void)
1673
/* Disable gslice, since it
1675
* - confuses valgrind
1676
* - caches too much memory
1677
* - hides memory access bugs
1678
* - is not faster than malloc
1680
* Note that g_slice_set_config() is broken in some versions of
1681
* GLib (and 'declared internal' according to Tim), so we use the
1682
* environment variable instead.
1684
if (!getenv ("G_SLICE"))
1685
putenv ("G_SLICE=always_malloc");
1687
/* Accessibility prevents sysprof from working reliably, so
1688
* disable it. Specifically, it
1690
* - causes large amounts of time to be spent in sysprof itself
1691
* whenever the label is updated.
1692
* - sometimes hangs at shutdown
1693
* - does long-running roundtrip requests that prevents
1694
* reading the event buffers, resulting in lost events.
1696
putenv ("NO_GAIL=1");
1697
putenv ("NO_AT_BRIDGE=1");
1536
main (int argc, char **argv)
1538
1704
Application *app;
1705
const char *filename;
1707
apply_workarounds();
1709
filename = process_options (argc, argv);
1540
1711
gtk_init (&argc, &argv);
1542
1713
app = application_new ();
1546
g_timeout_add (10, on_timeout, app);
1715
if (!build_gui (app))
1551
1718
update_sensitivity (app);
1555
1722
FileOpenData *file_open_data = g_new0 (FileOpenData, 1);
1557
file_open_data->filename = argv[1];
1723
file_open_data->filename = filename;
1558
1724
file_open_data->app = app;
1560
g_idle_add (load_file, file_open_data);
1726
/* This has to run at G_PRIORITY_LOW because of bug 350517
1728
g_idle_add_full (G_PRIORITY_LOW, load_file, file_open_data, NULL);