Change help menu item from Gtk default to Gnome (apparent) standard
[nautilus-actions.git] / src / nact / nact-iaction-tab.c
blob0ccde5aba42a67cbf0f44ad3203f26f80b620e47
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 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 );
98 static void icon_combo_list_fill( GtkComboBoxEntry* combo );
99 static void on_icon_browse( GtkButton *button, NactIActionTab *instance );
100 static void on_icon_changed( GtkEntry *entry, NactIActionTab *instance );
101 static gint sort_stock_ids( gconstpointer a, gconstpointer b );
102 static gchar *strip_underscore( const gchar *text );
103 static void release_icon_combobox( NactIActionTab *instance );
105 GType
106 nact_iaction_tab_get_type( void )
108 static GType iface_type = 0;
110 if( !iface_type ){
111 iface_type = register_type();
114 return( iface_type );
117 static GType
118 register_type( void )
120 static const gchar *thisfn = "nact_iaction_tab_register_type";
121 GType type;
123 static const GTypeInfo info = {
124 sizeof( NactIActionTabInterface ),
125 ( GBaseInitFunc ) interface_base_init,
126 ( GBaseFinalizeFunc ) interface_base_finalize,
127 NULL,
128 NULL,
129 NULL,
132 NULL
135 g_debug( "%s", thisfn );
137 type = g_type_register_static( G_TYPE_INTERFACE, "NactIActionTab", &info, 0 );
139 g_type_interface_add_prerequisite( type, BASE_WINDOW_TYPE );
141 return( type );
144 static void
145 interface_base_init( NactIActionTabInterface *klass )
147 static const gchar *thisfn = "nact_iaction_tab_interface_base_init";
149 if( !st_initialized ){
151 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
153 klass->private = g_new0( NactIActionTabInterfacePrivate, 1 );
155 st_initialized = TRUE;
159 static void
160 interface_base_finalize( NactIActionTabInterface *klass )
162 static const gchar *thisfn = "nact_iaction_tab_interface_base_finalize";
164 if( st_initialized && !st_finalized ){
166 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
168 st_finalized = TRUE;
170 g_free( klass->private );
175 * GTK_ICON_SIZE_MENU : 16x16
176 * GTK_ICON_SIZE_SMALL_TOOLBAR: 18x18
177 * GTK_ICON_SIZE_LARGE_TOOLBAR: 24x24
178 * GTK_ICON_SIZE_BUTTON : 20x20
179 * GTK_ICON_SIZE_DND : 32x32
180 * GTK_ICON_SIZE_DIALOG : 48x48
182 * icon is rendered for GTK_ICON_SIZE_MENU (na_object_item_get_pixbuf)
184 void
185 nact_iaction_tab_initial_load_toplevel( NactIActionTab *instance )
187 static const gchar *thisfn = "nact_iaction_tab_initial_load_toplevel";
188 GtkWidget *icon_widget;
189 GtkTreeModel *model;
190 GtkButton *button;
191 GtkRequisition requisition;
192 GtkFrame *frame;
193 gint size;
195 g_return_if_fail( NACT_IS_IACTION_TAB( instance ));
197 if( st_initialized && !st_finalized ){
199 g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
201 button = GTK_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ActionIconBrowseButton" ));
202 gtk_widget_size_request( GTK_WIDGET( button ), &requisition );
203 g_debug( "%s: button requisition width=%d, height=%d", thisfn, requisition.width, requisition.height );
204 frame = GTK_FRAME( base_window_get_widget( BASE_WINDOW( instance ), "ActionIconFrame" ));
205 size = requisition.height - 4;
206 gtk_widget_set_size_request( GTK_WIDGET( frame ), size, size );
207 gtk_frame_set_shadow_type( frame, GTK_SHADOW_IN );
209 icon_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconComboBoxEntry" );
210 model = create_stock_icon_model();
211 gtk_combo_box_set_model( GTK_COMBO_BOX( icon_widget ), model );
212 g_object_unref( model );
213 icon_combo_list_fill( GTK_COMBO_BOX_ENTRY( icon_widget ));
217 void
218 nact_iaction_tab_runtime_init_toplevel( NactIActionTab *instance )
220 static const gchar *thisfn = "nact_iaction_tab_runtime_init_toplevel";
221 GtkWidget *label_widget, *tooltip_widget, *icon_widget;
222 GtkWidget *button;
224 g_return_if_fail( NACT_IS_IACTION_TAB( instance ));
226 if( st_initialized && !st_finalized ){
228 g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
230 base_window_signal_connect(
231 BASE_WINDOW( instance ),
232 G_OBJECT( instance ),
233 MAIN_WINDOW_SIGNAL_SELECTION_CHANGED,
234 G_CALLBACK( on_tab_updatable_selection_changed ));
236 base_window_signal_connect(
237 BASE_WINDOW( instance ),
238 G_OBJECT( instance ),
239 IACTIONS_LIST_SIGNAL_COLUMN_EDITED,
240 G_CALLBACK( on_iactions_list_column_edited ));
242 button = base_window_get_widget( BASE_WINDOW( instance ), "ActionTargetSelectionButton" );
243 base_window_signal_connect(
244 BASE_WINDOW( instance ),
245 G_OBJECT( button ),
246 "toggled",
247 G_CALLBACK( on_target_selection_toggled ));
249 button = base_window_get_widget( BASE_WINDOW( instance ), "ActionTargetLocationButton" );
250 base_window_signal_connect(
251 BASE_WINDOW( instance ),
252 G_OBJECT( button ),
253 "toggled",
254 G_CALLBACK( on_target_location_toggled ));
256 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionMenuLabelEntry" );
257 base_window_signal_connect(
258 BASE_WINDOW( instance ),
259 G_OBJECT( label_widget ),
260 "changed",
261 G_CALLBACK( on_label_changed ));
263 button = base_window_get_widget( BASE_WINDOW( instance ), "ActionTargetToolbarButton" );
264 base_window_signal_connect(
265 BASE_WINDOW( instance ),
266 G_OBJECT( button ),
267 "toggled",
268 G_CALLBACK( on_target_toolbar_toggled ));
270 button = base_window_get_widget( BASE_WINDOW( instance ), "ToolbarSameLabelButton" );
271 base_window_signal_connect(
272 BASE_WINDOW( instance ),
273 G_OBJECT( button ),
274 "toggled",
275 G_CALLBACK( on_toolbar_same_label_toggled ));
277 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionToolbarLabelEntry" );
278 base_window_signal_connect(
279 BASE_WINDOW( instance ),
280 G_OBJECT( label_widget ),
281 "changed",
282 G_CALLBACK( on_toolbar_label_changed ));
284 tooltip_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionTooltipEntry" );
285 base_window_signal_connect(
286 BASE_WINDOW( instance ),
287 G_OBJECT( tooltip_widget ),
288 "changed",
289 G_CALLBACK( on_tooltip_changed ));
291 icon_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconComboBoxEntry" );
292 base_window_signal_connect(
293 BASE_WINDOW( instance ),
294 G_OBJECT( gtk_bin_get_child( GTK_BIN( icon_widget ))),
295 "changed",
296 G_CALLBACK( on_icon_changed ));
298 button = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconBrowseButton" );
299 base_window_signal_connect(
300 BASE_WINDOW( instance ),
301 G_OBJECT( button ),
302 "clicked",
303 G_CALLBACK( on_icon_browse ));
307 void
308 nact_iaction_tab_all_widgets_showed( NactIActionTab *instance )
310 static const gchar *thisfn = "nact_iaction_tab_all_widgets_showed";
312 g_return_if_fail( NACT_IS_IACTION_TAB( instance ));
314 if( st_initialized && !st_finalized ){
316 g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
320 void
321 nact_iaction_tab_dispose( NactIActionTab *instance )
323 static const gchar *thisfn = "nact_iaction_tab_dispose";
325 g_return_if_fail( NACT_IS_IACTION_TAB( instance ));
327 if( st_initialized && !st_finalized ){
329 g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
331 release_icon_combobox( instance );
336 * nact_iaction_tab_has_label:
337 * @window: this #NactIActionTab instance.
339 * An action or a menu can only be written if it has at least a label.
341 * Returns %TRUE if the label of the action or of the menu is not empty.
343 gboolean
344 nact_iaction_tab_has_label( NactIActionTab *instance )
346 GtkWidget *label_widget;
347 const gchar *label;
348 gboolean has_label = FALSE;
350 g_return_val_if_fail( NACT_IS_IACTION_TAB( instance ), FALSE );
352 if( st_initialized && !st_finalized ){
354 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionMenuLabelEntry" );
355 label = gtk_entry_get_text( GTK_ENTRY( label_widget ));
356 has_label = ( g_utf8_strlen( label, -1 ) > 0 );
359 return( has_label );
362 static void
363 on_iactions_list_column_edited( NactIActionTab *instance, NAObject *object, gchar *text, gint column )
365 GtkWidget *label_widget;
367 g_return_if_fail( NACT_IS_IACTION_TAB( instance ));
369 if( st_initialized && !st_finalized ){
371 if( object && NA_IS_OBJECT_ITEM( object )){
372 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionMenuLabelEntry" );
373 gtk_entry_set_text( GTK_ENTRY( label_widget ), text );
378 static void
379 on_tab_updatable_selection_changed( NactIActionTab *instance, gint count_selected )
381 static const gchar *thisfn = "nact_iaction_tab_on_tab_updatable_selection_changed";
382 gboolean enable_tab;
383 NAObjectItem *item;
384 gboolean editable;
385 gboolean target_selection, target_location, target_toolbar;
386 gboolean enable_label;
387 gboolean same_label;
388 GtkWidget *label_widget, *tooltip_widget, *icon_widget;
389 gchar *label, *tooltip, *icon;
390 GtkButton *icon_button;
391 GtkToggleButton *toggle;
393 g_return_if_fail( BASE_IS_WINDOW( instance ));
394 g_return_if_fail( NACT_IS_IACTION_TAB( instance ));
396 if( st_initialized && !st_finalized ){
398 g_debug( "%s: instance=%p, count_selected=%d", thisfn, ( void * ) instance, count_selected );
400 enable_tab = ( count_selected == 1 );
401 nact_main_tab_enable_page( NACT_MAIN_WINDOW( instance ), TAB_ACTION, enable_tab );
403 st_on_selection_change = TRUE;
405 g_object_get(
406 G_OBJECT( instance ),
407 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
408 TAB_UPDATABLE_PROP_EDITABLE, &editable,
409 NULL );
411 target_selection =
412 enable_tab &&
413 item != NULL &&
414 NA_IS_OBJECT_ACTION( item ) &&
415 na_object_is_target_selection( item );
417 target_location =
418 enable_tab &&
419 item != NULL &&
420 NA_IS_OBJECT_ACTION( item ) &&
421 na_object_is_target_location( item );
423 target_toolbar =
424 enable_tab &&
425 item != NULL &&
426 NA_IS_OBJECT_ACTION( item ) &&
427 na_object_is_target_toolbar( item );
429 toggle = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ActionTargetSelectionButton" ));
430 gtk_toggle_button_set_active( toggle, target_selection || ( item && NA_IS_OBJECT_MENU( item )));
431 gtk_widget_set_sensitive( GTK_WIDGET( toggle ), item && NA_IS_OBJECT_ACTION( item ));
432 nact_gtk_utils_set_editable( GTK_OBJECT( toggle ), editable );
434 toggle = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ActionTargetLocationButton" ));
435 gtk_toggle_button_set_active( toggle, target_location || ( item && NA_IS_OBJECT_MENU( item )));
436 gtk_widget_set_sensitive( GTK_WIDGET( toggle ), item && NA_IS_OBJECT_ACTION( item ));
437 nact_gtk_utils_set_editable( GTK_OBJECT( toggle ), editable );
439 enable_label = target_selection || target_location || ( item && NA_IS_OBJECT_MENU( item ));
440 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionMenuLabelEntry" );
441 label = item ? na_object_get_label( item ) : g_strdup( "" );
442 label = label ? label : g_strdup( "" );
443 gtk_entry_set_text( GTK_ENTRY( label_widget ), label );
444 if( item ){
445 check_for_label( instance, GTK_ENTRY( label_widget ), label );
447 g_free( label );
448 gtk_widget_set_sensitive( label_widget, enable_label );
449 nact_gtk_utils_set_editable( GTK_OBJECT( label_widget ), editable );
451 toggle = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ActionTargetToolbarButton" ));
452 gtk_toggle_button_set_active( toggle, target_toolbar );
453 gtk_widget_set_sensitive( GTK_WIDGET( toggle ), item && NA_IS_OBJECT_ACTION( item ));
454 nact_gtk_utils_set_editable( GTK_OBJECT( toggle ), editable );
456 toggle = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ToolbarSameLabelButton" ));
457 same_label = item && NA_IS_OBJECT_ACTION( item ) ? na_object_is_toolbar_same_label( item ) : FALSE;
458 gtk_toggle_button_set_active( toggle, same_label );
459 gtk_widget_set_sensitive( GTK_WIDGET( toggle ), target_toolbar );
460 nact_gtk_utils_set_editable( GTK_OBJECT( toggle ), editable );
462 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionToolbarLabelEntry" );
463 label = item && NA_IS_OBJECT_ACTION( item ) ? na_object_get_toolbar_label( item ) : g_strdup( "" );
464 gtk_entry_set_text( GTK_ENTRY( label_widget ), label );
465 g_free( label );
466 gtk_widget_set_sensitive( label_widget, target_toolbar && !same_label );
467 nact_gtk_utils_set_editable( GTK_OBJECT( label_widget ), editable );
469 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionToolbarLabelLabel" );
470 gtk_widget_set_sensitive( label_widget, target_toolbar && !same_label );
472 tooltip_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionTooltipEntry" );
473 tooltip = item ? na_object_get_tooltip( item ) : g_strdup( "" );
474 tooltip = tooltip ? tooltip : g_strdup( "" );
475 gtk_entry_set_text( GTK_ENTRY( tooltip_widget ), tooltip );
476 g_free( tooltip );
477 nact_gtk_utils_set_editable( GTK_OBJECT( tooltip_widget ), editable );
479 icon_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconComboBoxEntry" );
480 icon = item ? na_object_get_icon( item ) : g_strdup( "" );
481 icon = icon ? icon : g_strdup( "" );
482 gtk_entry_set_text( GTK_ENTRY( gtk_bin_get_child( GTK_BIN( icon_widget ))), icon );
483 g_free( icon );
484 nact_gtk_utils_set_editable( GTK_OBJECT( icon_widget ), editable );
486 icon_button = GTK_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ActionIconBrowseButton" ));
487 nact_gtk_utils_set_editable( GTK_OBJECT( icon_button ), editable );
489 st_on_selection_change = FALSE;
493 static void
494 on_target_selection_toggled( GtkToggleButton *button, NactIActionTab *instance )
496 static const gchar *thisfn = "nact_iaction_tab_on_target_selection_toggled";
497 NAObjectItem *item;
498 gboolean is_target;
499 gboolean editable;
501 if( !st_on_selection_change ){
503 g_debug( "%s: button=%p, instance=%p", thisfn, ( void * ) button, ( void * ) instance );
505 g_object_get(
506 G_OBJECT( instance ),
507 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
508 TAB_UPDATABLE_PROP_EDITABLE, &editable,
509 NULL );
511 g_debug( "%s: item=%p (%s), editable=%s",
512 thisfn, ( void * ) item, item ? G_OBJECT_TYPE_NAME( item ) : "null",
513 editable ? "True":"False" );
515 if( item && NA_IS_OBJECT_ACTION( item )){
516 is_target = gtk_toggle_button_get_active( button );
518 if( editable ){
519 na_object_set_target_selection( item, is_target );
520 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, item, FALSE );
522 } else {
523 g_signal_handlers_block_by_func(( gpointer ) button, on_target_selection_toggled, instance );
524 gtk_toggle_button_set_active( button, !is_target );
525 g_signal_handlers_unblock_by_func(( gpointer ) button, on_target_selection_toggled, instance );
531 static void
532 on_target_location_toggled( GtkToggleButton *button, NactIActionTab *instance )
534 static const gchar *thisfn = "nact_iaction_tab_on_target_location_toggled";
535 NAObjectItem *item;
536 gboolean is_target;
537 gboolean editable;
539 if( !st_on_selection_change ){
541 g_debug( "%s: button=%p, instance=%p", thisfn, ( void * ) button, ( void * ) instance );
543 g_object_get(
544 G_OBJECT( instance ),
545 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
546 TAB_UPDATABLE_PROP_EDITABLE, &editable,
547 NULL );
549 g_debug( "%s: item=%p (%s), editable=%s",
550 thisfn, ( void * ) item, item ? G_OBJECT_TYPE_NAME( item ) : "null",
551 editable ? "True":"False" );
553 if( item && NA_IS_OBJECT_ACTION( item )){
554 is_target = gtk_toggle_button_get_active( button );
556 if( editable ){
557 na_object_set_target_location( item, is_target );
558 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, item, FALSE );
560 } else {
561 g_signal_handlers_block_by_func(( gpointer ) button, on_target_location_toggled, instance );
562 gtk_toggle_button_set_active( button, !is_target );
563 g_signal_handlers_unblock_by_func(( gpointer ) button, on_target_location_toggled, instance );
569 static void
570 check_for_label( NactIActionTab *instance, GtkEntry *entry, const gchar *label )
572 NAObjectItem *item;
574 g_return_if_fail( NACT_IS_IACTION_TAB( instance ));
575 g_return_if_fail( GTK_IS_ENTRY( entry ));
577 if( st_initialized && !st_finalized ){
579 nact_main_statusbar_hide_status(
580 NACT_MAIN_WINDOW( instance ),
581 IACTION_TAB_PROP_STATUS_CONTEXT );
583 set_label_label( instance, "black" );
585 g_object_get(
586 G_OBJECT( instance ),
587 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
588 NULL );
590 if( item && g_utf8_strlen( label, -1 ) == 0 ){
592 /* i18n: status bar message when the action label is empty */
593 nact_main_statusbar_display_status(
594 NACT_MAIN_WINDOW( instance ),
595 IACTION_TAB_PROP_STATUS_CONTEXT,
596 _( "Caution: a label is mandatory for the action or the menu." ));
598 set_label_label( instance, "red" );
603 static void
604 on_label_changed( GtkEntry *entry, NactIActionTab *instance )
606 NAObjectItem *item;
607 const gchar *label;
609 g_object_get(
610 G_OBJECT( instance ),
611 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
612 NULL );
614 if( item ){
615 label = gtk_entry_get_text( entry );
616 na_object_set_label( item, label );
617 check_for_label( instance, entry, label );
619 if( NA_IS_OBJECT_ACTION( item )){
620 setup_toolbar_label( instance, item, label );
623 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, item, TRUE );
627 static void
628 set_label_label( NactIActionTab *instance, const gchar *color_str )
630 GtkWidget *label;
631 GdkColor color;
633 label = base_window_get_widget( BASE_WINDOW( instance ), "ActionMenuLabelLabel" );
634 gdk_color_parse( color_str, &color );
635 gtk_widget_modify_fg( label, GTK_STATE_NORMAL, &color );
638 static void
639 on_target_toolbar_toggled( GtkToggleButton *button, NactIActionTab *instance )
641 static const gchar *thisfn = "nact_iaction_tab_on_target_toolbar_toggled";
642 NAObjectAction *item;
643 gboolean is_target;
644 gboolean editable;
646 if( !st_on_selection_change ){
648 g_debug( "%s: button=%p, instance=%p", thisfn, ( void * ) button, ( void * ) instance );
650 g_object_get(
651 G_OBJECT( instance ),
652 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
653 TAB_UPDATABLE_PROP_EDITABLE, &editable,
654 NULL );
656 g_debug( "%s: item=%p (%s), editable=%s",
657 thisfn, ( void * ) item, item ? G_OBJECT_TYPE_NAME( item ) : "null",
658 editable ? "True":"False" );
660 if( item && NA_IS_OBJECT_ACTION( item )){
661 is_target = gtk_toggle_button_get_active( button );
663 if( editable ){
664 na_object_set_target_toolbar( item, is_target );
665 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, item, FALSE );
666 toolbar_same_label_set_sensitive( instance, NA_OBJECT_ITEM( item ));
667 toolbar_label_set_sensitive( instance, NA_OBJECT_ITEM( item ));
669 } else {
670 g_signal_handlers_block_by_func(( gpointer ) button, on_target_toolbar_toggled, instance );
671 gtk_toggle_button_set_active( button, !is_target );
672 g_signal_handlers_unblock_by_func(( gpointer ) button, on_target_toolbar_toggled, instance );
678 static void
679 on_toolbar_same_label_toggled( GtkToggleButton *button, NactIActionTab *instance )
681 static const gchar *thisfn = "nact_iaction_tab_on_toolbar_same_label_toggled";
682 NAObjectItem *item;
683 gboolean same_label;
684 gboolean editable;
685 gchar *label;
686 GtkWidget *label_widget;
688 if( !st_on_selection_change ){
689 g_debug( "%s: button=%p, instance=%p", thisfn, ( void * ) button, ( void * ) instance );
691 g_object_get(
692 G_OBJECT( instance ),
693 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
694 TAB_UPDATABLE_PROP_EDITABLE, &editable,
695 NULL );
697 g_debug( "%s: item=%p (%s), editable=%s",
698 thisfn, ( void * ) item, item ? G_OBJECT_TYPE_NAME( item ) : "null",
699 editable ? "True":"False" );
701 if( item && NA_IS_OBJECT_ACTION( item )){
702 same_label = gtk_toggle_button_get_active( button );
704 if( editable ){
705 na_object_set_toolbar_same_label( NA_OBJECT_ACTION( item ), same_label );
707 if( same_label ){
708 label = na_object_get_label( item );
709 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionToolbarLabelEntry" );
710 gtk_entry_set_text( GTK_ENTRY( label_widget ), label );
711 g_free( label );
714 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, item, FALSE );
715 toolbar_same_label_set_sensitive( instance, NA_OBJECT_ITEM( item ));
716 toolbar_label_set_sensitive( instance, NA_OBJECT_ITEM( item ));
718 } else {
719 g_signal_handlers_block_by_func(( gpointer ) button, on_toolbar_same_label_toggled, instance );
720 gtk_toggle_button_set_active( button, !same_label );
721 g_signal_handlers_unblock_by_func(( gpointer ) button, on_toolbar_same_label_toggled, instance );
727 static void
728 toolbar_same_label_set_sensitive( NactIActionTab *instance, NAObjectItem *item )
730 GtkToggleButton *toggle;
731 gboolean target_toolbar;
732 gboolean readonly;
734 readonly = item ? na_object_is_readonly( item ) : FALSE;
735 toggle = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ToolbarSameLabelButton" ));
736 target_toolbar = item && NA_IS_OBJECT_ACTION( item ) ? na_object_is_target_toolbar( NA_OBJECT_ACTION( item )) : FALSE;
737 gtk_widget_set_sensitive( GTK_WIDGET( toggle ), target_toolbar && !readonly );
741 * setup the label of the toolbar according to the toolbar_same_label flag
743 static void
744 setup_toolbar_label( NactIActionTab *instance, NAObjectItem *item, const gchar *label )
746 GtkWidget *label_widget;
748 if( item && NA_IS_OBJECT_ACTION( item )){
749 if( na_object_is_toolbar_same_label( item )){
750 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionToolbarLabelEntry" );
751 gtk_entry_set_text( GTK_ENTRY( label_widget ), label );
756 static void
757 on_toolbar_label_changed( GtkEntry *entry, NactIActionTab *instance )
759 NAObjectItem *item;
760 const gchar *label;
762 g_object_get(
763 G_OBJECT( instance ),
764 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
765 NULL );
767 if( item && NA_IS_OBJECT_ACTION( item )){
768 label = gtk_entry_get_text( entry );
769 na_object_set_toolbar_label( NA_OBJECT_ACTION( item ), label );
771 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, item, FALSE );
775 static void
776 toolbar_label_set_sensitive( NactIActionTab *instance, NAObjectItem *item )
778 gboolean is_action;
779 gboolean same_label;
780 GtkWidget *label_widget;
782 is_action = item && NA_IS_OBJECT_ACTION( item );
783 same_label = is_action ? na_object_is_toolbar_same_label( NA_OBJECT_ACTION( item )) : FALSE;
784 label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionToolbarLabelEntry" );
785 gtk_widget_set_sensitive( label_widget, is_action && !same_label );
788 static void
789 on_tooltip_changed( GtkEntry *entry, NactIActionTab *instance )
791 NAObjectItem *item;
793 g_object_get(
794 G_OBJECT( instance ),
795 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
796 NULL );
798 if( item ){
799 na_object_set_tooltip( item, gtk_entry_get_text( entry ));
800 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, item, FALSE );
804 static GtkTreeModel *
805 create_stock_icon_model( void )
807 GtkStockItem stock_item;
808 gchar* label;
809 GtkListStore *model;
810 GtkTreeIter row;
811 GSList *stock_list, *iter;
812 GtkIconTheme *icon_theme;
813 GtkIconInfo *icon_info;
815 model = gtk_list_store_new( ICON_N_COLUMN, G_TYPE_STRING, G_TYPE_STRING );
817 gtk_list_store_append( model, &row );
818 /* i18n notes: when no icon is selected in the drop-down list */
819 gtk_list_store_set( model, &row, ICON_STOCK_COLUMN, "", ICON_LABEL_COLUMN, _( "None" ), -1 );
821 stock_list = gtk_stock_list_ids();
822 icon_theme = gtk_icon_theme_get_default();
823 stock_list = g_slist_sort( stock_list, ( GCompareFunc ) sort_stock_ids );
825 for( iter = stock_list ; iter ; iter = iter->next ){
826 icon_info = gtk_icon_theme_lookup_icon( icon_theme, ( gchar * ) iter->data, GTK_ICON_SIZE_MENU, GTK_ICON_LOOKUP_GENERIC_FALLBACK );
827 if( icon_info ){
828 if( gtk_stock_lookup(( gchar * ) iter->data, &stock_item )){
829 gtk_list_store_append( model, &row );
830 label = strip_underscore( stock_item.label );
831 gtk_list_store_set( model, &row, ICON_STOCK_COLUMN, ( gchar * ) iter->data, ICON_LABEL_COLUMN, label, -1 );
832 g_free( label );
834 gtk_icon_info_free( icon_info );
838 g_slist_foreach( stock_list, ( GFunc ) g_free, NULL );
839 g_slist_free( stock_list );
841 return( GTK_TREE_MODEL( model ));
844 static void
845 icon_combo_list_fill( GtkComboBoxEntry* combo )
847 GtkCellRenderer *cell_renderer_pix;
848 GtkCellRenderer *cell_renderer_text;
850 if( gtk_combo_box_entry_get_text_column( combo ) == -1 ){
851 gtk_combo_box_entry_set_text_column( combo, ICON_STOCK_COLUMN );
854 gtk_cell_layout_clear( GTK_CELL_LAYOUT( combo ));
856 cell_renderer_pix = gtk_cell_renderer_pixbuf_new();
857 gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( combo ), cell_renderer_pix, FALSE );
858 gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT( combo ), cell_renderer_pix, "stock-id", ICON_STOCK_COLUMN );
860 cell_renderer_text = gtk_cell_renderer_text_new();
861 gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( combo ), cell_renderer_text, TRUE );
862 gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT( combo ), cell_renderer_text, "text", ICON_LABEL_COLUMN );
864 gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 0 );
867 static void
868 on_icon_browse( GtkButton *button, NactIActionTab *instance )
870 GtkWidget *icon_widget;
872 icon_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconComboBoxEntry" );
874 nact_gtk_utils_select_file(
875 BASE_WINDOW( instance ),
876 _( "Choosing an icon" ), IPREFS_ICONS_DIALOG,
877 gtk_bin_get_child( GTK_BIN( icon_widget )), IPREFS_ICONS_DIALOG, "" );
880 static void
881 on_icon_changed( GtkEntry *icon_entry, NactIActionTab *instance )
883 static const gchar *thisfn = "nact_iaction_tab_on_icon_changed";
884 GtkImage *image;
885 NAObjectItem *item;
886 const gchar *icon_name;
888 g_debug( "%s: entry=%p, instance=%p", thisfn, ( void * ) icon_entry, ( void * ) instance );
890 icon_name = NULL;
892 g_object_get(
893 G_OBJECT( instance ),
894 TAB_UPDATABLE_PROP_SELECTED_ITEM, &item,
895 NULL );
897 if( item ){
898 icon_name = gtk_entry_get_text( icon_entry );
899 na_object_set_icon( item, icon_name );
900 g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, item, TRUE );
902 image = GTK_IMAGE( base_window_get_widget( BASE_WINDOW( instance ), "ActionIconImage" ));
903 nact_gtk_utils_render( icon_name, image, GTK_ICON_SIZE_MENU );
907 static gint
908 sort_stock_ids( gconstpointer a, gconstpointer b )
910 GtkStockItem stock_item_a;
911 GtkStockItem stock_item_b;
912 gchar *label_a, *label_b;
913 gboolean is_a, is_b;
914 int retv = 0;
916 is_a = gtk_stock_lookup(( gchar * ) a, &stock_item_a );
917 is_b = gtk_stock_lookup(( gchar * ) b, &stock_item_b );
919 if( is_a && !is_b ){
920 retv = 1;
922 } else if( !is_a && is_b ){
923 retv = -1;
925 } else if( !is_a && !is_b ){
926 retv = 0;
928 } else {
929 label_a = strip_underscore( stock_item_a.label );
930 label_b = strip_underscore( stock_item_b.label );
931 retv = na_core_utils_str_collate( label_a, label_b );
932 g_free( label_a );
933 g_free( label_b );
936 return( retv );
939 static gchar *
940 strip_underscore( const gchar *text )
942 /* Code from gtk-demo */
943 gchar *p, *q, *result;
945 result = g_strdup( text );
946 p = q = result;
947 while( *p ){
948 if( *p != '_' ){
949 *q = *p;
950 q++;
952 p++;
954 *q = '\0';
956 return( result );
959 static void
960 release_icon_combobox( NactIActionTab *instance )
962 GtkWidget *combo;
963 GtkTreeModel *model;
965 combo = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconComboBoxEntry" );
966 model = gtk_combo_box_get_model( GTK_COMBO_BOX( combo ));
967 gtk_list_store_clear( GTK_LIST_STORE( model ));