1 /*****************************************************************************
2 * gtk_preferences.c: functions to handle the preferences dialog box.
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
5 * $Id: gtk_preferences.c,v 1.21 2002/03/31 22:59:01 gbazin Exp $
7 * Authors: Gildas Bazin <gbazin@netcourrier.com>
8 * Loïc Minier <lool@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
26 * Preamble: Our main job is to build a nice interface from the modules config
27 * structure. Once this is done, we need to track each change made by the
28 * user to the data contained in this interface so that when/if he decides to
29 * apply his changes we can quickly commit them into the modules config
30 * structure. (for this last task we use a GHashTable to accumulate the
31 * changes. To commit them, we then just have to circle through it )
33 *****************************************************************************/
34 #include <sys/types.h> /* off_t */
37 #include <videolan/vlc.h>
39 #ifdef MODULE_NAME_IS_gnome
47 #include "interface.h"
49 #include "gtk_support.h"
50 #include "gtk_common.h"
51 #include "gtk_preferences.h"
54 static void GtkCreateConfigDialog( char *, intf_thread_t * );
56 static void GtkConfigOk ( GtkButton *, gpointer );
57 static void GtkConfigApply ( GtkButton *, gpointer );
58 static void GtkConfigCancel ( GtkButton *, gpointer );
59 static void GtkConfigSave ( GtkButton *, gpointer );
61 static void GtkConfigDialogDestroyed ( GtkObject *, gpointer );
63 static void GtkStringChanged ( GtkEditable *, gpointer );
64 static void GtkIntChanged ( GtkEditable *, gpointer );
65 static void GtkBoolChanged ( GtkToggleButton *, gpointer );
67 static void GtkFreeHashTable ( gpointer );
68 static void GtkFreeHashValue ( gpointer, gpointer, gpointer );
69 static void GtkSaveHashValue ( gpointer, gpointer, gpointer );
71 static void GtkPluginConfigure ( GtkButton *, gpointer );
72 static void GtkPluginSelected ( GtkButton *, gpointer );
73 static void GtkPluginHighlighted ( GtkCList *, int, int, GdkEventButton *,
76 /****************************************************************************
77 * Callback for menuitems: display configuration interface window
78 ****************************************************************************/
79 void GtkPreferencesActivate( GtkMenuItem * menuitem, gpointer user_data )
81 intf_thread_t * p_intf;
83 p_intf = GetIntf( GTK_WIDGET(menuitem), (char*)user_data );
85 GtkCreateConfigDialog( "main", p_intf );
88 /****************************************************************************
89 * GtkCreateConfigDialog: dynamically creates the configuration dialog
90 * box from all the configuration data provided by the selected module.
91 ****************************************************************************/
93 /* create a new tooltipped area */
94 #define TOOLTIP( text ) \
95 /* create an event box to catch some events */ \
96 item_event_box = gtk_event_box_new(); \
97 /* add a tooltip on mouseover */ \
98 gtk_tooltips_set_tip( p_intf->p_sys->p_tooltips, \
99 item_event_box, text, "" ); \
100 gtk_container_set_border_width( GTK_CONTAINER(item_event_box), 4 );
102 /* draws a right aligned label in side of a widget */
103 #define LABEL_AND_WIDGET( label_text, widget, tooltip ) \
104 gtk_table_resize( GTK_TABLE(category_table), ++rows, 2 ); \
105 item_align = gtk_alignment_new( 1, .5, 0, 0 ); \
106 item_label = gtk_label_new( label_text ); \
107 gtk_container_add( GTK_CONTAINER(item_align), item_label ); \
108 gtk_table_attach_defaults( GTK_TABLE(category_table), item_align, \
109 0, 1, rows - 1, rows ); \
110 item_align = gtk_alignment_new( 0, .5, .5, 0 ); \
111 gtk_container_add( GTK_CONTAINER(item_align), widget ); \
113 gtk_container_add( GTK_CONTAINER(item_event_box), item_align ); \
114 gtk_table_attach_defaults( GTK_TABLE(category_table), item_event_box, \
115 1, 2, rows - 1, rows );
117 static void GtkCreateConfigDialog( char *psz_module_name,
118 intf_thread_t *p_intf )
120 module_t *p_module, *p_module_bis;
125 GHashTable *config_hash_table;
127 GtkWidget *item_event_box;
129 GtkWidget *config_dialog;
130 GtkWidget *config_dialog_vbox;
131 GtkWidget *config_notebook;
133 GtkWidget *category_table = NULL;
134 GtkWidget *category_label = NULL;
136 #ifndef MODULE_NAME_IS_gnome
137 GtkWidget *dialog_action_area;
140 GtkWidget *ok_button;
141 GtkWidget *apply_button;
142 GtkWidget *save_button;
143 GtkWidget *cancel_button;
145 GtkWidget *item_align;
146 GtkWidget *item_frame;
147 GtkWidget *item_hbox;
148 GtkWidget *item_label;
149 GtkWidget *item_vbox;
150 GtkWidget *string_entry;
151 GtkWidget *integer_spinbutton;
153 GtkWidget *bool_checkbutton;
154 GtkWidget *plugin_clist;
155 GtkWidget *plugin_config_button;
156 GtkWidget *plugin_select_button;
158 gint category_max_height;
160 /* Check if the dialog box is already opened, if so this will save us
161 * quite a bit of work. (the interface will be destroyed when you actually
162 * close the dialog window, but remember that it is only hidden if you
163 * clicked on the action buttons). This trick also allows us not to
164 * duplicate identical dialog windows. */
166 config_dialog = (GtkWidget *)gtk_object_get_data(
167 GTK_OBJECT(p_intf->p_sys->p_window), psz_module_name );
170 /* Yeah it was open */
171 gtk_widget_show( config_dialog );
172 gtk_widget_grab_focus( config_dialog );
177 /* Look for the selected module */
178 for( p_module = p_module_bank->first ; p_module != NULL ;
179 p_module = p_module->next )
182 if( psz_module_name && !strcmp( psz_module_name, p_module->psz_name ) )
185 if( !p_module ) return;
187 /* We found it, now we can start building its configuration interface */
188 /* Create the configuration dialog box */
190 #ifdef MODULE_NAME_IS_gnome
191 config_dialog = gnome_dialog_new( p_module->psz_longname, NULL );
192 config_dialog_vbox = GNOME_DIALOG(config_dialog)->vbox;
193 category_max_height = config_GetIntVariable( "gnome_prefs_maxh" );
195 config_dialog = gtk_dialog_new();
196 gtk_window_set_title( GTK_WINDOW(config_dialog), p_module->psz_longname );
197 config_dialog_vbox = GTK_DIALOG(config_dialog)->vbox;
198 category_max_height = config_GetIntVariable( "gtk_prefs_maxh" );
201 gtk_window_set_policy( GTK_WINDOW(config_dialog), TRUE, TRUE, FALSE );
202 gtk_container_set_border_width( GTK_CONTAINER(config_dialog_vbox), 0 );
204 /* Create our config hash table and associate it with the dialog box */
205 config_hash_table = g_hash_table_new( NULL, NULL );
206 gtk_object_set_data_full( GTK_OBJECT(config_dialog),
207 "config_hash_table", config_hash_table,
208 (GtkDestroyNotify)GtkFreeHashTable );
210 /* Create notebook */
211 config_notebook = gtk_notebook_new();
212 gtk_notebook_set_scrollable( GTK_NOTEBOOK(config_notebook), TRUE );
213 gtk_container_add( GTK_CONTAINER(config_dialog_vbox), config_notebook );
215 /* Enumerate config options and add corresponding config boxes */
216 for( i = 0; i < p_module->i_config_lines; i++ )
219 switch( p_module->p_config[i].i_type )
222 case MODULE_CONFIG_HINT_CATEGORY:
223 case MODULE_CONFIG_HINT_END:
226 * Before we start building the interface for the new category, we
227 * must close/finish the previous one we were generating.
231 GtkWidget *_scrolled_window;
232 GtkWidget *_viewport;
234 GtkRequisition _requisition;
236 /* create a vbox to deal with EXPAND/FILL issues in the
237 * notebook page, and pack it with the previously generated
239 _vbox = gtk_vbox_new( FALSE, 0 );
240 gtk_container_set_border_width( GTK_CONTAINER(_vbox), 4 );
241 gtk_box_pack_start( GTK_BOX(_vbox), category_table,
244 /* create a new scrolled window that will contain all of the
246 _scrolled_window = gtk_scrolled_window_new( NULL, NULL );
247 gtk_scrolled_window_set_policy(
248 GTK_SCROLLED_WINDOW(_scrolled_window), GTK_POLICY_NEVER,
249 GTK_POLICY_AUTOMATIC );
250 /* add scrolled window as a notebook page */
251 gtk_notebook_append_page( GTK_NOTEBOOK(config_notebook),
252 _scrolled_window, category_label );
253 /* pack the vbox into the scrolled window */
254 _viewport = gtk_viewport_new( NULL, NULL );
255 gtk_viewport_set_shadow_type( GTK_VIEWPORT(_viewport),
257 gtk_container_add( GTK_CONTAINER(_viewport), _vbox );
258 gtk_container_add( GTK_CONTAINER(_scrolled_window),
261 /* set the size of the scrolled window to the size of the
263 gtk_widget_show_all( _vbox );
264 gtk_widget_size_request( _vbox, &_requisition );
265 if( _requisition.height > category_max_height )
266 gtk_widget_set_usize( _scrolled_window, -1,
267 category_max_height );
269 gtk_widget_set_usize( _scrolled_window, -1,
270 _requisition.height );
273 if( p_module->p_config[i].i_type == MODULE_CONFIG_HINT_END ) break;
277 * Now we can start taking care of the new category
280 /* create a new table for right-left alignment of children */
281 category_table = gtk_table_new( 0, 0, FALSE );
282 gtk_table_set_col_spacings( GTK_TABLE(category_table), 4 );
285 /* create a new category label */
286 category_label = gtk_label_new( p_module->p_config[i].psz_text );
290 case MODULE_CONFIG_ITEM_PLUGIN:
292 item_frame = gtk_frame_new( p_module->p_config[i].psz_text );
294 gtk_table_resize( GTK_TABLE(category_table), ++rows, 2 );
295 gtk_table_attach_defaults( GTK_TABLE(category_table), item_frame,
296 0, 2, rows - 1, rows );
298 item_vbox = gtk_vbox_new( FALSE, 4 );
299 gtk_container_add( GTK_CONTAINER(item_frame), item_vbox );
301 /* create a new clist widget */
303 gchar * titles[] = { "Name", "Description" };
306 gtk_clist_new_with_titles( 2, titles );
308 gtk_clist_column_titles_passive( GTK_CLIST(plugin_clist) );
309 gtk_clist_set_selection_mode( GTK_CLIST(plugin_clist),
310 GTK_SELECTION_SINGLE);
311 gtk_container_add( GTK_CONTAINER(item_vbox), plugin_clist );
313 /* build a list of available plugins */
317 for( p_module_bis = p_module_bank->first ;
318 p_module_bis != NULL ;
319 p_module_bis = p_module_bis->next )
321 if( p_module_bis->i_capabilities &
322 (1 << p_module->p_config[i].i_value) )
324 entry[0] = p_module_bis->psz_name;
325 entry[1] = p_module_bis->psz_longname;
326 gtk_clist_append( GTK_CLIST(plugin_clist), entry );
331 gtk_clist_set_column_auto_resize( GTK_CLIST(plugin_clist),
333 gtk_clist_set_column_auto_resize( GTK_CLIST(plugin_clist),
336 /* connect signals to the plugins list */
337 gtk_signal_connect( GTK_OBJECT(plugin_clist), "select_row",
338 GTK_SIGNAL_FUNC(GtkPluginHighlighted),
341 /* hbox holding the "select" and "configure" buttons */
342 item_hbox = gtk_hbox_new( FALSE, 4 );
343 gtk_container_add( GTK_CONTAINER(item_vbox), item_hbox);
345 /* add configure button */
346 plugin_config_button =
347 gtk_button_new_with_label( _("Configure") );
348 gtk_widget_set_sensitive( plugin_config_button, FALSE );
349 gtk_container_add( GTK_CONTAINER(item_hbox),
350 plugin_config_button );
351 gtk_object_set_data( GTK_OBJECT(plugin_config_button),
353 gtk_object_set_data( GTK_OBJECT(plugin_clist),
354 "config_button", plugin_config_button );
356 /* add select button */
357 plugin_select_button =
358 gtk_button_new_with_label( _("Select") );
359 gtk_container_add( GTK_CONTAINER(item_hbox),
360 plugin_select_button );
361 /* add a tooltip on mouseover */
362 gtk_tooltips_set_tip( p_intf->p_sys->p_tooltips,
363 plugin_select_button,
364 p_module->p_config[i].psz_longtext, "" );
366 /* hbox holding the "selected" label and text input */
367 item_hbox = gtk_hbox_new( FALSE, 4 );
368 gtk_container_add( GTK_CONTAINER(item_vbox), item_hbox);
370 item_label = gtk_label_new( _("Selected:") );
371 gtk_container_add( GTK_CONTAINER(item_hbox), item_label );
373 /* add input box with default value */
374 string_entry = gtk_entry_new();
375 gtk_object_set_data( GTK_OBJECT(plugin_clist),
376 "plugin_entry", string_entry );
377 gtk_container_add( GTK_CONTAINER(item_hbox), string_entry );
378 vlc_mutex_lock( p_module->p_config[i].p_lock );
379 gtk_entry_set_text( GTK_ENTRY(string_entry),
380 p_module->p_config[i].psz_value ?
381 p_module->p_config[i].psz_value : "" );
382 vlc_mutex_unlock( p_module->p_config[i].p_lock );
383 /* add a tooltip on mouseover */
384 gtk_tooltips_set_tip( p_intf->p_sys->p_tooltips,
386 p_module->p_config[i].psz_longtext, "" );
388 /* connect signals to the buttons */
389 gtk_signal_connect( GTK_OBJECT(plugin_config_button), "clicked",
390 GTK_SIGNAL_FUNC(GtkPluginConfigure),
391 (gpointer)plugin_clist );
392 gtk_signal_connect( GTK_OBJECT(plugin_select_button), "clicked",
393 GTK_SIGNAL_FUNC(GtkPluginSelected),
394 (gpointer)plugin_clist );
396 /* connect signal to track changes in the text box */
397 gtk_object_set_data( GTK_OBJECT(string_entry), "config_option",
398 p_module->p_config[i].psz_name );
399 gtk_signal_connect( GTK_OBJECT(string_entry), "changed",
400 GTK_SIGNAL_FUNC(GtkStringChanged),
401 (gpointer)config_dialog );
404 case MODULE_CONFIG_ITEM_STRING:
405 case MODULE_CONFIG_ITEM_FILE:
407 /* add input box with default value */
408 string_entry = gtk_entry_new();
409 vlc_mutex_lock( p_module->p_config[i].p_lock );
410 gtk_entry_set_text( GTK_ENTRY(string_entry),
411 p_module->p_config[i].psz_value ?
412 p_module->p_config[i].psz_value : "" );
413 vlc_mutex_unlock( p_module->p_config[i].p_lock );
415 /* connect signal to track changes in the text box */
416 gtk_object_set_data( GTK_OBJECT(string_entry), "config_option",
417 p_module->p_config[i].psz_name );
418 gtk_signal_connect( GTK_OBJECT(string_entry), "changed",
419 GTK_SIGNAL_FUNC(GtkStringChanged),
420 (gpointer)config_dialog );
422 LABEL_AND_WIDGET( p_module->p_config[i].psz_text,
424 p_module->p_config[i].psz_longtext );
427 case MODULE_CONFIG_ITEM_INTEGER:
429 /* add input box with default value */
430 item_adj = gtk_adjustment_new( p_module->p_config[i].i_value,
431 -1, 99999, 1, 10, 10 );
432 integer_spinbutton = gtk_spin_button_new( GTK_ADJUSTMENT(item_adj),
435 /* connect signal to track changes in the spinbutton value */
436 gtk_object_set_data( GTK_OBJECT(integer_spinbutton),
438 p_module->p_config[i].psz_name );
439 gtk_signal_connect( GTK_OBJECT(integer_spinbutton), "changed",
440 GTK_SIGNAL_FUNC(GtkIntChanged),
441 (gpointer)config_dialog );
443 LABEL_AND_WIDGET( p_module->p_config[i].psz_text,
445 p_module->p_config[i].psz_longtext );
448 case MODULE_CONFIG_ITEM_BOOL:
450 /* add check button */
451 bool_checkbutton = gtk_check_button_new();
452 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(bool_checkbutton),
453 p_module->p_config[i].i_value );
455 /* connect signal to track changes in the button state */
456 gtk_object_set_data( GTK_OBJECT(bool_checkbutton), "config_option",
457 p_module->p_config[i].psz_name );
458 gtk_signal_connect( GTK_OBJECT(bool_checkbutton), "toggled",
459 GTK_SIGNAL_FUNC(GtkBoolChanged),
460 (gpointer)config_dialog );
462 LABEL_AND_WIDGET( p_module->p_config[i].psz_text,
464 p_module->p_config[i].psz_longtext );
470 #ifndef MODULE_NAME_IS_gnome
471 /* Now let's add the action buttons at the bottom of the page */
472 dialog_action_area = GTK_DIALOG(config_dialog)->action_area;
473 gtk_container_set_border_width( GTK_CONTAINER(dialog_action_area), 4 );
475 /* add a new table for the config option */
476 item_hbox = gtk_hbox_new( FALSE, 0 );
477 gtk_box_pack_end( GTK_BOX(dialog_action_area), item_hbox,
479 item_hbox = gtk_hbox_new( FALSE, 0 );
480 gtk_box_pack_end( GTK_BOX(dialog_action_area), item_hbox,
484 /* Create the OK button */
485 #ifdef MODULE_NAME_IS_gnome
486 gnome_dialog_append_button( GNOME_DIALOG(config_dialog),
487 GNOME_STOCK_BUTTON_OK );
489 GTK_WIDGET(g_list_last(GNOME_DIALOG(config_dialog)->buttons)->data);
491 gnome_dialog_append_button( GNOME_DIALOG(config_dialog),
492 GNOME_STOCK_BUTTON_APPLY );
494 GTK_WIDGET(g_list_last(GNOME_DIALOG(config_dialog)->buttons)->data);
496 gnome_dialog_append_button_with_pixmap(
497 GNOME_DIALOG(config_dialog), _("Save"), GNOME_STOCK_PIXMAP_SAVE );
499 GTK_WIDGET(g_list_last(GNOME_DIALOG(config_dialog)->buttons)->data);
501 gnome_dialog_append_button( GNOME_DIALOG(config_dialog),
502 GNOME_STOCK_BUTTON_CANCEL );
504 GTK_WIDGET(g_list_last(GNOME_DIALOG(config_dialog)->buttons)->data);
506 ok_button = gtk_button_new_with_label( _("Ok") );
507 gtk_box_pack_start( GTK_BOX(dialog_action_area), ok_button,
510 apply_button = gtk_button_new_with_label( _("Apply") );
511 gtk_box_pack_start( GTK_BOX(dialog_action_area), apply_button,
514 save_button = gtk_button_new_with_label( _("Save") );
515 gtk_box_pack_start( GTK_BOX(dialog_action_area), save_button,
518 cancel_button = gtk_button_new_with_label( _("Cancel") );
519 gtk_box_pack_start( GTK_BOX(dialog_action_area), cancel_button,
523 gtk_signal_connect( GTK_OBJECT(ok_button), "clicked",
524 GTK_SIGNAL_FUNC(GtkConfigOk),
526 gtk_signal_connect( GTK_OBJECT(apply_button), "clicked",
527 GTK_SIGNAL_FUNC(GtkConfigApply),
529 gtk_signal_connect( GTK_OBJECT(save_button), "clicked",
530 GTK_SIGNAL_FUNC(GtkConfigSave),
532 gtk_signal_connect( GTK_OBJECT(cancel_button), "clicked",
533 GTK_SIGNAL_FUNC(GtkConfigCancel),
538 /* Ok, job done successfully. Let's keep a reference to the dialog box */
539 gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_window),
540 psz_module_name, config_dialog );
541 gtk_object_set_data( GTK_OBJECT(config_dialog), "psz_module_name",
544 /* we want this ref to be destroyed if the object is destroyed */
545 gtk_signal_connect( GTK_OBJECT(config_dialog), "destroy",
546 GTK_SIGNAL_FUNC(GtkConfigDialogDestroyed),
549 gtk_widget_show_all( config_dialog );
552 #undef LABEL_AND_WIDGET
555 /****************************************************************************
556 * GtkConfigApply: store the changes to the config inside the modules
557 * configuration structure
558 ****************************************************************************/
559 void GtkConfigApply( GtkButton * button, gpointer user_data )
561 GHashTable *hash_table;
562 hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
563 "config_hash_table" );
564 g_hash_table_foreach( hash_table, GtkSaveHashValue, NULL );
568 void GtkConfigOk( GtkButton * button, gpointer user_data )
570 GtkConfigApply( button, user_data );
571 gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
575 void GtkConfigCancel( GtkButton * button, gpointer user_data )
577 gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
580 void GtkConfigSave( GtkButton * button, gpointer user_data )
582 GtkConfigApply( button, user_data );
583 config_SaveConfigFile( NULL );
586 /****************************************************************************
587 * GtkPluginHighlighted: display plugin description when an entry is selected
588 * in the clist, and activate the configure button if necessary.
589 ****************************************************************************/
590 void GtkPluginHighlighted( GtkCList *plugin_clist, int row, int column,
591 GdkEventButton *event, gpointer user_data )
593 GtkWidget *config_button;
597 if( gtk_clist_get_text( GTK_CLIST(plugin_clist), row, 0, &psz_name ) )
599 /* look for plugin 'psz_name' */
600 for( p_module = p_module_bank->first ;
602 p_module = p_module->next )
604 if( !strcmp( p_module->psz_name, psz_name ) )
606 gtk_object_set_data( GTK_OBJECT(plugin_clist),
607 "plugin_highlighted", p_module );
608 config_button = gtk_object_get_data( GTK_OBJECT(plugin_clist),
610 if( p_module->i_config_items )
611 gtk_widget_set_sensitive( config_button, TRUE );
613 gtk_widget_set_sensitive( config_button, FALSE );
622 /****************************************************************************
623 * GtkPluginConfigure: display plugin configuration dialog box.
624 ****************************************************************************/
625 void GtkPluginConfigure( GtkButton *button, gpointer user_data )
628 intf_thread_t *p_intf;
630 p_module = (module_t *)gtk_object_get_data( GTK_OBJECT(user_data),
631 "plugin_highlighted" );
633 if( !p_module ) return;
634 p_intf = (intf_thread_t *)gtk_object_get_data( GTK_OBJECT(button),
636 GtkCreateConfigDialog( p_module->psz_name, (gpointer)p_intf );
640 /****************************************************************************
641 * GtkPluginSelected: select plugin.
642 ****************************************************************************/
643 void GtkPluginSelected( GtkButton *button, gpointer user_data )
648 p_module = (module_t *)gtk_object_get_data( GTK_OBJECT(user_data),
649 "plugin_highlighted" );
650 widget = (GtkWidget *)gtk_object_get_data( GTK_OBJECT(user_data),
652 if( !p_module ) return;
654 gtk_entry_set_text( GTK_ENTRY(widget), p_module->psz_name );
658 /****************************************************************************
659 * GtkStringChanged: signal called when the user changes a string value.
660 ****************************************************************************/
661 static void GtkStringChanged( GtkEditable *editable, gpointer user_data )
663 module_config_t *p_config;
665 GHashTable *hash_table;
667 hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
668 "config_hash_table" );
669 /* free old p_config */
670 p_config = (module_config_t *)g_hash_table_lookup( hash_table,
671 (gpointer)editable );
672 if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, NULL );
674 p_config = malloc( sizeof(module_config_t) );
675 p_config->i_type = MODULE_CONFIG_ITEM_STRING;
676 p_config->psz_value = gtk_editable_get_chars( editable, 0, -1 );
677 p_config->psz_name = (char *)gtk_object_get_data( GTK_OBJECT(editable),
680 g_hash_table_insert( hash_table, (gpointer)editable,
681 (gpointer)p_config );
684 /****************************************************************************
685 * GtkIntChanged: signal called when the user changes a an integer value.
686 ****************************************************************************/
687 static void GtkIntChanged( GtkEditable *editable, gpointer user_data )
689 module_config_t *p_config;
691 GHashTable *hash_table;
693 hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
694 "config_hash_table" );
696 /* free old p_config */
697 p_config = (module_config_t *)g_hash_table_lookup( hash_table,
698 (gpointer)editable );
699 if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, NULL );
701 p_config = malloc( sizeof(module_config_t) );
702 p_config->i_type = MODULE_CONFIG_ITEM_INTEGER;
703 p_config->i_value = gtk_spin_button_get_value_as_int(
704 GTK_SPIN_BUTTON(editable) );
705 p_config->psz_name = (char *)gtk_object_get_data( GTK_OBJECT(editable),
708 g_hash_table_insert( hash_table, (gpointer)editable,
709 (gpointer)p_config );
712 /****************************************************************************
713 * GtkStringChanged: signal called when the user changes a bool value.
714 ****************************************************************************/
715 static void GtkBoolChanged( GtkToggleButton *button, gpointer user_data )
717 module_config_t *p_config;
719 GHashTable *hash_table;
721 hash_table = (GHashTable *)gtk_object_get_data( GTK_OBJECT(user_data),
722 "config_hash_table" );
724 /* free old p_config */
725 p_config = (module_config_t *)g_hash_table_lookup( hash_table,
727 if( p_config ) GtkFreeHashValue( NULL, (gpointer)p_config, NULL );
729 p_config = malloc( sizeof(module_config_t) );
730 p_config->i_type = MODULE_CONFIG_ITEM_BOOL;
731 p_config->i_value = gtk_toggle_button_get_active( button );
732 p_config->psz_name = (char *)gtk_object_get_data( GTK_OBJECT(button),
735 g_hash_table_insert( hash_table, (gpointer)button,
736 (gpointer)p_config );
739 /****************************************************************************
740 * GtkFreeHashTable: signal called when the config hash table is destroyed.
741 ****************************************************************************/
742 static void GtkFreeHashTable( gpointer user_data )
744 GHashTable *hash_table = (GHashTable *)user_data;
746 g_hash_table_foreach( hash_table, GtkFreeHashValue, NULL );
747 g_hash_table_destroy( hash_table );
750 /****************************************************************************
751 * GtkFreeHashValue: signal called when an element of the config hash table
753 ****************************************************************************/
754 static void GtkFreeHashValue( gpointer key, gpointer value, gpointer user_data)
756 module_config_t *p_config = (module_config_t *)value;
758 if( p_config->i_type == MODULE_CONFIG_ITEM_STRING )
759 g_free( p_config->psz_value );
763 /****************************************************************************
764 * GtkSaveHashValue: callback used when enumerating the hash table in
766 ****************************************************************************/
767 static void GtkSaveHashValue( gpointer key, gpointer value, gpointer user_data)
769 module_config_t *p_config = (module_config_t *)value;
771 switch( p_config->i_type )
774 case MODULE_CONFIG_ITEM_STRING:
775 case MODULE_CONFIG_ITEM_FILE:
776 case MODULE_CONFIG_ITEM_PLUGIN:
777 config_PutPszVariable( p_config->psz_name,
778 *p_config->psz_value? p_config->psz_value : NULL );
780 case MODULE_CONFIG_ITEM_INTEGER:
781 case MODULE_CONFIG_ITEM_BOOL:
782 config_PutIntVariable( p_config->psz_name, p_config->i_value );
787 /****************************************************************************
788 * GtkConfigDialogDestroyed: callback triggered when the config dialog box is
790 ****************************************************************************/
791 static void GtkConfigDialogDestroyed( GtkObject *object, gpointer user_data )
793 intf_thread_t *p_intf = (intf_thread_t *)user_data;
794 char *psz_module_name;
796 psz_module_name = gtk_object_get_data( object, "psz_module_name" );
798 /* remove the ref to the dialog box */
799 gtk_object_set_data( GTK_OBJECT(p_intf->p_sys->p_window),
800 psz_module_name, NULL );