gtdc/gui_variable_tab.c
2008-04-18 21:04:25 +02:00

284 lines
8.8 KiB
C

/***************************************************************************
* 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 <gtk/gtk.h>
#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, &current_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;
}