[nautilus-actions] NAImporterAsk: fix z-order



commit c86e3fcfcb0a4a2da160bd2fef173d17e6fb8236
Author: Pierre Wieser <pwieser trychlos org>
Date:   Wed Nov 30 23:26:06 2011 +0100

    NAImporterAsk: fix z-order
    
    As the NAImporterAsk dialog was transient for the main window, its z-order
    was actually between the main window and the assistant.
    
    Also no more load from GtkBuilder at each invocation, but hide/show the
    dialog instead.

 ChangeLog                        |   14 ++++
 src/core/na-importer-ask.c       |  136 ++++++++++++++++++++++++++++----------
 src/core/na-importer-ask.h       |    8 +-
 src/nact/nact-assistant-import.c |    2 +-
 4 files changed, 119 insertions(+), 41 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index d6257a0..71b6bda 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2011-11-30 Pierre Wieser <pwieser trychlos org>
+
+	* src/core/na-importer-ask.c:
+	* src/core/na-importer-ask.h: Now derives from GObject.
+
+	* src/core/na-importer-ask.c (import_ask_new):
+	All one-time initialization is made here, being able to return NULL if failed.
+
+	* src/core/na-importer-ask.c (on_destroy_toplevel):
+	NAImporterAsk is now attached to its parent, and destroyed with it.
+
+	* src/nact/nact-assistant-import.c (assistant_apply):
+	Make the assistant the parent of NAImporterAsk (instead of main window).
+
 2011-11-29 Pierre Wieser <pwieser trychlos org>
 
 	* src/core/na-object-item-factory.c:
diff --git a/src/core/na-importer-ask.c b/src/core/na-importer-ask.c
index 7b400e6..bf60135 100644
--- a/src/core/na-importer-ask.c
+++ b/src/core/na-importer-ask.c
@@ -51,7 +51,6 @@ struct _NAImporterAskClassPrivate {
  */
 struct _NAImporterAskPrivate {
 	gboolean                dispose_has_run;
-	GtkBuilder             *builder;
 	GtkWindow              *toplevel;
 	NAObjectItem           *importing;
 	NAObjectItem           *existing;
@@ -59,7 +58,9 @@ struct _NAImporterAskPrivate {
 	guint                   mode;
 };
 
-static GtkDialogClass *st_parent_class = NULL;
+static GObjectClass  *st_parent_class = NULL;
+static NAImporterAsk *st_dialog       = NULL;
+static const gchar   *st_uixml        = PKGDATADIR "/na-importer-ask.ui";
 
 static GType      register_type( void );
 static void       class_init( NAImporterAskClass *klass );
@@ -67,12 +68,11 @@ static void       instance_init( GTypeInstance *instance, gpointer klass );
 static void       instance_dispose( GObject *dialog );
 static void       instance_finalize( GObject *dialog );
 
-static NAImporterAsk *import_ask_new();
+static NAImporterAsk *import_ask_new( GtkWindow *parent );
 
 static void       init_dialog( NAImporterAsk *editor );
-/*static void       on_cancel_clicked( GtkButton *button, NAImporterAsk *editor );
-static void       on_ok_clicked( GtkButton *button, NAImporterAsk *editor );*/
 static void       get_selected_mode( NAImporterAsk *editor );
+static gboolean   on_destroy_toplevel( GtkWindow *toplevel, GdkEvent *event, NAImporterAsk *dialog );
 static gboolean   on_dialog_response( NAImporterAsk *editor, gint code );
 
 GType
@@ -107,7 +107,7 @@ register_type( void )
 
 	g_debug( "%s", thisfn );
 
-	type = g_type_register_static( GTK_TYPE_DIALOG, "NAImporterAsk", &info, 0 );
+	type = g_type_register_static( G_TYPE_OBJECT, "NAImporterAsk", &info, 0 );
 
 	return( type );
 }
@@ -134,7 +134,6 @@ instance_init( GTypeInstance *instance, gpointer klass )
 {
 	static const gchar *thisfn = "na_importer_ask_instance_init";
 	NAImporterAsk *self;
-	GError *error;
 
 	g_return_if_fail( NA_IS_IMPORTER_ASK( instance ));
 
@@ -145,18 +144,6 @@ instance_init( GTypeInstance *instance, gpointer klass )
 
 	self->private = g_new0( NAImporterAskPrivate, 1 );
 
-	self->private->builder = gtk_builder_new();
-
-	error = NULL;
-	gtk_builder_add_from_file( self->private->builder, PKGDATADIR "/na-importer-ask.ui", &error );
-	if( error ){
-		g_warning( "%s: %s", thisfn, error->message );
-		g_error_free( error );
-
-	} else {
-		self->private->toplevel = GTK_WINDOW( gtk_builder_get_object( self->private->builder, "ImporterAskDialog" ));
-	}
-
 	self->private->dispose_has_run = FALSE;
 }
 
@@ -176,8 +163,6 @@ instance_dispose( GObject *dialog )
 
 		self->private->dispose_has_run = TRUE;
 
-		g_object_unref( self->private->builder );
-
 		/* chain up to the parent class */
 		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
 			G_OBJECT_CLASS( st_parent_class )->dispose( dialog );
@@ -197,6 +182,10 @@ instance_finalize( GObject *dialog )
 
 	self = NA_IMPORTER_ASK( dialog );
 
+	if( self->private->toplevel ){
+		gtk_widget_destroy( GTK_WIDGET( self->private->toplevel ));
+	}
+
 	g_free( self->private );
 
 	/* chain call to parent class */
@@ -209,9 +198,53 @@ instance_finalize( GObject *dialog )
  * Returns a newly allocated NAImporterAsk object.
  */
 static NAImporterAsk *
-import_ask_new()
+import_ask_new( GtkWindow *parent )
 {
-	return( g_object_new( NA_IMPORTER_ASK_TYPE, NULL ));
+	NAImporterAsk *dialog;
+	GtkBuilder *builder;
+	GError *error;
+	GtkWindow *toplevel;
+
+	if( st_dialog ){
+		dialog = st_dialog;
+
+	} else {
+		dialog = g_object_new( NA_IMPORTER_ASK_TYPE, NULL );
+
+		builder = gtk_builder_new();
+		error = NULL;
+		gtk_builder_add_from_file( builder, st_uixml, &error );
+		if( error ){
+			gtk_message_dialog_new( parent, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", error->message );
+			g_error_free( error );
+			g_object_unref( dialog );
+			dialog = NULL;
+
+		} else {
+			toplevel = GTK_WINDOW( gtk_builder_get_object( builder, "ImporterAskDialog" ));
+			if( !toplevel ){
+				/* l10n: 'ImporterAskDialog' is the dialog name: do not translate */
+				gtk_message_dialog_new( parent, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _( "Unable to load 'ImporterAskDialog' from %s" ), st_uixml );
+				g_object_unref( dialog );
+				dialog = NULL;
+
+			} else {
+				dialog->private->toplevel = toplevel;
+
+				if( parent ){
+					gtk_window_set_transient_for( dialog->private->toplevel, parent );
+					gtk_window_set_destroy_with_parent( dialog->private->toplevel, TRUE );
+					g_signal_connect(
+							G_OBJECT( dialog->private->toplevel ),
+							"destroy", G_CALLBACK( on_destroy_toplevel ), dialog );
+					st_dialog = dialog;
+				}
+			}
+		}
+		g_object_unref( builder );
+	}
+
+	return( dialog );
 }
 
 /*
@@ -223,6 +256,16 @@ import_ask_new()
  * Ask the user for what to do when an imported item has the same ID
  * that an already existing one.
  *
+ * If a parent is specified, then we allocate a new NAImporterAsk from
+ * GtkBuilder, hiding and showing it for each invocation of the dialog
+ * by the parent, as long as the parent exists.
+ * When the parent is destroyed, this (maybe hidden) NAImporterAsk dialog
+ * is also destroyed.
+ *
+ * If there is no specified parent, then we recreate a new NAImporterAsk
+ * dialog at each invocation, destroying it after on_dialog_response()
+ * returns.
+ *
  * Returns: the definitive import mode.
  *
  * When the user selects 'Keep same choice without asking me', this choice
@@ -243,9 +286,9 @@ na_importer_ask_user( const NAObjectItem *importing, const NAObjectItem *existin
 			thisfn, ( void * ) importing, ( void * ) existing, ( void * ) parms );
 
 	mode = IMPORTER_MODE_NO_IMPORT;
-	dialog = import_ask_new();
+	dialog = import_ask_new( parms->parent );
 
-	if( dialog->private->toplevel ){
+	if( dialog ){
 
 		dialog->private->importing = ( NAObjectItem * ) importing;
 		dialog->private->existing = ( NAObjectItem * ) existing;
@@ -253,20 +296,19 @@ na_importer_ask_user( const NAObjectItem *importing, const NAObjectItem *existin
 		dialog->private->mode = na_iprefs_get_import_mode( NA_IPREFS_IMPORT_ASK_USER_LAST_MODE, NULL );
 
 		init_dialog( dialog );
-		/* toplevel is modal, not dialog
-		g_debug( "dialog is modal: %s", gtk_window_get_modal( GTK_WINDOW( dialog )) ? "True":"False" );
-		g_debug( "toplevel is modal: %s", gtk_window_get_modal( dialog->private->toplevel ) ? "True":"False" );*/
+
 		do {
 			code = gtk_dialog_run( GTK_DIALOG( dialog->private->toplevel ));
 		} while ( !on_dialog_response( dialog, code ));
 
 		mode = dialog->private->mode;
 
-		gtk_widget_hide( GTK_WIDGET( dialog->private->toplevel ));
-		gtk_widget_destroy( GTK_WIDGET( dialog->private->toplevel ));
+		if( parms->parent ){
+			gtk_widget_hide( GTK_WIDGET( dialog->private->toplevel ));
 
-	} else {
-		g_object_unref( dialog );
+		} else {
+			g_object_unref( dialog );
+		}
 	}
 
 	return( mode );
@@ -324,10 +366,6 @@ init_dialog( NAImporterAsk *editor )
 	button = na_gtk_utils_search_for_child_widget( GTK_CONTAINER( editor->private->toplevel ), "AskKeepChoiceButton" );
 	gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), editor->private->parms->keep_choice );
 
-	if( editor->private->parms->parent ){
-		gtk_window_set_transient_for( editor->private->toplevel, editor->private->parms->parent );
-	}
-
 	gtk_widget_show_all( GTK_WIDGET( editor->private->toplevel ));
 }
 
@@ -359,6 +397,32 @@ get_selected_mode( NAImporterAsk *editor )
 	na_settings_set_boolean( NA_IPREFS_IMPORT_ASK_USER_KEEP_LAST_CHOICE, keep );
 }
 
+/*
+ * destroy signal is only connected if the NAImporterAsk has been created
+ * with a parent window; it has been defined with 'destroy_with_parent'
+ * and so we have yet to unref the NAImporterAsk object itself
+ */
+static gboolean
+on_destroy_toplevel( GtkWindow *toplevel, GdkEvent *event, NAImporterAsk *dialog )
+{
+	static const gchar *thisfn = "na_importer_ask_on_destroy_toplevel";
+
+	g_debug( "%s: toplevel=%p, event=%p, dialog=%p",
+			thisfn, ( void * ) toplevel, ( void * ) event, ( void * ) dialog );
+
+	g_return_val_if_fail( NA_IS_IMPORTER_ASK( dialog ), FALSE );
+
+	if( !dialog->private->dispose_has_run ){
+		if( toplevel == dialog->private->toplevel ){
+			dialog->private->toplevel = NULL;
+		}
+		g_object_unref( dialog );
+	}
+
+	/* let the event be propagated */
+	return( FALSE );
+}
+
 static gboolean
 on_dialog_response( NAImporterAsk *editor, gint code )
 {
diff --git a/src/core/na-importer-ask.h b/src/core/na-importer-ask.h
index ba6fac9..3f0cafc 100644
--- a/src/core/na-importer-ask.h
+++ b/src/core/na-importer-ask.h
@@ -36,8 +36,8 @@
  * @include: core/na-importer-ask.h
  *
  * This class creates and manages a dialog. It is ran each time an
- * imported action as the same Id as an existing one, and the user
- * want to be ask to known what to do with it.
+ * imported action has the same Id as an existing one, and the user
+ * want to be asked to know what to do with it.
  */
 
 #include <gtk/gtk.h>
@@ -59,7 +59,7 @@ typedef struct _NAImporterAskPrivate        NAImporterAskPrivate;
 
 typedef struct {
 	/*< private >*/
-	GtkDialog             parent;
+	GObject               parent;
 	NAImporterAskPrivate *private;
 }
 	NAImporterAsk;
@@ -68,7 +68,7 @@ typedef struct _NAImporterAskClassPrivate   NAImporterAskClassPrivate;
 
 typedef struct {
 	/*< private >*/
-	GtkDialogClass             parent;
+	GObjectClass               parent;
 	NAImporterAskClassPrivate *private;
 }
 	NAImporterAskClass;
diff --git a/src/nact/nact-assistant-import.c b/src/nact/nact-assistant-import.c
index 389a0a2..c7f8c7a 100644
--- a/src/nact/nact-assistant-import.c
+++ b/src/nact/nact-assistant-import.c
@@ -662,7 +662,7 @@ assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
 	memset( &importer_parms, '\0', sizeof( NAImporterParms ));
 
 	g_object_get( G_OBJECT( wnd ), BASE_PROP_PARENT, &main_window, NULL );
-	importer_parms.parent = base_window_get_gtk_toplevel( main_window );
+	importer_parms.parent = base_window_get_gtk_toplevel( BASE_WINDOW( wnd ));
 	importer_parms.uris = gtk_file_chooser_get_uris( GTK_FILE_CHOOSER( window->private->file_chooser ));
 	importer_parms.mode = get_import_mode( window );
 	importer_parms.check_fn = ( NAIImporterCheckFn ) check_for_existence;



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