Commit 0680e22f authored by winckel's avatar winckel

Added buttons, menu items and calback functions to open and save messages files.

Added menu items and calback functions to open and save filters files.
By default, the signal list tree view show the last received signals, this can be stop by selecting manually another signal (not the last one).
Removed the "new" button, the signals list is cleared before each new aquisition or when opening a messages file becausethe signal list may not be compatible between to list of signals!
Enabled column header clicks and created callback functions to display and modify column filters.

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4316 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent 4c01f4f7
Branches unavailable
2023.w22 2023.w21 2023.w20 2023.w19 2023.w18 2023.w18b 2023.w16 2023.w15 2023.w14 2023.w13 2023.w12 2023.w11 2023.w11b 2023.w10 2023.w10b 2023.w09 2023.w08 2023.w08b 2023.w07 2023.w06 2023.w05 2023.w03 2023.w02 2022.42 2022.41 2022.w51 2022.w50 2022.w49 2022.w48 2022.w47 2022.w46 2022.w45 2022.w43 2022.w42 2022.w42b 2022.w41 2022.w40 2022.w39 2022.w38 2022.w37 2022.w37b 2022.w36 2022.w35 2022.w33 2022.w32 2022.w31 2022.w31b 2022.w30 2022.w29 2022.w26 2022.w25 2022.w24 2022.w24b 2022.w23 2022.w22 2022.w21 2022.w20 2022.w19 2022.w18 2022.w17 2022.w15 2022.w15b 2022.w14a 2022.w13 2022.w13b 2022.w13a 2022.w12 2022.w10 2022.w09 2022.w09b 2022.w08 2022.w08b 2022.w07 2022.w07b 2022.w06 2022.w06a 2022.w05 2022.w05b 2022.w03_hotfix 2022.w03_b 2022.w02 2022.w01 2021.wk46 2021.wk14_a 2021.wk13_d 2021.wk13_c 2021.w51_c 2021.w51_a 2021.w50_a 2021.w49_b 2021.w49_a 2021.w48 2021.w47 2021.w46 2021.w46-powder 2021.w45 2021.w45_b 2021.w44 2021.w43 2021.w42 2021.w37 2021.w36 2021.w35 2021.w34 2021.w33 2021.w32 2021.w31 2021.w30 2021.w29 2021.w28 2021.w27 2021.w26 2021.w25 2021.w24 2021.w23 2021.w22 2021.w20 2021.w19 2021.w18_b 2021.w18_a 2021.w17_b 2021.w16 2021.w15 2021.w14 2021.w13_a 2021.w12 2021.w11 2021.w10 2021.w09 2021.w08 2021.w06 2021.w05 2021.w04 2021.w02 2020.w51_2 2020.w51 2020.w50 2020.w49 2020.w48_2 2020.w48 2020.w47 2020.w46_2 2020.w46 2020.w45_2 2020.w45 2020.w44 2020.w42_2 2020.w42 2020.w41 2020.w39 2020.w38 2020.w37 2020.w36 2020.w34 2020.w33 2020.w31 2020.w30 2020.w29 2020.w28 2020.w26 2020.w25 2020.w24 2020.w23 2020.w22 2020.w19 2020.w17 2020.w16 2020.w15 2020.w11 2020.w09 2020.w06 2020.w05 2020.w04 2020.w03 2019.w51 2019.w44 2019.w41 2019.w36 2019.w30 2019.w28 2019.w27 2019.w25 2019.w23 2019.w21 2019.w17 2019.w15 2019.w13 2019.w11 2019.w10 2019.w09 2019.w08 2019.w07 2019.w06 2019.w04 2019.w03 2018.w51 2018.w48 2018.w47 2018.w46 2018.w44 2018.w41 2018.w40 2018.w39 2018.w36 2018.w33 2018.w31 2018.w29 2018.w25 2018.w19 2018.w15 2018.w12 2018.w11 2018.w10 2018.w09 2018.w08 2018.w07 2018.w06 2018.w05 2018.w04 2018.w03 2018.w02 2017.w48 2017.w46 2017.w43 2017.w42 2017.w34 2017.w30 2017.w25 2017.w24 2017.w22 2017.w20 2017.w19 2017.w15 2017.w14 2017.w13 2017.w12 2017.w11 2017.w10 2017.w09 2017.w08 2017.w07 2017.w06 2017.w05 2017.w04 2017.w03 2017.w02 2017.w01 2016.w50 2016.w49 v1.2.2 v1.2.1 v1.2.0 v1.1.1 v1.1.0 v1.0.3 v1.0.2 v1.0.1 v1.0.0 v1B0.8 v1B0.7 v1B0.6 v1B0.5 v1B0.4 v1B0.3 v1B0.2 v1B0.1 v0.6.1 v0.6.1_tdd v0.6 v0.5.2 v0.5.1_tdd v0.5 v0.4 v0.3 v0.2 v0.1 testing-cmw500 setparam osa-etsi-ws-ue osa-etsi-ws-try2 osa-etsi-ws-try1 osa-etsi-ws-gNB oai_nr_sync nr-ip-over-lte nr-ip-over-lte-v.1.5 nr-ip-over-lte-v.1.4 nr-ip-over-lte-v.1.3 nr-ip-over-lte-v.1.2 nr-ip-over-lte-v.1.1 nr-ip-over-lte-v.1.0 flexran-eol develop-nr-pdcch develop-nr-2020w03 develop-nr-2020w02 develop-nr-2019w51 develop-nr-2019w50 develop-nr-2019w48 develop-nr-2019w47 develop-nr-2019w45 develop-nr-2019w43 develop-nr-2019w42 develop-nr-2019w40 develop-nr-2019w28 develop-nr-2019w23 benetel_phase_rotation benetel_gnb_rel_2.0 benetel_gnb_rel_1.0 benetel_enb_rel_2.0 benetel_enb_rel_1.0
No related merge requests found
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "ui_notif_dlg.h" #include "ui_notif_dlg.h"
#include "ui_main_screen.h" #include "ui_main_screen.h"
#include "ui_menu_bar.h"
#include "ui_callbacks.h" #include "ui_callbacks.h"
#include "ui_interface.h" #include "ui_interface.h"
#include "ui_notifications.h" #include "ui_notifications.h"
...@@ -21,45 +22,59 @@ ...@@ -21,45 +22,59 @@
static gboolean ui_handle_socket_connection_failed(gint fd); static gboolean ui_handle_socket_connection_failed(gint fd);
gboolean ui_callback_on_open(GtkWidget *widget, gboolean ui_callback_on_open_messages(GtkWidget *widget, GdkEvent *event, gpointer data)
GdkEvent *event,
gpointer data)
{ {
g_debug("Open event occurred"); g_debug("Open replay event occurred");
CHECK_FCT(ui_file_chooser()); 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; return TRUE;
} }
gboolean ui_callback_on_about(GtkWidget *widget, gboolean ui_callback_on_about(GtkWidget *widget, GdkEvent *event, gpointer data)
GdkEvent *event,
gpointer data)
{ {
return TRUE; return TRUE;
} }
gboolean gboolean ui_callback_on_select_signal(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path,
ui_callback_on_select_signal(GtkTreeSelection *selection, gboolean path_currently_selected, gpointer user_data)
GtkTreeModel *model,
GtkTreePath *path,
gboolean path_currently_selected,
gpointer user_data)
{ {
ui_text_view_t *text_view; ui_text_view_t *text_view;
GtkTreeIter iter; GtkTreeIter iter;
text_view = (ui_text_view_t *)user_data; text_view = (ui_text_view_t *) user_data;
g_assert(text_view != NULL); 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; GValue buffer_store = G_VALUE_INIT;
gpointer buffer; 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) if (!path_currently_selected)
{ {
...@@ -76,43 +91,47 @@ ui_callback_on_select_signal(GtkTreeSelection *selection, ...@@ -76,43 +91,47 @@ ui_callback_on_select_signal(GtkTreeSelection *selection,
void ui_signal_add_to_list(gpointer data, gpointer user_data) void ui_signal_add_to_list(gpointer data, gpointer user_data)
{ {
buffer_t *signal_buffer; 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, get_message_id (root, signal_buffer, &signal_buffer->message_id);
message_id_to_string(signal_buffer->message_id),
get_origin_task_id(signal_buffer), ui_tree_view_new_signal_ind (signal_buffer->message_number, message_id_to_string (signal_buffer->message_id),
get_destination_task_id(signal_buffer), get_origin_task_id (signal_buffer), get_destination_task_id (signal_buffer), data);
data);
/* Increment number of messages */ /* Increment number of messages */
ui_main_data.nb_message_received++; 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, static gboolean ui_handle_update_signal_list(gint fd, void *data, size_t data_length)
size_t data_length)
{ {
pipe_new_signals_list_message_t *signal_list_message; pipe_new_signals_list_message_t *signal_list_message;
/* Enable buttons to move in the list of signals */ /* Enable buttons to move in the list of signals */
gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_clear_button), TRUE); ui_set_sensitive_move_buttons (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);
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 != NULL);
g_assert(signal_list_message->signal_list != 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 */ /* 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 the message */
free(signal_list_message); free (signal_list_message);
return TRUE; return TRUE;
} }
...@@ -121,17 +140,15 @@ static gboolean ui_handle_socket_connection_failed(gint fd) ...@@ -121,17 +140,15 @@ static gboolean ui_handle_socket_connection_failed(gint fd)
{ {
GtkWidget *dialogbox; GtkWidget *dialogbox;
dialogbox = gtk_message_dialog_new(GTK_WINDOW(ui_main_data.window), dialogbox = gtk_message_dialog_new (GTK_WINDOW(ui_main_data.window), GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
GTK_MESSAGE_ERROR, "Failed to connect to provided host/ip address");
GTK_BUTTONS_CLOSE,
"Failed to connect to provided host/ip address");
gtk_dialog_run(GTK_DIALOG(dialogbox)); gtk_dialog_run (GTK_DIALOG(dialogbox));
gtk_widget_destroy(dialogbox); gtk_widget_destroy (dialogbox);
/* Re-enable connect button */ /* Re-enable connect button */
ui_enable_connect_button(); ui_enable_connect_button ();
return TRUE; return TRUE;
} }
...@@ -139,45 +156,42 @@ static gboolean ui_handle_socket_connection_lost(gint fd) ...@@ -139,45 +156,42 @@ static gboolean ui_handle_socket_connection_lost(gint fd)
{ {
GtkWidget *dialogbox; GtkWidget *dialogbox;
dialogbox = gtk_message_dialog_new(GTK_WINDOW(ui_main_data.window), dialogbox = gtk_message_dialog_new (GTK_WINDOW(ui_main_data.window), GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
GTK_MESSAGE_ERROR, "Connection with remote host has been lost");
GTK_BUTTONS_CLOSE,
"Connection with remote host has been lost");
gtk_dialog_run(GTK_DIALOG(dialogbox)); gtk_dialog_run (GTK_DIALOG(dialogbox));
gtk_widget_destroy(dialogbox); gtk_widget_destroy (dialogbox);
/* Re-enable connect button */ /* Re-enable connect button */
ui_enable_connect_button(); ui_enable_connect_button ();
return TRUE; return TRUE;
} }
static gboolean ui_handle_socket_xml_definition(gint fd, void *data, static gboolean ui_handle_socket_xml_definition(gint fd, void *data, size_t data_length)
size_t data_length)
{ {
pipe_xml_definition_message_t *xml_definition_message; 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(xml_definition_message != NULL);
g_assert(data_length == sizeof(pipe_xml_definition_message_t)); g_assert(data_length == sizeof(pipe_xml_definition_message_t));
xml_parse_buffer(xml_definition_message->xml_definition, xml_parse_buffer (xml_definition_message->xml_definition, xml_definition_message->xml_definition_length);
xml_definition_message->xml_definition_length);
free(data); free (data);
return TRUE; return TRUE;
} }
gboolean ui_pipe_callback(gint source, gpointer user_data) gboolean ui_pipe_callback(gint source, gpointer user_data)
{ {
void *input_data = NULL; void *input_data = NULL;
size_t input_data_length = 0; size_t input_data_length = 0;
pipe_input_header_t input_header; pipe_input_header_t input_header;
/* Read the 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)); g_warning("Failed to read from pipe %d: %s", source, g_strerror(errno));
return FALSE; return FALSE;
} }
...@@ -185,24 +199,27 @@ gboolean ui_pipe_callback(gint source, gpointer user_data) ...@@ -185,24 +199,27 @@ gboolean ui_pipe_callback(gint source, gpointer user_data)
input_data_length = input_header.message_size - sizeof(input_header); input_data_length = input_header.message_size - sizeof(input_header);
/* Checking for non-header part */ /* Checking for non-header part */
if (input_data_length > 0) { if (input_data_length > 0)
input_data = malloc(input_data_length); {
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)); g_warning("Failed to read from pipe %d: %s", source, g_strerror(errno));
return FALSE; return FALSE;
} }
} }
switch (input_header.message_type) { switch (input_header.message_type)
{
case UI_PIPE_CONNECTION_FAILED: case UI_PIPE_CONNECTION_FAILED:
return ui_handle_socket_connection_failed(source); return ui_handle_socket_connection_failed (source);
case UI_PIPE_XML_DEFINITION: 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: 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: 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: default:
g_debug("[gui] Unhandled message type %u", input_header.message_type); g_debug("[gui] Unhandled message type %u", input_header.message_type);
g_assert_not_reached(); g_assert_not_reached();
...@@ -210,105 +227,108 @@ gboolean ui_pipe_callback(gint source, gpointer user_data) ...@@ -210,105 +227,108 @@ gboolean ui_pipe_callback(gint source, gpointer user_data)
return FALSE; return FALSE;
} }
gboolean ui_callback_on_connect(GtkWidget *widget, gboolean ui_callback_on_connect(GtkWidget *widget, GdkEvent *event, gpointer data)
GdkEvent *event,
gpointer data)
{ {
/* We have to retrieve the ip address and port of remote host */ /* We have to retrieve the ip address and port of remote host */
const char *ip; const char *ip;
uint16_t port; uint16_t port;
int pipe_fd[2]; int pipe_fd[2];
g_debug("Connect event occurred"); g_debug("Connect event occurred");
port = atoi(gtk_entry_get_text(GTK_ENTRY(ui_main_data.portentry))); port = atoi (gtk_entry_get_text (GTK_ENTRY(ui_main_data.portentry)));
ip = gtk_entry_get_text(GTK_ENTRY(ui_main_data.ipentry)); 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"); g_warning("NULL parameter given for ip address or port = 0");
/* TODO: add dialog box here */ /* TODO: add dialog box here */
return FALSE; 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 */ /* Disable the connect button */
ui_disable_connect_button(); ui_disable_connect_button ();
/* Disable buttons to move in the list of signals */ ui_callback_signal_clear_list (widget, event, data);
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); if (socket_connect_to_remote_host (ip, port, pipe_fd[1]) != 0)
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_enable_connect_button ();
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();
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
gboolean ui_callback_on_disconnect(GtkWidget *widget, gboolean ui_callback_on_disconnect(GtkWidget *widget, GdkEvent *event, gpointer data)
GdkEvent *event,
gpointer data)
{ {
/* We have to retrieve the ip address and port of remote host */ /* We have to retrieve the ip address and port of remote host */
g_debug("Disconnect event occurred"); g_debug("Disconnect event occurred");
ui_pipe_write_message(ui_main_data.pipe_fd[0], UI_PIPE_DISCONNECT_EVT, ui_pipe_write_message (ui_main_data.pipe_fd[0], UI_PIPE_DISCONNECT_EVT, NULL, 0);
NULL, 0);
ui_enable_connect_button(); ui_enable_connect_button ();
return TRUE; return TRUE;
} }
gboolean ui_callback_signal_go_to(GtkWidget *widget, gboolean ui_callback_signal_go_to(GtkWidget *widget, GdkEvent *event, gpointer data)
GdkEvent *event,
gpointer data)
{ {
ui_tree_view_select_row (ui_main_data.nb_message_received / 2, NULL);
return TRUE; return TRUE;
} }
gboolean ui_callback_signal_go_to_first(GtkWidget *widget, gboolean ui_callback_signal_go_to_first(GtkWidget *widget, GdkEvent *event, gpointer data)
GdkEvent *event,
gpointer data)
{ {
ui_tree_view_select_row(0); ui_tree_view_select_row (0, NULL);
return TRUE; return TRUE;
} }
gboolean ui_callback_signal_go_to_last(GtkWidget *widget, gboolean ui_callback_signal_go_to_last(GtkWidget *widget, GdkEvent *event, gpointer data)
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; return TRUE;
} }
gboolean ui_callback_signal_clear_list(GtkWidget *widget, gboolean ui_callback_signal_clear_list(GtkWidget *widget, GdkEvent *event, gpointer data)
GdkEvent *event,
gpointer data)
{ {
/* Disable buttons to move in the list of signals */ /* Disable buttons to move in the list of signals */
gtk_widget_set_sensitive(GTK_WIDGET(ui_main_data.signals_clear_button), FALSE); ui_set_sensitive_move_buttons (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); /* Clear list of signals */
ui_tree_view_destroy_list (ui_main_data.signalslist);
return TRUE; return TRUE;
} }
gboolean ui_callback_on_tree_view_select(GtkWidget *widget, gboolean ui_callback_on_tree_view_select(GtkWidget *widget, GdkEvent *event, gpointer data)
GdkEvent *event,
gpointer data)
{ {
/* We have to retrieve the ip address and port of remote host */ /* We have to retrieve the ip address and port of remote host */
g_debug("List selection event occurred"); g_debug("List selection event occurred");
return TRUE; 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;
}
#ifndef UI_CALLBACKS_H_ #ifndef UI_CALLBACKS_H_
#define UI_CALLBACKS_H_ #define UI_CALLBACKS_H_
gboolean ui_callback_on_open(GtkWidget *widget, gboolean ui_callback_on_open_messages(GtkWidget *widget,
GdkEvent *event, GdkEvent *event,
gpointer data); 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, gboolean ui_callback_on_about(GtkWidget *widget,
GdkEvent *event, GdkEvent *event,
...@@ -49,4 +61,16 @@ gboolean ui_callback_signal_clear_list(GtkWidget *widget, ...@@ -49,4 +61,16 @@ gboolean ui_callback_signal_clear_list(GtkWidget *widget,
gboolean ui_pipe_callback(gint source, gpointer user_data); 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_ */ #endif /* UI_CALLBACKS_H_ */
...@@ -14,6 +14,9 @@ typedef struct { ...@@ -14,6 +14,9 @@ typedef struct {
/* Buttons */ /* Buttons */
GtkToolItem *open_replay_file; GtkToolItem *open_replay_file;
GtkToolItem *save_replay_file;
GtkToolItem *open_filters_file;
GtkToolItem *save_filters_file;
GtkToolItem *connect; GtkToolItem *connect;
GtkToolItem *disconnect; GtkToolItem *disconnect;
...@@ -25,6 +28,7 @@ typedef struct { ...@@ -25,6 +28,7 @@ typedef struct {
GtkToolItem *signals_go_to_first_button; GtkToolItem *signals_go_to_first_button;
GtkTreeSelection *selection; GtkTreeSelection *selection;
GtkTreePath *path_last;
/* Nb of messages received */ /* Nb of messages received */
guint nb_message_received; guint nb_message_received;
......
...@@ -5,12 +5,24 @@ ...@@ -5,12 +5,24 @@
#include "ui_menu_bar.h" #include "ui_menu_bar.h"
#include "ui_callbacks.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) int ui_menu_bar_create(GtkWidget *vbox)
{ {
GtkWidget *menubar; GtkWidget *menubar;
GtkWidget *filemenu, *helpmenu; GtkWidget *filemenu, *helpmenu;
GtkWidget *file; GtkWidget *file;
GtkWidget *help; GtkWidget *help;
GtkWidget *open_messages;
GtkWidget *save_messages;
GtkWidget *open_filters;
GtkWidget *save_filters;
GtkWidget *quit; GtkWidget *quit;
GtkWidget *about; GtkWidget *about;
...@@ -23,11 +35,19 @@ int ui_menu_bar_create(GtkWidget *vbox) ...@@ -23,11 +35,19 @@ int ui_menu_bar_create(GtkWidget *vbox)
filemenu = gtk_menu_new(); filemenu = gtk_menu_new();
file = gtk_menu_item_new_with_label("File"); 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"); quit = gtk_menu_item_new_with_label("Quit");
gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), filemenu); 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(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); gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), quit);
/* Create the Help submenu */ /* Create the Help submenu */
...@@ -44,6 +64,18 @@ int ui_menu_bar_create(GtkWidget *vbox) ...@@ -44,6 +64,18 @@ int ui_menu_bar_create(GtkWidget *vbox)
/* Add the menubar to the vbox */ /* Add the menubar to the vbox */
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 3); 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_signal_connect(G_OBJECT(quit), "activate",
G_CALLBACK(gtk_main_quit), NULL); G_CALLBACK(gtk_main_quit), NULL);
...@@ -70,6 +102,7 @@ int ui_toolbar_create(GtkWidget *vbox) ...@@ -70,6 +102,7 @@ int ui_toolbar_create(GtkWidget *vbox)
gtk_container_set_border_width(GTK_CONTAINER(toolbar), 2); 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 */ /* 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); 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) ...@@ -83,18 +116,55 @@ int ui_toolbar_create(GtkWidget *vbox)
g_signal_connect(G_OBJECT(ui_main_data.signals_clear_button), "clicked", g_signal_connect(G_OBJECT(ui_main_data.signals_clear_button), "clicked",
G_CALLBACK(ui_callback_signal_clear_list), NULL); G_CALLBACK(ui_callback_signal_clear_list), NULL);
} }
#endif
/* Button to open replay file */ /* Button to open replay file */
{ {
ui_main_data.open_replay_file = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN); 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), 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); 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_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 */ /* Button to go given signal number */
{ {
ui_main_data.signals_go_to_button = gtk_tool_button_new_from_stock(GTK_STOCK_INDEX); 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) ...@@ -108,6 +178,7 @@ int ui_toolbar_create(GtkWidget *vbox)
g_signal_connect(G_OBJECT(ui_main_data.signals_go_to_button), "clicked", g_signal_connect(G_OBJECT(ui_main_data.signals_go_to_button), "clicked",
G_CALLBACK(ui_callback_signal_go_to), NULL); G_CALLBACK(ui_callback_signal_go_to), NULL);
} }
#endif
/* Button to go to first signal in list */ /* Button to go to first signal in list */
{ {
......
#ifndef UI_MENU_BAR_H_ #ifndef UI_MENU_BAR_H_
#define 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_menu_bar_create(GtkWidget *vbox);
int ui_toolbar_create(GtkWidget *vbox); int ui_toolbar_create(GtkWidget *vbox);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "ui_interface.h" #include "ui_interface.h"
#include "ui_main_screen.h" #include "ui_main_screen.h"
#include "ui_menu_bar.h"
#include "ui_notifications.h" #include "ui_notifications.h"
#include "ui_callbacks.h" #include "ui_callbacks.h"
...@@ -33,14 +34,16 @@ int ui_enable_connect_button(void) ...@@ -33,14 +34,16 @@ int ui_enable_connect_button(void)
return RC_OK; return RC_OK;
} }
int ui_file_chooser(void) int ui_messages_open_file_chooser(void)
{ {
GtkWidget *filechooser; GtkWidget *filechooser;
int result = RC_OK; int result = RC_OK;
filechooser = gtk_file_chooser_dialog_new ("Select file", GTK_WINDOW (ui_main_data.window), 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_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
NULL);
/* Process the response */ /* Process the response */
if (gtk_dialog_run (GTK_DIALOG (filechooser)) == GTK_RESPONSE_ACCEPT) if (gtk_dialog_run (GTK_DIALOG (filechooser)) == GTK_RESPONSE_ACCEPT)
...@@ -50,14 +53,22 @@ int ui_file_chooser(void) ...@@ -50,14 +53,22 @@ int ui_file_chooser(void)
int read_data = 0; int read_data = 0;
void *input_data = NULL; void *input_data = NULL;
size_t input_data_length = 0; size_t input_data_length = 0;
int read_messages = 0;
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filechooser)); filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (filechooser));
source = open (filename, O_RDONLY); 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; itti_socket_header_t message_header;
ui_callback_signal_clear_list(NULL, NULL, NULL);
do do
{ {
read_data = read (source, &message_header, sizeof(itti_socket_header_t)); read_data = read (source, &message_header, sizeof(itti_socket_header_t));
...@@ -106,6 +117,7 @@ int ui_file_chooser(void) ...@@ -106,6 +117,7 @@ int ui_file_chooser(void)
buffer->message_number = itti_signal_header->message_number; buffer->message_number = itti_signal_header->message_number;
ui_signal_add_to_list (buffer, NULL); ui_signal_add_to_list (buffer, NULL);
read_messages ++;
break; break;
} }
...@@ -124,7 +136,13 @@ int ui_file_chooser(void) ...@@ -124,7 +136,13 @@ int ui_file_chooser(void)
} }
} while (read_data > 0); } 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); close (source);
} }
...@@ -137,6 +155,63 @@ int ui_file_chooser(void) ...@@ -137,6 +155,63 @@ int ui_file_chooser(void)
return result; 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) int ui_progress_bar_set_fraction(double fraction)
{ {
// /* If not exist instantiate */ // /* If not exist instantiate */
......
...@@ -5,7 +5,11 @@ int ui_disable_connect_button(void); ...@@ -5,7 +5,11 @@ int ui_disable_connect_button(void);
int ui_enable_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); int ui_progress_bar_set_fraction(double fraction);
......
...@@ -28,14 +28,20 @@ ui_tree_view_init_list(GtkWidget *list) ...@@ -28,14 +28,20 @@ ui_tree_view_init_list(GtkWidget *list)
column = gtk_tree_view_column_new_with_attributes( column = gtk_tree_view_column_new_with_attributes(
"Signal", renderer, "text", COL_SIGNAL, NULL); "Signal", renderer, "text", COL_SIGNAL, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(list), column); 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( column = gtk_tree_view_column_new_with_attributes(
"From", renderer, "text", COL_FROM_TASK, NULL); "From", renderer, "text", COL_FROM_TASK, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(list), column); 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( column = gtk_tree_view_column_new_with_attributes(
"To", renderer, "text", COL_TO_TASK, NULL); "To", renderer, "text", COL_TO_TASK, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(list), column); 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, store = gtk_list_store_new(NUM_COLS,
G_TYPE_STRING, G_TYPE_STRING,
...@@ -86,6 +92,9 @@ void ui_tree_view_destroy_list(GtkWidget *list) ...@@ -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))); store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
gtk_list_store_clear(store); 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) int ui_tree_view_create(GtkWidget *window, GtkWidget *vbox)
...@@ -112,6 +121,7 @@ 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_main_data.signalslist);
ui_tree_view_init_list(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_widget_set_size_request(GTK_WIDGET(scrolled_window), 500, -1);
gtk_box_pack_start(GTK_BOX(hbox), scrolled_window, FALSE, FALSE, 0); 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 ...@@ -141,13 +151,21 @@ int ui_tree_view_new_signal_ind(const uint32_t message_number, const char *signa
return RC_OK; 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]; gchar indice[10];
sprintf(indice, "%d", row); sprintf(indice, "%d", row);
path = gtk_tree_path_new_from_string(indice); path_row = gtk_tree_path_new_from_string(indice);
gtk_tree_view_set_cursor(GTK_TREE_VIEW(ui_main_data.signalslist), path, NULL, FALSE); /* 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;
}
} }
#ifndef UI_TREE_VIEW_H_ #ifndef UI_TREE_VIEW_H_
#define UI_TREE_VIEW_H_ #define UI_TREE_VIEW_H_
enum typedef enum
{ {
COL_MSG_NUM = 0, COL_MSG_NUM = 0,
COL_SIGNAL, COL_SIGNAL,
...@@ -9,7 +9,7 @@ enum ...@@ -9,7 +9,7 @@ enum
COL_TO_TASK, COL_TO_TASK,
COL_BUFFER, COL_BUFFER,
NUM_COLS NUM_COLS
}; } col_type_e;
int ui_tree_view_create(GtkWidget *window, GtkWidget *vbox); 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 ...@@ -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_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_ */ #endif /* UI_TREE_VIEW_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment