diff options
author | Matthew Barnes <mbarnes@src.gnome.org> | 2009-01-24 05:41:01 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@src.gnome.org> | 2009-01-24 05:41:01 +0800 |
commit | bd9f473a896496b95b9896d30940f2ab27493432 (patch) | |
tree | 7c314e4776bcfbff0c483ee7995818519fbc43bb | |
parent | 3c7a575407bef757d434808904a4c4dc1ba60cb3 (diff) | |
download | gsoc2013-evolution-bd9f473a896496b95b9896d30940f2ab27493432.tar.gz gsoc2013-evolution-bd9f473a896496b95b9896d30940f2ab27493432.tar.zst gsoc2013-evolution-bd9f473a896496b95b9896d30940f2ab27493432.zip |
Redesign EPluginUI to accommodate merging and unmerging shell views.
Get the "mark-all-read" and "plugin-manager" plugins working.
svn path=/branches/kill-bonobo/; revision=37125
27 files changed, 512 insertions, 420 deletions
diff --git a/addressbook/gui/component/e-book-shell-view.c b/addressbook/gui/component/e-book-shell-view.c index 11cdaf6594..6244384390 100644 --- a/addressbook/gui/component/e-book-shell-view.c +++ b/addressbook/gui/component/e-book-shell-view.c @@ -286,6 +286,7 @@ book_shell_view_class_init (EBookShellViewClass *class, shell_view_class->label = _("Contacts"); shell_view_class->icon_name = "x-office-address-book"; shell_view_class->ui_definition = "evolution-contacts.ui"; + shell_view_class->ui_manager_id = "org.gnome.evolution.contacts"; shell_view_class->search_options = "/contact-search-options"; shell_view_class->search_rules = "addresstypes.xml"; shell_view_class->type_module = type_module; diff --git a/addressbook/gui/widgets/eab-contact-display.c b/addressbook/gui/widgets/eab-contact-display.c index 02aa5b81f0..42cc65294f 100644 --- a/addressbook/gui/widgets/eab-contact-display.c +++ b/addressbook/gui/widgets/eab-contact-display.c @@ -1087,6 +1087,7 @@ eab_contact_display_init (EABContactDisplay *display) { GtkActionGroup *action_group; GtkHTML *html; + const gchar *id; display->priv = EAB_CONTACT_DISPLAY_GET_PRIVATE (display); display->priv->mode = EAB_CONTACT_DISPLAY_RENDER_NORMAL; @@ -1146,8 +1147,9 @@ eab_contact_display_init (EABContactDisplay *display) display->priv->invisible, GDK_SELECTION_CLIPBOARD, GDK_SELECTION_TYPE_STRING, 1); - e_plugin_ui_register_manager ( - "contact-display", display->priv->ui_manager, display); + id = "org.gnome.evolution.contact-display"; + e_plugin_ui_register_manager (display->priv->ui_manager, id, display); + e_plugin_ui_enable_manager (display->priv->ui_manager, id); } GType diff --git a/calendar/gui/dialogs/event-editor.c b/calendar/gui/dialogs/event-editor.c index 72cbf37823..620600369e 100644 --- a/calendar/gui/dialogs/event-editor.c +++ b/calendar/gui/dialogs/event-editor.c @@ -465,6 +465,7 @@ event_editor_init (EventEditor *ee) GtkUIManager *manager; GtkActionGroup *action_group; GtkAction *action; + const gchar *id; GError *error = NULL; ee->priv = EVENT_EDITOR_GET_PRIVATE (ee); @@ -487,7 +488,10 @@ event_editor_init (EventEditor *ee) manager = comp_editor_get_ui_manager (editor); gtk_ui_manager_add_ui_from_string (manager, ui, -1, &error); - e_plugin_ui_register_manager ("event-editor", manager, ee); + + id = "org.gnome.evolution.event-editor"; + e_plugin_ui_register_manager (manager, id, ee); + e_plugin_ui_enable_manager (manager, id); if (error != NULL) { g_critical ("%s: %s", G_STRFUNC, error->message); diff --git a/calendar/gui/dialogs/memo-editor.c b/calendar/gui/dialogs/memo-editor.c index 90c77f2349..5e01327703 100644 --- a/calendar/gui/dialogs/memo-editor.c +++ b/calendar/gui/dialogs/memo-editor.c @@ -134,6 +134,7 @@ memo_editor_init (MemoEditor *me) { CompEditor *editor = COMP_EDITOR (me); GtkUIManager *manager; + const gchar *id; GError *error = NULL; me->priv = MEMO_EDITOR_GET_PRIVATE (me); @@ -141,7 +142,10 @@ memo_editor_init (MemoEditor *me) manager = comp_editor_get_ui_manager (editor); gtk_ui_manager_add_ui_from_string (manager, ui, -1, &error); - e_plugin_ui_register_manager ("memo-editor", manager, me); + + id = "org.gnome.evolution.memo-editor"; + e_plugin_ui_register_manager (manager, id, me); + e_plugin_ui_enable_manager (manager, id); if (error != NULL) { g_critical ("%s: %s", G_STRFUNC, error->message); diff --git a/calendar/gui/dialogs/task-editor.c b/calendar/gui/dialogs/task-editor.c index 656e7b4836..773dea4a47 100644 --- a/calendar/gui/dialogs/task-editor.c +++ b/calendar/gui/dialogs/task-editor.c @@ -303,6 +303,7 @@ task_editor_init (TaskEditor *te) CompEditor *editor = COMP_EDITOR (te); GtkUIManager *manager; GtkActionGroup *action_group; + const gchar *id; GError *error = NULL; te->priv = TASK_EDITOR_GET_PRIVATE (te); @@ -345,7 +346,10 @@ task_editor_init (TaskEditor *te) manager = comp_editor_get_ui_manager (editor); gtk_ui_manager_add_ui_from_string (manager, ui, -1, &error); - e_plugin_ui_register_manager ("task-editor", manager, te); + + id = "org.gnome.evolution.task-editor"; + e_plugin_ui_register_manager (manager, id, te); + e_plugin_ui_enable_manager (manager, id); if (error != NULL) { g_critical ("%s: %s", G_STRFUNC, error->message); diff --git a/calendar/modules/e-cal-shell-view.c b/calendar/modules/e-cal-shell-view.c index ca6264efef..67f7d788a4 100644 --- a/calendar/modules/e-cal-shell-view.c +++ b/calendar/modules/e-cal-shell-view.c @@ -194,6 +194,7 @@ cal_shell_view_class_init (ECalShellViewClass *class, shell_view_class->label = _("Calendar"); shell_view_class->icon_name = "x-office-calendar"; shell_view_class->ui_definition = "evolution-calendars.ui"; + shell_view_class->ui_manager_id = "org.gnome.evolution.calendars"; shell_view_class->search_options = "/calendar-search-options"; shell_view_class->search_rules = "caltypes.xml"; shell_view_class->type_module = type_module; diff --git a/calendar/modules/e-memo-shell-view.c b/calendar/modules/e-memo-shell-view.c index 0237e84e27..89efd8f15d 100644 --- a/calendar/modules/e-memo-shell-view.c +++ b/calendar/modules/e-memo-shell-view.c @@ -199,6 +199,7 @@ memo_shell_view_class_init (EMemoShellViewClass *class, shell_view_class->label = _("Memos"); shell_view_class->icon_name = "evolution-memos"; shell_view_class->ui_definition = "evolution-memos.ui"; + shell_view_class->ui_manager_id = "org.gnome.evolution.memos"; shell_view_class->search_options = "/memo-search-options"; shell_view_class->search_rules = "memotypes.xml"; shell_view_class->type_module = type_module; diff --git a/calendar/modules/e-task-shell-view.c b/calendar/modules/e-task-shell-view.c index 9c893d259a..3bf84100cc 100644 --- a/calendar/modules/e-task-shell-view.c +++ b/calendar/modules/e-task-shell-view.c @@ -232,6 +232,7 @@ task_shell_view_class_init (ETaskShellViewClass *class, shell_view_class->label = _("Tasks"); shell_view_class->icon_name = "evolution-tasks"; shell_view_class->ui_definition = "evolution-tasks.ui"; + shell_view_class->ui_manager_id = "org.gnome.evolution.tasks"; shell_view_class->search_options = "/task-search-options"; shell_view_class->search_rules = "tasktypes.xml"; shell_view_class->type_module = type_module; diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c index 1fb66a03dd..3e2faf1cfe 100644 --- a/composer/e-msg-composer.c +++ b/composer/e-msg-composer.c @@ -2726,6 +2726,7 @@ msg_composer_init (EMsgComposer *composer) GtkUIManager *manager; GtkhtmlEditor *editor; GtkHTML *html; + const gchar *id; composer->priv = E_MSG_COMPOSER_GET_PRIVATE (composer); @@ -2833,8 +2834,9 @@ msg_composer_init (EMsgComposer *composer) /* Initialization may have tripped the "changed" state. */ gtkhtml_editor_set_changed (editor, FALSE); - e_plugin_ui_register_manager ( - "org.gnome.evolution.composer", manager, composer); + id = "org.gnome.evolution.composer"; + e_plugin_ui_register_manager (manager, id, composer); + e_plugin_ui_enable_manager (manager, id); } GType diff --git a/configure.in b/configure.in index 73867d042d..3797b85e4a 100644 --- a/configure.in +++ b/configure.in @@ -1773,7 +1773,7 @@ plugins_experimental="$plugins_experimental_always $IPOD_SYNC $TNEF_ATTACHMENTS all_plugins_experimental="$plugins_experimental_always ipod-sync tnef-attachments" dnl Temporary KILL-BONOBO hack -enable_plugins="addressbook-file audio-inline bbdb bogo-junk-plugin caldav calendar-file calendar-http copy-tool default-source external-editor google-account-setup hula-account-setup imap-features mail-notification mail-to-meeting profiler sa-junk-plugin save-attachments save-calendar subject-thread tnef-attachments webdav-account-setup" +enable_plugins="addressbook-file audio-inline bbdb bogo-junk-plugin caldav calendar-file calendar-http copy-tool default-source external-editor google-account-setup hula-account-setup imap-features mail-notification mail-to-meeting mark-all-read plugin-manager profiler sa-junk-plugin save-attachments save-calendar subject-thread tnef-attachments webdav-account-setup" dnl PLUGINS NOT BUILDING YET dnl ------------------------ @@ -1791,9 +1791,7 @@ dnl ipod-sync dnl itip-formatter dnl mailing-list-actions dnl mail-to-task -dnl mark-all-read dnl mono -dnl plugin-manager dnl prefer-plain dnl pst-import dnl publish-calendar diff --git a/doc/reference/shell/tmpl/e-shell-view.sgml b/doc/reference/shell/tmpl/e-shell-view.sgml index 4eff37a0eb..fb10778576 100644 --- a/doc/reference/shell/tmpl/e-shell-view.sgml +++ b/doc/reference/shell/tmpl/e-shell-view.sgml @@ -91,6 +91,7 @@ EShellView @label: @icon_name: @ui_definition: +@ui_manager_id: @search_options: @search_rules: @type_module: diff --git a/e-util/e-plugin-ui.c b/e-util/e-plugin-ui.c index 0b28adda5d..2528efd0fa 100644 --- a/e-util/e-plugin-ui.c +++ b/e-util/e-plugin-ui.c @@ -25,7 +25,6 @@ #define E_PLUGIN_UI_INIT_FUNC "e_plugin_ui_init" #define E_PLUGIN_UI_HOOK_CLASS_ID "org.gnome.evolution.ui:1.0" -#define E_PLUGIN_UI_MANAGER_ID_KEY "e-plugin-ui-manager-id" struct _EPluginUIHookPrivate { @@ -33,9 +32,11 @@ struct _EPluginUIHookPrivate { * * For example: * - * <ui-manager id="org.gnome.evolution.sample"> - * ... UI definition ... - * </ui-manager> + * <hook class="org.gnome.evolution.ui:1.0"> + * <ui-manager id="org.gnome.evolution.sample"> + * ... UI definition ... + * </ui-manager> + * </hook> * * Results in: * @@ -49,201 +50,309 @@ struct _EPluginUIHookPrivate { * optional. */ GHashTable *ui_definitions; + + /* The registry is the heart of EPluginUI. It tracks GtkUIManager + * instances, GtkUIManager IDs, and UI merge IDs as a hash table of + * hash tables: + * + * GtkUIManager instance -> GtkUIManager ID -> UI Merge ID + * + * A GtkUIManager instance and ID form a unique key for looking up + * UI merge IDs. The reason both are needed is because the same + * GtkUIManager instance and be registered under multiple IDs. + * + * This is done primarily to support shell views, which share a + * common GtkUIManager instance for a particular shell window. + * Each shell view registers the same GtkUIManager instance under + * a unique ID: + * + * "org.gnome.evolution.mail" } + * "org.gnome.evolution.contacts" } aliases for a common + * "org.gnome.evolution.calendar" } GtkUIManager instance + * "org.gnome.evolution.memos" } + * "org.gnome.evolution.tasks" } + * + * Note: The shell window also registers the same GtkUIManager + * instance as "org.gnome.evolution.shell". + * + * This way, plugins that extend a shell view's UI will follow the + * merging and unmerging of the shell view automatically. + * + * The presence or absence of GtkUIManager IDs in the registry is + * significant. Presence of a (instance, ID) pair indicates that + * UI manager is active, absence indicates inactive. Furthermore, + * a non-zero merge ID for an active UI manager indicates the + * plugin is enabled. Zero indicates disabled. + * + * Here's a quick scenario to illustrate: + * + * Suppose we have a plugin that extends the mail shell view UI. + * Its EPlugin definition file has this section: + * + * <hook class="org.gnome.evolution.ui:1.0"> + * <ui-manager id="org.gnome.evolution.mail"> + * ... UI definition ... + * </ui-manager> + * </hook> + * + * The plugin is enabled and the active shell view is "mail". + * Let "ManagerA" denote the common GtkUIManager instance for + * this shell window. Here's what happens to the registry as + * the user performs various actions; + * + * - Initial State Merge ID + * V + * { "ManagerA", { "org.gnome.evolution.mail", 3 } } + * + * - User Disables the Plugin + * + * { "ManagerA", { "org.gnome.evolution.mail", 0 } } + * + * - User Enables the Plugin + * + * { "ManagerA", { "org.gnome.evolution.mail", 4 } } + * + * - User Switches to Calendar View + * + * { "ManagerA", { } } + * + * - User Disables the Plugin + * + * { "ManagerA", { } } + * + * - User Switches to Mail View + * + * { "ManagerA", { "org.gnome.evolution.mail", 0 } } + * + * - User Enables the Plugin + * + * { "ManagerA", { "org.gnome.evolution.mail", 5 } } + */ + GHashTable *registry; }; -/* The registry is a hash table of hash tables. It maps - * - * EPluginUIHook instance --> GtkUIManager instance --> UI merge id - * - * GtkUIManager instances are automatically removed when finalized. - */ -static GHashTable *registry; static gpointer parent_class; static void -plugin_ui_registry_remove (EPluginUIHook *hook, - GtkUIManager *manager) +plugin_ui_hook_unregister_manager (EPluginUIHook *hook, + GtkUIManager *manager) { - GHashTable *hash_table; + GHashTable *registry; /* Note: Manager may already be finalized. */ - - hash_table = g_hash_table_lookup (registry, hook); - g_return_if_fail (hash_table != NULL); - - g_hash_table_remove (hash_table, manager); - if (g_hash_table_size (hash_table) == 0) - g_hash_table_remove (registry, hook); + registry = hook->priv->registry; + g_hash_table_remove (registry, manager); } static void -plugin_ui_registry_insert (EPluginUIHook *hook, - GtkUIManager *manager, - guint merge_id) +plugin_ui_hook_register_manager (EPluginUIHook *hook, + GtkUIManager *manager, + gpointer user_data) { + EPlugin *plugin; + EPluginUIInitFunc func; + GHashTable *registry; GHashTable *hash_table; - if (registry == NULL) - registry = g_hash_table_new_full ( - g_direct_hash, g_direct_equal, - (GDestroyNotify) NULL, - (GDestroyNotify) g_hash_table_destroy); + plugin = ((EPluginHook *) hook)->plugin; + func = e_plugin_get_symbol (plugin, E_PLUGIN_UI_INIT_FUNC); - hash_table = g_hash_table_lookup (registry, hook); - if (hash_table == NULL) { - hash_table = g_hash_table_new (g_direct_hash, g_direct_equal); - g_hash_table_insert (registry, hook, hash_table); - } + /* Pass the manager and user_data to the plugin's e_plugin_ui_init() + * function (if it defined one). The plugin should install whatever + * GtkActions and GtkActionGroups are neccessary to implement the + * action names in its UI definition. */ + if (func != NULL && !func (manager, user_data)) + return; g_object_weak_ref ( G_OBJECT (manager), (GWeakNotify) - plugin_ui_registry_remove, hook); + plugin_ui_hook_unregister_manager, hook); - g_hash_table_insert (hash_table, manager, GUINT_TO_POINTER (merge_id)); + registry = hook->priv->registry; + hash_table = g_hash_table_lookup (registry, manager); + + if (hash_table == NULL) { + hash_table = g_hash_table_new_full ( + g_str_hash, g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) NULL); + g_hash_table_insert (registry, manager, hash_table); + } } -/* Helper for plugin_ui_hook_merge_ui() */ -static void -plugin_ui_hook_merge_foreach (GtkUIManager *manager, - const gchar *ui_definition, - GHashTable *hash_table) +static guint +plugin_ui_hook_merge_ui (EPluginUIHook *hook, + GtkUIManager *manager, + const gchar *id) { + GHashTable *hash_table; + const gchar *ui_definition; guint merge_id; GError *error = NULL; - /* Merge the UI definition into the manager. */ + hash_table = hook->priv->ui_definitions; + ui_definition = g_hash_table_lookup (hash_table, id); + g_return_val_if_fail (ui_definition != NULL, 0); + merge_id = gtk_ui_manager_add_ui_from_string ( manager, ui_definition, -1, &error); - gtk_ui_manager_ensure_update (manager); + if (error != NULL) { g_warning ("%s", error->message); g_error_free (error); } - /* Merge ID will be 0 on error, which is what we want. */ - g_hash_table_insert (hash_table, manager, GUINT_TO_POINTER (merge_id)); + return merge_id; } static void -plugin_ui_hook_merge_ui (EPluginUIHook *hook) +plugin_ui_enable_manager (EPluginUIHook *hook, + GtkUIManager *manager, + const gchar *id) { - GHashTable *old_merge_ids; - GHashTable *new_merge_ids; - GHashTable *intermediate; + GHashTable *hash_table; + GHashTable *ui_definitions; GList *keys; - old_merge_ids = g_hash_table_lookup (registry, hook); - if (old_merge_ids == NULL) - return; + hash_table = hook->priv->registry; + hash_table = g_hash_table_lookup (hash_table, manager); - /* The GtkUIManager instances and UI definitions live in separate - * tables, so we need to build an intermediate table that we can - * easily iterate over. */ - keys = g_hash_table_get_keys (old_merge_ids); - intermediate = g_hash_table_new (g_direct_hash, g_direct_equal); + if (hash_table == NULL) + return; - while (keys != NULL) { - GtkUIManager *manager = keys->data; - gchar *ui_definition; + if (id != NULL) + keys = g_list_prepend (NULL, (gpointer) id); + else + keys = g_hash_table_get_keys (hash_table); - ui_definition = g_hash_table_lookup ( - hook->priv->ui_definitions, - e_plugin_ui_get_manager_id (manager)); + ui_definitions = hook->priv->ui_definitions; - g_hash_table_insert (intermediate, manager, ui_definition); + while (keys != NULL) { + guint merge_id; + gpointer data; + id = keys->data; keys = g_list_delete_link (keys, keys); - } - new_merge_ids = g_hash_table_new (g_direct_hash, g_direct_equal); + if (g_hash_table_lookup (ui_definitions, id) == NULL) + continue; + + data = g_hash_table_lookup (hash_table, id); + merge_id = GPOINTER_TO_UINT (data); - g_hash_table_foreach ( - intermediate, (GHFunc) - plugin_ui_hook_merge_foreach, new_merge_ids); + if (merge_id > 0) + continue; - g_hash_table_insert (registry, hook, new_merge_ids); + if (((EPluginHook *) hook)->plugin->enabled) + merge_id = plugin_ui_hook_merge_ui (hook, manager, id); - g_hash_table_destroy (intermediate); + /* Merge ID will be 0 on error, which is what we want. */ + data = GUINT_TO_POINTER (merge_id); + g_hash_table_insert (hash_table, g_strdup (id), data); + } } -/* Helper for plugin_ui_hook_unmerge_ui() */ static void -plugin_ui_hook_unmerge_foreach (GtkUIManager *manager, - gpointer value, - GHashTable *hash_table) +plugin_ui_disable_manager (EPluginUIHook *hook, + GtkUIManager *manager, + const gchar *id, + gboolean remove) { - guint merge_id; + GHashTable *hash_table; + GHashTable *ui_definitions; + GList *keys; + + hash_table = hook->priv->registry; + hash_table = g_hash_table_lookup (hash_table, manager); + + if (hash_table == NULL) + return; + + if (id != NULL) + keys = g_list_prepend (NULL, (gpointer) id); + else + keys = g_hash_table_get_keys (hash_table); + + ui_definitions = hook->priv->ui_definitions; + + while (keys != NULL) { + guint merge_id; + gpointer data; - merge_id = GPOINTER_TO_UINT (value); - gtk_ui_manager_remove_ui (manager, merge_id); + id = keys->data; + keys = g_list_delete_link (keys, keys); + + if (g_hash_table_lookup (ui_definitions, id) == NULL) + continue; + + data = g_hash_table_lookup (hash_table, id); + merge_id = GPOINTER_TO_UINT (data); + + /* Merge ID could be 0 if the plugin is disabled. */ + if (merge_id > 0) + gtk_ui_manager_remove_ui (manager, merge_id); - g_hash_table_insert (hash_table, manager, GUINT_TO_POINTER (0)); + if (remove) + g_hash_table_remove (hash_table, id); + else + g_hash_table_insert (hash_table, g_strdup (id), NULL); + } } static void -plugin_ui_hook_unmerge_ui (EPluginUIHook *hook) +plugin_ui_enable_hook (EPluginUIHook *hook) { - GHashTable *old_merge_ids; - GHashTable *new_merge_ids; - - old_merge_ids = g_hash_table_lookup (registry, hook); - if (old_merge_ids == NULL) - return; + GHashTable *hash_table; + GHashTableIter iter; + gpointer key; - new_merge_ids = g_hash_table_new (g_direct_hash, g_direct_equal); + /* Enable all GtkUIManagers for this hook. */ - g_hash_table_foreach ( - old_merge_ids, (GHFunc) - plugin_ui_hook_unmerge_foreach, new_merge_ids); + hash_table = hook->priv->registry; + g_hash_table_iter_init (&iter, hash_table); - g_hash_table_insert (registry, hook, new_merge_ids); + while (g_hash_table_iter_next (&iter, &key, NULL)) { + GtkUIManager *manager = key; + plugin_ui_enable_manager (hook, manager, NULL); + } } static void -plugin_ui_hook_register_manager (EPluginUIHook *hook, - GtkUIManager *manager, - const gchar *ui_definition, - gpointer user_data) +plugin_ui_disable_hook (EPluginUIHook *hook) { - EPlugin *plugin; - EPluginUIInitFunc func; - guint merge_id = 0; - - plugin = ((EPluginHook *) hook)->plugin; - func = e_plugin_get_symbol (plugin, E_PLUGIN_UI_INIT_FUNC); + GHashTable *hash_table; + GHashTableIter iter; + gpointer key; - /* Pass the manager and user_data to the plugin's e_plugin_ui_init() - * function (if it defined one). The plugin should install whatever - * GtkActions and GtkActionGroups are neccessary to implement the - * action names in its UI definition. */ - if (func != NULL && !func (manager, user_data)) - return; + /* Disable all GtkUIManagers for this hook. */ - if (plugin->enabled) { - GError *error = NULL; + hash_table = hook->priv->registry; + g_hash_table_iter_init (&iter, hash_table); - /* Merge the UI definition into the manager. */ - merge_id = gtk_ui_manager_add_ui_from_string ( - manager, ui_definition, -1, &error); - gtk_ui_manager_ensure_update (manager); - if (error != NULL) { - g_warning ("%s", error->message); - g_error_free (error); - } + while (g_hash_table_iter_next (&iter, &key, NULL)) { + GtkUIManager *manager = key; + plugin_ui_disable_manager (hook, manager, NULL, FALSE); } - - /* Save merge ID's for later use. */ - plugin_ui_registry_insert (hook, manager, merge_id); } static void plugin_ui_hook_finalize (GObject *object) { EPluginUIHookPrivate *priv; + GHashTableIter iter; + gpointer manager; priv = E_PLUGIN_UI_HOOK_GET_PRIVATE (object); + /* Remove weak reference callbacks to GtkUIManagers. */ + g_hash_table_iter_init (&iter, priv->registry); + while (g_hash_table_iter_next (&iter, &manager, NULL)) + g_object_weak_unref ( + G_OBJECT (manager), (GWeakNotify) + plugin_ui_hook_unregister_manager, object); + g_hash_table_destroy (priv->ui_definitions); + g_hash_table_destroy (priv->registry); /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (parent_class)->dispose (object); @@ -304,9 +413,9 @@ plugin_ui_hook_enable (EPluginHook *hook, gint state) { if (state) - plugin_ui_hook_merge_ui (E_PLUGIN_UI_HOOK (hook)); + plugin_ui_enable_hook (E_PLUGIN_UI_HOOK (hook)); else - plugin_ui_hook_unmerge_ui (E_PLUGIN_UI_HOOK (hook)); + plugin_ui_disable_hook (E_PLUGIN_UI_HOOK (hook)); } static void @@ -331,14 +440,18 @@ static void plugin_ui_hook_init (EPluginUIHook *hook) { GHashTable *ui_definitions; + GHashTable *registry; ui_definitions = g_hash_table_new_full ( g_str_hash, g_str_equal, (GDestroyNotify) g_free, (GDestroyNotify) g_free); + registry = g_hash_table_new (g_direct_hash, g_direct_equal); + hook->priv = E_PLUGIN_UI_HOOK_GET_PRIVATE (hook); hook->priv->ui_definitions = ui_definitions; + hook->priv->registry = registry; } GType @@ -368,17 +481,14 @@ e_plugin_ui_hook_get_type (void) } void -e_plugin_ui_register_manager (const gchar *id, - GtkUIManager *manager, +e_plugin_ui_register_manager (GtkUIManager *manager, + const gchar *id, gpointer user_data) { - const gchar *key = E_PLUGIN_UI_MANAGER_ID_KEY; GSList *plugin_list; - g_return_if_fail (id != NULL); g_return_if_fail (GTK_IS_UI_MANAGER (manager)); - - g_object_set_data (G_OBJECT (manager), key, (gpointer) id); + g_return_if_fail (id != NULL); /* Loop over all installed plugins. */ plugin_list = e_plugin_list_plugins (); @@ -386,36 +496,84 @@ e_plugin_ui_register_manager (const gchar *id, EPlugin *plugin = plugin_list->data; GSList *iter; + plugin_list = g_slist_next (plugin_list); + /* Look for hooks of type EPluginUIHook. */ for (iter = plugin->hooks; iter != NULL; iter = iter->next) { EPluginUIHook *hook = iter->data; - const gchar *ui_definition; + GHashTable *hash_table; if (!E_IS_PLUGIN_UI_HOOK (hook)) continue; + hash_table = hook->priv->ui_definitions; + /* Check if the hook has a UI definition * for the GtkUIManager being registered. */ - ui_definition = g_hash_table_lookup ( - hook->priv->ui_definitions, id); - if (ui_definition == NULL) + if (g_hash_table_lookup (hash_table, id) == NULL) continue; /* Register the manager with the hook. */ plugin_ui_hook_register_manager ( - hook, manager, ui_definition, user_data); + hook, manager, user_data); } + } +} + +void +e_plugin_ui_enable_manager (GtkUIManager *manager, + const gchar *id) +{ + GSList *plugin_list; + + g_return_if_fail (GTK_IS_UI_MANAGER (manager)); + g_return_if_fail (id != NULL); + + /* Loop over all installed plugins. */ + plugin_list = e_plugin_list_plugins (); + while (plugin_list != NULL) { + EPlugin *plugin = plugin_list->data; + GSList *iter; plugin_list = g_slist_next (plugin_list); + + /* Look for hooks of type EPluginUIHook. */ + for (iter = plugin->hooks; iter != NULL; iter = iter->next) { + EPluginUIHook *hook = iter->data; + + if (!E_IS_PLUGIN_UI_HOOK (hook)) + continue; + + plugin_ui_enable_manager (hook, manager, id); + } } } -const gchar * -e_plugin_ui_get_manager_id (GtkUIManager *manager) +void +e_plugin_ui_disable_manager (GtkUIManager *manager, + const gchar *id) { - const gchar *key = E_PLUGIN_UI_MANAGER_ID_KEY; + GSList *plugin_list; + + g_return_if_fail (GTK_IS_UI_MANAGER (manager)); + g_return_if_fail (id != NULL); + + /* Loop over all installed plugins. */ + plugin_list = e_plugin_list_plugins (); + while (plugin_list != NULL) { + EPlugin *plugin = plugin_list->data; + GSList *iter; - g_return_val_if_fail (GTK_IS_UI_MANAGER (manager), NULL); + plugin_list = g_slist_next (plugin_list); + + /* Look for hooks of type EPluginUIHook. */ + for (iter = plugin->hooks; iter != NULL; iter = iter->next) { + EPluginUIHook *hook = iter->data; - return g_object_get_data (G_OBJECT (manager), key); + if (!E_IS_PLUGIN_UI_HOOK (hook)) + continue; + + plugin_ui_disable_manager (hook, manager, id, TRUE); + } + } } diff --git a/e-util/e-plugin-ui.h b/e-util/e-plugin-ui.h index 00e6ed5fcf..d1a380d91e 100644 --- a/e-util/e-plugin-ui.h +++ b/e-util/e-plugin-ui.h @@ -62,10 +62,13 @@ typedef gboolean (*EPluginUIInitFunc) (GtkUIManager *manager, GType e_plugin_ui_hook_get_type (void); -void e_plugin_ui_register_manager (const gchar *id, - GtkUIManager *manager, +void e_plugin_ui_register_manager (GtkUIManager *manager, + const gchar *id, gpointer user_data); -const gchar * e_plugin_ui_get_manager_id (GtkUIManager *manager); +void e_plugin_ui_enable_manager (GtkUIManager *manager, + const gchar *id); +void e_plugin_ui_disable_manager (GtkUIManager *manager, + const gchar *id); G_END_DECLS diff --git a/mail/e-mail-shell-view.c b/mail/e-mail-shell-view.c index 5a338ab011..dbca7b479c 100644 --- a/mail/e-mail-shell-view.c +++ b/mail/e-mail-shell-view.c @@ -211,6 +211,7 @@ mail_shell_view_class_init (EMailShellViewClass *class, shell_view_class->label = _("Mail"); shell_view_class->icon_name = "evolution-mail"; shell_view_class->ui_definition = "evolution-mail.ui"; + shell_view_class->ui_manager_id = "org.gnome.evolution.mail"; shell_view_class->search_options = "/mail-search-options"; shell_view_class->search_rules = "searchtypes.xml"; shell_view_class->type_module = type_module; diff --git a/plugins/mark-all-read/Makefile.am b/plugins/mark-all-read/Makefile.am index 756e945d00..c13125c7a5 100644 --- a/plugins/mark-all-read/Makefile.am +++ b/plugins/mark-all-read/Makefile.am @@ -12,7 +12,7 @@ liborg_gnome_mark_all_read_la_SOURCES = mark-all-read.c liborg_gnome_mark_all_read_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED) liborg_gnome_mark_all_read_la_LIBADD = \ $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/mail/libevolution-mail.la \ + $(top_builddir)/mail/libevolution-module-mail.la \ $(EVOLUTION_MAIL_LIBS) EXTRA_DIST = org-gnome-mark-all-read.eplug.xml diff --git a/plugins/mark-all-read/mark-all-read.c b/plugins/mark-all-read/mark-all-read.c index c9ea67ca61..c98b33edd1 100644 --- a/plugins/mark-all-read/mark-all-read.c +++ b/plugins/mark-all-read/mark-all-read.c @@ -28,20 +28,27 @@ #include <glib.h> #include <gtk/gtk.h> #include <glib/gi18n.h> -#include <e-util/e-config.h> -#include <mail/em-popup.h> +#include <e-util/e-plugin-ui.h> +#include <mail/e-mail-shell-sidebar.h> +#include <mail/em-folder-tree.h> #include <mail/mail-ops.h> #include <mail/mail-mt.h> #include <camel/camel-vee-folder.h> #include "e-util/e-error.h" +#include <shell/e-shell-sidebar.h> +#include <shell/e-shell-window.h> +#include <shell/e-shell-window-actions.h> + #define PRIMARY_TEXT \ N_("Also mark messages in subfolders?") #define SECONDARY_TEXT \ N_("Do you want to mark messages as read in the current folder " \ "only, or in the current folder as well as all subfolders?") -void org_gnome_mark_all_read (EPlugin *ep, EMPopupTargetFolder *target); +gboolean e_plugin_ui_init (GtkUIManager *manager, + EShellView *shell_view); + static void mar_got_folder (char *uri, CamelFolder *folder, void *data); static void mar_all_sub_folders (CamelStore *store, CamelFolderInfo *fi, CamelException *ex); @@ -190,16 +197,6 @@ prompt_user (void) return response; } -void -org_gnome_mark_all_read (EPlugin *ep, EMPopupTargetFolder *t) -{ - if (t->uri == NULL) { - return; - } - - mail_get_folder(t->uri, 0, mar_got_folder, NULL, mail_msg_unordered_push); -} - static void mark_all_as_read (CamelFolder *folder) { @@ -270,3 +267,52 @@ mar_all_sub_folders (CamelStore *store, CamelFolderInfo *fi, CamelException *ex) fi = fi->next; } } + +static void +action_mail_mark_read_recursive_cb (GtkAction *action, + EShellView *shell_view) +{ + EMailShellSidebar *mail_shell_sidebar; + EShellSidebar *shell_sidebar; + EMFolderTree *folder_tree; + const gchar *folder_uri; + + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); + g_return_if_fail (E_IS_MAIL_SHELL_SIDEBAR (shell_sidebar)); + + mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar); + folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); + folder_uri = em_folder_tree_get_selected_uri (folder_tree); + g_return_if_fail (folder_uri != NULL); + + mail_get_folder ( + folder_uri, 0, mar_got_folder, NULL, mail_msg_unordered_push); +} + +static GtkActionEntry entries[] = { + + { "mail-mark-read-recursive", + "mail-mark-read", + N_("Mark Me_ssages as Read"), + NULL, + NULL, /* XXX Add a tooltip! */ + G_CALLBACK (action_mail_mark_read_recursive_cb) } +}; + +gboolean +e_plugin_ui_init (GtkUIManager *manager, + EShellView *shell_view) +{ + EShellWindow *shell_window; + GtkActionGroup *action_group; + + shell_window = e_shell_view_get_shell_window (shell_view); + action_group = E_SHELL_WINDOW_ACTION_GROUP_SHELL (shell_window); + + /* Add actions to the "shell" action group. */ + gtk_action_group_add_actions ( + action_group, entries, + G_N_ELEMENTS (entries), shell_view); + + return TRUE; +} diff --git a/plugins/mark-all-read/org-gnome-mark-all-read.eplug.xml b/plugins/mark-all-read/org-gnome-mark-all-read.eplug.xml index a4542572a5..76c0864fa1 100644 --- a/plugins/mark-all-read/org-gnome-mark-all-read.eplug.xml +++ b/plugins/mark-all-read/org-gnome-mark-all-read.eplug.xml @@ -1,18 +1,21 @@ <?xml version="1.0"?> <e-plugin-list> - <e-plugin - id="org.gnome.evolution.mail.folder.mark_all_read" - type="shlib" - domain="@GETTEXT_PACKAGE@" - _name="Mark All Read" - location="@PLUGINDIR@/liborg-gnome-mark-all-read@SOEXT@"> - <author name="Chenthill Palanisamy" email="pchenthill@novell.com"/> - <_description>Used for marking all the messages under a folder as read</_description> + <e-plugin id="org.gnome.evolution.mail.folder.mark_all_read" + type="shlib" + domain="@GETTEXT_PACKAGE@" + _name="Mark All Read" + location="@PLUGINDIR@/liborg-gnome-mark-all-read@SOEXT@"> + <author name="Chenthill Palanisamy" email="pchenthill@novell.com"/> + <_description>Used for marking all the messages under a folder as read</_description> - <hook class="org.gnome.evolution.mail.popup:1.0"> - <menu id="org.gnome.evolution.mail.foldertree.popup" target="folder"> - <item type="item" path="30.emc.01" icon="mail-mark-read" _label="Mark Me_ssages as Read" activate="org_gnome_mark_all_read" enable="folder" visible="folder"/> - </menu> - </hook> - </e-plugin> + <hook class="org.gnome.evolution.ui:1.0"> + <ui-manager id="org.gnome.evolution.mail"> + <popup name="mail-folder-popup"> + <placeholder name="mail-folder-popup-actions"> + <menuitem action="mail-mark-read-recursive"/> + </placeholder> + </popup> + </ui-manager> + </hook> + </e-plugin> </e-plugin-list> diff --git a/plugins/plugin-manager/Makefile.am b/plugins/plugin-manager/Makefile.am index f9d6642521..22e4ca7d51 100644 --- a/plugins/plugin-manager/Makefile.am +++ b/plugins/plugin-manager/Makefile.am @@ -4,7 +4,7 @@ INCLUDES = \ @EVO_PLUGIN_RULE@ -plugin_DATA = org-gnome-plugin-manager.eplug org-gnome-plugin-manager.xml +plugin_DATA = org-gnome-plugin-manager.eplug plugin_LTLIBRARIES = liborg-gnome-plugin-manager.la liborg_gnome_plugin_manager_la_SOURCES = plugin-manager.c @@ -13,9 +13,8 @@ liborg_gnome_plugin_manager_la_LIBADD = \ $(top_builddir)/e-util/libeutil.la \ $(EVOLUTION_MAIL_LIBS) -EXTRA_DIST = \ - org-gnome-plugin-manager.eplug.xml \ - org-gnome-plugin-manager.xml +EXTRA_DIST = \ + org-gnome-plugin-manager.eplug.xml BUILT_SOURCES = org-gnome-plugin-manager.eplug diff --git a/plugins/plugin-manager/org-gnome-plugin-manager.eplug.xml b/plugins/plugin-manager/org-gnome-plugin-manager.eplug.xml index d8e4849f2f..c931b5c968 100644 --- a/plugins/plugin-manager/org-gnome-plugin-manager.eplug.xml +++ b/plugins/plugin-manager/org-gnome-plugin-manager.eplug.xml @@ -6,18 +6,19 @@ location="@PLUGINDIR@/liborg-gnome-plugin-manager@SOEXT@" _name="Plugin Manager" system_plugin="true"> - <_description>A plugin for managing which plugins are enabled or disabled.</_description> <author name="Michael Zucchi" email="notzed@ximian.com"/> - <hook class="org.gnome.evolution.shell.bonobomenu:1.0"> - <menu id="org.gnome.evolution.shell" target="shell"> - <!-- the path to the bonobo menu description --> - <ui file="@PLUGINDIR@/org-gnome-plugin-manager.xml"/> - <item - type="item" - verb="EPluginManagerManage" - path="/commands/EPluginManagerManage" - activate="org_gnome_plugin_manager_manage"/> - </menu> + <_description>A plugin for managing which plugins are enabled or disabled.</_description> + + <hook class="org.gnome.evolution.ui:1.0"> + <ui-manager id="org.gnome.evolution.shell"> + <menubar name="main-menu"> + <menu action="edit-menu"> + <placeholder name="administrative-actions"> + <menuitem action="plugin-manager"/> + </placeholder> + </menu> + </menubar> + </ui-manager> </hook> </e-plugin> </e-plugin-list> diff --git a/plugins/plugin-manager/org-gnome-plugin-manager.xml b/plugins/plugin-manager/org-gnome-plugin-manager.xml deleted file mode 100644 index 3f74a2dd4c..0000000000 --- a/plugins/plugin-manager/org-gnome-plugin-manager.xml +++ /dev/null @@ -1,15 +0,0 @@ -<Root> - <commands> - <cmd name="EPluginManagerManage" _label="_Plugins" - _tip="Enable and disable plugins"/> - </commands> - - <menu> - <submenu name="Edit"> - <placeholder name="PluginManagerPlaceholder"> - <menuitem name="EPluginManagerManage" verb=""/> - </placeholder> - </submenu> - - </menu> -</Root> diff --git a/plugins/plugin-manager/plugin-manager.c b/plugins/plugin-manager/plugin-manager.c index 19af3eeb7e..129ff0a74f 100644 --- a/plugins/plugin-manager/plugin-manager.c +++ b/plugins/plugin-manager/plugin-manager.c @@ -32,7 +32,8 @@ #include <stdio.h> #include "e-util/e-plugin.h" -#include "shell/es-menu.h" +#include "shell/e-shell-window.h" +#include "shell/e-shell-window-actions.h" #define d(S) (S) @@ -61,7 +62,6 @@ static struct { typedef struct _Manager Manager; struct _Manager { - GtkDialog *dialog; GtkTreeView *treeview; GtkTreeModel *model; @@ -75,13 +75,13 @@ struct _Manager { }; /* for tracking if we're shown */ -static GtkDialog *dialog; static GtkWidget *notebook; static GtkWidget *configure_page; static gint last_selected_page; static gulong switch_page_handler_id; -void org_gnome_plugin_manager_manage(void *ep, ESMenuTargetShell *t); +gboolean e_plugin_ui_init (GtkUIManager *manager, + EShellWindow *shell_window); static void eppm_set_label (GtkLabel *l, const char *v) @@ -221,19 +221,15 @@ eppm_free (void *data) } static void -eppm_response (GtkDialog *w, int button, Manager *m) -{ - gtk_widget_destroy (GTK_WIDGET (w)); - dialog = NULL; -} - -void -org_gnome_plugin_manager_manage (void *ep, ESMenuTargetShell *t) +action_plugin_manager_cb (GtkAction *action, + EShellWindow *shell_window) { Manager *m; int i; + GtkWidget *dialog; GtkWidget *hbox, *w; GtkWidget *overview_page; + GtkWidget *content_area; GtkListStore *store; GtkTreeSelection *selection; GtkCellRenderer *renderer; @@ -241,26 +237,23 @@ org_gnome_plugin_manager_manage (void *ep, ESMenuTargetShell *t) char *string; GtkWidget *subvbox; - if (dialog) { - gtk_window_present (GTK_WINDOW (dialog)); - return; - } - m = g_malloc0 (sizeof (*m)); /* Setup the ui */ - m->dialog = GTK_DIALOG (gtk_dialog_new_with_buttons (_("Plugin Manager"), - GTK_WINDOW (gtk_widget_get_toplevel (t->target.widget)), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, - NULL)); + dialog = gtk_dialog_new_with_buttons ( + _("Plugin Manager"), + GTK_WINDOW (shell_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); + + content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); - gtk_window_set_default_size (GTK_WINDOW (m->dialog), 640, 400); - g_object_set (G_OBJECT (m->dialog), "has_separator", FALSE, NULL); + gtk_window_set_default_size (GTK_WINDOW (dialog), 640, 400); + g_object_set (dialog, "has_separator", FALSE, NULL); hbox = gtk_hbox_new (FALSE, 0); gtk_container_set_border_width (GTK_CONTAINER (hbox), 12); - gtk_box_pack_start (GTK_BOX (m->dialog->vbox), hbox, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 0); string = g_strdup_printf ("<i>%s</i>", _("Note: Some changes will not take effect until restart")); @@ -272,7 +265,7 @@ org_gnome_plugin_manager_manage (void *ep, ESMenuTargetShell *t) gtk_widget_show (w); g_free (string); - gtk_box_pack_start (GTK_BOX (m->dialog->vbox), w, FALSE, TRUE, 6); + gtk_box_pack_start (GTK_BOX (content_area), w, FALSE, TRUE, 6); notebook = gtk_notebook_new (); gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), TRUE); @@ -423,24 +416,34 @@ org_gnome_plugin_manager_manage (void *ep, ESMenuTargetShell *t) atk_object_set_name (gtk_widget_get_accessible (GTK_WIDGET (m->treeview)), _("Plugin")); - g_object_set_data_full (G_OBJECT (m->dialog), "plugin-manager", m, eppm_free); - g_signal_connect (m->dialog, "response", G_CALLBACK (eppm_response), m); - - dialog = m->dialog; + gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_show (GTK_WIDGET (m->dialog)); + gtk_widget_destroy (dialog); + eppm_free (m); } -int e_plugin_lib_enable (EPluginLib *ep, int enable); +static GtkActionEntry entries[] = { -int -e_plugin_lib_enable (EPluginLib *ep, int enable) + { "plugin-manager", + NULL, + N_("_Plugins"), + NULL, + N_("Enable and disable plugins"), + G_CALLBACK (action_plugin_manager_cb) } +}; + +gboolean +e_plugin_ui_init (GtkUIManager *manager, + EShellWindow *shell_window) { - if (enable) { - } else { - /* This plugin can't be disabled ... */ - return -1; - } + GtkActionGroup *action_group; + + action_group = E_SHELL_WINDOW_ACTION_GROUP_SHELL (shell_window); + + /* Add actions to the "shell" action group. */ + gtk_action_group_add_actions ( + action_group, entries, + G_N_ELEMENTS (entries), shell_window); - return 0; + return TRUE; } diff --git a/shell/e-shell-view.c b/shell/e-shell-view.c index f1f1ffb476..d7a564c567 100644 --- a/shell/e-shell-view.c +++ b/shell/e-shell-view.c @@ -25,6 +25,7 @@ #include <glib/gi18n.h> #include "e-util/e-util.h" +#include "e-util/e-plugin-ui.h" #include "e-shell-content.h" #include "e-shell-module.h" @@ -76,7 +77,7 @@ static gpointer parent_class; static gulong signals[LAST_SIGNAL]; static void -shell_view_init_view_collection (EShellViewClass *shell_view_class) +shell_view_init_view_collection (EShellViewClass *class) { EShellModule *shell_module; const gchar *base_dir; @@ -84,8 +85,8 @@ shell_view_init_view_collection (EShellViewClass *shell_view_class) gchar *system_dir; gchar *local_dir; - shell_module = E_SHELL_MODULE (shell_view_class->type_module); - module_name = shell_view_class->type_module->name; + shell_module = E_SHELL_MODULE (class->type_module); + module_name = class->type_module->name; base_dir = EVOLUTION_GALVIEWSDIR; system_dir = g_build_filename (base_dir, module_name, NULL); @@ -94,15 +95,13 @@ shell_view_init_view_collection (EShellViewClass *shell_view_class) local_dir = g_build_filename (base_dir, "views", NULL); /* The view collection is never destroyed. */ - shell_view_class->view_collection = gal_view_collection_new (); + class->view_collection = gal_view_collection_new (); gal_view_collection_set_title ( - shell_view_class->view_collection, - shell_view_class->label); + class->view_collection, class->label); gal_view_collection_set_storage_directories ( - shell_view_class->view_collection, - system_dir, local_dir); + class->view_collection, system_dir, local_dir); g_free (system_dir); g_free (local_dir); @@ -319,13 +318,22 @@ shell_view_finalize (GObject *object) static void shell_view_constructed (GObject *object) { + EShellWindow *shell_window; EShellView *shell_view; EShellViewClass *class; + GtkUIManager *ui_manager; GtkWidget *widget; + const gchar *id; shell_view = E_SHELL_VIEW (object); class = E_SHELL_VIEW_GET_CLASS (object); + shell_window = e_shell_view_get_shell_window (shell_view); + ui_manager = e_shell_window_get_ui_manager (shell_window); + id = class->ui_manager_id; + + e_plugin_ui_register_manager (ui_manager, id, shell_view); + /* Invoke factory methods. */ widget = class->new_shell_content (shell_view); @@ -345,21 +353,24 @@ static void shell_view_toggled (EShellView *shell_view) { EShellViewPrivate *priv = shell_view->priv; - EShellViewClass *shell_view_class; + EShellViewClass *class; EShellWindow *shell_window; GtkUIManager *ui_manager; const gchar *basename; gboolean view_is_active; - shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + class = E_SHELL_VIEW_GET_CLASS (shell_view); shell_window = e_shell_view_get_shell_window (shell_view); ui_manager = e_shell_window_get_ui_manager (shell_window); view_is_active = e_shell_view_is_active (shell_view); - basename = shell_view_class->ui_definition; + basename = class->ui_definition; - if (view_is_active && priv->merge_id == 0) + if (view_is_active && priv->merge_id == 0) { priv->merge_id = e_load_ui_definition (ui_manager, basename); - else if (!view_is_active && priv->merge_id != 0) { + e_plugin_ui_enable_manager (ui_manager, class->ui_manager_id); + + } else if (!view_is_active && priv->merge_id != 0) { + e_plugin_ui_disable_manager (ui_manager, class->ui_manager_id); gtk_ui_manager_remove_ui (ui_manager, priv->merge_id); priv->merge_id = 0; } @@ -581,7 +592,7 @@ shell_view_class_init (EShellViewClass *class) static void shell_view_init (EShellView *shell_view, - EShellViewClass *shell_view_class) + EShellViewClass *class) { GtkSizeGroup *size_group; @@ -590,8 +601,8 @@ shell_view_init (EShellView *shell_view, shell_view->priv = E_SHELL_VIEW_GET_PRIVATE (shell_view); shell_view->priv->size_group = size_group; - if (shell_view_class->view_collection == NULL) - shell_view_init_view_collection (shell_view_class); + if (class->view_collection == NULL) + shell_view_init_view_collection (class); } GType @@ -785,17 +796,17 @@ e_shell_view_get_shell_window (EShellView *shell_view) EShellModule * e_shell_view_get_shell_module (EShellView *shell_view) { - EShellViewClass *shell_view_class; + EShellViewClass *class; g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); /* Calling this function during the shell view's instance * initialization function will return the wrong result, * so watch for that and emit a warning. */ - shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); - g_return_val_if_fail (E_IS_SHELL_VIEW_CLASS (shell_view_class), NULL); + class = E_SHELL_VIEW_GET_CLASS (shell_view); + g_return_val_if_fail (E_IS_SHELL_VIEW_CLASS (class), NULL); - return E_SHELL_MODULE (shell_view_class->type_module); + return E_SHELL_MODULE (class->type_module); } /** @@ -1018,15 +1029,15 @@ GalViewInstance * e_shell_view_new_view_instance (EShellView *shell_view, const gchar *instance_id) { - EShellViewClass *shell_view_class; + EShellViewClass *class; GalViewCollection *view_collection; GalViewInstance *view_instance; g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); + class = E_SHELL_VIEW_GET_CLASS (shell_view); - view_collection = shell_view_class->view_collection; + view_collection = class->view_collection; view_instance = gal_view_instance_new (view_collection, instance_id); g_signal_connect_swapped ( diff --git a/shell/e-shell-view.h b/shell/e-shell-view.h index 3159b5a71b..78987d9db6 100644 --- a/shell/e-shell-view.h +++ b/shell/e-shell-view.h @@ -85,6 +85,9 @@ struct _EShellView { * e_shell_view_get_action(). * @ui_definition: Base name of the UI definintion file to add * when the shell view is activated. + * @ui_manager_id: The #GtkUIManager ID for #EPluginUI. Plugins + * should use to this ID in their "eplug" files to + * add menu and toolbar items to the shell view. * @search_options: Widget path in the UI definition to the search * options popup menu. The menu gets shown when the * user clicks the "find" icon in the search entry. @@ -129,6 +132,9 @@ struct _EShellViewClass { /* Base name of the UI definition file. */ const gchar *ui_definition; + /* GtkUIManager ID for use with EPluginUI. */ + const gchar *ui_manager_id; + /* Widget path to the search options popup menu. */ const gchar *search_options; diff --git a/shell/e-shell-window.c b/shell/e-shell-window.c index 2a9adc67ac..53074d2352 100644 --- a/shell/e-shell-window.c +++ b/shell/e-shell-window.c @@ -353,6 +353,7 @@ static void shell_window_init (EShellWindow *shell_window) { GtkUIManager *ui_manager; + const gchar *id; shell_window->priv = E_SHELL_WINDOW_GET_PRIVATE (shell_window); @@ -362,8 +363,9 @@ shell_window_init (EShellWindow *shell_window) ui_manager = e_shell_window_get_ui_manager (shell_window); - e_plugin_ui_register_manager ( - "org.gnome.evolution.shell", ui_manager, shell_window); + id = "org.gnome.evolution.shell"; + e_plugin_ui_register_manager (ui_manager, id, shell_window); + e_plugin_ui_enable_manager (ui_manager, id); } GType diff --git a/ui/evolution-mail.ui b/ui/evolution-mail.ui index 5369802139..c8a9960d72 100644 --- a/ui/evolution-mail.ui +++ b/ui/evolution-mail.ui @@ -74,6 +74,7 @@ <separator/> <menuitem action='mail-popup-folder-delete'/> <separator/> + <placeholder name='mail-folder-popup-actions'/> <menuitem action='mail-popup-folder-rename'/> <menuitem action='mail-popup-folder-refresh'/> <menuitem action='mail-popup-flush-outbox'/> diff --git a/widgets/menus/gal-view-instance.c b/widgets/menus/gal-view-instance.c index a1eac04b6c..19ec402fa3 100644 --- a/widgets/menus/gal-view-instance.c +++ b/widgets/menus/gal-view-instance.c @@ -46,10 +46,6 @@ G_DEFINE_TYPE (GalViewInstance, gal_view_instance, G_TYPE_OBJECT) -static const EPopupMenu separator = E_POPUP_SEPARATOR; -static const EPopupMenu terminator = E_POPUP_TERMINATOR; - - #define d(x) enum { @@ -467,140 +463,3 @@ gal_view_instance_exists (GalViewInstance *instance) return FALSE; } - -typedef struct { - GalViewInstance *instance; - char *id; -} ListenerClosure; - -static void -view_item_cb (GtkWidget *widget, - gpointer user_data) -{ - ListenerClosure *closure = user_data; - - if (GTK_CHECK_MENU_ITEM (widget)->active) { - gal_view_instance_set_current_view_id (closure->instance, closure->id); - } -} - -static void -add_popup_radio_item (EPopupMenu *menu_item, - gchar *title, - GCallback fn, - gpointer closure, - gboolean value) -{ - EPopupMenu menu_item_struct = - E_POPUP_RADIO_ITEM_CC (title, - fn, - closure, - 0, - 0); - menu_item_struct.is_active = value; - - e_popup_menu_copy_1 (menu_item, &menu_item_struct); -} - -static void -add_popup_menu_item (EPopupMenu *menu_item, - gchar *title, - GCallback fn, - gpointer closure) -{ - EPopupMenu menu_item_struct = - E_POPUP_ITEM_CC (title, - fn, - closure, - 0); - - e_popup_menu_copy_1 (menu_item, &menu_item_struct); -} - -static void -define_views_dialog_response(GtkWidget *dialog, int id, GalViewInstance *instance) -{ - if (id == GTK_RESPONSE_OK) { - gal_view_collection_save(instance->collection); - } - gtk_widget_destroy (dialog); -} - -static void -define_views_cb(GtkWidget *widget, - GalViewInstance *instance) -{ - GtkWidget *dialog = gal_define_views_dialog_new(instance->collection); - g_signal_connect(dialog, "response", - G_CALLBACK(define_views_dialog_response), instance); - gtk_widget_show(dialog); -} - -static void -save_current_view_cb(GtkWidget *widget, - GalViewInstance *instance) -{ - gal_view_instance_save_as (instance); -} - -EPopupMenu * -gal_view_instance_get_popup_menu (GalViewInstance *instance) -{ - EPopupMenu *ret_val; - int length; - int i; - gboolean found = FALSE; - char *id; - - length = gal_view_collection_get_count(instance->collection); - id = gal_view_instance_get_current_view_id (instance); - - ret_val = g_new (EPopupMenu, length + 6); - - for (i = 0; i < length; i++) { - gboolean value = FALSE; - GalViewCollectionItem *item = gal_view_collection_get_view_item(instance->collection, i); - ListenerClosure *closure; - - closure = g_new (ListenerClosure, 1); - closure->instance = instance; - closure->id = item->id; - g_object_ref (closure->instance); - - if (!found && id && !strcmp (id, item->id)) { - found = TRUE; - value = TRUE; - } - - add_popup_radio_item (ret_val + i, item->title, G_CALLBACK (view_item_cb), closure, value); - } - - if (!found) { - e_popup_menu_copy_1 (ret_val + i++, &separator); - - add_popup_radio_item (ret_val + i++, N_("Custom View"), NULL, NULL, TRUE); - add_popup_menu_item (ret_val + i++, N_("Save Custom View"), G_CALLBACK (save_current_view_cb), instance); - } - - e_popup_menu_copy_1 (ret_val + i++, &separator); - add_popup_menu_item (ret_val + i++, N_("Define Views..."), G_CALLBACK (define_views_cb), instance); - e_popup_menu_copy_1 (ret_val + i++, &terminator); - - if (id) - g_free (id); - - return ret_val; -} - -void -gal_view_instance_free_popup_menu (GalViewInstance *instance, EPopupMenu *menu) -{ - int i; - /* This depends on the first non-custom closure to be a separator or a terminator. */ - for (i = 0; menu[i].name && *(menu[i].name); i++) { - g_object_unref (((ListenerClosure *)(menu[i].closure))->instance); - g_free (menu[i].closure); - } - - e_popup_menu_free (menu); -} diff --git a/widgets/menus/gal-view-instance.h b/widgets/menus/gal-view-instance.h index 37c8ad6869..096cc2b967 100644 --- a/widgets/menus/gal-view-instance.h +++ b/widgets/menus/gal-view-instance.h @@ -26,7 +26,6 @@ #include <glib-object.h> #include <widgets/menus/gal-view-collection.h> -#include <misc/e-popup-menu.h> G_BEGIN_DECLS @@ -107,10 +106,6 @@ const char *gal_view_instance_get_default_view (GalViewInstance *inst void gal_view_instance_set_default_view (GalViewInstance *instance, const char *id); -EPopupMenu *gal_view_instance_get_popup_menu (GalViewInstance *instance); -void gal_view_instance_free_popup_menu (GalViewInstance *instance, - EPopupMenu *menu); - G_END_DECLS #endif /* _GAL_VIEW_INSTANCE_H_ */ |