evolution r36022 - in branches/kill-bonobo/shell: . test



Author: mbarnes
Date: Tue Aug 19 02:55:45 2008
New Revision: 36022
URL: http://svn.gnome.org/viewvc/evolution?rev=36022&view=rev

Log:
Committing the day's progress.

Realized the "New" menu construction algorithm needs to live independently of
shell view instances since we lazy load the shell views but have to display
all possible "New" items immediately.

Prototype the mechanisms for managing the various shell views and keeping
track of which one is current.

Various other tightening up and rethinking of APIs.


Modified:
   branches/kill-bonobo/shell/e-shell-module.c
   branches/kill-bonobo/shell/e-shell-module.h
   branches/kill-bonobo/shell/e-shell-registry.c
   branches/kill-bonobo/shell/e-shell-registry.h
   branches/kill-bonobo/shell/e-shell-view.c
   branches/kill-bonobo/shell/e-shell-view.h
   branches/kill-bonobo/shell/e-shell-window-actions.c
   branches/kill-bonobo/shell/e-shell-window-private.c
   branches/kill-bonobo/shell/e-shell-window-private.h
   branches/kill-bonobo/shell/e-shell-window.c
   branches/kill-bonobo/shell/e-shell-window.h
   branches/kill-bonobo/shell/e-shell.c
   branches/kill-bonobo/shell/test/e-test-shell-module.c
   branches/kill-bonobo/shell/test/e-test-shell-view.c

Modified: branches/kill-bonobo/shell/e-shell-module.c
==============================================================================
--- branches/kill-bonobo/shell/e-shell-module.c	(original)
+++ branches/kill-bonobo/shell/e-shell-module.c	Tue Aug 19 02:55:45 2008
@@ -237,21 +237,17 @@
 	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 @@
 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 @@
 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 @@
 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;
-
-	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 = 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;
+
+	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;
 }

Modified: branches/kill-bonobo/shell/e-shell-module.h
==============================================================================
--- branches/kill-bonobo/shell/e-shell-module.h	(original)
+++ branches/kill-bonobo/shell/e-shell-module.h	Tue Aug 19 02:55:45 2008
@@ -51,16 +51,18 @@
 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 @@
 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,

Modified: branches/kill-bonobo/shell/e-shell-registry.c
==============================================================================
--- branches/kill-bonobo/shell/e-shell-registry.c	(original)
+++ branches/kill-bonobo/shell/e-shell-registry.c	Tue Aug 19 02:55:45 2008
@@ -66,7 +66,7 @@
 
 	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 @@
 	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;
+	EShellModule *shell_module;
 
-	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;
-
-		/* 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 *

Modified: branches/kill-bonobo/shell/e-shell-registry.h
==============================================================================
--- branches/kill-bonobo/shell/e-shell-registry.h	(original)
+++ branches/kill-bonobo/shell/e-shell-registry.h	Tue Aug 19 02:55:45 2008
@@ -28,7 +28,7 @@
 
 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);
 

Modified: branches/kill-bonobo/shell/e-shell-view.c
==============================================================================
--- branches/kill-bonobo/shell/e-shell-view.c	(original)
+++ branches/kill-bonobo/shell/e-shell-view.c	Tue Aug 19 02:55:45 2008
@@ -42,102 +42,6 @@
 
 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 @@
 	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 @@
 	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 @@
 }
 
 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 @@
 }
 
 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 @@
 
 	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);
-}

Modified: branches/kill-bonobo/shell/e-shell-view.h
==============================================================================
--- branches/kill-bonobo/shell/e-shell-view.h	(original)
+++ branches/kill-bonobo/shell/e-shell-view.h	Tue Aug 19 02:55:45 2008
@@ -60,31 +60,25 @@
 	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 */

Modified: branches/kill-bonobo/shell/e-shell-window-actions.c
==============================================================================
--- branches/kill-bonobo/shell/e-shell-window-actions.c	(original)
+++ branches/kill-bonobo/shell/e-shell-window-actions.c	Tue Aug 19 02:55:45 2008
@@ -799,12 +799,10 @@
                       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 @@
 	  -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 @@
 	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 @@
 	 * 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 @@
 			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 @@
 		g_type_class_unref (class);
 	}
 
-	g_free (types);
+	g_free (children);
 }

Modified: branches/kill-bonobo/shell/e-shell-window-private.c
==============================================================================
--- branches/kill-bonobo/shell/e-shell-window-private.c	(original)
+++ branches/kill-bonobo/shell/e-shell-window-private.c	Tue Aug 19 02:55:45 2008
@@ -98,6 +98,7 @@
 e_shell_window_private_init (EShellWindow *window)
 {
 	EShellWindowPrivate *priv = window->priv;
+	GHashTable *loaded_views;
 	GConfBridge *bridge;
 	GtkWidget *container;
 	GtkWidget *widget;
@@ -105,13 +106,17 @@
 	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 @@
 	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 @@
 {
 	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);
 }

Modified: branches/kill-bonobo/shell/e-shell-window-private.h
==============================================================================
--- branches/kill-bonobo/shell/e-shell-window-private.h	(original)
+++ branches/kill-bonobo/shell/e-shell-window-private.h	Tue Aug 19 02:55:45 2008
@@ -61,7 +61,9 @@
 
 	/*** Shell Views ***/
 
-	GPtrArray *shell_views;
+	GHashTable *loaded_views;
+	const gchar *current_view;
+	const gchar *default_view;
 
 	/*** Widgetry ***/
 
@@ -89,6 +91,7 @@
 /* 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);
 

Modified: branches/kill-bonobo/shell/e-shell-window.c
==============================================================================
--- branches/kill-bonobo/shell/e-shell-window.c	(original)
+++ branches/kill-bonobo/shell/e-shell-window.c	Tue Aug 19 02:55:45 2008
@@ -41,6 +41,7 @@
 
 enum {
 	PROP_0,
+	PROP_CURRENT_VIEW,
 	PROP_SAFE_MODE
 };
 
@@ -53,11 +54,17 @@
 			   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 @@
 			   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 @@
 
 	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 @@
 }
 
 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 @@
 }
 
 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 @@
 }
 
 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 @@
 }
 
 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 @@
 	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);
+	}
 }

Modified: branches/kill-bonobo/shell/e-shell-window.h
==============================================================================
--- branches/kill-bonobo/shell/e-shell-window.h	(original)
+++ branches/kill-bonobo/shell/e-shell-window.h	Tue Aug 19 02:55:45 2008
@@ -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 @@
 
 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 */

Modified: branches/kill-bonobo/shell/e-shell.c
==============================================================================
--- branches/kill-bonobo/shell/e-shell.c	(original)
+++ branches/kill-bonobo/shell/e-shell.c	Tue Aug 19 02:55:45 2008
@@ -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"

Modified: branches/kill-bonobo/shell/test/e-test-shell-module.c
==============================================================================
--- branches/kill-bonobo/shell/test/e-test-shell-module.c	(original)
+++ branches/kill-bonobo/shell/test/e-test-shell-module.c	Tue Aug 19 02:55:45 2008
@@ -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 @@
 }
 
 static gboolean
-test_module_shutdown (void)
+test_module_shutdown (EShellModule *shell_module)
 {
 	g_debug ("%s", G_STRFUNC);
 
@@ -46,7 +47,8 @@
 }
 
 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 @@
 }
 
 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 @@
 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);
 }

Modified: branches/kill-bonobo/shell/test/e-test-shell-view.c
==============================================================================
--- branches/kill-bonobo/shell/test/e-test-shell-view.c	(original)
+++ branches/kill-bonobo/shell/test/e-test-shell-view.c	Tue Aug 19 02:55:45 2008
@@ -34,7 +34,8 @@
 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 @@
 	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 @@
 			(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 =



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]