diff --git a/common/utils/itti_analyzer/libui/ui_callbacks.c b/common/utils/itti_analyzer/libui/ui_callbacks.c
index f4be4438e9d9bf737348a98131b3a42d1718275a..1ae52ee580fd992448f98cc7998787d279927e86 100644
--- a/common/utils/itti_analyzer/libui/ui_callbacks.c
+++ b/common/utils/itti_analyzer/libui/ui_callbacks.c
@@ -9,6 +9,7 @@
 
 #include "ui_notif_dlg.h"
 #include "ui_main_screen.h"
+#include "ui_menu_bar.h"
 #include "ui_callbacks.h"
 #include "ui_interface.h"
 #include "ui_notifications.h"
@@ -21,45 +22,59 @@
 
 static gboolean ui_handle_socket_connection_failed(gint fd);
 
-gboolean ui_callback_on_open(GtkWidget *widget,
-                             GdkEvent  *event,
-                             gpointer   data)
+gboolean ui_callback_on_open_messages(GtkWidget *widget, GdkEvent *event, gpointer data)
 {
-    g_debug("Open event occurred");
-    CHECK_FCT(ui_file_chooser());
+    g_debug("Open replay event occurred");
+    CHECK_FCT(ui_messages_open_file_chooser());
+
+    return TRUE;
+}
+
+gboolean ui_callback_on_save_messages(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+    g_debug("Save replay event occurred");
+    // CHECK_FCT(ui_file_chooser());
+    return TRUE;
+}
+
+gboolean ui_callback_on_open_filters(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+    g_debug("Open filters event occurred");
+    CHECK_FCT(ui_filters_open_file_chooser());
+    return TRUE;
+}
+
+gboolean ui_callback_on_save_filters(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+    g_debug("Save filters event occurred");
+    CHECK_FCT(ui_filters_save_file_chooser());
     return TRUE;
 }
 
-gboolean ui_callback_on_about(GtkWidget *widget,
-                              GdkEvent  *event,
-                              gpointer   data)
+gboolean ui_callback_on_about(GtkWidget *widget, GdkEvent *event, gpointer data)
 {
 
     return TRUE;
 }
 
-gboolean
-ui_callback_on_select_signal(GtkTreeSelection *selection,
-                             GtkTreeModel     *model,
-                             GtkTreePath      *path,
-                             gboolean          path_currently_selected,
-                             gpointer          user_data)
+gboolean ui_callback_on_select_signal(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path,
+                                      gboolean path_currently_selected, gpointer user_data)
 {
     ui_text_view_t *text_view;
     GtkTreeIter iter;
 
-    text_view = (ui_text_view_t *)user_data;
+    text_view = (ui_text_view_t *) user_data;
 
     g_assert(text_view != NULL);
 
-    if (gtk_tree_model_get_iter(model, &iter, path))
+    if (gtk_tree_model_get_iter (model, &iter, path))
     {
         GValue buffer_store = G_VALUE_INIT;
         gpointer buffer;
 
-        gtk_tree_model_get_value(model, &iter, COL_BUFFER, &buffer_store);
+        gtk_tree_model_get_value (model, &iter, COL_BUFFER, &buffer_store);
 
-        buffer = g_value_get_pointer(&buffer_store);
+        buffer = g_value_get_pointer (&buffer_store);
 
         if (!path_currently_selected)
         {
@@ -76,43 +91,47 @@ ui_callback_on_select_signal(GtkTreeSelection *selection,
 void ui_signal_add_to_list(gpointer data, gpointer user_data)
 {
     buffer_t *signal_buffer;
+    GtkTreePath *path;
+    GtkTreeViewColumn *focus_column;
 
-    signal_buffer = (buffer_t *)data;
+    gtk_tree_view_get_cursor (GTK_TREE_VIEW(ui_main_data.signalslist), &path, &focus_column);
 
-    get_message_id(root, signal_buffer, &signal_buffer->message_id);
+    signal_buffer = (buffer_t *) data;
 
-    ui_tree_view_new_signal_ind(signal_buffer->message_number,
-                                message_id_to_string(signal_buffer->message_id),
-                                get_origin_task_id(signal_buffer),
-                                get_destination_task_id(signal_buffer),
-                                data);
+    get_message_id (root, signal_buffer, &signal_buffer->message_id);
+
+    ui_tree_view_new_signal_ind (signal_buffer->message_number, message_id_to_string (signal_buffer->message_id),
+                                 get_origin_task_id (signal_buffer), get_destination_task_id (signal_buffer), data);
 
     /* Increment number of messages */
     ui_main_data.nb_message_received++;
+
+    /* Check if no signal was selected in the list or if it was the last signal */
+    if ((ui_main_data.path_last == NULL) || (gtk_tree_path_compare(ui_main_data.path_last, path) == 0))
+    {
+        /* Advance to the new last signal */
+        ui_callback_signal_go_to_last (NULL, NULL, NULL);
+    }
 }
 
-static gboolean ui_handle_update_signal_list(gint fd, void *data,
-                                             size_t data_length)
+static gboolean ui_handle_update_signal_list(gint fd, void *data, size_t data_length)
 {
     pipe_new_signals_list_message_t *signal_list_message;
 
     /* Enable buttons to move in the list of signals */
-    gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_clear_button), TRUE);
-    gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_go_to_button), TRUE);
-    gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_go_to_last_button), TRUE);
-    gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_go_to_first_button), TRUE);
+    ui_set_sensitive_move_buttons (TRUE);
 
-    signal_list_message = (pipe_new_signals_list_message_t *)data;
+    signal_list_message = (pipe_new_signals_list_message_t *) data;
 
     g_assert(signal_list_message != NULL);
     g_assert(signal_list_message->signal_list != NULL);
 
-    g_list_foreach(signal_list_message->signal_list, ui_signal_add_to_list, NULL);
+    g_list_foreach (signal_list_message->signal_list, ui_signal_add_to_list, NULL);
 
     /* Free the list but not user data associated with each element */
-    g_list_free(signal_list_message->signal_list);
+    g_list_free (signal_list_message->signal_list);
     /* Free the message */
-    free(signal_list_message);
+    free (signal_list_message);
 
     return TRUE;
 }
@@ -121,17 +140,15 @@ static gboolean ui_handle_socket_connection_failed(gint fd)
 {
     GtkWidget *dialogbox;
 
-    dialogbox = gtk_message_dialog_new(GTK_WINDOW(ui_main_data.window),
-                                       GTK_DIALOG_DESTROY_WITH_PARENT,
-                                       GTK_MESSAGE_ERROR,
-                                       GTK_BUTTONS_CLOSE,
-                                       "Failed to connect to provided host/ip address");
+    dialogbox = gtk_message_dialog_new (GTK_WINDOW(ui_main_data.window), GTK_DIALOG_DESTROY_WITH_PARENT,
+                                        GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+                                        "Failed to connect to provided host/ip address");
 
-    gtk_dialog_run(GTK_DIALOG(dialogbox));
-    gtk_widget_destroy(dialogbox);
+    gtk_dialog_run (GTK_DIALOG(dialogbox));
+    gtk_widget_destroy (dialogbox);
 
     /* Re-enable connect button */
-    ui_enable_connect_button();
+    ui_enable_connect_button ();
     return TRUE;
 }
 
@@ -139,45 +156,42 @@ static gboolean ui_handle_socket_connection_lost(gint fd)
 {
     GtkWidget *dialogbox;
 
-    dialogbox = gtk_message_dialog_new(GTK_WINDOW(ui_main_data.window),
-                                       GTK_DIALOG_DESTROY_WITH_PARENT,
-                                       GTK_MESSAGE_ERROR,
-                                       GTK_BUTTONS_CLOSE,
-                                       "Connection with remote host has been lost");
+    dialogbox = gtk_message_dialog_new (GTK_WINDOW(ui_main_data.window), GTK_DIALOG_DESTROY_WITH_PARENT,
+                                        GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+                                        "Connection with remote host has been lost");
 
-    gtk_dialog_run(GTK_DIALOG(dialogbox));
-    gtk_widget_destroy(dialogbox);
+    gtk_dialog_run (GTK_DIALOG(dialogbox));
+    gtk_widget_destroy (dialogbox);
 
     /* Re-enable connect button */
-    ui_enable_connect_button();
+    ui_enable_connect_button ();
     return TRUE;
 }
 
-static gboolean ui_handle_socket_xml_definition(gint fd, void *data,
-                                                size_t data_length)
+static gboolean ui_handle_socket_xml_definition(gint fd, void *data, size_t data_length)
 {
     pipe_xml_definition_message_t *xml_definition_message;
 
-    xml_definition_message = (pipe_xml_definition_message_t *)data;
+    xml_definition_message = (pipe_xml_definition_message_t *) data;
     g_assert(xml_definition_message != NULL);
     g_assert(data_length == sizeof(pipe_xml_definition_message_t));
 
-    xml_parse_buffer(xml_definition_message->xml_definition,
-                     xml_definition_message->xml_definition_length);
+    xml_parse_buffer (xml_definition_message->xml_definition, xml_definition_message->xml_definition_length);
 
-    free(data);
+    free (data);
 
     return TRUE;
 }
 
 gboolean ui_pipe_callback(gint source, gpointer user_data)
 {
-    void                *input_data = NULL;
-    size_t               input_data_length = 0;
-    pipe_input_header_t  input_header;
+    void *input_data = NULL;
+    size_t input_data_length = 0;
+    pipe_input_header_t input_header;
 
     /* Read the header */
-    if (read(source, &input_header, sizeof(input_header)) < 0) {
+    if (read (source, &input_header, sizeof(input_header)) < 0)
+    {
         g_warning("Failed to read from pipe %d: %s", source, g_strerror(errno));
         return FALSE;
     }
@@ -185,24 +199,27 @@ gboolean ui_pipe_callback(gint source, gpointer user_data)
     input_data_length = input_header.message_size - sizeof(input_header);
 
     /* Checking for non-header part */
-    if (input_data_length > 0) {
-        input_data = malloc(input_data_length);
+    if (input_data_length > 0)
+    {
+        input_data = malloc (input_data_length);
 
-        if (read(source, input_data, input_data_length) < 0) {
+        if (read (source, input_data, input_data_length) < 0)
+        {
             g_warning("Failed to read from pipe %d: %s", source, g_strerror(errno));
             return FALSE;
         }
     }
 
-    switch (input_header.message_type) {
+    switch (input_header.message_type)
+    {
         case UI_PIPE_CONNECTION_FAILED:
-            return ui_handle_socket_connection_failed(source);
+            return ui_handle_socket_connection_failed (source);
         case UI_PIPE_XML_DEFINITION:
-            return ui_handle_socket_xml_definition(source, input_data, input_data_length);
+            return ui_handle_socket_xml_definition (source, input_data, input_data_length);
         case UI_PIPE_CONNECTION_LOST:
-            return ui_handle_socket_connection_lost(source);
+            return ui_handle_socket_connection_lost (source);
         case UI_PIPE_UPDATE_SIGNAL_LIST:
-            return ui_handle_update_signal_list(source, input_data, input_data_length);
+            return ui_handle_update_signal_list (source, input_data, input_data_length);
         default:
             g_debug("[gui] Unhandled message type %u", input_header.message_type);
             g_assert_not_reached();
@@ -210,105 +227,108 @@ gboolean ui_pipe_callback(gint source, gpointer user_data)
     return FALSE;
 }
 
-gboolean ui_callback_on_connect(GtkWidget *widget,
-                                GdkEvent  *event,
-                                gpointer   data)
+gboolean ui_callback_on_connect(GtkWidget *widget, GdkEvent *event, gpointer data)
 {
     /* We have to retrieve the ip address and port of remote host */
     const char *ip;
-    uint16_t    port;
-    int         pipe_fd[2];
+    uint16_t port;
+    int pipe_fd[2];
 
     g_debug("Connect event occurred");
 
-    port = atoi(gtk_entry_get_text(GTK_ENTRY(ui_main_data.portentry)));
-    ip = gtk_entry_get_text(GTK_ENTRY(ui_main_data.ipentry));
+    port = atoi (gtk_entry_get_text (GTK_ENTRY(ui_main_data.portentry)));
+    ip = gtk_entry_get_text (GTK_ENTRY(ui_main_data.ipentry));
 
-    if ((ip == NULL) || (port == 0)) {
+    if ((ip == NULL) || (port == 0))
+    {
         g_warning("NULL parameter given for ip address or port = 0");
         /* TODO: add dialog box here */
         return FALSE;
     }
 
-    ui_pipe_new(pipe_fd, ui_pipe_callback, NULL);
+    ui_pipe_new (pipe_fd, ui_pipe_callback, NULL);
 
-    memcpy(ui_main_data.pipe_fd, pipe_fd, sizeof(int) * 2);
+    memcpy (ui_main_data.pipe_fd, pipe_fd, sizeof(int) * 2);
 
     /* Disable the connect button */
-    ui_disable_connect_button();
+    ui_disable_connect_button ();
 
-    /* Disable buttons to move in the list of signals */
-    gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_clear_button), FALSE);
-    gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_go_to_button), FALSE);
-    gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_go_to_last_button), FALSE);
-    gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_go_to_first_button), FALSE);
-    ui_tree_view_destroy_list(ui_main_data.signalslist);
-
-    if (socket_connect_to_remote_host(ip, port, pipe_fd[1]) != 0) {
-        ui_enable_connect_button();
+    ui_callback_signal_clear_list (widget, event, data);
+
+    if (socket_connect_to_remote_host (ip, port, pipe_fd[1]) != 0)
+    {
+        ui_enable_connect_button ();
         return FALSE;
     }
 
     return TRUE;
 }
 
-gboolean ui_callback_on_disconnect(GtkWidget *widget,
-                                   GdkEvent  *event,
-                                   gpointer   data)
+gboolean ui_callback_on_disconnect(GtkWidget *widget, GdkEvent *event, gpointer data)
 {
     /* We have to retrieve the ip address and port of remote host */
 
     g_debug("Disconnect event occurred");
 
-    ui_pipe_write_message(ui_main_data.pipe_fd[0], UI_PIPE_DISCONNECT_EVT,
-                          NULL, 0);
+    ui_pipe_write_message (ui_main_data.pipe_fd[0], UI_PIPE_DISCONNECT_EVT, NULL, 0);
 
-    ui_enable_connect_button();
+    ui_enable_connect_button ();
     return TRUE;
 }
 
-gboolean ui_callback_signal_go_to(GtkWidget *widget,
-                                  GdkEvent  *event,
-                                  gpointer   data)
+gboolean ui_callback_signal_go_to(GtkWidget *widget, GdkEvent *event, gpointer data)
 {
+    ui_tree_view_select_row (ui_main_data.nb_message_received / 2, NULL);
     return TRUE;
 }
 
-gboolean ui_callback_signal_go_to_first(GtkWidget *widget,
-                                        GdkEvent  *event,
-                                        gpointer   data)
+gboolean ui_callback_signal_go_to_first(GtkWidget *widget, GdkEvent *event, gpointer data)
 {
-    ui_tree_view_select_row(0);
+    ui_tree_view_select_row (0, NULL);
     return TRUE;
 }
 
-gboolean ui_callback_signal_go_to_last(GtkWidget *widget,
-                                       GdkEvent  *event,
-                                       gpointer   data)
+gboolean ui_callback_signal_go_to_last(GtkWidget *widget, GdkEvent *event, gpointer data)
 {
-    ui_tree_view_select_row(ui_main_data.nb_message_received - 1);
+    GtkTreePath *path;
+
+    ui_tree_view_select_row (ui_main_data.nb_message_received - 1, &path);
+    ui_main_data.path_last = path;
+
     return TRUE;
 }
 
-gboolean ui_callback_signal_clear_list(GtkWidget *widget,
-                                       GdkEvent  *event,
-                                       gpointer   data)
+gboolean ui_callback_signal_clear_list(GtkWidget *widget, GdkEvent *event, gpointer data)
 {
     /* Disable buttons to move in the list of signals */
-    gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_clear_button), FALSE);
-    gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_go_to_button), FALSE);
-    gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_go_to_last_button), FALSE);
-    gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_go_to_first_button), FALSE);
+    ui_set_sensitive_move_buttons (FALSE);
 
-    ui_tree_view_destroy_list(ui_main_data.signalslist);
+    /* Clear list of signals */
+    ui_tree_view_destroy_list (ui_main_data.signalslist);
     return TRUE;
 }
 
-gboolean ui_callback_on_tree_view_select(GtkWidget *widget,
-                                         GdkEvent  *event,
-                                         gpointer   data)
+gboolean ui_callback_on_tree_view_select(GtkWidget *widget, GdkEvent *event, gpointer data)
 {
     /* We have to retrieve the ip address and port of remote host */
     g_debug("List selection event occurred");
     return TRUE;
 }
+
+gboolean ui_callback_on_tree_column_header_click_signal(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+    g_debug("ui_callback_on_tree_column_header_click_signal\n");
+    return TRUE;
+}
+
+gboolean ui_callback_on_tree_column_header_click_from(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+    g_debug("ui_callback_on_tree_column_header_click_from\n");
+    return TRUE;
+}
+
+gboolean ui_callback_on_tree_column_header_click_to(GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+    g_debug("ui_callback_on_tree_column_header_click_to\n");
+    return TRUE;
+}
diff --git a/common/utils/itti_analyzer/libui/ui_callbacks.h b/common/utils/itti_analyzer/libui/ui_callbacks.h
index be3ccb9041419b014952a2966af2b9f58bade53f..9524b7c8d383166e390d1a6ab7c74e835c9ef8df 100644
--- a/common/utils/itti_analyzer/libui/ui_callbacks.h
+++ b/common/utils/itti_analyzer/libui/ui_callbacks.h
@@ -1,9 +1,21 @@
 #ifndef UI_CALLBACKS_H_
 #define UI_CALLBACKS_H_
 
-gboolean ui_callback_on_open(GtkWidget *widget,
-                             GdkEvent  *event,
-                             gpointer   data);
+gboolean ui_callback_on_open_messages(GtkWidget *widget,
+                                      GdkEvent  *event,
+                                      gpointer   data);
+
+gboolean ui_callback_on_save_messages(GtkWidget *widget,
+                                      GdkEvent  *event,
+                                      gpointer   data);
+
+gboolean ui_callback_on_open_filters(GtkWidget *widget,
+                                     GdkEvent *event,
+                                     gpointer data);
+
+gboolean ui_callback_on_save_filters(GtkWidget *widget,
+                                     GdkEvent *event,
+                                     gpointer data);
 
 gboolean ui_callback_on_about(GtkWidget *widget,
                               GdkEvent  *event,
@@ -49,4 +61,16 @@ gboolean ui_callback_signal_clear_list(GtkWidget *widget,
 
 gboolean ui_pipe_callback(gint source, gpointer user_data);
 
+gboolean ui_callback_on_tree_column_header_click_signal(GtkWidget *widget,
+                                                        GdkEvent  *event,
+                                                        gpointer   data);
+
+gboolean ui_callback_on_tree_column_header_click_from(GtkWidget *widget,
+                                                      GdkEvent  *event,
+                                                      gpointer   data);
+
+gboolean ui_callback_on_tree_column_header_click_to(GtkWidget *widget,
+                                                    GdkEvent  *event,
+                                                    gpointer   data);
+
 #endif /* UI_CALLBACKS_H_ */
diff --git a/common/utils/itti_analyzer/libui/ui_main_screen.h b/common/utils/itti_analyzer/libui/ui_main_screen.h
index b9d2a5770cafd40e6f4e886a880e7ac186929721..c30b1843294cdf053bc7f0d8abb03d15dd183c18 100644
--- a/common/utils/itti_analyzer/libui/ui_main_screen.h
+++ b/common/utils/itti_analyzer/libui/ui_main_screen.h
@@ -14,6 +14,9 @@ typedef struct {
 
     /* Buttons */
     GtkToolItem *open_replay_file;
+    GtkToolItem *save_replay_file;
+    GtkToolItem *open_filters_file;
+    GtkToolItem *save_filters_file;
     GtkToolItem *connect;
     GtkToolItem *disconnect;
 
@@ -25,6 +28,7 @@ typedef struct {
     GtkToolItem *signals_go_to_first_button;
 
     GtkTreeSelection *selection;
+    GtkTreePath *path_last;
 
     /* Nb of messages received */
     guint nb_message_received;
diff --git a/common/utils/itti_analyzer/libui/ui_menu_bar.c b/common/utils/itti_analyzer/libui/ui_menu_bar.c
index c23ed2d2221e0c2ef20f75f637b4d32aee89510f..e2f5d2b396e7329f3fd03ea1c242a5264cfb19a0 100644
--- a/common/utils/itti_analyzer/libui/ui_menu_bar.c
+++ b/common/utils/itti_analyzer/libui/ui_menu_bar.c
@@ -5,12 +5,24 @@
 #include "ui_menu_bar.h"
 #include "ui_callbacks.h"
 
+void ui_set_sensitive_move_buttons(gboolean enable)
+{
+    // gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_clear_button), enable);
+    // gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_go_to_button), enable);
+    gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_go_to_last_button), enable);
+    gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_go_to_first_button), enable);
+}
+
 int ui_menu_bar_create(GtkWidget *vbox)
 {
     GtkWidget *menubar;
     GtkWidget *filemenu, *helpmenu;
     GtkWidget *file;
     GtkWidget *help;
+    GtkWidget *open_messages;
+    GtkWidget *save_messages;
+    GtkWidget *open_filters;
+    GtkWidget *save_filters;
     GtkWidget *quit;
     GtkWidget *about;
 
@@ -23,11 +35,19 @@ int ui_menu_bar_create(GtkWidget *vbox)
     filemenu = gtk_menu_new();
 
     file = gtk_menu_item_new_with_label("File");
+    open_messages  = gtk_menu_item_new_with_label("Open messages file");
+    save_messages  = gtk_menu_item_new_with_label("Save messages file");
+    open_filters  = gtk_menu_item_new_with_label("Open filters file");
+    save_filters  = gtk_menu_item_new_with_label("Save filters file");
     quit  = gtk_menu_item_new_with_label("Quit");
 
     gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), filemenu);
 
     gtk_menu_shell_append(GTK_MENU_SHELL(menubar), file);
+    gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), open_messages);
+    gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), save_messages);
+    gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), open_filters);
+    gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), save_filters);
     gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), quit);
 
     /* Create the Help submenu */
@@ -44,6 +64,18 @@ int ui_menu_bar_create(GtkWidget *vbox)
     /* Add the menubar to the vbox */
     gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 3);
 
+    g_signal_connect(G_OBJECT(open_messages), "activate",
+                     G_CALLBACK(ui_callback_on_open_messages), NULL);
+
+    g_signal_connect(G_OBJECT(save_messages), "activate",
+                     G_CALLBACK(ui_callback_on_save_messages), NULL);
+
+    g_signal_connect(G_OBJECT(open_filters), "activate",
+                     G_CALLBACK(ui_callback_on_open_filters), NULL);
+
+    g_signal_connect(G_OBJECT(save_filters), "activate",
+                     G_CALLBACK(ui_callback_on_save_filters), NULL);
+
     g_signal_connect(G_OBJECT(quit), "activate",
                      G_CALLBACK(gtk_main_quit), NULL);
 
@@ -70,6 +102,7 @@ int ui_toolbar_create(GtkWidget *vbox)
 
     gtk_container_set_border_width(GTK_CONTAINER(toolbar), 2);
 
+#if 0 /* Not useful anymore, signals list is cleared before every new replay file opening or remote connection */
     /* Button to clear signal list and clear signal dissect view */
     {
         ui_main_data.signals_clear_button = gtk_tool_button_new_from_stock(GTK_STOCK_NEW);
@@ -83,18 +116,55 @@ int ui_toolbar_create(GtkWidget *vbox)
         g_signal_connect(G_OBJECT(ui_main_data.signals_clear_button), "clicked",
                         G_CALLBACK(ui_callback_signal_clear_list), NULL);
     }
+#endif
 
     /* Button to open replay file */
     {
         ui_main_data.open_replay_file = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN);
         gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(ui_main_data.open_replay_file),
-                                    "Open new replay file");
+                                    "Open messages file");
         gtk_toolbar_insert(GTK_TOOLBAR(toolbar), ui_main_data.open_replay_file, -1);
 
         g_signal_connect(G_OBJECT(ui_main_data.open_replay_file), "clicked",
-                        G_CALLBACK(ui_callback_on_open), NULL);
+                        G_CALLBACK(ui_callback_on_open_messages), NULL);
+    }
+
+    /* Button to save replay file */
+    {
+        ui_main_data.save_replay_file = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE);
+        gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(ui_main_data.save_replay_file),
+                                    "Save messages file");
+        gtk_toolbar_insert(GTK_TOOLBAR(toolbar), ui_main_data.save_replay_file, -1);
+
+        g_signal_connect(G_OBJECT(ui_main_data.save_replay_file), "clicked",
+                        G_CALLBACK(ui_callback_on_save_messages), NULL);
+    }
+
+#if 0 /* Too much button in the bar, it is confusing ! */
+    /* Button to open filters file */
+    {
+        ui_main_data.open_filters_file = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN);
+        gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(ui_main_data.open_filters_file),
+                                    "Open filters file");
+        gtk_toolbar_insert(GTK_TOOLBAR(toolbar), ui_main_data.open_filters_file, -1);
+
+        g_signal_connect(G_OBJECT(ui_main_data.open_filters_file), "clicked",
+                        G_CALLBACK(ui_callback_on_open_filters), NULL);
+    }
+
+    /* Button to save filters file */
+    {
+        ui_main_data.save_filters_file = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE);
+        gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(ui_main_data.save_filters_file),
+                                    "Save filters file");
+        gtk_toolbar_insert(GTK_TOOLBAR(toolbar), ui_main_data.save_filters_file, -1);
+
+        g_signal_connect(G_OBJECT(ui_main_data.save_filters_file), "clicked",
+                        G_CALLBACK(ui_callback_on_save_filters), NULL);
     }
+#endif
 
+#if 0 /* This function is already handled by GTK */
     /* Button to go given signal number */
     {
         ui_main_data.signals_go_to_button = gtk_tool_button_new_from_stock(GTK_STOCK_INDEX);
@@ -108,6 +178,7 @@ int ui_toolbar_create(GtkWidget *vbox)
         g_signal_connect(G_OBJECT(ui_main_data.signals_go_to_button), "clicked",
                         G_CALLBACK(ui_callback_signal_go_to), NULL);
     }
+#endif
 
     /* Button to go to first signal in list */
     {
diff --git a/common/utils/itti_analyzer/libui/ui_menu_bar.h b/common/utils/itti_analyzer/libui/ui_menu_bar.h
index 22532079455e19d734527e8cc1b23b12af2be3fd..529a0674c384907a97ea01a26deb792e264e7e86 100644
--- a/common/utils/itti_analyzer/libui/ui_menu_bar.h
+++ b/common/utils/itti_analyzer/libui/ui_menu_bar.h
@@ -1,6 +1,8 @@
 #ifndef UI_MENU_BAR_H_
 #define UI_MENU_BAR_H_
 
+void ui_set_sensitive_move_buttons(gboolean enable);
+
 int ui_menu_bar_create(GtkWidget *vbox);
 
 int ui_toolbar_create(GtkWidget *vbox);
diff --git a/common/utils/itti_analyzer/libui/ui_notifications.c b/common/utils/itti_analyzer/libui/ui_notifications.c
index 15caa49c89b1e07ab4140e26f38d825eeb448e05..dbafad8511536e4da86ff67fd3a6cfcc7bd42003 100644
--- a/common/utils/itti_analyzer/libui/ui_notifications.c
+++ b/common/utils/itti_analyzer/libui/ui_notifications.c
@@ -10,6 +10,7 @@
 
 #include "ui_interface.h"
 #include "ui_main_screen.h"
+#include "ui_menu_bar.h"
 #include "ui_notifications.h"
 #include "ui_callbacks.h"
 
@@ -33,14 +34,16 @@ int ui_enable_connect_button(void)
     return RC_OK;
 }
 
-int ui_file_chooser(void)
+int ui_messages_open_file_chooser(void)
 {
     GtkWidget *filechooser;
     int result = RC_OK;
 
     filechooser = gtk_file_chooser_dialog_new ("Select file", GTK_WINDOW (ui_main_data.window),
-                                               GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
-                                               GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
+                                               GTK_FILE_CHOOSER_ACTION_OPEN,
+                                               GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+                                               GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+                                               NULL);
 
     /* Process the response */
     if (gtk_dialog_run (GTK_DIALOG (filechooser)) == GTK_RESPONSE_ACCEPT)
@@ -50,14 +53,22 @@ int ui_file_chooser(void)
         int read_data = 0;
         void *input_data = NULL;
         size_t input_data_length = 0;
+        int read_messages = 0;
 
         filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filechooser));
 
         source = open (filename, O_RDONLY);
-        if (source >= 0)
+        if (source < 0)
+        {
+            g_warning ("Failed to open file \"%s\": %s", filename, g_strerror (errno));
+            result = RC_FAIL;
+        }
+        else
         {
             itti_socket_header_t message_header;
 
+            ui_callback_signal_clear_list(NULL, NULL, NULL);
+
             do
             {
                 read_data = read (source, &message_header, sizeof(itti_socket_header_t));
@@ -106,6 +117,7 @@ int ui_file_chooser(void)
                             buffer->message_number = itti_signal_header->message_number;
 
                             ui_signal_add_to_list (buffer, NULL);
+                            read_messages ++;
                             break;
                         }
 
@@ -124,7 +136,13 @@ int ui_file_chooser(void)
                 }
             } while (read_data > 0);
 
-            g_debug ("Read %d message from file \"%s\"\n", ui_main_data.nb_message_received, filename);
+            if (read_messages > 0)
+            {
+                /* Enable buttons to move in the list of signals */
+                ui_set_sensitive_move_buttons(TRUE);
+            }
+
+            g_debug ("Read %d messages from file \"%s\"\n", read_messages, filename);
 
             close (source);
         }
@@ -137,6 +155,63 @@ int ui_file_chooser(void)
     return result;
 }
 
+int ui_filters_open_file_chooser(void)
+{
+    GtkWidget *filechooser;
+    int result = RC_OK;
+
+    filechooser = gtk_file_chooser_dialog_new ("Select file", GTK_WINDOW (ui_main_data.window),
+                                               GTK_FILE_CHOOSER_ACTION_OPEN,
+                                               GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+                                               GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+                                               NULL);
+
+    /* Process the response */
+    if (gtk_dialog_run (GTK_DIALOG (filechooser)) == GTK_RESPONSE_ACCEPT)
+    {
+        char *filename;
+
+        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filechooser));
+
+        g_free (filename);
+    }
+
+    gtk_widget_destroy (filechooser);
+
+    return RC_OK;
+}
+
+int ui_filters_save_file_chooser(void)
+{
+    GtkWidget *filechooser;
+    int result = RC_OK;
+
+    filechooser = gtk_file_chooser_dialog_new ("Save file", GTK_WINDOW (ui_main_data.window),
+                                               GTK_FILE_CHOOSER_ACTION_SAVE,
+                                               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                               GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+                                               NULL);
+
+    gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (filechooser), TRUE);
+
+    //gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (filechooser), "filters.xml");
+    gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (filechooser), "./filters.xml");
+
+    /* Process the response */
+    if (gtk_dialog_run (GTK_DIALOG (filechooser)) == GTK_RESPONSE_ACCEPT)
+    {
+        char *filename;
+
+        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filechooser));
+
+        g_free (filename);
+    }
+
+    gtk_widget_destroy (filechooser);
+
+    return RC_OK;
+}
+
 int ui_progress_bar_set_fraction(double fraction)
 {
 //     /* If not exist instantiate */
diff --git a/common/utils/itti_analyzer/libui/ui_notifications.h b/common/utils/itti_analyzer/libui/ui_notifications.h
index 4cee44c3546b5fd1c4578fd53106ca2a9a719c58..fcb38540f82328da751a8909e8527e731675c26c 100644
--- a/common/utils/itti_analyzer/libui/ui_notifications.h
+++ b/common/utils/itti_analyzer/libui/ui_notifications.h
@@ -5,7 +5,11 @@ int ui_disable_connect_button(void);
 
 int ui_enable_connect_button(void);
 
-int ui_file_chooser(void);
+int ui_messages_open_file_chooser(void);
+
+int ui_filters_open_file_chooser(void);
+
+int ui_filters_save_file_chooser(void);
 
 int ui_progress_bar_set_fraction(double fraction);
 
diff --git a/common/utils/itti_analyzer/libui/ui_tree_view.c b/common/utils/itti_analyzer/libui/ui_tree_view.c
index 269f65ad2c1719da94e382f7f322593642b8b50b..dcbadd65593ba05d6d3250a93a19ae3eaed6788c 100644
--- a/common/utils/itti_analyzer/libui/ui_tree_view.c
+++ b/common/utils/itti_analyzer/libui/ui_tree_view.c
@@ -28,14 +28,20 @@ ui_tree_view_init_list(GtkWidget *list)
     column = gtk_tree_view_column_new_with_attributes(
         "Signal", renderer, "text", COL_SIGNAL, NULL);
     gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
+    g_signal_connect(G_OBJECT(column), "clicked",
+                     G_CALLBACK(ui_callback_on_tree_column_header_click_signal), NULL);
 
     column = gtk_tree_view_column_new_with_attributes(
         "From", renderer, "text", COL_FROM_TASK, NULL);
     gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
+    g_signal_connect(G_OBJECT(column), "clicked",
+                     G_CALLBACK(ui_callback_on_tree_column_header_click_from), NULL);
 
     column = gtk_tree_view_column_new_with_attributes(
         "To", renderer, "text", COL_TO_TASK, NULL);
     gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
+    g_signal_connect(G_OBJECT(column), "clicked",
+                     G_CALLBACK(ui_callback_on_tree_column_header_click_to), NULL);
 
     store = gtk_list_store_new(NUM_COLS,
                                G_TYPE_STRING,
@@ -86,6 +92,9 @@ void ui_tree_view_destroy_list(GtkWidget *list)
     store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
 
     gtk_list_store_clear(store);
+
+    /* Reset number of messages */
+    ui_main_data.nb_message_received = 0;
 }
 
 int ui_tree_view_create(GtkWidget *window, GtkWidget *vbox)
@@ -112,6 +121,7 @@ int ui_tree_view_create(GtkWidget *window, GtkWidget *vbox)
                       ui_main_data.signalslist);
 
     ui_tree_view_init_list(ui_main_data.signalslist);
+    gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(ui_main_data.signalslist), TRUE);
 
     gtk_widget_set_size_request(GTK_WIDGET(scrolled_window), 500, -1);
     gtk_box_pack_start(GTK_BOX(hbox), scrolled_window, FALSE, FALSE, 0);
@@ -141,13 +151,21 @@ int ui_tree_view_new_signal_ind(const uint32_t message_number, const char *signa
     return RC_OK;
 }
 
-void ui_tree_view_select_row(gint row)
+void ui_tree_view_select_row(gint row, GtkTreePath **path)
 {
-    GtkTreePath *path;
+    GtkTreePath *path_row;
     gchar        indice[10];
 
     sprintf(indice, "%d", row);
 
-    path = gtk_tree_path_new_from_string(indice);
-    gtk_tree_view_set_cursor(GTK_TREE_VIEW(ui_main_data.signalslist), path, NULL, FALSE);
+    path_row = gtk_tree_path_new_from_string(indice);
+    /* Select the message in requested row */
+    gtk_tree_view_set_cursor(GTK_TREE_VIEW(ui_main_data.signalslist), path_row, NULL, FALSE);
+    /* Center the message in the middle of the list if possible */
+    gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(ui_main_data.signalslist), path_row, NULL, TRUE, 0.5, 0.0);
+
+    if (path != NULL)
+    {
+        *path = path_row;
+    }
 }
diff --git a/common/utils/itti_analyzer/libui/ui_tree_view.h b/common/utils/itti_analyzer/libui/ui_tree_view.h
index 83691c664121506582e28ccd5a19e7678cae5505..e04224c8578dbb0eac11a955818009d691637e51 100644
--- a/common/utils/itti_analyzer/libui/ui_tree_view.h
+++ b/common/utils/itti_analyzer/libui/ui_tree_view.h
@@ -1,7 +1,7 @@
 #ifndef UI_TREE_VIEW_H_
 #define UI_TREE_VIEW_H_
 
-enum
+typedef enum
 {
     COL_MSG_NUM = 0,
     COL_SIGNAL,
@@ -9,7 +9,7 @@ enum
     COL_TO_TASK,
     COL_BUFFER,
     NUM_COLS
-};
+} col_type_e;
 
 int ui_tree_view_create(GtkWidget *window, GtkWidget *vbox);
 
@@ -18,6 +18,6 @@ int ui_tree_view_new_signal_ind(const uint32_t message_number, const char *signa
 
 void ui_tree_view_destroy_list(GtkWidget *list);
 
-void ui_tree_view_select_row(gint row);
+void ui_tree_view_select_row(gint row, GtkTreePath **path);
 
 #endif /* UI_TREE_VIEW_H_ */