/*************************************************************************** * Copyright (C) 04/2008 by Olaf Rempel * * razzor@kopf-tisch.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; version 2 of the License * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include "tdc_store.h" #include "tdc_parser.h" #include "tdc_proto.h" #include "gui_graph_tab.h" enum { COL_ID = 0, /* UINT */ COL_GRAPH, /* BOOLEAN */ COL_VALUE, /* POINTER to var */ COL_VALUE_EDIT, /* BOOLEAN */ COL_TYPE, /* STRING */ COL_NAME, /* STRING */ }; static GtkListStore *list_store; static int viewmode = 0; static int sortmode = GTK_SORT_ASCENDING; static struct tdc_var *current_edited_var; 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); gboolean toggle; struct tdc_var *var; gtk_tree_model_get(GTK_TREE_MODEL(user_data), &it, COL_GRAPH, &toggle, COL_VALUE, &var, -1); if (var->flags & TDC_GUI_GRAPH) { var->flags &= ~TDC_GUI_GRAPH; if (var->privdata_graphtab != NULL) gui_graphtab_remove_var(var); } else { if (var->privdata_graphtab == NULL) /* bailout if no new graph allowed */ if (gui_graphtab_add_var(var) < 0) return; var->flags |= TDC_GUI_GRAPH; } // FIXME: assuming board 1 tdcstore_graph_refresh(1, -1); gtk_list_store_set(GTK_LIST_STORE(user_data), &it, COL_GRAPH, !toggle, -1); } 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 value_edit_started(GtkCellRenderer *renderer, GtkCellEditable *editable, gchar *path, gpointer user_data) { GtkTreeIter it; gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(list_store), &it, path); gtk_tree_model_get(GTK_TREE_MODEL(list_store), &it, COL_VALUE, ¤t_edited_var, -1); } static void value_edit_canceled(GtkCellRenderer *renderer, gpointer user_data) { current_edited_var = NULL; } static void value_edit_done(GtkCellRendererText *cell, gchar *path, gchar *text, gpointer user_data) { GtkTreeIter it; gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(list_store), &it, path); struct tdc_var *var; gtk_tree_model_get(GTK_TREE_MODEL(list_store), &it, COL_VALUE, &var, -1); if (tdcvar_parse_value(var, text) >= 0) { // FIXME: assuming board 1 tdcparser_send_setvalue(1, var->id); } current_edited_var = NULL; } 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 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]; tdcvar_get_value(var, buf, sizeof(buf), viewmode); g_object_set(cell, "text", buf, NULL); } gint gui_vartab_init(GtkNotebook *notebook) { list_store = gtk_list_store_new(6, G_TYPE_UINT, 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; col = gtk_tree_view_column_new(); gtk_tree_view_column_set_title(col, "Graph"); gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); 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, 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(); g_signal_connect(renderer, "edited", (GCallback)value_edit_done, NULL); g_signal_connect(renderer, "editing-started", (GCallback)value_edit_started, NULL); g_signal_connect(renderer, "editing-canceled", (GCallback)value_edit_canceled, NULL); 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, 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, FALSE); gtk_tree_view_column_add_attribute(col, renderer, "text", COL_NAME); GtkWidget *scrollbar = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbar), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(scrollbar), view); GtkWidget *label = gtk_label_new(" Variables "); return gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrollbar, label); } void gui_vartab_add_var(struct tdc_var *var) { GtkTreeIter it; gtk_list_store_append(list_store, &it); char typestr[32]; tdcvar_get_type(var, typestr, sizeof(typestr)); gtk_list_store_set(list_store, &it, COL_ID, var->id, COL_GRAPH, FALSE, COL_VALUE, var, COL_VALUE_EDIT, !(var->flags & TDC_READONLY), COL_TYPE, typestr, COL_NAME, var->name, -1); var->privdata_vartab = gtk_tree_iter_copy(&it); } int gui_vartab_update_var(struct tdc_var *var) { // TODO: update even in graph mode every xxx ms if (var == current_edited_var || (var->flags & TDC_GUI_GRAPH)) return 0; /* do a dummy write to update cells */ GtkTreeIter *it = (GtkTreeIter *)var->privdata_vartab; gtk_list_store_set(list_store, it, -1); return 0; } void gui_vartab_remove_var(struct tdc_var *var) { GtkTreeIter *it = (GtkTreeIter *)var->privdata_vartab; gtk_list_store_remove(list_store, it); gtk_tree_iter_free(it); var->privdata_vartab = NULL; }