trace-graph: Add loading and saving of task and event filters

Add the filter loading and saving to trace-graph. Most of the work
was done already to get trace-view working. This just hooks into
that framework.

Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
diff --git a/trace-graph-main.c b/trace-graph-main.c
index 303f342..4a9fed1 100644
--- a/trace-graph-main.c
+++ b/trace-graph-main.c
@@ -152,6 +152,50 @@
 	free(selected);
 }
 
+/* Callback for the clicked signal of the Load Filters button */
+static void
+load_filters_clicked (gpointer data)
+{
+	struct graph_info *ginfo = data;
+	struct tracecmd_xml_handle *handle;
+	gchar *filename;
+
+	filename = trace_get_file_dialog("Load Filters");
+	if (!filename)
+		return;
+
+	handle = tracecmd_xml_open(filename);
+	if (!handle)
+		warning("Could not open %s", filename);
+	g_free(filename);
+
+	trace_graph_load_filters(ginfo, handle);
+
+	tracecmd_xml_close(handle);
+}
+
+/* Callback for the clicked signal of the Save Filters button */
+static void
+save_filters_clicked (gpointer data)
+{
+	struct graph_info *ginfo = data;
+	struct tracecmd_xml_handle *handle;
+	gchar *filename;
+
+	filename = trace_get_file_dialog("Save Filters");
+	if (!filename)
+		return;
+
+	handle = tracecmd_xml_create(filename);
+	if (!handle)
+		warning("Could not create %s", filename);
+	g_free(filename);
+
+	trace_graph_save_filters(ginfo, handle);
+
+	tracecmd_xml_close(handle);
+}
+
 void trace_graph(int argc, char **argv)
 {
 	struct tracecmd_input *handle = NULL;
@@ -247,6 +291,35 @@
 	gtk_widget_show(sub_item);
 
 
+	/* --- File - Load Filter Option --- */
+
+	sub_item = gtk_menu_item_new_with_label("Load filters");
+
+	/* Add them to the menu */
+	gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
+
+	g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
+				  G_CALLBACK (load_filters_clicked),
+				  (gpointer) ginfo);
+
+	/* We do need to show menu items */
+	gtk_widget_show(sub_item);
+
+
+	/* --- File - Save Filter Option --- */
+
+	sub_item = gtk_menu_item_new_with_label("Save filters");
+
+	/* Add them to the menu */
+	gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item);
+
+	g_signal_connect_swapped (G_OBJECT (sub_item), "activate",
+				  G_CALLBACK (save_filters_clicked),
+				  (gpointer) ginfo);
+
+	/* We do need to show menu items */
+	gtk_widget_show(sub_item);
+
 	/* --- File - Quit Option --- */
 
 	sub_item = gtk_menu_item_new_with_label("Quit");
diff --git a/trace-graph.c b/trace-graph.c
index 6ed7851..9ec3924 100644
--- a/trace-graph.c
+++ b/trace-graph.c
@@ -32,6 +32,8 @@
 #include "trace-hash.h"
 #include "trace-filter.h"
 
+#include "version.h"
+
 #include "util.h"
 
 #define DEBUG_LEVEL	0
@@ -2395,6 +2397,123 @@
 	return 0;
 }
 
+static int load_event_filter(struct graph_info *ginfo,
+			     struct tracecmd_xml_handle *handle,
+			     struct tracecmd_xml_system_node *node)
+{
+	struct tracecmd_xml_system_node *child;
+	struct event_filter *event_filter;
+	const char *name;
+	const char *value;
+
+	event_filter = ginfo->event_filter;
+
+	child = tracecmd_xml_node_child(node);
+	name = tracecmd_xml_node_type(child);
+	if (strcmp(name, "FilterType") != 0)
+		return -1;
+
+	value = tracecmd_xml_node_value(handle, child);
+	/* Do nothing with all events enabled */
+	if (strcmp(value, "all events") == 0)
+		return 0;
+
+	node = tracecmd_xml_node_next(child);
+	if (!node)
+		return -1;
+
+	pevent_filter_clear_trivial(event_filter, FILTER_TRIVIAL_BOTH);
+	ginfo->all_events = FALSE;
+
+	trace_filter_load_events(event_filter, handle, node);
+
+	return 0;
+}
+
+int trace_graph_load_filters(struct graph_info *ginfo,
+			     struct tracecmd_xml_handle *handle)
+{
+	struct tracecmd_xml_system *system;
+	struct tracecmd_xml_system_node *syschild;
+	const char *name;
+
+	system = tracecmd_xml_find_system(handle, "TraceGraph");
+	if (!system)
+		return -1;
+
+	syschild = tracecmd_xml_system_node(system);
+	if (!syschild)
+		goto out_free_sys;
+
+	do {
+		name = tracecmd_xml_node_type(syschild);
+
+		if (strcmp(name, "EventFilter") == 0)
+			load_event_filter(ginfo, handle, syschild);
+
+		else if (strcmp(name, "TaskFilter") == 0)
+			trace_filter_load_task_filter(ginfo->task_filter, handle, syschild);
+
+		else if (strcmp(name, "HideTasks") == 0)
+			trace_filter_load_task_filter(ginfo->hide_tasks, handle, syschild);
+
+		syschild = tracecmd_xml_node_next(syschild);
+	} while (syschild);
+
+	if (filter_task_count(ginfo->task_filter) ||
+	    filter_task_count(ginfo->hide_tasks))
+		ginfo->filter_available = 1;
+	else
+		ginfo->filter_available = 0;
+
+	tracecmd_xml_free_system(system);
+
+	trace_graph_refresh(ginfo);
+
+	return 0;
+
+ out_free_sys:
+	tracecmd_xml_free_system(system);
+	return -1;
+}
+
+int trace_graph_save_filters(struct graph_info *ginfo,
+			     struct tracecmd_xml_handle *handle)
+{
+	struct event_filter *event_filter;
+
+	tracecmd_xml_start_system(handle, "TraceGraph", VERSION_STRING);
+
+	event_filter = ginfo->event_filter;
+
+	tracecmd_xml_start_sub_system(handle, "EventFilter");
+
+	if (ginfo->all_events || !event_filter)
+		tracecmd_xml_write_element(handle, "FilterType", "all events");
+	else {
+		tracecmd_xml_write_element(handle, "FilterType", "filter");
+		trace_filter_save_events(handle, event_filter);
+	}
+
+	tracecmd_xml_end_sub_system(handle);
+
+	if (ginfo->task_filter && filter_task_count(ginfo->task_filter)) {
+		tracecmd_xml_start_sub_system(handle, "TaskFilter");
+		trace_filter_save_tasks(handle, ginfo->task_filter);
+		tracecmd_xml_end_sub_system(handle);
+	}
+
+	if (ginfo->hide_tasks && filter_task_count(ginfo->hide_tasks)) {
+		tracecmd_xml_start_sub_system(handle, "HideTasks");
+		trace_filter_save_tasks(handle, ginfo->hide_tasks);
+		tracecmd_xml_end_sub_system(handle);
+	}
+
+	tracecmd_xml_end_system(handle);
+
+	return 0;
+}
+
 struct graph_info *
 trace_graph_create_with_callbacks(struct tracecmd_input *handle,
 				  struct graph_callbacks *cbs)
diff --git a/trace-graph.h b/trace-graph.h
index 91ae161..916ad50 100644
--- a/trace-graph.h
+++ b/trace-graph.h
@@ -24,6 +24,7 @@
 #include <gtk/gtk.h>
 #include "trace-cmd.h"
 #include "trace-hash.h"
+#include "trace-xml.h"
 
 struct graph_info;
 
@@ -306,6 +307,11 @@
 			     struct event_filter *event_filter);
 gint *trace_graph_task_list(struct graph_info *ginfo);
 
+int trace_graph_load_filters(struct graph_info *ginfo,
+			     struct tracecmd_xml_handle *handle);
+int trace_graph_save_filters(struct graph_info *ginfo,
+			     struct tracecmd_xml_handle *handle);
+
 /* plots */
 void trace_graph_plot_free(struct graph_info *ginfo);
 void trace_graph_plot_init(struct graph_info *ginfo);