From 7d2c28c02c6ecddcf492f385cacbd3d24ac215db Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Mon, 15 Sep 2008 14:55:41 +0000 Subject: Begin documenting the new shell design. svn path=/branches/kill-bonobo/; revision=36337 --- shell/Makefile.am | 2 - shell/e-shell-module.c | 91 +++++++++++++++++- shell/e-shell-module.h | 41 ++++++-- shell/e-shell-registry.c | 158 ------------------------------- shell/e-shell-registry.h | 38 -------- shell/e-shell-switcher.c | 66 ++++++++++++- shell/e-shell-window-private.h | 1 - shell/e-shell-window.c | 206 +++++++++++++++++++++++++++++++++++++++-- shell/e-shell.c | 192 ++++++++++++++++++++++++++++++++++++-- shell/e-shell.h | 8 ++ shell/main.c | 4 +- 11 files changed, 580 insertions(+), 227 deletions(-) delete mode 100644 shell/e-shell-registry.c delete mode 100644 shell/e-shell-registry.h (limited to 'shell') diff --git a/shell/Makefile.am b/shell/Makefile.am index 12900aac3f..f15661007e 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -103,8 +103,6 @@ evolution_SOURCES = \ e-shell-constants.h \ e-shell-importer.c \ e-shell-importer.h \ - e-shell-registry.c \ - e-shell-registry.h \ e-shell-window-private.c \ e-shell-window-private.h \ es-event.c \ diff --git a/shell/e-shell-module.c b/shell/e-shell-module.c index 6d6849ee29..373a78564d 100644 --- a/shell/e-shell-module.c +++ b/shell/e-shell-module.c @@ -25,6 +25,8 @@ #include #include +#include + /* This is the symbol we look for when loading a module. */ #define INIT_SYMBOL "e_shell_module_init" @@ -34,8 +36,8 @@ struct _EShellModulePrivate { - /* Set during module initialization. This must come - * first in the struct so the registry can read it. */ + /* Set during module initialization. This must + * come first in the struct so EShell can read it. */ EShellModuleInfo info; GModule *module; @@ -212,6 +214,11 @@ shell_module_class_init (EShellModuleClass *class) type_module_class->load = shell_module_load; type_module_class->unload = shell_module_unload; + /** + * EShellModule:filename + * + * The filename of the module. + **/ g_object_class_install_property ( object_class, PROP_FILENAME, @@ -223,6 +230,11 @@ shell_module_class_init (EShellModuleClass *class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * EShellModule:shell + * + * The #EShell singleton. + **/ g_object_class_install_property ( object_class, PROP_SHELL, @@ -267,6 +279,19 @@ e_shell_module_get_type (void) return type; } +/** + * e_shell_module_new: + * @shell: an #EShell + * @filename: the name of the file containing the shell module + * + * Loads @filename as a #GTypeModule and tries to invoke a module + * function named e_shell_module_init, passing + * the newly loaded #GTypeModule as an argument. The shell module is + * responsible for defining such a function to perform the appropriate + * initialization steps. + * + * Returns: a new #EShellModule + **/ EShellModule * e_shell_module_new (EShell *shell, const gchar *filename) @@ -278,6 +303,18 @@ e_shell_module_new (EShell *shell, "filename", filename, NULL); } +/** + * e_shell_module_compare: + * @shell_module_a: an #EShellModule + * @shell_module_b: an #EShellModule + * + * Using the sort_order field from both modules' + * #EShellModuleInfo, compares @shell_module_a with @shell_mobule_b and + * returns -1, 0 or +1 if @shell_module_a is found to be less than, equal + * to or greater than @shell_module_b, respectively. + * + * Returns: -1, 0 or +1, for a less than, equal to or greater than result + **/ gint e_shell_module_compare (EShellModule *shell_module_a, EShellModule *shell_module_b) @@ -288,6 +325,16 @@ e_shell_module_compare (EShellModule *shell_module_a, return (a < b) ? -1 : (a > b); } +/** + * e_shell_module_get_config_dir: + * @shell_module: an #EShellModule + * + * Returns the absolute path to the configuration directory for + * @shell_module. The string is owned by @shell_module and should + * not be modified or freed. + * + * Returns: the module's configuration directory + **/ const gchar * e_shell_module_get_config_dir (EShellModule *shell_module) { @@ -297,6 +344,16 @@ e_shell_module_get_config_dir (EShellModule *shell_module) return shell_module->priv->config_dir; } +/** + * e_shell_module_get_data_dir: + * @shell_module: an #EShellModule + * + * Returns the absolute path to the data directory for @shell_module. + * The string is owned by @shell_module and should not be modified or + * freed. + * + * Returns: the module's data directory + **/ const gchar * e_shell_module_get_data_dir (EShellModule *shell_module) { @@ -306,6 +363,16 @@ e_shell_module_get_data_dir (EShellModule *shell_module) return shell_module->priv->data_dir; } +/** + * e_shell_module_get_filename: + * @shell_module: an #EShellModule + * + * Returns the name of the file from which @shell_module was loaded. + * The string is owned by @shell_module and should not be modified or + * freed. + * + * Returns: the module's file name + **/ const gchar * e_shell_module_get_filename (EShellModule *shell_module) { @@ -322,6 +389,14 @@ e_shell_module_get_searches (EShellModule *shell_module) return shell_module->priv->info.searches; } +/** + * e_shell_module_get_shell: + * @shell_module: an #EShellModule + * + * Returns the #EShell that was passed to e_shell_module_new(). + * + * Returns: the #EShell + **/ EShell * e_shell_module_get_shell (EShellModule *shell_module) { @@ -360,6 +435,18 @@ e_shell_module_shutdown (EShellModule *shell_module) return TRUE; } +/** + * e_shell_module_set_info: + * @shell_module: an #EShellModule + * @info: an #EShellModuleInfo + * + * Registers basic configuration information about @shell_module that + * the #EShell can use for processing command-line arguments. + * + * Configuration information should be registered from + * @shell_module's e_shell_module_init + * initialization function. See e_shell_module_new() for more information. + **/ void e_shell_module_set_info (EShellModule *shell_module, const EShellModuleInfo *info) diff --git a/shell/e-shell-module.h b/shell/e-shell-module.h index d9baa84a9a..71fdc6b4e9 100644 --- a/shell/e-shell-module.h +++ b/shell/e-shell-module.h @@ -21,7 +21,7 @@ #ifndef E_SHELL_MODULE_H #define E_SHELL_MODULE_H -#include +#include /* Standard GObject macros */ #define E_TYPE_SHELL_MODULE \ @@ -44,16 +44,45 @@ G_BEGIN_DECLS +/* Avoid including */ +struct _EShell; + typedef struct _EShellModule EShellModule; typedef struct _EShellModuleInfo EShellModuleInfo; typedef struct _EShellModuleClass EShellModuleClass; typedef struct _EShellModulePrivate EShellModulePrivate; +/** + * EShellModuleInfo: + * @name: The name of the module. Also becomes the name of + * the corresponding #EShellView subclass that the + * module will register. + * @aliases: Colon-separated list of aliases that can be used + * when referring to a module or view by name, such + * as in e_shell_window_set_current_view(). + * @schemes: Colon-separated list of URI schemes. The #EShell + * will forward command-line URIs to the appropriate + * module based on this list. + * @searches: Base name of the XML file containing predefined + * search rules for this module. These show up as + * options in the search entry drop-down. + * @sort_order: Used to determine the order of modules listed in + * the main menu and in the switcher. See + * e_shell_module_compare(). + * @is_busy: Callback for querying whether the module has + * operations in progress that cannot be cancelled + * or finished immediately. Returning %TRUE prevents + * the application from shutting down. + * @shutdown: Callback for notifying the module to begin + * shutting down. Returning %FALSE indicates there + * are still unfinished operations and the #EShell + * should check back shortly. + **/ struct _EShellModuleInfo { const gchar *name; - const gchar *aliases; /* colon-separated list */ - const gchar *schemes; /* colon-separated list */ - const gchar *searches; /* built-in search rules */ + const gchar *aliases; + const gchar *schemes; + const gchar *searches; gint sort_order; gboolean (*is_busy) (EShellModule *shell_module); @@ -70,7 +99,7 @@ struct _EShellModuleClass { }; GType e_shell_module_get_type (void); -EShellModule * e_shell_module_new (EShell *shell, +EShellModule * e_shell_module_new (struct _EShell *shell, const gchar *filename); gint e_shell_module_compare (EShellModule *shell_module_a, EShellModule *shell_module_b); @@ -78,7 +107,7 @@ const gchar * e_shell_module_get_config_dir (EShellModule *shell_module); const gchar * e_shell_module_get_data_dir (EShellModule *shell_module); const gchar * e_shell_module_get_filename (EShellModule *shell_module); const gchar * e_shell_module_get_searches (EShellModule *shell_module); -EShell * e_shell_module_get_shell (EShellModule *shell_module); +struct _EShell *e_shell_module_get_shell (EShellModule *shell_module); gboolean e_shell_module_is_busy (EShellModule *shell_module); gboolean e_shell_module_shutdown (EShellModule *shell_module); void e_shell_module_set_info (EShellModule *shell_module, diff --git a/shell/e-shell-registry.c b/shell/e-shell-registry.c deleted file mode 100644 index af95b0adad..0000000000 --- a/shell/e-shell-registry.c +++ /dev/null @@ -1,158 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* e-shell-registry.c - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "e-shell-registry.h" - -static GList *loaded_modules; -static GHashTable *modules_by_name; -static GHashTable *modules_by_scheme; - -static void -shell_registry_insert_items (GHashTable *hash_table, - const gchar *items, - EShellModule *shell_module) -{ - gpointer key; - gchar **strv; - gint ii; - - strv = g_strsplit_set (items, ":", -1); - - for (ii = 0; strv[ii] != NULL; ii++) { - key = (gpointer) g_intern_string (strv[ii]); - g_hash_table_insert (hash_table, key, shell_module); - } - - g_strfreev (strv); -} - -static void -shell_registry_query_module (EShell *shell, - const gchar *filename) -{ - EShellModule *shell_module; - EShellModuleInfo *info; - const gchar *string; - - shell_module = e_shell_module_new (shell, filename); - - if (!g_type_module_use (G_TYPE_MODULE (shell_module))) { - g_critical ("Failed to load module: %s", filename); - g_object_unref (shell_module); - return; - } - - loaded_modules = g_list_insert_sorted ( - loaded_modules, shell_module, - (GCompareFunc) e_shell_module_compare); - - /* Bookkeeping */ - - info = (EShellModuleInfo *) shell_module->priv; - - if ((string = info->name) != NULL) - g_hash_table_insert ( - modules_by_name, (gpointer) - g_intern_string (string), shell_module); - - if ((string = info->aliases) != NULL) - shell_registry_insert_items ( - modules_by_name, string, shell_module); - - if ((string = info->schemes) != NULL) - shell_registry_insert_items ( - modules_by_scheme, string, shell_module); -} - -void -e_shell_registry_init (EShell *shell) -{ - GDir *dir; - const gchar *dirname; - const gchar *basename; - GError *error = NULL; - - g_return_if_fail (E_IS_SHELL (shell)); - g_return_if_fail (loaded_modules == NULL); - - modules_by_name = g_hash_table_new (g_str_hash, g_str_equal); - modules_by_scheme = g_hash_table_new (g_str_hash, g_str_equal); - - dirname = EVOLUTION_MODULEDIR; - - dir = g_dir_open (dirname, 0, &error); - if (dir == NULL) { - g_critical ("%s", error->message); - g_error_free (error); - return; - } - - while ((basename = g_dir_read_name (dir)) != NULL) { - gchar *filename; - - if (!g_str_has_suffix (basename, "." G_MODULE_SUFFIX)) - continue; - - filename = g_build_filename (dirname, basename, NULL); - shell_registry_query_module (shell, filename); - g_free (filename); - } - - g_dir_close (dir); -} - -GList * -e_shell_registry_list_modules (void) -{ - return loaded_modules; -} - -const gchar * -e_shell_registry_get_canonical_name (const gchar *name) -{ - EShellModule *shell_module; - - /* Handle NULL arguments silently. */ - if (name == NULL) - return NULL; - - shell_module = e_shell_registry_get_module_by_name (name); - - if (shell_module == NULL) - return NULL; - - return G_TYPE_MODULE (shell_module)->name; -} - -EShellModule * -e_shell_registry_get_module_by_name (const gchar *name) -{ - g_return_val_if_fail (name != NULL, NULL); - - return g_hash_table_lookup (modules_by_name, name); -} - -EShellModule * -e_shell_registry_get_module_by_scheme (const gchar *scheme) -{ - g_return_val_if_fail (scheme != NULL, NULL); - - return g_hash_table_lookup (modules_by_scheme, scheme); -} diff --git a/shell/e-shell-registry.h b/shell/e-shell-registry.h deleted file mode 100644 index 852d9236fe..0000000000 --- a/shell/e-shell-registry.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* e-shell-registry.h - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef E_SHELL_REGISTRY -#define E_SHELL_REGISTRY - -#include "e-shell-common.h" -#include "e-shell-module.h" -#include "e-shell.h" - -G_BEGIN_DECLS - -void e_shell_registry_init (EShell *shell); -GList * e_shell_registry_list_modules (void); -const gchar * e_shell_registry_get_canonical_name (const gchar *name); -EShellModule * e_shell_registry_get_module_by_name (const gchar *name); -EShellModule * e_shell_registry_get_module_by_scheme (const gchar *scheme); - -G_END_DECLS - -#endif /* E_SHELL_REGISTRY */ diff --git a/shell/e-shell-switcher.c b/shell/e-shell-switcher.c index f9cf1810b7..ae29900fb2 100644 --- a/shell/e-shell-switcher.c +++ b/shell/e-shell-switcher.c @@ -430,29 +430,46 @@ shell_switcher_class_init (EShellSwitcherClass *class) class->style_changed = shell_switcher_style_changed; + /** + * EShellSwitcher:toolbar-style + * + * The switcher's toolbar style. + **/ g_object_class_install_property ( object_class, PROP_TOOLBAR_STYLE, g_param_spec_enum ( "toolbar-style", - NULL, - NULL, + _("Toolbar Style"), + _("The switcher's toolbar style"), GTK_TYPE_TOOLBAR_STYLE, E_SHELL_SWITCHER_DEFAULT_TOOLBAR_STYLE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + /** + * EShellSwitcher:toolbar-visible + * + * Whether the switcher is visible. + **/ g_object_class_install_property ( object_class, PROP_TOOLBAR_VISIBLE, g_param_spec_boolean ( "toolbar-visible", - NULL, - NULL, + _("Toolbar Visible"), + _("Whether the switcher is visible"), TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + /** + * EShellSwitcher::style-changed + * @switcher: the #EShellSwitcher which emitted the signal + * @style: the new #GtkToolbarStyle of the switcher + * + * Emitted when the style of the switcher changes. + **/ signals[STYLE_CHANGED] = g_signal_new ( "style-changed", G_OBJECT_CLASS_TYPE (class), @@ -516,12 +533,30 @@ e_shell_switcher_get_type (void) return type; } +/** + * e_shell_switcher_new: + * + * Creates a new #EShellSwitcher instance. + * + * Returns: a new #EShellSwitcher instance + **/ GtkWidget * e_shell_switcher_new (void) { return g_object_new (E_TYPE_SHELL_SWITCHER, NULL); } +/** + * e_shell_switcher_add_action: + * @switcher: an #EShellSwitcher + * @action: a #GtkAction + * + * Adds a button to @switcher that proxies for @action. Switcher buttons + * appear in the order they were added. + * + * #EShellWindow adds switcher actions in the order given by the + * sort_order field in #EShellModuleInfo. + **/ void e_shell_switcher_add_action (EShellSwitcher *switcher, GtkAction *action) @@ -543,6 +578,14 @@ e_shell_switcher_add_action (EShellSwitcher *switcher, gtk_widget_queue_resize (GTK_WIDGET (switcher)); } +/** + * e_shell_switcher_get_style: + * @switcher: an #EShellSwitcher + * + * Returns whether @switcher has text, icons or both. + * + * Returns: the current style of @shell + **/ GtkToolbarStyle e_shell_switcher_get_style (EShellSwitcher *switcher) { @@ -553,6 +596,14 @@ e_shell_switcher_get_style (EShellSwitcher *switcher) return switcher->priv->style; } +/** + * e_shell_switcher_set_style: + * @switcher: an #EShellSwitcher + * @style: the new style for @switcher + * + * Alters the view of @switcher to display either icons only, text only, + * or both. + **/ void e_shell_switcher_set_style (EShellSwitcher *switcher, GtkToolbarStyle style) @@ -563,6 +614,13 @@ e_shell_switcher_set_style (EShellSwitcher *switcher, g_signal_emit (switcher, signals[STYLE_CHANGED], 0, style); } +/** + * e_shell_switcher_unset_style: + * @switcher: an #EShellSwitcher + * + * Unsets a switcher style set with e_shell_switcher_set_style(), so + * that user preferences will be used to determine the switcher style. + **/ void e_shell_switcher_unset_style (EShellSwitcher *switcher) { diff --git a/shell/e-shell-window-private.h b/shell/e-shell-window-private.h index 67cd51458b..7c04d87f6b 100644 --- a/shell/e-shell-window-private.h +++ b/shell/e-shell-window-private.h @@ -36,7 +36,6 @@ #include #include #include -#include #include #include diff --git a/shell/e-shell-window.c b/shell/e-shell-window.c index b1a7e4b6b1..d35ca0605a 100644 --- a/shell/e-shell-window.c +++ b/shell/e-shell-window.c @@ -225,34 +225,49 @@ shell_window_class_init (EShellWindowClass *class) object_class->dispose = shell_window_dispose; object_class->finalize = shell_window_finalize; + /** + * EShellWindow:current-view + * + * Name of the currently active #EShellView. + **/ g_object_class_install_property ( object_class, PROP_CURRENT_VIEW, g_param_spec_string ( "current-view", - NULL, - NULL, + _("Current Shell View"), + _("Name of the currently active shell view"), NULL, G_PARAM_READWRITE)); + /** + * EShellWindow:safe-mode + * + * Whether the shell window is in safe mode. + **/ g_object_class_install_property ( object_class, PROP_SAFE_MODE, g_param_spec_boolean ( "safe-mode", - NULL, - NULL, + _("Safe Mode"), + _("Whether the shell window is in safe mode"), FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + /** + * EShellWindow:shell + * + * The #EShell singleton. + **/ g_object_class_install_property ( object_class, PROP_SHELL, g_param_spec_object ( "shell", - NULL, - NULL, + _("Shell"), + _("The EShell singleton"), E_TYPE_SHELL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); @@ -299,6 +314,25 @@ e_shell_window_get_type (void) return type; } +/** + * e_shell_window_new: + * @shell: an #EShell + * @safe_mode: whether to initialize the window to "safe mode" + * + * Returns a new #EShellWindow. + * + * It's up to the various #EShellView's to define exactly + * what "safe mode" means, but the #EShell usually puts the initial + * #EShellWindow into "safe mode" if detects the previous Evolution + * session crashed. + * + * The initial view for the window is determined by GConf key + * /apps/evolution/shell/view_defaults/component_id. + * Or, if the GConf key is not set or can't be read, the first view + * in the switcher is used. + * + * Returns: a new #EShellWindow + **/ GtkWidget * e_shell_window_new (EShell *shell, gboolean safe_mode) @@ -308,6 +342,22 @@ e_shell_window_new (EShell *shell, "shell", shell, "safe-mode", safe_mode, NULL); } +/** + * e_shell_window_get_view: + * @shell_window: an #EShellWindow + * @view_name: name of a shell view + * + * Returns the #EShellView named @view_name (see the + * name field in #EShellModuleInfo). This + * will also instantiate the #EShellView the first time it's requested. + * To reduce resource consumption, Evolution tries to delay instantiating + * shell views until the user switches to them. So in general, only the + * currently active view name, as returned by + * e_shell_window_get_current_view(), should be requested. + * + * Returns: the requested #EShellView, or %NULL if no such view is + * registered + **/ gpointer e_shell_window_get_view (EShellWindow *shell_window, const gchar *view_name) @@ -355,6 +405,14 @@ e_shell_window_get_view (EShellWindow *shell_window, return shell_view; } +/** + * e_shell_window_get_shell: + * @shell_window: an #EShellWindow + * + * Returns the #EShell that was passed to e_shell_window_new(). + * + * Returns: the #EShell + **/ EShell * e_shell_window_get_shell (EShellWindow *shell_window) { @@ -363,6 +421,17 @@ e_shell_window_get_shell (EShellWindow *shell_window) return shell_window->priv->shell; } +/** + * e_shell_window_get_ui_manager: + * @shell_window: an #EShellWindow + * + * Returns @shell_window's user interface manager, which + * manages the window's menus and toolbars via #GtkActions. + * This is the mechanism by which shell views and plugins can extend + * Evolution's menus and toolbars. + * + * Returns: the #GtkUIManager for @shell_window + **/ GtkUIManager * e_shell_window_get_ui_manager (EShellWindow *shell_window) { @@ -371,6 +440,16 @@ e_shell_window_get_ui_manager (EShellWindow *shell_window) return shell_window->priv->ui_manager; } +/** + * e_shell_window_get_action: + * @shell_window: an #EShellWindow + * @action_name: the name of an action + * + * Returns the #GtkAction named @action_name in @shell_window's + * user interface manager, or %NULL if no such action exists. + * + * Returns: the #GtkAction named @action_name + **/ GtkAction * e_shell_window_get_action (EShellWindow *shell_window, const gchar *action_name) @@ -398,6 +477,17 @@ e_shell_window_get_action (EShellWindow *shell_window, return action; } +/** + * e_shell_window_get_action_group: + * @shell_window: an #EShellWindow + * @group_name: the name of an action group + * + * Returns the #GtkActionGroup named @group_name in + * @shell_window's user interface manager, or %NULL if no + * such action group exists. + * + * Returns: the #GtkActionGroup named @group_name + **/ GtkActionGroup * e_shell_window_get_action_group (EShellWindow *shell_window, const gchar *group_name) @@ -425,6 +515,18 @@ e_shell_window_get_action_group (EShellWindow *shell_window, g_return_val_if_reached (NULL); } +/** + * e_shell_window_get_managed_widget: + * @shell_window: an #EShellWindow + * @widget_path: path in the UI definintion + * + * Looks up a widget in @shell_window's user interface manager by + * following a path. See gtk_ui_manager_get_widget() for more information + * about paths. + * + * Returns: the widget found by following the path, or %NULL if no widget + * was found + **/ GtkWidget * e_shell_window_get_managed_widget (EShellWindow *shell_window, const gchar *widget_path) @@ -443,6 +545,14 @@ e_shell_window_get_managed_widget (EShellWindow *shell_window, return widget; } +/** + * e_shell_window_get_current_view: + * @shell_window: an #EShellWindow + * + * Returns the name of the currently active #EShellView. + * + * Returns: the name of the current view + **/ const gchar * e_shell_window_get_current_view (EShellWindow *shell_window) { @@ -451,22 +561,43 @@ e_shell_window_get_current_view (EShellWindow *shell_window) return shell_window->priv->current_view; } +/** + * e_shell_window_set_current_view: + * @shell_window: an #EShellWindow + * @name_or_alias: the name of the shell view to switch to + * + * Switches @shell_window to the #EShellView named (or with an alias of) + * @name_or_alias, causing the entire content of @shell_window to change. + * This is typically called as a result of the user clicking one of the + * switcher buttons. + * + * See #EShellModuleInfo for more information about shell view names and + * aliases. + * + * The name of the newly activated shell view is also written to GConf key + * /apps/evolution/shell/view_defaults/component_id. + * This makes the current shell view persistent across Evolution sessions. + * It also causes new shell windows created within the current Evolution + * session to open to the most recently selected shell view. + **/ void e_shell_window_set_current_view (EShellWindow *shell_window, const gchar *name_or_alias) { GtkAction *action; EShellView *shell_view; + EShell *shell; GList *list; const gchar *view_name; g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); view_name = name_or_alias; - list = e_shell_registry_list_modules (); + shell = e_shell_window_get_shell (shell_window); + list = e_shell_list_modules (shell); if (view_name != NULL) - view_name = e_shell_registry_get_canonical_name (view_name); + view_name = e_shell_get_canonical_name (shell, view_name); if (view_name == NULL && list != NULL) view_name = G_TYPE_MODULE (list->data)->name; @@ -486,6 +617,18 @@ e_shell_window_set_current_view (EShellWindow *shell_window, e_shell_window_switch_to_view (shell_window, view_name); } +/** + * e_shell_window_get_safe_mode: + * @shell_window: an #EShellWindow + * + * Returns %TRUE if @shell_window is in "safe mode". + * + * It's up to the various #EShellView's to define exactly + * what "safe mode" means. The @shell_window simply manages the + * "safe mode" state. + * + * Returns: %TRUE if @shell_window is in "safe mode" + **/ gboolean e_shell_window_get_safe_mode (EShellWindow *shell_window) { @@ -494,6 +637,17 @@ e_shell_window_get_safe_mode (EShellWindow *shell_window) return shell_window->priv->safe_mode; } +/** + * e_shell_window_set_safe_mode: + * @shell_window: an #EShellWindow + * @safe_mode: whether to put @shell_window into "safe mode" + * + * If %TRUE, puts @shell_window into "safe mode". + * + * It's up to the various #EShellView's to define exactly + * what "safe mode" means. The @shell_window simply manages the + * "safe mode" state. + **/ void e_shell_window_set_safe_mode (EShellWindow *shell_window, gboolean safe_mode) @@ -505,6 +659,24 @@ e_shell_window_set_safe_mode (EShellWindow *shell_window, g_object_notify (G_OBJECT (shell_window), "safe-mode"); } +/** + * e_shell_window_register_new_item_actions: + * @shell_window: an #EShellWindow + * @module_name: name of an #EShellModule + * @entries: an array of #GtkActionEntrys + * @n_entries: number of elements in the array + * + * Registers a list of #GtkActions to appear in + * @shell_window's "New" menu and toolbar button. This + * function should be called from an #EShellModule's + * #EShell::window-created signal handler. The #EShellModule calling + * this function should pass its own name for the @module_name argument + * (i.e. the name field from its own + * #EShellModuleInfo). + * + * The registered #GtkActions should be for creating individual + * items such as an email message or a calendar appointment. + **/ void e_shell_window_register_new_item_actions (EShellWindow *shell_window, const gchar *module_name, @@ -551,6 +723,24 @@ e_shell_window_register_new_item_actions (EShellWindow *shell_window, e_shell_window_update_new_menu (shell_window); } +/** + * e_shell_window_register_new_source_actions: + * @shell_window: an #EShellWindow + * @module_name: name of an #EShellModule + * @entries: an array of #GtkActionEntrys + * @n_entries: number of elements in the array + * + * Registers a list of #GtkActions to appear in + * @shell_window's "New" menu and toolbar button. This + * function should be called from an #EShellModule's + * #EShell::window-created signal handler. The #EShellModule calling + * this function should pass its own name for the @module_name argument + * (i.e. the name field from its own + * #EShellModuleInfo). + * + * The registered #GtkActions should be for creating item + * containers such as an email folder or a calendar. + **/ void e_shell_window_register_new_source_actions (EShellWindow *shell_window, const gchar *module_name, diff --git a/shell/e-shell.c b/shell/e-shell.c index b96ceb4944..304a90e10e 100644 --- a/shell/e-shell.c +++ b/shell/e-shell.c @@ -24,10 +24,9 @@ #include #include -#include "e-shell-marshal.h" -#include "e-shell-module.h" -#include "e-shell-registry.h" -#include "e-shell-window.h" +#include +#include +#include #define SHUTDOWN_TIMEOUT 500 /* milliseconds */ @@ -39,6 +38,11 @@ struct _EShellPrivate { GList *active_windows; EShellLineStatus line_status; + /* Shell Modules */ + GList *loaded_modules; + GHashTable *modules_by_name; + GHashTable *modules_by_scheme; + guint online_mode : 1; guint safe_mode : 1; }; @@ -90,6 +94,68 @@ shell_window_weak_notify_cb (EShell *shell, g_signal_emit (shell, signals[WINDOW_DESTROYED], 0, last_window); } +/* Helper for shell_query_module() */ +static void +shell_split_and_insert_items (GHashTable *hash_table, + const gchar *items, + EShellModule *shell_module) +{ + gpointer key; + gchar **strv; + gint ii; + + strv = g_strsplit_set (items, ":", -1); + + for (ii = 0; strv[ii] != NULL; ii++) { + key = (gpointer) g_intern_string (strv[ii]); + g_hash_table_insert (hash_table, key, shell_module); + } + + g_strfreev (strv); +} + +static void +shell_query_module (EShell *shell, + const gchar *filename) +{ + EShellModule *shell_module; + EShellModuleInfo *info; + GHashTable *modules_by_name; + GHashTable *modules_by_scheme; + const gchar *string; + + shell_module = e_shell_module_new (shell, filename); + + if (!g_type_module_use (G_TYPE_MODULE (shell_module))) { + g_critical ("Failed to load module: %s", filename); + g_object_unref (shell_module); + return; + } + + shell->priv->loaded_modules = g_list_insert_sorted ( + shell->priv->loaded_modules, shell_module, + (GCompareFunc) e_shell_module_compare); + + /* Bookkeeping */ + + info = (EShellModuleInfo *) shell_module->priv; + modules_by_name = shell->priv->modules_by_name; + modules_by_scheme = shell->priv->modules_by_scheme; + + if ((string = info->name) != NULL) + g_hash_table_insert ( + modules_by_name, (gpointer) + g_intern_string (string), shell_module); + + if ((string = info->aliases) != NULL) + shell_split_and_insert_items ( + modules_by_name, string, shell_module); + + if ((string = info->schemes) != NULL) + shell_split_and_insert_items ( + modules_by_scheme, string, shell_module); +} + static gboolean shell_shutdown_timeout (EShell *shell) { @@ -99,7 +165,7 @@ shell_shutdown_timeout (EShell *shell) static guint message_timer = 1; /* Module list is read-only; do not free. */ - list = e_shell_registry_list_modules (); + list = e_shell_list_modules (shell); /* Any module can defer shutdown if it's still busy. */ for (iter = list; proceed && iter != NULL; iter = iter->next) { @@ -175,6 +241,16 @@ shell_get_property (GObject *object, static void shell_dispose (GObject *object) { + EShellPrivate *priv; + + priv = E_SHELL_GET_PRIVATE (object); + + g_list_foreach ( + priv->loaded_modules, + (GFunc) g_type_module_unuse, NULL); + g_list_free (priv->loaded_modules); + priv->loaded_modules = NULL; + /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -182,10 +258,50 @@ shell_dispose (GObject *object) static void shell_finalize (GObject *object) { + EShellPrivate *priv; + + priv = E_SHELL_GET_PRIVATE (object); + + g_hash_table_destroy (priv->modules_by_name); + g_hash_table_destroy (priv->modules_by_scheme); + /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (parent_class)->finalize (object); } +static void +shell_constructed (GObject *object) +{ + GDir *dir; + EShell *shell; + const gchar *dirname; + const gchar *basename; + GError *error = NULL; + + shell = E_SHELL (object); + dirname = EVOLUTION_MODULEDIR; + + dir = g_dir_open (dirname, 0, &error); + if (dir == NULL) { + g_critical ("%s", error->message); + g_error_free (error); + return; + } + + while ((basename = g_dir_read_name (dir)) != NULL) { + gchar *filename; + + if (!g_str_has_suffix (basename, "." G_MODULE_SUFFIX)) + continue; + + filename = g_build_filename (dirname, basename, NULL); + shell_query_module (shell, filename); + g_free (filename); + } + + g_dir_close (dir); +} + static void shell_class_init (EShellClass *class) { @@ -199,6 +315,7 @@ shell_class_init (EShellClass *class) object_class->get_property = shell_get_property; object_class->dispose = shell_dispose; object_class->finalize = shell_finalize; + object_class->constructed = shell_constructed; g_object_class_install_property ( object_class, @@ -251,8 +368,16 @@ shell_class_init (EShellClass *class) static void shell_init (EShell *shell) { + GHashTable *modules_by_name; + GHashTable *modules_by_scheme; + shell->priv = E_SHELL_GET_PRIVATE (shell); + modules_by_name = g_hash_table_new (g_str_hash, g_str_equal); + modules_by_scheme = g_hash_table_new (g_str_hash, g_str_equal); + + shell->priv->modules_by_name = modules_by_name; + shell->priv->modules_by_scheme = modules_by_scheme; shell->priv->safe_mode = e_file_lock_exists (); #if NM_SUPPORT @@ -260,7 +385,6 @@ shell_init (EShell *shell) #endif e_file_lock_create (); - e_shell_registry_init (shell); } GType @@ -295,6 +419,62 @@ e_shell_new (gboolean online_mode) return g_object_new (E_TYPE_SHELL, "online-mode", online_mode, NULL); } +GList * +e_shell_list_modules (EShell *shell) +{ + g_return_val_if_fail (E_IS_SHELL (shell), NULL); + + return shell->priv->loaded_modules; +} + +const gchar * +e_shell_get_canonical_name (EShell *shell, + const gchar *name) +{ + EShellModule *shell_module; + + g_return_val_if_fail (E_IS_SHELL (shell), NULL); + + /* Handle NULL name arguments silently. */ + if (name == NULL) + return NULL; + + shell_module = e_shell_get_module_by_name (shell, name); + + if (shell_module == NULL) + return NULL; + + return G_TYPE_MODULE (shell_module)->name; +} + +EShellModule * +e_shell_get_module_by_name (EShell *shell, + const gchar *name) +{ + GHashTable *hash_table; + + g_return_val_if_fail (E_IS_SHELL (shell), NULL); + g_return_val_if_fail (name != NULL, NULL); + + hash_table = shell->priv->modules_by_name; + + return g_hash_table_lookup (hash_table, name); +} + +EShellModule * +e_shell_get_module_by_scheme (EShell *shell, + const gchar *scheme) +{ + GHashTable *hash_table; + + g_return_val_if_fail (E_IS_SHELL (shell), NULL); + g_return_val_if_fail (scheme != NULL, NULL); + + hash_table = shell->priv->modules_by_scheme; + + return g_hash_table_lookup (hash_table, scheme); +} + GtkWidget * e_shell_create_window (EShell *shell) { diff --git a/shell/e-shell.h b/shell/e-shell.h index 709e4db170..1500c2bcb4 100644 --- a/shell/e-shell.h +++ b/shell/e-shell.h @@ -24,6 +24,7 @@ #define E_SHELL_H #include +#include /* Standard GObject macros */ #define E_TYPE_SHELL \ @@ -70,6 +71,13 @@ enum _EShellLineStatus { GType e_shell_get_type (void); EShell * e_shell_new (gboolean online); +GList * e_shell_list_modules (EShell *shell); +const gchar * e_shell_get_canonical_name (EShell *shell, + const gchar *name); +EShellModule * e_shell_get_module_by_name (EShell *shell, + const gchar *name); +EShellModule * e_shell_get_module_by_scheme (EShell *shell, + const gchar *scheme); GtkWidget * e_shell_create_window (EShell *shell); gboolean e_shell_handle_uri (EShell *shell, const gchar *uri); diff --git a/shell/main.c b/shell/main.c index 4b7c3cce3d..4d28eb7549 100644 --- a/shell/main.c +++ b/shell/main.c @@ -34,7 +34,6 @@ #include "e-util/e-bconf-map.h" #include -#include "e-shell-registry.h" #include "e-util/e-profile-event.h" #include "e-util/e-util.h" @@ -294,7 +293,8 @@ idle_cb (gchar **uris) return FALSE; } - initial_view = e_shell_registry_get_canonical_name (requested_view); + initial_view = e_shell_get_canonical_name ( + global_shell, requested_view); if (initial_view != NULL) { GConfClient *client; -- cgit v1.2.3