1 /*
2  * Nautilus-Actions
3  * A Nautilus extension which offers configurable context menu actions.
4  *
5  * Copyright (C) 2005 The GNOME Foundation
6  * Copyright (C) 2006-2008 Frederic Ruaudel and others (see AUTHORS)
7  * Copyright (C) 2009-2014 Pierre Wieser and others (see AUTHORS)
8  *
9  * Nautilus-Actions is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * Nautilus-Actions is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with Nautilus-Actions; see the file COPYING. If not, see
21  * <http://www.gnu.org/licenses/>.
22  *
23  * Authors:
24  *   Frederic Ruaudel <grumz@grumz.net>
25  *   Rodrigo Moya <rodrigo@gnome-db.org>
26  *   Pierre Wieser <pwieser@trychlos.org>
27  *   ... and many others (see AUTHORS)
28  */
29 
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33 
34 #include <glib/gi18n.h>
35 #include <libintl.h>
36 
37 #include <api/na-iimporter.h>
38 
39 #include <core/na-desktop-environment.h>
40 #include <core/na-exporter.h>
41 #include <core/na-export-format.h>
42 #include <core/na-gtk-utils.h>
43 #include <core/na-import-mode.h>
44 #include <core/na-importer.h>
45 #include <core/na-ioptions-list.h>
46 #include <core/na-iprefs.h>
47 #include <core/na-tokens.h>
48 
49 #include "nact-application.h"
50 #include "base-gtk-utils.h"
51 #include "nact-schemes-list.h"
52 #include "nact-providers-list.h"
53 #include "nact-preferences-editor.h"
54 
55 /* private class data
56  */
57 struct _NactPreferencesEditorClassPrivate {
58 	void *empty;						/* so that gcc -pedantic is happy */
59 };
60 
61 /* private instance data
62  */
63 struct _NactPreferencesEditorPrivate {
64 	gboolean dispose_has_run;
65 	gboolean preferences_locked;
66 
67 	/* first tab: runtime preferences */
68 	guint    order_mode;
69 	gboolean order_mode_mandatory;
70 	gboolean root_menu;
71 	gboolean root_menu_mandatory;
72 	gboolean about_item;
73 	gboolean about_item_mandatory;
74 
75 	/* second tab: runtime execution */
76 	gchar   *terminal_pattern;
77 	gboolean terminal_pattern_mandatory;
78 	gchar   *desktop;
79 	gboolean desktop_mandatory;
80 
81 	/* third tab: ui preferences */
82 	gboolean relabel_menu;
83 	gboolean relabel_menu_mandatory;
84 	gboolean relabel_action;
85 	gboolean relabel_action_mandatory;
86 	gboolean relabel_profile;
87 	gboolean relabel_profile_mandatory;
88 	gboolean esc_quit;
89 	gboolean esc_quit_mandatory;
90 	gboolean esc_confirm;
91 	gboolean esc_confirm_mandatory;
92 	gboolean auto_save;
93 	gboolean auto_save_mandatory;
94 	guint    auto_save_period;
95 	gboolean auto_save_period_mandatory;
96 
97 	/* fourth tab: import mode */
98 	guint    import_mode;
99 	gboolean import_mode_mandatory;
100 
101 	/* fifth tab: export format */
102 	gboolean export_format_mandatory;
103 
104 	/* sixth tab: default list of available schemes */
105 	/* seventh tab: i/o providers */
106 };
107 
108 /* column ordering in the desktop environment combobox
109  */
110 enum {
111 	DESKTOP_ID_COLUMN = 0,
112 	DESKTOP_LABEL_COLUMN = 0,
113 	DESKTOP_N_COLUMN
114 };
115 
116 /* i18n: the user is not willing to identify his current desktop environment,
117  *       and prefers rely on the runtime detection */
118 static const NADesktopEnv st_no_desktop     = { "None", N_( "Rely on runtime detection" ) };
119 
120 static const gchar       *st_xmlui_filename = PKGUIDIR "/nact-preferences.ui";
121 static const gchar       *st_toplevel_name  = "PreferencesDialog";
122 static const gchar       *st_wsp_name       = NA_IPREFS_PREFERENCES_WSP;
123 
124 static GObjectClass      *st_parent_class   = NULL;
125 static guint              st_last_tab       = 0;
126 
127 static GType      register_type( void );
128 static void       class_init( NactPreferencesEditorClass *klass );
129 static void       ioptions_list_iface_init( NAIOptionsListInterface *iface, void *user_data );
130 static GList     *ioptions_list_get_options( const NAIOptionsList *instance, GtkWidget *container );
131 static void       ioptions_list_free_options( const NAIOptionsList *instance, GtkWidget *container, GList *options );
132 static NAIOption *ioptions_list_get_ask_option( const NAIOptionsList *instance, GtkWidget *container );
133 static void       instance_init( GTypeInstance *instance, gpointer klass );
134 static void       instance_constructed( GObject *dialog );
135 static void       instance_dispose( GObject *dialog );
136 static void       instance_finalize( GObject *dialog );
137 
138 static void       on_base_initialize_gtk( NactPreferencesEditor *editor, GtkDialog *toplevel, gpointer user_data );
139 static void       on_base_initialize_window( NactPreferencesEditor *editor, gpointer user_data );
140 static void       on_base_show_widgets( NactPreferencesEditor *editor, gpointer user_data );
141 static void       order_mode_setup( NactPreferencesEditor *editor );
142 static void       order_mode_on_alpha_asc_toggled( GtkToggleButton *togglebutton, NactPreferencesEditor *editor );
143 static void       order_mode_on_alpha_desc_toggled( GtkToggleButton *togglebutton, NactPreferencesEditor *editor );
144 static void       order_mode_on_manual_toggled( GtkToggleButton *togglebutton, NactPreferencesEditor *editor );
145 static void       order_mode_on_toggled( NactPreferencesEditor *editor, GtkToggleButton *togglebutton, GCallback cb, guint order_mode );
146 static void       root_menu_setup( NactPreferencesEditor *editor );
147 static void       root_menu_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor );
148 static void       about_item_setup( NactPreferencesEditor *editor );
149 static void       about_item_set_sensitive( NactPreferencesEditor *editor );
150 static void       about_item_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor );
151 static void       terminal_pattern_setup( NactPreferencesEditor *editor );
152 static void       terminal_pattern_on_changed( GtkEntry *entry, NactPreferencesEditor *editor );
153 static void       desktop_create_model( NactPreferencesEditor *editor );
154 static void       desktop_setup( NactPreferencesEditor *editor );
155 static void       desktop_on_changed( GtkComboBox *combo, NactPreferencesEditor *editor );
156 static void       relabel_menu_setup( NactPreferencesEditor *editor );
157 static void       relabel_menu_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor );
158 static void       relabel_action_setup( NactPreferencesEditor *editor );
159 static void       relabel_action_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor );
160 static void       relabel_profile_setup( NactPreferencesEditor *editor );
161 static void       relabel_profile_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor );
162 static void       esc_quit_setup( NactPreferencesEditor *editor );
163 static void       esc_quit_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor );
164 static void       esc_confirm_setup( NactPreferencesEditor *editor );
165 static void       esc_confirm_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor );
166 static void       auto_save_setup( NactPreferencesEditor *editor );
167 static void       auto_save_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor );
168 static void       auto_save_period_on_change_value( GtkSpinButton *spinbutton, NactPreferencesEditor *editor );
169 static void       on_cancel_clicked( GtkButton *button, NactPreferencesEditor *editor );
170 static void       on_ok_clicked( GtkButton *button, NactPreferencesEditor *editor );
171 static void       on_dialog_ok( BaseDialog *dialog );
172 
173 GType
nact_preferences_editor_get_type(void)174 nact_preferences_editor_get_type( void )
175 {
176 	static GType dialog_type = 0;
177 
178 	if( !dialog_type ){
179 		dialog_type = register_type();
180 	}
181 
182 	return( dialog_type );
183 }
184 
185 static GType
register_type(void)186 register_type( void )
187 {
188 	static const gchar *thisfn = "nact_preferences_editor_register_type";
189 	GType type;
190 
191 	static GTypeInfo info = {
192 		sizeof( NactPreferencesEditorClass ),
193 		( GBaseInitFunc ) NULL,
194 		( GBaseFinalizeFunc ) NULL,
195 		( GClassInitFunc ) class_init,
196 		NULL,
197 		NULL,
198 		sizeof( NactPreferencesEditor ),
199 		0,
200 		( GInstanceInitFunc ) instance_init
201 	};
202 
203 	static const GInterfaceInfo ioptions_list_iface_info = {
204 		( GInterfaceInitFunc ) ioptions_list_iface_init,
205 		NULL,
206 		NULL
207 	};
208 
209 	g_debug( "%s", thisfn );
210 
211 	type = g_type_register_static( BASE_TYPE_DIALOG, "NactPreferencesEditor", &info, 0 );
212 
213 	g_type_add_interface_static( type, NA_TYPE_IOPTIONS_LIST, &ioptions_list_iface_info );
214 
215 	return( type );
216 }
217 
218 static void
class_init(NactPreferencesEditorClass * klass)219 class_init( NactPreferencesEditorClass *klass )
220 {
221 	static const gchar *thisfn = "nact_preferences_editor_class_init";
222 	GObjectClass *object_class;
223 	BaseDialogClass *dialog_class;
224 
225 	g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
226 
227 	st_parent_class = g_type_class_peek_parent( klass );
228 
229 	object_class = G_OBJECT_CLASS( klass );
230 	object_class->constructed = instance_constructed;
231 	object_class->dispose = instance_dispose;
232 	object_class->finalize = instance_finalize;
233 
234 	klass->private = g_new0( NactPreferencesEditorClassPrivate, 1 );
235 
236 	dialog_class = BASE_DIALOG_CLASS( klass );
237 	dialog_class->ok = on_dialog_ok;
238 }
239 
240 static void
ioptions_list_iface_init(NAIOptionsListInterface * iface,void * user_data)241 ioptions_list_iface_init( NAIOptionsListInterface *iface, void *user_data )
242 {
243 	static const gchar *thisfn = "nact_assistant_export_ioptions_list_iface_init";
244 
245 	g_debug( "%s: iface=%p, user_data=%p", thisfn, ( void * ) iface, ( void * ) user_data );
246 
247 	iface->get_options = ioptions_list_get_options;
248 	iface->free_options = ioptions_list_free_options;
249 	iface->get_ask_option = ioptions_list_get_ask_option;
250 }
251 
252 /*
253  * ioptions_list_get_options, ioptions_list_free_options:
254  * manages import mode options or export format options depending of the
255  * current container
256  */
257 static GList *
ioptions_list_get_options(const NAIOptionsList * instance,GtkWidget * container)258 ioptions_list_get_options( const NAIOptionsList *instance, GtkWidget *container )
259 {
260 	static const gchar *thisfn = "nact_preferences_editor_ioptions_list_get_options";
261 	GList *options;
262 	NactApplication *application;
263 	NAUpdater *updater;
264 
265 	g_return_val_if_fail( NACT_IS_PREFERENCES_EDITOR( instance ), NULL );
266 
267 	options = NULL;
268 
269 	if( container == base_window_get_widget( BASE_WINDOW( instance ), "PreferencesExportFormatVBox" )){
270 		application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( instance )));
271 		updater = nact_application_get_updater( application );
272 		options = na_exporter_get_formats( NA_PIVOT( updater ));
273 
274 	} else if( container == base_window_get_widget( BASE_WINDOW( instance ), "PreferencesImportModeVBox" )){
275 		options = na_importer_get_modes();
276 
277 	} else {
278 		g_warning( "%s: container=%p (%s): unmanaged container",
279 				thisfn,
280 				( void * ) container, G_OBJECT_TYPE_NAME( container ));
281 	}
282 
283 	return( options );
284 }
285 
286 static void
ioptions_list_free_options(const NAIOptionsList * instance,GtkWidget * container,GList * options)287 ioptions_list_free_options( const NAIOptionsList *instance, GtkWidget *container, GList *options )
288 {
289 	static const gchar *thisfn = "nact_preferences_editor_ioptions_list_free_options";
290 
291 	g_return_if_fail( NACT_IS_PREFERENCES_EDITOR( instance ));
292 
293 	if( container == base_window_get_widget( BASE_WINDOW( instance ), "PreferencesExportFormatVBox" )){
294 		na_exporter_free_formats( options );
295 
296 	} else if( container == base_window_get_widget( BASE_WINDOW( instance ), "PreferencesImportModeVBox" )){
297 		na_importer_free_modes( options );
298 
299 	} else {
300 		g_warning( "%s: container=%p (%s): unmanaged container",
301 				thisfn,
302 				( void * ) container, G_OBJECT_TYPE_NAME( container ));
303 	}
304 }
305 
306 static NAIOption *
ioptions_list_get_ask_option(const NAIOptionsList * instance,GtkWidget * container)307 ioptions_list_get_ask_option( const NAIOptionsList *instance, GtkWidget *container )
308 {
309 	static const gchar *thisfn = "nact_preferences_editor_ioptions_list_get_ask_option";
310 	NAIOption *option;
311 
312 	g_return_val_if_fail( NACT_IS_PREFERENCES_EDITOR( instance ), NULL );
313 
314 	option = NULL;
315 
316 	if( container == base_window_get_widget( BASE_WINDOW( instance ), "PreferencesExportFormatVBox" )){
317 		option = na_exporter_get_ask_option();
318 
319 	} else if( container == base_window_get_widget( BASE_WINDOW( instance ), "PreferencesImportModeVBox" )){
320 		option = na_importer_get_ask_mode();
321 
322 	} else {
323 		g_warning( "%s: container=%p (%s): unmanaged container",
324 				thisfn,
325 				( void * ) container, G_OBJECT_TYPE_NAME( container ));
326 	}
327 
328 	return( option );
329 }
330 
331 static void
instance_init(GTypeInstance * instance,gpointer klass)332 instance_init( GTypeInstance *instance, gpointer klass )
333 {
334 	static const gchar *thisfn = "nact_preferences_editor_instance_init";
335 	NactPreferencesEditor *self;
336 
337 	g_return_if_fail( NACT_IS_PREFERENCES_EDITOR( instance ));
338 
339 	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
340 
341 	self = NACT_PREFERENCES_EDITOR( instance );
342 
343 	self->private = g_new0( NactPreferencesEditorPrivate, 1 );
344 
345 	self->private->dispose_has_run = FALSE;
346 }
347 
348 static void
instance_constructed(GObject * dialog)349 instance_constructed( GObject *dialog )
350 {
351 	static const gchar *thisfn = "nact_preferences_editor_instance_constructed";
352 	NactPreferencesEditorPrivate *priv;
353 
354 	g_return_if_fail( NACT_IS_PREFERENCES_EDITOR( dialog ));
355 
356 	priv = NACT_PREFERENCES_EDITOR( dialog )->private;
357 
358 	if( !priv->dispose_has_run ){
359 
360 		/* chain up to the parent class */
361 		if( G_OBJECT_CLASS( st_parent_class )->constructed ){
362 			G_OBJECT_CLASS( st_parent_class )->constructed( dialog );
363 		}
364 
365 		g_debug( "%s: dialog=%p (%s)", thisfn, ( void * ) dialog, G_OBJECT_TYPE_NAME( dialog ));
366 
367 		base_window_signal_connect(
368 				BASE_WINDOW( dialog ),
369 				G_OBJECT( dialog ),
370 				BASE_SIGNAL_INITIALIZE_GTK,
371 				G_CALLBACK( on_base_initialize_gtk ));
372 
373 		base_window_signal_connect(
374 				BASE_WINDOW( dialog ),
375 				G_OBJECT( dialog ),
376 				BASE_SIGNAL_INITIALIZE_WINDOW,
377 				G_CALLBACK( on_base_initialize_window ));
378 
379 		base_window_signal_connect(
380 				BASE_WINDOW( dialog ),
381 				G_OBJECT( dialog ),
382 				BASE_SIGNAL_SHOW_WIDGETS,
383 				G_CALLBACK( on_base_show_widgets ));
384 	}
385 }
386 
387 static void
instance_dispose(GObject * dialog)388 instance_dispose( GObject *dialog )
389 {
390 	static const gchar *thisfn = "nact_preferences_editor_instance_dispose";
391 	NactPreferencesEditor *self;
392 
393 	g_return_if_fail( NACT_IS_PREFERENCES_EDITOR( dialog ));
394 
395 	self = NACT_PREFERENCES_EDITOR( dialog );
396 
397 	if( !self->private->dispose_has_run ){
398 		g_debug( "%s: dialog=%p (%s)", thisfn, ( void * ) dialog, G_OBJECT_TYPE_NAME( dialog ));
399 
400 		self->private->dispose_has_run = TRUE;
401 
402 		nact_schemes_list_dispose( BASE_WINDOW( self ));
403 		nact_providers_list_dispose( BASE_WINDOW( self ));
404 
405 		/* chain up to the parent class */
406 		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
407 			G_OBJECT_CLASS( st_parent_class )->dispose( dialog );
408 		}
409 	}
410 }
411 
412 static void
instance_finalize(GObject * dialog)413 instance_finalize( GObject *dialog )
414 {
415 	static const gchar *thisfn = "nact_preferences_editor_instance_finalize";
416 	NactPreferencesEditor *self;
417 
418 	g_return_if_fail( NACT_IS_PREFERENCES_EDITOR( dialog ));
419 
420 	g_debug( "%s: dialog=%p (%s)", thisfn, ( void * ) dialog, G_OBJECT_TYPE_NAME( dialog ));
421 
422 	self = NACT_PREFERENCES_EDITOR( dialog );
423 
424 	g_free( self->private );
425 
426 	/* chain call to parent class */
427 	if( G_OBJECT_CLASS( st_parent_class )->finalize ){
428 		G_OBJECT_CLASS( st_parent_class )->finalize( dialog );
429 	}
430 }
431 
432 /**
433  * nact_preferences_editor_run:
434  * @parent: the BaseWindow parent of this dialog
435  * (usually the NactMainWindow).
436  *
437  * Initializes and runs the dialog.
438  */
439 void
nact_preferences_editor_run(BaseWindow * parent)440 nact_preferences_editor_run( BaseWindow *parent )
441 {
442 	static const gchar *thisfn = "nact_preferences_editor_run";
443 	NactPreferencesEditor *editor;
444 	gboolean are_locked, mandatory;
445 	GtkNotebook *notebook;
446 
447 	g_return_if_fail( BASE_IS_WINDOW( parent ));
448 
449 	g_debug( "%s: parent=%p (%s)", thisfn, ( void * ) parent, G_OBJECT_TYPE_NAME( parent ));
450 
451 	editor = g_object_new( NACT_TYPE_PREFERENCES_EDITOR,
452 					BASE_PROP_PARENT,          parent,
453 					BASE_PROP_XMLUI_FILENAME,  st_xmlui_filename,
454 					/*
455 					 * having our own builder let us, e.g., set a weak reference on
456 					 * pixbufs allocated by plugins - but this way we are losing
457 					 * mutualization of gtk initializations...
458 					 */
459 					/*BASE_PROP_HAS_OWN_BUILDER, TRUE,*/
460 					BASE_PROP_TOPLEVEL_NAME,   st_toplevel_name,
461 					BASE_PROP_WSP_NAME,        st_wsp_name,
462 					NULL );
463 
464 	are_locked = na_settings_get_boolean( NA_IPREFS_ADMIN_PREFERENCES_LOCKED, NULL, &mandatory );
465 	editor->private->preferences_locked = are_locked && mandatory;
466 	g_debug( "%s: are_locked=%s, mandatory=%s",
467 			thisfn, are_locked ? "True":"False", mandatory ? "True":"False" );
468 
469 	base_window_run( BASE_WINDOW( editor ));
470 
471 	notebook = GTK_NOTEBOOK( base_window_get_widget( BASE_WINDOW( editor ), "PreferencesNotebook" ));
472 	st_last_tab = gtk_notebook_get_current_page( notebook );
473 
474 	g_object_unref( editor );
475 }
476 
477 static void
on_base_initialize_gtk(NactPreferencesEditor * editor,GtkDialog * toplevel,gpointer user_data)478 on_base_initialize_gtk( NactPreferencesEditor *editor, GtkDialog *toplevel, gpointer user_data )
479 {
480 	static const gchar *thisfn = "nact_preferences_editor_on_base_initialize_gtk";
481 	GtkWidget *container;
482 	GtkTreeView *listview;
483 
484 	g_return_if_fail( NACT_IS_PREFERENCES_EDITOR( editor ));
485 
486 	if( !editor->private->dispose_has_run ){
487 
488 		g_debug( "%s: dialog=%p, toplevel=%p, user_data=%p",
489 				thisfn, ( void * ) editor, ( void * ) toplevel, ( void * ) user_data );
490 
491 		desktop_create_model( editor );
492 
493 		container = base_window_get_widget( BASE_WINDOW( editor ), "PreferencesImportModeVBox" );
494 		na_ioptions_list_gtk_init( NA_IOPTIONS_LIST( editor ), container, TRUE );
495 
496 		container = base_window_get_widget( BASE_WINDOW( editor ), "PreferencesExportFormatVBox" );
497 		na_ioptions_list_gtk_init( NA_IOPTIONS_LIST( editor ), container, TRUE );
498 
499 		listview = GTK_TREE_VIEW( base_window_get_widget( BASE_WINDOW( editor ), "SchemesTreeView" ));
500 		nact_schemes_list_create_model( listview, SCHEMES_LIST_FOR_PREFERENCES );
501 
502 		listview = GTK_TREE_VIEW( base_window_get_widget( BASE_WINDOW( editor ), "ProvidersTreeView" ));
503 		nact_providers_list_create_model( listview );
504 
505 #if !GTK_CHECK_VERSION( 2,22,0 )
506 		gtk_dialog_set_has_separator( toplevel, FALSE );
507 #endif
508 	}
509 }
510 
511 static void
on_base_initialize_window(NactPreferencesEditor * editor,gpointer user_data)512 on_base_initialize_window( NactPreferencesEditor *editor, gpointer user_data )
513 {
514 	static const gchar *thisfn = "nact_preferences_editor_on_base_initialize_window";
515 	GtkWidget *container;
516 	GtkTreeView *listview;
517 	GtkWidget *ok_button;
518 	gchar *export_format;
519 	gchar *import_mode;
520 
521 	g_return_if_fail( NACT_IS_PREFERENCES_EDITOR( editor ));
522 
523 	if( !editor->private->dispose_has_run ){
524 
525 		g_debug( "%s: dialog=%p, user_data=%p", thisfn, ( void * ) editor, ( void * ) user_data );
526 
527 		/* first tab: runtime preferences
528 		 */
529 		order_mode_setup( editor );
530 		root_menu_setup( editor );
531 		about_item_setup( editor );
532 
533 		/* second tab: runtime execution
534 		 */
535 		terminal_pattern_setup( editor );
536 		desktop_setup( editor );
537 
538 		/* third tab: ui preferences
539 		 */
540 		relabel_menu_setup( editor );
541 		relabel_action_setup( editor );
542 		relabel_profile_setup( editor );
543 		esc_quit_setup( editor );
544 		esc_confirm_setup( editor );
545 		auto_save_setup( editor );
546 
547 		/* fourth tab: import mode
548 		 */
549 		container = base_window_get_widget( BASE_WINDOW( editor ), "PreferencesImportModeVBox" );
550 		import_mode = na_settings_get_string( NA_IPREFS_IMPORT_PREFERRED_MODE, NULL, &editor->private->import_mode_mandatory );
551 		na_ioptions_list_set_editable(
552 				NA_IOPTIONS_LIST( editor ), container,
553 				!editor->private->import_mode_mandatory && !editor->private->preferences_locked );
554 		na_ioptions_list_set_default(
555 				NA_IOPTIONS_LIST( editor ), container,
556 				import_mode );
557 		g_free( import_mode );
558 
559 		/* fifth tab: export format
560 		 */
561 		container = base_window_get_widget( BASE_WINDOW( editor ), "PreferencesExportFormatVBox" );
562 		export_format = na_settings_get_string( NA_IPREFS_EXPORT_PREFERRED_FORMAT, NULL, &editor->private->export_format_mandatory );
563 		na_ioptions_list_set_editable(
564 				NA_IOPTIONS_LIST( editor ), container,
565 				!editor->private->export_format_mandatory && !editor->private->preferences_locked );
566 		na_ioptions_list_set_default(
567 				NA_IOPTIONS_LIST( editor ), container,
568 				export_format );
569 		g_free( export_format );
570 
571 		/* sixth tab: default schemes
572 		 */
573 		listview = GTK_TREE_VIEW( base_window_get_widget( BASE_WINDOW( editor ), "SchemesTreeView" ));
574 		nact_schemes_list_init_view( listview, BASE_WINDOW( editor ), NULL, NULL );
575 
576 		/* seventh tab: I/O providers priorities
577 		 */
578 		listview = GTK_TREE_VIEW( base_window_get_widget( BASE_WINDOW( editor ), "ProvidersTreeView" ));
579 		nact_providers_list_init_view( BASE_WINDOW( editor ), listview );
580 
581 		/* dialog buttons
582 		 */
583 		base_window_signal_connect_by_name( BASE_WINDOW( editor ),
584 				"CancelButton", "clicked", G_CALLBACK( on_cancel_clicked ));
585 
586 		ok_button = base_window_get_widget( BASE_WINDOW( editor ), "OKButton" );
587 		base_window_signal_connect( BASE_WINDOW( editor ),
588 				G_OBJECT( ok_button ), "clicked", G_CALLBACK( on_ok_clicked ));
589 		base_gtk_utils_set_editable( G_OBJECT( ok_button ), !editor->private->preferences_locked );
590 	}
591 }
592 
593 static void
on_base_show_widgets(NactPreferencesEditor * editor,gpointer user_data)594 on_base_show_widgets( NactPreferencesEditor *editor, gpointer user_data )
595 {
596 	static const gchar *thisfn = "nact_preferences_editor_on_base_show_widgets";
597 	GtkNotebook *notebook;
598 
599 	g_return_if_fail( NACT_IS_PREFERENCES_EDITOR( editor ));
600 
601 	if( !editor->private->dispose_has_run ){
602 
603 		g_debug( "%s: dialog=%p, user_data=%p", thisfn, ( void * ) editor, ( void * ) user_data );
604 
605 		notebook = GTK_NOTEBOOK( base_window_get_widget( BASE_WINDOW( editor ), "PreferencesNotebook" ));
606 		gtk_notebook_set_current_page( notebook, st_last_tab );
607 
608 		nact_schemes_list_show_all( BASE_WINDOW( editor ));
609 	}
610 }
611 
612 /*
613  * 'order mode' is editable if preferences in general are not locked,
614  * and this one is not mandatory.
615  *
616  * This is not related in any way to the level zero order writability status
617  *
618  * The radio button group is insensitive if preferences are locked.
619  * If preferences in general are not locked, but this one is mandatory,
620  * then the radio group is sensitive, but not editable.
621  */
622 static void
order_mode_setup(NactPreferencesEditor * editor)623 order_mode_setup( NactPreferencesEditor *editor )
624 {
625 	gboolean editable;
626 	GtkWidget *alpha_asc_button, *alpha_desc_button, *manual_button;
627 	GtkWidget *active_button;
628 	GCallback active_handler;
629 
630 	editor->private->order_mode = na_iprefs_get_order_mode( &editor->private->order_mode_mandatory );
631 	editable = !editor->private->preferences_locked && !editor->private->order_mode_mandatory;
632 
633 	alpha_asc_button = base_window_get_widget( BASE_WINDOW( editor ), "OrderAlphaAscButton" );
634 	base_window_signal_connect( BASE_WINDOW( editor ), G_OBJECT( alpha_asc_button ), "toggled", G_CALLBACK( order_mode_on_alpha_asc_toggled ));
635 
636 	alpha_desc_button = base_window_get_widget( BASE_WINDOW( editor ), "OrderAlphaDescButton" );
637 	base_window_signal_connect( BASE_WINDOW( editor ), G_OBJECT( alpha_desc_button ), "toggled", G_CALLBACK( order_mode_on_alpha_desc_toggled ));
638 
639 	manual_button = base_window_get_widget( BASE_WINDOW( editor ), "OrderManualButton" );
640 	base_window_signal_connect( BASE_WINDOW( editor ), G_OBJECT( manual_button ), "toggled", G_CALLBACK( order_mode_on_manual_toggled ));
641 
642 	switch( editor->private->order_mode ){
643 		case IPREFS_ORDER_ALPHA_ASCENDING:
644 			active_button = alpha_asc_button;
645 			active_handler = G_CALLBACK( order_mode_on_alpha_asc_toggled );
646 			break;
647 		case IPREFS_ORDER_ALPHA_DESCENDING:
648 			active_button = alpha_desc_button;
649 			active_handler = G_CALLBACK( order_mode_on_alpha_desc_toggled );
650 			break;
651 		case IPREFS_ORDER_MANUAL:
652 		default:
653 			active_button = manual_button;
654 			active_handler = G_CALLBACK( order_mode_on_manual_toggled );
655 			break;
656 	}
657 
658 	base_gtk_utils_radio_set_initial_state(
659 			GTK_RADIO_BUTTON( active_button ),
660 			active_handler, editor, editable, !editor->private->preferences_locked );
661 }
662 
663 static void
order_mode_on_alpha_asc_toggled(GtkToggleButton * toggle_button,NactPreferencesEditor * editor)664 order_mode_on_alpha_asc_toggled( GtkToggleButton *toggle_button, NactPreferencesEditor *editor )
665 {
666 	order_mode_on_toggled( editor, toggle_button, G_CALLBACK( order_mode_on_alpha_asc_toggled ), IPREFS_ORDER_ALPHA_ASCENDING );
667 }
668 
669 static void
order_mode_on_alpha_desc_toggled(GtkToggleButton * toggle_button,NactPreferencesEditor * editor)670 order_mode_on_alpha_desc_toggled( GtkToggleButton *toggle_button, NactPreferencesEditor *editor )
671 {
672 	order_mode_on_toggled( editor, toggle_button, G_CALLBACK( order_mode_on_alpha_desc_toggled ), IPREFS_ORDER_ALPHA_DESCENDING );
673 }
674 
675 static void
order_mode_on_manual_toggled(GtkToggleButton * toggle_button,NactPreferencesEditor * editor)676 order_mode_on_manual_toggled( GtkToggleButton *toggle_button, NactPreferencesEditor *editor )
677 {
678 	order_mode_on_toggled( editor, toggle_button, G_CALLBACK( order_mode_on_manual_toggled ), IPREFS_ORDER_MANUAL );
679 }
680 
681 static void
order_mode_on_toggled(NactPreferencesEditor * editor,GtkToggleButton * toggle_button,GCallback cb,guint order_mode)682 order_mode_on_toggled( NactPreferencesEditor *editor, GtkToggleButton *toggle_button, GCallback cb, guint order_mode )
683 {
684 	gboolean editable;
685 	gboolean active;
686 
687 	editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( toggle_button ), NA_TOGGLE_DATA_EDITABLE ));
688 
689 	if( editable ){
690 		active = gtk_toggle_button_get_active( toggle_button );
691 		if( active ){
692 			editor->private->order_mode = order_mode;
693 		}
694 	} else {
695 		base_gtk_utils_radio_reset_initial_state( GTK_RADIO_BUTTON( toggle_button ), cb );
696 	}
697 }
698 
699 /*
700  * create a root menu
701  */
702 static void
root_menu_setup(NactPreferencesEditor * editor)703 root_menu_setup( NactPreferencesEditor *editor )
704 {
705 	gboolean editable;
706 
707 	editor->private->root_menu = na_settings_get_boolean( NA_IPREFS_ITEMS_CREATE_ROOT_MENU, NULL, &editor->private->root_menu_mandatory );
708 	editable = !editor->private->preferences_locked && !editor->private->root_menu_mandatory;
709 
710 	base_gtk_utils_toggle_set_initial_state( BASE_WINDOW( editor ),
711 			"CreateRootMenuButton", G_CALLBACK( root_menu_on_toggled ),
712 			editor->private->root_menu, editable, !editor->private->preferences_locked );
713 }
714 
715 static void
root_menu_on_toggled(GtkToggleButton * button,NactPreferencesEditor * editor)716 root_menu_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor )
717 {
718 	gboolean editable;
719 
720 	editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
721 
722 	if( editable ){
723 		editor->private->root_menu = gtk_toggle_button_get_active( button );
724 		about_item_set_sensitive( editor );
725 
726 	} else {
727 		base_gtk_utils_toggle_reset_initial_state( button );
728 	}
729 }
730 
731 /*
732  * add an about item
733  *
734  * The About item is only added if the Nautilus-Actions root menu exists
735  */
736 static void
about_item_setup(NactPreferencesEditor * editor)737 about_item_setup( NactPreferencesEditor *editor )
738 {
739 	gboolean editable;
740 
741 	editor->private->about_item = na_settings_get_boolean( NA_IPREFS_ITEMS_ADD_ABOUT_ITEM, NULL, &editor->private->about_item_mandatory );
742 	editable = !editor->private->preferences_locked && !editor->private->about_item_mandatory;
743 
744 	base_gtk_utils_toggle_set_initial_state( BASE_WINDOW( editor ),
745 			"AddAboutButton", G_CALLBACK( about_item_on_toggled ),
746 			editor->private->about_item, editable, !editor->private->preferences_locked );
747 
748 	about_item_set_sensitive( editor );
749 }
750 
751 static void
about_item_set_sensitive(NactPreferencesEditor * editor)752 about_item_set_sensitive( NactPreferencesEditor *editor )
753 {
754 	GtkWidget *add_about;
755 
756 	add_about = base_window_get_widget( BASE_WINDOW( editor ), "AddAboutButton" );
757 	gtk_widget_set_sensitive( add_about, editor->private->root_menu );
758 }
759 
760 static void
about_item_on_toggled(GtkToggleButton * button,NactPreferencesEditor * editor)761 about_item_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor )
762 {
763 	gboolean editable;
764 
765 	editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
766 
767 	if( editable ){
768 		editor->private->about_item = gtk_toggle_button_get_active( button );
769 
770 	} else {
771 		base_gtk_utils_toggle_reset_initial_state( button );
772 	}
773 }
774 
775 /*
776  * terminal command
777  * the command when execution mode is 'Terminal'
778  * should have a 'COMMAND' keyword inside
779  */
780 static void
terminal_pattern_setup(NactPreferencesEditor * editor)781 terminal_pattern_setup( NactPreferencesEditor *editor )
782 {
783 	gboolean editable;
784 	GtkWidget *entry;
785 
786 	editor->private->terminal_pattern = na_settings_get_string( NA_IPREFS_TERMINAL_PATTERN, NULL, &editor->private->terminal_pattern_mandatory );
787 	editable = !editor->private->preferences_locked && !editor->private->terminal_pattern_mandatory;
788 
789 	entry = base_window_get_widget( BASE_WINDOW( editor ), "TerminalPrefixEntry" );
790 	gtk_entry_set_text( GTK_ENTRY( entry ), editor->private->terminal_pattern );
791 	gtk_widget_set_sensitive( entry, !editor->private->preferences_locked );
792 	base_gtk_utils_set_editable( G_OBJECT( entry ), editable );
793 
794 	terminal_pattern_on_changed( GTK_ENTRY( entry ), editor );
795 
796 	base_window_signal_connect( BASE_WINDOW( editor ),
797 			G_OBJECT( entry ), "changed", G_CALLBACK( terminal_pattern_on_changed ));
798 }
799 
800 static void
terminal_pattern_on_changed(GtkEntry * entry,NactPreferencesEditor * editor)801 terminal_pattern_on_changed( GtkEntry *entry, NactPreferencesEditor *editor )
802 {
803 	gboolean editable;
804 	gchar *example_label;
805 	gchar *example_markup;
806 	GtkWidget *example_widget;
807 
808 	editable = !editor->private->preferences_locked && !editor->private->terminal_pattern_mandatory;
809 
810 	if( editable ){
811 		g_free( editor->private->terminal_pattern );
812 		editor->private->terminal_pattern = g_strdup( gtk_entry_get_text( entry ));
813 
814 		example_widget = base_window_get_widget( BASE_WINDOW( editor ), "TerminalPrefixExample" );
815 		example_label = na_tokens_command_for_terminal( editor->private->terminal_pattern, "ls -l" );
816 
817 		/* i18n: command-line example: Ex.: gnome-terminal -c "ls -l" */
818 		example_markup = g_markup_printf_escaped(
819 				"<i><b><span size=\"small\">%s %s</span></b></i>", _( "Ex.:" ), example_label );
820 
821 		gtk_label_set_label( GTK_LABEL( example_widget ), example_markup );
822 
823 		g_free( example_label );
824 		g_free( example_markup );
825 	}
826 }
827 
828 /*
829  * desktop environment
830  * for OnlyShowIn and NotshowIn contexts
831  */
832 static void
desktop_create_model(NactPreferencesEditor * editor)833 desktop_create_model( NactPreferencesEditor *editor )
834 {
835 	GtkWidget *combo;
836 	GtkListStore *model;
837 	GtkCellRenderer *text_cell;
838 	const NADesktopEnv *desktops;
839 	guint i;
840 	GtkTreeIter row;
841 
842 	combo = base_window_get_widget( BASE_WINDOW( editor ), "DesktopComboBox" );
843 	model = gtk_list_store_new( DESKTOP_N_COLUMN, G_TYPE_STRING, G_TYPE_STRING );
844 	gtk_combo_box_set_model( GTK_COMBO_BOX( combo ), GTK_TREE_MODEL( model ));
845 	g_object_unref( model );
846 
847 	/* id */
848 	text_cell = gtk_cell_renderer_text_new();
849 	gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( combo ), text_cell, FALSE );
850 	gtk_cell_layout_set_attributes( GTK_CELL_LAYOUT( combo ), text_cell, "text", 0, NULL );
851 	gtk_cell_renderer_set_visible( GTK_CELL_RENDERER( text_cell ), FALSE );
852 
853 	/* label */
854 	text_cell = gtk_cell_renderer_text_new();
855 	gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( combo ), text_cell, TRUE );
856 	gtk_cell_layout_set_attributes( GTK_CELL_LAYOUT( combo ), text_cell, "text", 0, NULL );
857 	gtk_cell_renderer_set_visible( GTK_CELL_RENDERER( text_cell ), TRUE );
858 
859 	/* insert the "rely on runtime detection item"
860 	 * this item must be inserted first (see desktop_setup())
861 	 */
862 	gtk_list_store_append( model, &row );
863 	gtk_list_store_set( model, &row,
864 			DESKTOP_ID_COLUMN, st_no_desktop.id,
865 			DESKTOP_LABEL_COLUMN, gettext( st_no_desktop.label ),
866 			-1 );
867 
868 	/* insert list of known desktops
869 	 */
870 	desktops = na_desktop_environment_get_known_list();
871 	for( i = 0 ; desktops[i].id ; ++i ){
872 		gtk_list_store_append( model, &row );
873 		gtk_list_store_set( model, &row,
874 				DESKTOP_ID_COLUMN, desktops[i].id,
875 				DESKTOP_LABEL_COLUMN, gettext( desktops[i].label ),
876 				-1 );
877 	}
878 }
879 
880 static void
desktop_setup(NactPreferencesEditor * editor)881 desktop_setup( NactPreferencesEditor *editor )
882 {
883 	GtkWidget *combo;
884 	const NADesktopEnv *desktops;
885 	guint i;
886 	gint found;
887 	GtkWidget *widget;
888 	const gchar *desktop_id;
889 	const gchar *desktop_label;
890 
891 	found = -1;
892 	editor->private->desktop = na_settings_get_string( NA_IPREFS_DESKTOP_ENVIRONMENT, NULL, &editor->private->desktop_mandatory );
893 
894 	if( editor->private->desktop && strlen( editor->private->desktop )){
895 		desktops = na_desktop_environment_get_known_list();
896 		for( i = 0 ; desktops[i].id && found == -1 ; ++i ){
897 			if( !strcmp( desktops[i].id, editor->private->desktop )){
898 				found = 1+i;
899 			}
900 		}
901 	}
902 
903 	/* if the user has not selected a "preferred" desktop,
904 	 * we suppose he relies on runtime detection
905 	 */
906 	if( found == -1 ){
907 		found = 0;
908 	}
909 
910 	combo = base_window_get_widget( BASE_WINDOW( editor ), "DesktopComboBox" );
911 	gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), found );
912 
913 	base_window_signal_connect(
914 			BASE_WINDOW( editor ),
915 			G_OBJECT( combo ), "changed",
916 			G_CALLBACK( desktop_on_changed ));
917 
918 	/* set the currently detected desktop
919 	 */
920 	widget = base_window_get_widget( BASE_WINDOW( editor ), "DesktopLabel" );
921 	desktop_id = na_desktop_environment_detect_running_desktop();
922 	desktop_label = na_desktop_environment_get_label( desktop_id );
923 	gtk_label_set_text( GTK_LABEL( widget ), desktop_label );
924 }
925 
926 static void
desktop_on_changed(GtkComboBox * combo,NactPreferencesEditor * editor)927 desktop_on_changed( GtkComboBox *combo, NactPreferencesEditor *editor )
928 {
929 	gboolean editable;
930 	gint active;
931 	const NADesktopEnv *desktops;
932 
933 	editable = !editor->private->preferences_locked && !editor->private->desktop_mandatory;
934 
935 	if( editable ){
936 		g_free( editor->private->desktop );
937 		editor->private->desktop = NULL;
938 
939 		active = gtk_combo_box_get_active( combo );
940 		if( active > 0 ){
941 			desktops = na_desktop_environment_get_known_list();
942 			editor->private->desktop = g_strdup( desktops[active-1].id );
943 		}
944 	}
945 }
946 
947 /*
948  * relabel copied/paster menu ?
949  */
950 static void
relabel_menu_setup(NactPreferencesEditor * editor)951 relabel_menu_setup( NactPreferencesEditor *editor )
952 {
953 	gboolean editable;
954 
955 	editor->private->relabel_menu = na_settings_get_boolean( NA_IPREFS_RELABEL_DUPLICATE_MENU, NULL, &editor->private->relabel_menu_mandatory );
956 	editable = !editor->private->preferences_locked && !editor->private->relabel_menu_mandatory;
957 
958 	base_gtk_utils_toggle_set_initial_state( BASE_WINDOW( editor ),
959 			"RelabelMenuButton", G_CALLBACK( relabel_menu_on_toggled ),
960 			editor->private->relabel_menu, editable, !editor->private->preferences_locked );
961 }
962 
963 static void
relabel_menu_on_toggled(GtkToggleButton * button,NactPreferencesEditor * editor)964 relabel_menu_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor )
965 {
966 	gboolean editable;
967 
968 	editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
969 
970 	if( editable ){
971 		editor->private->relabel_menu = gtk_toggle_button_get_active( button );
972 
973 	} else {
974 		base_gtk_utils_toggle_reset_initial_state( button );
975 	}
976 }
977 
978 /*
979  * add an about item
980  */
981 static void
relabel_action_setup(NactPreferencesEditor * editor)982 relabel_action_setup( NactPreferencesEditor *editor )
983 {
984 	gboolean editable;
985 
986 	editor->private->relabel_action = na_settings_get_boolean( NA_IPREFS_RELABEL_DUPLICATE_ACTION, NULL, &editor->private->relabel_action_mandatory );
987 	editable = !editor->private->preferences_locked && !editor->private->relabel_action_mandatory;
988 
989 	base_gtk_utils_toggle_set_initial_state( BASE_WINDOW( editor ),
990 			"RelabelActionButton", G_CALLBACK( relabel_action_on_toggled ),
991 			editor->private->relabel_action, editable, !editor->private->preferences_locked );
992 }
993 
994 static void
relabel_action_on_toggled(GtkToggleButton * button,NactPreferencesEditor * editor)995 relabel_action_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor )
996 {
997 	gboolean editable;
998 
999 	editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
1000 
1001 	if( editable ){
1002 		editor->private->relabel_action = gtk_toggle_button_get_active( button );
1003 
1004 	} else {
1005 		base_gtk_utils_toggle_reset_initial_state( button );
1006 	}
1007 }
1008 
1009 /*
1010  * add an about item
1011  */
1012 static void
relabel_profile_setup(NactPreferencesEditor * editor)1013 relabel_profile_setup( NactPreferencesEditor *editor )
1014 {
1015 	gboolean editable;
1016 
1017 	editor->private->relabel_profile = na_settings_get_boolean( NA_IPREFS_RELABEL_DUPLICATE_PROFILE, NULL, &editor->private->relabel_profile_mandatory );
1018 	editable = !editor->private->preferences_locked && !editor->private->relabel_profile_mandatory;
1019 
1020 	base_gtk_utils_toggle_set_initial_state( BASE_WINDOW( editor ),
1021 			"RelabelProfileButton", G_CALLBACK( relabel_profile_on_toggled ),
1022 			editor->private->relabel_profile, editable, !editor->private->preferences_locked );
1023 }
1024 
1025 static void
relabel_profile_on_toggled(GtkToggleButton * button,NactPreferencesEditor * editor)1026 relabel_profile_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor )
1027 {
1028 	gboolean editable;
1029 
1030 	editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
1031 
1032 	if( editable ){
1033 		editor->private->relabel_profile = gtk_toggle_button_get_active( button );
1034 
1035 	} else {
1036 		base_gtk_utils_toggle_reset_initial_state( button );
1037 	}
1038 }
1039 
1040 /*
1041  * whether Esc key quits the assistants
1042  */
1043 static void
esc_quit_setup(NactPreferencesEditor * editor)1044 esc_quit_setup( NactPreferencesEditor *editor )
1045 {
1046 	gboolean editable;
1047 
1048 	editor->private->esc_quit = na_settings_get_boolean( NA_IPREFS_ASSISTANT_ESC_QUIT, NULL, &editor->private->esc_quit_mandatory );
1049 	editable = !editor->private->preferences_locked && !editor->private->esc_quit_mandatory;
1050 
1051 	base_gtk_utils_toggle_set_initial_state( BASE_WINDOW( editor ),
1052 			"EscCloseButton", G_CALLBACK( esc_quit_on_toggled ),
1053 			editor->private->esc_quit, editable, !editor->private->preferences_locked );
1054 }
1055 
1056 static void
esc_quit_on_toggled(GtkToggleButton * button,NactPreferencesEditor * editor)1057 esc_quit_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor )
1058 {
1059 	gboolean editable;
1060 	GtkWidget *confirm_button;
1061 
1062 	editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
1063 
1064 	if( editable ){
1065 		editor->private->esc_quit = gtk_toggle_button_get_active( button );
1066 		confirm_button = base_window_get_widget( BASE_WINDOW( editor ), "EscConfirmButton" );
1067 		gtk_widget_set_sensitive( confirm_button, editor->private->esc_quit );
1068 
1069 	} else {
1070 		base_gtk_utils_toggle_reset_initial_state( button );
1071 	}
1072 }
1073 
1074 /*
1075  * whether we should ask for a user confirmation when quitting an assistant
1076  * on 'Esc' key
1077  */
1078 static void
esc_confirm_setup(NactPreferencesEditor * editor)1079 esc_confirm_setup( NactPreferencesEditor *editor )
1080 {
1081 	gboolean editable;
1082 
1083 	editor->private->esc_confirm = na_settings_get_boolean( NA_IPREFS_ASSISTANT_ESC_CONFIRM, NULL, &editor->private->esc_confirm_mandatory );
1084 	editable = !editor->private->preferences_locked && !editor->private->esc_confirm_mandatory;
1085 
1086 	base_gtk_utils_toggle_set_initial_state( BASE_WINDOW( editor ),
1087 			"EscConfirmButton", G_CALLBACK( esc_confirm_on_toggled ),
1088 			editor->private->esc_confirm, editable, !editor->private->preferences_locked );
1089 }
1090 
1091 static void
esc_confirm_on_toggled(GtkToggleButton * button,NactPreferencesEditor * editor)1092 esc_confirm_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor )
1093 {
1094 	gboolean editable;
1095 
1096 	editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
1097 
1098 	if( editable ){
1099 		editor->private->esc_confirm = gtk_toggle_button_get_active( button );
1100 
1101 	} else {
1102 		base_gtk_utils_toggle_reset_initial_state( button );
1103 	}
1104 }
1105 
1106 /*
1107  * add an about item
1108  */
1109 static void
auto_save_setup(NactPreferencesEditor * editor)1110 auto_save_setup( NactPreferencesEditor *editor )
1111 {
1112 	gboolean editable;
1113 	GtkWidget *spin_button;
1114 	GtkAdjustment *adjustment;
1115 
1116 	g_debug( "nact_preferences_editor_auto_save_setup" );
1117 	editor->private->auto_save = na_settings_get_boolean( NA_IPREFS_MAIN_SAVE_AUTO, NULL, &editor->private->auto_save_mandatory );
1118 	editable = !editor->private->preferences_locked && !editor->private->auto_save_mandatory;
1119 
1120 	editor->private->auto_save_period = na_settings_get_uint( NA_IPREFS_MAIN_SAVE_PERIOD, NULL, &editor->private->auto_save_period_mandatory );
1121 	spin_button = base_window_get_widget( BASE_WINDOW( editor ), "AutoSavePeriodicitySpinButton" );
1122 	adjustment = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON( spin_button ));
1123 	gtk_adjustment_configure( adjustment, editor->private->auto_save_period, 1, 999, 1, 10, 0 );
1124 
1125 	editable = !editor->private->preferences_locked && !editor->private->auto_save_period_mandatory;
1126 	gtk_editable_set_editable( GTK_EDITABLE( spin_button ), editable );
1127 	base_window_signal_connect( BASE_WINDOW( editor ),
1128 			G_OBJECT( spin_button ), "value-changed", G_CALLBACK( auto_save_period_on_change_value ));
1129 
1130 	editable = !editor->private->preferences_locked && !editor->private->auto_save_mandatory;
1131 	base_gtk_utils_toggle_set_initial_state( BASE_WINDOW( editor ),
1132 			"AutoSaveCheckButton", G_CALLBACK( auto_save_on_toggled ),
1133 			editor->private->auto_save, editable, !editor->private->preferences_locked );
1134 }
1135 
1136 static void
auto_save_on_toggled(GtkToggleButton * button,NactPreferencesEditor * editor)1137 auto_save_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor )
1138 {
1139 	gboolean editable;
1140 	GtkWidget *widget;
1141 	gboolean sensitive;
1142 
1143 	editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
1144 
1145 	if( editable ){
1146 		editor->private->auto_save = gtk_toggle_button_get_active( button );
1147 
1148 	} else {
1149 		base_gtk_utils_toggle_reset_initial_state( button );
1150 	}
1151 
1152 	sensitive = editor->private->auto_save && !editor->private->preferences_locked;
1153 
1154 	widget = base_window_get_widget( BASE_WINDOW( editor ), "AutoSavePeriodicitySpinButton" );
1155 	gtk_widget_set_sensitive( widget, sensitive );
1156 
1157 	widget = base_window_get_widget( BASE_WINDOW( editor ), "AutoSaveLabel1" );
1158 	gtk_widget_set_sensitive( widget, sensitive  );
1159 
1160 	widget = base_window_get_widget( BASE_WINDOW( editor ), "AutoSaveLabel2" );
1161 	gtk_widget_set_sensitive( widget, sensitive  );
1162 }
1163 
1164 static void
auto_save_period_on_change_value(GtkSpinButton * spinbutton,NactPreferencesEditor * editor)1165 auto_save_period_on_change_value( GtkSpinButton *spinbutton, NactPreferencesEditor *editor )
1166 {
1167 	g_debug( "nact_preferences_editor_auto_save_period_on_change_value" );
1168 	editor->private->auto_save_period = gtk_spin_button_get_value_as_int( spinbutton );
1169 }
1170 
1171 static void
on_cancel_clicked(GtkButton * button,NactPreferencesEditor * editor)1172 on_cancel_clicked( GtkButton *button, NactPreferencesEditor *editor )
1173 {
1174 	GtkWindow *toplevel = base_window_get_gtk_toplevel( BASE_WINDOW( editor ));
1175 	gtk_dialog_response( GTK_DIALOG( toplevel ), GTK_RESPONSE_CLOSE );
1176 }
1177 
1178 static void
on_ok_clicked(GtkButton * button,NactPreferencesEditor * editor)1179 on_ok_clicked( GtkButton *button, NactPreferencesEditor *editor )
1180 {
1181 	GtkWindow *toplevel = base_window_get_gtk_toplevel( BASE_WINDOW( editor ));
1182 	gtk_dialog_response( GTK_DIALOG( toplevel ), GTK_RESPONSE_OK );
1183 }
1184 
1185 static void
on_dialog_ok(BaseDialog * dialog)1186 on_dialog_ok( BaseDialog *dialog )
1187 {
1188 	NactPreferencesEditor *editor;
1189 	GtkWidget *container;
1190 	NAIOption *option;
1191 	gchar *import_mode;
1192 	gchar *export_format;
1193 
1194 	g_return_if_fail( NACT_IS_PREFERENCES_EDITOR( dialog ));
1195 
1196 	editor = NACT_PREFERENCES_EDITOR( dialog );
1197 
1198 	if( !editor->private->preferences_locked ){
1199 
1200 		/* first tab: runtime preferences
1201 		 */
1202 		if( !editor->private->order_mode_mandatory ){
1203 			na_iprefs_set_order_mode( editor->private->order_mode );
1204 		}
1205 		if( !editor->private->root_menu_mandatory ){
1206 			na_settings_set_boolean( NA_IPREFS_ITEMS_CREATE_ROOT_MENU, editor->private->root_menu );
1207 		}
1208 		if( !editor->private->about_item_mandatory ){
1209 			na_settings_set_boolean( NA_IPREFS_ITEMS_ADD_ABOUT_ITEM, editor->private->about_item );
1210 		}
1211 
1212 		/* second tab: runtime execution
1213 		 */
1214 		if( !editor->private->terminal_pattern_mandatory ){
1215 			na_settings_set_string( NA_IPREFS_TERMINAL_PATTERN, editor->private->terminal_pattern );
1216 		}
1217 		if( !editor->private->desktop_mandatory ){
1218 			na_settings_set_string( NA_IPREFS_DESKTOP_ENVIRONMENT, editor->private->desktop );
1219 		}
1220 
1221 		/* third tab: ui preferences
1222 		 */
1223 		if( !editor->private->relabel_menu_mandatory ){
1224 			na_settings_set_boolean( NA_IPREFS_RELABEL_DUPLICATE_MENU, editor->private->relabel_menu );
1225 		}
1226 		if( !editor->private->relabel_action_mandatory ){
1227 			na_settings_set_boolean( NA_IPREFS_RELABEL_DUPLICATE_ACTION, editor->private->relabel_action );
1228 		}
1229 		if( !editor->private->relabel_profile_mandatory ){
1230 			na_settings_set_boolean( NA_IPREFS_RELABEL_DUPLICATE_PROFILE, editor->private->relabel_profile );
1231 		}
1232 		if( !editor->private->esc_quit_mandatory ){
1233 			na_settings_set_boolean( NA_IPREFS_ASSISTANT_ESC_QUIT, editor->private->esc_quit );
1234 		}
1235 		if( !editor->private->esc_confirm_mandatory ){
1236 			na_settings_set_boolean( NA_IPREFS_ASSISTANT_ESC_CONFIRM, editor->private->esc_confirm );
1237 		}
1238 		if( !editor->private->auto_save_mandatory ){
1239 			na_settings_set_boolean( NA_IPREFS_MAIN_SAVE_AUTO, editor->private->auto_save );
1240 		}
1241 		if( !editor->private->auto_save_period_mandatory ){
1242 			na_settings_set_uint( NA_IPREFS_MAIN_SAVE_PERIOD, editor->private->auto_save_period );
1243 		}
1244 
1245 		/* fourth tab: import mode
1246 		 */
1247 		if( !editor->private->import_mode_mandatory ){
1248 			container = base_window_get_widget( BASE_WINDOW( editor ), "PreferencesImportModeVBox" );
1249 			option = na_ioptions_list_get_selected( NA_IOPTIONS_LIST( editor ), container );
1250 			g_return_if_fail( NA_IS_IMPORT_MODE( option ));
1251 			import_mode = na_ioption_get_id( option );
1252 			na_settings_set_string( NA_IPREFS_IMPORT_PREFERRED_MODE, import_mode );
1253 			g_free( import_mode );
1254 		}
1255 
1256 		/* fifth tab: export format
1257 		 */
1258 		if( !editor->private->export_format_mandatory ){
1259 			container = base_window_get_widget( BASE_WINDOW( editor ), "PreferencesExportFormatVBox" );
1260 			option = na_ioptions_list_get_selected( NA_IOPTIONS_LIST( editor ), container );
1261 			g_debug( "nact_preferences_editor_on_dialog_ok: option=%p", ( void * ) option );
1262 			g_return_if_fail( NA_IS_EXPORT_FORMAT( option ));
1263 			export_format = na_ioption_get_id( option );
1264 			na_settings_set_string( NA_IPREFS_EXPORT_PREFERRED_FORMAT, export_format );
1265 			g_free( export_format );
1266 		}
1267 
1268 		/* sixth tab: list of default schemes
1269 		 */
1270 		nact_schemes_list_save_defaults( BASE_WINDOW( editor ));
1271 
1272 		/* seventh tab: priorities of I/O providers
1273 		 */
1274 		nact_providers_list_save( BASE_WINDOW( editor ));
1275 	}
1276 }
1277