na_updater_is_item_writable is renamed as na_updater_check_item_writability_status
[nautilus-actions.git] / src / nact / nact-main-window.c
blob22dd4b347749446cfbaa40e9d1d9e755c7c8bd70
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 <stdlib.h>
38 #include <api/na-object-api.h>
39 #include <api/na-timeout.h>
41 #include <core/na-iabout.h>
42 #include <core/na-iprefs.h>
43 #include <core/na-pivot.h>
45 #include "base-marshal.h"
46 #include "nact-iaction-tab.h"
47 #include "nact-icommand-tab.h"
48 #include "nact-ibasenames-tab.h"
49 #include "nact-imimetypes-tab.h"
50 #include "nact-ifolders-tab.h"
51 #include "nact-ischemes-tab.h"
52 #include "nact-icapabilities-tab.h"
53 #include "nact-ienvironment-tab.h"
54 #include "nact-iexecution-tab.h"
55 #include "nact-iproperties-tab.h"
56 #include "nact-main-tab.h"
57 #include "nact-main-statusbar.h"
58 #include "nact-main-window.h"
59 #include "nact-menubar.h"
60 #include "nact-tree-view.h"
61 #include "nact-confirm-logout.h"
62 #include "nact-sort-buttons.h"
64 /* private class data
66 struct _NactMainWindowClassPrivate {
67 void *empty; /* so that gcc -pedantic is happy */
70 /* private instance data
72 struct _NactMainWindowPrivate {
73 gboolean dispose_has_run;
75 NAUpdater *updater;
77 /**
78 * Current action or menu.
80 * This is the action or menu which is displayed in tabs Action/Menu
81 * and Properties ; it may be different of the exact row being currently
82 * selected, e.g. when a sub-profile is edited.
84 * Can be null, and this implies that @current_profile is also null,
85 * e.g. when the list is empty or in the case of a multiple selection.
87 * 'editable' property is set on selection change;
88 * This is the actual current writability status of the item at this time.
90 NAObjectItem *current_item;
91 gboolean editable;
92 guint reason;
94 /**
95 * Current profile.
97 * This is the profile which is displayed in tab Command;
98 * it may be different of the exact row being currently selected,
99 * e.g. when an action with only one profile is selected.
101 * Can be null if @current_item is a menu, or an action with more
102 * than one profile is selected, or the list is empty, or in the
103 * case of a multiple selection.
105 * In other words, it is not null if:
106 * a) a profile is selected,
107 * b) an action is selected and it has exactly one profile.
109 NAObjectProfile *current_profile;
112 * Current context.
114 * This is the #NAIContext data which corresponds to @current_profile
115 * or @current_item, depending of which one is actually selected.
117 NAIContext *current_context;
120 * Some convenience objects and data.
122 NactTreeView *items_view;
123 gboolean is_tree_modified;
124 NactClipboard *clipboard;
125 NactMenubar *menubar;
127 gulong pivot_handler_id;
128 NATimeout pivot_timeout;
131 /* properties set against the main window
132 * these are set on selection changes
134 enum {
135 MAIN_PROP_0 = 0,
137 MAIN_PROP_ITEM_ID,
138 MAIN_PROP_PROFILE_ID,
139 MAIN_PROP_CONTEXT_ID,
140 MAIN_PROP_EDITABLE_ID,
141 MAIN_PROP_REASON_ID,
143 MAIN_PROP_N_PROPERTIES
146 /* signals
148 enum {
149 MAIN_ITEM_UPDATED,
150 TAB_ITEM_UPDATED,
151 SELECTION_CHANGED,
152 LAST_SIGNAL
155 static const gchar *st_xmlui_filename = PKGDATADIR "/nautilus-actions-config-tool.ui";
156 static const gchar *st_toplevel_name = "MainWindow";
157 static const gchar *st_wsp_name = NA_IPREFS_MAIN_WINDOW_WSP;
159 static gint st_burst_timeout = 2500; /* burst timeout in msec */
160 static BaseWindowClass *st_parent_class = NULL;
161 static gint st_signals[ LAST_SIGNAL ] = { 0 };
163 static GType register_type( void );
164 static void class_init( NactMainWindowClass *klass );
165 static void iaction_tab_iface_init( NactIActionTabInterface *iface );
166 static void icommand_tab_iface_init( NactICommandTabInterface *iface );
167 static void ibasenames_tab_iface_init( NactIBasenamesTabInterface *iface );
168 static void imimetypes_tab_iface_init( NactIMimetypesTabInterface *iface );
169 static void ifolders_tab_iface_init( NactIFoldersTabInterface *iface );
170 static void ischemes_tab_iface_init( NactISchemesTabInterface *iface );
171 static void icapabilities_tab_iface_init( NactICapabilitiesTabInterface *iface );
172 static void ienvironment_tab_iface_init( NactIEnvironmentTabInterface *iface );
173 static void iexecution_tab_iface_init( NactIExecutionTabInterface *iface );
174 static void iproperties_tab_iface_init( NactIPropertiesTabInterface *iface );
175 static void iabout_iface_init( NAIAboutInterface *iface );
176 static void instance_init( GTypeInstance *instance, gpointer klass );
177 static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
178 static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
179 static void instance_constructed( GObject *application );
180 static void instance_dispose( GObject *application );
181 static void instance_finalize( GObject *application );
183 static void on_base_initialize_gtk_toplevel( NactMainWindow *window, GtkWindow *toplevel, gpointer user_data );
184 static void on_base_initialize_base_window( NactMainWindow *window, gpointer user_data );
185 static void on_base_all_widgets_showed( NactMainWindow *window, gpointer user_data );
187 static void on_block_items_changed_timeout( NactMainWindow *window );
188 static void on_tree_view_modified_status_changed( NactMainWindow *window, gboolean is_modified, gpointer user_data );
189 static void on_tree_view_selection_changed( NactMainWindow *window, GList *selected_items, gpointer user_data );
190 static void on_selection_changed_cleanup_handler( BaseWindow *window, GList *selected_items );
191 static void on_tab_updatable_item_updated( NactMainWindow *window, NAIContext *context, guint data, gpointer user_data );
192 static void raz_selection_properties( NactMainWindow *window );
193 static void setup_current_selection( NactMainWindow *window, NAObjectId *selected_row );
194 static void setup_dialog_title( NactMainWindow *window );
195 static void setup_writability_status( NactMainWindow *window );
197 /* items have changed */
198 static void on_pivot_items_changed( NAUpdater *updater, NactMainWindow *window );
199 static gboolean confirm_for_giveup_from_pivot( const NactMainWindow *window );
200 static gboolean confirm_for_giveup_from_menu( const NactMainWindow *window );
201 static void load_or_reload_items( NactMainWindow *window );
203 /* application termination */
204 static gboolean on_base_is_willing_to_quit( const BaseWindow *window, gconstpointer user_data );
205 static gboolean on_delete_event( GtkWidget *toplevel, GdkEvent *event, NactMainWindow *window );
206 static gboolean warn_modified( NactMainWindow *window );
208 /* NAIAbout interface */
209 static gchar *iabout_get_application_name( NAIAbout *instance );
210 static GtkWindow *iabout_get_toplevel( NAIAbout *instance );
213 GType
214 nact_main_window_get_type( void )
216 static GType window_type = 0;
218 if( !window_type ){
219 window_type = register_type();
222 return( window_type );
225 static GType
226 register_type( void )
228 static const gchar *thisfn = "nact_main_window_register_type";
229 GType type;
231 static GTypeInfo info = {
232 sizeof( NactMainWindowClass ),
233 ( GBaseInitFunc ) NULL,
234 ( GBaseFinalizeFunc ) NULL,
235 ( GClassInitFunc ) class_init,
236 NULL,
237 NULL,
238 sizeof( NactMainWindow ),
240 ( GInstanceInitFunc ) instance_init
243 static const GInterfaceInfo iaction_tab_iface_info = {
244 ( GInterfaceInitFunc ) iaction_tab_iface_init,
245 NULL,
246 NULL
249 static const GInterfaceInfo icommand_tab_iface_info = {
250 ( GInterfaceInitFunc ) icommand_tab_iface_init,
251 NULL,
252 NULL
255 static const GInterfaceInfo ibasenames_tab_iface_info = {
256 ( GInterfaceInitFunc ) ibasenames_tab_iface_init,
257 NULL,
258 NULL
261 static const GInterfaceInfo imimetypes_tab_iface_info = {
262 ( GInterfaceInitFunc ) imimetypes_tab_iface_init,
263 NULL,
264 NULL
267 static const GInterfaceInfo ifolders_tab_iface_info = {
268 ( GInterfaceInitFunc ) ifolders_tab_iface_init,
269 NULL,
270 NULL
273 static const GInterfaceInfo ischemes_tab_iface_info = {
274 ( GInterfaceInitFunc ) ischemes_tab_iface_init,
275 NULL,
276 NULL
279 static const GInterfaceInfo icapabilities_tab_iface_info = {
280 ( GInterfaceInitFunc ) icapabilities_tab_iface_init,
281 NULL,
282 NULL
285 static const GInterfaceInfo ienvironment_tab_iface_info = {
286 ( GInterfaceInitFunc ) ienvironment_tab_iface_init,
287 NULL,
288 NULL
291 static const GInterfaceInfo iexecution_tab_iface_info = {
292 ( GInterfaceInitFunc ) iexecution_tab_iface_init,
293 NULL,
294 NULL
297 static const GInterfaceInfo iproperties_tab_iface_info = {
298 ( GInterfaceInitFunc ) iproperties_tab_iface_init,
299 NULL,
300 NULL
303 static const GInterfaceInfo iabout_iface_info = {
304 ( GInterfaceInitFunc ) iabout_iface_init,
305 NULL,
306 NULL
309 g_debug( "%s", thisfn );
311 type = g_type_register_static( BASE_WINDOW_TYPE, "NactMainWindow", &info, 0 );
313 g_type_add_interface_static( type, NACT_IACTION_TAB_TYPE, &iaction_tab_iface_info );
315 g_type_add_interface_static( type, NACT_ICOMMAND_TAB_TYPE, &icommand_tab_iface_info );
317 g_type_add_interface_static( type, NACT_IBASENAMES_TAB_TYPE, &ibasenames_tab_iface_info );
319 g_type_add_interface_static( type, NACT_IMIMETYPES_TAB_TYPE, &imimetypes_tab_iface_info );
321 g_type_add_interface_static( type, NACT_IFOLDERS_TAB_TYPE, &ifolders_tab_iface_info );
323 g_type_add_interface_static( type, NACT_ISCHEMES_TAB_TYPE, &ischemes_tab_iface_info );
325 g_type_add_interface_static( type, NACT_ICAPABILITIES_TAB_TYPE, &icapabilities_tab_iface_info );
327 g_type_add_interface_static( type, NACT_IENVIRONMENT_TAB_TYPE, &ienvironment_tab_iface_info );
329 g_type_add_interface_static( type, NACT_IEXECUTION_TAB_TYPE, &iexecution_tab_iface_info );
331 g_type_add_interface_static( type, NACT_IPROPERTIES_TAB_TYPE, &iproperties_tab_iface_info );
333 g_type_add_interface_static( type, NA_IABOUT_TYPE, &iabout_iface_info );
335 return( type );
338 static void
339 class_init( NactMainWindowClass *klass )
341 static const gchar *thisfn = "nact_main_window_class_init";
342 GObjectClass *object_class;
344 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
346 st_parent_class = g_type_class_peek_parent( klass );
348 object_class = G_OBJECT_CLASS( klass );
349 object_class->set_property = instance_set_property;
350 object_class->get_property = instance_get_property;
351 object_class->constructed = instance_constructed;
352 object_class->dispose = instance_dispose;
353 object_class->finalize = instance_finalize;
355 g_object_class_install_property( object_class, MAIN_PROP_ITEM_ID,
356 g_param_spec_pointer(
357 MAIN_PROP_ITEM,
358 "Current NAObjectItem",
359 "A pointer to the currently edited NAObjectItem, an action or a menu",
360 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE ));
362 g_object_class_install_property( object_class, MAIN_PROP_PROFILE_ID,
363 g_param_spec_pointer(
364 MAIN_PROP_PROFILE,
365 "Current NAObjectProfile",
366 "A pointer to the currently edited NAObjectProfile",
367 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE ));
369 g_object_class_install_property( object_class, MAIN_PROP_CONTEXT_ID,
370 g_param_spec_pointer(
371 MAIN_PROP_CONTEXT,
372 "Current NAIContext",
373 "A pointer to the currently edited NAIContext",
374 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE ));
376 g_object_class_install_property( object_class, MAIN_PROP_EDITABLE_ID,
377 g_param_spec_boolean(
378 MAIN_PROP_EDITABLE,
379 "Editable item ?",
380 "Whether the item will be able to be updated against its I/O provider", FALSE,
381 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE ));
383 g_object_class_install_property( object_class, MAIN_PROP_REASON_ID,
384 g_param_spec_int(
385 MAIN_PROP_REASON,
386 "No edition reason",
387 "Why is this item not editable", 0, 255, 0,
388 G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE ));
390 klass->private = g_new0( NactMainWindowClassPrivate, 1 );
393 * NactMainWindow::main-item-updated:
395 * This signal is emitted on the BaseWindow when the item has been modified
396 * elsewhere that in a tab. The tabs should so update accordingly their
397 * widgets.
399 * Args:
400 * - an OR-ed list of the modified data, or 0 if not relevant.
402 st_signals[ MAIN_ITEM_UPDATED ] = g_signal_new(
403 MAIN_SIGNAL_ITEM_UPDATED,
404 G_TYPE_OBJECT,
405 G_SIGNAL_RUN_LAST,
406 0, /* no default handler */
407 NULL,
408 NULL,
409 nact_cclosure_marshal_VOID__POINTER_UINT,
410 G_TYPE_NONE,
412 G_TYPE_POINTER,
413 G_TYPE_UINT );
416 * nact-tab-updatable-item-updated:
418 * This signal is emitted by the notebook tabs, when any property
419 * of an item has been modified.
421 * Args:
422 * - an OR-ed list of the modified data, or 0 if not relevant.
424 * This main window is rather the only consumer of this message,
425 * does its tricks (title, etc.), and then reforward an item-updated
426 * message to IActionsList.
428 st_signals[ TAB_ITEM_UPDATED ] = g_signal_new(
429 TAB_UPDATABLE_SIGNAL_ITEM_UPDATED,
430 G_TYPE_OBJECT,
431 G_SIGNAL_RUN_LAST,
432 0, /* no default handler */
433 NULL,
434 NULL,
435 nact_cclosure_marshal_VOID__POINTER_UINT,
436 G_TYPE_NONE,
438 G_TYPE_POINTER,
439 G_TYPE_UINT );
442 * NactMainWindow::main-selection-changed:
444 * This signal is emitted on the window parent each time the selection
445 * has changed in the treeview, after having set the current item/profile/
446 * context properties.
448 * This way, we are sure that notebook edition tabs which required to
449 * have a current item/profile/context will have it, whenever they have
450 * connected to the 'selection-changed' signal.
452 * Signal args:
453 * - a #GList of currently selected #NAObjectItems.
455 * Handler prototype:
456 * void ( *handler )( BaseWindow *window, GList *selected, gpointer user_data );
458 st_signals[ SELECTION_CHANGED ] = g_signal_new_class_handler(
459 MAIN_SIGNAL_SELECTION_CHANGED,
460 G_TYPE_OBJECT,
461 G_SIGNAL_RUN_CLEANUP,
462 G_CALLBACK( on_selection_changed_cleanup_handler ),
463 NULL,
464 NULL,
465 g_cclosure_marshal_VOID__POINTER,
466 G_TYPE_NONE,
468 G_TYPE_POINTER );
471 static void
472 iaction_tab_iface_init( NactIActionTabInterface *iface )
474 static const gchar *thisfn = "nact_main_window_iaction_tab_iface_init";
476 g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
479 static void
480 icommand_tab_iface_init( NactICommandTabInterface *iface )
482 static const gchar *thisfn = "nact_main_window_icommand_tab_iface_init";
484 g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
487 static void
488 ibasenames_tab_iface_init( NactIBasenamesTabInterface *iface )
490 static const gchar *thisfn = "nact_main_window_ibasenames_tab_iface_init";
492 g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
495 static void
496 imimetypes_tab_iface_init( NactIMimetypesTabInterface *iface )
498 static const gchar *thisfn = "nact_main_window_imimetypes_tab_iface_init";
500 g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
503 static void
504 ifolders_tab_iface_init( NactIFoldersTabInterface *iface )
506 static const gchar *thisfn = "nact_main_window_ifolders_tab_iface_init";
508 g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
511 static void
512 ischemes_tab_iface_init( NactISchemesTabInterface *iface )
514 static const gchar *thisfn = "nact_main_window_ischemes_tab_iface_init";
516 g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
519 static void
520 icapabilities_tab_iface_init( NactICapabilitiesTabInterface *iface )
522 static const gchar *thisfn = "nact_main_window_icapabilities_tab_iface_init";
524 g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
527 static void
528 ienvironment_tab_iface_init( NactIEnvironmentTabInterface *iface )
530 static const gchar *thisfn = "nact_main_window_ienvironment_tab_iface_init";
532 g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
535 static void
536 iexecution_tab_iface_init( NactIExecutionTabInterface *iface )
538 static const gchar *thisfn = "nact_main_window_iexecution_tab_iface_init";
540 g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
543 static void
544 iproperties_tab_iface_init( NactIPropertiesTabInterface *iface )
546 static const gchar *thisfn = "nact_main_window_iproperties_tab_iface_init";
548 g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
551 static void
552 iabout_iface_init( NAIAboutInterface *iface )
554 static const gchar *thisfn = "nact_main_window_iabout_iface_init";
556 g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
558 iface->get_application_name = iabout_get_application_name;
559 iface->get_toplevel = iabout_get_toplevel;
562 static void
563 instance_init( GTypeInstance *instance, gpointer klass )
565 static const gchar *thisfn = "nact_main_window_instance_init";
566 NactMainWindow *self;
568 g_return_if_fail( NACT_IS_MAIN_WINDOW( instance ));
570 g_debug( "%s: instance=%p (%s), klass=%p",
571 thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
573 self = NACT_MAIN_WINDOW( instance );
575 self->private = g_new0( NactMainWindowPrivate, 1 );
577 self->private->dispose_has_run = FALSE;
579 /* initialize timeout parameters when blocking 'pivot-items-changed' handler
581 self->private->pivot_timeout.timeout = st_burst_timeout;
582 self->private->pivot_timeout.handler = ( NATimeoutFunc ) on_block_items_changed_timeout;
583 self->private->pivot_timeout.user_data = self;
584 self->private->pivot_timeout.source_id = 0;
587 static void
588 instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
590 NactMainWindow *self;
592 g_return_if_fail( NACT_IS_MAIN_WINDOW( object ));
593 self = NACT_MAIN_WINDOW( object );
595 if( !self->private->dispose_has_run ){
597 switch( property_id ){
598 case MAIN_PROP_ITEM_ID:
599 g_value_set_pointer( value, self->private->current_item );
600 break;
602 case MAIN_PROP_PROFILE_ID:
603 g_value_set_pointer( value, self->private->current_profile );
604 break;
606 case MAIN_PROP_CONTEXT_ID:
607 g_value_set_pointer( value, self->private->current_context );
608 break;
610 case MAIN_PROP_EDITABLE_ID:
611 g_value_set_boolean( value, self->private->editable );
612 break;
614 case MAIN_PROP_REASON_ID:
615 g_value_set_int( value, self->private->reason );
616 break;
618 default:
619 G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
620 break;
625 static void
626 instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
628 NactMainWindow *self;
630 g_return_if_fail( NACT_IS_MAIN_WINDOW( object ));
631 self = NACT_MAIN_WINDOW( object );
633 if( !self->private->dispose_has_run ){
635 switch( property_id ){
636 case MAIN_PROP_ITEM_ID:
637 self->private->current_item = g_value_get_pointer( value );
638 break;
640 case MAIN_PROP_PROFILE_ID:
641 self->private->current_profile = g_value_get_pointer( value );
642 break;
644 case MAIN_PROP_CONTEXT_ID:
645 self->private->current_context = g_value_get_pointer( value );
646 break;
648 case MAIN_PROP_EDITABLE_ID:
649 self->private->editable = g_value_get_boolean( value );
650 break;
652 case MAIN_PROP_REASON_ID:
653 self->private->reason = g_value_get_int( value );
654 break;
656 default:
657 G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
658 break;
663 static void
664 instance_constructed( GObject *window )
666 static const gchar *thisfn = "nact_main_window_instance_constructed";
667 NactMainWindow *self;
668 NactApplication *application;
670 g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
672 self = NACT_MAIN_WINDOW( window );
674 if( !self->private->dispose_has_run ){
675 g_debug( "%s: window=%p (%s)", thisfn, ( void * ) window, G_OBJECT_TYPE_NAME( window ));
677 /* first connect to BaseWindow signals
678 * so that convenience objects instanciated later will have this same signal
679 * triggered after the one of NactMainWindow
681 base_window_signal_connect( BASE_WINDOW( window ),
682 G_OBJECT( window ), BASE_SIGNAL_INITIALIZE_GTK, G_CALLBACK( on_base_initialize_gtk_toplevel ));
684 base_window_signal_connect( BASE_WINDOW( window ),
685 G_OBJECT( window ), BASE_SIGNAL_INITIALIZE_WINDOW, G_CALLBACK( on_base_initialize_base_window ));
687 base_window_signal_connect( BASE_WINDOW( window ),
688 G_OBJECT( window ), BASE_SIGNAL_ALL_WIDGETS_SHOWED, G_CALLBACK( on_base_all_widgets_showed ));
690 application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
691 self->private->updater = nact_application_get_updater( application );
693 self->private->pivot_handler_id = base_window_signal_connect( BASE_WINDOW( window ),
694 G_OBJECT( self->private->updater ), PIVOT_SIGNAL_ITEMS_CHANGED, G_CALLBACK( on_pivot_items_changed ));
696 base_window_signal_connect( BASE_WINDOW( window ),
697 G_OBJECT( window ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, G_CALLBACK( on_tab_updatable_item_updated ));
699 /* create the tree view which will create itself its own tree model
701 self->private->items_view = nact_tree_view_new( BASE_WINDOW( window ), "ActionsList", TREE_MODE_EDITION );
703 base_window_signal_connect( BASE_WINDOW( window ),
704 G_OBJECT( window ), TREE_SIGNAL_SELECTION_CHANGED, G_CALLBACK( on_tree_view_selection_changed ));
706 base_window_signal_connect( BASE_WINDOW( window ),
707 G_OBJECT( window ), TREE_SIGNAL_MODIFIED_STATUS_CHANGED, G_CALLBACK( on_tree_view_modified_status_changed ));
709 /* create the menubar and other convenience objects
711 self->private->menubar = nact_menubar_new( BASE_WINDOW( window ));
712 self->private->clipboard = nact_clipboard_new( BASE_WINDOW( window ));
714 /* chain up to the parent class */
715 if( G_OBJECT_CLASS( st_parent_class )->constructed ){
716 G_OBJECT_CLASS( st_parent_class )->constructed( window );
721 static void
722 instance_dispose( GObject *window )
724 static const gchar *thisfn = "nact_main_window_instance_dispose";
725 NactMainWindow *self;
726 GtkWidget *pane;
727 gint pos;
728 NASettings *settings;
730 g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
732 self = NACT_MAIN_WINDOW( window );
734 if( !self->private->dispose_has_run ){
735 g_debug( "%s: window=%p (%s)", thisfn, ( void * ) window, G_OBJECT_TYPE_NAME( window ));
737 self->private->dispose_has_run = TRUE;
739 g_object_unref( self->private->clipboard );
740 g_object_unref( self->private->menubar );
742 settings = na_pivot_get_settings( NA_PIVOT( self->private->updater ));
744 pane = base_window_get_widget( BASE_WINDOW( window ), "MainPaned" );
745 pos = gtk_paned_get_position( GTK_PANED( pane ));
746 na_settings_set_uint( settings, NA_IPREFS_MAIN_PANED, pos );
748 nact_iaction_tab_dispose( NACT_IACTION_TAB( window ));
749 nact_icommand_tab_dispose( NACT_ICOMMAND_TAB( window ));
750 nact_ibasenames_tab_dispose( NACT_IBASENAMES_TAB( window ));
751 nact_imimetypes_tab_dispose( NACT_IMIMETYPES_TAB( window ));
752 nact_ifolders_tab_dispose( NACT_IFOLDERS_TAB( window ));
753 nact_ischemes_tab_dispose( NACT_ISCHEMES_TAB( window ));
754 nact_icapabilities_tab_dispose( NACT_ICAPABILITIES_TAB( window ));
755 nact_ienvironment_tab_dispose( NACT_IENVIRONMENT_TAB( window ));
756 nact_iexecution_tab_dispose( NACT_IEXECUTION_TAB( window ));
757 nact_iproperties_tab_dispose( NACT_IPROPERTIES_TAB( window ));
759 /* unref items view at last as gtk_tree_model_store_clear() will
760 * finalize all objects, thus invaliditing all our references
762 g_object_unref( self->private->items_view );
764 /* chain up to the parent class */
765 if( G_OBJECT_CLASS( st_parent_class )->dispose ){
766 G_OBJECT_CLASS( st_parent_class )->dispose( window );
771 static void
772 instance_finalize( GObject *window )
774 static const gchar *thisfn = "nact_main_window_instance_finalize";
775 NactMainWindow *self;
777 g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
779 g_debug( "%s: window=%p (%s)", thisfn, ( void * ) window, G_OBJECT_TYPE_NAME( window ));
781 self = NACT_MAIN_WINDOW( window );
783 g_free( self->private );
785 /* chain call to parent class */
786 if( G_OBJECT_CLASS( st_parent_class )->finalize ){
787 G_OBJECT_CLASS( st_parent_class )->finalize( window );
792 * Returns a newly allocated NactMainWindow object.
794 NactMainWindow *
795 nact_main_window_new( const NactApplication *application )
797 NactMainWindow *window;
799 g_return_val_if_fail( NACT_IS_APPLICATION( application ), NULL );
801 window = g_object_new( NACT_MAIN_WINDOW_TYPE,
802 BASE_PROP_APPLICATION, application,
803 BASE_PROP_XMLUI_FILENAME, st_xmlui_filename,
804 BASE_PROP_TOPLEVEL_NAME, st_toplevel_name,
805 BASE_PROP_WSP_NAME, st_wsp_name,
806 NULL );
808 return( window );
812 * note that for this NactMainWindow, on_base_initialize_gtk_toplevel() and
813 * on_base_initialize_base_window() are roughly equivalent, as there is only
814 * one occurrence on this window in the application: closing this window
815 * is the same than quitting the application
817 static void
818 on_base_initialize_gtk_toplevel( NactMainWindow *window, GtkWindow *toplevel, gpointer user_data )
820 static const gchar *thisfn = "nact_main_window_on_base_initialize_gtk_toplevel";
822 g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
824 if( !window->private->dispose_has_run ){
825 g_debug( "%s: window=%p, toplevel=%p, user_data=%p",
826 thisfn, ( void * ) window, ( void * ) toplevel, ( void * ) user_data );
828 nact_iaction_tab_initial_load_toplevel( NACT_IACTION_TAB( window ));
829 nact_icommand_tab_initial_load_toplevel( NACT_ICOMMAND_TAB( window ));
830 nact_ibasenames_tab_initial_load_toplevel( NACT_IBASENAMES_TAB( window ));
831 nact_imimetypes_tab_initial_load_toplevel( NACT_IMIMETYPES_TAB( window ));
832 nact_ifolders_tab_initial_load_toplevel( NACT_IFOLDERS_TAB( window ));
833 nact_ischemes_tab_initial_load_toplevel( NACT_ISCHEMES_TAB( window ));
834 nact_icapabilities_tab_initial_load_toplevel( NACT_ICAPABILITIES_TAB( window ));
835 nact_ienvironment_tab_initial_load_toplevel( NACT_IENVIRONMENT_TAB( window ));
836 nact_iexecution_tab_initial_load_toplevel( NACT_IEXECUTION_TAB( window ));
837 nact_iproperties_tab_initial_load_toplevel( NACT_IPROPERTIES_TAB( window ));
839 nact_main_statusbar_initialize_gtk_toplevel( window );
843 static void
844 on_base_initialize_base_window( NactMainWindow *window, gpointer user_data )
846 static const gchar *thisfn = "nact_main_window_on_base_initialize_base_window";
847 NASettings *settings;
848 guint pos;
849 GtkWidget *pane;
851 g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
853 if( !window->private->dispose_has_run ){
854 g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
856 settings = na_pivot_get_settings( NA_PIVOT( window->private->updater ));
858 pos = na_settings_get_uint( settings, NA_IPREFS_MAIN_PANED, NULL, NULL );
859 if( pos ){
860 pane = base_window_get_widget( BASE_WINDOW( window ), "MainPaned" );
861 gtk_paned_set_position( GTK_PANED( pane ), pos );
864 nact_iaction_tab_runtime_init_toplevel( NACT_IACTION_TAB( window ));
865 nact_icommand_tab_runtime_init_toplevel( NACT_ICOMMAND_TAB( window ));
866 nact_ibasenames_tab_runtime_init_toplevel( NACT_IBASENAMES_TAB( window ));
867 nact_imimetypes_tab_runtime_init_toplevel( NACT_IMIMETYPES_TAB( window ));
868 nact_ifolders_tab_runtime_init_toplevel( NACT_IFOLDERS_TAB( window ));
869 nact_ischemes_tab_runtime_init_toplevel( NACT_ISCHEMES_TAB( window ));
870 nact_icapabilities_tab_runtime_init_toplevel( NACT_ICAPABILITIES_TAB( window ));
871 nact_ienvironment_tab_runtime_init_toplevel( NACT_IENVIRONMENT_TAB( window ));
872 nact_iexecution_tab_runtime_init_toplevel( NACT_IEXECUTION_TAB( window ));
873 nact_iproperties_tab_runtime_init_toplevel( NACT_IPROPERTIES_TAB( window ));
875 /* terminate the application by clicking the top right [X] button
877 base_window_signal_connect( BASE_WINDOW( window ),
878 G_OBJECT( base_window_get_gtk_toplevel( BASE_WINDOW( window ))),
879 "delete-event", G_CALLBACK( on_delete_event ));
881 /* is willing to quit ?
883 base_window_signal_connect( BASE_WINDOW( window ),
884 G_OBJECT( window ), BASE_SIGNAL_WILLING_TO_QUIT, G_CALLBACK( on_base_is_willing_to_quit ));
888 static void
889 on_base_all_widgets_showed( NactMainWindow *window, gpointer user_data )
891 static const gchar *thisfn = "nact_main_window_on_base_all_widgets_showed";
893 g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
894 g_return_if_fail( NACT_IS_IACTION_TAB( window ));
895 g_return_if_fail( NACT_IS_ICOMMAND_TAB( window ));
896 g_return_if_fail( NACT_IS_IBASENAMES_TAB( window ));
897 g_return_if_fail( NACT_IS_IMIMETYPES_TAB( window ));
898 g_return_if_fail( NACT_IS_IFOLDERS_TAB( window ));
899 g_return_if_fail( NACT_IS_ISCHEMES_TAB( window ));
900 g_return_if_fail( NACT_IS_IENVIRONMENT_TAB( window ));
901 g_return_if_fail( NACT_IS_IEXECUTION_TAB( window ));
902 g_return_if_fail( NACT_IS_IPROPERTIES_TAB( window ));
904 if( !window->private->dispose_has_run ){
905 g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
907 nact_iaction_tab_all_widgets_showed( NACT_IACTION_TAB( window ));
908 nact_icommand_tab_all_widgets_showed( NACT_ICOMMAND_TAB( window ));
909 nact_ibasenames_tab_all_widgets_showed( NACT_IBASENAMES_TAB( window ));
910 nact_imimetypes_tab_all_widgets_showed( NACT_IMIMETYPES_TAB( window ));
911 nact_ifolders_tab_all_widgets_showed( NACT_IFOLDERS_TAB( window ));
912 nact_ischemes_tab_all_widgets_showed( NACT_ISCHEMES_TAB( window ));
913 nact_icapabilities_tab_all_widgets_showed( NACT_ICAPABILITIES_TAB( window ));
914 nact_ienvironment_tab_all_widgets_showed( NACT_IENVIRONMENT_TAB( window ));
915 nact_iexecution_tab_all_widgets_showed( NACT_IEXECUTION_TAB( window ));
916 nact_iproperties_tab_all_widgets_showed( NACT_IPROPERTIES_TAB( window ));
918 load_or_reload_items( window );
923 * nact_main_window_get_clipboard:
924 * @window: this #NactMainWindow instance.
926 * Returns: the #NactClipboard convenience object.
928 NactClipboard *
929 nact_main_window_get_clipboard( const NactMainWindow *window )
931 NactClipboard *clipboard;
933 g_return_val_if_fail( NACT_IS_MAIN_WINDOW( window ), NULL );
935 clipboard = NULL;
937 if( !window->private->dispose_has_run ){
939 clipboard = window->private->clipboard;
942 return( clipboard );
946 * nact_main_window_get_items_view:
947 * @window: this #NactMainWindow instance.
949 * Returns: The #NactTreeView convenience object.
951 NactTreeView *
952 nact_main_window_get_items_view( const NactMainWindow *window )
954 NactTreeView *view;
956 g_return_val_if_fail( NACT_IS_MAIN_WINDOW( window ), NULL );
958 view = NULL;
960 if( !window->private->dispose_has_run ){
962 view = window->private->items_view;
965 return( view );
969 * nact_main_window_reload:
970 * @window: this #NactMainWindow instance.
972 * Refresh the list of items.
973 * If there is some non-yet saved modifications, a confirmation is
974 * required before giving up with them.
976 void
977 nact_main_window_reload( NactMainWindow *window )
979 gboolean reload_ok;
981 g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
983 if( !window->private->dispose_has_run ){
985 reload_ok = confirm_for_giveup_from_menu( window );
987 if( reload_ok ){
988 load_or_reload_items( window );
994 * nact_main_window_block_reload:
995 * @window: this #NactMainWindow instance.
997 * Temporarily blocks the handling of pivot-items-changed signal.
999 void
1000 nact_main_window_block_reload( NactMainWindow *window )
1002 static const gchar *thisfn = "nact_main_window_block_reload";
1004 g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
1006 if( !window->private->dispose_has_run ){
1008 g_debug( "%s: blocking %s signal", thisfn, PIVOT_SIGNAL_ITEMS_CHANGED );
1009 g_signal_handler_block( window->private->updater, window->private->pivot_handler_id );
1010 na_timeout_event( &window->private->pivot_timeout );
1014 static void
1015 on_block_items_changed_timeout( NactMainWindow *window )
1017 static const gchar *thisfn = "nact_main_window_on_block_items_changed_timeout";
1019 g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
1021 g_debug( "%s: unblocking %s signal", thisfn, PIVOT_SIGNAL_ITEMS_CHANGED );
1022 g_signal_handler_unblock( window->private->updater, window->private->pivot_handler_id );
1026 * the modification status of the items view has changed
1028 static void
1029 on_tree_view_modified_status_changed( NactMainWindow *window, gboolean is_modified, gpointer user_data )
1031 static const gchar *thisfn = "nact_main_window_on_tree_view_modified_status_changed";
1033 g_debug( "%s: window=%p, is_modified=%s, user_data=%p",
1034 thisfn, ( void * ) window, is_modified ? "True":"False", ( void * ) user_data );
1036 if( !window->private->dispose_has_run ){
1038 window->private->is_tree_modified = is_modified;
1039 setup_dialog_title( window );
1044 * tree view selection has changed
1046 static void
1047 on_tree_view_selection_changed( NactMainWindow *window, GList *selected_items, gpointer user_data )
1049 static const gchar *thisfn = "nact_main_window_on_tree_view_selection_changed";
1050 guint count;
1052 count = g_list_length( selected_items );
1054 if( !window->private->dispose_has_run ){
1055 g_debug( "%s: window=%p, selected_items=%p (count=%d), user_data=%p",
1056 thisfn, ( void * ) window,
1057 ( void * ) selected_items, count, ( void * ) user_data );
1059 raz_selection_properties( window );
1061 if( count == 1 ){
1062 g_return_if_fail( NA_IS_OBJECT_ID( selected_items->data ));
1063 setup_current_selection( window, NA_OBJECT_ID( selected_items->data ));
1064 setup_writability_status( window );
1067 setup_dialog_title( window );
1069 g_signal_emit_by_name( G_OBJECT( window ),
1070 MAIN_SIGNAL_SELECTION_CHANGED, na_object_copyref_items( selected_items ));
1075 * cleanup handler for our MAIN_SIGNAL_SELECTION_CHANGED signal
1077 static void
1078 on_selection_changed_cleanup_handler( BaseWindow *window, GList *selected_items )
1080 static const gchar *thisfn = "nact_main_window_on_selection_changed_cleanup_handler";
1082 g_debug( "%s: window=%p, selected_items=%p (count=%u)",
1083 thisfn, ( void * ) window,
1084 ( void * ) selected_items, g_list_length( selected_items ));
1086 na_object_free_items( selected_items );
1089 static void
1090 on_tab_updatable_item_updated( NactMainWindow *window, NAIContext *context, guint data, gpointer user_data )
1092 static const gchar *thisfn = "nact_main_window_on_tab_updatable_item_updated";
1094 g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
1096 if( !window->private->dispose_has_run ){
1097 g_debug( "%s: window=%p, context=%p (%s), data=%u, user_data=%p",
1098 thisfn, ( void * ) window, ( void * ) context, G_OBJECT_TYPE_NAME( context ),
1099 data, ( void * ) user_data );
1101 if( context ){
1102 na_object_check_status( context );
1107 static void
1108 raz_selection_properties( NactMainWindow *window )
1110 window->private->current_item = NULL;
1111 window->private->current_profile = NULL;
1112 window->private->current_context = NULL;
1113 window->private->editable = FALSE;
1114 window->private->reason = 0;
1116 nact_main_statusbar_set_locked( window, FALSE, 0 );
1120 * enter after raz_properties
1121 * only called when only one selected row
1123 static void
1124 setup_current_selection( NactMainWindow *window, NAObjectId *selected_row )
1126 guint nb_profiles;
1127 GList *profiles;
1129 if( NA_IS_OBJECT_PROFILE( selected_row )){
1130 window->private->current_profile = NA_OBJECT_PROFILE( selected_row );
1131 window->private->current_item = NA_OBJECT_ITEM( na_object_get_parent( selected_row ));
1133 } else {
1134 g_return_if_fail( NA_IS_OBJECT_ITEM( selected_row ));
1135 window->private->current_item = NA_OBJECT_ITEM( selected_row );
1136 window->private->current_context = NA_ICONTEXT( selected_row );
1138 if( NA_IS_OBJECT_ACTION( selected_row )){
1139 nb_profiles = na_object_get_items_count( selected_row );
1141 if( nb_profiles == 1 ){
1142 profiles = na_object_get_items( selected_row );
1143 window->private->current_profile = NA_OBJECT_PROFILE( profiles->data );
1144 window->private->current_context = NA_ICONTEXT( profiles->data );
1151 * the title bar of the main window brings up three informations:
1152 * - the name of the application
1153 * - the name of the currently selected item if there is only one
1154 * - an asterisk if anything has been modified
1156 static void
1157 setup_dialog_title( NactMainWindow *window )
1159 static const gchar *thisfn = "nact_main_window_setup_dialog_title";
1160 GtkWindow *toplevel;
1161 NactApplication *application;
1162 gchar *title;
1163 gchar *label;
1164 gchar *tmp;
1165 gboolean is_modified;
1167 g_debug( "%s: window=%p", thisfn, ( void * ) window );
1169 application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
1170 title = base_application_get_application_name( BASE_APPLICATION( application ));
1172 if( window->private->current_item ){
1173 label = na_object_get_label( window->private->current_item );
1174 is_modified = na_object_is_modified( window->private->current_item );
1175 tmp = g_strdup_printf( "%s%s - %s", is_modified ? "*" : "", label, title );
1176 g_free( label );
1177 g_free( title );
1178 title = tmp;
1181 toplevel = base_window_get_gtk_toplevel( BASE_WINDOW( window ));
1182 gtk_window_set_title( toplevel, title );
1183 g_free( title );
1186 static void
1187 setup_writability_status( NactMainWindow *window )
1189 g_return_if_fail( NA_IS_OBJECT_ITEM( window->private->current_item ));
1191 window->private->editable = na_updater_check_item_writability_status( window->private->updater, window->private->current_item, &window->private->reason );
1192 nact_main_statusbar_set_locked( window, !window->private->editable, window->private->reason );
1196 * The handler of the signal sent by NAPivot when items have been modified
1197 * in the underlying storage subsystems
1199 static void
1200 on_pivot_items_changed( NAUpdater *updater, NactMainWindow *window )
1202 static const gchar *thisfn = "nact_main_window_on_pivot_items_changed";
1203 gboolean reload_ok;
1205 g_return_if_fail( NA_IS_UPDATER( updater ));
1206 g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
1208 if( !window->private->dispose_has_run ){
1209 g_debug( "%s: updater=%p (%s), window=%p (%s)", thisfn,
1210 ( void * ) updater, G_OBJECT_TYPE_NAME( updater ),
1211 ( void * ) window, G_OBJECT_TYPE_NAME( window ));
1213 reload_ok = confirm_for_giveup_from_pivot( window );
1215 if( reload_ok ){
1216 load_or_reload_items( window );
1222 * informs the user that the actions in underlying storage subsystem
1223 * have changed, and propose for reloading
1226 static gboolean
1227 confirm_for_giveup_from_pivot( const NactMainWindow *window )
1229 gboolean reload_ok;
1230 gchar *first, *second;
1232 first = g_strdup(
1233 _( "One or more actions have been modified in the filesystem.\n"
1234 "You could keep to work with your current list of actions, "
1235 "or you may want to reload a fresh one." ));
1237 if( window->private->is_tree_modified){
1239 gchar *tmp = g_strdup_printf( "%s\n\n%s", first,
1240 _( "Note that reloading a fresh list of actions requires "
1241 "that you give up with your current modifications." ));
1242 g_free( first );
1243 first = tmp;
1246 second = g_strdup( _( "Do you want to reload a fresh list of actions ?" ));
1248 reload_ok = base_window_display_yesno_dlg( BASE_WINDOW( window ), first, second );
1250 g_free( second );
1251 g_free( first );
1253 return( reload_ok );
1257 * requires a confirmation from the user when is has asked for reloading
1258 * the actions via the Edit menu
1260 static gboolean
1261 confirm_for_giveup_from_menu( const NactMainWindow *window )
1263 gboolean reload_ok = TRUE;
1264 gchar *first, *second;
1266 if( window->private->is_tree_modified ){
1268 first = g_strdup(
1269 _( "Reloading a fresh list of actions requires "
1270 "that you give up with your current modifications." ));
1272 second = g_strdup( _( "Do you really want to do this ?" ));
1274 reload_ok = base_window_display_yesno_dlg( BASE_WINDOW( window ), first, second );
1276 g_free( second );
1277 g_free( first );
1280 return( reload_ok );
1283 static void
1284 load_or_reload_items( NactMainWindow *window )
1286 static const gchar *thisfn = "nact_main_window_load_or_reload_items";
1287 GList *tree;
1289 g_debug( "%s: window=%p", thisfn, ( void * ) window );
1291 raz_selection_properties( window );
1293 tree = na_updater_load_items( window->private->updater );
1294 nact_tree_view_fill( window->private->items_view, tree );
1296 g_debug( "%s: end of tree view filling", thisfn );
1300 * nact_main_window_quit:
1301 * @window: the #NactMainWindow main window.
1303 * Quit the window, thus terminating the application.
1305 * Returns: %TRUE if the application will terminate, and the @window object
1306 * is no more valid; %FALSE if the application will continue to run.
1308 gboolean
1309 nact_main_window_quit( NactMainWindow *window )
1311 static const gchar *thisfn = "nact_main_window_quit";
1312 gboolean terminated;
1314 g_return_val_if_fail( NACT_IS_MAIN_WINDOW( window ), FALSE );
1316 terminated = FALSE;
1318 if( !window->private->dispose_has_run ){
1319 g_debug( "%s: window=%p (%s)", thisfn, ( void * ) window, G_OBJECT_TYPE_NAME( window ));
1321 if( !window->private->is_tree_modified || warn_modified( window )){
1322 g_object_unref( window );
1323 terminated = TRUE;
1327 return( terminated );
1331 * signal handler
1332 * should return %FALSE if it is not willing to quit
1333 * this will also stop the emission of the signal (i.e. the first FALSE wins)
1335 static gboolean
1336 on_base_is_willing_to_quit( const BaseWindow *window, gconstpointer user_data )
1338 static const gchar *thisfn = "nact_main_window_on_base_is_willing_to_quit";
1339 gboolean willing_to;
1341 g_return_val_if_fail( NACT_IS_MAIN_WINDOW( window ), TRUE );
1343 willing_to = TRUE;
1345 if( !NACT_MAIN_WINDOW( window )->private->dispose_has_run ){
1346 g_debug( "%s (virtual): window=%p", thisfn, ( void * ) window );
1348 if( NACT_MAIN_WINDOW( window )->private->is_tree_modified ){
1349 willing_to = nact_confirm_logout_run( NACT_MAIN_WINDOW( window ));
1353 return( willing_to );
1357 * triggered when the user clicks on the top right [X] button
1358 * returns %TRUE to stop the signal to be propagated (which would cause the
1359 * window to be destroyed); instead we gracefully quit the application
1361 static gboolean
1362 on_delete_event( GtkWidget *toplevel, GdkEvent *event, NactMainWindow *window )
1364 static const gchar *thisfn = "nact_main_window_on_delete_event";
1366 g_debug( "%s: toplevel=%p, event=%p, window=%p",
1367 thisfn, ( void * ) toplevel, ( void * ) event, ( void * ) window );
1369 nact_main_window_quit( window );
1371 return( TRUE );
1375 * warn_modified:
1376 * @window: this #NactWindow instance.
1378 * Emits a warning if at least one item has been modified.
1380 * Returns: %TRUE if the user confirms he wants to quit.
1382 static gboolean
1383 warn_modified( NactMainWindow *window )
1385 gboolean confirm = FALSE;
1386 gchar *first;
1387 gchar *second;
1389 first = g_strdup_printf( _( "Some items have been modified." ));
1390 second = g_strdup( _( "Are you sure you want to quit without saving them ?" ));
1392 confirm = base_window_display_yesno_dlg( BASE_WINDOW( window ), first, second );
1394 g_free( second );
1395 g_free( first );
1397 return( confirm );
1400 static gchar *
1401 iabout_get_application_name( NAIAbout *instance )
1403 BaseApplication *application;
1405 g_return_val_if_fail( NA_IS_IABOUT( instance ), NULL );
1406 g_return_val_if_fail( BASE_IS_WINDOW( instance ), NULL );
1408 application = base_window_get_application( BASE_WINDOW( instance ));
1409 return( base_application_get_application_name( application ));
1412 static GtkWindow *
1413 iabout_get_toplevel( NAIAbout *instance )
1415 g_return_val_if_fail( NA_IS_IABOUT( instance ), NULL );
1416 g_return_val_if_fail( BASE_IS_WINDOW( instance ), NULL );
1418 return( base_window_get_gtk_toplevel( BASE_WINDOW( instance )));