From 0b5838e40bed5b175f7703b788eae361e2ca8177 Mon Sep 17 00:00:00 2001 From: Matthias Vogelgesang Date: Mon, 16 Apr 2012 17:00:00 +0200 Subject: Implement property editing --- test/control.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 156 insertions(+), 6 deletions(-) (limited to 'test/control.c') diff --git a/test/control.c b/test/control.c index 0614071..a5a4e22 100644 --- a/test/control.c +++ b/test/control.c @@ -18,9 +18,11 @@ #include #include #include +#include #include #include #include +#include #include "uca-camera.h" @@ -31,6 +33,7 @@ typedef struct { guchar *buffer, *pixels; GdkPixbuf *pixbuf; GtkWidget *image; + GtkTreeModel *property_model; UcaCamera *camera; GtkStatusbar *statusbar; @@ -51,8 +54,6 @@ typedef struct { enum { COLUMN_NAME = 0, COLUMN_VALUE, - COLUMN_UNIT, - COLUMN_UCA_ID, NUM_COLUMNS }; @@ -145,7 +146,7 @@ void on_adjustment_scale_value_changed(GtkAdjustment* adjustment, gpointer user_ data->scale = gtk_adjustment_get_value(adjustment); } -void on_toolbutton_run_clicked(GtkWidget *widget, gpointer args) +static void on_toolbutton_run_clicked(GtkWidget *widget, gpointer args) { ThreadData *data = (ThreadData *) args; @@ -168,7 +169,7 @@ void on_toolbutton_run_clicked(GtkWidget *widget, gpointer args) } } -void on_toolbutton_stop_clicked(GtkWidget *widget, gpointer args) +static void on_toolbutton_stop_clicked(GtkWidget *widget, gpointer args) { ThreadData *data = (ThreadData *) args; data->running = FALSE; @@ -176,7 +177,7 @@ void on_toolbutton_stop_clicked(GtkWidget *widget, gpointer args) uca_camera_stop_recording(data->camera, NULL); } -void on_toolbutton_record_clicked(GtkWidget *widget, gpointer args) +static void on_toolbutton_record_clicked(GtkWidget *widget, gpointer args) { ThreadData *data = (ThreadData *) args; data->timestamp = (int) time(0); @@ -187,7 +188,7 @@ void on_toolbutton_record_clicked(GtkWidget *widget, gpointer args) if (data->running != TRUE) { data->running = TRUE; - uca_camera_start_recording(data->cam, &error); + uca_camera_start_recording(data->camera, &error); if (!g_thread_create(grab_thread, data, FALSE, &error)) { g_printerr("Failed to create thread: %s\n", error->message); @@ -195,6 +196,142 @@ void on_toolbutton_record_clicked(GtkWidget *widget, gpointer args) } } +static void on_valuecell_edited(GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer data) +{ + ThreadData *td = (ThreadData *) data; + GtkTreePath *tree_path = gtk_tree_path_new_from_string(path); + GtkTreeIter iter; + + if (gtk_tree_model_get_iter(td->property_model, &iter, tree_path)) { + gchar *propname; + GValue dest_value = {0}, src_value = {0}; + g_value_init(&src_value, G_TYPE_STRING); + g_value_set_string(&src_value, new_text); + + gtk_tree_model_get(td->property_model, &iter, COLUMN_NAME, &propname, -1); + + GParamSpec *spec = g_object_class_find_property(G_OBJECT_GET_CLASS(td->camera), propname); + g_value_init(&dest_value, spec->value_type); + errno = 0; + + if (g_value_transform(&src_value, &dest_value) && (errno != EINVAL)) { + g_object_set_property(G_OBJECT(td->camera), propname, &dest_value); + g_object_get_property(G_OBJECT(td->camera), propname, &src_value); + gtk_list_store_set(GTK_LIST_STORE(td->property_model), &iter, COLUMN_VALUE, g_value_get_string(&src_value), -1); + } + else + g_print("Couldn't transform %s\n", g_value_get_string(&src_value)); + } +} + +static void value_cell_data_func(GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, gpointer data) +{ + UcaCamera *camera = UCA_CAMERA(data); + gchar *propname; + gtk_tree_model_get(model, iter, COLUMN_NAME, &propname, -1); + GParamSpec *spec = g_object_class_find_property(G_OBJECT_GET_CLASS(camera), propname); + + if (spec->flags & G_PARAM_WRITABLE) { + g_object_set(cell, + "mode", GTK_CELL_RENDERER_MODE_EDITABLE, + "editable", TRUE, + "style", PANGO_STYLE_NORMAL, + "foreground", "#000000", + NULL); + } + else { + g_object_set(cell, + "mode", GTK_CELL_RENDERER_MODE_INERT, + "editable", FALSE, + "foreground", "#aaaaaa", + NULL); + } + + g_free(propname); +} + +static void populate_property_list(GtkBuilder *builder, UcaCamera *camera) +{ + GtkTreeViewColumn *value_column = GTK_TREE_VIEW_COLUMN(gtk_builder_get_object(builder, "valuecolumn")); + GtkCellRendererText *value_renderer = GTK_CELL_RENDERER_TEXT(gtk_builder_get_object(builder, "valuecell")); + GtkListStore *list_store = GTK_LIST_STORE(gtk_builder_get_object(builder, "camera-properties")); + GtkTreeIter iter; + + gtk_tree_view_column_set_cell_data_func(value_column, GTK_CELL_RENDERER(value_renderer), value_cell_data_func, camera, NULL); + + GObjectClass *oclass = G_OBJECT_GET_CLASS(camera); + guint num_specs = 0; + GParamSpec **specs = g_object_class_list_properties(oclass, &num_specs); + GValue dest_value = {0}, src_value = {0}; + g_value_init(&dest_value, G_TYPE_STRING); + + for (guint i = 0; i < num_specs; i++) { + gtk_list_store_append(list_store, &iter); + gtk_list_store_set(list_store, &iter, 0, specs[i]->name, -1); + + if (specs[i]->flags & G_PARAM_READABLE) { + g_value_init(&src_value, specs[i]->value_type); + g_object_get_property(G_OBJECT(camera), specs[i]->name, &src_value); + if (g_value_transform(&src_value, &dest_value)) + gtk_list_store_set(list_store, &iter, 1, g_value_get_string(&dest_value), -1); + g_value_unset(&src_value); + } + } + + g_free(specs); +} + +static void transform_string_to_boolean(const GValue *src_value, GValue *dest_value) +{ + const gchar *str = g_value_get_string(src_value); + + if (g_ascii_strncasecmp(str, "TRUE", 4) == 0) + g_value_set_boolean(dest_value, TRUE); + else if (g_ascii_strncasecmp(str, "FALSE", 4) == 0) + g_value_set_boolean(dest_value, FALSE); +} + +static void transform_string_to_uint(const GValue *src_value, GValue *dest_value) +{ + const gchar *str = g_value_get_string(src_value); + gchar *endptr = NULL; + guint64 result = g_ascii_strtoull(str, &endptr, 10); + if (endptr != str) + g_value_set_uint(dest_value, result); + else + errno = EINVAL; +} + +static void transform_string_to_double(const GValue *src_value, GValue *dest_value) +{ + const gchar *str = g_value_get_string(src_value); + gchar *endptr = NULL; + gdouble result = g_ascii_strtod(str, &endptr); + if (endptr != str) + g_value_set_double(dest_value, result); + else + errno = EINVAL; +} + +static void transform_string_to_float(const GValue *src_value, GValue *dest_value) +{ + const gchar *str = g_value_get_string(src_value); + gchar *endptr = NULL; + gdouble result = g_ascii_strtod(str, &endptr); + if (endptr != str) + g_value_set_float(dest_value, (gfloat) result); + else + errno = EINVAL; +} + +static void register_transform_funcs(void) +{ + g_value_register_transform_func(G_TYPE_STRING, G_TYPE_BOOLEAN, &transform_string_to_boolean); + g_value_register_transform_func(G_TYPE_STRING, G_TYPE_UINT, &transform_string_to_uint); + g_value_register_transform_func(G_TYPE_STRING, G_TYPE_DOUBLE, &transform_string_to_double); + g_value_register_transform_func(G_TYPE_STRING, G_TYPE_FLOAT, &transform_string_to_float); +} + static void create_main_window(GtkBuilder *builder, const gchar* camera_name) { static ThreadData td; @@ -219,6 +356,9 @@ static void create_main_window(GtkBuilder *builder, const gchar* camera_name) GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, td.width, td.height); gtk_image_set_from_pixbuf(GTK_IMAGE(image), pixbuf); + register_transform_funcs(); + populate_property_list(builder, camera); + td.pixel_size = bits_per_sample == 16 ? 2 : 1; td.image = image; td.pixbuf = pixbuf; @@ -230,6 +370,7 @@ static void create_main_window(GtkBuilder *builder, const gchar* camera_name) td.statusbar_context_id = gtk_statusbar_get_context_id(td.statusbar, "Recording Information"); td.store = FALSE; td.camera = camera; + td.property_model = GTK_TREE_MODEL(gtk_builder_get_object(builder, "camera-properties")); g_signal_connect(window, "destroy", G_CALLBACK(on_destroy), &td); g_signal_connect(gtk_builder_get_object(builder, "toolbutton_run"), @@ -238,6 +379,8 @@ static void create_main_window(GtkBuilder *builder, const gchar* camera_name) "clicked", G_CALLBACK(on_toolbutton_stop_clicked), &td); g_signal_connect(gtk_builder_get_object(builder, "toolbutton_record"), "clicked", G_CALLBACK(on_toolbutton_record_clicked), &td); + g_signal_connect(gtk_builder_get_object(builder, "valuecell"), + "edited", G_CALLBACK(on_valuecell_edited), &td); gtk_widget_show(image); gtk_widget_show(window); @@ -268,6 +411,12 @@ static void on_button_proceed_clicked(GtkWidget *widget, gpointer data) g_list_free(selected_rows); } +static void on_treeview_keypress(GtkWidget *widget, GdkEventKey *event, gpointer data) +{ + if (event->keyval == GDK_KEY_Return) + gtk_widget_grab_focus(GTK_WIDGET(data)); +} + static void create_choice_window(GtkBuilder *builder) { gchar **camera_types = uca_camera_get_types(); @@ -293,6 +442,7 @@ static void create_choice_window(GtkBuilder *builder) g_strfreev(camera_types); g_signal_connect(proceed_button, "clicked", G_CALLBACK(on_button_proceed_clicked), builder); + g_signal_connect(treeview, "key-press-event", G_CALLBACK(on_treeview_keypress), proceed_button); gtk_widget_show_all(GTK_WIDGET(choice_window)); } -- cgit v1.2.3