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.
25 * Frederic Ruaudel <grumz@grumz.net>
26 * Rodrigo Moya <rodrigo@gnome-db.org>
27 * Pierre Wieser <pwieser@trychlos.org>
28 * ... and many others (see AUTHORS)
35 #include <glib/gi18n.h>
37 #include <core/na-io-provider.h>
39 #include "nact-application.h"
40 #include "nact-iactions-list.h"
41 #include "nact-main-tab.h"
42 #include "nact-main-menubar-file.h"
44 static void save_item( NactMainWindow
*window
, NAUpdater
*updater
, NAObjectItem
*item
);
47 * nact_main_menubar_file_on_update_sensitivities:
48 * @window: the #NactMainWindow main window.
49 * user_data: the data passed to the function via the signal.
50 * @mis: the #MenubarIndicatorsStruct struct.
52 * Update sensitivity of items of the File menu.
55 nact_main_menubar_file_on_update_sensitivities( NactMainWindow
*window
, gpointer user_data
, MenubarIndicatorsStruct
*mis
)
57 static const gchar
*thisfn
= "nact_main_menubar_file_on_update_sensitivities";
58 gboolean new_item_enabled
;
59 gboolean new_profile_enabled
;
60 NAObject
*first_parent
;
61 NAObject
*selected_action
;
62 NAObject
*parent_item
;
63 gboolean is_first_parent_writable
;
64 gboolean has_modified_items
;
67 first_parent
= mis
->selected_items
&& g_list_length( mis
->selected_items
)
68 ? ( NAObject
* ) na_object_get_parent( mis
->selected_items
->data
)
70 is_first_parent_writable
= first_parent
71 ? nact_window_is_item_writable( NACT_WINDOW( window
), NA_OBJECT_ITEM( first_parent
), NULL
)
72 : mis
->is_level_zero_writable
;
74 has_modified_items
= nact_main_window_has_modified_items( window
);
75 g_debug( "%s: has_modified_items=%s", thisfn
, has_modified_items
? "True":"False" );
77 /* new menu / new action
78 * new item will be inserted just before beginning of selection
79 * parent of the first selected row must be writable
80 * we must have at least one writable provider
82 new_item_enabled
= is_first_parent_writable
&& mis
->has_writable_providers
;
83 nact_main_menubar_enable_item( window
, "NewMenuItem", new_item_enabled
);
84 nact_main_menubar_enable_item( window
, "NewActionItem", new_item_enabled
);
86 /* new profile enabled if selection is relative to only one writable action
87 * i.e. contains profile(s) of the same action, or only contains one action
88 * action must be writable
90 new_profile_enabled
= TRUE
;
91 selected_action
= NULL
;
92 for( is
= mis
->selected_items
; is
; is
= is
->next
){
94 if( NA_IS_OBJECT_MENU( is
->data
)){
95 new_profile_enabled
= FALSE
;
98 } else if( NA_IS_OBJECT_ACTION( is
->data
)){
99 if( !selected_action
){
100 selected_action
= NA_OBJECT( is
->data
);
101 } else if( selected_action
!= is
->data
){
102 new_profile_enabled
= FALSE
;
106 } else if( NA_IS_OBJECT_PROFILE( is
->data
)){
107 parent_item
= NA_OBJECT( na_object_get_parent( is
->data
));
108 if( !selected_action
){
109 selected_action
= parent_item
;
110 } else if( selected_action
!= parent_item
){
111 new_profile_enabled
= FALSE
;
116 nact_main_menubar_enable_item( window
, "NewProfileItem",
117 new_profile_enabled
&&
118 selected_action
!= NULL
&&
119 nact_window_is_item_writable( NACT_WINDOW( window
), NA_OBJECT_ITEM( selected_action
), NULL
));
121 /* save enabled if at least one item has been modified
122 * or level-zero has been resorted and is writable
124 nact_main_menubar_enable_item( window
, "SaveItem",
125 has_modified_items
|| ( mis
->level_zero_order_changed
&& mis
->is_level_zero_writable
));
127 /* quit always enabled */
131 * nact_main_menubar_file_on_new_menu:
132 * @gtk_action: the #GtkAction action.
133 * @window: the #NactMainWindow main window.
135 * Triggers File / New menu item.
138 nact_main_menubar_file_on_new_menu( GtkAction
*gtk_action
, NactMainWindow
*window
)
143 g_return_if_fail( GTK_IS_ACTION( gtk_action
));
144 g_return_if_fail( NACT_IS_MAIN_WINDOW( window
));
146 menu
= na_object_menu_new_with_defaults();
147 na_object_check_status( menu
);
148 items
= g_list_prepend( NULL
, menu
);
149 nact_iactions_list_bis_insert_items( NACT_IACTIONS_LIST( window
), items
, NULL
);
150 na_object_unref_items( items
);
154 * nact_main_menubar_file_on_new_action:
155 * @gtk_action: the #GtkAction action.
156 * @window: the #NactMainWindow main window.
158 * Triggers File / New action item.
161 nact_main_menubar_file_on_new_action( GtkAction
*gtk_action
, NactMainWindow
*window
)
163 NAObjectAction
*action
;
166 g_return_if_fail( GTK_IS_ACTION( gtk_action
));
167 g_return_if_fail( NACT_IS_MAIN_WINDOW( window
));
169 action
= na_object_action_new_with_defaults();
170 na_object_check_status( action
);
171 items
= g_list_prepend( NULL
, action
);
172 nact_iactions_list_bis_insert_items( NACT_IACTIONS_LIST( window
), items
, NULL
);
173 na_object_unref_items( items
);
177 * nact_main_menubar_file_on_new_profile:
178 * @gtk_action: the #GtkAction action.
179 * @window: the #NactMainWindow main window.
181 * Triggers File / New profile item.
184 nact_main_menubar_file_on_new_profile( GtkAction
*gtk_action
, NactMainWindow
*window
)
186 NAObjectAction
*action
;
187 NAObjectProfile
*profile
;
191 g_return_if_fail( GTK_IS_ACTION( gtk_action
));
192 g_return_if_fail( NACT_IS_MAIN_WINDOW( window
));
196 TAB_UPDATABLE_PROP_SELECTED_ITEM
, &action
,
199 profile
= na_object_profile_new_with_defaults();
200 na_object_set_label( profile
, _( "New profile" ));
202 name
= na_object_action_get_new_profile_name( action
);
203 na_object_set_id( profile
, name
);
206 /*na_object_attach_profile( action, profile );*/
208 na_object_check_status( profile
);
210 items
= g_list_prepend( NULL
, profile
);
211 nact_iactions_list_bis_insert_items( NACT_IACTIONS_LIST( window
), items
, NULL
);
212 na_object_unref_items( items
);
216 * nact_main_menubar_file_on_save:
217 * @gtk_action: the #GtkAction action.
218 * @window: the #NactMainWindow main window.
220 * Triggers File /Save item.
222 * Saving is not only saving modified items, but also saving hierarchy
223 * (and order if alpha order is not set).
225 * This is the same function that #nact_main_menubar_file_save_items(), just with
226 * different arguments.
229 nact_main_menubar_file_on_save( GtkAction
*gtk_action
, NactMainWindow
*window
)
231 static const gchar
*thisfn
= "nact_main_menubar_file_on_save";
233 g_debug( "%s: gtk_action=%p, window=%p", thisfn
, ( void * ) gtk_action
, ( void * ) window
);
234 g_return_if_fail( GTK_IS_ACTION( gtk_action
));
235 g_return_if_fail( NACT_IS_MAIN_WINDOW( window
));
237 nact_main_menubar_file_save_items( window
);
241 * nact_main_menubar_file_save_items:
242 * @gtk_action: the #GtkAction action.
243 * @window: the #NactMainWindow main window.
246 * This is the same function that #nact_main_menubar_file_on_save(), just with
247 * different arguments.
250 nact_main_menubar_file_save_items( NactMainWindow
*window
)
252 static const gchar
*thisfn
= "nact_main_menubar_file_save_items";
254 NactApplication
*application
;
256 MenubarIndicatorsStruct
*mis
;
259 NAObjectItem
*duplicate
;
261 g_return_if_fail( NACT_IS_MAIN_WINDOW( window
));
263 g_debug( "%s: window=%p", thisfn
, ( void * ) window
);
265 /* remove deleted items
266 * so that new actions with same id do not risk to be deleted later
268 nact_main_window_remove_deleted( window
);
270 /* always write the level zero list of items
271 * and reset the corresponding modification flag
273 application
= NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window
)));
274 updater
= nact_application_get_updater( application
);
275 items
= nact_iactions_list_bis_get_items( NACT_IACTIONS_LIST( window
));
277 na_pivot_write_level_zero( NA_PIVOT( updater
), items
);
278 mis
= ( MenubarIndicatorsStruct
* ) g_object_get_data( G_OBJECT( window
), MENUBAR_PROP_INDICATORS
);
279 mis
->level_zero_order_changed
= FALSE
;
281 /* recursively save the modified items
282 * check is useless here if item was not modified, but not very costly
283 * above all, it is less costly to check the status here, than to check
284 * recursively each and every modified item
288 for( it
= items
; it
; it
= it
->next
){
289 label
= na_object_get_label( it
->data
);
290 g_debug( "%s saving item %s %p (%s), modified=%s",
292 G_OBJECT_TYPE_NAME( it
->data
),
293 ( void * ) it
->data
, label
,
294 na_object_is_modified( it
->data
) ? "True":"False" );
297 save_item( window
, updater
, NA_OBJECT_ITEM( it
->data
));
299 duplicate
= NA_OBJECT_ITEM( na_object_duplicate( it
->data
));
300 na_object_reset_origin( it
->data
, duplicate
);
301 na_object_check_status( it
->data
);
302 new_pivot
= g_list_prepend( new_pivot
, duplicate
);
305 na_pivot_set_new_items( NA_PIVOT( updater
), g_list_reverse( new_pivot
));
306 g_list_free( items
);
308 /* when new_pivot is empty, then there has been no chance of updating
309 * sensibilities on check status - so force it there
312 g_signal_emit_by_name( window
, MAIN_WINDOW_SIGNAL_UPDATE_ACTION_SENSITIVITIES
, NULL
);
315 /* get ride of notification messages of IOProviders
317 na_ipivot_consumer_delay_notify( NA_IPIVOT_CONSUMER( window
));
321 * iterates here on each and every NAObjectItem row stored in the tree
323 * do not deal with profiles as they are directly managed by the action
324 * they are attached to
326 * level zero order has already been saved from tree store order, so that
327 * we actually do not care of the exact order of level zero NAPivot items
329 * saving means non-recursively save modified NAObjectItem, simultaneously
330 * reproducing the new item in NAPivot
340 * save order: A-B-C-D-E-F-G-H (first parent, then children)
343 save_item( NactMainWindow
*window
, NAUpdater
*updater
, NAObjectItem
*item
)
345 NAIOProvider
*provider_before
;
346 NAIOProvider
*provider_after
;
347 GList
*subitems
, *it
;
349 g_return_if_fail( NACT_IS_MAIN_WINDOW( window
));
350 g_return_if_fail( NA_IS_UPDATER( updater
));
351 g_return_if_fail( NA_IS_OBJECT_ITEM( item
));
353 provider_before
= na_object_get_provider( item
);
355 if( na_object_is_modified( item
) &&
356 nact_window_save_item( NACT_WINDOW( window
), item
)){
358 if( NA_IS_OBJECT_ACTION( item
)){
359 na_object_reset_last_allocated( item
);
362 nact_iactions_list_bis_remove_modified( NACT_IACTIONS_LIST( window
), item
);
364 provider_after
= na_object_get_provider( item
);
365 if( provider_after
!= provider_before
){
366 g_signal_emit_by_name( window
, TAB_UPDATABLE_SIGNAL_PROVIDER_CHANGED
, item
);
370 if( NA_IS_OBJECT_MENU( item
)){
371 subitems
= na_object_get_items( item
);
372 for( it
= subitems
; it
; it
= it
->next
){
373 save_item( window
, updater
, NA_OBJECT_ITEM( it
->data
));
379 * nact_main_menubar_file_on_quit:
380 * @gtk_action: the #GtkAction action.
381 * @window: the #NactMainWindow main window.
383 * Triggers the File / Quit item.
386 nact_main_menubar_file_on_quit( GtkAction
*gtk_action
, NactMainWindow
*window
)
388 static const gchar
*thisfn
= "nact_main_menubar_file_on_quit";
389 gboolean has_modified
;
391 g_debug( "%s: item=%p, window=%p", thisfn
, ( void * ) gtk_action
, ( void * ) window
);
392 g_return_if_fail( GTK_IS_ACTION( gtk_action
) || gtk_action
== NULL
);
393 g_return_if_fail( NACT_IS_MAIN_WINDOW( window
));
395 has_modified
= nact_main_window_has_modified_items( window
);
396 if( !has_modified
|| nact_window_warn_modified( NACT_WINDOW( window
))){
397 g_object_unref( window
);