aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2010-06-13 02:28:07 +0800
committerMatthew Barnes <mbarnes@redhat.com>2010-06-13 02:28:07 +0800
commit51d0fc6863be998af5056605281cc0ebc2abfe00 (patch)
treeca9410d6729e2b3d989f0fbbc069c2563a634739
parent077116eac4cbfd5f06c44c8f5634469eab3130e6 (diff)
downloadgsoc2013-evolution-51d0fc6863be998af5056605281cc0ebc2abfe00.tar.gz
gsoc2013-evolution-51d0fc6863be998af5056605281cc0ebc2abfe00.tar.zst
gsoc2013-evolution-51d0fc6863be998af5056605281cc0ebc2abfe00.zip
Bug 603468 - Improve handling of --quit option
-rw-r--r--addressbook/gui/contact-editor/eab-editor.c11
-rw-r--r--doc/reference/shell/tmpl/e-shell.sgml2
-rw-r--r--glib-gen.mak42
-rw-r--r--mail/e-mail-backend.c5
-rw-r--r--shell/Makefile.am13
-rw-r--r--shell/e-shell-window-actions.c2
-rw-r--r--shell/e-shell.c116
-rw-r--r--shell/e-shell.h33
-rw-r--r--shell/main.c16
9 files changed, 170 insertions, 70 deletions
diff --git a/addressbook/gui/contact-editor/eab-editor.c b/addressbook/gui/contact-editor/eab-editor.c
index 17ac1c391c..f53ecc30cd 100644
--- a/addressbook/gui/contact-editor/eab-editor.c
+++ b/addressbook/gui/contact-editor/eab-editor.c
@@ -57,11 +57,16 @@ static gpointer parent_class;
static guint signals[LAST_SIGNAL];
static void
-eab_editor_quit_requested_cb (EABEditor *editor,
- EShell *shell)
+eab_editor_quit_requested_cb (EShell *shell,
+ EShellQuitReason reason,
+ EABEditor *editor)
{
GtkWindow *window;
+ /* Quit immediately if another Evolution process asked us to. */
+ if (reason == E_SHELL_QUIT_REMOTE_REQUEST)
+ return;
+
window = eab_editor_get_window (editor);
eab_editor_raise (editor);
@@ -78,7 +83,7 @@ eab_editor_set_shell (EABEditor *editor,
editor->priv->shell = g_object_ref (shell);
- g_signal_connect_swapped (
+ g_signal_connect (
shell, "quit-requested",
G_CALLBACK (eab_editor_quit_requested_cb), editor);
}
diff --git a/doc/reference/shell/tmpl/e-shell.sgml b/doc/reference/shell/tmpl/e-shell.sgml
index 2287392fee..5505f3e03f 100644
--- a/doc/reference/shell/tmpl/e-shell.sgml
+++ b/doc/reference/shell/tmpl/e-shell.sgml
@@ -73,6 +73,7 @@ EShell
</para>
@eshell: the object which received the signal.
+@Param2:
<!-- ##### SIGNAL EShell::send-receive ##### -->
<para>
@@ -339,6 +340,7 @@ EShell
</para>
@shell:
+@reason:
@Returns:
diff --git a/glib-gen.mak b/glib-gen.mak
new file mode 100644
index 0000000000..7aae596e15
--- /dev/null
+++ b/glib-gen.mak
@@ -0,0 +1,42 @@
+# these are the variables your Makefile.am should set
+# the example is based on the colorbalance interface
+
+#glib_enum_headers=$(colorbalance_headers)
+#glib_enum_define=GST_COLOR_BALANCE
+#glib_enum_prefix=gst_color_balance
+
+# these are all the rules generating the relevant files
+%-marshal.h: %-marshal.list
+ glib-genmarshal --header --prefix=$(glib_enum_prefix)_marshal $^ > $*-marshal.h.tmp
+ mv $*-marshal.h.tmp $*-marshal.h
+
+%-marshal.c: %-marshal.list
+ echo "#include \"$*-marshal.h\"" >> $*-marshal.c.tmp
+ glib-genmarshal --body --prefix=$(glib_enum_prefix)_marshal $^ >> $*-marshal.c.tmp
+ mv $*-marshal.c.tmp $*-marshal.c
+
+%-enumtypes.h: $(glib_enum_headers)
+ glib-mkenums \
+ --fhead "#ifndef __$(glib_enum_define)_ENUM_TYPES_H__\n#define __$(glib_enum_define)_ENUM_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \
+ --fprod "/* enumerations from \"@filename@\" */\n" \
+ --vhead "GType @enum_name@_get_type (void);\n#define E_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \
+ --ftail "G_END_DECLS\n\n#endif /* __$(glib_enum_define)_ENUM_TYPES_H__ */" \
+ $^ > $@
+
+%-enumtypes.c: $(glib_enum_headers)
+ @if test "x$(glib_enum_headers)" == "x"; then echo "ERROR: glib_enum_headers is empty, please fix Makefile"; exit 1; fi
+ glib-mkenums \
+ --fhead "#include <$*.h>\n#include \"$*-enumtypes.h\"" \
+ --fprod "\n/* enumerations from \"@filename@\" */" \
+ --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \
+ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@VALUENAME@\" }," \
+ --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \
+ $^ > $@
+
+# a hack rule to make sure .Plo files exist because they get include'd
+# from Makefile's
+.deps/%-marshal.Plo:
+ touch $@
+
+.deps/%-enumtypes.Plo:
+ touch $@
diff --git a/mail/e-mail-backend.c b/mail/e-mail-backend.c
index 7f62c466ad..a0453a963d 100644
--- a/mail/e-mail-backend.c
+++ b/mail/e-mail-backend.c
@@ -260,6 +260,7 @@ mail_backend_prepare_for_quit_cb (EShell *shell,
static void
mail_backend_quit_requested_cb (EShell *shell,
+ EShellQuitReason reason,
EShellBackend *shell_backend)
{
CamelFolder *folder;
@@ -272,6 +273,10 @@ mail_backend_quit_requested_cb (EShell *shell,
if (!e_shell_get_online (shell))
return;
+ /* Or if another Evolution process asked us to. */
+ if (reason == E_SHELL_QUIT_REMOTE_REQUEST)
+ return;
+
/* In express mode, don't raise mail request in non mail window. */
if (e_shell_get_express_mode(shell) &&
strcmp(e_shell_window_get_active_view((EShellWindow *)window), "mail") != 0)
diff --git a/shell/Makefile.am b/shell/Makefile.am
index 567059e0f1..2f044e420e 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -6,15 +6,23 @@ endif
bin_PROGRAMS = evolution
# Shell library
-privsolib_LTLIBRARIES = libeshell.la
+privsolib_LTLIBRARIES = libeshell.la
eshellincludedir = $(privincludedir)/shell
+include $(top_srcdir)/glib-gen.mak
+glib_enum_headers=e-shell.h
+glib_enum_define=E_SHELL
+glib_enum_prefix=e_shell
+
+ENUM_GENERATED = e-shell-enumtypes.h e-shell-enumtypes.c
+
eshellinclude_HEADERS = \
e-shell.h \
e-shell-backend.h \
e-shell-common.h \
e-shell-content.h \
+ e-shell-enumtypes.h \
e-shell-searchbar.h \
e-shell-settings.h \
e-shell-sidebar.h \
@@ -58,6 +66,7 @@ libeshell_la_SOURCES = \
e-shell.c \
e-shell-backend.c \
e-shell-content.c \
+ e-shell-enumtypes.c \
e-shell-meego.c \
e-shell-meego.h \
e-shell-searchbar.c \
@@ -217,7 +226,7 @@ evolution.pure: evolution
endif
-BUILT_SOURCES = $(error_DATA)
+BUILT_SOURCES = $(error_DATA) $(ENUM_GENERATED)
CLEANFILES = $(BUILT_SOURCES)
DISTCLEANFILES = $(schema_DATA)
diff --git a/shell/e-shell-window-actions.c b/shell/e-shell-window-actions.c
index 606f125f33..480b99da2b 100644
--- a/shell/e-shell-window-actions.c
+++ b/shell/e-shell-window-actions.c
@@ -1012,7 +1012,7 @@ action_quit_cb (GtkAction *action,
EShell *shell;
shell = e_shell_window_get_shell (shell_window);
- e_shell_quit (shell);
+ e_shell_quit (shell, E_SHELL_QUIT_ACTION);
}
/**
diff --git a/shell/e-shell.c b/shell/e-shell.c
index f82931cec0..21bf16e0c8 100644
--- a/shell/e-shell.c
+++ b/shell/e-shell.c
@@ -38,6 +38,7 @@
#include "widgets/misc/e-preferences-window.h"
#include "e-shell-backend.h"
+#include "e-shell-enumtypes.h"
#include "e-shell-window.h"
#include "e-shell-utils.h"
@@ -65,6 +66,7 @@ struct _EShellPrivate {
gchar *startup_view;
guint auto_reconnect : 1;
+ guint modules_loaded : 1;
guint network_available : 1;
guint online : 1;
guint quit_cancelled : 1;
@@ -145,7 +147,7 @@ shell_window_delete_event_cb (EShell *shell,
return FALSE;
/* Otherwise we initiate application quit. */
- e_shell_quit (shell);
+ e_shell_quit (shell, E_SHELL_QUIT_LAST_WINDOW);
return TRUE;
}
@@ -311,15 +313,6 @@ shell_ready_for_quit (EShell *shell,
/* Finalize the activity. */
g_object_ref (activity);
- /* This handles a strange corner case where --quit is given on
- * the command-line but no other Evolution process is running.
- * We bring all the shell backends up and then immediately run
- * the shutdown procedure, which gets us here. But because no
- * windows have been shown yet, the usual "main loop ends when
- * the last window is destroyed" trick won't work. */
- if (e_shell_get_watched_windows (shell) == NULL)
- gtk_main_quit ();
-
/* Destroy all watched windows. Note, we iterate over a -copy-
* of the watched windows list because the act of destroying a
* watched window will modify the watched windows list, which
@@ -362,7 +355,8 @@ shell_prepare_for_quit (EShell *shell)
}
static gboolean
-shell_request_quit (EShell *shell)
+shell_request_quit (EShell *shell,
+ EShellQuitReason reason)
{
/* Are preparations already in progress? */
if (shell->priv->preparing_for_quit != NULL)
@@ -370,28 +364,11 @@ shell_request_quit (EShell *shell)
/* Give the application a chance to cancel quit. */
shell->priv->quit_cancelled = FALSE;
- g_signal_emit (shell, signals[QUIT_REQUESTED], 0);
+ g_signal_emit (shell, signals[QUIT_REQUESTED], 0, reason);
return !shell->priv->quit_cancelled;
}
-static void
-shell_load_modules (EShell *shell)
-{
- const gchar *module_directory;
- GList *modules = NULL;
-
- /* Load all shared library modules. */
-
- module_directory = e_shell_get_module_directory (shell);
- g_return_if_fail (module_directory != NULL);
-
- modules = e_module_load_all_in_directory (module_directory);
-
- g_list_foreach (modules, (GFunc) g_type_module_unuse, NULL);
- g_list_free (modules);
-}
-
/* Helper for shell_add_backend() */
static void
shell_split_and_insert_items (GHashTable *hash_table,
@@ -443,12 +420,13 @@ static void
shell_sm_quit_requested_cb (EShell *shell,
EggSMClient *sm_client)
{
+ EShellQuitReason reason = E_SHELL_QUIT_SESSION_REQUEST;
gboolean will_quit;
/* If preparations are already in progress then we have already
* committed ourselves to quitting, and can answer 'yes'. */
if (shell->priv->preparing_for_quit == NULL)
- will_quit = shell_request_quit (shell);
+ will_quit = shell_request_quit (shell, reason);
else
will_quit = TRUE;
@@ -675,34 +653,14 @@ shell_finalize (GObject *object)
static void
shell_constructed (GObject *object)
{
- EShellPrivate *priv;
- GList *list;
-
- priv = E_SHELL_GET_PRIVATE (object);
-
/* The first EShell instance is the default. */
if (default_shell == NULL) {
default_shell = object;
g_object_add_weak_pointer (object, &default_shell);
}
- /* UniqueApp will have by this point determined whether we're
- * the only Evolution process running. If so, proceed normally.
- * Otherwise we just issue commands to the other process. */
- if (unique_app_is_running (UNIQUE_APP (object)))
- return;
-
- e_file_lock_create ();
-
- shell_load_modules (E_SHELL (object));
-
- /* Process shell backends. */
- list = g_list_sort (
- e_extensible_list_extensions (
- E_EXTENSIBLE (object), E_TYPE_SHELL_BACKEND),
- (GCompareFunc) e_shell_backend_compare);
- g_list_foreach (list, (GFunc) shell_process_backend, object);
- priv->loaded_backends = list;
+ if (!unique_app_is_running (UNIQUE_APP (object)))
+ e_file_lock_create ();
}
static UniqueResponse
@@ -753,7 +711,7 @@ shell_message_handle_close (EShell *shell,
{
UniqueResponse response;
- if (e_shell_quit (shell))
+ if (e_shell_quit (shell, E_SHELL_QUIT_REMOTE_REQUEST))
response = UNIQUE_RESPONSE_OK;
else
response = UNIQUE_RESPONSE_CANCEL;
@@ -1070,6 +1028,7 @@ e_shell_class_init (EShellClass *class)
/**
* EShell::quit-requested
* @shell: the #EShell which emitted the signal
+ * @reason: the reason for quitting
*
* Emitted when the user elects to quit the application, before
* #EShell::prepare-for-quit.
@@ -1086,8 +1045,9 @@ e_shell_class_init (EShellClass *class)
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (EShellClass, quit_requested),
NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ g_cclosure_marshal_VOID__ENUM,
+ G_TYPE_NONE, 1,
+ E_TYPE_SHELL_QUIT_REASON);
/**
* EShell::send-receive
@@ -1245,6 +1205,46 @@ e_shell_get_default (void)
}
/**
+ * e_shell_load_modules:
+ * @shell: an #EShell
+ *
+ * Loads all installed modules and performs some internal bookkeeping.
+ * This function should be called after creating the #EShell instance
+ * but before initiating migration or starting the main loop.
+ **/
+void
+e_shell_load_modules (EShell *shell)
+{
+ const gchar *module_directory;
+ GList *list;
+
+ g_return_if_fail (E_IS_SHELL (shell));
+
+ if (shell->priv->modules_loaded)
+ return;
+
+ /* Load all shared library modules. */
+
+ module_directory = e_shell_get_module_directory (shell);
+ g_return_if_fail (module_directory != NULL);
+
+ list = e_module_load_all_in_directory (module_directory);
+ g_list_foreach (list, (GFunc) g_type_module_unuse, NULL);
+ g_list_free (list);
+
+ /* Process shell backends. */
+
+ list = g_list_sort (
+ e_extensible_list_extensions (
+ E_EXTENSIBLE (shell), E_TYPE_SHELL_BACKEND),
+ (GCompareFunc) e_shell_backend_compare);
+ g_list_foreach (list, (GFunc) shell_process_backend, shell);
+ shell->priv->loaded_backends = list;
+
+ shell->priv->modules_loaded = TRUE;
+}
+
+/**
* e_shell_get_shell_backends:
* @shell: an #EShell
*
@@ -1846,6 +1846,7 @@ e_shell_event (EShell *shell,
/**
* e_shell_quit:
* @shell: an #EShell
+ * @reason: the reason for quitting
*
* Requests an application shutdown. This happens in two phases: the
* first is synchronous, the second is asynchronous.
@@ -1866,7 +1867,8 @@ e_shell_event (EShell *shell,
* Returns: %TRUE if shutdown is underway, %FALSE if it was cancelled
**/
gboolean
-e_shell_quit (EShell *shell)
+e_shell_quit (EShell *shell,
+ EShellQuitReason reason)
{
UniqueApp *app;
UniqueResponse response;
@@ -1878,7 +1880,7 @@ e_shell_quit (EShell *shell)
if (unique_app_is_running (app))
goto unique;
- if (!shell_request_quit (shell))
+ if (!shell_request_quit (shell, reason))
return FALSE;
shell_prepare_for_quit (shell);
diff --git a/shell/e-shell.h b/shell/e-shell.h
index f1d76b9ea6..6962ff6d0f 100644
--- a/shell/e-shell.h
+++ b/shell/e-shell.h
@@ -57,6 +57,32 @@ typedef struct _EShellClass EShellClass;
typedef struct _EShellPrivate EShellPrivate;
/**
+ * EShellQuitReason:
+ *
+ * @E_SHELL_QUIT_ACTION:
+ * @E_SHELL_WINDOW_ACTION_QUIT was activated.
+ * @E_SHELL_QUIT_LAST_WINDOW:
+ * The last watched window has been destroyed.
+ * @E_SHELL_QUIT_OPTION:
+ * The program was invoked with --quit. Extensions will never
+ * see this value because they are not loaded when --quit is given.
+ * @E_SHELL_QUIT_REMOTE_REQUEST:
+ * Another Evolution process requested we quit.
+ * @E_SHELL_QUIT_SESSION_REQUEST:
+ * The desktop session requested we quit.
+ *
+ * These values are passed in the #EShell::quit-requested signal to
+ * indicate why the shell is requesting to shut down.
+ **/
+typedef enum {
+ E_SHELL_QUIT_ACTION,
+ E_SHELL_QUIT_LAST_WINDOW,
+ E_SHELL_QUIT_OPTION,
+ E_SHELL_QUIT_REMOTE_REQUEST,
+ E_SHELL_QUIT_SESSION_REQUEST
+} EShellQuitReason;
+
+/**
* EShell:
*
* Contains only private data that should be read and manipulated using the
@@ -78,7 +104,8 @@ struct _EShellClass {
EActivity *activity);
void (*prepare_for_quit) (EShell *shell,
EActivity *activity);
- void (*quit_requested) (EShell *shell);
+ void (*quit_requested) (EShell *shell,
+ EShellQuitReason reason);
void (*send_receive) (EShell *shell,
GtkWindow *parent);
void (*window_created) (EShell *shell,
@@ -88,6 +115,7 @@ struct _EShellClass {
GType e_shell_get_type (void);
EShell * e_shell_get_default (void);
+void e_shell_load_modules (EShell *shell);
GList * e_shell_get_shell_backends (EShell *shell);
const gchar * e_shell_get_canonical_name (EShell *shell,
const gchar *name);
@@ -122,7 +150,8 @@ GtkWidget * e_shell_get_preferences_window (EShell *shell);
void e_shell_event (EShell *shell,
const gchar *event_name,
gpointer event_data);
-gboolean e_shell_quit (EShell *shell);
+gboolean e_shell_quit (EShell *shell,
+ EShellQuitReason reason);
void e_shell_cancel_quit (EShell *shell);
void e_shell_adapt_window_size (EShell *shell,
diff --git a/shell/main.c b/shell/main.c
index cac04dd0bd..7e58d97aa6 100644
--- a/shell/main.c
+++ b/shell/main.c
@@ -232,9 +232,7 @@ idle_cb (gchar **uris)
/* These calls do the right thing when another Evolution
* process is running. */
- if (quit)
- e_shell_quit (shell);
- else if (uris != NULL && *uris != NULL) {
+ if (uris != NULL && *uris != NULL) {
if (e_shell_handle_uris (shell, uris, import_uris) == 0)
gtk_main_quit ();
} else {
@@ -578,6 +576,13 @@ main (gint argc, gchar **argv)
shell = create_default_shell ();
+ if (quit) {
+ e_shell_quit (shell, E_SHELL_QUIT_OPTION);
+ goto exit;
+ }
+
+ e_shell_load_modules (shell);
+
if (!disable_eplugin) {
/* Register built-in plugin hook types. */
es_event_hook_get_type ();
@@ -593,9 +598,9 @@ main (gint argc, gchar **argv)
}
if (requested_view)
- e_shell_set_startup_view(shell, requested_view);
+ e_shell_set_startup_view (shell, requested_view);
else if (express_mode)
- e_shell_set_startup_view(shell, "mail");
+ e_shell_set_startup_view (shell, "mail");
/* Attempt migration -after- loading all modules and plugins,
* as both shell backends and certain plugins hook into this. */
@@ -608,6 +613,7 @@ main (gint argc, gchar **argv)
gtk_main ();
+exit:
/* Drop what should be the last reference to the shell.
* That will cause e_shell_get_default() to henceforth
* return NULL. Use that to check for reference leaks. */