[nautilus-actions] Review BaseApplication, BaseISession and BaseIUnique



commit a37a969fb98e72920fcd0d3c3d37cfc8bbd6287e
Author: Pierre Wieser <pwieser trychlos org>
Date:   Wed Jan 11 21:05:18 2012 +0100

    Review BaseApplication, BaseISession and BaseIUnique

 ChangeLog                          |   40 +++++
 src/nact/Makefile.am               |   12 ++-
 src/nact/base-application.c        |   92 +++++++-----
 src/nact/base-application.h        |   61 +++++---
 src/nact/base-assistant.c          |    2 +-
 src/nact/base-dialog.c             |    2 +-
 src/nact/base-isession.c           |  288 ++++++++++++++++++++++++++---------
 src/nact/base-isession.h           |   25 ++-
 src/nact/base-iunique.c            |   64 +++++----
 src/nact/base-iunique.h            |   12 +-
 src/nact/base-marshal.def          |    9 +-
 src/nact/base-window.c             |  180 +++++-----------------
 src/nact/base-window.h             |   23 +---
 src/nact/main.c                    |    2 +-
 src/nact/nact-application.c        |    4 +-
 src/nact/nact-main-window.c        |    5 +-
 src/nact/nact-marshal.def          |    6 +
 src/nact/nact-menubar-maintainer.c |    3 +-
 src/nact/nact-tree-view.c          |    2 +-
 19 files changed, 476 insertions(+), 356 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 37a9b5f..7740078 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,43 @@
+2012-01-11 Pierre Wieser <pwieser trychlos org>
+
+	* BASE_SIGNAL_QUIT_REQUESTED, BASE_SIGNAL_QUIT: New signals, defined in
+	BaseISession interface.
+
+	* src/nact/nact-marshal.def: New file.
+
+	* src/nact/Makefile.am: Updated accordingly.
+
+	* src/nact/base-application.c
+	* src/nact/base-application.h
+	(register_type): As BaseISession now only requires G_TYPE_OBJECT, then 
+	declare the implementation in register_type().
+	(base_application_run): Renamed as base_application_run_with_args().
+	BASE_EXIT_CODE_START_FAIL exit code replaced with BASE_EXIT_CODE_PROGRAM.
+	(base_application_is_willing_to_quit): New function, moved from BaseWindow.
+	BASE_APPLICATION_TYPE macro renamed as BASE_TYPE_APPLICATION.
+
+	* src/nact/base-assistant.c (do_run):
+	* src/nact/base-dialog.c (do_run):
+	* src/nact/nact-application.c (register_type):
+	* src/nact/nact-main-window.c:
+	* src/nact/nact-menubar-maintainer.c:
+	* src/nact/nact-tree-view.c: Updated accordingly.
+
+	* src/nact/base-isession.c:
+	* src/nact/base-isession.h:
+	Define ISessionData pseudo-properties.
+	Implement BASE_SIGNAL_QUIT_REQUESTED and BASE_SIGNAL_QUIT class handlers.
+
+	* src/nact/base-iunique.c:
+	* src/nact/base-iunique.h:
+	Define IUniqueData pseudo-properties.
+
+	* src/nact/base-window.c:
+	* src/nact/base-window.h:
+	Define BaseGtkData pseudo-properties.
+	Remove BASE_SIGNAL_WILLING_TO_QUIT definition and handlers.
+	(base_window_is_willing_to_quit): Removed function.
+
 2012-01-09 Pierre Wieser <pwieser trychlos org>
 
 	* src/nact/base-isession.c:
diff --git a/src/nact/Makefile.am b/src/nact/Makefile.am
index da0d906..b4cb769 100644
--- a/src/nact/Makefile.am
+++ b/src/nact/Makefile.am
@@ -45,6 +45,8 @@ AM_CPPFLAGS += \
 BUILT_SOURCES = \
 	base-marshal.c										\
 	base-marshal.h										\
+	nact-marshal.c										\
+	nact-marshal.h										\
 	$(NULL)
 
 nautilus_actions_config_tool_SOURCES = \
@@ -151,10 +153,17 @@ nautilus_actions_config_tool_SOURCES = \
 	$(NULL)
 
 base-marshal.h: base-marshal.def $(GLIB_GENMARSHAL)
-	$(GLIB_GENMARSHAL) $< --header --prefix=nact_cclosure_marshal > $@
+	$(GLIB_GENMARSHAL) $< --header --prefix=base_cclosure_marshal > $@
 
 base-marshal.c: base-marshal.def $(GLIB_GENMARSHAL)
 	echo "#include \"base-marshal.h\"" > $@ && \
+	$(GLIB_GENMARSHAL) $< --body --prefix=base_cclosure_marshal >> $@
+
+nact-marshal.h: nact-marshal.def $(GLIB_GENMARSHAL)
+	$(GLIB_GENMARSHAL) $< --header --prefix=nact_cclosure_marshal > $@
+
+nact-marshal.c: nact-marshal.def $(GLIB_GENMARSHAL)
+	echo "#include \"nact-marshal.h\"" > $@ && \
 	$(GLIB_GENMARSHAL) $< --body --prefix=nact_cclosure_marshal >> $@
 
 nautilus_actions_config_tool_LDADD = \
@@ -211,4 +220,5 @@ EXTRA_DIST = \
 	$(applications_in_files)							\
 	$(pkgdata_DATA)										\
 	base-marshal.def									\
+	nact-marshal.def									\
 	$(NULL)
diff --git a/src/nact/base-application.c b/src/nact/base-application.c
index 5a009b9..a69df7d 100644
--- a/src/nact/base-application.c
+++ b/src/nact/base-application.c
@@ -81,26 +81,26 @@ enum {
 
 static GObjectClass *st_parent_class = NULL;
 
-static GType          register_type( void );
-static void           class_init( BaseApplicationClass *klass );
-static void           isession_iface_init( BaseISessionInterface *iface, void *user_data );
-static void           iunique_iface_init( BaseIUniqueInterface *iface, void *user_data );
-static const gchar   *iunique_get_application_name( const BaseIUnique *instance );
-static void           instance_init( GTypeInstance *instance, gpointer klass );
-static void           instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
-static void           instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
-static void           instance_dispose( GObject *application );
-static void           instance_finalize( GObject *application );
-
-static gboolean       init_i18n( BaseApplication *application );
-static gboolean       init_application_name( BaseApplication *application );
-static gboolean       init_gtk( BaseApplication *application );
-static gboolean       v_manage_options( BaseApplication *application );
-static gboolean       init_unique_manager( BaseApplication *application );
-static gboolean       init_session_manager( BaseApplication *application );
-static gboolean       init_icon_name( BaseApplication *application );
-static gboolean       v_init_application( BaseApplication *application );
-static gboolean       v_create_windows( BaseApplication *application );
+static GType        register_type( void );
+static void         class_init( BaseApplicationClass *klass );
+static void         isession_iface_init( BaseISessionInterface *iface, void *user_data );
+static void         iunique_iface_init( BaseIUniqueInterface *iface, void *user_data );
+static const gchar *iunique_get_application_name( const BaseIUnique *instance );
+static void         instance_init( GTypeInstance *instance, gpointer klass );
+static void         instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void         instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
+static void         instance_dispose( GObject *application );
+static void         instance_finalize( GObject *application );
+
+static gboolean     init_i18n( BaseApplication *application );
+static gboolean     init_application_name( BaseApplication *application );
+static gboolean     init_gtk( BaseApplication *application );
+static gboolean     v_manage_options( BaseApplication *application );
+static gboolean     init_unique_manager( BaseApplication *application );
+static gboolean     init_session_manager( BaseApplication *application );
+static gboolean     init_icon_name( BaseApplication *application );
+static gboolean     v_init_application( BaseApplication *application );
+static gboolean     v_create_windows( BaseApplication *application );
 
 /*
  * the BaseISessionInterface interface is registered here because
@@ -113,15 +113,8 @@ base_application_get_type( void )
 {
 	static GType application_type = 0;
 
-	static const GInterfaceInfo isession_iface_info = {
-		( GInterfaceInitFunc ) isession_iface_init,
-		NULL,
-		NULL
-	};
-
 	if( !application_type ){
 		application_type = register_type();
-		g_type_add_interface_static( application_type, BASE_ISESSION_TYPE, &isession_iface_info );
 	}
 
 	return( application_type );
@@ -145,6 +138,12 @@ register_type( void )
 		( GInstanceInitFunc ) instance_init
 	};
 
+	static const GInterfaceInfo isession_iface_info = {
+		( GInterfaceInitFunc ) isession_iface_init,
+		NULL,
+		NULL
+	};
+
 	static const GInterfaceInfo iunique_iface_info = {
 		( GInterfaceInitFunc ) iunique_iface_init,
 		NULL,
@@ -157,7 +156,9 @@ register_type( void )
 
 	type = g_type_register_static( G_TYPE_OBJECT, "BaseApplication", &info, 0 );
 
-	g_type_add_interface_static( type, BASE_IUNIQUE_TYPE, &iunique_iface_info );
+	g_type_add_interface_static( type, BASE_TYPE_ISESSION, &isession_iface_info );
+
+	g_type_add_interface_static( type, BASE_TYPE_IUNIQUE, &iunique_iface_info );
 
 	return( type );
 }
@@ -450,7 +451,7 @@ instance_finalize( GObject *application )
 }
 
 /**
- * base_application_run:
+ * base_application_run_with_args:
  * @application: this #BaseApplication -derived instance.
  *
  * Starts and runs the application.
@@ -465,15 +466,12 @@ instance_finalize( GObject *application )
  * seldomly needed to override this in a derived class.
  */
 int
-base_application_run( BaseApplication *application, int argc, GStrv argv )
+base_application_run_with_args( BaseApplication *application, int argc, GStrv argv )
 {
-	static const gchar *thisfn = "base_application_run";
+	static const gchar *thisfn = "base_application_run_with_args";
 	BaseApplicationPrivate *priv;
-#if 0
-	GtkWindow *gtk_toplevel;
-#endif
 
-	g_return_val_if_fail( BASE_IS_APPLICATION( application ), BASE_EXIT_CODE_START_FAIL );
+	g_return_val_if_fail( BASE_IS_APPLICATION( application ), BASE_EXIT_CODE_PROGRAM );
 
 	priv = application->private;
 
@@ -486,9 +484,6 @@ base_application_run( BaseApplication *application, int argc, GStrv argv )
 
 		priv->argc = argc;
 		priv->argv = g_strdupv( argv );
-#if 0
-		priv->main_window = NULL;
-#endif
 		priv->code = BASE_EXIT_CODE_OK;
 
 		if( init_i18n( application ) &&
@@ -560,7 +555,7 @@ init_application_name( BaseApplication *application )
 		g_set_application_name( name );
 
 	} else {
-		application->private->code = BASE_EXIT_CODE_NO_APPLICATION_NAME;
+		application->private->code = BASE_EXIT_CODE_APPLICATION_NAME;
 		ret = FALSE;
 	}
 	g_free( name );
@@ -751,3 +746,22 @@ base_application_get_application_name( const BaseApplication *application )
 
 	return( name );
 }
+
+/**
+ * base_application_is_willing_to_quit:
+ * @application: this #BaseApplication instance.
+ *
+ * Returns: %TRUE if the application is willing to quit, %FALSE else.
+ *
+ * This function is typically called from the derived application, when
+ * the user has required the termination, in order to let it handle
+ * unsaved modifications.
+ */
+gboolean
+base_application_is_willing_to_quit( const BaseApplication *application )
+{
+	g_return_val_if_fail( BASE_IS_APPLICATION( application ), TRUE );
+	g_return_val_if_fail( BASE_IS_ISESSION( application ), TRUE );
+
+	return( base_isession_is_willing_to_quit( BASE_ISESSION( application )));
+}
diff --git a/src/nact/base-application.h b/src/nact/base-application.h
index 5dd8858..0e3d1cf 100644
--- a/src/nact/base-application.h
+++ b/src/nact/base-application.h
@@ -56,7 +56,7 @@
  *         int code;
  *
  *         appli = my_application_new();
- *         code = base_appliction_run( BASE_APPLICATION( appli ), argc, argv );
+ *         code = base_appliction_run_with_args( BASE_APPLICATION( appli ), argc, argv );
  *         g_object_unref( appli );
  *
  *         return( code );
@@ -76,7 +76,7 @@
  *                                             command-line definitions
  *                                             unique name (if apply)
  * --------------------+--------------------+--------------------+--------------------+-------------------
- * ret = base_application_run( appli, argc, argv )
+ * ret = base_application_run_with_args( appli, argc, argv )
  * --------------------+--------------------+--------------------+--------------------+-------------------
  *                      init i18n
  *                      init application name
@@ -127,12 +127,12 @@
 
 G_BEGIN_DECLS
 
-#define BASE_APPLICATION_TYPE                ( base_application_get_type())
-#define BASE_APPLICATION( object )           ( G_TYPE_CHECK_INSTANCE_CAST( object, BASE_APPLICATION_TYPE, BaseApplication ))
-#define BASE_APPLICATION_CLASS( klass )      ( G_TYPE_CHECK_CLASS_CAST( klass, BASE_APPLICATION_TYPE, BaseApplicationClass ))
-#define BASE_IS_APPLICATION( object )        ( G_TYPE_CHECK_INSTANCE_TYPE( object, BASE_APPLICATION_TYPE ))
-#define BASE_IS_APPLICATION_CLASS( klass )   ( G_TYPE_CHECK_CLASS_TYPE(( klass ), BASE_APPLICATION_TYPE ))
-#define BASE_APPLICATION_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), BASE_APPLICATION_TYPE, BaseApplicationClass ))
+#define BASE_TYPE_APPLICATION                ( base_application_get_type())
+#define BASE_APPLICATION( object )           ( G_TYPE_CHECK_INSTANCE_CAST( object, BASE_TYPE_APPLICATION, BaseApplication ))
+#define BASE_APPLICATION_CLASS( klass )      ( G_TYPE_CHECK_CLASS_CAST( klass, BASE_TYPE_APPLICATION, BaseApplicationClass ))
+#define BASE_IS_APPLICATION( object )        ( G_TYPE_CHECK_INSTANCE_TYPE( object, BASE_TYPE_APPLICATION ))
+#define BASE_IS_APPLICATION_CLASS( klass )   ( G_TYPE_CHECK_CLASS_TYPE(( klass ), BASE_TYPE_APPLICATION ))
+#define BASE_APPLICATION_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), BASE_TYPE_APPLICATION, BaseApplicationClass ))
 
 typedef struct _BaseApplicationPrivate       BaseApplicationPrivate;
 
@@ -235,7 +235,7 @@ typedef struct {
  * Properties defined by the BaseApplication class.
  * They may be provided at object instantiation time, either in the derived-
  * application constructor, or in the main() function, but in all cases
- * before calling base_application_run().
+ * before calling base_application_run_with_args().
  *
  * @BASE_PROP_ARGC:             count of arguments in command-line.
  * @BASE_PROP_ARGV:             array of command-line arguments.
@@ -255,28 +255,43 @@ typedef struct {
 #define BASE_PROP_UNIQUE_NAME				"base-prop-application-unique-name"
 #define BASE_PROP_CODE						"base-prop-application-code"
 
+/**
+ * BaseExitCode:
+ *
+ * The code returned by the application.
+ *
+ * The BaseApplication -derived class may define its own codes, starting
+ * them with @BASE_EXIT_CODE_USER_APP.
+ *
+ * @BASE_EXIT_CODE_PROGRAM = -1:         this is a program error code.
+ * @BASE_EXIT_CODE_OK = 0:               the program has successfully run, and returns zero.
+ * @BASE_EXIT_CODE_APPLICATION_NAME = 1: no application name has been set by the derived class
+ * @BASE_EXIT_CODE_ARGS = 2:             unable to interpret command-line options
+ * @BASE_EXIT_CODE_UNIQUE_APP = 3:       another instance is already running
+ * @BASE_EXIT_CODE_INIT_WINDOW = 4:      unable to create a startup window
+ *
+ * @BASE_EXIT_CODE_USER_APP = 32:        BaseApplication -derived class may use program return codes
+ *                                       starting with this value
+ */
 typedef enum {
-	BASE_EXIT_CODE_START_FAIL = -1,
+	BASE_EXIT_CODE_PROGRAM = -1,
 	BASE_EXIT_CODE_OK = 0,
-	BASE_EXIT_CODE_NO_APPLICATION_NAME,		/* no application name has been set by the derived class */
-	BASE_EXIT_CODE_ARGS,					/* unable to interpret command-line options */
-	BASE_EXIT_CODE_UNIQUE_APP,				/* another instance is already running */
-	BASE_EXIT_CODE_WINDOW,					/* unable to create a startup window */
-	BASE_EXIT_CODE_INIT_FAIL,
-	BASE_EXIT_CODE_PROGRAM,
-	/*
-	 * BaseApplication -derived class may use program return codes
-	 * starting with this value
-	 */
+	BASE_EXIT_CODE_APPLICATION_NAME,
+	BASE_EXIT_CODE_ARGS,
+	BASE_EXIT_CODE_UNIQUE_APP,
+	BASE_EXIT_CODE_INIT_WINDOW,
+
 	BASE_EXIT_CODE_USER_APP = 32
 }
 	BaseExitCode;
 
-GType  base_application_get_type            ( void );
+GType    base_application_get_type            ( void );
+
+int      base_application_run_with_args       ( BaseApplication *application, int argc, GStrv argv );
 
-int    base_application_run                 ( BaseApplication *application, int argc, GStrv argv );
+gchar   *base_application_get_application_name( const BaseApplication *application );
 
-gchar *base_application_get_application_name( const BaseApplication *application );
+gboolean base_application_is_willing_to_quit  ( const BaseApplication *application );
 
 G_END_DECLS
 
diff --git a/src/nact/base-assistant.c b/src/nact/base-assistant.c
index a61bff4..a45a58f 100644
--- a/src/nact/base-assistant.c
+++ b/src/nact/base-assistant.c
@@ -337,7 +337,7 @@ do_run( BaseWindow *window, GtkWindow *toplevel )
 	g_return_val_if_fail( BASE_IS_ASSISTANT( window ), BASE_EXIT_CODE_PROGRAM );
 	g_return_val_if_fail( GTK_IS_ASSISTANT( toplevel ), BASE_EXIT_CODE_PROGRAM );
 
-	code = BASE_EXIT_CODE_INIT_FAIL;
+	code = BASE_EXIT_CODE_INIT_WINDOW;
 
 	if( !BASE_ASSISTANT( window )->private->dispose_has_run ){
 		g_debug( "%s: window=%p (%s), toplevel=%p (%s), starting gtk_main",
diff --git a/src/nact/base-dialog.c b/src/nact/base-dialog.c
index bfba833..a2d1def 100644
--- a/src/nact/base-dialog.c
+++ b/src/nact/base-dialog.c
@@ -190,7 +190,7 @@ do_run( BaseWindow *window, GtkWindow *toplevel )
 	g_return_val_if_fail( BASE_IS_DIALOG( window ), BASE_EXIT_CODE_PROGRAM );
 	g_return_val_if_fail( GTK_IS_DIALOG( toplevel ), BASE_EXIT_CODE_PROGRAM );
 
-	code = BASE_EXIT_CODE_INIT_FAIL;
+	code = BASE_EXIT_CODE_INIT_WINDOW;
 
 	if( !BASE_DIALOG( window )->private->dispose_has_run ){
 		g_debug( "%s: window=%p (%s), toplevel=%p (%s), starting gtk_dialog_run",
diff --git a/src/nact/base-isession.c b/src/nact/base-isession.c
index 1e5470c..5f814d2 100644
--- a/src/nact/base-isession.c
+++ b/src/nact/base-isession.c
@@ -32,8 +32,8 @@
 #include <config.h>
 #endif
 
-#include "base-application.h"
 #include "base-isession.h"
+#include "base-marshal.h"
 #include "egg-sm-client.h"
 
 /* private interface data
@@ -42,30 +42,39 @@ struct _BaseISessionInterfacePrivate {
 	void *empty;						/* so that gcc -pedantic is happy */
 };
 
-/* private properties, set against the instance
+/* pseudo-properties, set against the instance
  */
 typedef struct {
 	EggSMClient *sm_client;
 	gulong       sm_client_quit_handler_id;
 	gulong       sm_client_quit_requested_handler_id;
 }
-	ISessionStr;
+	ISessionData;
 
-/* Above ISessionStr struct is set as a BaseISession pseudo-property
- * of the instance.
+#define BASE_PROP_ISESSION_DATA			"base-prop-isession-data"
+
+/* signals defined by the BaseISession interface
  */
-#define BASE_PROP_ISESSION				"base-prop-isession"
+enum {
+	QUIT_REQUESTED,
+	QUIT,
+	LAST_SIGNAL
+};
 
 static guint st_initializations = 0;	/* interface initialisation count */
+static gint  st_signals[ LAST_SIGNAL ] = { 0 };
 
-static GType        register_type( void );
-static void         interface_base_init( BaseISessionInterface *klass );
-static void         interface_base_finalize( BaseISessionInterface *klass );
+static GType         register_type( void );
+static void          interface_base_init( BaseISessionInterface *klass );
+static void          interface_base_finalize( BaseISessionInterface *klass );
 
-static void         on_instance_finalized( gpointer user_data, BaseISession *instance );
-static void         client_quit_requested_cb( EggSMClient *client, BaseISession *instance );
-static void         client_quit_cb( EggSMClient *client, BaseISession *instance );
-static ISessionStr *get_isession_str( BaseISession *instance );
+static ISessionData *get_isession_data( BaseISession *instance );
+static void          on_instance_finalized( gpointer user_data, BaseISession *instance );
+static void          client_quit_requested_cb( EggSMClient *client, BaseISession *instance );
+static gboolean      on_quit_requested_class_handler( BaseISession *instance, void *user_data );
+static gboolean      signal_accumulator_false_handled( GSignalInvocationHint *hint, GValue *return_accu, const GValue *handler_return, gpointer dummy);
+static void          client_quit_cb( EggSMClient *client, BaseISession *instance );
+static void          on_quit_class_handler( BaseISession *instance, void *user_data );
 
 GType
 base_isession_get_type( void )
@@ -101,7 +110,7 @@ register_type( void )
 
 	type = g_type_register_static( G_TYPE_INTERFACE, "BaseISession", &info, 0 );
 
-	g_type_interface_add_prerequisite( type, BASE_APPLICATION_TYPE );
+	g_type_interface_add_prerequisite( type, G_TYPE_OBJECT );
 
 	return( type );
 }
@@ -115,6 +124,64 @@ interface_base_init( BaseISessionInterface *klass )
 
 		g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
 
+		/**
+		 * base-signal-isession-quit-requested:
+		 *
+		 * The signal is emitted when the session is about to terminate,
+		 * to determine if all implementations are actually willing to quit.
+		 *
+		 * If the implementation is not willing to quit, then the user handler
+		 * should return %FALSE to stop the signal emission.
+		 *
+		 * Returning %TRUE will let the signal be emitted to other connected
+		 * handlers, eventually authorizing the application to terminate.
+		 *
+		 * Notes about GLib signals.
+		 *
+		 * If the signal is defined as G_SIGNAL_RUN_CLEANUP, then the object
+		 * handler does not participate to the return value of the signal
+		 * (accumulator is not called). More this object handler is triggered
+		 * unconditionnally, event if a user handler has returned %FALSE to
+		 * stop the emission.
+		 *
+		 * Contrarily, if the signal is defined as G_SIGNAL_RUN_LAST, then the
+		 * object handler returned value is taken into account by the accumulator,
+		 * and can participate to the return value for the signal. If a user
+		 * handler returns FALSE to stop the emission, then the object handler
+		 * will not be triggered.
+		 */
+		st_signals[ QUIT_REQUESTED ] =
+			g_signal_new_class_handler(
+					BASE_SIGNAL_QUIT_REQUESTED,
+					G_TYPE_FROM_CLASS( klass ),
+					G_SIGNAL_RUN_LAST,
+					G_CALLBACK( on_quit_requested_class_handler ),
+					( GSignalAccumulator ) signal_accumulator_false_handled,
+					NULL,
+					base_cclosure_marshal_BOOLEAN__VOID,
+					G_TYPE_BOOLEAN,
+					0 );
+
+		/**
+		 * base-signal-isession-quit:
+		 *
+		 * The signal is emitted when the session is about to terminate,
+		 * and no application has refused to abort then end of session
+		 * (all have accepted the end). It is time for the application
+		 * to terminate cleanly.
+		 */
+		st_signals[ QUIT ] =
+			g_signal_new_class_handler(
+					BASE_SIGNAL_QUIT,
+					G_TYPE_FROM_CLASS( klass ),
+					G_SIGNAL_RUN_LAST,
+					G_CALLBACK( on_quit_class_handler ),
+					NULL,
+					NULL,
+					g_cclosure_marshal_VOID__VOID,
+					G_TYPE_NONE,
+					0 );
+
 		klass->private = g_new0( BaseISessionInterfacePrivate, 1 );
 	}
 
@@ -136,97 +203,179 @@ interface_base_finalize( BaseISessionInterface *klass )
 	}
 }
 
+static ISessionData *
+get_isession_data( BaseISession *instance )
+{
+	ISessionData *data;
+
+	data = ( ISessionData * ) g_object_get_data( G_OBJECT( instance ), BASE_PROP_ISESSION_DATA );
+
+	if( !data ){
+		data = g_new0( ISessionData, 1 );
+		g_object_set_data( G_OBJECT( instance ), BASE_PROP_ISESSION_DATA, data );
+
+		g_object_weak_ref( G_OBJECT( instance ), ( GWeakNotify ) on_instance_finalized, NULL );
+	}
+
+	return( data );
+}
+
+static void
+on_instance_finalized( gpointer user_data, BaseISession *instance )
+{
+	static const gchar *thisfn = "base_isession_on_instance_finalized";
+	ISessionData *data;
+
+	g_debug( "%s: instance=%p, user_data=%p", thisfn, ( void * ) instance, ( void * ) user_data );
+
+	data = get_isession_data( instance );
+
+	if( data->sm_client_quit_handler_id &&
+		g_signal_handler_is_connected( data->sm_client, data->sm_client_quit_handler_id )){
+			g_signal_handler_disconnect( data->sm_client, data->sm_client_quit_handler_id  );
+	}
+
+	if( data->sm_client_quit_requested_handler_id &&
+		g_signal_handler_is_connected( data->sm_client, data->sm_client_quit_requested_handler_id )){
+			g_signal_handler_disconnect( data->sm_client, data->sm_client_quit_requested_handler_id  );
+	}
+
+	if( data->sm_client ){
+		g_object_unref( data->sm_client );
+	}
+
+	g_free( data );
+}
+
 void
 base_isession_init( BaseISession *instance )
 {
 	static const gchar *thisfn = "base_isession_init";
-	ISessionStr *str;
+	ISessionData *data;
 
 	g_return_if_fail( BASE_IS_ISESSION( instance ));
 
 	g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
 
-	str = get_isession_str( instance );
-
-	/* set a weak reference to be advertised when the instance is finalized
-	 */
-	g_object_weak_ref( G_OBJECT( instance ), ( GWeakNotify ) on_instance_finalized, NULL );
+	data = get_isession_data( instance );
 
 	/* initialize the session manager
 	 */
 	egg_sm_client_set_mode( EGG_SM_CLIENT_MODE_NO_RESTART );
-	str->sm_client = egg_sm_client_get();
+	data->sm_client = egg_sm_client_get();
 	egg_sm_client_startup();
-	g_debug( "%s: sm_client=%p", thisfn, ( void * ) str->sm_client );
+	g_debug( "%s: sm_client=%p", thisfn, ( void * ) data->sm_client );
 
-	str->sm_client_quit_handler_id =
+	data->sm_client_quit_handler_id =
 			g_signal_connect(
-					str->sm_client,
+					data->sm_client,
 					"quit-requested",
 					G_CALLBACK( client_quit_requested_cb ),
 					instance );
 
-	str->sm_client_quit_requested_handler_id =
+	data->sm_client_quit_requested_handler_id =
 			g_signal_connect(
-					str->sm_client,
+					data->sm_client,
 					"quit",
 					G_CALLBACK( client_quit_cb ),
 					instance );
 }
 
-static void
-on_instance_finalized( gpointer user_data, BaseISession *instance )
+/*
+ * base_isession_is_willing_to_quit:
+ * @instance: this #BaseISession instance.
+ *
+ * Returns: %TRUE if the implementation is willing to quit, %FALSE else.
+ *
+ * From the session management strict point of view, this function may be
+ * just static and reserved for the own internal use of the interface.
+ * We make it public because it is also useful for the application itself,
+ * and we are so able to reuse both the signal and its handler mechanisms.
+ */
+gboolean
+base_isession_is_willing_to_quit( const BaseISession *instance )
 {
-	static const gchar *thisfn = "base_isession_on_instance_finalized";
-	ISessionStr *str;
+	static const gchar *thisfn = "base_isession_is_willing_to_quit";
+	GValue instance_params = {0};
+	GValue return_value = {0};
 
-	g_debug( "%s: instance=%p, user_data=%p", thisfn, ( void * ) instance, ( void * ) user_data );
+	g_return_val_if_fail( BASE_IS_ISESSION( instance ), TRUE );
 
-	str = get_isession_str( instance );
+	g_debug( "%s: instance=%p (%s)", thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ));
 
-	if( str->sm_client_quit_handler_id &&
-		g_signal_handler_is_connected( str->sm_client, str->sm_client_quit_handler_id )){
-			g_signal_handler_disconnect( str->sm_client, str->sm_client_quit_handler_id  );
-	}
+	g_value_init( &instance_params, G_TYPE_FROM_INSTANCE( instance ));
+	g_value_set_instance( &instance_params, ( gpointer ) instance );
 
-	if( str->sm_client_quit_requested_handler_id &&
-		g_signal_handler_is_connected( str->sm_client, str->sm_client_quit_requested_handler_id )){
-			g_signal_handler_disconnect( str->sm_client, str->sm_client_quit_requested_handler_id  );
-	}
+	g_value_init( &return_value, G_TYPE_BOOLEAN );
+	g_value_set_boolean( &return_value, TRUE );
 
-	if( str->sm_client ){
-		g_object_unref( str->sm_client );
-	}
+	g_signal_emitv( &instance_params, st_signals[ QUIT_REQUESTED ], 0, &return_value );
 
-	g_free( str );
+	return( g_value_get_boolean( &return_value ));
 }
 
 /*
  * the session manager advertises us that the session is about to exit
+ *
+ * Returns: %TRUE if the application is willing to quit, %FALSE else.
+ *
+ * This function is called when the session manager detects the end of
+ * session and thus asks its clients if they are willing to quit.
  */
 static void
 client_quit_requested_cb( EggSMClient *client, BaseISession *instance )
 {
-	static const gchar *thisfn = "base_isession_client_quit_requested_cb";
-	gboolean willing_to = TRUE;
+	gboolean willing_to;
 
-	g_return_if_fail( BASE_IS_ISESSION( instance ));
+	willing_to = base_isession_is_willing_to_quit( instance );
 
-	g_debug( "%s: client=%p, instance=%p", thisfn, ( void * ) client, ( void * ) instance );
+	egg_sm_client_will_quit( client, willing_to );
+}
 
-#if 0
-		if( application->private->main_window ){
+/*
+ * Handler of BASE_SIGNAL_QUIT_REQUESTED message
+ *
+ * Application should handle this signal in order to trap application
+ * termination, returning %FALSE if it is not willing to quit.
+ */
+static gboolean
+on_quit_requested_class_handler( BaseISession *instance, void *user_data )
+{
+	static const gchar *thisfn = "base_isession_on_quit_requested_class_handler";
 
-				g_return_if_fail( BASE_IS_WINDOW( application->private->main_window ));
-				willing_to = base_window_is_willing_to_quit( application->private->main_window );
-		}
-#endif
+	g_return_val_if_fail( BASE_IS_ISESSION( instance ), TRUE );
 
-	egg_sm_client_will_quit( client, willing_to );
+	g_debug( "%s: instance=%p (%s), user_data=%p",
+			thisfn,
+			( void * ) instance, G_OBJECT_TYPE_NAME( instance ),
+			( void * ) user_data );
+
+	return( TRUE );
+}
+
+/*
+ * the first handler which returns FALSE stops the emission
+ * this is used on BASE_SIGNAL_QUIT_REQUESTED signal
+ */
+static gboolean
+signal_accumulator_false_handled(
+		GSignalInvocationHint *hint, GValue *return_accu, const GValue *handler_return, gpointer dummy)
+{
+	static const gchar *thisfn = "base_isession_signal_accumulator_false_handled";
+	gboolean continue_emission;
+	gboolean willing_to_quit;
+
+	willing_to_quit = g_value_get_boolean( handler_return );
+	g_value_set_boolean( return_accu, willing_to_quit );
+	continue_emission = willing_to_quit;
+
+	g_debug( "%s: willing_to handler returns %s", thisfn, willing_to_quit ? "True":"False" );
+	return( continue_emission );
 }
 
 /*
- * cleanly terminate the main window when exiting the session
+ * cleanly terminate the application when exiting the session
+ * -> triggers the implementation
  */
 static void
 client_quit_cb( EggSMClient *client, BaseISession *instance )
@@ -237,27 +386,18 @@ client_quit_cb( EggSMClient *client, BaseISession *instance )
 
 	g_debug( "%s: client=%p, instance=%p", thisfn, ( void * ) client, ( void * ) instance );
 
-#if 0
-		if( application->private->main_window ){
-
-				g_return_if_fail( BASE_IS_WINDOW( application->private->main_window ));
-				g_object_unref( application->private->main_window );
-				application->private->main_window = NULL;
-		}
-#endif
+	g_signal_emit_by_name( G_OBJECT( instance ), BASE_SIGNAL_QUIT, NULL );
 }
 
-static ISessionStr *
-get_isession_str( BaseISession *instance )
+static void
+on_quit_class_handler( BaseISession *instance, void *user_data )
 {
-	ISessionStr *str;
-
-	str = ( ISessionStr * ) g_object_get_data( G_OBJECT( instance ), BASE_PROP_ISESSION );
+	static const gchar *thisfn = "base_isession_on_quit_class_handler";
 
-	if( !str ){
-		str = g_new0( ISessionStr, 1 );
-		g_object_set_data( G_OBJECT( instance ), BASE_PROP_ISESSION, str );
-	}
+	g_return_if_fail( BASE_IS_ISESSION( instance ));
 
-	return( str );
+	g_debug( "%s: instance=%p (%s), user_data=%p",
+			thisfn,
+			( void * ) instance, G_OBJECT_TYPE_NAME( instance ),
+			( void * ) user_data );
 }
diff --git a/src/nact/base-isession.h b/src/nact/base-isession.h
index 874ce52..791d919 100644
--- a/src/nact/base-isession.h
+++ b/src/nact/base-isession.h
@@ -36,18 +36,19 @@
  * @short_description: #BaseISession interface definition.
  * @include: nact/base-isession.h
  *
- * This interface implements the features to make an application
- * unique, i.e. cjheck that we run only one instance of it.
+ * This interface implements the features needed to monitor the end of the
+ * session, thus letting the application react if some modifications need
+ * to be saved before allowing to quit.
  */
 
 #include <gtk/gtk.h>
 
 G_BEGIN_DECLS
 
-#define BASE_ISESSION_TYPE                      ( base_isession_get_type())
-#define BASE_ISESSION( object )                 ( G_TYPE_CHECK_INSTANCE_CAST( object, BASE_ISESSION_TYPE, BaseISession ))
-#define BASE_IS_ISESSION( object )              ( G_TYPE_CHECK_INSTANCE_TYPE( object, BASE_ISESSION_TYPE ))
-#define BASE_ISESSION_GET_INTERFACE( instance ) ( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), BASE_ISESSION_TYPE, BaseISessionInterface ))
+#define BASE_TYPE_ISESSION                      ( base_isession_get_type())
+#define BASE_ISESSION( instance )               ( G_TYPE_CHECK_INSTANCE_CAST( instance, BASE_TYPE_ISESSION, BaseISession ))
+#define BASE_IS_ISESSION( instance )            ( G_TYPE_CHECK_INSTANCE_TYPE( instance, BASE_TYPE_ISESSION ))
+#define BASE_ISESSION_GET_INTERFACE( instance ) ( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), BASE_TYPE_ISESSION, BaseISessionInterface ))
 
 typedef struct _BaseISession                    BaseISession;
 typedef struct _BaseISessionInterfacePrivate    BaseISessionInterfacePrivate;
@@ -59,9 +60,17 @@ typedef struct {
 }
 	BaseISessionInterface;
 
-GType    base_isession_get_type( void );
+/**
+ * Signals defined by the BaseISession interface
+ */
+#define BASE_SIGNAL_QUIT_REQUESTED			"base-signal-isession-quit-requested"
+#define BASE_SIGNAL_QUIT					"base-signal-isession-quit"
+
+GType    base_isession_get_type          ( void );
+
+void     base_isession_init              ( BaseISession *instance );
 
-void     base_isession_init    ( BaseISession *instance );
+gboolean base_isession_is_willing_to_quit( const BaseISession *instance );
 
 G_END_DECLS
 
diff --git a/src/nact/base-iunique.c b/src/nact/base-iunique.c
index 631359a..b3184bd 100644
--- a/src/nact/base-iunique.c
+++ b/src/nact/base-iunique.c
@@ -45,19 +45,24 @@ struct _BaseIUniqueInterfacePrivate {
 	void *empty;						/* so that gcc -pedantic is happy */
 };
 
-/* BaseIUnique properties, set as data association against the GObject instance
+/* pseudo-properties, set against the instance
  */
-#define BASE_PROP_HANDLE				"base-prop-iunique-handle"
-#define BASE_PROP_INITIALIZED			"base-prop-iunique-initialized"
+typedef struct {
+	gchar     *unique_app_name;
+	UniqueApp *handle;
+}
+	IUniqueData;
+
+#define BASE_PROP_IUNIQUE_DATA			"base-prop-iunique-data"
 
 static guint st_initializations = 0;	/* interface initialisation count */
 
-static GType register_type( void );
-static void  interface_base_init( BaseIUniqueInterface *klass );
-static void  interface_base_finalize( BaseIUniqueInterface *klass );
+static GType        register_type( void );
+static void         interface_base_init( BaseIUniqueInterface *klass );
+static void         interface_base_finalize( BaseIUniqueInterface *klass );
 
-static void  instance_init( BaseIUnique *instance );
-static void  on_instance_finalized( gpointer user_data, BaseIUnique *instance );
+static IUniqueData *get_iunique_data( BaseIUnique *instance );
+static void         on_instance_finalized( gpointer user_data, BaseIUnique *instance );
 
 #if 0
 static UniqueResponse on_unique_message_received( UniqueApp *app, UniqueCommand command, UniqueMessageData *message, guint time, gpointer user_data );
@@ -134,34 +139,40 @@ interface_base_finalize( BaseIUniqueInterface *klass )
 	}
 }
 
-static void
-instance_init( BaseIUnique *instance )
+static IUniqueData *
+get_iunique_data( BaseIUnique *instance )
 {
-	static const gchar *thisfn = "base_iunique_instance_init";
+	IUniqueData *data;
 
-	if( ! ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( instance ), BASE_PROP_INITIALIZED ))){
+	data = ( IUniqueData * ) g_object_get_data( G_OBJECT( instance ), BASE_PROP_IUNIQUE_DATA );
 
-		g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+	if( !data ){
+		data = g_new0( IUniqueData, 1 );
+		g_object_set_data( G_OBJECT( instance ), BASE_PROP_IUNIQUE_DATA, data );
 
 		g_object_weak_ref( G_OBJECT( instance ), ( GWeakNotify ) on_instance_finalized, NULL );
-
-		g_object_set_data( G_OBJECT( instance ), BASE_PROP_INITIALIZED, GUINT_TO_POINTER( TRUE ));
 	}
+
+	return( data );
 }
 
 static void
 on_instance_finalized( gpointer user_data, BaseIUnique *instance )
 {
 	static const gchar *thisfn = "base_iunique_on_instance_finalized";
+	IUniqueData *data;
 
 	g_debug( "%s: instance=%p, user_data=%p", thisfn, ( void * ) instance, ( void * ) user_data );
 
-	UniqueApp *handle = ( UniqueApp * ) g_object_get_data( G_OBJECT( instance ), BASE_PROP_HANDLE );
+	data = get_iunique_data( instance );
 
-	if( handle ){
-		g_return_if_fail( UNIQUE_IS_APP( handle ));
-		g_object_unref( handle );
+	if( data->handle ){
+		g_return_if_fail( UNIQUE_IS_APP( data->handle ));
+		g_object_unref( data->handle );
 	}
+
+	g_free( data->unique_app_name );
+	g_free( data );
 }
 
 /*
@@ -174,26 +185,25 @@ gboolean
 base_iunique_init_with_name( BaseIUnique *instance, const gchar *unique_app_name )
 {
 	static const gchar *thisfn = "base_iunique_init_with_name";
+	IUniqueData *data;
 	gboolean ret;
 	gboolean is_first;
 	gchar *msg;
-	UniqueApp *handle;
 
 	g_return_val_if_fail( BASE_IS_IUNIQUE( instance ), FALSE );
 
-	instance_init( instance );
-
 	g_debug( "%s: instance=%p, unique_app_name=%s", thisfn, ( void * ) instance, unique_app_name );
 
 	ret = TRUE;
+	data = get_iunique_data( instance );
 
 	if( unique_app_name && strlen( unique_app_name )){
 
-			handle = unique_app_new( unique_app_name, NULL );
-			is_first = !unique_app_is_running( handle );
+			data->handle = unique_app_new( unique_app_name, NULL );
+			is_first = !unique_app_is_running( data->handle );
 
 			if( !is_first ){
-				unique_app_send_message( handle, UNIQUE_ACTIVATE, NULL );
+				unique_app_send_message( data->handle, UNIQUE_ACTIVATE, NULL );
 				/* i18n: application name */
 				msg = g_strdup_printf(
 						_( "Another instance of %s is already running.\n"
@@ -208,13 +218,13 @@ base_iunique_init_with_name( BaseIUnique *instance, const gchar *unique_app_name
 			 */
 			} else {
 				g_signal_connect(
-						handle,
+						data->handle,
 						"message-received",
 						G_CALLBACK( on_unique_message_received ),
 						instance );
 #endif
 			} else {
-				g_object_set_data( G_OBJECT( instance ), BASE_PROP_HANDLE, handle );
+				data->unique_app_name = g_strdup( unique_app_name );
 			}
 	}
 
diff --git a/src/nact/base-iunique.h b/src/nact/base-iunique.h
index 6cbb630..63bd123 100644
--- a/src/nact/base-iunique.h
+++ b/src/nact/base-iunique.h
@@ -37,17 +37,17 @@
  * @include: nact/base-iunique.h
  *
  * This interface implements the features to make an application
- * unique, i.e. cjheck that we run only one instance of it.
+ * unique, i.e. check that we run only one instance of it.
  */
 
-#include <gtk/gtk.h>
+#include <glib-object.h>
 
 G_BEGIN_DECLS
 
-#define BASE_IUNIQUE_TYPE                      ( base_iunique_get_type())
-#define BASE_IUNIQUE( object )                 ( G_TYPE_CHECK_INSTANCE_CAST( object, BASE_IUNIQUE_TYPE, BaseIUnique ))
-#define BASE_IS_IUNIQUE( object )              ( G_TYPE_CHECK_INSTANCE_TYPE( object, BASE_IUNIQUE_TYPE ))
-#define BASE_IUNIQUE_GET_INTERFACE( instance ) ( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), BASE_IUNIQUE_TYPE, BaseIUniqueInterface ))
+#define BASE_TYPE_IUNIQUE                      ( base_iunique_get_type())
+#define BASE_IUNIQUE( instance )               ( G_TYPE_CHECK_INSTANCE_CAST( instance, BASE_TYPE_IUNIQUE, BaseIUnique ))
+#define BASE_IS_IUNIQUE( instance )            ( G_TYPE_CHECK_INSTANCE_TYPE( instance, BASE_TYPE_IUNIQUE ))
+#define BASE_IUNIQUE_GET_INTERFACE( instance ) ( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), BASE_TYPE_IUNIQUE, BaseIUniqueInterface ))
 
 typedef struct _BaseIUnique                    BaseIUnique;
 typedef struct _BaseIUniqueInterfacePrivate    BaseIUniqueInterfacePrivate;
diff --git a/src/nact/base-marshal.def b/src/nact/base-marshal.def
index c88f1dd..726daa1 100644
--- a/src/nact/base-marshal.def
+++ b/src/nact/base-marshal.def
@@ -1,9 +1,2 @@
-# BaseWindow:: BASE_SIGNAL_WILLING_TO_QUIT
+# BaseISession:: BASE_SIGNAL_QUIT_REQUESTED
 BOOLEAN:VOID
-#
-# NactTreeView:: TREE_SIGNAL_COUNT_CHANGED
-VOID:BOOLEAN,INT,INT,INT
-#
-# NactMainWindow::TAB_UPDATABLE_SIGNAL_ITEM_UPDATED
-# NactMainWindow::MAIN_SIGNAL_ITEM_UPDATED
-VOID:POINTER,UINT
diff --git a/src/nact/base-window.c b/src/nact/base-window.c
index 30a6db6..210722d 100644
--- a/src/nact/base-window.c
+++ b/src/nact/base-window.c
@@ -72,7 +72,7 @@ struct _BaseWindowPrivate {
 	BaseBuilder     *builder;
 };
 
-/* connected signal, to be disconnected at NactWindow dispose
+/* connected signal, to be disconnected at BaseWindow::instance_dispose()
  */
 typedef struct {
 	gpointer instance;
@@ -95,9 +95,14 @@ enum {
 	BASE_PROP_N_PROPERTIES
 };
 
-/* pseudo-properties, set as GObject data association
+/* pseudo-properties set against the Gtk toplevel
  */
-#define BASE_PROP_GTK_INITIALIZED		"base-prop-window-gtk-initialized"
+typedef struct {
+	gboolean gtk_initialized;
+}
+	BaseGtkData;
+
+#define BASE_PROP_GTK_DATA				"base-prop-window-gtk-data"
 
 /* signals defined in BaseWindow, to be used in all derived classes
  */
@@ -105,7 +110,6 @@ enum {
 	INITIALIZE_GTK,
 	INITIALIZE_BASE,
 	SHOW_WIDGETS,
-	WILLING_TO_QUIT,
 	LAST_SIGNAL
 };
 
@@ -124,6 +128,7 @@ static void     instance_finalize( GObject *window );
 
 /* initialization process
  */
+static BaseGtkData *get_base_gtk_data( BaseWindow *window );
 static gboolean base_window_init2( BaseWindow *window );
 static gboolean setup_builder( const BaseWindow *window );
 static gboolean load_gtk_toplevel( const BaseWindow *window );
@@ -143,10 +148,8 @@ static void     do_show_widgets( BaseWindow *window );
 
 static gboolean do_run( BaseWindow *window, GtkWindow *toplevel );
 static gboolean on_delete_event( GtkWidget *widget, GdkEvent *event, BaseWindow *window );
-static gboolean on_is_willing_to_quit_class_handler( BaseWindow *window );
 
 static void     record_connected_signal( BaseWindow *window, GObject *instance, gulong handler_id );
-static gboolean signal_accumulator_false_handled( GSignalInvocationHint *hint, GValue *return_accu, const GValue *handler_return, gpointer dummy);
 static gint     display_dlg( const BaseWindow *parent, GtkMessageType type_message, GtkButtonsType type_buttons, const gchar *primary, const gchar *secondary );
 
 GType
@@ -257,7 +260,6 @@ class_init( BaseWindowClass *klass )
 	klass->initialize_base_window = do_initialize_base_window;
 	klass->all_widgets_showed = do_show_widgets;
 	klass->run = do_run;
-	klass->is_willing_to_quit = NULL;
 
 	/**
 	 * base-signal-window-initialize-gtk:
@@ -320,45 +322,6 @@ class_init( BaseWindowClass *klass )
 				g_cclosure_marshal_VOID__VOID,
 				G_TYPE_NONE,
 				0 );
-
-	/**
-	 * base-signal-window-willing-to-quit:
-	 *
-	 * The signal is emitted when the application is about to terminate,
-	 * to determine if all BaseWindow-derived windows are actually willing
-	 * to quit.
-	 *
-	 * If the window is not willing to quit, then the user handler should
-	 * return %FALSE to stop the signal emission.
-	 *
-	 * Returning %TRUE will let the signal be emitted to other connected
-	 * handlers, eventually authorizing the application to terminate.
-	 *
-	 * Notes about GLib signals.
-	 *
-	 * If the signal is defined as G_SIGNAL_RUN_CLEANUP, then the object
-	 * handler does not participate to the return value of the signal
-	 * (accumulator is not called). More this object handler is triggered
-	 * unconditionnally, event if a user handler has returned %FALSE to
-	 * stop the emission.
-	 *
-	 * Contrarily, if the signal is defined as G_SIGNAL_RUN_LAST, then the
-	 * object handler returned value is taken into account by the accumulator,
-	 * and can participate to the return value for the signal. If a user
-	 * handler returns FALSE to stop the emission, then the object handler
-	 * will not be triggered.
-	 */
-	st_signals[ WILLING_TO_QUIT ] =
-		g_signal_new_class_handler(
-				BASE_SIGNAL_WILLING_TO_QUIT,
-				G_TYPE_FROM_CLASS( klass ),
-				G_SIGNAL_RUN_LAST,
-				G_CALLBACK( on_is_willing_to_quit_class_handler ),
-				( GSignalAccumulator ) signal_accumulator_false_handled,
-				NULL,
-				nact_cclosure_marshal_BOOLEAN__VOID,
-				G_TYPE_BOOLEAN,
-				0 );
 }
 
 static void
@@ -605,6 +568,26 @@ instance_finalize( GObject *window )
 	}
 }
 
+static BaseGtkData *
+get_base_gtk_data( BaseWindow *window )
+{
+	BaseGtkData *data;
+	BaseWindowPrivate *priv;
+
+	priv = window->private;
+
+	g_return_val_if_fail( GTK_IS_WINDOW( priv->gtk_toplevel ), NULL );
+
+	data = ( BaseGtkData * ) g_object_get_data( G_OBJECT( priv->gtk_toplevel ), BASE_PROP_GTK_DATA );
+
+	if( !data ){
+		data = g_new0( BaseGtkData, 1 );
+		g_object_set_data( G_OBJECT( priv->gtk_toplevel ), BASE_PROP_GTK_DATA, data );
+	}
+
+	return( data );
+}
+
 /*
  * base_window_init2:
  * @window: this #BaseWindow object.
@@ -744,17 +727,21 @@ load_gtk_toplevel( const BaseWindow *window )
 static gboolean
 is_gtk_toplevel_initialized( const BaseWindow *window, GtkWindow *gtk_toplevel )
 {
-	gboolean initialized;
+	BaseGtkData *data;
 
-	initialized = GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( gtk_toplevel ), BASE_PROP_GTK_INITIALIZED ));
+	data = get_base_gtk_data(( BaseWindow * ) window );
 
-	return( initialized );
+	return( data->gtk_initialized );
 }
 
 static void
 set_gtk_toplevel_initialized( const BaseWindow *window, GtkWindow *gtk_toplevel, gboolean initialized )
 {
-	g_object_set_data( G_OBJECT( gtk_toplevel ), BASE_PROP_GTK_INITIALIZED, GUINT_TO_POINTER( initialized ));
+	BaseGtkData *data;
+
+	data = get_base_gtk_data(( BaseWindow * ) window );
+
+	data->gtk_initialized = initialized;
 }
 
 /*
@@ -819,7 +806,7 @@ base_window_run( BaseWindow *window )
 	gboolean run_ok;
 	int code;
 
-	code = BASE_EXIT_CODE_START_FAIL;
+	code = BASE_EXIT_CODE_PROGRAM;
 
 	g_return_val_if_fail( BASE_IS_WINDOW( window ), code );
 
@@ -832,7 +819,7 @@ base_window_run( BaseWindow *window )
 		}
 
 		if( !run_ok ){
-			code = BASE_EXIT_CODE_INIT_FAIL;
+			code = BASE_EXIT_CODE_INIT_WINDOW;
 
 		} else {
 			g_return_val_if_fail( GTK_IS_WINDOW( window->private->gtk_toplevel ), code );
@@ -1064,7 +1051,7 @@ do_run( BaseWindow *window, GtkWindow *toplevel )
 	g_return_val_if_fail( BASE_IS_WINDOW( window ), BASE_EXIT_CODE_PROGRAM );
 	g_return_val_if_fail( GTK_IS_WINDOW( toplevel ), BASE_EXIT_CODE_PROGRAM );
 
-	code = BASE_EXIT_CODE_INIT_FAIL;
+	code = BASE_EXIT_CODE_INIT_WINDOW;
 
 	if( !window->private->dispose_has_run ){
 		g_signal_connect( G_OBJECT( toplevel ), "delete-event", G_CALLBACK( on_delete_event ), window );
@@ -1257,93 +1244,6 @@ base_window_get_widget( const BaseWindow *window, const gchar *name )
 }
 
 /**
- * base_window_is_willing_to_quit:
- * @window: this #BaseWindow instance.
- *
- * Returns: %TRUE if the application is willing to quit, %FALSE else.
- *
- * This function is called when the session manager detects the end of
- * session and thus asks its client if they are willing to quit.
- */
-gboolean
-base_window_is_willing_to_quit( const BaseWindow *window )
-{
-	static const gchar *thisfn = "base_window_is_willing_to_quit";
-	gboolean willing_to_quit;
-	GValue instance_params = {0};
-	GValue return_value = {0};
-
-	willing_to_quit = TRUE;
-
-	g_return_val_if_fail( BASE_IS_WINDOW( window ), TRUE );
-
-	if( !window->private->dispose_has_run ){
-		g_debug( "%s: window=%p", thisfn, ( void * ) window );
-
-		g_value_init( &instance_params, G_TYPE_FROM_INSTANCE( window ));
-		g_value_set_instance( &instance_params, ( gpointer ) window );
-
-		g_value_init( &return_value, G_TYPE_BOOLEAN );
-		g_value_set_boolean( &return_value, TRUE );
-
-		g_signal_emitv( &instance_params, st_signals[WILLING_TO_QUIT], 0, &return_value );
-
-		willing_to_quit = g_value_get_boolean( &return_value );
-	}
-
-	return( willing_to_quit );
-}
-
-/*
- * Handler of BASE_SIGNAL_WILLING_TO_QUIT message connected on the main window Gtk toplevel
- *
- * As other BaseWindow signals, the default object handler converts the
- *  signal to a virtual method.
- *
- * Main window should handle this signal in order to trap application termination,
- * returning %FALSE if it is not willing to quit.
- */
-static gboolean
-on_is_willing_to_quit_class_handler( BaseWindow *window )
-{
-	static const gchar *thisfn = "base_window_on_is_willing_to_quit_class_handler";
-	gboolean willing_to;
-
-	willing_to = TRUE;
-
-	g_return_val_if_fail( BASE_IS_WINDOW( window ), TRUE );
-
-	if( !window->private->dispose_has_run ){
-		g_debug( "%s: window=%p", thisfn, ( void * ) window );
-
-		if( BASE_WINDOW_GET_CLASS( window )->is_willing_to_quit ){
-			willing_to = BASE_WINDOW_GET_CLASS( window )->is_willing_to_quit( window );
-		}
-	}
-
-	return( willing_to );
-}
-
-/*
- * the first handler which returns FALSE stops the emission
- * this is used on BASE_SIGNAL_WILLING_TO_QUIT signal
- */
-static gboolean
-signal_accumulator_false_handled( GSignalInvocationHint *hint, GValue *return_accu, const GValue *handler_return, gpointer dummy)
-{
-	static const gchar *thisfn = "base_window_signal_accumulator_false_handled";
-	gboolean continue_emission;
-	gboolean willing_to_quit;
-
-	willing_to_quit = g_value_get_boolean( handler_return );
-	g_value_set_boolean( return_accu, willing_to_quit );
-	continue_emission = willing_to_quit;
-
-	g_debug( "%s: willing_to handler returns %s", thisfn, willing_to_quit ? "True":"False" );
-	return( continue_emission );
-}
-
-/**
  * base_window_display_error_dlg:
  * @parent: the #BaseWindow parent, may be %NULL.
  * @primary: the primary message.
diff --git a/src/nact/base-window.h b/src/nact/base-window.h
index e368313..301108d 100644
--- a/src/nact/base-window.h
+++ b/src/nact/base-window.h
@@ -171,22 +171,6 @@ typedef struct {
 	 * Returns: the exit code of the program if it is the main window.
 	 */
 	int      ( *run )                    ( BaseWindow *window, GtkWindow *toplevel );
-
-	/**
-	 * is_willing_to_quit:
-	 * @window: this #BaseWindow instance.
-	 *
-	 * Invoked (e.g. by the session manager) when the application
-	 * has been asked for to terminate itself.
-	 *
-	 * Unless the derived class is not willing to quit, it should call
-	 * its parent class method, in order to give it a chance to also
-	 * refuse the termination of the application.
-	 *
-	 * The derived method should return %TRUE if it is willing to quit,
-	 * %FALSE else.
-	 */
-	gboolean ( *is_willing_to_quit )     ( const BaseWindow *window );
 }
 	BaseWindowClass;
 
@@ -194,8 +178,8 @@ typedef struct {
  * Properties defined by the BaseWindow class.
  * They should be provided at object instanciation time.
  *
- * Either PARENT or APPLICATION must be provided at instanciation time.
- * Instanciation time also requires:
+ * Instanciation time requires:
+ * - either PARENT or APPLICATION
  * - XMLUI_FILENAME
  * - TOPLEVEL_NAME
  * - HAS_OWN_BUILDER
@@ -226,7 +210,6 @@ typedef struct {
 #define BASE_SIGNAL_INITIALIZE_GTK				"base-signal-window-initialize-gtk"
 #define BASE_SIGNAL_INITIALIZE_WINDOW			"base-signal-window-initialize-window"
 #define BASE_SIGNAL_SHOW_WIDGETS				"base-signal-window-show-widgets"
-#define BASE_SIGNAL_WILLING_TO_QUIT				"base-signal-window-willing-to-quit"
 
 GType            base_window_get_type( void );
 
@@ -243,8 +226,6 @@ GtkWindow       *base_window_get_gtk_toplevel        ( const BaseWindow *window
 GtkWindow       *base_window_get_gtk_toplevel_by_name( const BaseWindow *window, const gchar *name );
 GtkWidget       *base_window_get_widget              ( const BaseWindow *window, const gchar *name );
 
-gboolean         base_window_is_willing_to_quit      ( const BaseWindow *window );
-
 void             base_window_display_error_dlg       ( const BaseWindow *parent, const gchar *primary, const gchar *secondary );
 gboolean         base_window_display_yesno_dlg       ( const BaseWindow *parent, const gchar *primary, const gchar *secondary );
 void             base_window_display_message_dlg     ( const BaseWindow *parent, GSList *message );
diff --git a/src/nact/main.c b/src/nact/main.c
index 075c307..11502dc 100644
--- a/src/nact/main.c
+++ b/src/nact/main.c
@@ -69,7 +69,7 @@ main( int argc, char *argv[] )
 	 */
 	appli = nact_application_new();
 
-	ret = base_application_run( BASE_APPLICATION( appli ), argc, argv );
+	ret = base_application_run_with_args( BASE_APPLICATION( appli ), argc, argv );
 
 	g_object_unref( appli );
 
diff --git a/src/nact/nact-application.c b/src/nact/nact-application.c
index 5b47e6c..60bd784 100644
--- a/src/nact/nact-application.c
+++ b/src/nact/nact-application.c
@@ -114,7 +114,7 @@ register_type( void )
 
 	g_debug( "%s", thisfn );
 
-	type = g_type_register_static( BASE_APPLICATION_TYPE, "NactApplication", &info, 0 );
+	type = g_type_register_static( BASE_TYPE_APPLICATION, "NactApplication", &info, 0 );
 
 	return( type );
 }
@@ -323,7 +323,7 @@ appli_create_windows( BaseApplication *application )
 		ret = TRUE;
 
 	} else {
-		g_object_set( G_OBJECT( application ), BASE_PROP_CODE, BASE_EXIT_CODE_WINDOW, NULL );
+		g_object_set( G_OBJECT( application ), BASE_PROP_CODE, BASE_EXIT_CODE_INIT_WINDOW, NULL );
 	}
 
 	return( ret );
diff --git a/src/nact/nact-main-window.c b/src/nact/nact-main-window.c
index 2bb747e..8a701f1 100644
--- a/src/nact/nact-main-window.c
+++ b/src/nact/nact-main-window.c
@@ -41,7 +41,7 @@
 #include <core/na-iprefs.h>
 #include <core/na-pivot.h>
 
-#include "base-marshal.h"
+#include "base-isession.h"
 #include "nact-iaction-tab.h"
 #include "nact-icommand-tab.h"
 #include "nact-ibasenames-tab.h"
@@ -55,6 +55,7 @@
 #include "nact-main-tab.h"
 #include "nact-main-statusbar.h"
 #include "nact-main-window.h"
+#include "nact-marshal.h"
 #include "nact-menubar.h"
 #include "nact-tree-view.h"
 #include "nact-confirm-logout.h"
@@ -884,7 +885,7 @@ on_base_initialize_base_window( NactMainWindow *window, gpointer user_data )
 		/* is willing to quit ?
 		 */
 		base_window_signal_connect( BASE_WINDOW( window ),
-				G_OBJECT( window ), BASE_SIGNAL_WILLING_TO_QUIT, G_CALLBACK( on_base_is_willing_to_quit ));
+				G_OBJECT( window ), BASE_SIGNAL_QUIT_REQUESTED, G_CALLBACK( on_base_is_willing_to_quit ));
 	}
 }
 
diff --git a/src/nact/nact-marshal.def b/src/nact/nact-marshal.def
new file mode 100644
index 0000000..4623a90
--- /dev/null
+++ b/src/nact/nact-marshal.def
@@ -0,0 +1,6 @@
+# NactTreeView:: TREE_SIGNAL_COUNT_CHANGED
+VOID:BOOLEAN,INT,INT,INT
+#
+# NactMainWindow::TAB_UPDATABLE_SIGNAL_ITEM_UPDATED
+# NactMainWindow::MAIN_SIGNAL_ITEM_UPDATED
+VOID:POINTER,UINT
diff --git a/src/nact/nact-menubar-maintainer.c b/src/nact/nact-menubar-maintainer.c
index 85d7415..43e6c20 100644
--- a/src/nact/nact-menubar-maintainer.c
+++ b/src/nact/nact-menubar-maintainer.c
@@ -123,6 +123,7 @@ nact_menubar_maintainer_on_dump_clipboard( GtkAction *action, BaseWindow *window
 void
 nact_menubar_maintainer_on_test_function( GtkAction *action, BaseWindow *window )
 {
-	gboolean is_willing = base_window_is_willing_to_quit( BASE_WINDOW( window ));
+	BaseApplication *application = base_window_get_application( window );
+	gboolean is_willing = base_application_is_willing_to_quit( application );
 	g_debug( "nact_menubar_maintainer_on_test_function: willing_to=%s", is_willing ? "True":"False" );
 }
diff --git a/src/nact/nact-tree-view.c b/src/nact/nact-tree-view.c
index 31d6643..9b7be77 100644
--- a/src/nact/nact-tree-view.c
+++ b/src/nact/nact-tree-view.c
@@ -39,8 +39,8 @@
 #include <core/na-gtk-utils.h>
 
 #include "base-keysyms.h"
-#include "base-marshal.h"
 #include "nact-application.h"
+#include "nact-marshal.h"
 #include "nact-tree-view.h"
 #include "nact-tree-model.h"
 #include "nact-tree-ieditable.h"



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]