aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--shell/e-shell-module.c74
-rw-r--r--shell/e-shell-module.h17
-rw-r--r--shell/e-shell-registry.c31
-rw-r--r--shell/e-shell-registry.h2
-rw-r--r--shell/e-shell-view.c238
-rw-r--r--shell/e-shell-view.h16
-rw-r--r--shell/e-shell-window-actions.c196
-rw-r--r--shell/e-shell-window-private.c14
-rw-r--r--shell/e-shell-window-private.h5
-rw-r--r--shell/e-shell-window.c180
-rw-r--r--shell/e-shell-window.h29
-rw-r--r--shell/e-shell.c1
-rw-r--r--shell/test/e-test-shell-module.c26
-rw-r--r--shell/test/e-test-shell-view.c10
14 files changed, 478 insertions, 361 deletions
diff --git a/shell/e-shell-module.c b/shell/e-shell-module.c
index e969bbe382..5efddd532c 100644
--- a/shell/e-shell-module.c
+++ b/shell/e-shell-module.c
@@ -237,21 +237,17 @@ e_shell_module_get_filename (EShellModule *shell_module)
return shell_module->priv->filename;
}
-GType
-e_shell_module_get_view_type (EShellModule *shell_module)
-{
- g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), 0);
-
- return shell_module->priv->info.shell_view_type;
-}
-
gboolean
e_shell_module_is_busy (EShellModule *shell_module)
{
+ EShellModuleInfo *module_info;
+
g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), FALSE);
- if (shell_module->priv->info.is_busy != NULL)
- return shell_module->priv->info.is_busy ();
+ module_info = &shell_module->priv->info;
+
+ if (module_info->is_busy != NULL)
+ return module_info->is_busy (shell_module);
return FALSE;
}
@@ -259,10 +255,14 @@ e_shell_module_is_busy (EShellModule *shell_module)
gboolean
e_shell_module_shutdown (EShellModule *shell_module)
{
+ EShellModuleInfo *module_info;
+
g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), TRUE);
- if (shell_module->priv->info.shutdown != NULL)
- return shell_module->priv->info.shutdown ();
+ module_info = &shell_module->priv->info;
+
+ if (module_info->shutdown != NULL)
+ return module_info->shutdown (shell_module);
return TRUE;
}
@@ -271,11 +271,15 @@ gboolean
e_shell_module_handle_uri (EShellModule *shell_module,
const gchar *uri)
{
+ EShellModuleInfo *module_info;
+
g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), FALSE);
g_return_val_if_fail (uri != NULL, FALSE);
- if (shell_module->priv->info.handle_uri != NULL)
- return shell_module->priv->info.handle_uri (uri);
+ module_info = &shell_module->priv->info;
+
+ if (module_info->handle_uri != NULL)
+ return module_info->handle_uri (shell_module, uri);
return FALSE;
}
@@ -283,37 +287,55 @@ e_shell_module_handle_uri (EShellModule *shell_module,
void
e_shell_module_send_and_receive (EShellModule *shell_module)
{
+ EShellModuleInfo *module_info;
+
g_return_if_fail (E_IS_SHELL_MODULE (shell_module));
- if (shell_module->priv->info.send_and_receive != NULL)
- shell_module->priv->info.send_and_receive ();
+ module_info = &shell_module->priv->info;
+
+ if (module_info->send_and_receive != NULL)
+ module_info->send_and_receive (shell_module);
}
void
e_shell_module_window_created (EShellModule *shell_module,
EShellWindow *shell_window)
{
+ EShellModuleInfo *module_info;
+
g_return_if_fail (E_IS_SHELL_MODULE (shell_module));
g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
- if (shell_module->priv->info.window_created != NULL)
- shell_module->priv->info.window_created (shell_window);
+ module_info = &shell_module->priv->info;
+
+ if (module_info->window_created != NULL)
+ module_info->window_created (shell_module, shell_window);
}
void
e_shell_module_set_info (EShellModule *shell_module,
const EShellModuleInfo *info)
{
+ GTypeModule *module;
+ EShellModuleInfo *module_info;
+
g_return_if_fail (E_IS_SHELL_MODULE (shell_module));
g_return_if_fail (info != NULL);
- shell_module->priv->info.sort_order = info->sort_order;
- shell_module->priv->info.aliases = g_intern_string (info->aliases);
- shell_module->priv->info.schemes = g_intern_string (info->schemes);
- shell_module->priv->info.shell_view_type = info->shell_view_type;
+ module = G_TYPE_MODULE (shell_module);
+ module_info = &shell_module->priv->info;
+
+ /* A module name is required. */
+ g_return_if_fail (info->name != NULL);
+ module_info->name = g_intern_string (info->name);
+ g_type_module_set_name (module, module_info->name);
+
+ module_info->aliases = g_intern_string (info->aliases);
+ module_info->schemes = g_intern_string (info->schemes);
+ module_info->sort_order = info->sort_order;
- shell_module->priv->info.is_busy = info->is_busy;
- shell_module->priv->info.shutdown = info->shutdown;
- shell_module->priv->info.send_and_receive = info->send_and_receive;
- shell_module->priv->info.window_created = info->window_created;
+ module_info->is_busy = info->is_busy;
+ module_info->shutdown = info->shutdown;
+ module_info->send_and_receive = info->send_and_receive;
+ module_info->window_created = info->window_created;
}
diff --git a/shell/e-shell-module.h b/shell/e-shell-module.h
index 7ea9dee4ef..c1bbf6b594 100644
--- a/shell/e-shell-module.h
+++ b/shell/e-shell-module.h
@@ -51,16 +51,18 @@ typedef struct _EShellModuleClass EShellModuleClass;
typedef struct _EShellModulePrivate EShellModulePrivate;
struct _EShellModuleInfo {
- gint sort_order;
+ const gchar *name;
const gchar *aliases; /* colon-separated list */
const gchar *schemes; /* colon-separated list */
- GType shell_view_type; /* EShellView subclass */
+ gint sort_order;
- gboolean (*is_busy) (void);
- gboolean (*shutdown) (void);
- gboolean (*handle_uri) (const gchar *uri);
- void (*send_and_receive) (void);
- void (*window_created) (EShellWindow *window);
+ gboolean (*is_busy) (EShellModule *shell_module);
+ gboolean (*shutdown) (EShellModule *shell_module);
+ gboolean (*handle_uri) (EShellModule *shell_module,
+ const gchar *uri);
+ void (*send_and_receive) (EShellModule *shell_module);
+ void (*window_created) (EShellModule *shell_module,
+ EShellWindow *shell_window);
};
struct _EShellModule {
@@ -77,7 +79,6 @@ EShellModule * e_shell_module_new (const gchar *filename);
gint e_shell_module_compare (EShellModule *shell_module_a,
EShellModule *shell_module_b);
const gchar * e_shell_module_get_filename (EShellModule *shell_module);
-GType e_shell_module_get_view_type (EShellModule *shell_module);
gboolean e_shell_module_is_busy (EShellModule *shell_module);
gboolean e_shell_module_shutdown (EShellModule *shell_module);
gboolean e_shell_module_handle_uri (EShellModule *shell_module,
diff --git a/shell/e-shell-registry.c b/shell/e-shell-registry.c
index 91f489111a..14808ebb01 100644
--- a/shell/e-shell-registry.c
+++ b/shell/e-shell-registry.c
@@ -66,7 +66,7 @@ shell_registry_query_module (const gchar *filename)
info = (EShellModuleInfo *) shell_module->priv;
- if ((string = G_TYPE_MODULE (shell_module)->name) != NULL)
+ if ((string = info->name) != NULL)
g_hash_table_insert (
modules_by_name, (gpointer)
g_intern_string (string), shell_module);
@@ -122,32 +122,19 @@ e_shell_registry_list_modules (void)
return loaded_modules;
}
-GType *
-e_shell_registry_get_view_types (guint *n_types)
+const gchar *
+e_shell_registry_get_canonical_name (const gchar *name)
{
- GType *types;
- GList *iter;
- guint ii = 0;
-
- types = g_new0 (GType, g_list_length (loaded_modules) + 1);
-
- for (iter = loaded_modules; iter != NULL; iter = iter->next) {
- EShellModule *shell_module = iter->data;
- EShellModuleInfo *info;
-
- info = (EShellModuleInfo *) shell_module->priv;
+ EShellModule *shell_module;
- /* Allow for modules with no corresponding view type. */
- if (!g_type_is_a (info->shell_view_type, E_TYPE_SHELL_VIEW))
- continue;
+ g_return_val_if_fail (name != NULL, NULL);
- types[ii++] = info->shell_view_type;
- }
+ shell_module = e_shell_registry_get_module_by_name (name);
- if (n_types != NULL)
- *n_types = ii;
+ if (shell_module == NULL)
+ return NULL;
- return types;
+ return G_TYPE_MODULE (shell_module)->name;
}
EShellModule *
diff --git a/shell/e-shell-registry.h b/shell/e-shell-registry.h
index ad86a94797..335e5e1c3f 100644
--- a/shell/e-shell-registry.h
+++ b/shell/e-shell-registry.h
@@ -28,7 +28,7 @@ G_BEGIN_DECLS
void e_shell_registry_init (void);
GList * e_shell_registry_list_modules (void);
-GType * e_shell_registry_get_view_types (guint *n_types);
+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);
diff --git a/shell/e-shell-view.c b/shell/e-shell-view.c
index 1187c17ee4..52f6479b18 100644
--- a/shell/e-shell-view.c
+++ b/shell/e-shell-view.c
@@ -42,102 +42,6 @@ enum {
static gpointer parent_class;
-static gint
-shell_view_compare_actions (GtkAction *action1,
- GtkAction *action2)
-{
- gchar *label1, *label2;
- gint result;
-
- /* XXX This is really inefficient, but we're only sorting
- * a small number of actions (repeatedly, though). */
-
- g_object_get (action1, "label", &label1, NULL);
- g_object_get (action2, "label", &label2, NULL);
-
- result = g_utf8_collate (label1, label2);
-
- g_free (label1);
- g_free (label2);
-
- return result;
-}
-
-static void
-shell_view_extract_actions (EShellView *shell_view,
- GList **source_list,
- GList **destination_list)
-{
- GList *match_list = NULL;
- GList *iter;
-
- /* Pick out the actions from the source list that are tagged
- * as belonging to the given EShellView and move them to the
- * destination list. */
-
- /* Example: Suppose [A] and [C] are tagged for this EShellView.
- *
- * source_list = [A] -> [B] -> [C]
- * ^ ^
- * | |
- * match_list = [ ] --------> [ ]
- *
- *
- * destination_list = [1] -> [2] (other actions)
- */
- for (iter = *source_list; iter != NULL; iter = iter->next) {
- GtkAction *action = iter->data;
- EShellView *action_shell_view;
-
- action_shell_view = g_object_get_data (
- G_OBJECT (action), "shell-view");
-
- if (action_shell_view != shell_view)
- continue;
-
- match_list = g_list_append (match_list, iter);
- }
-
- /* source_list = [B] match_list = [A] -> [C] */
- for (iter = match_list; iter != NULL; iter = iter->next) {
- GList *link = iter->data;
-
- iter->data = link->data;
- *source_list = g_list_delete_link (*source_list, link);
- }
-
- /* destination_list = [1] -> [2] -> [A] -> [C] */
- *destination_list = g_list_concat (*destination_list, match_list);
-}
-
-static void
-shell_view_register_new_actions (EShellView *shell_view,
- GtkActionGroup *action_group,
- const GtkActionEntry *entries,
- guint n_entries)
-{
- guint ii;
-
- gtk_action_group_add_actions (
- action_group, entries, n_entries, shell_view);
-
- /* Tag each action with the shell view that registered it.
- * This is used to help sort items in the "New" menu. */
-
- for (ii = 0; ii < n_entries; ii++) {
- const gchar *action_name;
- GtkAction *action;
-
- action_name = entries[ii].name;
-
- action = gtk_action_group_get_action (
- action_group, action_name);
-
- g_object_set_data (
- G_OBJECT (action), "shell-view", shell_view);
- }
-}
-
static void
shell_view_set_window (EShellView *shell_view,
GtkWidget *window)
@@ -226,80 +130,6 @@ shell_view_finalize (GObject *object)
G_OBJECT_CLASS (parent_class)->finalize (object);
}
-static GtkWidget *
-shell_view_create_new_menu (EShellView *shell_view)
-{
- GtkActionGroup *action_group;
- GList *new_item_actions;
- GList *new_source_actions;
- GList *iter, *list = NULL;
- GtkWidget *menu;
- GtkWidget *separator;
- GtkWidget *window;
-
- window = e_shell_view_get_window (shell_view);
-
- /* Get sorted lists of "new item" and "new source" actions. */
-
- action_group = E_SHELL_WINDOW_ACTION_GROUP_NEW_ITEM (window);
-
- new_item_actions = g_list_sort (
- gtk_action_group_list_actions (action_group),
- (GCompareFunc) shell_view_compare_actions);
-
- action_group = E_SHELL_WINDOW_ACTION_GROUP_NEW_SOURCE (window);
-
- new_source_actions = g_list_sort (
- gtk_action_group_list_actions (action_group),
- (GCompareFunc) shell_view_compare_actions);
-
- /* Give priority to actions that belong to this shell view. */
-
- shell_view_extract_actions (
- shell_view, &new_item_actions, &list);
-
- shell_view_extract_actions (
- shell_view, &new_source_actions, &list);
-
- /* Convert the actions to menu item proxy widgets. */
-
- for (iter = list; iter != NULL; iter = iter->next)
- iter->data = gtk_action_create_menu_item (iter->data);
-
- for (iter = new_item_actions; iter != NULL; iter = iter->next)
- iter->data = gtk_action_create_menu_item (iter->data);
-
- for (iter = new_source_actions; iter != NULL; iter = iter->next)
- iter->data = gtk_action_create_menu_item (iter->data);
-
- /* Add menu separators. */
-
- separator = gtk_separator_menu_item_new ();
- new_item_actions = g_list_prepend (new_item_actions, separator);
-
- separator = gtk_separator_menu_item_new ();
- new_source_actions = g_list_prepend (new_source_actions, separator);
-
- /* Merge everything into one list, reflecting the menu layout. */
-
- list = g_list_concat (list, new_item_actions);
- new_item_actions = NULL; /* just for clarity */
-
- list = g_list_concat (list, new_source_actions);
- new_source_actions = NULL; /* just for clarity */
-
- /* And finally, build the menu. */
-
- menu = gtk_menu_new ();
-
- for (iter = list; iter != NULL; iter = iter->next)
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), iter->data);
-
- g_list_free (list);
-
- return menu;
-}
-
static void
shell_view_class_init (EShellViewClass *class)
{
@@ -314,8 +144,6 @@ shell_view_class_init (EShellViewClass *class)
object_class->dispose = shell_view_dispose;
object_class->finalize = shell_view_finalize;
- class->create_new_menu = shell_view_create_new_menu;
-
g_object_class_install_property (
object_class,
PROP_TITLE,
@@ -373,6 +201,23 @@ e_shell_view_get_type (void)
}
const gchar *
+e_shell_view_get_name (EShellView *shell_view)
+{
+ EShellViewClass *class;
+
+ g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
+
+ /* A shell view's name is taken from the name of the
+ * module that registered the shell view subclass. */
+
+ class = E_SHELL_VIEW_GET_CLASS (shell_view);
+ g_return_val_if_fail (class->module != NULL, NULL);
+ g_return_val_if_fail (class->module->name != NULL, NULL);
+
+ return class->module->name;
+}
+
+const gchar *
e_shell_view_get_title (EShellView *shell_view)
{
g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
@@ -401,19 +246,6 @@ e_shell_view_get_window (EShellView *shell_view)
}
GtkWidget *
-e_shell_view_create_new_menu (EShellView *shell_view)
-{
- EShellViewClass *class;
-
- g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
-
- class = E_SHELL_VIEW_CLASS (shell_view);
- g_return_val_if_fail (class->create_new_menu != NULL, NULL);
-
- return class->create_new_menu (shell_view);
-}
-
-GtkWidget *
e_shell_view_get_content_widget (EShellView *shell_view)
{
EShellViewClass *class;
@@ -451,39 +283,3 @@ e_shell_view_get_status_widget (EShellView *shell_view)
return class->get_status_widget (shell_view);
}
-
-void
-e_shell_view_register_new_item_actions (EShellView *shell_view,
- const GtkActionEntry *entries,
- guint n_entries)
-{
- GtkWidget *window;
- GtkActionGroup *action_group;
-
- g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
- g_return_if_fail (entries != NULL);
-
- window = e_shell_view_get_window (shell_view);
- action_group = E_SHELL_WINDOW_ACTION_GROUP_NEW_ITEM (window);
-
- shell_view_register_new_actions (
- shell_view, action_group, entries, n_entries);
-}
-
-void
-e_shell_view_register_new_source_actions (EShellView *shell_view,
- const GtkActionEntry *entries,
- guint n_entries)
-{
- GtkWidget *window;
- GtkActionGroup *action_group;
-
- g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
- g_return_if_fail (entries != NULL);
-
- window = e_shell_view_get_window (shell_view);
- action_group = E_SHELL_WINDOW_ACTION_GROUP_NEW_SOURCE (window);
-
- shell_view_register_new_actions (
- shell_view, action_group, entries, n_entries);
-}
diff --git a/shell/e-shell-view.h b/shell/e-shell-view.h
index 5f1be6fa7d..433c02f01a 100644
--- a/shell/e-shell-view.h
+++ b/shell/e-shell-view.h
@@ -60,31 +60,25 @@ struct _EShellViewClass {
const gchar *label;
const gchar *icon_name;
- GtkWidget * (*create_new_menu) (EShellView *shell_view);
+ /* Subclasses should set this via the "class_data" field in
+ * the GTypeInfo they pass to g_type_module_register_type(). */
+ GTypeModule *module;
+
GtkWidget * (*get_content_widget) (EShellView *shell_view);
GtkWidget * (*get_sidebar_widget) (EShellView *shell_view);
GtkWidget * (*get_status_widget) (EShellView *shell_view);
};
GType e_shell_view_get_type (void);
+const gchar * e_shell_view_get_name (EShellView *shell_view);
const gchar * e_shell_view_get_title (EShellView *shell_view);
void e_shell_view_set_title (EShellView *shell_view,
const gchar *title);
GtkWidget * e_shell_view_get_window (EShellView *shell_view);
-GtkWidget * e_shell_view_create_new_menu (EShellView *shell_view);
GtkWidget * e_shell_view_get_content_widget (EShellView *shell_view);
GtkWidget * e_shell_view_get_sidebar_widget (EShellView *shell_view);
GtkWidget * e_shell_view_get_status_widget (EShellView *shell_view);
-void e_shell_view_register_new_item_actions
- (EShellView *shell_view,
- const GtkActionEntry *entries,
- guint n_entries);
-void e_shell_view_register_new_source_actions
- (EShellView *shell_view,
- const GtkActionEntry *entries,
- guint n_entries);
-
G_END_DECLS
#endif /* E_SHELL_VIEW_H */
diff --git a/shell/e-shell-window-actions.c b/shell/e-shell-window-actions.c
index 85bdf445d9..a176a202b5 100644
--- a/shell/e-shell-window-actions.c
+++ b/shell/e-shell-window-actions.c
@@ -799,12 +799,10 @@ action_shell_view_cb (GtkRadioAction *action,
GtkRadioAction *current,
EShellWindow *window)
{
- gint value;
+ const gchar *view_name;
- if (action != current)
- return;
-
- value = gtk_radio_action_get_current_value (action);
+ view_name = g_object_get_data (G_OBJECT (current), "view-name");
+ e_shell_window_set_current_view (window, view_name);
}
static void
@@ -1188,6 +1186,77 @@ static GtkRadioActionEntry shell_switcher_style_entries[] = {
-1 }
};
+static gint
+shell_window_compare_actions (GtkAction *action1,
+ GtkAction *action2)
+{
+ gchar *label1, *label2;
+ gint result;
+
+ /* XXX This is really inefficient, but we're only sorting
+ * a small number of actions (repeatedly, though). */
+
+ g_object_get (action1, "label", &label1, NULL);
+ g_object_get (action2, "label", &label2, NULL);
+
+ result = g_utf8_collate (label1, label2);
+
+ g_free (label1);
+ g_free (label2);
+
+ return result;
+}
+
+static void
+shell_window_extract_actions (EShellWindow *window,
+ GList **source_list,
+ GList **destination_list)
+{
+ const gchar *current_view;
+ GList *match_list = NULL;
+ GList *iter;
+
+ /* Pick out the actions from the source list that are tagged
+ * as belonging to the current EShellView and move them to the
+ * destination list. */
+
+ current_view = e_shell_window_get_current_view (window);
+
+ /* Example: Suppose [A] and [C] are tagged for this EShellView.
+ *
+ * source_list = [A] -> [B] -> [C]
+ * ^ ^
+ * | |
+ * match_list = [ ] --------> [ ]
+ *
+ *
+ * destination_list = [1] -> [2] (other actions)
+ */
+ for (iter = *source_list; iter != NULL; iter = iter->next) {
+ GtkAction *action = iter->data;
+ const gchar *view_name;
+
+ view_name = g_object_get_data (
+ G_OBJECT (action), "view-name");
+
+ if (view_name != current_view)
+ continue;
+
+ match_list = g_list_append (match_list, iter);
+ }
+
+ /* source_list = [B] match_list = [A] -> [C] */
+ for (iter = match_list; iter != NULL; iter = iter->next) {
+ GList *link = iter->data;
+
+ iter->data = link->data;
+ *source_list = g_list_delete_link (*source_list, link);
+ }
+
+ /* destination_list = [1] -> [2] -> [A] -> [C] */
+ *destination_list = g_list_concat (*destination_list, match_list);
+}
+
void
e_shell_window_actions_init (EShellWindow *window)
{
@@ -1231,20 +1300,91 @@ e_shell_window_actions_init (EShellWindow *window)
gtk_ui_manager_insert_action_group (manager, action_group, 0);
}
+GtkWidget *
+e_shell_window_create_new_menu (EShellWindow *window)
+{
+ GtkActionGroup *action_group;
+ GList *new_item_actions;
+ GList *new_source_actions;
+ GList *iter, *list = NULL;
+ GtkWidget *menu;
+ GtkWidget *separator;
+
+ /* Get sorted lists of "new item" and "new source" actions. */
+
+ action_group = window->priv->new_item_actions;
+
+ new_item_actions = g_list_sort (
+ gtk_action_group_list_actions (action_group),
+ (GCompareFunc) shell_window_compare_actions);
+
+ action_group = window->priv->new_source_actions;
+
+ new_source_actions = g_list_sort (
+ gtk_action_group_list_actions (action_group),
+ (GCompareFunc) shell_window_compare_actions);
+
+ /* Give priority to actions that belong to this shell view. */
+
+ shell_window_extract_actions (
+ window, &new_item_actions, &list);
+
+ shell_window_extract_actions (
+ window, &new_source_actions, &list);
+
+ /* Convert the actions to menu item proxy widgets. */
+
+ for (iter = list; iter != NULL; iter = iter->next)
+ iter->data = gtk_action_create_menu_item (iter->data);
+
+ for (iter = new_item_actions; iter != NULL; iter = iter->next)
+ iter->data = gtk_action_create_menu_item (iter->data);
+
+ for (iter = new_source_actions; iter != NULL; iter = iter->next)
+ iter->data = gtk_action_create_menu_item (iter->data);
+
+ /* Add menu separators. */
+
+ separator = gtk_separator_menu_item_new ();
+ new_item_actions = g_list_prepend (new_item_actions, separator);
+
+ separator = gtk_separator_menu_item_new ();
+ new_source_actions = g_list_prepend (new_source_actions, separator);
+
+ /* Merge everything into one list, reflecting the menu layout. */
+
+ list = g_list_concat (list, new_item_actions);
+ new_item_actions = NULL; /* just for clarity */
+
+ list = g_list_concat (list, new_source_actions);
+ new_source_actions = NULL; /* just for clarity */
+
+ /* And finally, build the menu. */
+
+ menu = gtk_menu_new ();
+
+ for (iter = list; iter != NULL; iter = iter->next)
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), iter->data);
+
+ g_list_free (list);
+
+ return menu;
+}
+
void
e_shell_window_create_shell_view_actions (EShellWindow *window)
{
- GType *types;
+ GType *children;
GSList *group = NULL;
GtkActionGroup *action_group;
GtkUIManager *manager;
- guint n_types, ii;
+ guint n_children, ii;
guint merge_id;
g_return_if_fail (E_IS_SHELL_WINDOW (window));
action_group = window->priv->shell_view_actions;
- types = e_shell_registry_get_view_types (&n_types);
+ children = g_type_children (E_TYPE_SHELL_VIEW, &n_children);
manager = e_shell_window_get_ui_manager (window);
merge_id = gtk_ui_manager_new_merge_id (manager);
@@ -1252,22 +1392,31 @@ e_shell_window_create_shell_view_actions (EShellWindow *window)
* subclasses and register them with our ESidebar. These actions
* are manifested as switcher buttons and View->Window menu items. */
- for (ii = 0; ii < n_types; ii++) {
+ for (ii = 0; ii < n_children; ii++) {
EShellViewClass *class;
GtkRadioAction *action;
- const gchar *type_name;
+ const gchar *view_name;
gchar *action_name;
gchar *tooltip;
- class = g_type_class_ref (types[ii]);
- type_name = g_type_name (types[ii]);
+ class = g_type_class_ref (children[ii]);
if (class->label == NULL) {
- g_critical ("Label member not set on %s", type_name);
+ g_critical (
+ "Label member not set on %s",
+ G_OBJECT_CLASS_NAME (class));
+ continue;
+ }
+
+ if (class->module == NULL) {
+ g_critical (
+ "Module member not set on %s",
+ G_OBJECT_CLASS_NAME (class));
continue;
}
- action_name = g_strdup_printf ("shell-view-%s", type_name);
+ view_name = class->module->name;
+ action_name = g_strdup_printf ("shell-view-%s", view_name);
tooltip = g_strdup_printf (_("Switch to %s"), class->label);
/* Note, we have to set "icon-name" separately because
@@ -1282,9 +1431,20 @@ e_shell_window_create_shell_view_actions (EShellWindow *window)
G_OBJECT (action),
"icon-name", class->icon_name, NULL);
- g_signal_connect (
- action, "changed",
- G_CALLBACK (action_shell_view_cb), window);
+ g_object_set_data (
+ G_OBJECT (action),
+ "view-name", (gpointer) view_name);
+
+ if (group == NULL) {
+
+ /* First view is the default. */
+ window->priv->default_view = view_name;
+
+ /* Only listen to the first action. */
+ g_signal_connect (
+ action, "changed",
+ G_CALLBACK (action_shell_view_cb), window);
+ }
gtk_radio_action_set_group (action, group);
group = gtk_radio_action_get_group (action);
@@ -1308,5 +1468,5 @@ e_shell_window_create_shell_view_actions (EShellWindow *window)
g_type_class_unref (class);
}
- g_free (types);
+ g_free (children);
}
diff --git a/shell/e-shell-window-private.c b/shell/e-shell-window-private.c
index 1db8652cfa..5e750cfcf4 100644
--- a/shell/e-shell-window-private.c
+++ b/shell/e-shell-window-private.c
@@ -98,6 +98,7 @@ void
e_shell_window_private_init (EShellWindow *window)
{
EShellWindowPrivate *priv = window->priv;
+ GHashTable *loaded_views;
GConfBridge *bridge;
GtkWidget *container;
GtkWidget *widget;
@@ -105,13 +106,17 @@ e_shell_window_private_init (EShellWindow *window)
const gchar *key;
gint height;
+ loaded_views = g_hash_table_new_full (
+ g_direct_hash, g_direct_equal,
+ (GDestroyNotify) NULL,
+ (GDestroyNotify) g_object_unref);
+
priv->manager = gtk_ui_manager_new ();
priv->shell_actions = gtk_action_group_new ("shell");
priv->new_item_actions = gtk_action_group_new ("new-item");
priv->new_source_actions = gtk_action_group_new ("new-source");
priv->shell_view_actions = gtk_action_group_new ("shell-view");
-
- priv->shell_views = g_ptr_array_new ();
+ priv->loaded_views = loaded_views;
e_load_ui_definition (priv->manager, "evolution-shell.ui");
@@ -255,6 +260,8 @@ e_shell_window_private_dispose (EShellWindow *window)
DISPOSE (priv->new_source_actions);
DISPOSE (priv->shell_view_actions);
+ g_hash_table_remove_all (priv->loaded_views);
+
DISPOSE (priv->main_menu);
DISPOSE (priv->main_toolbar);
DISPOSE (priv->content_pane);
@@ -280,6 +287,5 @@ e_shell_window_private_finalize (EShellWindow *window)
{
EShellWindowPrivate *priv = window->priv;
- g_ptr_array_foreach (priv->shell_views, (GFunc) g_object_unref, NULL);
- g_ptr_array_free (priv->shell_views, TRUE);
+ g_hash_table_destroy (priv->loaded_views);
}
diff --git a/shell/e-shell-window-private.h b/shell/e-shell-window-private.h
index e8287fc23d..bc5fbc7645 100644
--- a/shell/e-shell-window-private.h
+++ b/shell/e-shell-window-private.h
@@ -61,7 +61,9 @@ struct _EShellWindowPrivate {
/*** Shell Views ***/
- GPtrArray *shell_views;
+ GHashTable *loaded_views;
+ const gchar *current_view;
+ const gchar *default_view;
/*** Widgetry ***/
@@ -89,6 +91,7 @@ void e_shell_window_private_finalize (EShellWindow *window);
/* Private Utilities */
void e_shell_window_actions_init (EShellWindow *window);
+GtkWidget * e_shell_window_create_new_menu (EShellWindow *window);
void e_shell_window_create_shell_view_actions
(EShellWindow *window);
diff --git a/shell/e-shell-window.c b/shell/e-shell-window.c
index 45c1fa2637..ca7776c201 100644
--- a/shell/e-shell-window.c
+++ b/shell/e-shell-window.c
@@ -41,6 +41,7 @@
enum {
PROP_0,
+ PROP_CURRENT_VIEW,
PROP_SAFE_MODE
};
@@ -53,11 +54,17 @@ shell_window_set_property (GObject *object,
GParamSpec *pspec)
{
switch (property_id) {
+ case PROP_CURRENT_VIEW:
+ e_shell_window_set_current_view (
+ E_SHELL_WINDOW (object),
+ g_value_get_string (value));
+ return;
+
case PROP_SAFE_MODE:
e_shell_window_set_safe_mode (
E_SHELL_WINDOW (object),
g_value_get_boolean (value));
- break;
+ return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -70,11 +77,17 @@ shell_window_get_property (GObject *object,
GParamSpec *pspec)
{
switch (property_id) {
+ case PROP_CURRENT_VIEW:
+ g_value_set_string (
+ value, e_shell_window_get_current_view (
+ E_SHELL_WINDOW (object)));
+ return;
+
case PROP_SAFE_MODE:
g_value_set_boolean (
value, e_shell_window_get_safe_mode (
E_SHELL_WINDOW (object)));
- break;
+ return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -114,6 +127,17 @@ shell_window_class_init (EShellWindowClass *class)
g_object_class_install_property (
object_class,
+ PROP_CURRENT_VIEW,
+ g_param_spec_string (
+ "current-view",
+ NULL,
+ NULL,
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
PROP_SAFE_MODE,
g_param_spec_boolean (
"safe-mode",
@@ -125,18 +149,18 @@ shell_window_class_init (EShellWindowClass *class)
}
static void
-shell_window_init (EShellWindow *window)
+shell_window_init (EShellWindow *shell_window)
{
GtkUIManager *manager;
- window->priv = E_SHELL_WINDOW_GET_PRIVATE (window);
+ shell_window->priv = E_SHELL_WINDOW_GET_PRIVATE (shell_window);
- e_shell_window_private_init (window);
+ e_shell_window_private_init (shell_window);
- manager = e_shell_window_get_ui_manager (window);
+ manager = e_shell_window_get_ui_manager (shell_window);
e_plugin_ui_register_manager (
- "org.gnome.evolution.shell", manager, window);
+ "org.gnome.evolution.shell", manager, shell_window);
}
GType
@@ -173,25 +197,25 @@ e_shell_window_new (gboolean safe_mode)
}
GtkUIManager *
-e_shell_window_get_ui_manager (EShellWindow *window)
+e_shell_window_get_ui_manager (EShellWindow *shell_window)
{
- g_return_val_if_fail (E_IS_SHELL_WINDOW (window), NULL);
+ g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
- return window->priv->manager;
+ return shell_window->priv->manager;
}
GtkAction *
-e_shell_window_get_action (EShellWindow *window,
+e_shell_window_get_action (EShellWindow *shell_window,
const gchar *action_name)
{
GtkUIManager *manager;
GtkAction *action = NULL;
GList *iter;
- g_return_val_if_fail (E_IS_SHELL_WINDOW (window), NULL);
+ g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
g_return_val_if_fail (action_name != NULL, NULL);
- manager = e_shell_window_get_ui_manager (window);
+ manager = e_shell_window_get_ui_manager (shell_window);
iter = gtk_ui_manager_get_action_groups (manager);
while (iter != NULL && action == NULL) {
@@ -208,16 +232,16 @@ e_shell_window_get_action (EShellWindow *window,
}
GtkActionGroup *
-e_shell_window_get_action_group (EShellWindow *window,
+e_shell_window_get_action_group (EShellWindow *shell_window,
const gchar *group_name)
{
GtkUIManager *manager;
GList *iter;
- g_return_val_if_fail (E_IS_SHELL_WINDOW (window), NULL);
+ g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
g_return_val_if_fail (group_name != NULL, NULL);
- manager = e_shell_window_get_ui_manager (window);
+ manager = e_shell_window_get_ui_manager (shell_window);
iter = gtk_ui_manager_get_action_groups (manager);
while (iter != NULL) {
@@ -235,16 +259,16 @@ e_shell_window_get_action_group (EShellWindow *window,
}
GtkWidget *
-e_shell_window_get_managed_widget (EShellWindow *window,
+e_shell_window_get_managed_widget (EShellWindow *shell_window,
const gchar *widget_path)
{
GtkUIManager *manager;
GtkWidget *widget;
- g_return_val_if_fail (E_IS_SHELL_WINDOW (window), NULL);
+ g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
g_return_val_if_fail (widget_path != NULL, NULL);
- manager = e_shell_window_get_ui_manager (window);
+ manager = e_shell_window_get_ui_manager (shell_window);
widget = gtk_ui_manager_get_widget (manager, widget_path);
g_return_val_if_fail (widget != NULL, NULL);
@@ -252,21 +276,125 @@ e_shell_window_get_managed_widget (EShellWindow *window,
return widget;
}
+const gchar *
+e_shell_window_get_current_view (EShellWindow *shell_window)
+{
+ g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
+
+ return shell_window->priv->current_view;
+}
+
+void
+e_shell_window_set_current_view (EShellWindow *shell_window,
+ const gchar *name_or_alias)
+{
+ const gchar *current_view;
+
+ g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
+
+ if (name_or_alias != NULL)
+ current_view =
+ e_shell_registry_get_canonical_name (name_or_alias);
+
+ if (current_view == NULL)
+ current_view = shell_window->priv->default_view;
+
+ shell_window->priv->current_view = current_view;
+
+ g_object_notify (G_OBJECT (shell_window), "current-view");
+}
+
gboolean
-e_shell_window_get_safe_mode (EShellWindow *window)
+e_shell_window_get_safe_mode (EShellWindow *shell_window)
{
- g_return_val_if_fail (E_IS_SHELL_WINDOW (window), FALSE);
+ g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE);
- return window->priv->safe_mode;
+ return shell_window->priv->safe_mode;
}
void
-e_shell_window_set_safe_mode (EShellWindow *window,
+e_shell_window_set_safe_mode (EShellWindow *shell_window,
gboolean safe_mode)
{
- g_return_if_fail (E_IS_SHELL_WINDOW (window));
+ g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
- window->priv->safe_mode = safe_mode;
+ shell_window->priv->safe_mode = safe_mode;
- g_object_notify (G_OBJECT (window), "safe-mode");
+ g_object_notify (G_OBJECT (shell_window), "safe-mode");
+}
+
+void
+e_shell_window_register_new_item_actions (EShellWindow *shell_window,
+ const gchar *module_name,
+ const GtkActionEntry *entries,
+ guint n_entries)
+{
+ GtkActionGroup *action_group;
+ guint ii;
+
+ g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
+ g_return_if_fail (module_name != NULL);
+ g_return_if_fail (entries != NULL);
+
+ action_group = shell_window->priv->new_item_actions;
+ module_name = g_intern_string (module_name);
+
+ gtk_action_group_add_actions (
+ action_group, entries, n_entries, shell_window);
+
+ /* Tag each action with the name of the shell module that
+ * registered it. This is used to help sort actions in the
+ * "New" menu. */
+
+ for (ii = 0; ii < n_entries; ii++) {
+ const gchar *action_name;
+ GtkAction *action;
+
+ action_name = entries[ii].name;
+
+ action = gtk_action_group_get_action (
+ action_group, action_name);
+
+ g_object_set_data (
+ G_OBJECT (action),
+ "module-name", (gpointer) module_name);
+ }
+}
+
+void
+e_shell_window_register_new_source_actions (EShellWindow *shell_window,
+ const gchar *module_name,
+ const GtkActionEntry *entries,
+ guint n_entries)
+{
+ GtkActionGroup *action_group;
+ guint ii;
+
+ g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
+ g_return_if_fail (module_name != NULL);
+ g_return_if_fail (entries != NULL);
+
+ action_group = shell_window->priv->new_source_actions;
+ module_name = g_intern_string (module_name);
+
+ gtk_action_group_add_actions (
+ action_group, entries, n_entries, shell_window);
+
+ /* Tag each action with the name of the shell module that
+ * registered it. This is used to help sort actions in the
+ * "New" menu. */
+
+ for (ii = 0; ii < n_entries; ii++) {
+ const gchar *action_name;
+ GtkAction *action;
+
+ action_name = entries[ii].name;
+
+ action = gtk_action_group_get_action (
+ action_group, action_name);
+
+ g_object_set_data (
+ G_OBJECT (action),
+ "module-name", (gpointer) module_name);
+ }
}
diff --git a/shell/e-shell-window.h b/shell/e-shell-window.h
index e7b0d9da8d..2ff65138a8 100644
--- a/shell/e-shell-window.h
+++ b/shell/e-shell-window.h
@@ -22,7 +22,6 @@
#define E_SHELL_WINDOW_H
#include "e-shell-common.h"
-#include "e-shell-view.h"
/* Standard GObject macros */
#define E_TYPE_SHELL_WINDOW \
@@ -60,18 +59,34 @@ struct _EShellWindowClass {
GType e_shell_window_get_type (void);
GtkWidget * e_shell_window_new (gboolean safe_mode);
-GtkUIManager * e_shell_window_get_ui_manager (EShellWindow *window);
-GtkAction * e_shell_window_get_action (EShellWindow *window,
+GtkUIManager * e_shell_window_get_ui_manager (EShellWindow *shell_window);
+GtkAction * e_shell_window_get_action (EShellWindow *shell_window,
const gchar *action_name);
-GtkActionGroup *e_shell_window_get_action_group (EShellWindow *window,
+GtkActionGroup *e_shell_window_get_action_group (EShellWindow *shell_window,
const gchar *group_name);
GtkWidget * e_shell_window_get_managed_widget
- (EShellWindow *window,
+ (EShellWindow *shell_window,
const gchar *widget_path);
-gboolean e_shell_window_get_safe_mode (EShellWindow *window);
-void e_shell_window_set_safe_mode (EShellWindow *window,
+const gchar * e_shell_window_get_current_view (EShellWindow *shell_window);
+void e_shell_window_set_current_view (EShellWindow *shell_window,
+ const gchar *name_or_alias);
+gboolean e_shell_window_get_safe_mode (EShellWindow *shell_window);
+void e_shell_window_set_safe_mode (EShellWindow *shell_window,
gboolean safe_mode);
+/* These should be called from the shell module's window_created() method. */
+
+void e_shell_window_register_new_item_actions
+ (EShellWindow *shell_window,
+ const gchar *module_name,
+ const GtkActionEntry *entries,
+ guint n_entries);
+void e_shell_window_register_new_source_actions
+ (EShellWindow *shell_window,
+ const gchar *module_name,
+ const GtkActionEntry *entries,
+ guint n_entries);
+
G_END_DECLS
#endif /* E_SHELL_WINDOW_H */
diff --git a/shell/e-shell.c b/shell/e-shell.c
index 1d2d68b57e..9678790d72 100644
--- a/shell/e-shell.c
+++ b/shell/e-shell.c
@@ -22,6 +22,7 @@
#include <glib/gi18n.h>
#include <e-preferences-window.h>
+#include <e-util/e-util.h>
#include "e-shell-module.h"
#include "e-shell-registry.h"
diff --git a/shell/test/e-test-shell-module.c b/shell/test/e-test-shell-module.c
index 16515c1e30..de6210f654 100644
--- a/shell/test/e-test-shell-module.c
+++ b/shell/test/e-test-shell-module.c
@@ -22,15 +22,16 @@
#include "e-test-shell-view.h"
-#define MODULE_SORT_ORDER 100
-#define MODULE_ALIASES "test"
+#define MODULE_NAME "test"
+#define MODULE_ALIASES "monkey"
#define MODULE_SCHEMES ""
+#define MODULE_SORT_ORDER 100
/* Module Entry Point */
void e_shell_module_init (GTypeModule *module);
static gboolean
-test_module_is_busy (void)
+test_module_is_busy (EShellModule *shell_module)
{
g_debug ("%s", G_STRFUNC);
@@ -38,7 +39,7 @@ test_module_is_busy (void)
}
static gboolean
-test_module_shutdown (void)
+test_module_shutdown (EShellModule *shell_module)
{
g_debug ("%s", G_STRFUNC);
@@ -46,7 +47,8 @@ test_module_shutdown (void)
}
static gboolean
-test_module_handle_uri (const gchar *uri)
+test_module_handle_uri (EShellModule *shell_module,
+ const gchar *uri)
{
g_debug ("%s (uri=%s)", G_STRFUNC, uri);
@@ -54,23 +56,24 @@ test_module_handle_uri (const gchar *uri)
}
static void
-test_module_send_and_receive (void)
+test_module_send_and_receive (EShellModule *shell_module)
{
g_debug ("%s", G_STRFUNC);
}
static void
-test_module_window_created (EShellWindow *window)
+test_module_window_created (EShellModule *shell_module,
+ EShellWindow *shell_window)
{
- g_debug ("%s (window=%p)", G_STRFUNC, window);
+ g_debug ("%s (window=%p)", G_STRFUNC, shell_window);
}
static EShellModuleInfo module_info = {
- MODULE_SORT_ORDER,
+ MODULE_NAME,
MODULE_ALIASES,
MODULE_SCHEMES,
- G_TYPE_INVALID,
+ MODULE_SORT_ORDER,
/* Methods */
test_module_is_busy,
@@ -83,7 +86,6 @@ static EShellModuleInfo module_info = {
void
e_shell_module_init (GTypeModule *module)
{
- g_type_module_set_name (module, "name");
- module_info.shell_view_type = e_test_shell_view_get_type (module);
+ e_test_shell_view_get_type (module);
e_shell_module_set_info (E_SHELL_MODULE (module), &module_info);
}
diff --git a/shell/test/e-test-shell-view.c b/shell/test/e-test-shell-view.c
index 7b2ff9a251..c76d459160 100644
--- a/shell/test/e-test-shell-view.c
+++ b/shell/test/e-test-shell-view.c
@@ -34,7 +34,8 @@ GType e_test_shell_view_type = 0;
static gpointer parent_class;
static void
-test_shell_view_class_init (ETestShellViewClass *class)
+test_shell_view_class_init (ETestShellViewClass *class,
+ GTypeModule *module)
{
EShellViewClass *shell_view_class;
@@ -44,6 +45,7 @@ test_shell_view_class_init (ETestShellViewClass *class)
shell_view_class = E_SHELL_VIEW_CLASS (class);
shell_view_class->label = N_("Test");
shell_view_class->icon_name = "face-monkey";
+ shell_view_class->module = module;
}
static void
@@ -62,11 +64,11 @@ e_test_shell_view_get_type (GTypeModule *module)
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) test_shell_view_class_init,
(GClassFinalizeFunc) NULL,
- NULL, /* class_data */
+ module, /* class_data */
sizeof (ETestShellView),
- 0, /* n_preallocs */
+ 0, /* n_preallocs */
(GInstanceInitFunc) test_shell_view_init,
- NULL /* value_table */
+ NULL /* value_table */
};
e_test_shell_view_type =