diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/control.c | 162 | ||||
| -rw-r--r-- | test/control.glade | 68 | 
2 files changed, 168 insertions, 62 deletions
| 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 <glib/gprintf.h>  #include <gtk/gtk.h>  #include <gdk/gdk.h> +#include <gdk/gdkkeysyms.h>  #include <string.h>  #include <time.h>  #include <unistd.h> +#include <errno.h>  #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));  } diff --git a/test/control.glade b/test/control.glade index eeeeaaf..bee9323 100644 --- a/test/control.glade +++ b/test/control.glade @@ -2,28 +2,24 @@  <interface>    <requires lib="gtk+" version="2.20"/>    <!-- interface-naming-policy project-wide --> -  <object class="GtkTreeStore" id="cameraproperties"> +  <object class="GtkListStore" id="camera-types">      <columns> -      <!-- column-name PropertyName --> -      <column type="gchararray"/> -      <!-- column-name PropertyValue --> -      <column type="gchararray"/> -      <!-- column-name PropertyUnit --> +      <!-- column-name name -->        <column type="gchararray"/> -      <!-- column-name PropertyUCA --> -      <column type="guint"/>      </columns>    </object> -  <object class="GtkListStore" id="camera-types"> +  <object class="GtkListStore" id="camera-properties">      <columns> -      <!-- column-name name --> +      <!-- column-name PropertyName --> +      <column type="gchararray"/> +      <!-- column-name PropertyValue -->        <column type="gchararray"/>      </columns>    </object>    <object class="GtkWindow" id="window">      <property name="title" translatable="yes">Camera Control</property> -    <property name="default_width">800</property> -    <property name="default_height">600</property> +    <property name="default_width">1024</property> +    <property name="default_height">768</property>      <signal name="delete_event" handler="on_delete_event"/>      <child>        <object class="GtkVBox" id="vbox1"> @@ -198,10 +194,10 @@                      <property name="hscrollbar_policy">automatic</property>                      <property name="vscrollbar_policy">automatic</property>                      <child> -                      <object class="GtkTreeView" id="treeview"> +                      <object class="GtkTreeView" id="treeview-properties">                          <property name="visible">True</property>                          <property name="can_focus">True</property> -                        <property name="model">cameraproperties</property> +                        <property name="model">camera-properties</property>                          <property name="headers_clickable">False</property>                          <property name="search_column">0</property>                          <child> @@ -226,17 +222,6 @@                              </child>                            </object>                          </child> -                        <child> -                          <object class="GtkTreeViewColumn" id="unitcolumn"> -                            <property name="title">Unit</property> -                            <child> -                              <object class="GtkCellRendererText" id="unitcell"/> -                              <attributes> -                                <attribute name="text">2</attribute> -                              </attributes> -                            </child> -                          </object> -                        </child>                        </object>                      </child>                    </object> @@ -314,6 +299,7 @@      <property name="page_increment">10</property>    </object>    <object class="GtkWindow" id="choice-window"> +    <property name="border_width">6</property>      <child>        <object class="GtkVBox" id="vbox3">          <property name="visible">True</property> @@ -325,7 +311,7 @@              <property name="model">camera-types</property>              <child>                <object class="GtkTreeViewColumn" id="treeviewcolumn1"> -                <property name="title">column</property> +                <property name="title">Choose camera</property>                  <child>                    <object class="GtkCellRendererText" id="cellrenderertext1"/>                    <attributes> @@ -383,34 +369,4 @@        </object>      </child>    </object> -  <object class="GtkDialog" id="dialog1"> -    <property name="border_width">5</property> -    <property name="type_hint">normal</property> -    <child internal-child="vbox"> -      <object class="GtkVBox" id="dialog-vbox2"> -        <property name="visible">True</property> -        <property name="spacing">2</property> -        <child> -          <placeholder/> -        </child> -        <child internal-child="action_area"> -          <object class="GtkHButtonBox" id="dialog-action_area2"> -            <property name="visible">True</property> -            <property name="layout_style">end</property> -            <child> -              <placeholder/> -            </child> -            <child> -              <placeholder/> -            </child> -          </object> -          <packing> -            <property name="expand">False</property> -            <property name="pack_type">end</property> -            <property name="position">0</property> -          </packing> -        </child> -      </object> -    </child> -  </object>  </interface> | 
