unicapgtk_property_dialog.c
Upload User: shyika
Upload Date: 2017-11-25
Package Size: 1227k
Code Size: 19k
Category:

Video Capture

Development Platform:

Unix_Linux

  1. /* unicap
  2.  *
  3.  * Copyright (C) 2004 Arne Caspari ( arne_caspari@users.sourceforge.net )
  4.  *
  5.   This program is free software; you can redistribute it and/or modify
  6.   it under the terms of the GNU General Public License as published by
  7.   the Free Software Foundation; either version 2 of the License, or
  8.   (at your option) any later version.
  9.   This program is distributed in the hope that it will be useful,
  10.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.   GNU General Public License for more details.
  13.   You should have received a copy of the GNU General Public License
  14.   along with this program; if not, write to the Free Software
  15.   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  16.  */
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <gtk/gtk.h>
  21. #include <glib/gi18n.h>
  22. #include <glib/gstdio.h>
  23. #include <libintl.h>
  24. #include "config.h"
  25. #include "unicapgtk.h"
  26. #include "unicapgtk_property_dialog.h"
  27. #include "unicapgtk_device_property.h"
  28. #if UNICAPGTK_DEBUG
  29. #define DEBUG
  30. #endif
  31. #include "debug.h"
  32. enum
  33. {
  34.    PROP_0 = 0,
  35.    PROP_UPDATE_INTERVAL
  36. };
  37. enum {
  38.    UNICAPGTK_PROPERTY_DIALOG_CHANGED_SIGNAL,
  39.    LAST_SIGNAL
  40. };
  41. struct ppty_relation
  42. {
  43.       gchar identifier[128];
  44.       GtkWidget *widget;
  45. };
  46. static void unicapgtk_property_dialog_class_init          (UnicapgtkPropertyDialogClass *klass);
  47. static void unicapgtk_property_dialog_init                (UnicapgtkPropertyDialog      *ugtk);
  48. static void unicapgtk_property_dialog_finalize            (GObject                      *object);
  49. static void unicapgtk_property_dialog_destroy             (GtkObject                    *object);
  50. static void unicapgtk_property_dialog_set_property        ( GObject       *object, 
  51.     guint          property_id, 
  52.     const GValue  *value, 
  53.     GParamSpec    *pspec );
  54. static void unicapgtk_property_dialog_get_property        ( GObject       *object, 
  55.     guint          property_id, 
  56.     GValue        *value, 
  57.     GParamSpec    *pspec );
  58. static gboolean property_update_timeout_cb( UnicapgtkPropertyDialog *ugtk );
  59. static void update_lock_destroy_cb( gpointer _id );
  60. static gboolean save_device_defaults( UnicapgtkPropertyDialog *ugtk, gboolean overwrite );
  61. static void load_device_defaults( UnicapgtkPropertyDialog *ugtk );
  62. /* static guint unicapgtk_property_dialog_signals[LAST_SIGNAL] = { 0 }; */
  63. G_DEFINE_TYPE( UnicapgtkPropertyDialog, unicapgtk_property_dialog, GTK_TYPE_DIALOG );
  64. static void unicapgtk_property_dialog_class_init( UnicapgtkPropertyDialogClass *klass )
  65. {
  66.    GObjectClass *object_class = G_OBJECT_CLASS( klass );
  67.    GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS( klass );
  68.    unicapgtk_initialize();
  69.    object_class->finalize = unicapgtk_property_dialog_finalize;
  70.    gtk_object_class->destroy = unicapgtk_property_dialog_destroy;
  71.    object_class->set_property = unicapgtk_property_dialog_set_property;
  72.    object_class->get_property = unicapgtk_property_dialog_get_property;
  73. /*    unicapgtk_property_dialog_signals[UNICAPGTK_PROPERTY_DIALOG_CHANGED_SIGNAL] =  */
  74. /*       g_signal_new( "unicapgtk_property_dialog_changed", */
  75. /*      G_TYPE_FROM_CLASS(klass), */
  76. /*      G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, */
  77. /*      G_STRUCT_OFFSET(UnicapgtkPropertyDialogClass, unicapgtk_property_dialog), */
  78. /*      NULL,  */
  79. /*      NULL,                 */
  80. /*      g_cclosure_marshal_VOID__POINTER, */
  81. /*      G_TYPE_NONE, 1,  */
  82. /*      G_TYPE_POINTER ); */
  83.    g_object_class_install_property (object_class,
  84.     PROP_UPDATE_INTERVAL,
  85.     g_param_spec_int ("update-interval",
  86.       NULL, NULL,
  87.       0, 99999,
  88.       100,
  89.       G_PARAM_READWRITE));
  90. }
  91. static void unicapgtk_property_dialog_set_property( GObject *object, 
  92.     guint property_id, 
  93.     const GValue *value, 
  94.     GParamSpec *pspec )
  95. {
  96.    UnicapgtkPropertyDialog *ugtk = UNICAPGTK_PROPERTY_DIALOG( object );
  97.    gint interval;
  98.    switch( property_id )
  99.    {
  100.       case PROP_UPDATE_INTERVAL:
  101.  g_source_remove( ugtk->update_timeout_id );
  102.  interval = g_value_get_int( value );
  103.  if( interval > 0 )
  104.  {
  105.     g_timeout_add( interval, (GSourceFunc)property_update_timeout_cb, ugtk );
  106.  }
  107.  break;
  108.       default:
  109.  G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, pspec );
  110.  break;
  111.    }
  112. }
  113. static void unicapgtk_property_dialog_get_property( GObject *object, 
  114.     guint property_id, 
  115.     GValue *value, 
  116.     GParamSpec *pspec )
  117. {
  118.    UnicapgtkPropertyDialog *ugtk = UNICAPGTK_PROPERTY_DIALOG( object );
  119.    switch( property_id )
  120.    {
  121.       case PROP_UPDATE_INTERVAL:
  122.          g_value_set_int( value, ugtk->update_interval );
  123.          break;
  124.       default:
  125.  G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, pspec );
  126.  break;
  127.    }
  128. }
  129. static void unicapgtk_property_dialog_finalize( GObject *object )
  130. {
  131.    UnicapgtkPropertyDialog *ugtk = (UnicapgtkPropertyDialog *)object;
  132.    g_list_foreach( ugtk->size_groups, (GFunc)g_object_unref, NULL );
  133.    g_list_free( ugtk->size_groups );
  134.    G_OBJECT_CLASS( unicapgtk_property_dialog_parent_class )->finalize( object );
  135. }
  136. static void unicapgtk_property_dialog_destroy( GtkObject *object )
  137. {
  138.    UnicapgtkPropertyDialog *ugtk = (UnicapgtkPropertyDialog *)object;
  139.    GList *entry;
  140.    for( entry = ugtk->property_list; entry; entry = entry->next )
  141.    {
  142.       struct ppty_relation *rel;
  143.       guint timeout_id = 0;
  144.       rel = (struct ppty_relation *) entry->data;
  145.       
  146.       timeout_id = (guint)g_object_get_data( G_OBJECT( rel->widget ), "update lock" );
  147.       if( timeout_id )
  148.       {
  149.  g_source_remove( timeout_id );
  150.       }
  151.       
  152.       g_free( entry->data );
  153.    }
  154.    g_list_free( ugtk->property_list );
  155.    ugtk->property_list = NULL;
  156.    ugtk->update_entry = NULL;
  157.    if( ugtk->unicap_handle )
  158.    {
  159.       unicap_close( ugtk->unicap_handle );
  160.       ugtk->unicap_handle = NULL;
  161.    }
  162.    GTK_OBJECT_CLASS( unicapgtk_property_dialog_parent_class )->destroy( object );
  163. }
  164. static void format_label( gchar *string, gint maxlen )
  165. {
  166.    gchar *c;
  167.    
  168.    for( c = string; c != NULL; c = g_strstr_len( c, maxlen, " " ) )
  169.    {
  170.       if( *c == ' ' )
  171.       {
  172.  c++;
  173.       }
  174.       
  175.       if( *c )
  176.       {
  177.  *c = g_ascii_toupper( *c );
  178.       }
  179.    }
  180. }
  181. static gboolean remove_update_lock_timeout_cb( GtkWidget *widget )
  182. {
  183.    g_object_set_data( G_OBJECT( widget ), "update lock", NULL );
  184.    
  185.    return FALSE;
  186. }
  187. static gboolean property_update_timeout_cb( UnicapgtkPropertyDialog *ugtk )
  188. {
  189.    struct ppty_relation *rel;
  190.    if( !ugtk->update_entry )
  191.    {
  192.       return TRUE;
  193.    }
  194.    
  195.    rel = ugtk->update_entry->data;
  196.    if( !g_object_get_data( G_OBJECT( rel->widget ), "update lock" ) )
  197.    {
  198.       unicapgtk_device_property_update( UNICAPGTK_DEVICE_PROPERTY( rel->widget ) );
  199.    }
  200.    
  201.    if( ugtk->update_entry->next )
  202.    {
  203.       ugtk->update_entry = ugtk->update_entry->next;
  204.    }
  205.    else
  206.    {
  207.       ugtk->update_entry = g_list_first( ugtk->property_list );
  208.    }
  209.    return TRUE;
  210. }
  211. static void update_lock_destroy_cb( gpointer _id )
  212. {
  213.    guint id = ( guint ) id;
  214.    
  215.    if( id )
  216.    {
  217.       g_source_remove( id );
  218.    }
  219. }
  220. static void property_changed_cb( GtkWidget *widget, unicap_property_t *property, UnicapgtkPropertyDialog *ugtk )
  221. {
  222.    int i;
  223.    guint timeout_id = 0;
  224.    timeout_id = (guint)g_object_get_data( G_OBJECT( widget ), "update lock" );
  225.    if( timeout_id )
  226.    {
  227.       g_source_remove( timeout_id );
  228.    }
  229.    
  230.    // block the update of this property for the next 5 seconds to
  231.    // avoid confusion when the property takes some time to reflect the
  232.    // new setting ( eg. zoom )
  233.    timeout_id = g_timeout_add( 5000, (GSourceFunc)remove_update_lock_timeout_cb, widget );
  234.    g_object_set_data_full( G_OBJECT( widget ), "update lock", (gpointer)timeout_id, update_lock_destroy_cb );
  235.    
  236.    unicap_set_property( ugtk->unicap_handle, property );
  237.  
  238.    for( i = 0; i < property->relations_count; i++ )
  239.    {
  240.       GList *entry;
  241.       
  242.       entry = g_list_find_custom( ugtk->property_list, property->relations[i], (GCompareFunc)strcmp );
  243.       if( entry )
  244.       {
  245.  struct ppty_relation *rel = (struct ppty_relation *)entry->data;
  246.  unicapgtk_device_property_update( UNICAPGTK_DEVICE_PROPERTY( rel->widget ) );
  247.       }
  248.    }
  249. }
  250. static GtkWidget *create_category_vbox( UnicapgtkPropertyDialog *ugtk, unicap_handle_t unicap_handle, char *category )
  251. {
  252.    unicap_property_t ppty_spec, ppty;
  253.    GtkWidget *vbox;
  254.    GtkWidget *widget;
  255.    GtkWidget *label;
  256.    gint i;
  257.    GtkSizeGroup *size_group;
  258.    vbox = gtk_vbox_new( FALSE, 6 );
  259.    gtk_container_set_border_width( GTK_CONTAINER( vbox ), 12 );
  260.    unicap_void_property( &ppty_spec );
  261.    strcpy( ppty_spec.category, category );
  262.    
  263.    
  264.    size_group = gtk_size_group_new( GTK_SIZE_GROUP_HORIZONTAL );
  265.    for( i = 0; SUCCESS( unicap_enumerate_properties( unicap_handle, 
  266.      &ppty_spec, 
  267.      &ppty, 
  268.      i ) ); i++ )
  269.    {
  270.       struct ppty_relation *rel;
  271.    
  272.       widget = unicapgtk_device_property_new_by_handle( unicap_handle, &ppty );
  273.       gtk_box_pack_start( GTK_BOX( vbox ), widget,FALSE, FALSE, 0 );
  274.       g_signal_connect( G_OBJECT( widget ),
  275. "unicapgtk_device_property_changed",
  276. G_CALLBACK( property_changed_cb ),
  277. ugtk );
  278.       label = unicapgtk_device_property_get_label( UNICAPGTK_DEVICE_PROPERTY( widget ) );
  279.       if (label)
  280.       {
  281.  gtk_size_group_add_widget( size_group, label );
  282.       }
  283.    
  284.       rel = g_malloc( sizeof( struct ppty_relation ) );
  285.       strcpy( rel->identifier, ppty.identifier );
  286.       rel->widget = widget;
  287.       ugtk->property_list = g_list_append( ugtk->property_list, rel );
  288.    }
  289.    ugtk->size_groups = g_list_append( ugtk->size_groups, size_group );
  290.    ugtk->update_entry = g_list_first( ugtk->property_list );
  291.    return vbox;
  292. }
  293. static void append_pages( UnicapgtkPropertyDialog *ugtk, unicap_handle_t unicap_handle )
  294. {
  295.    unicap_property_t property;
  296.    GList *categories = NULL;
  297.    GList *entry;
  298.    gchar *label;
  299.    int i;
  300.    
  301.    for( i = 0; SUCCESS( unicap_enumerate_properties( unicap_handle, NULL, &property, i ) ); i++ )
  302.    {
  303.       if( !g_list_find_custom( categories, property.category, (GCompareFunc)strcmp ) )
  304.       {
  305.  categories = g_list_append( categories, g_strdup(property.category) );
  306.       }
  307.    }
  308.    
  309.    for( entry = g_list_first( categories ); entry; entry=entry->next )
  310.    {
  311.       label = g_strdup( dgettext( GETTEXT_PACKAGE, entry->data ) );
  312.       format_label( label, 128 );
  313.       gtk_notebook_append_page( GTK_NOTEBOOK( ugtk->notebook ),
  314.                                 create_category_vbox( ugtk, unicap_handle, entry->data ),
  315. gtk_label_new( label ) );
  316.       g_free( label );
  317.    }  
  318.    g_list_foreach( categories, (GFunc)g_free, NULL );
  319.    g_list_free( categories );
  320.    gtk_widget_show_all( ugtk->notebook );
  321. }
  322. static gboolean save_device_defaults( UnicapgtkPropertyDialog *ugtk, gboolean overwrite )
  323. {
  324.    gchar *config_path;
  325.    gchar *ini_path;
  326.    gchar *ini_filename;
  327.    unicap_device_t device;
  328.    GKeyFile *keyfile;
  329.    gboolean result = FALSE;
  330.    
  331.    if( !ugtk->unicap_handle )
  332.    {
  333.       return FALSE;
  334.    }
  335.    if( !SUCCESS( unicap_get_device( ugtk->unicap_handle, &device ) ) )
  336.    {
  337.       return FALSE;
  338.    }
  339.    config_path = unicapgtk_get_user_config_path();
  340.    if( !config_path )
  341.    {
  342.       return FALSE;
  343.    }
  344.    
  345.    ini_filename = g_strconcat( device.identifier, ".ini", NULL );
  346.    ini_path = g_build_path( G_DIR_SEPARATOR_S, config_path, ini_filename, NULL );
  347.    g_free( ini_filename );
  348.    g_free( config_path );
  349.    
  350.    if( !overwrite )
  351.    {
  352.       if( g_file_test( ini_path, G_FILE_TEST_EXISTS ) )
  353.       {
  354.  g_free( ini_path );
  355.  return FALSE;
  356.       }
  357.    }
  358.    
  359.    keyfile = unicapgtk_save_device_state( ugtk->unicap_handle, UNICAPGTK_DEVICE_STATE_PROPERTIES );
  360.    if( keyfile )
  361.    {
  362.       FILE *f;
  363.       gchar *data;
  364.       gsize size;
  365.       
  366.       data = g_key_file_to_data( keyfile, &size, NULL );
  367.       f = fopen( ini_path, "w" );
  368.       if( f )
  369.       {
  370.  fwrite( data, size, 1, f );
  371.  fclose( f );
  372.  result = TRUE;
  373.       }
  374.       
  375.       g_free( data );
  376.       g_key_file_free( keyfile );
  377.    }
  378.    
  379.    g_free( ini_path );
  380.    return result;
  381. }
  382. static void load_device_defaults( UnicapgtkPropertyDialog *ugtk )
  383. {
  384.    gchar *config_path;
  385.    gchar *ini_path;
  386.    gchar *ini_filename;
  387.    unicap_device_t device;
  388.    GKeyFile *keyfile;
  389.    
  390.    if( !ugtk->unicap_handle )
  391.    {
  392.       return;
  393.    }
  394.    if( !SUCCESS( unicap_get_device( ugtk->unicap_handle, &device ) ) )
  395.    {
  396.       return;
  397.    }
  398.    config_path = unicapgtk_get_user_config_path();
  399.    if( !config_path )
  400.    {
  401.       return;
  402.    }
  403.    
  404.    ini_filename = g_strconcat( device.identifier, ".ini", NULL );
  405.    ini_path = g_build_path( G_DIR_SEPARATOR_S, config_path, ini_filename, NULL );
  406.    g_free( ini_filename );
  407.    g_free( config_path );
  408.    
  409.    keyfile = g_key_file_new( );
  410.    if( g_key_file_load_from_file( keyfile, 
  411.   ini_path, 
  412.   G_KEY_FILE_NONE, 
  413.   NULL ) )
  414.    {
  415.       unicapgtk_load_device_state( ugtk->unicap_handle, keyfile, UNICAPGTK_DEVICE_STATE_PROPERTIES );
  416.    }
  417.    g_free( ini_path );
  418.    g_key_file_free( keyfile );
  419. }
  420. static void unicapgtk_property_dialog_init( UnicapgtkPropertyDialog *ugtk )
  421. {
  422.    GtkWidget *button;
  423.    ugtk->size_groups = NULL;
  424.    gtk_dialog_set_has_separator( GTK_DIALOG( ugtk ), FALSE );
  425.    gtk_dialog_add_button( GTK_DIALOG( ugtk ), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE );
  426.    gtk_dialog_set_default_response( GTK_DIALOG( ugtk ), GTK_RESPONSE_CLOSE );
  427.    g_signal_connect( ugtk,
  428.      "response",
  429.      G_CALLBACK( gtk_widget_hide ),
  430.                      NULL );
  431.    ugtk->notebook = gtk_notebook_new( );
  432.    gtk_container_set_border_width( GTK_CONTAINER( ugtk->notebook ), 6 );
  433.    gtk_box_pack_start( GTK_BOX( GTK_DIALOG( ugtk )->vbox ), ugtk->notebook, TRUE, TRUE, 0 );
  434.    button = gtk_button_new_with_label( _("Update") );
  435.    gtk_box_pack_start( GTK_BOX( GTK_DIALOG( ugtk )->action_area ), button, FALSE, TRUE, 0 );
  436.    gtk_button_box_set_child_secondary (GTK_BUTTON_BOX ( GTK_DIALOG( ugtk )->action_area ),
  437.                                        button, TRUE);
  438.    g_signal_connect_swapped( G_OBJECT( button ), 
  439.      "clicked", 
  440.      G_CALLBACK( unicapgtk_property_dialog_reset ), 
  441.      ugtk );
  442.    button = gtk_button_new_with_label( _("Defaults") );
  443.    gtk_box_pack_start( GTK_BOX( GTK_DIALOG( ugtk )->action_area ), button, FALSE, TRUE, 0 );
  444.    gtk_button_box_set_child_secondary (GTK_BUTTON_BOX ( GTK_DIALOG( ugtk )->action_area ),
  445.                                        button, TRUE);
  446.    g_signal_connect_swapped( G_OBJECT( button ), 
  447.      "clicked", 
  448.      G_CALLBACK( load_device_defaults ), 
  449.      ugtk );
  450.    ugtk->unicap_handle = NULL;
  451.    ugtk->update_timeout_id = g_timeout_add( 100, (GSourceFunc)property_update_timeout_cb, ugtk );
  452.    ugtk->update_interval = 100;
  453.    gtk_window_set_default_size ( GTK_WINDOW( ugtk ), 400, 300 );
  454.    gtk_widget_show_all( GTK_WIDGET( ugtk ));
  455. }
  456. /**
  457.  * unicapgtk_property_dialog_new:
  458.  *
  459.  * Creates a new #UnicapgtkPropertyDialog
  460.  *
  461.  * Returns: a new #UnicapgtkPropertyDialog
  462.  */
  463. GtkWidget *unicapgtk_property_dialog_new( void )
  464. {
  465.    UnicapgtkPropertyDialog *ugtk;
  466.    ugtk = g_object_new( UNICAPGTK_PROPERTY_DIALOG_TYPE, NULL );
  467.    ugtk->unicap_handle = 0;
  468.    return GTK_WIDGET( ugtk );
  469. }
  470. /**
  471.  * unicapgtk_property_dialog_new_by_handle:
  472.  * @handle: a #unicap_handle_t
  473.  *
  474.  * Creates a new #UnicapgtkPropertyDialog with a given
  475.  * #unicap_handle_t
  476.  *
  477.  * Returns: a new #UnicapgtkPropertyDialog
  478.  */
  479. GtkWidget* unicapgtk_property_dialog_new_by_handle( unicap_handle_t handle )
  480. {
  481.    UnicapgtkPropertyDialog *ugtk;
  482.    unicap_device_t device;
  483.    gchar title[512];
  484.    ugtk = g_object_new( UNICAPGTK_PROPERTY_DIALOG_TYPE, NULL );
  485.    ugtk->unicap_handle = unicap_clone_handle( handle );
  486.    save_device_defaults( ugtk, FALSE );
  487.    append_pages( ugtk, ugtk->unicap_handle );
  488.    gtk_widget_show_all( ugtk->notebook );
  489.    unicap_get_device( ugtk->unicap_handle, &device );
  490.    sprintf( title, "%s - Properties", device.identifier );
  491.    gtk_window_set_title( GTK_WINDOW( ugtk ), title );
  492.    return GTK_WIDGET( ugtk );
  493. }
  494. /**
  495.  * unicapgtk_property_dialog_set_device:
  496.  * @ugtk: a #UnicapgtkPropertyDialog
  497.  * @device_spec: the device to be controlled by this dialog
  498.  *
  499.  * Sets the device which should be controlled by this dialog
  500.  */
  501. void unicapgtk_property_dialog_set_device( UnicapgtkPropertyDialog *ugtk, unicap_device_t *device_spec )
  502. {
  503.    unicap_device_t device;
  504.    gchar title[512];
  505.    if( ugtk->unicap_handle )
  506.    {
  507.       unicap_close( ugtk->unicap_handle );
  508.       ugtk->unicap_handle = 0;
  509.    }
  510.    if( SUCCESS( unicap_enumerate_devices( device_spec, &device, 0 ) ) )
  511.    {
  512.       unicap_open( &ugtk->unicap_handle, &device );
  513.    }
  514.    save_device_defaults( ugtk, FALSE );
  515.    unicapgtk_property_dialog_reset( ugtk );
  516.    sprintf( title, "%s - Properties", device.identifier );
  517.    gtk_window_set_title( GTK_WINDOW( ugtk ), title );
  518. }
  519. /**
  520.  * unicapgtk_property_dialog_set_handle:
  521.  * @ugtk: a #UnicapgtkPropertyDialog
  522.  * @handle: a handle of the device to be controlled by this dialog
  523.  *
  524.  * Sets the handle to the device to be controlled by this dialog. The
  525.  * handle will be cloned by this call. 
  526.  */
  527. void unicapgtk_property_dialog_set_handle( UnicapgtkPropertyDialog *ugtk, unicap_handle_t handle )
  528. {
  529.    unicap_device_t device;
  530.    gchar title[512];
  531.    if( ugtk->unicap_handle )
  532.    {
  533.       unicap_close( ugtk->unicap_handle );
  534.       ugtk->unicap_handle = 0;
  535.    }
  536.    if( handle )
  537.    {
  538.       ugtk->unicap_handle = unicap_clone_handle( handle );
  539.       save_device_defaults( ugtk, FALSE );
  540.       if( !SUCCESS( unicap_get_device( handle, &device ) ) )
  541.       {
  542.  gtk_window_set_title( GTK_WINDOW( ugtk ), "Properties" );
  543.  return;
  544.       }
  545.       sprintf( title, "%s - Properties", device.identifier );
  546.       gtk_window_set_title( GTK_WINDOW( ugtk ), title );
  547.    }
  548.    else
  549.    {
  550.       gtk_window_set_title( GTK_WINDOW( ugtk ), "No Device" );
  551.    }
  552.    unicapgtk_property_dialog_reset( ugtk );   
  553. }
  554. /**
  555.  * unicapgtk_property_dialog_reset:
  556.  * @ugtk: an #UnicapgtkPropertyDialog
  557.  *
  558.  * 
  559.  */
  560. void unicapgtk_property_dialog_reset( UnicapgtkPropertyDialog *ugtk )
  561. {
  562.    GList *entry;   
  563.    gint cur_page;
  564.    for( entry = ugtk->property_list; entry; entry = entry->next )
  565.    {
  566.       struct ppty_relation *rel;
  567.       guint timeout_id = 0;
  568.       rel = (struct ppty_relation *) entry->data;
  569.       
  570.       timeout_id = (guint)g_object_get_data( G_OBJECT( rel->widget ), "update lock" );
  571.       if( timeout_id )
  572.       {
  573.  g_source_remove( timeout_id );
  574.       }
  575.       g_free( entry->data );
  576.    }
  577.    
  578.    cur_page = gtk_notebook_get_current_page( GTK_NOTEBOOK( ugtk->notebook ) );
  579.    while( gtk_notebook_get_n_pages( GTK_NOTEBOOK( ugtk->notebook ) ) )
  580.    {
  581.       gtk_widget_destroy( gtk_notebook_get_nth_page( GTK_NOTEBOOK( ugtk->notebook ), 0 ) );
  582.       gtk_notebook_remove_page( GTK_NOTEBOOK( ugtk->notebook ), 0 );
  583.    }
  584.    g_list_free( ugtk->property_list );
  585.    ugtk->property_list = NULL;
  586.    ugtk->update_entry = NULL;
  587.    if( ugtk->unicap_handle )
  588.    {
  589.       unicap_reenumerate_properties( ugtk->unicap_handle, NULL );      
  590.       
  591.       append_pages( ugtk, ugtk->unicap_handle );
  592.       
  593.       gtk_widget_show_all( ugtk->notebook );
  594.    }
  595.    gtk_notebook_set_current_page( GTK_NOTEBOOK( ugtk->notebook ), cur_page );
  596. }