diff --git a/tdc_store.c b/tdc_store.c index 111096d..1a67239 100644 --- a/tdc_store.c +++ b/tdc_store.c @@ -15,6 +15,151 @@ static struct tdc_var * var_map[256]; static GByteArray *stream; +void get_varvalue(struct tdc_var *var, char *buf, int size, int viewmode) +{ + switch ((var->flags & TDC_TYPEMASK) | ((viewmode & 0x01) << 8)) { + case TDC_UNSIGNED: + switch (var->flags & TDC_SIZEMASK) { + case 1: snprintf(buf, size, "%u", var->data_uint8); + break; + + case 2: snprintf(buf, size, "%u", var->data_uint16); + break; + + case 4: snprintf(buf, size, "%u", var->data_uint32); + break; + + case 8: snprintf(buf, size, "%llu", var->data_uint64); + break; + + default: + snprintf(buf, size, "???"); + break; + } + break; + + case TDC_UNSIGNED | 0x100: + switch (var->flags & TDC_SIZEMASK) { + case 1: snprintf(buf, size, "0x%02x", var->data_uint8); + break; + + case 2: snprintf(buf, size, "0x%04x", var->data_uint16); + break; + + case 4: snprintf(buf, size, "0x%08x", var->data_uint32); + break; + + case 8: snprintf(buf, size, "0x%16llx", var->data_uint64); + break; + + default: + snprintf(buf, size, "???"); + break; + } + break; + + case TDC_SIGNED: + switch (var->flags & TDC_SIZEMASK) { + case 1: snprintf(buf, size, "%d", (int8_t)var->data_uint8); + break; + + case 2: snprintf(buf, size, "%d", (int16_t)var->data_uint16); + break; + + case 4: snprintf(buf, size, "%d", (int32_t)var->data_uint32); + break; + + case 8: snprintf(buf, size, "%lld", (int64_t)var->data_uint64); + break; + + default: + snprintf(buf, size, "???"); + break; + } + break; + + case TDC_SIGNED | 0x100: + switch (var->flags & TDC_SIZEMASK) { + case 1: snprintf(buf, size, "0x%02x", (int8_t)var->data_uint8); + break; + + case 2: snprintf(buf, size, "0x%04x", (int16_t)var->data_uint16); + break; + + case 4: snprintf(buf, size, "0x%08x", (int32_t)var->data_uint32); + break; + + case 8: snprintf(buf, size, "0x%16llx", (int64_t)var->data_uint64); + break; + + default: + snprintf(buf, size, "???"); + break; + } + break; + + case TDC_FP: + case TDC_FP | 0x100: + switch (var->flags & TDC_SIZEMASK) { + case sizeof(float): + snprintf(buf, size, "%.8f", var->data_float); + break; + + case sizeof(double): + snprintf(buf, size, "%.12f", var->data_double); + break; + + default: + snprintf(buf, size, "???"); + break; + } + break; + + case TDC_FIXED: + case TDC_FIXED | 0x100: + snprintf(buf, size, "???"); + break; + } +} + +void get_vartype(struct tdc_var *var, char *buf, int size) +{ + int pos; + int width = (var->flags & TDC_SIZEMASK); + + switch (var->flags & TDC_TYPEMASK) { + case TDC_UNSIGNED: + pos = snprintf(buf, size, "uint%d_t", width * 8); + break; + + case TDC_SIGNED: + pos = snprintf(buf, size, "int%d_t", width * 8); + break; + + case TDC_FP: + if (width == sizeof(float)) + pos = snprintf(buf, size, "float"); + + else if (size == sizeof(double)) + pos = snprintf(buf, size, "double"); + + else + pos = snprintf(buf, size, "fp%d_t", width * 8); + break; + + case TDC_FIXED: + pos = snprintf(buf, size, "fix%d_t", width * 8); + break; + + default: + pos = snprintf(buf, size, "???"); + break; + } + + if (var->flags & TDC_READONLY) + pos = snprintf(buf + pos, size - pos, " (ro)"); +} + static void destroy_var(int id) { g_free(var_map[id]); diff --git a/tdc_store.h b/tdc_store.h index 5b893de..6eb7e5c 100644 --- a/tdc_store.h +++ b/tdc_store.h @@ -17,6 +17,9 @@ struct tdc_var { char name[0]; }; +void get_varvalue(struct tdc_var *var, char *buf, int size, int viewmode); +void get_vartype(struct tdc_var *var, char *buf, int size); + int tdc_parse_data(int fd); void tdc_flush_vars(void); void tdc_send_hello(int fd); diff --git a/variable_tab.c b/variable_tab.c index 11b53b8..688f748 100644 --- a/variable_tab.c +++ b/variable_tab.c @@ -6,7 +6,7 @@ enum { COL_ID = 0, /* UINT */ COL_GRAPH, /* BOOLEAN */ - COL_VALUE, /* PTR?, with cell_data_func */ + COL_VALUE, /* POINTER to var */ COL_VALUE_EDIT, /* BOOLEAN */ COL_TYPE, /* STRING */ COL_NAME, /* STRING */ @@ -14,7 +14,9 @@ enum { static GtkListStore *list_store; -static void cell_graph_toggle(GtkCellRendererToggle *cell, gchar *path_string, gpointer user_data) +static void cell_graph_toggle(GtkCellRendererToggle *cell, + gchar *path_string, + gpointer user_data) { GtkTreeIter it; gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(user_data), &it, path_string); @@ -30,20 +32,95 @@ static void cell_graph_toggle(GtkCellRendererToggle *cell, gchar *path_string, g -1); } -static void cell_value_edited(GtkCellRendererText *cell, gchar *path_string, gchar *new_text, gpointer user_data) +static gboolean header_toggle_update(GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) +{ + gtk_tree_model_row_changed(model, path, iter); + return FALSE; +} + +static void cell_value_edited(GtkCellRendererText *cell, + gchar *path_string, + gchar *new_text, + gpointer user_data) { printf("cell_value_edited\n"); } +static gint sort_by_name_func(GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer userdata) +{ + gint ret = 0; + + gchar *name1, *name2; + gtk_tree_model_get(model, a, COL_NAME, &name1, -1); + gtk_tree_model_get(model, b, COL_NAME, &name2, -1); + + if (name1 == NULL || name2 == NULL) { + if (name1 != NULL || name2 != NULL) + ret = (name1 == NULL) ? -1 : 1; + + } else { + ret = g_utf8_collate(name1, name2); + } + + g_free(name1); + g_free(name2); + return ret; +} + +static int viewmode = 0; +static int sortmode = GTK_SORT_ASCENDING; + +static void header_name_toggle(GtkTreeViewColumn *treeviewcolumn, + gpointer user_data) +{ + sortmode = (sortmode == GTK_SORT_ASCENDING) ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING; + + GtkTreeSortable *sortable = GTK_TREE_SORTABLE(list_store); + gtk_tree_sortable_set_sort_func(sortable, COL_NAME, sort_by_name_func, NULL, NULL); + gtk_tree_sortable_set_sort_column_id(sortable, COL_NAME, sortmode); +} + +static void header_value_toggle(GtkTreeViewColumn *treeviewcolumn, + gpointer user_data) +{ + viewmode = (viewmode +1) & 0x01; + gtk_tree_model_foreach(GTK_TREE_MODEL(list_store), header_toggle_update, NULL); +} + +static void cell_value_func(GtkTreeViewColumn *column, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer data) +{ + struct tdc_var *var; + gtk_tree_model_get(model, iter, COL_VALUE, &var, -1); + + char buf[32]; + get_varvalue(var, buf, sizeof(buf), viewmode); + g_object_set(cell, "text", buf, NULL); +} + gint variable_tab_init(GtkNotebook *notebook) { list_store = gtk_list_store_new(6, G_TYPE_UINT, G_TYPE_BOOLEAN, - G_TYPE_STRING, G_TYPE_BOOLEAN, + G_TYPE_POINTER, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING); + GtkTreeSortable *sortable = GTK_TREE_SORTABLE(list_store); + gtk_tree_sortable_set_sort_func(sortable, COL_NAME, sort_by_name_func, NULL, NULL); + gtk_tree_sortable_set_sort_column_id(sortable, COL_NAME, sortmode); + GtkWidget *view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store)); g_object_unref(list_store); + gtk_tree_view_set_grid_lines(GTK_TREE_VIEW(view), GTK_TREE_VIEW_GRID_LINES_VERTICAL); GtkTreeViewColumn *col; GtkCellRenderer *renderer; @@ -54,34 +131,34 @@ gint variable_tab_init(GtkNotebook *notebook) renderer = gtk_cell_renderer_toggle_new(); g_object_set(renderer, "activatable", TRUE, NULL); g_signal_connect(renderer, "toggled", (GCallback)cell_graph_toggle, list_store); - gtk_tree_view_column_pack_start(col, renderer, TRUE); + gtk_tree_view_column_pack_start(col, renderer, FALSE); gtk_tree_view_column_add_attribute(col, renderer, "active", COL_GRAPH); - col = gtk_tree_view_column_new(); gtk_tree_view_column_set_title(col, "Value"); gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); + g_object_set(col, "clickable", TRUE, NULL); + g_signal_connect(col, "clicked", (GCallback)header_value_toggle, NULL); renderer = gtk_cell_renderer_text_new(); -// gtk_tree_view_column_set_cell_data_func(col, renderer, cell_value_func, NULL, NULL); g_signal_connect(renderer, "edited", (GCallback)cell_value_edited, NULL); - gtk_tree_view_column_pack_start(col, renderer, TRUE); - gtk_tree_view_column_add_attribute(col, renderer, "text", COL_VALUE); + gtk_tree_view_column_pack_start(col, renderer, FALSE); gtk_tree_view_column_add_attribute(col, renderer, "editable", COL_VALUE_EDIT); - + gtk_tree_view_column_set_cell_data_func(col, renderer, cell_value_func, NULL, NULL); col = gtk_tree_view_column_new(); gtk_tree_view_column_set_title(col, "Type"); gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_column_pack_start(col, renderer, TRUE); + gtk_tree_view_column_pack_start(col, renderer, FALSE); gtk_tree_view_column_add_attribute(col, renderer, "text", COL_TYPE); - col = gtk_tree_view_column_new(); gtk_tree_view_column_set_title(col, "Name"); gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); + g_object_set(col, "clickable", TRUE, NULL); + g_signal_connect(col, "clicked", (GCallback)header_name_toggle, NULL); renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_column_pack_start(col, renderer, TRUE); + gtk_tree_view_column_pack_start(col, renderer, FALSE); gtk_tree_view_column_add_attribute(col, renderer, "text", COL_NAME); GtkWidget *scrollbar = gtk_scrolled_window_new(NULL, NULL); @@ -97,39 +174,13 @@ void vartab_add_var(struct tdc_var *var) GtkTreeIter it; gtk_list_store_append(list_store, &it); - char typestr[16]; - - int size = (var->flags & TDC_SIZEMASK); - - switch (var->flags & TDC_TYPEMASK) { - case TDC_UNSIGNED: - snprintf(typestr, sizeof(typestr), "uint%d_t", size * 8); - break; - - case TDC_SIGNED: - snprintf(typestr, sizeof(typestr), "int%d_t", size * 8); - break; - - case TDC_FP: - if (size == sizeof(float)) - snprintf(typestr, sizeof(typestr), "float"); - - else if (size == sizeof(double)) - snprintf(typestr, sizeof(typestr), "double"); - - else - snprintf(typestr, sizeof(typestr), "float(%d)", size * 8); - break; - - case TDC_FIXED: - snprintf(typestr, sizeof(typestr), "fixed(%d)", size * 8); - break; - } + char typestr[32]; + get_vartype(var, typestr, sizeof(typestr)); gtk_list_store_set(list_store, &it, COL_ID, var->id, COL_GRAPH, FALSE, - COL_VALUE, "none", + COL_VALUE, var, COL_VALUE_EDIT, !(var->flags & TDC_READONLY), COL_TYPE, typestr, COL_NAME, var->name,