blob: 52678cea9b7976911bcfca52d49a7d636b7f77ea [file] [log] [blame]
/*
* Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License (not later!)
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#define _GNU_SOURCE
#include <gtk/gtk.h>
#include <getopt.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "trace-cmd.h"
#include "trace-view.h"
#define version "0.1.1"
#define TRACE_WIDTH 800
#define TRACE_HEIGHT 600
#define default_input_file "trace.dat"
static char *input_file;
struct trace_tree_info {
GtkWidget *trace_tree;
GtkWidget *spin;
};
void usage(char *prog)
{
printf("Usage: %s\n", prog);
printf(" -h Display this help message\n");
printf(" -i input_file, default is %s\n", default_input_file);
}
/* Callback for the clicked signal of the Load button */
static void
load_clicked (gpointer data)
{
struct trace_tree_info *info = data;
struct tracecmd_input *handle;
GtkWidget *dialog;
gchar *filename;
dialog = gtk_file_chooser_dialog_new("Load File",
NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
handle = tracecmd_open(filename);
if (handle) {
trace_view_reload(info->trace_tree, handle, info->spin);
/* Free handle when freeing the trace tree */
tracecmd_close(handle);
}
g_free(filename);
}
gtk_widget_destroy(dialog);
}
/* Callback for the clicked signal of the Exit button */
static void
exit_clicked (GtkWidget *widget, gpointer data)
{
gtk_widget_destroy (GTK_WIDGET (data)); /* the user data points to the main window */
gtk_main_quit ();
}
/* Callback for the delete_event signal of the main application window */
static gint
delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
{
gtk_widget_destroy (widget); /* destroy the main window */
gtk_main_quit ();
return TRUE;
}
/* Callback for the clicked signal of the Events filter button */
static void
events_clicked (gpointer data)
{
struct trace_tree_info *info = data;
struct event_filter *event_filter;
GtkTreeView *trace_tree = GTK_TREE_VIEW(info->trace_tree);
GtkTreeModel *model;
TraceViewStore *store;
gboolean all_events;
model = gtk_tree_view_get_model(trace_tree);
if (!model)
return;
store = TRACE_VIEW_STORE(model);
all_events = trace_view_store_get_all_events_enabled(store);
event_filter = trace_view_store_get_event_filter(store);
trace_filter_event_filter_dialog(store->handle, event_filter,
all_events,
trace_view_event_filter_callback,
trace_tree);
}
/* Callback for the clicked signal of the Advanced filter button */
static void
adv_filter_clicked (gpointer data)
{
struct trace_tree_info *info = data;
struct event_filter *event_filter;
GtkTreeView *trace_tree = GTK_TREE_VIEW(info->trace_tree);
GtkTreeModel *model;
TraceViewStore *store;
model = gtk_tree_view_get_model(trace_tree);
if (!model)
return;
store = TRACE_VIEW_STORE(model);
event_filter = trace_view_store_get_event_filter(store);
trace_adv_filter_dialog(store->handle, event_filter,
trace_view_adv_filter_callback, trace_tree);
}
/* Callback for the clicked signal of the CPUs filter button */
static void
cpus_clicked (gpointer data)
{
struct trace_tree_info *info = data;
GtkTreeView *trace_tree = GTK_TREE_VIEW(info->trace_tree);
TraceViewStore *store;
gboolean all_cpus;
guint64 *cpu_mask;
store = TRACE_VIEW_STORE(gtk_tree_view_get_model(trace_tree));
all_cpus = trace_view_store_get_all_cpus(store);
cpu_mask = trace_view_store_get_cpu_mask(store);
trace_filter_cpu_dialog(all_cpus, cpu_mask,
trace_view_store_get_cpus(store),
trace_view_cpu_filter_callback, trace_tree);
}
#if 0
static GtkTreeModel *
create_combo_box_model(void)
{
GtkListStore *store;
GtkTreeIter iter;
store = gtk_list_store_new(1, G_TYPE_STRING);
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, 0, "1", -1);
return GTK_TREE_MODEL(store);
}
#endif
void trace_view(int argc, char **argv)
{
static struct tracecmd_input *handle;
struct trace_tree_info tree_info;
struct stat st;
GtkWidget *trace_tree;
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *menu_bar;
GtkWidget *menu;
GtkWidget *menu_item;
GtkWidget *sub_item;
GtkWidget *scrollwin;
GtkWidget *label;
GtkWidget *spin;
int ret;
int c;
gtk_init(&argc, &argv);
while ((c = getopt(argc, argv, "hi:")) != -1) {
switch(c) {
case 'h':
usage(basename(argv[0]));
return;
case 'i':
input_file = optarg;
break;
default:
/* assume the other options are for gtk */
break;
}
}
if ((argc - optind) >= 1) {
if (input_file)
usage(basename(argv[0]));
input_file = argv[optind];
}
if (!input_file) {
ret = stat(default_input_file, &st);
if (ret >= 0)
input_file = default_input_file;
}
if (input_file)
handle = tracecmd_open(input_file);
/* --- Main window --- */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
/* --- Top Level Vbox --- */
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER (window), vbox);
gtk_widget_show(vbox);
/* --- Menu Bar --- */
menu_bar = gtk_menu_bar_new();
gtk_box_pack_start(GTK_BOX (vbox), menu_bar, FALSE, FALSE, 0);
gtk_widget_show(menu_bar);
/* --- File Option --- */
menu_item = gtk_menu_item_new_with_label("File");
gtk_widget_show(menu_item);
gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), menu_item);
menu = gtk_menu_new(); /* Don't need to show menus */
/* --- File - Load Option --- */
sub_item = gtk_menu_item_new_with_label("Load info");
/* Add them to the menu */
gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
/* We can attach the Quit menu item to our exit function */
g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
G_CALLBACK (load_clicked),
(gpointer) &tree_info);
/* We do need to show menu items */
gtk_widget_show(sub_item);
/* --- File - Quit Option --- */
sub_item = gtk_menu_item_new_with_label("Quit");
/* Add them to the menu */
gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
/* We can attach the Quit menu item to our exit function */
g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
G_CALLBACK (exit_clicked),
(gpointer) window);
/* We do need to show menu items */
gtk_widget_show(sub_item);
gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu);
/* --- end File options --- */
/* --- Filter Option --- */
menu_item = gtk_menu_item_new_with_label("Filter");
gtk_widget_show(menu_item);
gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), menu_item);
menu = gtk_menu_new(); /* Don't need to show menus */
/* --- Filter - Events Option --- */
sub_item = gtk_menu_item_new_with_label("events");
/* Add them to the menu */
gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
/* We can attach the Quit menu item to our exit function */
g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
G_CALLBACK (events_clicked),
(gpointer) &tree_info);
/* We do need to show menu items */
gtk_widget_show(sub_item);
/* --- Filter - Advanced Events Option --- */
sub_item = gtk_menu_item_new_with_label("advanced event filter");
/* Add them to the menu */
gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
/* We can attach the Quit menu item to our exit function */
g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
G_CALLBACK (adv_filter_clicked),
(gpointer) &tree_info);
/* We do need to show menu items */
gtk_widget_show(sub_item);
/* --- Filter - CPUs Option --- */
sub_item = gtk_menu_item_new_with_label("CPUs");
/* Add them to the menu */
gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
/* We can attach the Quit menu item to our exit function */
g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
G_CALLBACK (cpus_clicked),
(gpointer) &tree_info);
/* We do need to show menu items */
gtk_widget_show(sub_item);
/* --- End Filter Options --- */
gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu);
/* --- Paging Hbox --- */
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show(hbox);
/* --- Page Spin Button --- */
label = gtk_label_new("Page");
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
gtk_widget_show(label);
spin = gtk_spin_button_new(NULL, 1.0, 0);
gtk_spin_button_set_range(GTK_SPIN_BUTTON(spin), 1, 1);
gtk_box_pack_start(GTK_BOX(hbox), spin, FALSE, FALSE, 0);
gtk_widget_show(spin);
/* --- Search --- */
/* --- Get handle for trace view first --- */
trace_tree = gtk_tree_view_new();
/* The tree needs its columns loaded now */
trace_view_load(trace_tree, handle, spin);
/* Let the handle be freed when the trace_view is */
if (handle)
tracecmd_close(handle);
label = gtk_label_new(" Search: ");
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
gtk_widget_show(label);
trace_view_search_setup(GTK_BOX(hbox), GTK_TREE_VIEW(trace_tree));
/* --- Top Level Hbox --- */
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
gtk_widget_show(hbox);
/* --- Scroll Window --- */
scrollwin = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_box_pack_start(GTK_BOX (hbox), scrollwin, TRUE, TRUE, 0);
gtk_widget_show(scrollwin);
/* --- Set up Trace Tree --- */
gtk_container_add(GTK_CONTAINER(scrollwin), trace_tree);
gtk_widget_show(trace_tree);
/**********************************************
* Main Window
**********************************************/
/* Connect to the delete_event signal and Run the application */
gtk_signal_connect (GTK_OBJECT (window), "delete_event",
(GtkSignalFunc) delete_event,
NULL);
gtk_widget_set_size_request(window, TRACE_WIDTH, TRACE_HEIGHT);
/* Set up info for call backs */
tree_info.trace_tree = trace_tree;
tree_info.spin = spin;
gtk_widget_show (window);
gtk_main ();
}
int main(int argc, char **argv)
{
trace_view(argc, argv);
return 0;
}