rendered paste bodyIndex: 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");