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 "base-keysyms.h"
36 #include "base-iprefs.h"
37 #include "nact-application.h"
38 #include "nact-gtk-utils.h"
39 #include "nact-icon-chooser.h"
43 struct _NactIconChooserClassPrivate
{
44 void *empty
; /* so that gcc -pedantic is happy */
47 /* private instance data
49 struct _NactIconChooserPrivate
{
50 gboolean dispose_has_run
;
51 BaseWindow
*main_window
;
52 const gchar
*initial_icon
;
54 GtkWidget
*path_preview
;
57 #define VIEW_ICON_SIZE GTK_ICON_SIZE_DND
58 #define VIEW_ICON_DEFAULT_WIDTH 32 /* width of the GTK_ICON_SIZE_DND icon size */
59 #define PREVIEW_ICON_SIZE GTK_ICON_SIZE_DIALOG
60 #define PREVIEW_ICON_WIDTH 64
61 #define CURRENT_ICON_SIZE GTK_ICON_SIZE_DIALOG
63 /* column ordering in the Stock model
66 STOCK_NAME_COLUMN
= 0,
72 /* column ordering in the ThemeContext model
73 * this is the list store on the left which lets the user select the context
76 THEME_CONTEXT_LABEL_COLUMN
= 0,
77 THEME_CONTEXT_STORE_COLUMN
,
78 THEME_CONTEXT_LAST_SELECTED_COLUMN
,
79 THEME_CONTEXT_N_COLUMN
82 /* column ordering in the ThemeIconView model
83 * foreach selected context, we display in the icon view the list of
87 THEME_ICON_LABEL_COLUMN
= 0,
88 THEME_ICON_PIXBUF_COLUMN
,
92 static const gchar
*st_xmlui_filename
= PKGDATADIR
"/nact-icon-chooser.ui";
94 static BaseDialogClass
*st_parent_class
= NULL
;
96 static GType
register_type( void );
97 static void class_init( NactIconChooserClass
*klass
);
98 static void instance_init( GTypeInstance
*instance
, gpointer klass
);
99 static void instance_dispose( GObject
*dialog
);
100 static void instance_finalize( GObject
*dialog
);
102 static NactIconChooser
*icon_chooser_new( BaseWindow
*parent
);
104 static gchar
*base_get_iprefs_window_id( const BaseWindow
*window
);
105 static gchar
*base_get_dialog_name( const BaseWindow
*window
);
106 static void on_base_initial_load_dialog( NactIconChooser
*editor
, gpointer user_data
);
107 static void do_initialize_themed_icons( NactIconChooser
*editor
);
108 static void do_initialize_icons_by_path( NactIconChooser
*editor
);
109 static void on_base_runtime_init_dialog( NactIconChooser
*editor
, gpointer user_data
);
110 static void fillup_themed_icons( NactIconChooser
*editor
);
111 static void fillup_icons_by_path( NactIconChooser
*editor
);
112 static void on_base_all_widgets_showed( NactIconChooser
*editor
, gpointer user_data
);
113 static void on_cancel_clicked( GtkButton
*button
, NactIconChooser
*editor
);
114 static void on_ok_clicked( GtkButton
*button
, NactIconChooser
*editor
);
115 static gboolean
base_dialog_response( GtkDialog
*dialog
, gint code
, BaseWindow
*window
);
116 static void on_current_icon_changed( const NactIconChooser
*editor
);
117 static gboolean
on_destroy( GtkWidget
*widget
, GdkEvent
*event
, void *foo
);
118 static gboolean
on_icon_view_button_press_event( GtkWidget
*widget
, GdkEventButton
*event
, NactIconChooser
*editor
);
119 static gboolean
on_key_pressed_event( GtkWidget
*widget
, GdkEventKey
*event
, NactIconChooser
*editor
);
120 static void on_themed_context_changed( GtkTreeSelection
*selection
, NactIconChooser
*editor
);
121 static void on_themed_icon_changed( GtkIconView
*icon_view
, NactIconChooser
*editor
);
122 static void on_themed_apply_button_clicked( GtkButton
*button
, NactIconChooser
*editor
);
123 static void on_themed_apply_triggered( NactIconChooser
*editor
);
124 static void on_path_selection_changed( GtkFileChooser
*chooser
, NactIconChooser
*editor
);
125 static void on_path_update_preview( GtkFileChooser
*chooser
, NactIconChooser
*editor
);
126 static void on_path_apply_button_clicked( GtkButton
*button
, NactIconChooser
*editor
);
127 static GtkListStore
*theme_context_load_icons( NactIconChooser
*editor
, const gchar
*context
);
130 nact_icon_chooser_get_type( void )
132 static GType dialog_type
= 0;
135 dialog_type
= register_type();
138 return( dialog_type
);
142 register_type( void )
144 static const gchar
*thisfn
= "nact_icon_chooser_register_type";
147 static GTypeInfo info
= {
148 sizeof( NactIconChooserClass
),
149 ( GBaseInitFunc
) NULL
,
150 ( GBaseFinalizeFunc
) NULL
,
151 ( GClassInitFunc
) class_init
,
154 sizeof( NactIconChooser
),
156 ( GInstanceInitFunc
) instance_init
159 g_debug( "%s", thisfn
);
161 type
= g_type_register_static( BASE_DIALOG_TYPE
, "NactIconChooser", &info
, 0 );
167 class_init( NactIconChooserClass
*klass
)
169 static const gchar
*thisfn
= "nact_icon_chooser_class_init";
170 GObjectClass
*object_class
;
171 BaseWindowClass
*base_class
;
173 g_debug( "%s: klass=%p", thisfn
, ( void * ) klass
);
175 st_parent_class
= g_type_class_peek_parent( klass
);
177 object_class
= G_OBJECT_CLASS( klass
);
178 object_class
->dispose
= instance_dispose
;
179 object_class
->finalize
= instance_finalize
;
181 klass
->private = g_new0( NactIconChooserClassPrivate
, 1 );
183 base_class
= BASE_WINDOW_CLASS( klass
);
184 base_class
->dialog_response
= base_dialog_response
;
185 base_class
->get_toplevel_name
= base_get_dialog_name
;
186 base_class
->get_iprefs_window_id
= base_get_iprefs_window_id
;
190 instance_init( GTypeInstance
*instance
, gpointer klass
)
192 static const gchar
*thisfn
= "nact_icon_chooser_instance_init";
193 NactIconChooser
*self
;
195 g_return_if_fail( NACT_IS_ICON_CHOOSER( instance
));
197 g_debug( "%s: instance=%p (%s), klass=%p",
198 thisfn
, ( void * ) instance
, G_OBJECT_TYPE_NAME( instance
), ( void * ) klass
);
200 self
= NACT_ICON_CHOOSER( instance
);
202 self
->private = g_new0( NactIconChooserPrivate
, 1 );
204 base_window_signal_connect(
207 BASE_SIGNAL_INITIALIZE_GTK
,
208 G_CALLBACK( on_base_initial_load_dialog
));
210 base_window_signal_connect(
213 BASE_SIGNAL_INITIALIZE_WINDOW
,
214 G_CALLBACK( on_base_runtime_init_dialog
));
216 base_window_signal_connect(
219 BASE_SIGNAL_ALL_WIDGETS_SHOWED
,
220 G_CALLBACK( on_base_all_widgets_showed
));
222 self
->private->dispose_has_run
= FALSE
;
226 instance_dispose( GObject
*dialog
)
228 static const gchar
*thisfn
= "nact_icon_chooser_instance_dispose";
229 NactIconChooser
*self
;
232 NactApplication
*application
;
234 NASettings
*settings
;
236 g_return_if_fail( NACT_IS_ICON_CHOOSER( dialog
));
238 g_debug( "%s: dialog=%p (%s)", thisfn
, ( void * ) dialog
, G_OBJECT_TYPE_NAME( dialog
));
240 self
= NACT_ICON_CHOOSER( dialog
);
242 if( !self
->private->dispose_has_run
){
244 self
->private->dispose_has_run
= TRUE
;
246 application
= NACT_APPLICATION( base_window_get_application( BASE_WINDOW( self
)));
247 updater
= nact_application_get_updater( application
);
248 settings
= na_pivot_get_settings( NA_PIVOT( updater
));
250 paned
= base_window_get_widget( BASE_WINDOW( self
), "IconPaned" );
251 pos
= gtk_paned_get_position( GTK_PANED( paned
));
252 na_settings_set_uint( settings
, NA_IPREFS_ICON_CHOOSER_PANED
, pos
);
254 /* chain up to the parent class */
255 if( G_OBJECT_CLASS( st_parent_class
)->dispose
){
256 G_OBJECT_CLASS( st_parent_class
)->dispose( dialog
);
262 instance_finalize( GObject
*dialog
)
264 static const gchar
*thisfn
= "nact_icon_chooser_instance_finalize";
265 NactIconChooser
*self
;
267 g_return_if_fail( NACT_IS_ICON_CHOOSER( dialog
));
269 g_debug( "%s: dialog=%p", thisfn
, ( void * ) dialog
);
271 self
= NACT_ICON_CHOOSER( dialog
);
273 g_free( self
->private->current_icon
);
275 g_free( self
->private );
277 /* chain call to parent class */
278 if( G_OBJECT_CLASS( st_parent_class
)->finalize
){
279 G_OBJECT_CLASS( st_parent_class
)->finalize( dialog
);
284 * Returns a newly allocated NactIconChooser object.
286 static NactIconChooser
*
287 icon_chooser_new( BaseWindow
*parent
)
289 return( g_object_new( NACT_ICON_CHOOSER_TYPE
,
290 BASE_PROP_PARENT
, parent
,
291 BASE_PROP_XMLUI_FILENAME
, st_xmlui_filename
,
296 * nact_icon_chooser_choose_icon:
297 * @parent: the #BaseWindow parent of this dialog.
298 * @icon_name: the current icon at startup.
300 * Initializes and runs the dialog.
302 * This dialog lets the user choose an icon, either as the name of a
303 * themed icon, or as the path of an image.
305 * Returns: the selected icon, as a new string which should be g_free()
309 nact_icon_chooser_choose_icon( BaseWindow
*parent
, const gchar
*icon_name
)
311 static const gchar
*thisfn
= "nact_icon_chooser_choose_icon";
312 NactIconChooser
*editor
;
315 g_return_val_if_fail( BASE_IS_WINDOW( parent
), NULL
);
317 g_debug( "%s: parent=%p, icon_name=%s", thisfn
, ( void * ) parent
, icon_name
);
319 editor
= icon_chooser_new( parent
);
320 editor
->private->main_window
= parent
;
321 editor
->private->initial_icon
= icon_name
;
323 new_name
= g_strdup( editor
->private->initial_icon
);
325 if( base_window_run( BASE_WINDOW( editor
))){
327 new_name
= g_strdup( editor
->private->current_icon
);
330 g_object_unref( editor
);
336 base_get_iprefs_window_id( const BaseWindow
*window
)
338 return( g_strdup( NA_IPREFS_ICON_CHOOSER_WSP
));
342 base_get_dialog_name( const BaseWindow
*window
)
344 return( g_strdup( "IconChooserDialog" ));
348 on_base_initial_load_dialog( NactIconChooser
*editor
, gpointer user_data
)
350 static const gchar
*thisfn
= "nact_icon_chooser_on_initial_load_dialog";
352 g_return_if_fail( NACT_IS_ICON_CHOOSER( editor
));
354 g_debug( "%s: editor=%p, user_data=%p", thisfn
, ( void * ) editor
, ( void * ) user_data
);
356 /* initialize the notebook
358 do_initialize_themed_icons( editor
);
359 do_initialize_icons_by_path( editor
);
362 * there is here that we are going to release our stores
364 GtkDialog
*dialog
= GTK_DIALOG( base_window_get_gtk_toplevel( BASE_WINDOW( editor
)));
365 g_signal_connect( G_OBJECT( dialog
), "destroy", G_CALLBACK( on_destroy
), NULL
);
369 * initialize the themed icon tab
370 * first, the listview which handles the context list
371 * each context carries a list store which handles the corresponding icons
372 * this store is initialized the first time the context is selected
375 do_initialize_themed_icons( NactIconChooser
*editor
)
377 GtkTreeView
*context_view
;
378 GtkTreeModel
*context_model
;
379 GtkCellRenderer
*text_cell
;
380 GtkTreeViewColumn
*column
;
381 GtkIconView
*icon_view
;
382 GtkTreeSelection
*selection
;
383 GtkIconTheme
*icon_theme
;
384 GList
*theme_contexts
, *it
;
385 const gchar
*context_label
;
388 context_view
= GTK_TREE_VIEW( base_window_get_widget( BASE_WINDOW( editor
), "ThemedTreeView" ));
389 context_model
= GTK_TREE_MODEL(
390 gtk_list_store_new( THEME_CONTEXT_N_COLUMN
,
391 G_TYPE_STRING
, G_TYPE_OBJECT
, G_TYPE_STRING
));
392 gtk_tree_view_set_model( context_view
, context_model
);
393 gtk_tree_view_set_headers_visible( context_view
, FALSE
);
395 text_cell
= gtk_cell_renderer_text_new();
396 column
= gtk_tree_view_column_new_with_attributes(
399 "text", THEME_CONTEXT_LABEL_COLUMN
,
401 gtk_tree_view_append_column( context_view
, column
);
403 icon_view
= GTK_ICON_VIEW( base_window_get_widget( BASE_WINDOW( editor
), "ThemedIconView" ));
404 gtk_icon_view_set_text_column( icon_view
, THEME_ICON_LABEL_COLUMN
);
405 gtk_icon_view_set_pixbuf_column( icon_view
, THEME_ICON_PIXBUF_COLUMN
);
406 gtk_icon_view_set_selection_mode( icon_view
, GTK_SELECTION_BROWSE
);
408 selection
= gtk_tree_view_get_selection( context_view
);
409 gtk_tree_selection_set_mode( selection
, GTK_SELECTION_BROWSE
);
411 icon_theme
= gtk_icon_theme_get_default();
412 theme_contexts
= g_list_sort(
413 gtk_icon_theme_list_contexts( icon_theme
), ( GCompareFunc
) g_utf8_collate
);
415 for( it
= theme_contexts
; it
; it
= it
->next
){
416 context_label
= ( const gchar
*) it
->data
;
417 gtk_list_store_append( GTK_LIST_STORE( context_model
), &iter
);
418 gtk_list_store_set( GTK_LIST_STORE( context_model
), &iter
,
419 THEME_CONTEXT_LABEL_COLUMN
, context_label
,
420 THEME_CONTEXT_STORE_COLUMN
, NULL
,
423 g_list_foreach( theme_contexts
, ( GFunc
) g_free
, NULL
);
424 g_list_free( theme_contexts
);
426 g_object_unref( context_model
);
430 do_initialize_icons_by_path( NactIconChooser
*editor
)
432 GtkFileChooser
*file_chooser
;
434 file_chooser
= GTK_FILE_CHOOSER( base_window_get_widget( BASE_WINDOW( editor
), "FileChooser" ));
435 gtk_file_chooser_set_action( file_chooser
, GTK_FILE_CHOOSER_ACTION_OPEN
);
436 gtk_file_chooser_set_select_multiple( file_chooser
, FALSE
);
440 on_base_runtime_init_dialog( NactIconChooser
*editor
, gpointer user_data
)
442 static const gchar
*thisfn
= "nact_icon_chooser_on_runtime_init_dialog";
445 NactApplication
*application
;
447 NASettings
*settings
;
449 g_return_if_fail( NACT_IS_ICON_CHOOSER( editor
));
451 g_debug( "%s: editor=%p, user_data=%p", thisfn
, ( void * ) editor
, ( void * ) user_data
);
453 application
= NACT_APPLICATION( base_window_get_application( BASE_WINDOW( editor
)));
454 updater
= nact_application_get_updater( application
);
455 settings
= na_pivot_get_settings( NA_PIVOT( updater
));
457 pos
= na_settings_get_uint( settings
, NA_IPREFS_ICON_CHOOSER_PANED
, NULL
, NULL
);
459 paned
= base_window_get_widget( BASE_WINDOW( editor
), "IconPaned" );
460 gtk_paned_set_position( GTK_PANED( paned
), pos
);
463 /* setup the initial icon
465 editor
->private->current_icon
= g_strdup( editor
->private->initial_icon
);
466 on_current_icon_changed( editor
);
468 /* fillup the icon stores
470 fillup_themed_icons( editor
);
471 fillup_icons_by_path( editor
);
473 /* intercept Escape key: we do not quit on Esc.
475 base_window_signal_connect(
476 BASE_WINDOW( editor
),
477 G_OBJECT( base_window_get_gtk_toplevel( BASE_WINDOW( editor
))),
479 G_CALLBACK( on_key_pressed_event
));
483 base_window_signal_connect_by_name(
484 BASE_WINDOW( editor
), "CancelButton", "clicked", G_CALLBACK( on_cancel_clicked
));
486 base_window_signal_connect_by_name(
487 BASE_WINDOW( editor
), "OKButton", "clicked", G_CALLBACK( on_ok_clicked
));
491 fillup_themed_icons( NactIconChooser
*editor
)
493 GtkTreeView
*context_view
;
494 GtkTreeSelection
*selection
;
496 GtkIconView
*icon_view
;
498 icon_view
= GTK_ICON_VIEW( base_window_get_widget( BASE_WINDOW( editor
), "ThemedIconView" ));
499 base_window_signal_connect(
500 BASE_WINDOW( editor
), G_OBJECT( icon_view
), "selection-changed", G_CALLBACK( on_themed_icon_changed
));
501 /* catch double-click */
502 base_window_signal_connect(
503 BASE_WINDOW( editor
), G_OBJECT( icon_view
), "button-press-event", G_CALLBACK( on_icon_view_button_press_event
));
505 context_view
= GTK_TREE_VIEW( base_window_get_widget( BASE_WINDOW( editor
), "ThemedTreeView" ));
506 selection
= gtk_tree_view_get_selection( context_view
);
507 base_window_signal_connect(
508 BASE_WINDOW( editor
), G_OBJECT( selection
), "changed", G_CALLBACK( on_themed_context_changed
));
510 path
= gtk_tree_path_new_first();
511 gtk_tree_selection_select_path( selection
, path
);
512 gtk_tree_path_free( path
);
514 base_window_signal_connect_by_name(
515 BASE_WINDOW( editor
), "ThemedApplyButton", "clicked", G_CALLBACK( on_themed_apply_button_clicked
));
519 fillup_icons_by_path( NactIconChooser
*editor
)
521 GtkFileChooser
*file_chooser
;
522 NactApplication
*application
;
524 NASettings
*settings
;
527 file_chooser
= GTK_FILE_CHOOSER( base_window_get_widget( BASE_WINDOW( editor
), "FileChooser" ));
528 editor
->private->path_preview
= gtk_image_new();
529 gtk_file_chooser_set_preview_widget( file_chooser
, editor
->private->path_preview
);
531 application
= NACT_APPLICATION( base_window_get_application( BASE_WINDOW( editor
)));
532 updater
= nact_application_get_updater( application
);
533 settings
= na_pivot_get_settings( NA_PIVOT( updater
));
535 gtk_file_chooser_unselect_all( file_chooser
);
537 uri
= na_settings_get_string( settings
, NA_IPREFS_ICON_CHOOSER_URI
, NULL
, NULL
);
539 gtk_file_chooser_set_current_folder_uri( file_chooser
, uri
);
541 } else if( editor
->private->current_icon
){
542 gtk_file_chooser_set_filename( file_chooser
, editor
->private->current_icon
);
545 base_window_signal_connect(
546 BASE_WINDOW( editor
), G_OBJECT( file_chooser
), "selection-changed", G_CALLBACK( on_path_selection_changed
));
547 base_window_signal_connect(
548 BASE_WINDOW( editor
), G_OBJECT( file_chooser
), "update-preview", G_CALLBACK( on_path_update_preview
));
550 base_window_signal_connect_by_name(
551 BASE_WINDOW( editor
), "PathApplyButton", "clicked", G_CALLBACK( on_path_apply_button_clicked
));
555 on_base_all_widgets_showed( NactIconChooser
*editor
, gpointer user_data
)
557 static const gchar
*thisfn
= "nact_icon_chooser_on_all_widgets_showed";
558 GtkWidget
*about_button
;
560 g_return_if_fail( NACT_IS_ICON_CHOOSER( editor
));
562 g_debug( "%s: editor=%p, user_data=%p", thisfn
, ( void * ) editor
, ( void * ) user_data
);
564 /* hide about button not used here
566 about_button
= base_window_get_widget( BASE_WINDOW( editor
), "AboutButton" );
567 gtk_widget_hide( about_button
);
571 on_cancel_clicked( GtkButton
*button
, NactIconChooser
*editor
)
573 GtkWindow
*toplevel
= base_window_get_gtk_toplevel( BASE_WINDOW( editor
));
574 gtk_dialog_response( GTK_DIALOG( toplevel
), GTK_RESPONSE_CLOSE
);
578 on_ok_clicked( GtkButton
*button
, NactIconChooser
*editor
)
580 GtkWindow
*toplevel
= base_window_get_gtk_toplevel( BASE_WINDOW( editor
));
581 gtk_dialog_response( GTK_DIALOG( toplevel
), GTK_RESPONSE_OK
);
585 base_dialog_response( GtkDialog
*dialog
, gint code
, BaseWindow
*window
)
587 static const gchar
*thisfn
= "nact_icon_chooser_on_dialog_response";
588 NactIconChooser
*editor
;
590 g_return_val_if_fail( NACT_IS_ICON_CHOOSER( window
), FALSE
);
592 g_debug( "%s: dialog=%p, code=%d, window=%p", thisfn
, ( void * ) dialog
, code
, ( void * ) window
);
594 editor
= NACT_ICON_CHOOSER( window
);
597 case GTK_RESPONSE_NONE
:
598 case GTK_RESPONSE_DELETE_EVENT
:
599 case GTK_RESPONSE_CLOSE
:
600 case GTK_RESPONSE_CANCEL
:
602 g_free( editor
->private->current_icon
);
603 editor
->private->current_icon
= g_strdup( editor
->private->initial_icon
);
607 case GTK_RESPONSE_OK
:
616 * display at the top of the dialog the icon addressed in @icon
617 * this is this icon which will be returned if the user validates
621 on_current_icon_changed( const NactIconChooser
*editor
)
627 image
= GTK_IMAGE( base_window_get_widget( BASE_WINDOW( editor
), "IconImage" ));
628 nact_gtk_utils_render( editor
->private->current_icon
, image
, CURRENT_ICON_SIZE
);
630 if( editor
->private->current_icon
){
631 if( g_path_is_absolute( editor
->private->current_icon
)){
632 icon_label
= g_filename_to_utf8( editor
->private->current_icon
, -1, NULL
, NULL
, NULL
);
634 icon_label
= g_strdup( editor
->private->current_icon
);
636 label
= GTK_LABEL( base_window_get_widget( BASE_WINDOW( editor
), "IconLabel" ));
637 gtk_label_set_label( label
, icon_label
);
638 g_free( icon_label
);
643 on_destroy( GtkWidget
*widget
, GdkEvent
*event
, void *foo
)
645 static const gchar
*thisfn
= "nact_icon_chooser_on_destroy";
646 GtkTreeView
*context_view
;
647 GtkListStore
*context_store
;
648 GtkTreeIter context_iter
;
649 GtkListStore
*icon_store
;
650 gchar
*context_label
;
652 g_debug( "%s: widget=%p", thisfn
, ( void * ) widget
);
654 /* clear the various models
656 context_view
= GTK_TREE_VIEW( nact_gtk_utils_get_widget_by_name( GTK_WINDOW( widget
), "ThemedTreeView" ));
657 context_store
= GTK_LIST_STORE( gtk_tree_view_get_model( context_view
));
659 if( gtk_tree_model_get_iter_first( GTK_TREE_MODEL( context_store
), &context_iter
)){
662 gtk_tree_model_get( GTK_TREE_MODEL( context_store
), &context_iter
,
663 THEME_CONTEXT_LABEL_COLUMN
, &context_label
,
664 THEME_CONTEXT_STORE_COLUMN
, &icon_store
,
667 g_debug( "%s: context=%s, clearing store=%p", thisfn
, context_label
, ( void * ) icon_store
);
668 gtk_list_store_clear( icon_store
);
669 g_object_unref( icon_store
);
672 g_free( context_label
);
674 if( !gtk_tree_model_iter_next( GTK_TREE_MODEL( context_store
), &context_iter
)){
680 gtk_list_store_clear( context_store
);
682 /* let other handlers get this message */
687 * mouse click on the themed icons icon view
690 on_icon_view_button_press_event( GtkWidget
*widget
, GdkEventButton
*event
, NactIconChooser
*editor
)
692 gboolean stop
= FALSE
;
694 /* double-click of left button
695 * > triggers a 'Apply' action
697 if( event
->type
== GDK_2BUTTON_PRESS
&& event
->button
== 1 ){
698 on_themed_apply_triggered( editor
);
706 on_key_pressed_event( GtkWidget
*widget
, GdkEventKey
*event
, NactIconChooser
*editor
)
708 gboolean stop
= FALSE
;
710 g_return_val_if_fail( NACT_IS_ICON_CHOOSER( editor
), FALSE
);
712 if( !editor
->private->dispose_has_run
){
714 /* inhibit Escape key */
715 if( event
->keyval
== NACT_KEY_Escape
){
724 on_themed_context_changed( GtkTreeSelection
*selection
, NactIconChooser
*editor
)
729 gchar
*context
, *last_path
;
731 GtkWidget
*preview_image
, *preview_label
;
733 if( gtk_tree_selection_get_selected( selection
, &model
, &iter
)){
734 gtk_tree_model_get( model
, &iter
,
735 THEME_CONTEXT_LABEL_COLUMN
, &context
,
736 THEME_CONTEXT_STORE_COLUMN
, &store
,
737 THEME_CONTEXT_LAST_SELECTED_COLUMN
, &last_path
,
741 store
= theme_context_load_icons( editor
, context
);
742 gtk_list_store_set( GTK_LIST_STORE( model
), &iter
, THEME_CONTEXT_STORE_COLUMN
, store
, -1 );
745 GtkIconView
*iconview
= GTK_ICON_VIEW( base_window_get_widget( BASE_WINDOW( editor
), "ThemedIconView" ));
746 gtk_icon_view_set_model( iconview
, GTK_TREE_MODEL( store
));
749 path
= gtk_tree_path_new_from_string( last_path
);
750 gtk_icon_view_select_path( iconview
, path
);
751 gtk_tree_path_free( path
);
754 preview_image
= base_window_get_widget( BASE_WINDOW( editor
), "ThemedIconImage" );
755 gtk_image_set_from_pixbuf( GTK_IMAGE( preview_image
), NULL
);
756 preview_label
= base_window_get_widget( BASE_WINDOW( editor
), "ThemedIconName" );
757 gtk_label_set_text( GTK_LABEL( preview_label
), "" );
762 g_object_unref( store
);
767 on_themed_icon_changed( GtkIconView
*icon_view
, NactIconChooser
*editor
)
773 GtkWidget
*preview_image
, *preview_label
;
774 GtkTreeView
*context_view
;
775 GtkListStore
*context_store
;
776 GtkTreeSelection
*context_selection
;
777 GtkTreeIter context_iter
;
780 selected
= gtk_icon_view_get_selected_items( icon_view
);
782 model
= gtk_icon_view_get_model( icon_view
);
784 if( gtk_tree_model_get_iter( model
, &iter
, ( GtkTreePath
* ) selected
->data
)){
785 gtk_tree_model_get( model
, &iter
,
786 THEME_ICON_LABEL_COLUMN
, &label
,
789 preview_image
= base_window_get_widget( BASE_WINDOW( editor
), "ThemedIconImage" );
790 nact_gtk_utils_render( label
, GTK_IMAGE( preview_image
), PREVIEW_ICON_SIZE
);
791 preview_label
= base_window_get_widget( BASE_WINDOW( editor
), "ThemedIconName" );
792 gtk_label_set_text( GTK_LABEL( preview_label
), label
);
794 /* record in context tree view the path to the last selected icon
796 context_view
= GTK_TREE_VIEW( base_window_get_widget( BASE_WINDOW( editor
), "ThemedTreeView" ));
797 context_selection
= gtk_tree_view_get_selection( context_view
);
798 if( gtk_tree_selection_get_selected( context_selection
, ( GtkTreeModel
** ) &context_store
, &context_iter
)){
799 icon_path
= gtk_tree_model_get_string_from_iter( model
, &iter
);
800 gtk_list_store_set( context_store
, &context_iter
, THEME_CONTEXT_LAST_SELECTED_COLUMN
, icon_path
, -1 );
807 g_list_foreach( selected
, ( GFunc
) gtk_tree_path_free
, NULL
);
808 g_list_free( selected
);
813 on_themed_apply_button_clicked( GtkButton
*button
, NactIconChooser
*editor
)
815 on_themed_apply_triggered( editor
);
819 on_themed_apply_triggered( NactIconChooser
*editor
)
821 GtkWidget
*icon_label
;
822 const gchar
*icon_name
;
824 icon_label
= base_window_get_widget( BASE_WINDOW( editor
), "ThemedIconName" );
825 icon_name
= gtk_label_get_text( GTK_LABEL( icon_label
));
827 g_free( editor
->private->current_icon
);
828 editor
->private->current_icon
= g_strdup( icon_name
);
829 on_current_icon_changed( editor
);
833 on_path_selection_changed( GtkFileChooser
*file_chooser
, NactIconChooser
*editor
)
836 NactApplication
*application
;
838 NASettings
*settings
;
840 uri
= gtk_file_chooser_get_current_folder_uri( file_chooser
);
842 application
= NACT_APPLICATION( base_window_get_application( BASE_WINDOW( editor
)));
843 updater
= nact_application_get_updater( application
);
844 settings
= na_pivot_get_settings( NA_PIVOT( updater
));
845 na_settings_set_string( settings
, NA_IPREFS_ICON_CHOOSER_URI
, uri
);
851 on_path_update_preview( GtkFileChooser
*file_chooser
, NactIconChooser
*editor
)
853 static const gchar
*thisfn
= "nact_icon_chooser_on_path_update_preview";
856 gboolean have_preview
;
859 if( !gtk_icon_size_lookup( PREVIEW_ICON_SIZE
, &width
, &height
)){
860 width
= PREVIEW_ICON_WIDTH
;
861 height
= PREVIEW_ICON_WIDTH
;
864 have_preview
= FALSE
;
865 filename
= gtk_file_chooser_get_preview_filename( file_chooser
);
866 g_debug( "%s: file_chooser=%p, editor=%p, filename=%s",
867 thisfn
, ( void * ) file_chooser
, ( void * ) editor
, filename
);
870 pixbuf
= gdk_pixbuf_new_from_file_at_size( filename
, width
, height
, NULL
);
871 have_preview
= ( pixbuf
!= NULL
);
876 gtk_image_set_from_pixbuf( GTK_IMAGE( editor
->private->path_preview
), pixbuf
);
877 g_object_unref( pixbuf
);
880 gtk_file_chooser_set_preview_widget_active( file_chooser
, TRUE
);
884 on_path_apply_button_clicked( GtkButton
*button
, NactIconChooser
*editor
)
886 GtkFileChooser
*file_chooser
= GTK_FILE_CHOOSER( base_window_get_widget( BASE_WINDOW( editor
), "FileChooser" ));
888 /* this is a filename in the character set specified by the G_FILENAME_ENCODING
889 * environment variable
891 g_free( editor
->private->current_icon
);
892 editor
->private->current_icon
= gtk_file_chooser_get_filename( file_chooser
);
893 on_current_icon_changed( editor
);
896 static GtkListStore
*
897 theme_context_load_icons( NactIconChooser
*editor
, const gchar
*context
)
899 static const gchar
*thisfn
= "nact_icon_chooser_theme_context_load_icons";
905 g_debug( "%s: editor=%p, context=%s", thisfn
, ( void * ) editor
, context
);
907 GtkIconTheme
*icon_theme
= gtk_icon_theme_get_default();
908 GtkListStore
*store
= gtk_list_store_new( THEME_ICON_N_COLUMN
, G_TYPE_STRING
, GDK_TYPE_PIXBUF
);
910 GList
*icon_list
= g_list_sort( gtk_icon_theme_list_icons( icon_theme
, context
), ( GCompareFunc
) g_utf8_collate
);
912 if( !gtk_icon_size_lookup( VIEW_ICON_SIZE
, &width
, &height
)){
913 width
= VIEW_ICON_DEFAULT_WIDTH
;
915 g_debug( "%s: width=%d", thisfn
, width
);
917 for( ic
= icon_list
; ic
; ic
= ic
->next
){
918 const gchar
*icon_name
= ( const gchar
* ) ic
->data
;
920 GdkPixbuf
*pixbuf
= gtk_icon_theme_load_icon(
921 icon_theme
, icon_name
, width
, GTK_ICON_LOOKUP_GENERIC_FALLBACK
, &error
);
923 g_warning( "%s: %s", thisfn
, error
->message
);
924 g_error_free( error
);
926 gtk_list_store_append( store
, &iter
);
927 gtk_list_store_set( store
, &iter
,
928 THEME_ICON_LABEL_COLUMN
, icon_name
,
929 THEME_ICON_PIXBUF_COLUMN
, pixbuf
,
931 g_object_unref( pixbuf
);
934 g_debug( "%s: %d loaded icons in store=%p", thisfn
, g_list_length( icon_list
), ( void * ) store
);
935 g_list_foreach( icon_list
, ( GFunc
) g_free
, NULL
);
936 g_list_free( icon_list
);