aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--e-util/ChangeLog7
-rw-r--r--e-util/e-util.c49
-rw-r--r--e-util/e-util.h4
-rw-r--r--shell/ChangeLog9
-rw-r--r--shell/apps_evolution_shell.schemas.in27
-rw-r--r--shell/e-shell.c3
-rw-r--r--shell/main.c100
7 files changed, 197 insertions, 2 deletions
diff --git a/e-util/ChangeLog b/e-util/ChangeLog
index 06a841a3d7..1cd661efc8 100644
--- a/e-util/ChangeLog
+++ b/e-util/ChangeLog
@@ -1,3 +1,10 @@
+2007-12-05 Srinivasa Ragavan <sragavan@novell.com>
+
+ * e-util.c: (get_lock_filename), (e_file_lock_create),
+ (e_file_lock_destroy), (e_file_lock_exists): Add utility functions for
+ startup-running lock create, check and delete.
+ * e-util.h:
+
2007-12-04 Milan Crha <mcrha@redhat.com>
** Part of fix for bug #500210
diff --git a/e-util/e-util.c b/e-util/e-util.c
index 625c617a8b..b1634bcfff 100644
--- a/e-util/e-util.c
+++ b/e-util/e-util.c
@@ -1017,3 +1017,52 @@ e_file_get_save_path (void)
return (uri);
}
+/* Evolution Locks for crash recovery */
+
+#define LOCK_FILE ".running"
+
+static const gchar *
+get_lock_filename (void)
+{
+ static gchar *filename = NULL;
+
+ if (G_UNLIKELY (filename == NULL))
+ filename = g_build_filename (g_get_home_dir (), ".evolution", LOCK_FILE, NULL);
+
+ return filename;
+}
+
+gboolean
+e_file_lock_create ()
+{
+ const char *fname = get_lock_filename ();
+ gboolean status = FALSE;
+
+ int fd = g_creat (fname, S_IRUSR|S_IWUSR);
+ if (fd == -1){
+ g_warning ("Lock file '%s' creation failed, error %d\n", fname, errno);
+ } else {
+ status = TRUE;
+ close (fd);
+ }
+
+ return status;
+}
+
+void
+e_file_lock_destroy ()
+{
+ const char *fname = get_lock_filename ();
+
+ if (g_unlink (fname) == -1){
+ g_warning ("Lock destroy: failed to unlink file '%s'!",fname);
+ }
+}
+
+gboolean
+e_file_lock_exists ()
+{
+ const char *fname = get_lock_filename ();
+
+ return g_file_test (fname, G_FILE_TEST_EXISTS);
+}
diff --git a/e-util/e-util.h b/e-util/e-util.h
index e3774c5852..b37f2abdb5 100644
--- a/e-util/e-util.h
+++ b/e-util/e-util.h
@@ -111,6 +111,10 @@ void e_file_update_save_path (gchar *uri,
gboolean free);
gchar * e_file_get_save_path (void);
+gboolean e_file_lock_create ();
+void e_file_lock_destroy ();
+gboolean e_file_lock_exists ();
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/shell/ChangeLog b/shell/ChangeLog
index 2e97d88040..3e5f090d0c 100644
--- a/shell/ChangeLog
+++ b/shell/ChangeLog
@@ -1,3 +1,12 @@
+2007-12-05 Srinivasa Ragavan <sragavan@novell.com>
+
+ ** Add basic support for crash recovery
+
+ * apps_evolution_shell.schemas.in: Keys to recover and recovery dialog.
+ * e-shell.c: (e_shell_quit): Delete the lock while quitting.
+ * main.c: (show_recovery_warning), (idle_cb): Create lock and also show
+ the warning dialog.
+
2007-11-30 Matthew Barnes <mbarnes@redhat.com>
** Fixes bug #499920
diff --git a/shell/apps_evolution_shell.schemas.in b/shell/apps_evolution_shell.schemas.in
index f7d1e71f98..5375f09845 100644
--- a/shell/apps_evolution_shell.schemas.in
+++ b/shell/apps_evolution_shell.schemas.in
@@ -41,7 +41,32 @@
</locale>
</schema>
- <!-- Offline Mode -->
+ <!-- Recovery -->
+ <schema>
+ <key>/schemas/apps/evolution/shell/skip_recovery_dialog</key>
+ <applyto>/apps/evolution/shell/skip_recovery_dialog</applyto>
+ <owner>evolution</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Skip recovery warning dialog</short>
+ <long>Whether the warning dialog in recovery of Evolution is skipped.</long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/evolution/shell/recovery</key>
+ <applyto>/apps/evolution/shell/recovery</applyto>
+ <owner>evolution</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Whether crash recovery should be done or not</short>
+ <long>Decides whether the crash recovery should be run or not</long>
+ </locale>
+ </schema>
+
+ <!-- Offline Mode -->
<schema>
<key>/schemas/apps/evolution/shell/start_offline</key>
diff --git a/shell/e-shell.c b/shell/e-shell.c
index 4e651453a4..51ab69c8c1 100644
--- a/shell/e-shell.c
+++ b/shell/e-shell.c
@@ -1377,6 +1377,9 @@ e_shell_quit(EShell *shell)
e_shell_window_save_defaults (p->data);
}
can_quit = !es_run_quit(shell);
+
+ /* Mark a safe quit by destroying the lock. */
+ e_file_lock_destroy ();
}
return can_quit;
diff --git a/shell/main.c b/shell/main.c
index 4d9e785cc3..bcd7fbada4 100644
--- a/shell/main.c
+++ b/shell/main.c
@@ -31,6 +31,7 @@
#include <e-util/e-icon-factory.h>
#include "e-shell-constants.h"
#include "e-util/e-profile-event.h"
+#include "e-util/e-util.h"
#include "e-shell.h"
#include "es-menu.h"
@@ -91,6 +92,11 @@
#define SKIP_WARNING_DIALOG_KEY \
"/apps/evolution/shell/skip_warning_dialog"
+#define SKIP_RECOVERY_DIALOG_KEY \
+ "/apps/evolution/shell/skip_recovery_dialog"
+#define RECOVERY_KEY \
+ "/apps/evolution/shell/recovery"
+
static EShell *shell = NULL;
@@ -284,6 +290,70 @@ destroy_config (GConfClient *client)
#endif /* DEVELOPMENT */
+static int
+show_recovery_warning(void)
+{
+ GtkWidget *vbox;
+ GtkWidget *label;
+ GtkWidget *warning_dialog;
+ GtkWidget *checkbox;
+ GtkWidget *alignment;
+ gboolean skip;
+ char *text;
+ int flags = 0, response;
+
+ warning_dialog = gtk_dialog_new ();
+ gtk_window_set_title (GTK_WINDOW (warning_dialog), _("Evolution Crash Recovery"));
+ gtk_window_set_modal (GTK_WINDOW (warning_dialog), TRUE);
+ gtk_dialog_add_button (GTK_DIALOG (warning_dialog), _("Ig_nore"), GTK_RESPONSE_CANCEL);
+ gtk_dialog_add_button (GTK_DIALOG (warning_dialog), _("_Recover"), GTK_RESPONSE_OK);
+
+ gtk_dialog_set_has_separator (GTK_DIALOG (warning_dialog), FALSE);
+
+ gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (warning_dialog)->vbox), 0);
+ gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (warning_dialog)->action_area), 12);
+
+ vbox = gtk_vbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (warning_dialog)->vbox), vbox,
+ TRUE, TRUE, 0);
+
+ text = g_strdup(
+ /* xgettext:no-c-format */
+ _("Evolution appears to have exited unexpectedly the last time it was\n"
+ "run. As a precautionary measure, all preview panes will be hidden.\n"
+ "You can restore the preview panes from the View menu.\n"));
+ label = gtk_label_new (text);
+ g_free(text);
+
+ gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
+
+ gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
+
+ checkbox = gtk_check_button_new_with_mnemonic (_("_Do not show this again"));
+
+ alignment = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
+
+ gtk_container_add (GTK_CONTAINER (alignment), checkbox);
+ gtk_box_pack_start (GTK_BOX (vbox), alignment, TRUE, TRUE, 0);
+
+ gtk_widget_show_all (warning_dialog);
+
+ response = gtk_dialog_run (GTK_DIALOG (warning_dialog));
+
+ if (response != GTK_RESPONSE_CANCEL)
+ flags = flags|(1<<1);
+
+ skip = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox));
+ if (skip)
+ flags = flags|(1<<2);
+
+ gtk_widget_destroy (warning_dialog);
+
+ return flags;
+}
+
static void
open_uris (GNOME_Evolution_Shell corba_shell, gchar **uris)
{
@@ -363,8 +433,36 @@ idle_cb (gchar **uris)
if (shell != NULL) {
if (uris != NULL)
open_uris (corba_shell, uris);
- else
+ else {
+ GConfClient *client = gconf_client_get_default ();
+
+ if (gconf_client_get_bool (client, RECOVERY_KEY, NULL) && e_file_lock_exists ()) {
+ /* It should have crashed last time or a force-shutdown */
+ gboolean skip = gconf_client_get_bool (client, SKIP_RECOVERY_DIALOG_KEY, NULL);
+ gboolean recover = TRUE;
+ if (!skip){
+ int flags = show_recovery_warning ();
+
+ gconf_client_set_bool (client, SKIP_RECOVERY_DIALOG_KEY, (flags & (1<<2)) ? TRUE : FALSE, NULL);
+ recover = (flags & (1<<1)) ? TRUE: FALSE;
+ }
+
+ if (recover) {
+ /* Disable the previews */
+ gconf_client_set_bool (client, "/apps/evolution/mail/display/show_preview", FALSE, NULL);
+ gconf_client_set_bool (client, "/apps/evolution/mail/display/safe_list", TRUE, NULL);
+ gconf_client_set_bool (client, "/apps/evolution/addressbook/display/show_preview", FALSE, NULL);
+ gconf_client_set_bool (client, "/apps/evolution/calendar/display/show_task_preview", FALSE, NULL);
+ }
+ /* Let us not delete and recreate a lock, instead reuse it. We don't use timestamps anyways */
+ } else {
+ /* What great can we do, if lock creation fails ?*/
+ e_file_lock_create ();
+ }
+ g_object_unref (client);
+
e_shell_create_window (shell, default_component_id, NULL);
+ }
} else {
CORBA_Environment ev;