All pastes #32364 Raw Edit

Anonymous

public text v1 · immutable
#32364 ·published 2005-12-04 15:15 UTC
rendered paste body
Index: gedit-session.c
===================================================================
RCS file: /cvs/gnome/gedit/gedit/gedit-session.c,v
retrieving revision 1.9.8.10
diff -u -p -r1.9.8.10 gedit-session.c
--- gedit-session.c	4 Dec 2005 14:20:33 -0000	1.9.8.10
+++ gedit-session.c	4 Dec 2005 15:14:29 -0000
@@ -3,7 +3,7 @@
  * This file is part of gedit
  *
  * Copyright (C) 2002 Ximian, Inc.
- * Copyright (C) 2005 Paolo Maggi 
+ * Copyright (C) 2005 - Paolo Maggi 
  *
  * Author: Federico Mena-Quintero <federico@ximian.com>
  *
@@ -28,9 +28,10 @@
  * list of people on the gedit Team.  
  * See the ChangeLog files for a list of changes.
  *
- * $Id: gedit-session.c,v 1.9.8.10 2005/12/04 14:20:33 paolo Exp $
+ * $Id: gedit-session.c,v 1.9.8.8 2005/11/27 09:11:21 paolo Exp $
  */
 
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
@@ -51,6 +52,8 @@
 #include "gedit-metadata-manager.h"
 #include "gedit-window.h"
 #include "gedit-app.h"
+#include "gedit-commands.h"
+#include "dialogs/gedit-close-confirmation-dialog.h"
 
 /* The master client we use for SM */
 static GnomeClient *master_client = NULL;
@@ -58,6 +61,12 @@ static GnomeClient *master_client = NULL
 /* argv[0] from main(); used as the command to restart the program */
 static const char *program_argv0 = NULL;
 
+/* FIXME: get rid of these two globals...
+ * Can there be more than an interaction request at once?
+ */
+static gint interaction_key;
+static GSList *window_dirty_list;
+
 static gchar *
 get_session_dir ()
 {
@@ -77,7 +86,7 @@ get_session_file_path (GnomeClient *clie
 	const gchar *prefix;
 	gchar *session_dir;
 	gchar *session_file;
-	gchar *session_path;	
+	gchar *session_path;
 
 	prefix = gnome_client_get_config_prefix (client);
 	gedit_debug_message (DEBUG_SESSION, "Prefix: %s", prefix);
@@ -218,12 +227,17 @@ save_window_session (xmlTextWriterPtr  w
 }
 
 static void
-save_session (const gchar *fname)
+save_session ()
 {
 	int ret;
+	gchar *fname;
 	xmlTextWriterPtr writer;
 	const GList *windows;
 
+	/* nitpick: we are using the master client instead of the one 
+	 * passed to the interaction_func... we have just a client anyway */
+	fname = get_session_file_path (master_client);
+
 	gedit_debug_message (DEBUG_SESSION, "Session file: %s", fname);
 
 	if (!ensure_session_dir ())
@@ -274,33 +288,263 @@ out:
 
 	if (ret < 0)
 		unlink (fname);
+
+	g_free (fname);
 }
 
-static void 
-interaction_function (GnomeClient     *client,
-		      gint             key,
-		      GnomeDialogType  dialog_type,
-		      gpointer         shutdown)
+static void
+finish_interaction (gboolean cancel_shutdown)
 {
-	gchar *fname;
+	/* save session file even if shutdown was cancelled */
+	save_session ();
+
+	gnome_interaction_key_return (interaction_key,
+				      cancel_shutdown);
+
+	interaction_key = 0;
+}
+
+/* move to gedit-window.c ? We would use it also in commands-file.c...
+ * we also call this multiple time per window, so we may want to either
+ * cache the result or keep it always uptodate... list is short though,
+ * so it's not a real performance problem.
+ */
+static GList *
+window_get_unsaved_documents (GeditWindow *window)
+{
+	GList *unsaved_docs = NULL;
+	GList *docs;
+	GList *l;
+
+	docs = gedit_window_get_documents (window);
+
+	for (l = docs; l != NULL; l = l->next)
+	{
+		GeditTab *tab;
+		GeditDocument *doc;
+
+		doc = GEDIT_DOCUMENT (l->data);
+		tab = gedit_tab_get_from_document (doc);
+
+		if (!_gedit_tab_can_close (tab))
+			unsaved_docs = g_list_prepend (unsaved_docs, doc);
+	}
+
+	g_list_free (docs);
+
+	return g_list_reverse (unsaved_docs);
+}
+
+static void
+window_handled (GeditWindow *window)
+{
+	window_dirty_list = g_slist_remove (window_dirty_list, window);
+
+	/* whee... we made it! */
+	if (window_dirty_list == NULL)
+		finish_interaction (FALSE);
+}
+
+static void
+window_state_change (GeditWindow *window,
+		     GParamSpec  *pspec,
+		     gpointer     data)
+{
+	/* FIXME: should we also check the window state? */
+
+	/* FIXME: we may still have unsaved docs if we unselected
+	 * them in the confirmation dialog */
+	if (window_get_unsaved_documents (window) == NULL)
+	{
+		g_signal_handlers_disconnect_by_func (window, window_state_change, data);
+		window_handled (window);
+	}
+}
+
+static void
+close_discarded_and_save_the_rest (const GList *docs_to_save,
+				   GeditWindow  *window)
+{
+	GList *tabs;
+	GList *l;
+	GList *tabs_to_close = NULL;
+
+	tabs = gtk_container_get_children (
+			GTK_CONTAINER (_gedit_window_get_notebook (window)));
+
+	for (l = tabs; l != NULL; l = l->next)
+	{
+		GeditTab *t;
+		GeditDocument *doc;
+
+		t = GEDIT_TAB (l->data);
+
+		doc = gedit_tab_get_document (t);
+
+		if (!g_list_find (docs_to_save, doc))
+			g_list_prepend (tabs_to_close, t);
+	}
+
+	gedit_window_close_tabs (window, tabs_to_close);
+	g_list_free (tabs_to_close);
+
+	_gedit_cmd_file_save_documents_list (window, docs_to_save);
+}
+
+static void
+close_confirmation_dialog_response_handler (GeditCloseConfirmationDialog *dlg,
+					    gint                          response_id,
+					    GeditWindow                  *window)
+{
+	const GList *unsaved_documents;
+	const GList *selected_documents;
+	GSList *l;
+
+	gedit_debug (DEBUG_COMMANDS);
+
+	unsaved_documents = gedit_close_confirmation_dialog_get_unsaved_documents (dlg);
+
+	switch (response_id)
+	{
+		case GTK_RESPONSE_YES:
+			/* save selected docs */
+
+			g_signal_connect (window,
+					  "notify::state",
+					  G_CALLBACK (window_state_change),
+					  NULL);
+
+			selected_documents = gedit_close_confirmation_dialog_get_selected_documents (dlg);
+
+			close_discarded_and_save_the_rest (selected_documents, window);
+
+			// FIXME: also need to lock the window to prevent further changes..
+
+			break;
+
+		case GTK_RESPONSE_NO:
+			/* dont save */
+			window_handled (window);
+			break;
+
+		default:
+			/* disconnect window_state_changed where needed */
+			for (l = window_dirty_list; l != NULL; l = l->next)
+				g_signal_handlers_disconnect_by_func (window,
+						window_state_change, NULL);
+			g_slist_free (window_dirty_list);
+			window_dirty_list = NULL;
+
+			/* cancel shutdown */
+			finish_interaction (TRUE);
+
+			break;
+	}
+
+	gtk_widget_destroy (GTK_WIDGET (dlg));
+}
+
+static void
+session_close_all (GeditWindow *window)
+{
+	GSList *unsaved_docs;
+	GtkWidget *dlg;
 
 	gedit_debug (DEBUG_SESSION);
-#if 0
-	/* Save all unsaved files */
-	if (GPOINTER_TO_INT (shutdown))		
-		gedit_file_save_all ();
-#endif
 
-	/* Save session data */
-	fname = get_session_file_path (client);
+	unsaved_docs = window_get_unsaved_documents (window);
 
-	save_session (fname);
+	g_return_if_fail (unsaved_docs != NULL);
 
-	g_free (fname);
+	if (unsaved_docs->next == NULL)
+	{
+		/* There is only one unsaved document */
+		GeditTab *tab;
+		GeditDocument *doc;
 
-	gnome_interaction_key_return (key, FALSE);
+		doc = GEDIT_DOCUMENT (unsaved_docs->data);
 
-	gedit_debug_message (DEBUG_SESSION, "END");
+		tab = gedit_tab_get_from_document (doc);
+		g_return_if_fail (tab != NULL);
+
+		gedit_window_set_active_tab (window, tab);
+
+		dlg = gedit_close_confirmation_dialog_new_single (
+						GTK_WINDOW (window),
+						doc);
+	}
+	else
+	{
+		dlg = gedit_close_confirmation_dialog_new (GTK_WINDOW (window),
+							   unsaved_docs);
+	}
+
+	g_slist_free (unsaved_docs);
+
+	g_signal_connect (dlg,
+			  "response",
+			  G_CALLBACK (close_confirmation_dialog_response_handler),
+			  window);
+
+	gtk_widget_show (dlg);
+}
+
+static void
+save_all_docs_and_save_session ()
+{
+	GeditApp *app;
+	const GList *l;
+
+	app = gedit_app_get_default ();
+
+	g_assert (window_dirty_list == NULL);
+
+	for (l = gedit_app_get_windows (app); l != NULL; l = l->next)
+	{
+		if (window_get_unsaved_documents (GEDIT_WINDOW (l->data)) != NULL)
+		{
+			window_dirty_list = g_slist_prepend (window_dirty_list, l->data);
+		}
+	}
+
+	/* no modified docs, go on and save session */
+	if (window_dirty_list == NULL)
+	{
+		finish_interaction (FALSE);
+
+		return;
+	}
+
+	for (l = window_dirty_list; l != NULL; l = l->next)
+	{
+		// maybe run the dialog in sequence when one is closed instead?
+
+		session_close_all (GEDIT_WINDOW (l->data));
+	}
+}
+
+static void
+interaction_function (GnomeClient     *client,
+		      gint             key,
+		      GnomeDialogType  dialog_type,
+		      gpointer         shutdown)
+{
+	gedit_debug (DEBUG_SESSION);
+
+	g_assert (interaction_key == 0);
+	interaction_key = key;
+
+	/* If we are shutting down, give the user the chance to save
+	 * first, otherwise just ignore untitled documents documents.
+	 */
+	if (GPOINTER_TO_INT (shutdown))
+	{
+		save_all_docs_and_save_session ();
+	}
+	else
+	{
+		finish_interaction (FALSE);
+	}
 }
 
 /* save_yourself handler for the master client */
@@ -321,20 +565,20 @@ client_save_yourself_cb (GnomeClient    
 					  GNOME_DIALOG_NORMAL, 
 					  interaction_function,
 					  GINT_TO_POINTER (shutdown));
-	
+
 	/* Tell the session manager how to discard this save */
 	argv[2] = get_session_file_path (client);
 	gnome_client_set_discard_command (client, 3, argv);
 
 	g_free (argv[2]);
-	
+
 	/* Tell the session manager how to clone or restart this instance */
 
 	argv[0] = (char *) program_argv0;
-	argv[1] = NULL; /* "--debug-session"; */
+	argv[1] = NULL;
 
-	gnome_client_set_clone_command (client, 1 /*2*/, argv);
-	gnome_client_set_restart_command (client, 1 /*2*/, argv);
+	gnome_client_set_clone_command (client, 1, argv);
+	gnome_client_set_restart_command (client, 1, argv);
 
 	gedit_debug_message (DEBUG_SESSION, "END");