Set Nautilus-Actions as being the actual official product name
[nautilus-actions.git] / src / nact / nact-iaction-tab.c
blob3bce923e13805cbdcda5397d6e8e94592343bbbb
1 /*
2 * Nautilus-Actions
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.
24 * Authors:
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)
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
35 #include <glib/gi18n.h>
36 #include <string.h>
38 #include <api/na-core-utils.h>
39 #include <api/na-object-api.h>
41 #include <core/na-io-provider.h>
43 #include "base-iprefs.h"
44 #include "base-window.h"
45 #include "nact-application.h"
46 #include "nact-iprefs.h"
47 #include "nact-main-statusbar.h"
48 #include "nact-gtk-utils.h"
49 #include "nact-iactions-list.h"
50 #include "nact-main-tab.h"
51 #include "nact-iaction-tab.h"
53 /* private interface data
55 struct NactIActionTabInterfacePrivate {
56 void *empty; /* so that gcc -pedantic is happy */
59 /* columns in the icon combobox
61 enum {
62 ICON_STOCK_COLUMN = 0,
63 ICON_LABEL_COLUMN,
64 ICON_N_COLUMN
67 #define IPREFS_ICONS_DIALOG "icons-chooser"
68 #define IPREFS_ICONS_PATH "icons-path"
70 /* IActionTab properties, set against the GObject instance
72 #define IACTION_TAB_PROP_STATUS_CONTEXT "nact-iaction-tab-status-context"
74 static gboolean st_initialized = FALSE;
75 static gboolean st_finalized = FALSE;
76 static gboolean st_on_selection_change = FALSE;
78 static GType register_type( void );
79 static void interface_base_init( NactIActionTabInterface *klass );
80 static void interface_base_finalize( NactIActionTabInterface *klass );
82 static void on_iactions_list_column_edited( NactIActionTab *instance, NAObject *object, gchar *text, gint column );
83 static void on_tab_updatable_selection_changed( NactIActionTab *instance, gint count_selected );
85 static void on_target_selection_toggled( GtkToggleButton *button, NactIActionTab *instance );
86 static void on_target_location_toggled( GtkToggleButton *button, NactIActionTab *instance );
87 static void check_for_label( NactIActionTab *instance, GtkEntry *entry, const gchar *label );
88 static void on_label_changed( GtkEntry *entry, NactIActionTab *instance );
89 static void set_label_label( NactIActionTab *instance, const gchar *color );
90 static void on_target_toolbar_toggled( GtkToggleButton *button, NactIActionTab *instance );
91 static void on_toolbar_same_label_toggled( GtkToggleButton *button, NactIActionTab *instance );
92 static void toolbar_same_label_set_sensitive( NactIActionTab *instance, NAObjectItem *item );
93 static void setup_toolbar_label( NactIActionTab *instance, NAObjectItem *item, const gchar *label );
94 static void on_toolbar_label_changed( GtkEntry *entry, NactIActionTab *instance );
95 static void toolbar_label_set_sensitive( NactIActionTab *instance, NAObjectItem *item );
96 static void on_tooltip_changed( GtkEntry *entry, NactIActionTab *instance );
97 static GtkTreeModel *create_stock_icon_model( void );
99 /* GtkComboBoxEntry is deprecated from Gtk+3
100 * see. http://git.gnome.org/browse/gtk+/commit/?id=9612c648176378bf237ad0e1a8c6c995b0ca7c61
101 * while 'has_entry' property exists since 2.24
103 #if(( GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 24 ) || GTK_MAJOR_VERSION >= 3 )
104 static void icon_combo_list_set_entry( GtkComboBox* combo );
105 #else
106 static void icon_combo_list_set_entry( GtkComboBoxEntry* combo );
107 #endif
109 static void icon_combo_list_set_layout( GtkComboBox* combo );
110 static void on_icon_browse( GtkButton *button, NactIActionTab *instance );
111 static void on_icon_changed( GtkEntry *entry, NactIActionTab *instance );
112 static void icon_preview_cb( GtkFileChooser *dialog, GtkWidget *preview );
113 static gint sort_stock_ids( gconstpointer a, gconstpointer b );
114 static gchar *strip_underscore( const gchar *text );
115 static void release_icon_combobox( NactIActionTab *instance );
116 static GtkWidget *get_icon_combo_box( NactIActionTab *instance );
118 GType
119 nact_iaction_tab_get_type( void )
121 static GType iface_type = 0;
123 if( !iface_type ){
124 iface_type = register_type();
127 return( iface_type );
130 static GType
131 register_type( void )
133 static const gchar *thisfn = "nact_iaction_tab_register_type";
134 GType type;
136 static const GTypeInfo info = {
137 sizeof( NactIActionTabInterface ),
138 ( GBaseInitFunc ) interface_base_init,
139 ( GBaseFinalizeFunc ) interface_base_finalize,
140 NULL,
141 NULL,
142 NULL,
145 NULL
148 g_debug( "%s", thisfn );
150 type = g_type_register_static( G_TYPE_INTERFACE, "NactIActionTab", &info, 0 );
152 g_type_interface_add_prerequisite( type, BASE_WINDOW_TYPE );
154 return( type );
157 static void
158 interface_base_init( NactIActionTabInterface *klass )
160 static const gchar *thisfn = "nact_iaction_tab_interface_base_init";
162 if( !st_initialized ){
164 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
166 klass->private = g_new0( NactIActionTabInterfacePrivate, 1 );
168 st_initialized = TRUE;
172 static void
173 interface_base_finalize( NactIActionTabInterface *klass )
175 static const gchar *thisfn = "nact_iaction_tab_interface_base_finalize";
177 if( st_initialized && !st_finalized ){
179 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
181 st_finalized = TRUE;
183 g_free( klass->private );
188 * GTK_ICON_SIZE_MENU : 16x16
189 * GTK_ICON_SIZE_SMALL_TOOLBAR: 18x18
190 * GTK_ICON_SIZE_LARGE_TOOLBAR: 24x24
191 * GTK_ICON_SIZE_BUTTON : 20x20
192 * GTK_ICON_SIZE_DND : 32x32
193 * GTK_ICON_SIZE_DIALOG : 48x48
195 * icon is rendered for GTK_ICON_SIZE_MENU (na_object_item_get_pixbuf)
197 * Starting with 3.0.3, the ComboBox is dynamically created into its container.
199 void
200 nact_iaction_tab_initial_load_toplevel( NactIActionTab *instance )
202 static const gchar *thisfn = "nact_iaction_tab_initial_load_toplevel";
203 GtkFrame *frame;
204 GtkButton *button;
205 gint size;
206 #if(( GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 91 ) || GTK_MAJOR_VERSION >= 3 )
207 GtkRequisition minimal_size, natural_size;
208 #else
209 GtkRequisition requisition;
210 #endif
211 GtkWidget *container;
212 GtkWidget *icon_combo;
213 GtkTreeModel *model;
215 g_return_if_fail( NACT_IS_IACTION_TAB( instance ));
217 if( st_initialized && !st_finalized ){
219 g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
221 button = GTK_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ActionIconBrowseButton" ));
222 frame = GTK_FRAME( base_window_get_widget( BASE_WINDOW( instance ), "ActionIconFrame" ));
223 #if(( GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 91 ) || GTK_MAJOR_VERSION >= 3 )
224 gtk_widget_get_preferred_size( GTK_WIDGET( button ), &minimal_size, &natural_size );
225 size = MAX( minimal_size.height, natural_size.height );
226 #else
227 gtk_widget_size_request( GTK_WIDGET( button ), &requisition );
228 size = requisition.height;
229 #endif
230 gtk_widget_set_size_request( GTK_WIDGET( frame ), size, size );
231 gtk_frame_set_shadow_type( frame, GTK_SHADOW_IN );
233 model = create_stock_icon_model();
234 #if(( GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 24 ) || GTK_MAJOR_VERSION >= 3 )
235 icon_combo = gtk_combo_box_new_with_model_and_entry( model );
236 #else
237 icon_combo = gtk_combo_box_entry_new_with_model( model, ICON_LABEL_COLUMN );
238 #endif
239 g_object_unref( model );
240 container = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconHBox" );
241 gtk_box_pack_start( GTK_BOX( container ), icon_combo, TRUE, TRUE, 0 );
243 #if(( GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 24 ) || GTK_MAJOR_VERSION >= 3 )
244 icon_combo_list_set_entry( GTK_COMBO_BOX( icon_combo ));
245 #else
246 icon_combo_list_set_entry( GTK_COMBO_BOX_ENTRY( icon_combo ));
247 #endif
248 icon_combo_list_set_layout( GTK_COMBO_BOX( icon_combo ));
252 void
253 nact_iaction_tab_runtime_init_toplevel( NactIActionTab *instance )
255 static const gchar *thisfn = "nact_iaction_tab_runtime_init_toplevel";
256 GtkWidget *label_widget, *tooltip_widget, *icon_widget;
257 GtkWidget *button;
259 g_return_if_fail( NACT_IS_IACTION_TAB( instance ));
261 if( st_initialized && !st_finalized ){
263 g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
265 base_window_signal_connect(
266 BASE_WINDOW( instance ),
267 G_OBJECT( instance ),
268 MAIN_WINDOW_SIGNAL_SELECTION_CHANGED,
269 G_CALLBACK( on_tab_updatable_selection_changed ));
271 base_window_signal_connect(
272 BASE_WINDOW( instance ),
273 G_OBJECT( instance ),
274 IACTIONS_LIST_SIGNAL_COLUMN_EDITED,
275 G_CALLBACK( on_iactions_list_column_edited ));
277 button = base_window_get_widget( BASE_WINDOW( instance ), "ActionTargetSelectionButton" );
278 base_window_signal_connect(
279 BASE_WINDOW( instance ),
280 G_OBJECT( button ),
281 "toggled",
282 G_CALLBACK( on_target_selection_toggled ));
284 button = base_window_get_widget( BASE_WINDOW( instance ), "ActionTargetLocationButton" );
285 base_window_signal_connect(
286 BASE_WINDOW( instance ),
287 G_OBJECT( button ),
288 "toggled",
289 G_CALLBACK( on_target_location_toggled ));
291 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionMenuLabelEntry" );
292 base_window_signal_connect(
293 BASE_WINDOW( instance ),
294 G_OBJECT( label_widget ),
295 "changed",
296 G_CALLBACK( on_label_changed ));
298 button = base_window_get_widget( BASE_WINDOW( instance ), "ActionTargetToolbarButton" );
299 base_window_signal_connect(
300 BASE_WINDOW( instance ),
301 G_OBJECT( button ),
302 "toggled",
303 G_CALLBACK( on_target_toolbar_toggled ));
305 button = base_window_get_widget( BASE_WINDOW( instance ), "ToolbarSameLabelButton" );
306 base_window_signal_connect(
307 BASE_WINDOW( instance ),
308 G_OBJECT( button ),
309 "toggled",
310 G_CALLBACK( on_toolbar_same_label_toggled ));
312 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionToolbarLabelEntry" );
313 base_window_signal_connect(
314 BASE_WINDOW( instance ),
315 G_OBJECT( label_widget ),
316 "changed",
317 G_CALLBACK( on_toolbar_label_changed ));
319 tooltip_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionTooltipEntry" );
320 base_window_signal_connect(
321 BASE_WINDOW( instance ),
322 G_OBJECT( tooltip_widget ),
323 "changed",
324 G_CALLBACK( on_tooltip_changed ));
326 icon_widget = get_icon_combo_box( instance );
327 base_window_signal_connect(
328 BASE_WINDOW( instance ),
329 G_OBJECT( gtk_bin_get_child( GTK_BIN( icon_widget ))),
330 "changed",
331 G_CALLBACK( on_icon_changed ));
333 button = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconBrowseButton" );
334 base_window_signal_connect(
335 BASE_WINDOW( instance ),
336 G_OBJECT( button ),
337 "clicked",
338 G_CALLBACK( on_icon_browse ));
342 void
343 nact_iaction_tab_all_widgets_showed( NactIActionTab *instance )
345 static const gchar *thisfn = "nact_iaction_tab_all_widgets_showed";
347 g_return_if_fail( NACT_IS_IACTION_TAB( instance ));
349 if( st_initialized && !st_finalized ){
351 g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
355 void
356 nact_iaction_tab_dispose( NactIActionTab *instance )
358 static const gchar *thisfn = "nact_iaction_tab_dispose";
360 g_return_if_fail( NACT_IS_IACTION_TAB( instance ));
362 if( st_initialized && !st_finalized ){
364 g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
366 release_icon_combobox( instance );
371 * nact_iaction_tab_has_label:
372 * @window: this #NactIActionTab instance.
374 * An action or a menu can only be written if it has at least a label.
376 * Returns %TRUE if the label of the action or of the menu is not empty.
378 gboolean
379 nact_iaction_tab_has_label( NactIActionTab *instance )
381 GtkWidget *label_widget;
382 const gchar *label;
383 gboolean has_label = FALSE;
385 g_return_val_if_fail( NACT_IS_IACTION_TAB( instance ), FALSE );
387 if( st_initialized && !st_finalized ){
389 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionMenuLabelEntry" );
390 label = gtk_entry_get_text( GTK_ENTRY( label_widget ));
391 has_label = ( g_utf8_strlen( label, -1 ) > 0 );
394 return( has_label );
397 static void
398 on_iactions_list_column_edited( NactIActionTab *instance, NAObject *object, gchar *text, gint column )
400 GtkWidget *label_widget;
402 g_return_if_fail( NACT_IS_IACTION_TAB( instance ));
404 if( st_initialized && !st_finalized ){
406 if( object && NA_IS_OBJECT_ITEM( object )){
407 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionMenuLabelEntry" );
408 gtk_entry_set_text( GTK_ENTRY( label_widget ), text );
413 static void
414 on_tab_updatable_selection_changed( NactIActionTab *instance, gint count_selected )
416 static const gchar *thisfn = "nact_iaction_tab_on_tab_updatable_selection_changed";
417 gboolean enable_tab;
418 NAObjectItem *item;
419 gboolean editable;
420 gboolean target_selection, target_location, target_toolbar;
421 gboolean enable_label;
422 gboolean same_label;
423 GtkWidget *label_widget, *tooltip_widget, *icon_widget;
424 gchar *label, *tooltip, *icon;
425 GtkButton *icon_button;
426 GtkToggleButton *toggle;
428 g_return_if_fail( BASE_IS_WINDOW( instance ));
429 g_return_if_fail( NACT_IS_IACTION_TAB( instance ));
431 if( st_initialized && !st_finalized ){
433 g_debug( "%s: instance=%p, count_selected=%d", thisfn, ( void * ) instance, count_selected );
435 enable_tab = ( count_selected == 1 );
436 nact_main_tab_enable_page( NACT_MAIN_WINDOW( instance ), TAB_ACTION, enable_tab );
438 st_on_selection_change = TRUE;
440 g_object_get(
441 G_OBJECT( instance ),
442 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
443 TAB_UPDATABLE_PROP_EDITABLE, &editable,
444 NULL );
446 target_selection =
447 enable_tab &&
448 item != NULL &&
449 NA_IS_OBJECT_ACTION( item ) &&
450 na_object_is_target_selection( item );
452 target_location =
453 enable_tab &&
454 item != NULL &&
455 NA_IS_OBJECT_ACTION( item ) &&
456 na_object_is_target_location( item );
458 target_toolbar =
459 enable_tab &&
460 item != NULL &&
461 NA_IS_OBJECT_ACTION( item ) &&
462 na_object_is_target_toolbar( item );
464 toggle = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ActionTargetSelectionButton" ));
465 gtk_toggle_button_set_active( toggle, target_selection || ( item && NA_IS_OBJECT_MENU( item )));
466 gtk_widget_set_sensitive( GTK_WIDGET( toggle ), item && NA_IS_OBJECT_ACTION( item ));
467 nact_gtk_utils_set_editable( G_OBJECT( toggle ), editable );
469 toggle = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ActionTargetLocationButton" ));
470 gtk_toggle_button_set_active( toggle, target_location || ( item && NA_IS_OBJECT_MENU( item )));
471 gtk_widget_set_sensitive( GTK_WIDGET( toggle ), item && NA_IS_OBJECT_ACTION( item ));
472 nact_gtk_utils_set_editable( G_OBJECT( toggle ), editable );
474 enable_label = target_selection || target_location || ( item && NA_IS_OBJECT_MENU( item ));
475 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionMenuLabelEntry" );
476 label = item ? na_object_get_label( item ) : g_strdup( "" );
477 label = label ? label : g_strdup( "" );
478 gtk_entry_set_text( GTK_ENTRY( label_widget ), label );
479 if( item ){
480 check_for_label( instance, GTK_ENTRY( label_widget ), label );
482 g_free( label );
483 gtk_widget_set_sensitive( label_widget, enable_label );
484 nact_gtk_utils_set_editable( G_OBJECT( label_widget ), editable );
486 toggle = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ActionTargetToolbarButton" ));
487 gtk_toggle_button_set_active( toggle, target_toolbar );
488 gtk_widget_set_sensitive( GTK_WIDGET( toggle ), item && NA_IS_OBJECT_ACTION( item ));
489 nact_gtk_utils_set_editable( G_OBJECT( toggle ), editable );
491 toggle = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ToolbarSameLabelButton" ));
492 same_label = item && NA_IS_OBJECT_ACTION( item ) ? na_object_is_toolbar_same_label( item ) : FALSE;
493 gtk_toggle_button_set_active( toggle, same_label );
494 gtk_widget_set_sensitive( GTK_WIDGET( toggle ), target_toolbar );
495 nact_gtk_utils_set_editable( G_OBJECT( toggle ), editable );
497 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionToolbarLabelEntry" );
498 label = item && NA_IS_OBJECT_ACTION( item ) ? na_object_get_toolbar_label( item ) : g_strdup( "" );
499 gtk_entry_set_text( GTK_ENTRY( label_widget ), label );
500 g_free( label );
501 gtk_widget_set_sensitive( label_widget, target_toolbar && !same_label );
502 nact_gtk_utils_set_editable( G_OBJECT( label_widget ), editable );
504 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionToolbarLabelLabel" );
505 gtk_widget_set_sensitive( label_widget, target_toolbar && !same_label );
507 tooltip_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionTooltipEntry" );
508 tooltip = item ? na_object_get_tooltip( item ) : g_strdup( "" );
509 tooltip = tooltip ? tooltip : g_strdup( "" );
510 gtk_entry_set_text( GTK_ENTRY( tooltip_widget ), tooltip );
511 g_free( tooltip );
512 nact_gtk_utils_set_editable( G_OBJECT( tooltip_widget ), editable );
514 icon_widget = get_icon_combo_box( instance );
515 icon = item ? na_object_get_icon( item ) : g_strdup( "" );
516 icon = icon ? icon : g_strdup( "" );
517 gtk_entry_set_text( GTK_ENTRY( gtk_bin_get_child( GTK_BIN( icon_widget ))), icon );
518 g_free( icon );
519 nact_gtk_utils_set_editable( G_OBJECT( icon_widget ), editable );
521 icon_button = GTK_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ActionIconBrowseButton" ));
522 nact_gtk_utils_set_editable( G_OBJECT( icon_button ), editable );
524 st_on_selection_change = FALSE;
528 static void
529 on_target_selection_toggled( GtkToggleButton *button, NactIActionTab *instance )
531 static const gchar *thisfn = "nact_iaction_tab_on_target_selection_toggled";
532 NAObjectItem *item;
533 gboolean is_target;
534 gboolean editable;
536 if( !st_on_selection_change ){
538 g_debug( "%s: button=%p, instance=%p", thisfn, ( void * ) button, ( void * ) instance );
540 g_object_get(
541 G_OBJECT( instance ),
542 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
543 TAB_UPDATABLE_PROP_EDITABLE, &editable,
544 NULL );
546 g_debug( "%s: item=%p (%s), editable=%s",
547 thisfn, ( void * ) item, item ? G_OBJECT_TYPE_NAME( item ) : "null",
548 editable ? "True":"False" );
550 if( item && NA_IS_OBJECT_ACTION( item )){
551 is_target = gtk_toggle_button_get_active( button );
553 if( editable ){
554 na_object_set_target_selection( item, is_target );
555 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, item, FALSE );
557 } else {
558 g_signal_handlers_block_by_func(( gpointer ) button, on_target_selection_toggled, instance );
559 gtk_toggle_button_set_active( button, !is_target );
560 g_signal_handlers_unblock_by_func(( gpointer ) button, on_target_selection_toggled, instance );
566 static void
567 on_target_location_toggled( GtkToggleButton *button, NactIActionTab *instance )
569 static const gchar *thisfn = "nact_iaction_tab_on_target_location_toggled";
570 NAObjectItem *item;
571 gboolean is_target;
572 gboolean editable;
574 if( !st_on_selection_change ){
576 g_debug( "%s: button=%p, instance=%p", thisfn, ( void * ) button, ( void * ) instance );
578 g_object_get(
579 G_OBJECT( instance ),
580 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
581 TAB_UPDATABLE_PROP_EDITABLE, &editable,
582 NULL );
584 g_debug( "%s: item=%p (%s), editable=%s",
585 thisfn, ( void * ) item, item ? G_OBJECT_TYPE_NAME( item ) : "null",
586 editable ? "True":"False" );
588 if( item && NA_IS_OBJECT_ACTION( item )){
589 is_target = gtk_toggle_button_get_active( button );
591 if( editable ){
592 na_object_set_target_location( item, is_target );
593 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, item, FALSE );
595 } else {
596 g_signal_handlers_block_by_func(( gpointer ) button, on_target_location_toggled, instance );
597 gtk_toggle_button_set_active( button, !is_target );
598 g_signal_handlers_unblock_by_func(( gpointer ) button, on_target_location_toggled, instance );
604 static void
605 check_for_label( NactIActionTab *instance, GtkEntry *entry, const gchar *label )
607 NAObjectItem *item;
609 g_return_if_fail( NACT_IS_IACTION_TAB( instance ));
610 g_return_if_fail( GTK_IS_ENTRY( entry ));
612 if( st_initialized && !st_finalized ){
614 nact_main_statusbar_hide_status(
615 NACT_MAIN_WINDOW( instance ),
616 IACTION_TAB_PROP_STATUS_CONTEXT );
618 set_label_label( instance, "black" );
620 g_object_get(
621 G_OBJECT( instance ),
622 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
623 NULL );
625 if( item && g_utf8_strlen( label, -1 ) == 0 ){
627 /* i18n: status bar message when the action label is empty */
628 nact_main_statusbar_display_status(
629 NACT_MAIN_WINDOW( instance ),
630 IACTION_TAB_PROP_STATUS_CONTEXT,
631 _( "Caution: a label is mandatory for the action or the menu." ));
633 set_label_label( instance, "red" );
638 static void
639 on_label_changed( GtkEntry *entry, NactIActionTab *instance )
641 NAObjectItem *item;
642 const gchar *label;
644 g_object_get(
645 G_OBJECT( instance ),
646 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
647 NULL );
649 if( item ){
650 label = gtk_entry_get_text( entry );
651 na_object_set_label( item, label );
652 check_for_label( instance, entry, label );
654 if( NA_IS_OBJECT_ACTION( item )){
655 setup_toolbar_label( instance, item, label );
658 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, item, TRUE );
662 static void
663 set_label_label( NactIActionTab *instance, const gchar *color_str )
665 GtkWidget *label;
667 label = base_window_get_widget( BASE_WINDOW( instance ), "ActionMenuLabelLabel" );
669 /* gtk_widget_modify_fg() is deprecated as of Gtk+ 3.0
671 #if(( GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 91 ) || GTK_MAJOR_VERSION >= 3 )
672 GdkRGBA color;
673 gdk_rgba_parse( &color, color_str );
674 gtk_widget_override_color( label, GTK_STATE_FLAG_ACTIVE, &color );
675 #else
676 GdkColor color;
677 gdk_color_parse( color_str, &color );
678 gtk_widget_modify_fg( label, GTK_STATE_NORMAL, &color );
679 #endif
682 static void
683 on_target_toolbar_toggled( GtkToggleButton *button, NactIActionTab *instance )
685 static const gchar *thisfn = "nact_iaction_tab_on_target_toolbar_toggled";
686 NAObjectAction *item;
687 gboolean is_target;
688 gboolean editable;
690 if( !st_on_selection_change ){
692 g_debug( "%s: button=%p, instance=%p", thisfn, ( void * ) button, ( void * ) instance );
694 g_object_get(
695 G_OBJECT( instance ),
696 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
697 TAB_UPDATABLE_PROP_EDITABLE, &editable,
698 NULL );
700 g_debug( "%s: item=%p (%s), editable=%s",
701 thisfn, ( void * ) item, item ? G_OBJECT_TYPE_NAME( item ) : "null",
702 editable ? "True":"False" );
704 if( item && NA_IS_OBJECT_ACTION( item )){
705 is_target = gtk_toggle_button_get_active( button );
707 if( editable ){
708 na_object_set_target_toolbar( item, is_target );
709 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, item, FALSE );
710 toolbar_same_label_set_sensitive( instance, NA_OBJECT_ITEM( item ));
711 toolbar_label_set_sensitive( instance, NA_OBJECT_ITEM( item ));
713 } else {
714 g_signal_handlers_block_by_func(( gpointer ) button, on_target_toolbar_toggled, instance );
715 gtk_toggle_button_set_active( button, !is_target );
716 g_signal_handlers_unblock_by_func(( gpointer ) button, on_target_toolbar_toggled, instance );
722 static void
723 on_toolbar_same_label_toggled( GtkToggleButton *button, NactIActionTab *instance )
725 static const gchar *thisfn = "nact_iaction_tab_on_toolbar_same_label_toggled";
726 NAObjectItem *item;
727 gboolean same_label;
728 gboolean editable;
729 gchar *label;
730 GtkWidget *label_widget;
732 if( !st_on_selection_change ){
733 g_debug( "%s: button=%p, instance=%p", thisfn, ( void * ) button, ( void * ) instance );
735 g_object_get(
736 G_OBJECT( instance ),
737 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
738 TAB_UPDATABLE_PROP_EDITABLE, &editable,
739 NULL );
741 g_debug( "%s: item=%p (%s), editable=%s",
742 thisfn, ( void * ) item, item ? G_OBJECT_TYPE_NAME( item ) : "null",
743 editable ? "True":"False" );
745 if( item && NA_IS_OBJECT_ACTION( item )){
746 same_label = gtk_toggle_button_get_active( button );
748 if( editable ){
749 na_object_set_toolbar_same_label( NA_OBJECT_ACTION( item ), same_label );
751 if( same_label ){
752 label = na_object_get_label( item );
753 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionToolbarLabelEntry" );
754 gtk_entry_set_text( GTK_ENTRY( label_widget ), label );
755 g_free( label );
758 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, item, FALSE );
759 toolbar_same_label_set_sensitive( instance, NA_OBJECT_ITEM( item ));
760 toolbar_label_set_sensitive( instance, NA_OBJECT_ITEM( item ));
762 } else {
763 g_signal_handlers_block_by_func(( gpointer ) button, on_toolbar_same_label_toggled, instance );
764 gtk_toggle_button_set_active( button, !same_label );
765 g_signal_handlers_unblock_by_func(( gpointer ) button, on_toolbar_same_label_toggled, instance );
771 static void
772 toolbar_same_label_set_sensitive( NactIActionTab *instance, NAObjectItem *item )
774 GtkToggleButton *toggle;
775 gboolean target_toolbar;
776 gboolean readonly;
778 readonly = item ? na_object_is_readonly( item ) : FALSE;
779 toggle = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ToolbarSameLabelButton" ));
780 target_toolbar = item && NA_IS_OBJECT_ACTION( item ) ? na_object_is_target_toolbar( NA_OBJECT_ACTION( item )) : FALSE;
781 gtk_widget_set_sensitive( GTK_WIDGET( toggle ), target_toolbar && !readonly );
785 * setup the label of the toolbar according to the toolbar_same_label flag
787 static void
788 setup_toolbar_label( NactIActionTab *instance, NAObjectItem *item, const gchar *label )
790 GtkWidget *label_widget;
792 if( item && NA_IS_OBJECT_ACTION( item )){
793 if( na_object_is_toolbar_same_label( item )){
794 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionToolbarLabelEntry" );
795 gtk_entry_set_text( GTK_ENTRY( label_widget ), label );
800 static void
801 on_toolbar_label_changed( GtkEntry *entry, NactIActionTab *instance )
803 NAObjectItem *item;
804 const gchar *label;
806 g_object_get(
807 G_OBJECT( instance ),
808 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
809 NULL );
811 if( item && NA_IS_OBJECT_ACTION( item )){
812 label = gtk_entry_get_text( entry );
813 na_object_set_toolbar_label( NA_OBJECT_ACTION( item ), label );
815 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, item, FALSE );
819 static void
820 toolbar_label_set_sensitive( NactIActionTab *instance, NAObjectItem *item )
822 gboolean is_action;
823 gboolean same_label;
824 GtkWidget *label_widget;
826 is_action = item && NA_IS_OBJECT_ACTION( item );
827 same_label = is_action ? na_object_is_toolbar_same_label( NA_OBJECT_ACTION( item )) : FALSE;
828 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionToolbarLabelEntry" );
829 gtk_widget_set_sensitive( label_widget, is_action && !same_label );
832 static void
833 on_tooltip_changed( GtkEntry *entry, NactIActionTab *instance )
835 NAObjectItem *item;
837 g_object_get(
838 G_OBJECT( instance ),
839 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
840 NULL );
842 if( item ){
843 na_object_set_tooltip( item, gtk_entry_get_text( entry ));
844 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, item, FALSE );
848 static GtkTreeModel *
849 create_stock_icon_model( void )
851 GtkStockItem stock_item;
852 gchar* label;
853 GtkListStore *model;
854 GtkTreeIter row;
855 GSList *stock_list, *iter;
856 GtkIconTheme *icon_theme;
857 GtkIconInfo *icon_info;
859 model = gtk_list_store_new( ICON_N_COLUMN, G_TYPE_STRING, G_TYPE_STRING );
861 gtk_list_store_append( model, &row );
862 /* i18n notes: when no icon is selected in the drop-down list */
863 gtk_list_store_set( model, &row, ICON_STOCK_COLUMN, "", ICON_LABEL_COLUMN, _( "None" ), -1 );
865 stock_list = gtk_stock_list_ids();
866 icon_theme = gtk_icon_theme_get_default();
867 stock_list = g_slist_sort( stock_list, ( GCompareFunc ) sort_stock_ids );
869 for( iter = stock_list ; iter ; iter = iter->next ){
870 icon_info = gtk_icon_theme_lookup_icon( icon_theme, ( gchar * ) iter->data, GTK_ICON_SIZE_MENU, GTK_ICON_LOOKUP_GENERIC_FALLBACK );
871 if( icon_info ){
872 if( gtk_stock_lookup(( gchar * ) iter->data, &stock_item )){
873 gtk_list_store_append( model, &row );
874 label = strip_underscore( stock_item.label );
875 gtk_list_store_set( model, &row, ICON_STOCK_COLUMN, ( gchar * ) iter->data, ICON_LABEL_COLUMN, label, -1 );
876 g_free( label );
878 gtk_icon_info_free( icon_info );
882 g_slist_foreach( stock_list, ( GFunc ) g_free, NULL );
883 g_slist_free( stock_list );
885 return( GTK_TREE_MODEL( model ));
888 #if(( GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 24 ) || GTK_MAJOR_VERSION >= 3 )
889 static void
890 icon_combo_list_set_entry( GtkComboBox* combo )
892 if( gtk_combo_box_get_entry_text_column( combo ) == -1 ){
893 gtk_combo_box_set_entry_text_column( combo, ICON_STOCK_COLUMN );
896 #else
897 static void
898 icon_combo_list_set_entry( GtkComboBoxEntry* combo )
900 if( gtk_combo_box_entry_get_text_column( combo ) == -1 ){
901 gtk_combo_box_entry_set_text_column( combo, ICON_STOCK_COLUMN );
904 #endif
906 static void
907 icon_combo_list_set_layout( GtkComboBox *combo )
909 GtkCellRenderer *cell_renderer_pix;
910 GtkCellRenderer *cell_renderer_text;
912 gtk_cell_layout_clear( GTK_CELL_LAYOUT( combo ));
914 cell_renderer_pix = gtk_cell_renderer_pixbuf_new();
915 gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( combo ), cell_renderer_pix, FALSE );
916 gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT( combo ), cell_renderer_pix, "stock-id", ICON_STOCK_COLUMN );
918 cell_renderer_text = gtk_cell_renderer_text_new();
919 gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( combo ), cell_renderer_text, TRUE );
920 gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT( combo ), cell_renderer_text, "text", ICON_LABEL_COLUMN );
922 gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 0 );
925 static void
926 on_icon_browse( GtkButton *button, NactIActionTab *instance )
928 nact_gtk_utils_select_file_with_preview(
929 BASE_WINDOW( instance ),
930 _( "Choosing an icon" ),
931 IPREFS_ICONS_DIALOG,
932 gtk_bin_get_child( GTK_BIN( get_icon_combo_box( instance ))),
933 IPREFS_ICONS_PATH,
935 G_CALLBACK( icon_preview_cb )
939 static void
940 on_icon_changed( GtkEntry *icon_entry, NactIActionTab *instance )
942 static const gchar *thisfn = "nact_iaction_tab_on_icon_changed";
943 GtkImage *image;
944 NAObjectItem *item;
945 const gchar *icon_name;
947 g_debug( "%s: entry=%p, instance=%p", thisfn, ( void * ) icon_entry, ( void * ) instance );
949 icon_name = NULL;
951 g_object_get(
952 G_OBJECT( instance ),
953 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
954 NULL );
956 if( item ){
957 icon_name = gtk_entry_get_text( icon_entry );
958 na_object_set_icon( item, icon_name );
959 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, item, TRUE );
962 /* icon_name may be null if there is no current item
963 * in such a case, we blank the image
965 image = GTK_IMAGE( base_window_get_widget( BASE_WINDOW( instance ), "ActionIconImage" ));
966 nact_gtk_utils_render( icon_name, image, GTK_ICON_SIZE_SMALL_TOOLBAR );
969 static void
970 icon_preview_cb( GtkFileChooser *dialog, GtkWidget *preview )
972 char *filename;
973 GdkPixbuf *pixbuf;
974 gboolean have_preview;
976 filename = gtk_file_chooser_get_preview_filename( dialog );
977 pixbuf = gdk_pixbuf_new_from_file_at_size( filename, 128, 128, NULL );
978 have_preview = ( pixbuf != NULL );
979 g_free( filename );
981 if( have_preview ){
982 gtk_image_set_from_pixbuf( GTK_IMAGE( preview ), pixbuf );
983 g_object_unref( pixbuf );
986 gtk_file_chooser_set_preview_widget_active( dialog, have_preview );
989 static gint
990 sort_stock_ids( gconstpointer a, gconstpointer b )
992 GtkStockItem stock_item_a;
993 GtkStockItem stock_item_b;
994 gchar *label_a, *label_b;
995 gboolean is_a, is_b;
996 int retv = 0;
998 is_a = gtk_stock_lookup(( gchar * ) a, &stock_item_a );
999 is_b = gtk_stock_lookup(( gchar * ) b, &stock_item_b );
1001 if( is_a && !is_b ){
1002 retv = 1;
1004 } else if( !is_a && is_b ){
1005 retv = -1;
1007 } else if( !is_a && !is_b ){
1008 retv = 0;
1010 } else {
1011 label_a = strip_underscore( stock_item_a.label );
1012 label_b = strip_underscore( stock_item_b.label );
1013 retv = na_core_utils_str_collate( label_a, label_b );
1014 g_free( label_a );
1015 g_free( label_b );
1018 return( retv );
1021 static gchar *
1022 strip_underscore( const gchar *text )
1024 /* Code from gtk-demo */
1025 gchar *p, *q, *result;
1027 result = g_strdup( text );
1028 p = q = result;
1029 while( *p ){
1030 if( *p != '_' ){
1031 *q = *p;
1032 q++;
1034 p++;
1036 *q = '\0';
1038 return( result );
1041 static void
1042 release_icon_combobox( NactIActionTab *instance )
1044 GtkWidget *combo;
1045 GtkTreeModel *model;
1047 combo = get_icon_combo_box( instance );
1048 model = gtk_combo_box_get_model( GTK_COMBO_BOX( combo ));
1049 gtk_list_store_clear( GTK_LIST_STORE( model ));
1052 static GtkWidget *
1053 get_icon_combo_box( NactIActionTab *instance )
1055 GtkWidget *icon_box, *icon_combo;
1057 icon_box = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconHBox" );
1058 icon_combo = GTK_WIDGET( gtk_container_get_children( GTK_CONTAINER( icon_box ))->data );
1060 return( icon_combo );