3 * A Nautilus extension which offers configurable context menu actions.
5 * Copyright (C) 2005 The GNOME Foundation
6 * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
7 * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS)
9 * This Program 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.
14 * This Program 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
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public
20 * License along with this Library; see the file COPYING. If not,
21 * write to the Free Software Foundation, Inc., 59 Temple Place,
22 * Suite 330, Boston, MA 02111-1307, USA.
25 * Frederic Ruaudel <grumz@grumz.net>
26 * Rodrigo Moya <rodrigo@gnome-db.org>
27 * Pierre Wieser <pwieser@trychlos.org>
28 * ... and many others (see AUTHORS)
35 #include <glib/gi18n.h>
37 #include <api/na-core-utils.h>
38 #include <api/na-gconf-utils.h>
39 #include <api/na-object-api.h>
41 #include <core/na-io-provider.h>
42 #include <core/na-iprefs.h>
44 #include "nact-application.h"
45 #include "base-gtk-utils.h"
46 #include "nact-providers-list.h"
51 PROVIDER_READABLE_COLUMN
= 0,
52 PROVIDER_READABLE_MANDATORY_COLUMN
,
53 PROVIDER_WRITABLE_COLUMN
,
54 PROVIDER_WRITABLE_MANDATORY_COLUMN
,
55 PROVIDER_LIBELLE_COLUMN
,
57 PROVIDER_PROVIDER_COLUMN
,
61 /* data attached to the treeview widget on gtk toplevel initialization
62 * at this time, only treeview is set
63 * at base window initialization time, the current window is associated
66 /* set when creating the model (on_initialize_gtk_toplevel)
68 GtkTreeView
*treeview
;
70 /* set when initializing the view (on_initialize_base_window)
73 gboolean preferences_locked
;
78 /* some data needed when saving the list store
83 ProvidersListSaveData
;
85 #define PROVIDERS_LIST_DATA "nact-providers-list-data"
86 #define PROVIDERS_LIST_TREEVIEW "nact-providers-list-treeview"
88 static gboolean st_on_selection_change
= FALSE
;
90 static void init_view_setup_providers( GtkTreeView
*treeview
, BaseWindow
*window
);
91 static void init_view_connect_signals( GtkTreeView
*treeview
, BaseWindow
*window
);
92 static void init_view_select_first_row( GtkTreeView
*treeview
);
94 static gboolean
providers_list_save_iter( GtkTreeModel
*model
, GtkTreePath
*path
, GtkTreeIter
* iter
, ProvidersListSaveData
*plsd
);
96 static void on_selection_changed( GtkTreeSelection
*selection
, BaseWindow
*window
);
97 static void on_readable_toggled( GtkCellRendererToggle
*renderer
, gchar
*path
, BaseWindow
*window
);
98 static void on_writable_toggled( GtkCellRendererToggle
*renderer
, gchar
*path
, BaseWindow
*window
);
99 static void on_up_clicked( GtkButton
*button
, BaseWindow
*window
);
100 static void on_down_clicked( GtkButton
*button
, BaseWindow
*window
);
102 static void display_label( GtkTreeViewColumn
*column
, GtkCellRenderer
*cell
, GtkTreeModel
*model
, GtkTreeIter
*iter
, ProvidersListData
*data
);
103 static GtkButton
*get_up_button( BaseWindow
*window
);
104 static GtkButton
*get_down_button( BaseWindow
*window
);
105 static ProvidersListData
*get_providers_list_data( GtkTreeView
*treeview
);
108 * nact_providers_list_create_model:
109 * @treeview: the #GtkTreeView.
111 * Create the treeview model when initially loading the widget from
115 nact_providers_list_create_model( GtkTreeView
*treeview
)
117 static const char *thisfn
= "nact_providers_list_create_model";
119 GtkCellRenderer
*toggled_cell
;
120 GtkTreeViewColumn
*column
;
121 GtkCellRenderer
*text_cell
;
122 GtkTreeSelection
*selection
;
123 ProvidersListData
*data
;
125 g_return_if_fail( GTK_IS_TREE_VIEW( treeview
));
127 g_debug( "%s: treeview=%p", thisfn
, ( void * ) treeview
);
129 data
= get_providers_list_data( treeview
);
131 model
= gtk_list_store_new( PROVIDER_N_COLUMN
,
132 G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
, G_TYPE_STRING
, G_TYPE_STRING
, G_TYPE_OBJECT
);
133 gtk_tree_view_set_model( treeview
, GTK_TREE_MODEL( model
));
134 g_object_unref( model
);
137 toggled_cell
= gtk_cell_renderer_toggle_new();
138 column
= gtk_tree_view_column_new_with_attributes(
141 "active", PROVIDER_READABLE_COLUMN
,
143 gtk_tree_view_append_column( treeview
, column
);
145 /* readable mandatory */
146 column
= gtk_tree_view_column_new();
147 gtk_tree_view_append_column( treeview
, column
);
148 gtk_tree_view_column_set_visible( column
, FALSE
);
151 toggled_cell
= gtk_cell_renderer_toggle_new();
152 column
= gtk_tree_view_column_new_with_attributes(
155 "active", PROVIDER_WRITABLE_COLUMN
,
157 gtk_tree_view_append_column( treeview
, column
);
159 /* writable mandatory */
160 column
= gtk_tree_view_column_new();
161 gtk_tree_view_append_column( treeview
, column
);
162 gtk_tree_view_column_set_visible( column
, FALSE
);
165 text_cell
= gtk_cell_renderer_text_new();
166 column
= gtk_tree_view_column_new_with_attributes(
169 "text", PROVIDER_LIBELLE_COLUMN
,
171 gtk_tree_view_column_set_cell_data_func( column
, text_cell
, ( GtkTreeCellDataFunc
) display_label
, data
, NULL
);
172 gtk_tree_view_append_column( treeview
, column
);
175 column
= gtk_tree_view_column_new();
176 gtk_tree_view_append_column( treeview
, column
);
177 gtk_tree_view_column_set_visible( column
, FALSE
);
180 column
= gtk_tree_view_column_new();
181 gtk_tree_view_append_column( treeview
, column
);
182 gtk_tree_view_column_set_visible( column
, FALSE
);
184 gtk_tree_view_set_headers_visible( treeview
, TRUE
);
186 selection
= gtk_tree_view_get_selection( treeview
);
187 gtk_tree_selection_set_mode( selection
, GTK_SELECTION_BROWSE
);
191 * nact_providers_list_init_view:
192 * @window: the parent #BaseWindow which embeds the view.
193 * @treeview: the #GtkTreeView.
195 * Connects signals at runtime initialization of the widget, and setup
196 * current default values.
199 nact_providers_list_init_view( BaseWindow
*window
, GtkTreeView
*treeview
)
201 static const gchar
*thisfn
= "nact_providers_list_init_view";
202 ProvidersListData
*data
;
203 NactApplication
*application
;
206 g_return_if_fail( BASE_IS_WINDOW( window
));
207 g_return_if_fail( GTK_IS_TREE_VIEW( treeview
));
209 g_debug( "%s: treeview=%p, window=%p", thisfn
, ( void * ) treeview
, ( void * ) window
);
211 g_object_set_data( G_OBJECT( window
), PROVIDERS_LIST_TREEVIEW
, treeview
);
213 data
= get_providers_list_data( treeview
);
214 data
->window
= window
;
215 application
= NACT_APPLICATION( base_window_get_application( window
));
216 updater
= nact_application_get_updater( application
);
217 data
->preferences_locked
= na_updater_are_preferences_locked( updater
);
219 init_view_setup_providers( treeview
, window
);
220 init_view_connect_signals( treeview
, window
);
222 init_view_select_first_row( treeview
);
226 init_view_setup_providers( GtkTreeView
*treeview
, BaseWindow
*window
)
228 static const gchar
*thisfn
= "nact_providers_list_init_view_setup_providers";
229 NactApplication
*application
;
232 const GList
*providers
;
236 gboolean readable
, readable_mandatory
;
237 gboolean writable
, writable_mandatory
;
238 NAIOProvider
*provider
;
240 model
= GTK_LIST_STORE( gtk_tree_view_get_model( treeview
));
242 application
= NACT_APPLICATION( base_window_get_application( window
));
243 updater
= nact_application_get_updater( application
);
244 providers
= na_io_provider_get_io_providers_list( NA_PIVOT( updater
));
246 for( iter
= providers
; iter
; iter
= iter
->next
){
247 provider
= NA_IO_PROVIDER( iter
->data
);
248 id
= na_io_provider_get_id( provider
);
249 libelle
= na_io_provider_get_name( provider
);
250 readable
= na_io_provider_is_conf_readable( provider
, NA_PIVOT( updater
), &readable_mandatory
);
251 writable
= na_io_provider_is_conf_writable( provider
, NA_PIVOT( updater
), &writable_mandatory
);
253 g_debug( "%s: id=%s, readable=%s (mandatory=%s), writable=%s (mandatory=%s)",
255 readable
? "True":"False", readable_mandatory
? "True":"False",
256 writable
? "True":"False", writable_mandatory
? "True":"False" );
258 if( !libelle
|| !g_utf8_strlen( libelle
, -1 )){
261 if( na_io_provider_is_available( provider
)){
262 /* i18n: default name when the I/O providers doesn't provide one */
263 libelle
= g_strdup_printf( "<%s: %s>", id
, _( "no name" ));
266 /* i18n: name displayed when the corresponding I/O provider is unavailable at runtime */
267 libelle
= g_strdup_printf( "<%s: %s>", id
, _( "unavailable I/O provider" ));
271 gtk_list_store_append( model
, &row
);
272 gtk_list_store_set( model
, &row
,
273 PROVIDER_READABLE_COLUMN
, readable
,
274 PROVIDER_READABLE_MANDATORY_COLUMN
, readable_mandatory
,
275 PROVIDER_WRITABLE_COLUMN
, writable
,
276 PROVIDER_WRITABLE_MANDATORY_COLUMN
, writable_mandatory
,
277 PROVIDER_LIBELLE_COLUMN
, libelle
,
278 PROVIDER_ID_COLUMN
, id
,
279 PROVIDER_PROVIDER_COLUMN
, iter
->data
,
288 init_view_connect_signals( GtkTreeView
*treeview
, BaseWindow
*window
)
290 GtkTreeViewColumn
*column
;
292 GtkButton
*up_button
, *down_button
;
294 column
= gtk_tree_view_get_column( treeview
, PROVIDER_READABLE_COLUMN
);
295 renderers
= gtk_cell_layout_get_cells( GTK_CELL_LAYOUT( column
));
296 base_window_signal_connect(
298 G_OBJECT( renderers
->data
),
300 G_CALLBACK( on_readable_toggled
));
302 column
= gtk_tree_view_get_column( treeview
, PROVIDER_WRITABLE_COLUMN
);
303 renderers
= gtk_cell_layout_get_cells( GTK_CELL_LAYOUT( column
));
304 base_window_signal_connect(
306 G_OBJECT( renderers
->data
),
308 G_CALLBACK( on_writable_toggled
));
310 up_button
= get_up_button( window
);
311 base_window_signal_connect(
313 G_OBJECT( up_button
),
315 G_CALLBACK( on_up_clicked
));
317 down_button
= get_down_button( window
);
318 base_window_signal_connect(
320 G_OBJECT( down_button
),
322 G_CALLBACK( on_down_clicked
));
324 base_window_signal_connect(
326 G_OBJECT( gtk_tree_view_get_selection( treeview
)),
328 G_CALLBACK( on_selection_changed
));
332 init_view_select_first_row( GtkTreeView
*treeview
)
334 GtkTreeSelection
*selection
;
337 path
= gtk_tree_path_new_first();
339 selection
= gtk_tree_view_get_selection( treeview
);
340 gtk_tree_selection_select_path( selection
, path
);
341 gtk_tree_path_free( path
);
346 * nact_providers_list_save:
347 * @window: the #BaseWindow which embeds this treeview.
349 * Save the I/O provider status as a user preference.
352 nact_providers_list_save( BaseWindow
*window
)
354 static const gchar
*thisfn
= "nact_providers_list_save";
355 GtkTreeView
*treeview
;
357 ProvidersListSaveData
*plsd
;
359 g_debug( "%s: window=%p", thisfn
, ( void * ) window
);
361 plsd
= g_new0( ProvidersListSaveData
, 1 );
364 treeview
= GTK_TREE_VIEW( g_object_get_data( G_OBJECT( window
), PROVIDERS_LIST_TREEVIEW
));
365 model
= gtk_tree_view_get_model( treeview
);
366 gtk_tree_model_foreach( model
, ( GtkTreeModelForeachFunc
) providers_list_save_iter
, plsd
);
368 plsd
->order
= g_slist_reverse( plsd
->order
);
369 na_settings_set_string_list( NA_IPREFS_IO_PROVIDERS_WRITE_ORDER
, plsd
->order
);
371 na_core_utils_slist_free( plsd
->order
);
376 providers_list_save_iter( GtkTreeModel
*model
, GtkTreePath
*path
, GtkTreeIter
* iter
, ProvidersListSaveData
*plsd
)
379 gboolean readable
, writable
;
380 NAIOProvider
*provider
;
383 gtk_tree_model_get( model
, iter
,
384 PROVIDER_ID_COLUMN
, &id
,
385 PROVIDER_READABLE_COLUMN
, &readable
,
386 PROVIDER_WRITABLE_COLUMN
, &writable
,
387 PROVIDER_PROVIDER_COLUMN
, &provider
,
390 group
= g_strdup_printf( "%s %s", NA_IPREFS_IO_PROVIDER_GROUP
, id
);
391 na_settings_set_boolean_ex( group
, NA_IPREFS_IO_PROVIDER_READABLE
, readable
);
392 na_settings_set_boolean_ex( group
, NA_IPREFS_IO_PROVIDER_WRITABLE
, writable
);
395 plsd
->order
= g_slist_prepend( plsd
->order
, g_strdup( id
));
397 g_object_unref( provider
);
400 return( FALSE
); /* don't stop looping */
404 * nact_providers_list_dispose:
405 * @treeview: the #GtkTreeView.
407 * Release the content of the page when we are closing the Preferences dialog.
410 nact_providers_list_dispose( BaseWindow
*window
)
412 static const gchar
*thisfn
= "nact_providers_list_dispose";
413 GtkTreeView
*treeview
;
415 GtkTreeSelection
*selection
;
417 g_debug( "%s: window=%p", thisfn
, ( void * ) window
);
419 treeview
= GTK_TREE_VIEW( g_object_get_data( G_OBJECT( window
), PROVIDERS_LIST_TREEVIEW
));
420 model
= gtk_tree_view_get_model( treeview
);
421 selection
= gtk_tree_view_get_selection( treeview
);
423 gtk_tree_selection_unselect_all( selection
);
424 gtk_list_store_clear( GTK_LIST_STORE( model
));
429 * - preferences are not locked
430 * - i/o providers order is not mandatory
433 on_selection_changed( GtkTreeSelection
*selection
, BaseWindow
*window
)
439 gboolean may_up
, may_down
;
440 gboolean order_mandatory
;
442 ProvidersListData
*data
;
443 GtkTreeView
*treeview
;
445 g_debug( "nact_providers_list_on_selection_changed: selection=%p, window=%p (%s)",
446 ( void * ) selection
, ( void * ) window
, G_OBJECT_TYPE_NAME( window
));
451 treeview
= GTK_TREE_VIEW( g_object_get_data( G_OBJECT( window
), PROVIDERS_LIST_TREEVIEW
));
452 data
= get_providers_list_data( treeview
);
454 write_order
= na_settings_get_string_list( NA_IPREFS_IO_PROVIDERS_WRITE_ORDER
, NULL
, &order_mandatory
);
456 if( !data
->preferences_locked
&&
458 gtk_tree_selection_get_selected( selection
, &model
, &iter
)){
460 path
= gtk_tree_model_get_path( model
, &iter
);
461 may_up
= gtk_tree_path_prev( path
);
462 gtk_tree_path_free( path
);
463 may_down
= gtk_tree_model_iter_next( model
, &iter
);
466 button
= get_up_button( window
);
467 gtk_widget_set_sensitive( GTK_WIDGET( button
), may_up
);
469 button
= get_down_button( window
);
470 gtk_widget_set_sensitive( GTK_WIDGET( button
), may_down
);
475 * - preferences are not locked
476 * - readable status is not mandatory
479 on_readable_toggled( GtkCellRendererToggle
*renderer
, gchar
*path_string
, BaseWindow
*window
)
481 static const gchar
*thisfn
= "nact_providers_list_on_readable_toggled";
482 ProvidersListData
*data
;
483 GtkTreeView
*treeview
;
487 gboolean readable_mandatory
;
490 if( !st_on_selection_change
){
492 treeview
= GTK_TREE_VIEW( g_object_get_data( G_OBJECT( window
), PROVIDERS_LIST_TREEVIEW
));
493 model
= gtk_tree_view_get_model( treeview
);
494 if( gtk_tree_model_get_iter_from_string( model
, &iter
, path_string
)){
495 gtk_tree_model_get( model
, &iter
,
496 PROVIDER_READABLE_COLUMN
, &state
,
497 PROVIDER_ID_COLUMN
, &id
,
498 PROVIDER_READABLE_MANDATORY_COLUMN
, &readable_mandatory
,
501 g_debug( "%s: id=%s, readable=%s (mandatory=%s)", thisfn
, id
,
502 state
? "True":"False", readable_mandatory
? "True":"False" );
504 data
= get_providers_list_data( treeview
);
506 if( readable_mandatory
|| data
->preferences_locked
){
507 g_signal_handlers_block_by_func(( gpointer
) renderer
, on_readable_toggled
, window
);
508 state
= gtk_cell_renderer_toggle_get_active( renderer
);
509 gtk_cell_renderer_toggle_set_active( renderer
, !state
);
510 g_signal_handlers_unblock_by_func(( gpointer
) renderer
, on_readable_toggled
, window
);
513 gtk_list_store_set( GTK_LIST_STORE( model
), &iter
, PROVIDER_READABLE_COLUMN
, !state
, -1 );
522 on_writable_toggled( GtkCellRendererToggle
*renderer
, gchar
*path_string
, BaseWindow
*window
)
524 static const gchar
*thisfn
= "nact_providers_list_on_writable_toggled";
525 GtkTreeView
*treeview
;
526 ProvidersListData
*data
;
530 gboolean writable_mandatory
;
533 if( !st_on_selection_change
){
535 treeview
= GTK_TREE_VIEW( g_object_get_data( G_OBJECT( window
), PROVIDERS_LIST_TREEVIEW
));
536 model
= gtk_tree_view_get_model( treeview
);
537 if( gtk_tree_model_get_iter_from_string( model
, &iter
, path_string
)){
538 gtk_tree_model_get( model
, &iter
,
539 PROVIDER_WRITABLE_COLUMN
, &state
,
540 PROVIDER_ID_COLUMN
, &id
,
541 PROVIDER_WRITABLE_MANDATORY_COLUMN
, &writable_mandatory
,
544 g_debug( "%s: id=%s, writable=%s (mandatory=%s)", thisfn
, id
,
545 state
? "True":"False", writable_mandatory
? "True":"False" );
547 data
= get_providers_list_data( treeview
);
549 if( writable_mandatory
|| data
->preferences_locked
){
550 g_signal_handlers_block_by_func(( gpointer
) renderer
, on_writable_toggled
, window
);
551 state
= gtk_cell_renderer_toggle_get_active( renderer
);
552 gtk_cell_renderer_toggle_set_active( renderer
, !state
);
553 g_signal_handlers_unblock_by_func(( gpointer
) renderer
, on_writable_toggled
, window
);
556 gtk_list_store_set( GTK_LIST_STORE( model
), &iter
, PROVIDER_WRITABLE_COLUMN
, !state
, -1 );
566 * - preferences are not locked
567 * - i/o providers order is not mandatory
570 on_up_clicked( GtkButton
*button
, BaseWindow
*window
)
572 GtkTreeView
*treeview
;
573 GtkTreeSelection
*selection
;
575 GtkTreeIter iter_selected
;
576 GtkTreePath
*path_prev
;
577 GtkTreeIter iter_prev
;
579 treeview
= GTK_TREE_VIEW( g_object_get_data( G_OBJECT( window
), PROVIDERS_LIST_TREEVIEW
));
580 selection
= gtk_tree_view_get_selection( treeview
);
581 if( gtk_tree_selection_get_selected( selection
, &model
, &iter_selected
)){
582 path_prev
= gtk_tree_model_get_path( model
, &iter_selected
);
583 if( gtk_tree_path_prev( path_prev
)){
584 if( gtk_tree_model_get_iter( model
, &iter_prev
, path_prev
)){
585 gtk_list_store_move_before( GTK_LIST_STORE( model
), &iter_selected
, &iter_prev
);
586 gtk_tree_selection_unselect_all( selection
);
587 gtk_tree_selection_select_path( selection
, path_prev
);
590 gtk_tree_path_free( path_prev
);
595 on_down_clicked( GtkButton
*button
, BaseWindow
*window
)
597 GtkTreeView
*treeview
;
598 GtkTreeSelection
*selection
;
600 GtkTreeIter iter_selected
;
601 GtkTreeIter
*iter_next
;
602 GtkTreePath
*path_next
;
604 treeview
= GTK_TREE_VIEW( g_object_get_data( G_OBJECT( window
), PROVIDERS_LIST_TREEVIEW
));
605 selection
= gtk_tree_view_get_selection( treeview
);
606 if( gtk_tree_selection_get_selected( selection
, &model
, &iter_selected
)){
607 iter_next
= gtk_tree_iter_copy( &iter_selected
);
608 if( gtk_tree_model_iter_next( model
, iter_next
)){
609 path_next
= gtk_tree_model_get_path( model
, iter_next
);
610 gtk_list_store_move_after( GTK_LIST_STORE( model
), &iter_selected
, iter_next
);
611 gtk_tree_selection_unselect_all( selection
);
612 gtk_tree_selection_select_path( selection
, path_next
);
613 gtk_tree_path_free( path_next
);
615 gtk_tree_iter_free( iter_next
);
620 * unavailable provider: italic grey
623 display_label( GtkTreeViewColumn
*column
, GtkCellRenderer
*cell
, GtkTreeModel
*model
, GtkTreeIter
*iter
, ProvidersListData
*data
)
625 NAIOProvider
*provider
;
628 gtk_tree_model_get( model
, iter
, PROVIDER_LIBELLE_COLUMN
, &name
, PROVIDER_PROVIDER_COLUMN
, &provider
, -1 );
630 g_object_set( cell
, "style-set", FALSE
, NULL
);
631 g_object_set( cell
, "foreground-set", FALSE
, NULL
);
633 if( !na_io_provider_is_available( provider
)){
634 g_object_set( cell
, "style", PANGO_STYLE_ITALIC
, "style-set", TRUE
, NULL
);
635 g_object_set( cell
, "foreground", "grey", "foreground-set", TRUE
, NULL
);
638 g_object_unref( provider
);
640 g_object_set( cell
, "text", name
, NULL
);
642 if( data
->preferences_locked
){
643 g_object_set( cell
, "foreground", "grey", "foreground-set", TRUE
, NULL
);
650 get_up_button( BaseWindow
*window
)
654 button
= GTK_BUTTON( base_window_get_widget( window
, "ProviderButtonUp" ));
660 get_down_button( BaseWindow
*window
)
664 button
= GTK_BUTTON( base_window_get_widget( window
, "ProviderButtonDown" ));
669 static ProvidersListData
*
670 get_providers_list_data( GtkTreeView
*treeview
)
672 ProvidersListData
*data
;
674 data
= ( ProvidersListData
* ) g_object_get_data( G_OBJECT( treeview
), PROVIDERS_LIST_DATA
);
677 data
= g_new0( ProvidersListData
, 1 );
678 g_object_set_data( G_OBJECT( treeview
), PROVIDERS_LIST_DATA
, data
);
679 data
->treeview
= treeview
;