evolution r36560 - in branches/kill-bonobo: addressbook/gui/component calendar/gui calendar/modules doc/reference/shell doc/reference/shell/tmpl shell shell/test



Author: mbarnes
Date: Sun Oct  5 04:12:09 2008
New Revision: 36560
URL: http://svn.gnome.org/viewvc/evolution?rev=36560&view=rev

Log:
Support migration in the new shell design.
Some code got duplicated for calendars and tasks.  Made a note to revisit.


Added:
   branches/kill-bonobo/addressbook/gui/component/e-book-shell-module-migrate.c   (contents, props changed)
      - copied, changed from r36534, /branches/kill-bonobo/addressbook/gui/component/addressbook-migrate.c
   branches/kill-bonobo/addressbook/gui/component/e-book-shell-module-migrate.h   (contents, props changed)
      - copied, changed from r36307, /branches/kill-bonobo/addressbook/gui/component/addressbook-migrate.h
   branches/kill-bonobo/calendar/modules/e-cal-shell-module-migrate.c
   branches/kill-bonobo/calendar/modules/e-cal-shell-module-migrate.h
   branches/kill-bonobo/calendar/modules/e-memo-shell-module-migrate.c
   branches/kill-bonobo/calendar/modules/e-memo-shell-module-migrate.h
   branches/kill-bonobo/calendar/modules/e-task-shell-module-migrate.c
   branches/kill-bonobo/calendar/modules/e-task-shell-module-migrate.h
   branches/kill-bonobo/shell/e-shell-migrate.c   (contents, props changed)
   branches/kill-bonobo/shell/e-shell-migrate.h   (contents, props changed)
Removed:
   branches/kill-bonobo/addressbook/gui/component/addressbook-migrate.c
   branches/kill-bonobo/addressbook/gui/component/addressbook-migrate.h
   branches/kill-bonobo/calendar/gui/migration.c
   branches/kill-bonobo/calendar/gui/migration.h
Modified:
   branches/kill-bonobo/addressbook/gui/component/Makefile.am
   branches/kill-bonobo/addressbook/gui/component/e-book-shell-module.c
   branches/kill-bonobo/addressbook/gui/component/e-book-shell-view-private.c
   branches/kill-bonobo/calendar/gui/Makefile.am
   branches/kill-bonobo/calendar/gui/e-cal-event.c
   branches/kill-bonobo/calendar/gui/e-cal-event.h
   branches/kill-bonobo/calendar/modules/e-cal-shell-module.c
   branches/kill-bonobo/calendar/modules/e-memo-shell-module.c
   branches/kill-bonobo/calendar/modules/e-task-shell-module.c
   branches/kill-bonobo/calendar/modules/e-task-shell-sidebar.c
   branches/kill-bonobo/doc/reference/shell/Makefile.am
   branches/kill-bonobo/doc/reference/shell/eshell-sections.txt
   branches/kill-bonobo/doc/reference/shell/tmpl/e-shell-module.sgml
   branches/kill-bonobo/doc/reference/shell/tmpl/e-shell.sgml
   branches/kill-bonobo/shell/Makefile.am
   branches/kill-bonobo/shell/e-shell-module.c
   branches/kill-bonobo/shell/e-shell-module.h
   branches/kill-bonobo/shell/e-shell.c
   branches/kill-bonobo/shell/e-shell.h
   branches/kill-bonobo/shell/test/e-test-shell-module.c

Modified: branches/kill-bonobo/addressbook/gui/component/Makefile.am
==============================================================================
--- branches/kill-bonobo/addressbook/gui/component/Makefile.am	(original)
+++ branches/kill-bonobo/addressbook/gui/component/Makefile.am	Sun Oct  5 04:12:09 2008
@@ -28,8 +28,6 @@
 libevolution_addressbook_la_SOURCES = 	\
 	addressbook-config.c		\
 	addressbook-config.h		\
-	addressbook-migrate.c		\
-	addressbook-migrate.h		\
 	autocompletion-config.c		\
 	autocompletion-config.h		\
 	addressbook.c			\
@@ -37,6 +35,8 @@
 	e-book-shell-content.c		\
 	e-book-shell-content.h		\
 	e-book-shell-module.c		\
+	e-book-shell-module-migrate.c	\
+	e-book-shell-module-migrate.h	\
 	e-book-shell-sidebar.c		\
 	e-book-shell-sidebar.h		\
 	e-book-shell-view.c		\

Copied: branches/kill-bonobo/addressbook/gui/component/e-book-shell-module-migrate.c (from r36534, /branches/kill-bonobo/addressbook/gui/component/addressbook-migrate.c)
==============================================================================
--- /branches/kill-bonobo/addressbook/gui/component/addressbook-migrate.c	(original)
+++ branches/kill-bonobo/addressbook/gui/component/e-book-shell-module-migrate.c	Sun Oct  5 04:12:09 2008
@@ -1,4 +1,6 @@
 /*
+ * e-book-shell-module-migrate.c
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
@@ -45,7 +47,7 @@
 #include "e-util/e-xml-utils.h"
 #include "e-util/e-folder-map.h"
 
-#include "addressbook-migrate.h"
+#include "e-book-shell-module-migrate.h"
 
 /*#define SLOW_MIGRATION*/
 
@@ -1110,11 +1112,11 @@
 }
 
 gboolean
-addressbook_migrate (EShellModule *shell_module,
-                     gint major,
-                     gint minor,
-                     gint revision,
-                     GError **error)
+e_book_shell_module_migrate (EShellModule *shell_module,
+                             gint major,
+                             gint minor,
+                             gint micro,
+                             GError **error)
 {
 	ESourceGroup *on_this_computer;
 	ESourceGroup *on_ldap_servers;
@@ -1123,8 +1125,6 @@
 	gboolean need_dialog = FALSE;
 	const gchar *data_dir;
 
-	printf ("addressbook_migrate (%d.%d.%d)\n", major, minor, revision);
-
 	g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), FALSE);
 
 	data_dir = e_shell_module_get_data_dir (shell_module);
@@ -1139,7 +1139,7 @@
 	if (major == 1
 	    /* we only need the most recent upgrade point here.
 	       further decomposition will happen below. */
-	    && (minor < 5 || (minor == 5 && revision <= 10)))
+	    && (minor < 5 || (minor == 5 && micro <= 10)))
 		need_dialog = TRUE;
 
 	if (need_dialog)
@@ -1147,7 +1147,7 @@
 
 	if (major == 1) {
 
-		if (minor < 5 || (minor == 5 && revision <= 2)) {
+		if (minor < 5 || (minor == 5 && micro <= 2)) {
 			/* initialize our dialog */
 			dialog_set_label (context,
 					  _("The location and hierarchy of the Evolution contact "
@@ -1162,7 +1162,7 @@
 			migrate_completion_folders (context);
 		}
 
-		if (minor < 5 || (minor == 5 && revision <= 7)) {
+		if (minor < 5 || (minor == 5 && micro <= 7)) {
 			dialog_set_label (context,
 					  _("The format of mailing list contacts has changed.\n\n"
 					    "Please be patient while Evolution migrates your "
@@ -1171,7 +1171,7 @@
 			migrate_contact_lists_for_local_folders (context, on_this_computer);
 		}
 
-		if (minor < 5 || (minor == 5 && revision <= 8)) {
+		if (minor < 5 || (minor == 5 && micro <= 8)) {
 			dialog_set_label (context,
 					  _("The way Evolution stores some phone numbers has changed.\n\n"
 					    "Please be patient while Evolution migrates your "
@@ -1180,7 +1180,7 @@
 			migrate_company_phone_for_local_folders (context, on_this_computer);
 		}
 
-		if (minor < 5 || (minor == 5 && revision <= 10)) {
+		if (minor < 5 || (minor == 5 && micro <= 10)) {
 			char *old_path, *new_path;
 
 			dialog_set_label (context, _("Evolution's Palm Sync changelog and map files have changed.\n\n"
@@ -1199,7 +1199,7 @@
 		   during one phase of development, as they take
 		   precedent over relative uris (but aren't updated
 		   when editing an ESource). */
-		if (minor == 5 && revision <= 11) {
+		if (minor == 5 && micro <= 11) {
 			GSList *g;
 			for (g = e_source_list_peek_groups (context->source_list); g; g = g->next) {
 				ESourceGroup *group = g->data;

Copied: branches/kill-bonobo/addressbook/gui/component/e-book-shell-module-migrate.h (from r36307, /branches/kill-bonobo/addressbook/gui/component/addressbook-migrate.h)
==============================================================================
--- /branches/kill-bonobo/addressbook/gui/component/addressbook-migrate.h	(original)
+++ branches/kill-bonobo/addressbook/gui/component/e-book-shell-module-migrate.h	Sun Oct  5 04:12:09 2008
@@ -1,4 +1,5 @@
 /*
+ * e-book-shell-module-migrate.h
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -21,20 +22,20 @@
  *
  */
 
-#ifndef _ADDRESSBOOK_MIGRATE_H_
-#define _ADDRESSBOOK_MIGRATE_H_
+#ifndef E_BOOK_SHELL_MODULE_MIGRATE_H
+#define E_BOOK_SHELL_MODULE_MIGRATE_H
 
 #include <glib.h>
-#include <e-shell-module.h>
+#include <shell/e-shell-module.h>
 
 G_BEGIN_DECLS
 
-gboolean	addressbook_migrate		(EShellModule *shell_module,
+gboolean	e_book_shell_module_migrate	(EShellModule *shell_module,
 						 gint major,
 						 gint minor,
-						 gint revision,
+						 gint micro,
 						 GError **error);
 
 G_END_DECLS
 
-#endif /* _ADDRESSBOOK_MIGRATE_H_ */
+#endif /* E_BOOK_SHELL_MODULE_MIGRATE_H */

Modified: branches/kill-bonobo/addressbook/gui/component/e-book-shell-module.c
==============================================================================
--- branches/kill-bonobo/addressbook/gui/component/e-book-shell-module.c	(original)
+++ branches/kill-bonobo/addressbook/gui/component/e-book-shell-module.c	Sun Oct  5 04:12:09 2008
@@ -27,19 +27,21 @@
 #include <libedataserver/e-source-list.h>
 #include <libedataserver/e-source-group.h>
 
-#include <e-shell.h>
-#include <e-shell-module.h>
-#include <e-shell-window.h>
+#include "shell/e-shell.h"
+#include "shell/e-shell-module.h"
+#include "shell/e-shell-window.h"
 
-#include <e-util/e-import.h>
-#include <addressbook/importers/evolution-addressbook-importers.h>
+#include "e-util/e-import.h"
+#include "addressbook/importers/evolution-addressbook-importers.h"
 
 #include <eab-config.h>
 #include <eab-gui-util.h>
-#include <e-book-shell-view.h>
 #include <addressbook-config.h>
 #include <autocompletion-config.h>
 
+#include "e-book-shell-view.h"
+#include "e-book-shell-module-migrate.h"
+
 #define MODULE_NAME		"addressbook"
 #define MODULE_ALIASES		"contacts"
 #define MODULE_SCHEMES		""
@@ -52,7 +54,7 @@
 void e_shell_module_init (GTypeModule *type_module);
 
 static void
-book_module_ensure_sources (EShellModule *shell_module)
+book_shell_module_ensure_sources (EShellModule *shell_module)
 {
 	/* XXX This is basically the same algorithm across all modules.
 	 *     Maybe we could somehow integrate this into EShellModule? */
@@ -182,7 +184,7 @@
 }
 
 static void
-book_module_init_importers (void)
+book_shell_module_init_importers (void)
 {
 	EImportClass *import_class;
 	EImportImporter *importer;
@@ -206,9 +208,9 @@
 }
 
 static void
-book_module_book_loaded_cb (EBook *book,
-                            EBookStatus status,
-                            gpointer user_data)
+book_shell_module_book_loaded_cb (EBook *book,
+                                  EBookStatus status,
+                                  gpointer user_data)
 {
 	EContact *contact;
 	GtkAction *action;
@@ -266,7 +268,8 @@
 	if (book == NULL)
 		book = e_book_new_default_addressbook (NULL);
 
-	e_book_async_open (book, FALSE, book_module_book_loaded_cb, action);
+	e_book_async_open (
+		book, FALSE, book_shell_module_book_loaded_cb, action);
 }
 
 static void
@@ -304,21 +307,21 @@
 };
 
 static gboolean
-book_module_is_busy (EShellModule *shell_module)
+book_shell_module_is_busy (EShellModule *shell_module)
 {
 	return !eab_editor_request_close_all ();
 }
 
 static gboolean
-book_module_shutdown (EShellModule *shell_module)
+book_shell_module_shutdown (EShellModule *shell_module)
 {
 	/* FIXME */
 	return TRUE;
 }
 
 static gboolean
-book_module_handle_uri (EShellModule *shell_module,
-                        const gchar *uri)
+book_shell_module_handle_uri (EShellModule *shell_module,
+                              const gchar *uri)
 {
 	EUri *euri;
 	const gchar *cp;
@@ -383,8 +386,8 @@
 }
 
 static void
-book_module_window_created (EShellModule *shell_module,
-                            EShellWindow *shell_window)
+book_shell_module_window_created (EShellModule *shell_module,
+                                  EShellWindow *shell_window)
 {
 	const gchar *module_name;
 
@@ -407,8 +410,9 @@
 	MODULE_SORT_ORDER,
 
 	/* Methods */
-	book_module_is_busy,
-	book_module_shutdown
+	book_shell_module_is_busy,
+	book_shell_module_shutdown,
+	e_book_shell_module_migrate
 };
 
 void
@@ -425,18 +429,18 @@
 
 	e_shell_module_set_info (shell_module, &module_info);
 
-	book_module_init_importers ();
-	book_module_ensure_sources (shell_module);
+	book_shell_module_init_importers ();
+	book_shell_module_ensure_sources (shell_module);
 
 	e_plugin_hook_register_type (eab_config_get_type ());
 
 	g_signal_connect_swapped (
 		shell, "handle-uri",
-		G_CALLBACK (book_module_handle_uri), shell_module);
+		G_CALLBACK (book_shell_module_handle_uri), shell_module);
 
 	g_signal_connect_swapped (
 		shell, "window-created",
-		G_CALLBACK (book_module_window_created), shell_module);
+		G_CALLBACK (book_shell_module_window_created), shell_module);
 
 	autocompletion_config_init ();
 }

Modified: branches/kill-bonobo/addressbook/gui/component/e-book-shell-view-private.c
==============================================================================
--- branches/kill-bonobo/addressbook/gui/component/e-book-shell-view-private.c	(original)
+++ branches/kill-bonobo/addressbook/gui/component/e-book-shell-view-private.c	Sun Oct  5 04:12:09 2008
@@ -70,7 +70,7 @@
 	EShellView *shell_view;
 	gint n_selected;
 
-	shell_view = E_SHELL_VIEW (shell_view);
+	shell_view = E_SHELL_VIEW (book_shell_view);
 	book_shell_content = book_shell_view->priv->book_shell_content;
 	current_view = e_book_shell_content_get_current_view (book_shell_content);
 

Modified: branches/kill-bonobo/calendar/gui/Makefile.am
==============================================================================
--- branches/kill-bonobo/calendar/gui/Makefile.am	(original)
+++ branches/kill-bonobo/calendar/gui/Makefile.am	Sun Oct  5 04:12:09 2008
@@ -50,8 +50,6 @@
 #	cal-search-bar.c
 # 	cal-search-bar.h
 # 	main.c
-# 	migration.c
-# 	migration.h
 
 libcal_gui_la_SOURCES =		\
  	e-calendar-view.c			\

Modified: branches/kill-bonobo/calendar/gui/e-cal-event.c
==============================================================================
--- branches/kill-bonobo/calendar/gui/e-cal-event.c	(original)
+++ branches/kill-bonobo/calendar/gui/e-cal-event.c	Sun Oct  5 04:12:09 2008
@@ -43,10 +43,10 @@
 ece_target_free (EEvent *ev, EEventTarget *t)
 {
 	switch (t->type) {
-	case E_CAL_EVENT_TARGET_COMPONENT: {
-		ECalEventTargetComponent *s = (ECalEventTargetComponent *) t;
-		if (s->component)
-			g_object_unref (s->component);
+	case E_CAL_EVENT_TARGET_MODULE: {
+		ECalEventTargetModule *s = (ECalEventTargetModule *) t;
+		if (s->shell_module)
+			g_object_unref (s->shell_module);
 		break; }
 	}
 
@@ -92,12 +92,12 @@
 	return e_cal_event;
 }
 
-ECalEventTargetComponent *
-e_cal_event_target_new_component (ECalEvent *ece, struct _CalendarComponent *component, guint32 flags)
+ECalEventTargetModule *
+e_cal_event_target_new_module (ECalEvent *ece, EShellModule *shell_module, guint32 flags)
 {
-	ECalEventTargetComponent *t = e_event_target_new (&ece->event, E_CAL_EVENT_TARGET_COMPONENT, sizeof (*t));
+	ECalEventTargetModule *t = e_event_target_new (&ece->event, E_CAL_EVENT_TARGET_MODULE, sizeof (*t));
 
-	t->component = g_object_ref (component);
+	t->shell_module = g_object_ref (shell_module);
 	t->target.mask = ~flags;
 
 	return t;
@@ -107,13 +107,13 @@
 
 static void *eceh_parent_class;
 
-static const EEventHookTargetMask eceh_component_masks[] = {
-	{ "migration", E_CAL_EVENT_COMPONENT_MIGRATION },
+static const EEventHookTargetMask eceh_module_masks[] = {
+	{ "migration", E_CAL_EVENT_MODULE_MIGRATION },
 	{ NULL },
 };
 
 static const EEventHookTargetMap eceh_targets[] = {
-	{ "component", E_CAL_EVENT_TARGET_COMPONENT, eceh_component_masks },
+	{ "module", E_CAL_EVENT_TARGET_MODULE, eceh_module_masks },
 	{ NULL },
 };
 

Modified: branches/kill-bonobo/calendar/gui/e-cal-event.h
==============================================================================
--- branches/kill-bonobo/calendar/gui/e-cal-event.h	(original)
+++ branches/kill-bonobo/calendar/gui/e-cal-event.h	Sun Oct  5 04:12:09 2008
@@ -27,6 +27,7 @@
 #include <glib-object.h>
 
 #include "e-util/e-event.h"
+#include "shell/e-shell-module.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -37,20 +38,19 @@
 typedef struct _ECalEventClass ECalEventClass;
 
 enum _e_cal_event_target_t {
-	E_CAL_EVENT_TARGET_COMPONENT,
+	E_CAL_EVENT_TARGET_MODULE,
 };
 
-/* Flags that describe TARGET_COMPONENT */
+/* Flags that describe TARGET_MODULE */
 enum {
-	E_CAL_EVENT_COMPONENT_MIGRATION = 1 << 0,
+	E_CAL_EVENT_MODULE_MIGRATION = 1 << 0,
 };
 
-typedef struct _ECalEventTargetComponent ECalEventTargetComponent;
+typedef struct _ECalEventTargetModule ECalEventTargetModule;
 
-struct _ECalEventTargetComponent {
+struct _ECalEventTargetModule {
 	EEventTarget target;
-
-	struct _CalendarComponent *component;
+	EShellModule *shell_module;
 };
 
 struct _ECalEvent {
@@ -65,7 +65,7 @@
 
 GType                     e_cal_event_get_type (void);
 ECalEvent*                e_cal_event_peek (void);
-ECalEventTargetComponent* e_cal_event_target_new_component (ECalEvent *ece, struct _CalendarComponent *component, guint32 flags);
+ECalEventTargetModule* e_cal_event_target_new_module (ECalEvent *ece, EShellModule *shell_module, guint32 flags);
 
 /* ********************************************************************** */
 

Added: branches/kill-bonobo/calendar/modules/e-cal-shell-module-migrate.c
==============================================================================
--- (empty file)
+++ branches/kill-bonobo/calendar/modules/e-cal-shell-module-migrate.c	Sun Oct  5 04:12:09 2008
@@ -0,0 +1,785 @@
+/*
+ * e-cal-shell-module-migrate.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>  
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-cal-shell-module-migrate.h"
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <libebackend/e-dbhash.h>
+#include <libedataserver/e-source.h>
+#include <libedataserver/e-source-group.h>
+#include <libedataserver/e-source-list.h>
+#include <libedataserver/e-xml-hash-utils.h>
+
+#include "e-util/e-bconf-map.h"
+#include "e-util/e-folder-map.h"
+#include "e-util/e-util-private.h"
+#include "calendar/gui/calendar-config.h"
+#include "calendar/gui/calendar-config-keys.h"
+#include "calendar/gui/e-cal-event.h"
+
+#define WEBCAL_BASE_URI "webcal://"
+#define CONTACTS_BASE_URI "contacts://"
+#define BAD_CONTACTS_BASE_URI "contact://"
+#define PERSONAL_RELATIVE_URI "system"
+
+static e_gconf_map_t calendar_display_map[] = {
+	/* /Calendar/Display */
+	{ "Timezone", "calendar/display/timezone", E_GCONF_MAP_STRING },
+	{ "Use24HourFormat", "calendar/display/use_24hour_format", E_GCONF_MAP_BOOL },
+	{ "WeekStartDay", "calendar/display/week_start_day", E_GCONF_MAP_INT },
+	{ "DayStartHour", "calendar/display/day_start_hour", E_GCONF_MAP_INT },
+	{ "DayStartMinute", "calendar/display/day_start_minute", E_GCONF_MAP_INT },
+	{ "DayEndHour", "calendar/display/day_end_hour", E_GCONF_MAP_INT },
+	{ "DayEndMinute", "calendar/display/day_end_minute", E_GCONF_MAP_INT },
+	{ "TimeDivisions", "calendar/display/time_divisions", E_GCONF_MAP_INT },
+	{ "View", "calendar/display/default_view", E_GCONF_MAP_INT },
+	{ "HPanePosition", "calendar/display/hpane_position", E_GCONF_MAP_FLOAT },
+	{ "VPanePosition", "calendar/display/vpane_position", E_GCONF_MAP_FLOAT },
+	{ "MonthHPanePosition", "calendar/display/month_hpane_position", E_GCONF_MAP_FLOAT },
+	{ "MonthVPanePosition", "calendar/display/month_vpane_position", E_GCONF_MAP_FLOAT },
+	{ "CompressWeekend", "calendar/display/compress_weekend", E_GCONF_MAP_BOOL },
+	{ "ShowEventEndTime", "calendar/display/show_event_end", E_GCONF_MAP_BOOL },
+	{ "WorkingDays", "calendar/display/working_days", E_GCONF_MAP_INT },
+	{ NULL },
+};
+
+static e_gconf_map_t calendar_other_map[] = {
+	/* /Calendar/Other */
+	{ "ConfirmDelete", "calendar/prompts/confirm_delete", E_GCONF_MAP_BOOL },
+	{ "ConfirmExpunge", "calendar/prompts/confirm_purge", E_GCONF_MAP_BOOL },
+	{ "UseDefaultReminder", "calendar/other/use_default_reminder", E_GCONF_MAP_BOOL },
+	{ "DefaultReminderInterval", "calendar/other/default_reminder_interval", E_GCONF_MAP_INT },
+	{ "DefaultReminderUnits", "calendar/other/default_reminder_units", E_GCONF_MAP_STRING },
+	{ NULL },
+};
+
+static e_gconf_map_t calendar_datenavigator_map[] = {
+	/* /Calendar/DateNavigator */
+	{ "ShowWeekNumbers", "calendar/date_navigator/show_week_numbers", E_GCONF_MAP_BOOL },
+	{ NULL },
+};
+
+static e_gconf_map_t calendar_alarmnotify_map[] = {
+	/* /Calendar/AlarmNotify */
+	{ "LastNotificationTime", "calendar/notify/last_notification_time", E_GCONF_MAP_INT },
+	{ "CalendarToLoad%i", "calendar/notify/calendars", E_GCONF_MAP_STRING|E_GCONF_MAP_LIST },
+	{ "BlessedProgram%i", "calendar/notify/programs", E_GCONF_MAP_STRING|E_GCONF_MAP_LIST },
+	{ NULL },
+};
+
+static e_gconf_map_list_t calendar_remap_list[] = {
+
+	{ "/Calendar/Display", calendar_display_map },
+	{ "/Calendar/Other/Map", calendar_other_map },
+	{ "/Calendar/DateNavigator", calendar_datenavigator_map },
+	{ "/Calendar/AlarmNotify", calendar_alarmnotify_map },
+
+	{ NULL },
+};
+
+static GtkWidget *window;
+static GtkLabel *label;
+static GtkProgressBar *progress;
+
+#ifndef G_OS_WIN32
+
+/* No previous versions have been available on Win32, so don't
+ * bother with upgrade support from 1.x on Win32.
+ */
+
+static void
+setup_progress_dialog (void)
+{
+	GtkWidget *vbox, *hbox, *w;
+
+	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+	gtk_window_set_title ((GtkWindow *) window, _("Migrating..."));
+	gtk_window_set_modal ((GtkWindow *) window, TRUE);
+	gtk_container_set_border_width ((GtkContainer *) window, 6);
+
+	vbox = gtk_vbox_new (FALSE, 6);
+	gtk_widget_show (vbox);
+	gtk_container_add ((GtkContainer *) window, vbox);
+
+	w = gtk_label_new (_("The location and hierarchy of the Evolution calendar "
+			     "folders has changed since Evolution 1.x.\n\nPlease be "
+			     "patient while Evolution migrates your folders..."));
+
+	gtk_label_set_line_wrap ((GtkLabel *) w, TRUE);
+	gtk_widget_show (w);
+	gtk_box_pack_start_defaults ((GtkBox *) vbox, w);
+
+	hbox = gtk_hbox_new (FALSE, 6);
+	gtk_widget_show (hbox);
+	gtk_box_pack_start_defaults ((GtkBox *) vbox, hbox);
+
+	label = (GtkLabel *) gtk_label_new ("");
+	gtk_widget_show ((GtkWidget *) label);
+	gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) label);
+
+	progress = (GtkProgressBar *) gtk_progress_bar_new ();
+	gtk_widget_show ((GtkWidget *) progress);
+	gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) progress);
+
+	gtk_widget_show (window);
+}
+
+static void
+dialog_close (void)
+{
+	gtk_widget_destroy ((GtkWidget *) window);
+}
+
+static void
+dialog_set_folder_name (const char *folder_name)
+{
+	char *text;
+
+	text = g_strdup_printf (_("Migrating '%s':"), folder_name);
+	gtk_label_set_text (label, text);
+	g_free (text);
+
+	gtk_progress_bar_set_fraction (progress, 0.0);
+
+	while (gtk_events_pending ())
+		gtk_main_iteration ();
+}
+
+static void
+dialog_set_progress (double percent)
+{
+	char text[5];
+
+	snprintf (text, sizeof (text), "%d%%", (int) (percent * 100.0f));
+
+	gtk_progress_bar_set_fraction (progress, percent);
+	gtk_progress_bar_set_text (progress, text);
+
+	while (gtk_events_pending ())
+		gtk_main_iteration ();
+}
+
+static gboolean
+check_for_conflict (ESourceGroup *group, char *name)
+{
+	GSList *sources;
+	GSList *s;
+
+	sources = e_source_group_peek_sources (group);
+
+	for (s = sources; s; s = s->next) {
+		ESource *source = E_SOURCE (s->data);
+
+		if (!strcmp (e_source_peek_name (source), name))
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+static char *
+get_source_name (ESourceGroup *group, const char *path)
+{
+	char **p = g_strsplit (path, "/", 0);
+	int i, j, starting_index;
+	int num_elements;
+	gboolean conflict;
+	GString *s = g_string_new (NULL);
+
+	for (i = 0; p[i]; i ++) ;
+
+	num_elements = i;
+	i--;
+
+	/* p[i] is now the last path element */
+
+	/* check if it conflicts */
+	starting_index = i;
+	do {
+		for (j = starting_index; j < num_elements; j += 2) {
+			if (j != starting_index)
+				g_string_append_c (s, '_');
+			g_string_append (s, p[j]);
+		}
+
+		conflict = check_for_conflict (group, s->str);
+
+
+		/* if there was a conflict back up 2 levels (skipping the /subfolder/ element) */
+		if (conflict)
+			starting_index -= 2;
+
+		/* we always break out if we can't go any further,
+		   regardless of whether or not we conflict. */
+		if (starting_index < 0)
+			break;
+
+	} while (conflict);
+	g_strfreev (p);
+
+	return g_string_free (s, FALSE);
+}
+
+static gboolean
+migrate_ical (ECal *old_ecal, ECal *new_ecal)
+{
+	GList *l, *objects;
+	int num_added = 0;
+	int num_objects;
+	gboolean retval = TRUE;
+
+	/* both ecals are loaded, start the actual migration */
+	if (!e_cal_get_object_list (old_ecal, "#t", &objects, NULL))
+		return FALSE;
+
+	num_objects = g_list_length (objects);
+	for (l = objects; l; l = l->next) {
+		icalcomponent *ical_comp = l->data;
+		GError *error = NULL;
+
+		if (!e_cal_create_object (new_ecal, ical_comp, NULL, &error)) {
+			g_warning ("Migration of object failed: %s", error->message);
+			retval = FALSE;
+		}
+
+		g_clear_error (&error);
+
+		num_added ++;
+		dialog_set_progress ((double)num_added / num_objects);
+	}
+
+	g_list_foreach (objects, (GFunc) icalcomponent_free, NULL);
+	g_list_free (objects);
+
+	return retval;
+}
+
+static gboolean
+migrate_ical_folder_to_source (char *old_path, ESource *new_source, ECalSourceType type)
+{
+	ECal *old_ecal = NULL, *new_ecal = NULL;
+	ESource *old_source;
+	ESourceGroup *group;
+	char *old_uri = g_strdup_printf ("file://%s", old_path);
+	GError *error = NULL;
+	gboolean retval = FALSE;
+
+	group = e_source_group_new ("", old_uri);
+	old_source = e_source_new ("", "");
+	e_source_group_add_source (group, old_source, -1);
+
+	dialog_set_folder_name (e_source_peek_name (new_source));
+
+	if (!(old_ecal = e_cal_new (old_source, type))) {
+		g_warning ("could not find a backend for '%s'", e_source_get_uri (old_source));
+		goto finish;
+	}
+	if (!e_cal_open (old_ecal, FALSE, &error)) {
+		g_warning ("failed to load source ecal for migration: '%s' (%s)", error->message,
+			   e_source_get_uri (old_source));
+		goto finish;
+	}
+
+	if (!(new_ecal = e_cal_new (new_source, type))) {
+		g_warning ("could not find a backend for '%s'", e_source_get_uri (new_source));
+		goto finish;
+	}
+	if (!e_cal_open (new_ecal, FALSE, &error)) {
+		g_warning ("failed to load destination ecal for migration: '%s' (%s)", error->message,
+			   e_source_get_uri (new_source));
+		goto finish;
+	}
+
+	retval = migrate_ical (old_ecal, new_ecal);
+
+finish:
+	g_clear_error (&error);
+	if (old_ecal)
+		g_object_unref (old_ecal);
+	g_object_unref (group);
+	if (new_ecal)
+		g_object_unref (new_ecal);
+	g_free (old_uri);
+
+	return retval;
+}
+
+static gboolean
+migrate_ical_folder (char *old_path, ESourceGroup *dest_group, char *source_name, ECalSourceType type)
+{
+	ESource *new_source;
+	gboolean retval;
+
+	new_source = e_source_new (source_name, source_name);
+	e_source_set_relative_uri (new_source, e_source_peek_uid (new_source));
+	e_source_group_add_source (dest_group, new_source, -1);
+
+	retval = migrate_ical_folder_to_source (old_path, new_source, type);
+
+	g_object_unref (new_source);
+
+	return retval;
+}
+
+#endif	/* !G_OS_WIN32 */
+
+#ifndef G_OS_WIN32
+
+static void
+migrate_pilot_db_key (const char *key, gpointer user_data)
+{
+	EXmlHash *xmlhash = user_data;
+
+	e_xmlhash_add (xmlhash, key, "");
+}
+
+static void
+migrate_pilot_data (const char *component, const char *conduit, const char *old_path, const char *new_path)
+{
+	char *changelog, *map;
+	const char *dent;
+	const char *ext;
+	char *filename;
+	GDir *dir;
+
+	if (!(dir = g_dir_open (old_path, 0, NULL)))
+		return;
+
+	map = g_alloca (12 + strlen (conduit));
+	sprintf (map, "pilot-map-%s-", conduit);
+
+	changelog = g_alloca (24 + strlen (conduit));
+	sprintf (changelog, "pilot-sync-evolution-%s-", conduit);
+
+	while ((dent = g_dir_read_name (dir))) {
+		if (!strncmp (dent, map, strlen (map)) &&
+		    ((ext = strrchr (dent, '.')) && !strcmp (ext, ".xml"))) {
+			/* pilot map file - src and dest file formats are identical */
+			unsigned char inbuf[4096];
+			size_t nread, nwritten;
+			int fd0, fd1;
+			ssize_t n;
+
+			filename = g_build_filename (old_path, dent, NULL);
+			if ((fd0 = g_open (filename, O_RDONLY|O_BINARY, 0)) == -1) {
+				g_free (filename);
+				continue;
+			}
+
+			g_free (filename);
+			filename = g_build_filename (new_path, dent, NULL);
+			if ((fd1 = g_open (filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666)) == -1) {
+				g_free (filename);
+				close (fd0);
+				continue;
+			}
+
+			do {
+				do {
+					n = read (fd0, inbuf, sizeof (inbuf));
+				} while (n == -1 && errno == EINTR);
+
+				if (n < 1)
+					break;
+
+				nread = n;
+				nwritten = 0;
+				do {
+					do {
+						n = write (fd1, inbuf + nwritten, nread - nwritten);
+					} while (n == -1 && errno == EINTR);
+
+					if (n > 0)
+						nwritten += n;
+				} while (nwritten < nread && n != -1);
+
+				if (n == -1)
+					break;
+			} while (1);
+
+			if (n != -1)
+				n = fsync (fd1);
+
+			if (n == -1) {
+				g_warning ("Failed to migrate %s: %s", dent, strerror (errno));
+				g_unlink (filename);
+			}
+
+			close (fd0);
+			close (fd1);
+			g_free (filename);
+		} else if (!strncmp (dent, changelog, strlen (changelog)) &&
+			   ((ext = strrchr (dent, '.')) && !strcmp (ext, ".db"))) {
+			/* src and dest formats differ, src format is db3 while dest format is xml */
+			EXmlHash *xmlhash;
+			EDbHash *dbhash;
+			struct stat st;
+
+			filename = g_build_filename (old_path, dent, NULL);
+			if (g_stat (filename, &st) == -1) {
+				g_free (filename);
+				continue;
+			}
+
+			dbhash = e_dbhash_new (filename);
+			g_free (filename);
+
+			filename = g_strdup_printf ("%s/%s.ics-%s", new_path, component, dent);
+			if (g_stat (filename, &st) != -1)
+				g_unlink (filename);
+			xmlhash = e_xmlhash_new (filename);
+			g_free (filename);
+
+			e_dbhash_foreach_key (dbhash, migrate_pilot_db_key, xmlhash);
+
+			e_dbhash_destroy (dbhash);
+
+			e_xmlhash_write (xmlhash);
+			e_xmlhash_destroy (xmlhash);
+		}
+	}
+
+	g_dir_close (dir);
+}
+
+#endif
+
+static ESourceGroup *
+create_calendar_contact_source (ESourceList *source_list)
+{
+	ESourceGroup *group;
+	ESource *source;
+
+	/* Create the contacts group */
+	group = e_source_group_new (_("Contacts"), CONTACTS_BASE_URI);
+	e_source_list_add_group (source_list, group, -1);
+
+	source = e_source_new (_("Birthdays & Anniversaries"), "/");
+	e_source_group_add_source (group, source, -1);
+	g_object_unref (source);
+
+	e_source_set_color_spec (source, "#FED4D3");
+	e_source_group_set_readonly (group, TRUE);
+
+	return group;
+}
+
+static void
+create_calendar_sources (EShellModule *shell_module,
+			 ESourceList *source_list,
+			 ESourceGroup **on_this_computer,
+			 ESource **personal_source,
+			 ESourceGroup **on_the_web,
+			 ESourceGroup **contacts)
+{
+	GSList *groups;
+	ESourceGroup *group;
+	char *base_uri, *base_uri_proto;
+	const gchar *base_dir;
+
+	*on_this_computer = NULL;
+	*on_the_web = NULL;
+	*contacts = NULL;
+	*personal_source = NULL;
+
+	base_dir = e_shell_module_get_config_dir (shell_module);
+	base_uri = g_build_filename (base_dir, "local", NULL);
+
+	base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL);
+
+	groups = e_source_list_peek_groups (source_list);
+	if (groups) {
+		/* groups are already there, we need to search for things... */
+		GSList *g;
+
+		for (g = groups; g; g = g->next) {
+
+			group = E_SOURCE_GROUP (g->data);
+
+			if (!strcmp (BAD_CONTACTS_BASE_URI, e_source_group_peek_base_uri (group)))
+				e_source_group_set_base_uri (group, CONTACTS_BASE_URI);
+
+			if (!strcmp (base_uri, e_source_group_peek_base_uri (group)))
+				e_source_group_set_base_uri (group, base_uri_proto);
+
+			if (!*on_this_computer && !strcmp (base_uri_proto, e_source_group_peek_base_uri (group)))
+				*on_this_computer = g_object_ref (group);
+			else if (!*on_the_web && !strcmp (WEBCAL_BASE_URI, e_source_group_peek_base_uri (group)))
+				*on_the_web = g_object_ref (group);
+			else if (!*contacts && !strcmp (CONTACTS_BASE_URI, e_source_group_peek_base_uri (group)))
+				*contacts = g_object_ref (group);
+		}
+	}
+
+	if (*on_this_computer) {
+		/* make sure "Personal" shows up as a source under
+		   this group */
+		GSList *sources = e_source_group_peek_sources (*on_this_computer);
+		GSList *s;
+		for (s = sources; s; s = s->next) {
+			ESource *source = E_SOURCE (s->data);
+			const gchar *relative_uri;
+
+			relative_uri = e_source_peek_relative_uri (source);
+			if (relative_uri == NULL)
+				continue;
+			if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) {
+				*personal_source = g_object_ref (source);
+				break;
+			}
+		}
+	} else {
+		/* create the local source group */
+		group = e_source_group_new (_("On This Computer"), base_uri_proto);
+		e_source_list_add_group (source_list, group, -1);
+
+		*on_this_computer = group;
+	}
+
+	if (!*personal_source) {
+		char *primary_calendar = calendar_config_get_primary_calendar ();
+
+		/* Create the default Person calendar */
+		ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI);
+		e_source_group_add_source (*on_this_computer, source, -1);
+
+		if (!primary_calendar && !calendar_config_get_calendars_selected ()) {
+			GSList selected;
+
+			calendar_config_set_primary_calendar (e_source_peek_uid (source));
+
+			selected.data = (gpointer)e_source_peek_uid (source);
+			selected.next = NULL;
+			calendar_config_set_calendars_selected (&selected);
+		}
+
+		g_free (primary_calendar);
+		e_source_set_color_spec (source, "#BECEDD");
+		*personal_source = source;
+	}
+
+	if (!*on_the_web) {
+		/* Create the Webcal source group */
+		group = e_source_group_new (_("On The Web"), WEBCAL_BASE_URI);
+		e_source_list_add_group (source_list, group, -1);
+
+		*on_the_web = group;
+	}
+
+	if (!*contacts) {
+		group = create_calendar_contact_source (source_list);
+
+		*contacts = group;
+	}
+
+	g_free (base_uri_proto);
+	g_free (base_uri);
+}
+
+gboolean
+e_cal_shell_module_migrate (EShellModule *shell_module,
+                            gint major,
+                            gint minor,
+                            gint micro,
+                            GError **error)
+{
+	ESourceGroup *on_this_computer = NULL, *on_the_web = NULL, *contacts = NULL;
+	ESource *personal_source = NULL;
+	ESourceList *source_list;
+	ECalEvent *ece;
+	ECalEventTargetModule *target;
+	gboolean retval = FALSE;
+
+	source_list = g_object_get_data (
+		G_OBJECT (shell_module), "source-list");
+
+	/* we call this unconditionally now - create_groups either
+	   creates the groups/sources or it finds the necessary
+	   groups/sources. */
+	create_calendar_sources (
+		shell_module, source_list, &on_this_computer,
+		&personal_source, &on_the_web, &contacts);
+
+#ifndef G_OS_WIN32
+	if (major == 1) {
+		xmlDocPtr config_doc = NULL;
+		char *conf_file;
+		struct stat st;
+
+		conf_file = g_build_filename (g_get_home_dir (), "evolution", "config.xmldb", NULL);
+		if (lstat (conf_file, &st) == 0 && S_ISREG (st.st_mode))
+			config_doc = xmlParseFile (conf_file);
+		g_free (conf_file);
+
+		if (config_doc && minor <= 2) {
+			GConfClient *gconf;
+			int res = 0;
+
+			/* move bonobo config to gconf */
+			gconf = gconf_client_get_default ();
+
+			res = e_bconf_import (gconf, config_doc, calendar_remap_list);
+
+			g_object_unref (gconf);
+
+			xmlFreeDoc(config_doc);
+
+			if (res != 0) {
+				/* FIXME: set proper domain/code */
+				g_set_error(error, 0, 0, _("Unable to migrate old settings from evolution/config.xmldb"));
+				goto fail;
+			}
+		}
+
+		if (minor <= 4) {
+			GSList *migration_dirs, *l;
+			char *path, *local_cal_folder;
+
+			setup_progress_dialog ();
+
+			path = g_build_filename (g_get_home_dir (), "evolution", "local", NULL);
+			migration_dirs = e_folder_map_local_folders (path, "calendar");
+			local_cal_folder = g_build_filename (path, "Calendar", NULL);
+			g_free (path);
+
+			if (personal_source)
+				migrate_ical_folder_to_source (local_cal_folder, personal_source, E_CAL_SOURCE_TYPE_EVENT);
+
+			for (l = migration_dirs; l; l = l->next) {
+				char *source_name;
+
+				if (personal_source && !strcmp ((char*)l->data, local_cal_folder))
+					continue;
+
+				source_name = get_source_name (on_this_computer, (char*)l->data);
+
+				if (!migrate_ical_folder (l->data, on_this_computer, source_name, E_CAL_SOURCE_TYPE_EVENT)) {
+					/* FIXME: domain/code */
+					g_set_error(error, 0, 0, _("Unable to migrate calendar `%s'"), source_name);
+					g_free(source_name);
+					goto fail;
+				}
+
+				g_free (source_name);
+			}
+
+			g_free (local_cal_folder);
+
+			dialog_close ();
+		}
+
+		if (minor <= 4 || (minor == 5 && micro < 5)) {
+			GConfClient *gconf;
+			GConfValue *gconf_val;
+			int i;
+			const char *keys[] = {
+				CALENDAR_CONFIG_HPANE_POS,
+				CALENDAR_CONFIG_VPANE_POS,
+				CALENDAR_CONFIG_MONTH_HPANE_POS,
+				CALENDAR_CONFIG_MONTH_VPANE_POS,
+				NULL
+			};
+
+			gconf = gconf_client_get_default ();
+
+			for (i = 0; keys[i]; i++) {
+				gconf_val = gconf_client_get (gconf, keys[i], NULL);
+				if (gconf_val) {
+					if (gconf_val->type != GCONF_VALUE_INT)
+						gconf_client_unset (gconf, keys[i], NULL);
+					gconf_value_free (gconf_val);
+				}
+			}
+
+			g_object_unref (gconf);
+		}
+
+		if (minor < 5 || (minor == 5 && micro <= 10)) {
+			char *old_path, *new_path;
+
+			old_path = g_build_filename (g_get_home_dir (), "evolution", "local", "Calendar", NULL);
+			new_path = g_build_filename (e_shell_module_get_config_dir (shell_module),
+						     "local", "system", NULL);
+			migrate_pilot_data ("calendar", "calendar", old_path, new_path);
+			g_free (new_path);
+			g_free (old_path);
+		}
+
+		/* we only need to do this next step if people ran
+		   older versions of 1.5.  We need to clear out the
+		   absolute URI's that were assigned to ESources
+		   during one phase of development, as they take
+		   precedent over relative uris (but aren't updated
+		   when editing an ESource). */
+		if (minor == 5 && micro <= 11) {
+			GSList *g;
+			for (g = e_source_list_peek_groups (source_list); g; g = g->next) {
+				ESourceGroup *group = g->data;
+				GSList *s;
+
+				for (s = e_source_group_peek_sources (group); s; s = s->next) {
+					ESource *source = s->data;
+					e_source_set_absolute_uri (source, NULL);
+				}
+			}
+		}
+
+	}
+#endif	/* !G_OS_WIN32 */
+
+	e_source_list_sync (source_list, NULL);
+
+	/** @Event: component.migration
+	 * @Title: Migration step in component initialization
+	 * @Target: ECalEventTargetComponent
+	 *
+	 * component.migration is emitted during the calendar component
+	 * initialization process. This allows new calendar backend types
+	 * to be distributed as an e-d-s backend and a plugin without
+	 * reaching their grubby little fingers into migration.c
+	 */
+	/* Fire off migration event */
+	ece = e_cal_event_peek ();
+	target = e_cal_event_target_new_module (ece, shell_module, 0);
+	e_event_emit ((EEvent *) ece, "module.migration", (EEventTarget *) target);
+
+	retval = TRUE;
+fail:
+	if (on_this_computer)
+		g_object_unref (on_this_computer);
+	if (on_the_web)
+		g_object_unref (on_the_web);
+	if (contacts)
+		g_object_unref (contacts);
+	if (personal_source)
+		g_object_unref (personal_source);
+
+	return retval;
+}
+

Added: branches/kill-bonobo/calendar/modules/e-cal-shell-module-migrate.h
==============================================================================
--- (empty file)
+++ branches/kill-bonobo/calendar/modules/e-cal-shell-module-migrate.h	Sun Oct  5 04:12:09 2008
@@ -0,0 +1,38 @@
+/*
+ * e-cal-shell-module-migrate.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>  
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_CAL_SHELL_MODULE_MIGRATE_H
+#define E_CAL_SHELL_MODULE_MIGRATE_H
+
+#include <glib.h>
+#include <shell/e-shell-module.h>
+
+G_BEGIN_DECLS
+
+gboolean	e_cal_shell_module_migrate	(EShellModule *shell_module,
+						 gint major,
+						 gint minor,
+						 gint micro,
+						 GError **error);
+
+G_END_DECLS
+
+#endif /* E_CAL_SHELL_MODULE_MIGRATE_H */

Modified: branches/kill-bonobo/calendar/modules/e-cal-shell-module.c
==============================================================================
--- branches/kill-bonobo/calendar/modules/e-cal-shell-module.c	(original)
+++ branches/kill-bonobo/calendar/modules/e-cal-shell-module.c	Sun Oct  5 04:12:09 2008
@@ -33,6 +33,7 @@
 #include "calendar/gui/calendar-config.h"
 
 #include "e-cal-shell-view.h"
+#include "e-cal-shell-module-migrate.h"
 
 #define MODULE_NAME		"calendar"
 #define MODULE_ALIASES		""
@@ -370,7 +371,11 @@
 	MODULE_NAME,
 	MODULE_ALIASES,
 	MODULE_SCHEMES,
-	MODULE_SORT_ORDER
+	MODULE_SORT_ORDER,
+
+	/* is_busy */ NULL,
+	/* shutdown */ NULL,
+	e_cal_shell_module_migrate
 };
 
 void

Added: branches/kill-bonobo/calendar/modules/e-memo-shell-module-migrate.c
==============================================================================
--- (empty file)
+++ branches/kill-bonobo/calendar/modules/e-memo-shell-module-migrate.c	Sun Oct  5 04:12:09 2008
@@ -0,0 +1,257 @@
+/*
+ * e-memo-shell-module-migrate.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>  
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-memo-shell-module-migrate.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <camel/camel-url.h>
+#include <libedataserver/e-account.h>
+#include <libedataserver/e-account-list.h>
+#include <libedataserver/e-source.h>
+#include <libedataserver/e-source-group.h>
+#include <libedataserver/e-source-list.h>
+
+#include "calendar/gui/calendar-config.h"
+#include "calendar/gui/calendar-config-keys.h"
+
+#define WEBCAL_BASE_URI "webcal://"
+#define PERSONAL_RELATIVE_URI "system"
+#define GROUPWISE_BASE_URI "groupwise://"
+
+static void
+create_memo_sources (EShellModule *shell_module,
+		     ESourceList *source_list,
+		     ESourceGroup **on_this_computer,
+		     ESourceGroup **on_the_web,
+		     ESource **personal_source)
+{
+	GSList *groups;
+	ESourceGroup *group;
+	char *base_uri, *base_uri_proto;
+	const gchar *base_dir;
+
+	*on_this_computer = NULL;
+	*on_the_web = NULL;
+	*personal_source = NULL;
+
+	base_dir = e_shell_module_get_config_dir (shell_module);
+	base_uri = g_build_filename (base_dir, "local", NULL);
+
+	base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL);
+
+	groups = e_source_list_peek_groups (source_list);
+	if (groups) {
+		/* groups are already there, we need to search for things... */
+		GSList *g;
+
+		for (g = groups; g; g = g->next) {
+
+			group = E_SOURCE_GROUP (g->data);
+
+			if (!*on_this_computer && !strcmp (base_uri_proto, e_source_group_peek_base_uri (group)))
+				*on_this_computer = g_object_ref (group);
+			else if (!*on_the_web && !strcmp (WEBCAL_BASE_URI, e_source_group_peek_base_uri (group)))
+				*on_the_web = g_object_ref (group);
+		}
+	}
+
+	if (*on_this_computer) {
+		/* make sure "Personal" shows up as a source under
+		   this group */
+		GSList *sources = e_source_group_peek_sources (*on_this_computer);
+		GSList *s;
+		for (s = sources; s; s = s->next) {
+			ESource *source = E_SOURCE (s->data);
+			const gchar *relative_uri;
+
+			relative_uri = e_source_peek_relative_uri (source);
+			if (relative_uri == NULL)
+				continue;
+			if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) {
+				*personal_source = g_object_ref (source);
+				break;
+			}
+		}
+	} else {
+		/* create the local source group */
+		group = e_source_group_new (_("On This Computer"), base_uri_proto);
+		e_source_list_add_group (source_list, group, -1);
+
+		*on_this_computer = group;
+	}
+
+	if (!*personal_source) {
+		/* Create the default Person task list */
+		ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI);
+		e_source_group_add_source (*on_this_computer, source, -1);
+
+		if (!calendar_config_get_primary_memos () && !calendar_config_get_memos_selected ()) {
+			GSList selected;
+
+			calendar_config_set_primary_memos (e_source_peek_uid (source));
+
+			selected.data = (gpointer)e_source_peek_uid (source);
+			selected.next = NULL;
+			calendar_config_set_memos_selected (&selected);
+		}
+
+		e_source_set_color_spec (source, "#BECEDD");
+		*personal_source = source;
+	}
+
+	if (!*on_the_web) {
+		/* Create the Webcal source group */
+		group = e_source_group_new (_("On The Web"), WEBCAL_BASE_URI);
+		e_source_list_add_group (source_list, group, -1);
+
+		*on_the_web = group;
+	}
+
+	g_free (base_uri_proto);
+	g_free (base_uri);
+}
+
+static gboolean
+is_groupwise_account (EAccount *account)
+{
+	if (account->source->url != NULL) {
+		return g_str_has_prefix (account->source->url, GROUPWISE_BASE_URI);
+	} else {
+		return FALSE;
+	}
+}
+
+static void
+add_gw_esource (ESourceList *source_list, const char *group_name,  const char *source_name, CamelURL *url, GConfClient *client)
+{
+	ESourceGroup *group;
+	ESource *source;
+	GSList *ids, *temp ;
+	GError *error = NULL;
+	char *relative_uri;
+	const char *soap_port;
+	const char * use_ssl;
+	const char *poa_address;
+	const char *offline_sync;
+
+
+	poa_address = url->host;
+	if (!poa_address || strlen (poa_address) ==0)
+		return;
+	soap_port = camel_url_get_param (url, "soap_port");
+
+ 	if (!soap_port || strlen (soap_port) == 0)
+		soap_port = "7191";
+
+	use_ssl = camel_url_get_param (url, "use_ssl");
+	offline_sync = camel_url_get_param (url, "offline_sync");
+
+	group = e_source_group_new (group_name,  GROUPWISE_BASE_URI);
+	if (!e_source_list_add_group (source_list, group, -1))
+		return;
+	relative_uri = g_strdup_printf ("%s %s/", url->user, poa_address);
+
+	source = e_source_new (source_name, relative_uri);
+	e_source_set_property (source, "auth", "1");
+	e_source_set_property (source, "username", url->user);
+	e_source_set_property (source, "port", camel_url_get_param (url, "soap_port"));
+	e_source_set_property (source, "auth-domain", "Groupwise");
+	e_source_set_property (source, "use_ssl", use_ssl);
+	e_source_set_property (source, "offline_sync", offline_sync ? "1" : "0" );
+
+	e_source_set_color_spec (source, "#EEBC60");
+	e_source_group_add_source (group, source, -1);
+
+	ids = gconf_client_get_list (client, CALENDAR_CONFIG_MEMOS_SELECTED_MEMOS, GCONF_VALUE_STRING, &error);
+	if ( error != NULL ) {
+		g_warning("%s (%s) %s\n", G_STRLOC, G_STRFUNC, error->message);
+		g_error_free(error);
+	}
+	ids = g_slist_append (ids, g_strdup (e_source_peek_uid (source)));
+	gconf_client_set_list (client, CALENDAR_CONFIG_MEMOS_SELECTED_MEMOS, GCONF_VALUE_STRING, ids, NULL);
+	temp  = ids;
+	for (; temp != NULL; temp = g_slist_next (temp))
+		g_free (temp->data);
+
+	g_slist_free (ids);
+	g_object_unref (source);
+	g_object_unref (group);
+	g_free (relative_uri);
+}
+
+gboolean
+e_memo_shell_module_migrate (EShellModule *shell_module,
+                             gint major,
+                             gint minor,
+                             gint revision,
+                             GError **error)
+{
+	ESourceGroup *on_this_computer = NULL;
+	ESourceGroup *on_the_web = NULL;
+	ESource *personal_source = NULL;
+	ESourceList *source_list = NULL;
+	gboolean retval = FALSE;
+
+	source_list = g_object_get_data (
+		G_OBJECT (shell_module), "source-list");
+
+	/* we call this unconditionally now - create_groups either
+	   creates the groups/sources or it finds the necessary
+	   groups/sources. */
+	create_memo_sources (
+		shell_module, source_list, &on_this_computer,
+		&on_the_web, &personal_source);
+
+	/* Migration for Gw accounts between versions < 2.8 */
+	if (major == 2 && minor < 8) {
+		EAccountList *al;
+		EAccount *a;
+		CamelURL *url;
+		EIterator *it;
+		GConfClient *gconf_client = gconf_client_get_default ();
+		al = e_account_list_new (gconf_client);
+		for (it = e_list_get_iterator((EList *)al);
+				e_iterator_is_valid(it);
+				e_iterator_next(it)) {
+			a = (EAccount *) e_iterator_get(it);
+			if (!a->enabled || !is_groupwise_account (a))
+				continue;
+			url = camel_url_new (a->source->url, NULL);
+			add_gw_esource (source_list, a->name, _("Notes"), url, gconf_client);
+			camel_url_free (url);
+		}
+		g_object_unref (al);
+		g_object_unref (gconf_client);
+	}
+
+	e_source_list_sync (source_list, NULL);
+	retval = TRUE;
+
+	if (on_this_computer)
+		g_object_unref (on_this_computer);
+	if (on_the_web)
+		g_object_unref (on_the_web);
+	if (personal_source)
+		g_object_unref (personal_source);
+
+        return retval;
+}

Added: branches/kill-bonobo/calendar/modules/e-memo-shell-module-migrate.h
==============================================================================
--- (empty file)
+++ branches/kill-bonobo/calendar/modules/e-memo-shell-module-migrate.h	Sun Oct  5 04:12:09 2008
@@ -0,0 +1,38 @@
+/*
+ * e-memo-shell-module-migrate.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>  
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_MEMO_SHELL_MODULE_MIGRATE_H
+#define E_MEMO_SHELL_MODULE_MIGRATE_H
+
+#include <glib.h>
+#include <shell/e-shell-module.h>
+
+G_BEGIN_DECLS
+
+gboolean	e_memo_shell_module_migrate	(EShellModule *shell_module,
+						 gint major,
+						 gint minor,
+						 gint micro,
+						 GError **error);
+
+G_END_DECLS
+
+#endif /* E_MEMO_SHELL_MODULE_MIGRATE_H */

Modified: branches/kill-bonobo/calendar/modules/e-memo-shell-module.c
==============================================================================
--- branches/kill-bonobo/calendar/modules/e-memo-shell-module.c	(original)
+++ branches/kill-bonobo/calendar/modules/e-memo-shell-module.c	Sun Oct  5 04:12:09 2008
@@ -38,6 +38,7 @@
 #include "calendar/gui/dialogs/memo-editor.h"
 
 #include "e-memo-shell-view.h"
+#include "e-memo-shell-module-migrate.h"
 
 #define MODULE_NAME		"memos"
 #define MODULE_ALIASES		""
@@ -463,7 +464,11 @@
 	MODULE_NAME,
 	MODULE_ALIASES,
 	MODULE_SCHEMES,
-	MODULE_SORT_ORDER
+	MODULE_SORT_ORDER,
+
+	/* is_busy */ NULL,
+	/* shutdown */ NULL,
+	e_memo_shell_module_migrate
 };
 
 void

Added: branches/kill-bonobo/calendar/modules/e-task-shell-module-migrate.c
==============================================================================
--- (empty file)
+++ branches/kill-bonobo/calendar/modules/e-task-shell-module-migrate.c	Sun Oct  5 04:12:09 2008
@@ -0,0 +1,664 @@
+/*
+ * e-task-shell-module-migrate.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>  
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-task-shell-module-migrate.h"
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <libebackend/e-dbhash.h>
+#include <libedataserver/e-source.h>
+#include <libedataserver/e-source-group.h>
+#include <libedataserver/e-source-list.h>
+#include <libedataserver/e-xml-hash-utils.h>
+#include <libedataserver/e-xml-utils.h>
+
+#include "e-util/e-bconf-map.h"
+#include "e-util/e-folder-map.h"
+#include "e-util/e-util-private.h"
+#include "calendar/gui/calendar-config.h"
+#include "calendar/gui/calendar-config-keys.h"
+
+#define WEBCAL_BASE_URI "webcal://"
+#define PERSONAL_RELATIVE_URI "system"
+
+static e_gconf_map_t calendar_tasks_map[] = {
+	/* /Calendar/Tasks */
+	{ "HideCompletedTasks", "calendar/tasks/hide_completed", E_GCONF_MAP_BOOL },
+	{ "HideCompletedTasksUnits", "calendar/tasks/hide_completed_units", E_GCONF_MAP_STRING },
+	{ "HideCompletedTasksValue", "calendar/tasks/hide_completed_value", E_GCONF_MAP_INT },
+	{ NULL },
+};
+
+static e_gconf_map_t calendar_tasks_colours_map[] = {
+	/* /Calendar/Tasks/Colors */
+	{ "TasksDueToday", "calendar/tasks/colors/due_today", E_GCONF_MAP_STRING },
+	{ "TasksOverDue", "calendar/tasks/colors/overdue", E_GCONF_MAP_STRING },
+	{ "TasksDueToday", "calendar/tasks/colors/due_today", E_GCONF_MAP_STRING },
+	{ NULL },
+};
+
+static e_gconf_map_list_t task_remap_list[] = {
+
+	{ "/Calendar/Tasks", calendar_tasks_map },
+	{ "/Calendar/Tasks/Colors", calendar_tasks_colours_map },
+
+	{ NULL },
+};
+
+static GtkWidget *window;
+static GtkLabel *label;
+static GtkProgressBar *progress;
+
+#ifndef G_OS_WIN32
+
+/* No previous versions have been available on Win32, so don't
+ * bother with upgrade support from 1.x on Win32.
+ */
+
+static void
+setup_progress_dialog (void)
+{
+	GtkWidget *vbox, *hbox, *w;
+
+	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+	gtk_window_set_title ((GtkWindow *) window, _("Migrating..."));
+	gtk_window_set_modal ((GtkWindow *) window, TRUE);
+	gtk_container_set_border_width ((GtkContainer *) window, 6);
+
+	vbox = gtk_vbox_new (FALSE, 6);
+	gtk_widget_show (vbox);
+	gtk_container_add ((GtkContainer *) window, vbox);
+
+	w = gtk_label_new (_("The location and hierarchy of the Evolution task "
+			     "folders has changed since Evolution 1.x.\n\nPlease be "
+			     "patient while Evolution migrates your folders..."));
+
+	gtk_label_set_line_wrap ((GtkLabel *) w, TRUE);
+	gtk_widget_show (w);
+	gtk_box_pack_start_defaults ((GtkBox *) vbox, w);
+
+	hbox = gtk_hbox_new (FALSE, 6);
+	gtk_widget_show (hbox);
+	gtk_box_pack_start_defaults ((GtkBox *) vbox, hbox);
+
+	label = (GtkLabel *) gtk_label_new ("");
+	gtk_widget_show ((GtkWidget *) label);
+	gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) label);
+
+	progress = (GtkProgressBar *) gtk_progress_bar_new ();
+	gtk_widget_show ((GtkWidget *) progress);
+	gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) progress);
+
+	gtk_widget_show (window);
+}
+
+static void
+dialog_close (void)
+{
+	gtk_widget_destroy ((GtkWidget *) window);
+}
+
+static void
+dialog_set_folder_name (const char *folder_name)
+{
+	char *text;
+
+	text = g_strdup_printf (_("Migrating '%s':"), folder_name);
+	gtk_label_set_text (label, text);
+	g_free (text);
+
+	gtk_progress_bar_set_fraction (progress, 0.0);
+
+	while (gtk_events_pending ())
+		gtk_main_iteration ();
+}
+
+static void
+dialog_set_progress (double percent)
+{
+	char text[5];
+
+	snprintf (text, sizeof (text), "%d%%", (int) (percent * 100.0f));
+
+	gtk_progress_bar_set_fraction (progress, percent);
+	gtk_progress_bar_set_text (progress, text);
+
+	while (gtk_events_pending ())
+		gtk_main_iteration ();
+}
+
+static gboolean
+check_for_conflict (ESourceGroup *group, char *name)
+{
+	GSList *sources;
+	GSList *s;
+
+	sources = e_source_group_peek_sources (group);
+
+	for (s = sources; s; s = s->next) {
+		ESource *source = E_SOURCE (s->data);
+
+		if (!strcmp (e_source_peek_name (source), name))
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+static char *
+get_source_name (ESourceGroup *group, const char *path)
+{
+	char **p = g_strsplit (path, "/", 0);
+	int i, j, starting_index;
+	int num_elements;
+	gboolean conflict;
+	GString *s = g_string_new (NULL);
+
+	for (i = 0; p[i]; i ++) ;
+
+	num_elements = i;
+	i--;
+
+	/* p[i] is now the last path element */
+
+	/* check if it conflicts */
+	starting_index = i;
+	do {
+		for (j = starting_index; j < num_elements; j += 2) {
+			if (j != starting_index)
+				g_string_append_c (s, '_');
+			g_string_append (s, p[j]);
+		}
+
+		conflict = check_for_conflict (group, s->str);
+
+
+		/* if there was a conflict back up 2 levels (skipping the /subfolder/ element) */
+		if (conflict)
+			starting_index -= 2;
+
+		/* we always break out if we can't go any further,
+		   regardless of whether or not we conflict. */
+		if (starting_index < 0)
+			break;
+
+	} while (conflict);
+	g_strfreev (p);
+
+	return g_string_free (s, FALSE);
+}
+
+static gboolean
+migrate_ical (ECal *old_ecal, ECal *new_ecal)
+{
+	GList *l, *objects;
+	int num_added = 0;
+	int num_objects;
+	gboolean retval = TRUE;
+
+	/* both ecals are loaded, start the actual migration */
+	if (!e_cal_get_object_list (old_ecal, "#t", &objects, NULL))
+		return FALSE;
+
+	num_objects = g_list_length (objects);
+	for (l = objects; l; l = l->next) {
+		icalcomponent *ical_comp = l->data;
+		GError *error = NULL;
+
+		if (!e_cal_create_object (new_ecal, ical_comp, NULL, &error)) {
+			g_warning ("Migration of object failed: %s", error->message);
+			retval = FALSE;
+		}
+
+		g_clear_error (&error);
+
+		num_added ++;
+		dialog_set_progress ((double)num_added / num_objects);
+	}
+
+	g_list_foreach (objects, (GFunc) icalcomponent_free, NULL);
+	g_list_free (objects);
+
+	return retval;
+}
+
+static gboolean
+migrate_ical_folder_to_source (char *old_path, ESource *new_source, ECalSourceType type)
+{
+	ECal *old_ecal = NULL, *new_ecal = NULL;
+	ESource *old_source;
+	ESourceGroup *group;
+	char *old_uri = g_strdup_printf ("file://%s", old_path);
+	GError *error = NULL;
+	gboolean retval = FALSE;
+
+	group = e_source_group_new ("", old_uri);
+	old_source = e_source_new ("", "");
+	e_source_group_add_source (group, old_source, -1);
+
+	dialog_set_folder_name (e_source_peek_name (new_source));
+
+	if (!(old_ecal = e_cal_new (old_source, type))) {
+		g_warning ("could not find a backend for '%s'", e_source_get_uri (old_source));
+		goto finish;
+	}
+	if (!e_cal_open (old_ecal, FALSE, &error)) {
+		g_warning ("failed to load source ecal for migration: '%s' (%s)", error->message,
+			   e_source_get_uri (old_source));
+		goto finish;
+	}
+
+	if (!(new_ecal = e_cal_new (new_source, type))) {
+		g_warning ("could not find a backend for '%s'", e_source_get_uri (new_source));
+		goto finish;
+	}
+	if (!e_cal_open (new_ecal, FALSE, &error)) {
+		g_warning ("failed to load destination ecal for migration: '%s' (%s)", error->message,
+			   e_source_get_uri (new_source));
+		goto finish;
+	}
+
+	retval = migrate_ical (old_ecal, new_ecal);
+
+finish:
+	g_clear_error (&error);
+	if (old_ecal)
+		g_object_unref (old_ecal);
+	g_object_unref (group);
+	if (new_ecal)
+		g_object_unref (new_ecal);
+	g_free (old_uri);
+
+	return retval;
+}
+
+static gboolean
+migrate_ical_folder (char *old_path, ESourceGroup *dest_group, char *source_name, ECalSourceType type)
+{
+	ESource *new_source;
+	gboolean retval;
+
+	new_source = e_source_new (source_name, source_name);
+	e_source_set_relative_uri (new_source, e_source_peek_uid (new_source));
+	e_source_group_add_source (dest_group, new_source, -1);
+
+	retval = migrate_ical_folder_to_source (old_path, new_source, type);
+
+	g_object_unref (new_source);
+
+	return retval;
+}
+
+#endif	/* !G_OS_WIN32 */
+
+#ifndef G_OS_WIN32
+
+static void
+migrate_pilot_db_key (const char *key, gpointer user_data)
+{
+	EXmlHash *xmlhash = user_data;
+
+	e_xmlhash_add (xmlhash, key, "");
+}
+
+static void
+migrate_pilot_data (const char *component, const char *conduit, const char *old_path, const char *new_path)
+{
+	char *changelog, *map;
+	const char *dent;
+	const char *ext;
+	char *filename;
+	GDir *dir;
+
+	if (!(dir = g_dir_open (old_path, 0, NULL)))
+		return;
+
+	map = g_alloca (12 + strlen (conduit));
+	sprintf (map, "pilot-map-%s-", conduit);
+
+	changelog = g_alloca (24 + strlen (conduit));
+	sprintf (changelog, "pilot-sync-evolution-%s-", conduit);
+
+	while ((dent = g_dir_read_name (dir))) {
+		if (!strncmp (dent, map, strlen (map)) &&
+		    ((ext = strrchr (dent, '.')) && !strcmp (ext, ".xml"))) {
+			/* pilot map file - src and dest file formats are identical */
+			unsigned char inbuf[4096];
+			size_t nread, nwritten;
+			int fd0, fd1;
+			ssize_t n;
+
+			filename = g_build_filename (old_path, dent, NULL);
+			if ((fd0 = g_open (filename, O_RDONLY|O_BINARY, 0)) == -1) {
+				g_free (filename);
+				continue;
+			}
+
+			g_free (filename);
+			filename = g_build_filename (new_path, dent, NULL);
+			if ((fd1 = g_open (filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666)) == -1) {
+				g_free (filename);
+				close (fd0);
+				continue;
+			}
+
+			do {
+				do {
+					n = read (fd0, inbuf, sizeof (inbuf));
+				} while (n == -1 && errno == EINTR);
+
+				if (n < 1)
+					break;
+
+				nread = n;
+				nwritten = 0;
+				do {
+					do {
+						n = write (fd1, inbuf + nwritten, nread - nwritten);
+					} while (n == -1 && errno == EINTR);
+
+					if (n > 0)
+						nwritten += n;
+				} while (nwritten < nread && n != -1);
+
+				if (n == -1)
+					break;
+			} while (1);
+
+			if (n != -1)
+				n = fsync (fd1);
+
+			if (n == -1) {
+				g_warning ("Failed to migrate %s: %s", dent, strerror (errno));
+				g_unlink (filename);
+			}
+
+			close (fd0);
+			close (fd1);
+			g_free (filename);
+		} else if (!strncmp (dent, changelog, strlen (changelog)) &&
+			   ((ext = strrchr (dent, '.')) && !strcmp (ext, ".db"))) {
+			/* src and dest formats differ, src format is db3 while dest format is xml */
+			EXmlHash *xmlhash;
+			EDbHash *dbhash;
+			struct stat st;
+
+			filename = g_build_filename (old_path, dent, NULL);
+			if (g_stat (filename, &st) == -1) {
+				g_free (filename);
+				continue;
+			}
+
+			dbhash = e_dbhash_new (filename);
+			g_free (filename);
+
+			filename = g_strdup_printf ("%s/%s.ics-%s", new_path, component, dent);
+			if (g_stat (filename, &st) != -1)
+				g_unlink (filename);
+			xmlhash = e_xmlhash_new (filename);
+			g_free (filename);
+
+			e_dbhash_foreach_key (dbhash, migrate_pilot_db_key, xmlhash);
+
+			e_dbhash_destroy (dbhash);
+
+			e_xmlhash_write (xmlhash);
+			e_xmlhash_destroy (xmlhash);
+		}
+	}
+
+	g_dir_close (dir);
+}
+
+#endif
+
+static void
+create_task_sources (EShellModule *shell_module,
+		     ESourceList *source_list,
+		     ESourceGroup **on_this_computer,
+		     ESourceGroup **on_the_web,
+		     ESource **personal_source)
+{
+	GSList *groups;
+	ESourceGroup *group;
+	char *base_uri, *base_uri_proto;
+	const gchar *base_dir;
+
+	*on_this_computer = NULL;
+	*on_the_web = NULL;
+	*personal_source = NULL;
+
+	base_dir = e_shell_module_get_config_dir (shell_module);
+	base_uri = g_build_filename (base_dir, "local", NULL);
+
+	base_uri_proto = g_filename_to_uri (base_uri, NULL, NULL);
+
+	groups = e_source_list_peek_groups (source_list);
+	if (groups) {
+		/* groups are already there, we need to search for things... */
+		GSList *g;
+
+		for (g = groups; g; g = g->next) {
+
+			group = E_SOURCE_GROUP (g->data);
+
+			if (!*on_this_computer && !strcmp (base_uri_proto, e_source_group_peek_base_uri (group)))
+				*on_this_computer = g_object_ref (group);
+			else if (!*on_the_web && !strcmp (WEBCAL_BASE_URI, e_source_group_peek_base_uri (group)))
+				*on_the_web = g_object_ref (group);
+		}
+	}
+
+	if (*on_this_computer) {
+		/* make sure "Personal" shows up as a source under
+		   this group */
+		GSList *sources = e_source_group_peek_sources (*on_this_computer);
+		GSList *s;
+		for (s = sources; s; s = s->next) {
+			ESource *source = E_SOURCE (s->data);
+			const gchar *relative_uri;
+
+			relative_uri = e_source_peek_relative_uri (source);
+			if (relative_uri == NULL)
+				continue;
+			if (!strcmp (PERSONAL_RELATIVE_URI, relative_uri)) {
+				*personal_source = g_object_ref (source);
+				break;
+			}
+		}
+	} else {
+		/* create the local source group */
+		group = e_source_group_new (_("On This Computer"), base_uri_proto);
+		e_source_list_add_group (source_list, group, -1);
+
+		*on_this_computer = group;
+	}
+
+	if (!*personal_source) {
+		/* Create the default Person task list */
+		ESource *source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI);
+		e_source_group_add_source (*on_this_computer, source, -1);
+
+		if (!calendar_config_get_primary_tasks () && !calendar_config_get_tasks_selected ()) {
+			GSList selected;
+
+			calendar_config_set_primary_tasks (e_source_peek_uid (source));
+
+			selected.data = (gpointer)e_source_peek_uid (source);
+			selected.next = NULL;
+			calendar_config_set_tasks_selected (&selected);
+		}
+
+		e_source_set_color_spec (source, "#BECEDD");
+		*personal_source = source;
+	}
+
+	if (!*on_the_web) {
+		/* Create the Webcal source group */
+		group = e_source_group_new (_("On The Web"), WEBCAL_BASE_URI);
+		e_source_list_add_group (source_list, group, -1);
+
+		*on_the_web = group;
+	}
+
+	g_free (base_uri_proto);
+	g_free (base_uri);
+}
+
+gboolean
+e_task_shell_module_migrate (EShellModule *shell_module,
+                             gint major,
+                             gint minor,
+                             gint micro,
+                             GError **error)
+{
+	ESourceGroup *on_this_computer = NULL;
+	ESourceGroup *on_the_web = NULL;
+	ESource *personal_source = NULL;
+	ESourceList *source_list;
+	gboolean retval = FALSE;
+
+	source_list = g_object_get_data (
+		G_OBJECT (source_list), "source-list");
+
+	/* we call this unconditionally now - create_groups either
+	   creates the groups/sources or it finds the necessary
+	   groups/sources. */
+	create_task_sources (
+		shell_module, source_list, &on_this_computer,
+		&on_the_web, &personal_source);
+
+#ifndef G_OS_WIN32
+	if (major == 1) {
+		xmlDocPtr config_doc = NULL;
+		char *conf_file;
+
+		conf_file = g_build_filename (g_get_home_dir (), "evolution", "config.xmldb", NULL);
+		if (g_file_test (conf_file, G_FILE_TEST_IS_REGULAR))
+			config_doc = e_xml_parse_file (conf_file);
+		g_free (conf_file);
+
+		if (config_doc && minor <= 2) {
+			GConfClient *gconf;
+			int res = 0;
+
+			/* move bonobo config to gconf */
+			gconf = gconf_client_get_default ();
+
+			res = e_bconf_import (gconf, config_doc, task_remap_list);
+
+			g_object_unref (gconf);
+
+			xmlFreeDoc(config_doc);
+
+			if (res != 0) {
+				g_set_error(error, 0, 0, _("Unable to migrate old settings from evolution/config.xmldb"));
+				goto fail;
+			}
+		}
+
+		if (minor <= 4) {
+			GSList *migration_dirs, *l;
+			char *path, *local_task_folder;
+
+			setup_progress_dialog ();
+
+			path = g_build_filename (g_get_home_dir (), "evolution", "local", NULL);
+			migration_dirs = e_folder_map_local_folders (path, "tasks");
+			local_task_folder = g_build_filename (path, "Tasks", NULL);
+			g_free (path);
+
+			if (personal_source)
+				migrate_ical_folder_to_source (local_task_folder, personal_source, E_CAL_SOURCE_TYPE_TODO);
+
+			for (l = migration_dirs; l; l = l->next) {
+				char *source_name;
+
+				if (personal_source && !strcmp ((char*)l->data, local_task_folder))
+					continue;
+
+				source_name = get_source_name (on_this_computer, (char*)l->data);
+
+				if (!migrate_ical_folder (l->data, on_this_computer, source_name, E_CAL_SOURCE_TYPE_TODO)) {
+					/* FIXME: domain/code */
+					g_set_error(error, 0, 0, _("Unable to migrate tasks `%s'"), source_name);
+					g_free(source_name);
+					goto fail;
+				}
+
+				g_free (source_name);
+			}
+
+			g_free (local_task_folder);
+
+			dialog_close ();
+		}
+
+		if (minor < 5 || (minor == 5 && micro <= 10)) {
+			char *old_path, *new_path;
+
+			old_path = g_build_filename (g_get_home_dir (), "evolution", "local", "Tasks", NULL);
+			new_path = g_build_filename (e_shell_module_get_config_dir (shell_module),
+						     "local", "system", NULL);
+			migrate_pilot_data ("tasks", "todo", old_path, new_path);
+			g_free (new_path);
+			g_free (old_path);
+		}
+
+		/* we only need to do this next step if people ran
+		   older versions of 1.5.  We need to clear out the
+		   absolute URI's that were assigned to ESources
+		   during one phase of development, as they take
+		   precedent over relative uris (but aren't updated
+		   when editing an ESource). */
+		if (minor == 5 && micro <= 11) {
+			GSList *g;
+			for (g = e_source_list_peek_groups (source_list); g; g = g->next) {
+				ESourceGroup *group = g->data;
+				GSList *s;
+
+				for (s = e_source_group_peek_sources (group); s; s = s->next) {
+					ESource *source = s->data;
+					e_source_set_absolute_uri (source, NULL);
+				}
+			}
+		}
+	}
+#endif	/* !G_OS_WIN32 */
+	e_source_list_sync (source_list, NULL);
+	retval = TRUE;
+fail:
+	if (on_this_computer)
+		g_object_unref (on_this_computer);
+	if (on_the_web)
+		g_object_unref (on_the_web);
+	if (personal_source)
+		g_object_unref (personal_source);
+
+        return retval;
+}

Added: branches/kill-bonobo/calendar/modules/e-task-shell-module-migrate.h
==============================================================================
--- (empty file)
+++ branches/kill-bonobo/calendar/modules/e-task-shell-module-migrate.h	Sun Oct  5 04:12:09 2008
@@ -0,0 +1,38 @@
+/*
+ * e-task-shell-module-migrate.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>  
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_TASK_SHELL_MODULE_MIGRATE_H
+#define E_TASK_SHELL_MODULE_MIGRATE_H
+
+#include <glib.h>
+#include <shell/e-shell-module.h>
+
+G_BEGIN_DECLS
+
+gboolean	e_task_shell_module_migrate	(EShellModule *shell_module,
+						 gint major,
+						 gint minor,
+						 gint micro,
+						 GError **error);
+
+G_END_DECLS
+
+#endif /* E_TASK_SHELL_MODULE_MIGRATE_H */

Modified: branches/kill-bonobo/calendar/modules/e-task-shell-module.c
==============================================================================
--- branches/kill-bonobo/calendar/modules/e-task-shell-module.c	(original)
+++ branches/kill-bonobo/calendar/modules/e-task-shell-module.c	Sun Oct  5 04:12:09 2008
@@ -38,6 +38,7 @@
 #include "calendar/gui/dialogs/task-editor.h"
 
 #include "e-task-shell-view.h"
+#include "e-task-shell-module-migrate.h"
 
 #define MODULE_NAME		"tasks"
 #define MODULE_ALIASES		""
@@ -469,7 +470,11 @@
         MODULE_NAME,
         MODULE_ALIASES,
         MODULE_SCHEMES,
-        MODULE_SORT_ORDER
+        MODULE_SORT_ORDER,
+
+	/* is_busy */ NULL,
+	/* shutdown */ NULL,
+	e_task_shell_module_migrate
 };
 
 void

Modified: branches/kill-bonobo/calendar/modules/e-task-shell-sidebar.c
==============================================================================
--- branches/kill-bonobo/calendar/modules/e-task-shell-sidebar.c	(original)
+++ branches/kill-bonobo/calendar/modules/e-task-shell-sidebar.c	Sun Oct  5 04:12:09 2008
@@ -434,7 +434,7 @@
 
 	g_signal_connect_swapped (
 		widget, "primary-selection-changed",
-		G_CALLBACK (task_shell_sidebar_selection_changed_cb),
+		G_CALLBACK (task_shell_sidebar_primary_selection_changed_cb),
 		object);
 }
 

Modified: branches/kill-bonobo/doc/reference/shell/Makefile.am
==============================================================================
--- branches/kill-bonobo/doc/reference/shell/Makefile.am	(original)
+++ branches/kill-bonobo/doc/reference/shell/Makefile.am	Sun Oct  5 04:12:09 2008
@@ -76,12 +76,15 @@
 	$(top_builddir)/shell/.libs/e-shell-sidebar.o			\
 	$(top_builddir)/shell/.libs/e-shell-switcher.o			\
 	$(top_builddir)/shell/.libs/e-shell-taskbar.o			\
+	$(top_builddir)/shell/.libs/e-shell-upgrade.o			\
 	$(top_builddir)/shell/.libs/e-shell-view.o			\
 	$(top_builddir)/shell/.libs/e-shell-window-actions.o		\
 	$(top_builddir)/shell/.libs/e-shell-window.o			\
+	$(top_builddir)/e-util/.libs/e-bconf-map.o			\
 	$(top_builddir)/e-util/.libs/e-dialog-utils.o			\
 	$(top_builddir)/e-util/.libs/e-error.o				\
 	$(top_builddir)/e-util/.libs/e-event.o				\
+	$(top_builddir)/e-util/.libs/e-fsutils.o			\
 	$(top_builddir)/e-util/.libs/e-icon-factory.o			\
 	$(top_builddir)/e-util/.libs/e-import.o				\
 	$(top_builddir)/e-util/.libs/e-logger.o				\

Modified: branches/kill-bonobo/doc/reference/shell/eshell-sections.txt
==============================================================================
--- branches/kill-bonobo/doc/reference/shell/eshell-sections.txt	(original)
+++ branches/kill-bonobo/doc/reference/shell/eshell-sections.txt	Sun Oct  5 04:12:09 2008
@@ -19,6 +19,8 @@
 e_shell_is_busy
 e_shell_do_quit
 e_shell_quit
+E_SHELL_UPGRADE_ERROR
+e_shell_upgrade_attempt
 <SUBSECTION Standard>
 E_SHELL
 E_IS_SHELL
@@ -30,6 +32,7 @@
 e_shell_get_type
 <SUBSECTION Private>
 EShellPrivate
+e_shell_upgrade_error_quirk
 </SECTION>
 
 <SECTION>
@@ -94,6 +97,7 @@
 e_shell_module_add_activity
 e_shell_module_is_busy
 e_shell_module_shutdown
+e_shell_module_upgrade
 e_shell_module_set_info
 <SUBSECTION Standard>
 E_SHELL_MODULE

Modified: branches/kill-bonobo/doc/reference/shell/tmpl/e-shell-module.sgml
==============================================================================
--- branches/kill-bonobo/doc/reference/shell/tmpl/e-shell-module.sgml	(original)
+++ branches/kill-bonobo/doc/reference/shell/tmpl/e-shell-module.sgml	Sun Oct  5 04:12:09 2008
@@ -52,6 +52,7 @@
 @sort_order: 
 @is_busy: 
 @shutdown: 
+ upgrade: 
 
 <!-- ##### FUNCTION e_shell_module_new ##### -->
 <para>
@@ -136,6 +137,19 @@
 @Returns: 
 
 
+<!-- ##### FUNCTION e_shell_module_upgrade ##### -->
+<para>
+
+</para>
+
+ shell_module: 
+ major: 
+ minor: 
+ micro: 
+ error: 
+ Returns: 
+
+
 <!-- ##### FUNCTION e_shell_module_set_info ##### -->
 <para>
 

Modified: branches/kill-bonobo/doc/reference/shell/tmpl/e-shell.sgml
==============================================================================
--- branches/kill-bonobo/doc/reference/shell/tmpl/e-shell.sgml	(original)
+++ branches/kill-bonobo/doc/reference/shell/tmpl/e-shell.sgml	Sun Oct  5 04:12:09 2008
@@ -218,3 +218,19 @@
 @Returns: 
 
 
+<!-- ##### MACRO E_SHELL_UPGRADE_ERROR ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION e_shell_upgrade_attempt ##### -->
+<para>
+
+</para>
+
+ shell: 
+ Returns: 
+
+

Modified: branches/kill-bonobo/shell/Makefile.am
==============================================================================
--- branches/kill-bonobo/shell/Makefile.am	(original)
+++ branches/kill-bonobo/shell/Makefile.am	Sun Oct  5 04:12:09 2008
@@ -61,6 +61,7 @@
 eshellinclude_HEADERS = 			\
 	e-shell-common.h			\
 	e-shell-content.h			\
+	e-shell-migrate.h			\
 	e-shell-module.h			\
 	e-shell-sidebar.h			\
 	e-shell-switcher.h			\
@@ -73,6 +74,7 @@
 libeshell_la_SOURCES =				\
 	$(IDL_GENERATED)			\
 	e-shell-content.c			\
+	e-shell-migrate.c			\
 	e-shell-module.c			\
 	e-shell-sidebar.c			\
 	e-shell-switcher.c			\

Added: branches/kill-bonobo/shell/e-shell-migrate.c
==============================================================================
--- (empty file)
+++ branches/kill-bonobo/shell/e-shell-migrate.c	Sun Oct  5 04:12:09 2008
@@ -0,0 +1,339 @@
+/*
+ * e-shell-migrate.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>  
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-shell-migrate.h"
+
+#include <string.h>
+#include <unistd.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <libedataserver/e-xml-utils.h>
+
+#include "e-util/e-bconf-map.h"
+#include "e-util/e-error.h"
+#include "e-util/e-fsutils.h"
+#include "e-util/e-util.h"
+
+#define GCONF_VERSION_KEY	"/apps/evolution/version"
+#define GCONF_LAST_VERSION_KEY	"/apps/evolution/last_version"
+
+static const gchar *
+shell_migrate_get_old_data_dir (void)
+{
+	static gchar *old_data_dir = NULL;
+
+	if (G_UNLIKELY (old_data_dir == NULL))
+		old_data_dir = g_build_filename (
+			g_get_home_dir (), "evolution", NULL);
+
+	return old_data_dir;
+}
+
+static gboolean
+shell_migrate_attempt (EShell *shell,
+                       gint major,
+                       gint minor,
+                       gint micro)
+{
+	GList *modules;
+	gboolean success = TRUE;
+
+	modules = e_shell_list_modules (shell);
+
+	while (success && modules != NULL) {
+		EShellModule *shell_module = modules->data;
+		GError *error = NULL;
+
+		success = e_shell_module_migrate (
+			shell_module, major, minor, micro, &error);
+
+		if (error != NULL) {
+			gint response;
+
+			response = e_error_run (
+				NULL, "shell:upgrade-failed",
+				error->message, NULL);
+
+			if (response == GTK_RESPONSE_CANCEL)
+				success = FALSE;
+
+			g_error_free (error);
+		}
+
+		modules = g_list_next (modules);
+	}
+
+	return success;
+}
+
+static void
+shell_migrate_get_version (gint *major,
+                           gint *minor,
+                           gint *micro)
+{
+	GConfClient *client;
+	const gchar *key;
+	const gchar *old_data_dir;
+	gchar *string;
+
+	old_data_dir = shell_migrate_get_old_data_dir ();
+
+	key = GCONF_VERSION_KEY;
+	client = gconf_client_get_default ();
+	string = gconf_client_get_string (client, key, NULL);
+	g_object_unref (client);
+
+	if (string != NULL) {
+		/* Since 1.4.0 we've kept the version key in GConf. */
+		sscanf (string, "%d.%d.%d", major, minor, micro);
+		g_free (string);
+
+	} else if (!g_file_test (old_data_dir, G_FILE_TEST_IS_DIR)) {
+		/* If the old data directory does not exist,
+		 * it must be a new installation. */
+		*major = 0;
+		*minor = 0;
+		*micro = 0;
+
+	} else {
+		xmlDocPtr doc;
+		xmlNodePtr source;
+		gchar *filename;
+
+		filename = g_build_filename (
+			old_data_dir, "config.xmldb", NULL);
+		doc = e_xml_parse_file (filename);
+		g_free (filename);
+
+		if (doc == NULL)
+			return;
+
+		source = e_bconf_get_path (doc, "/Shell");
+		if (source != NULL) {
+			key = "upgrade_from_1_0_to_1_2_performed";
+			string = e_bconf_get_value (source, key);
+		}
+
+		if (string != NULL && *string == '1') {
+			*major = 1;
+			*minor = 2;
+			*micro = 0;
+		} else {
+			*major = 1;
+			*minor = 0;
+			*micro = 0;
+		}
+
+		g_free (string);
+
+		if (doc != NULL)
+			xmlFreeDoc (doc);
+	}
+}
+
+static gint
+shell_migrate_remove_dir (const gchar *root,
+                          const gchar *path)
+{
+	GDir *dir;
+	const gchar *basename;
+	gchar *filename;
+	gint result = -1;
+
+	/* Recursively removes a directory and its contents. */
+
+	dir = g_dir_open (path, 0, NULL);
+	if (dir == NULL)
+		return -1;
+
+	while ((basename = g_dir_read_name (dir)) != NULL) {
+		filename = g_build_filename (path, basename, NULL);
+
+		/* Make sure we haven't strayed from the evolution dir. */
+		g_return_val_if_fail (strlen (path) >= strlen (root), -1);
+		g_return_val_if_fail (g_str_has_prefix (path, root), -1);
+
+		if (g_file_test (filename, G_FILE_TEST_IS_DIR)) {
+			if (shell_migrate_remove_dir (root, filename) < 0)
+				goto fail;
+		} else {
+			if (g_unlink (filename) < 0)
+				goto fail;
+		}
+
+		g_free (filename);
+		filename = NULL;
+	}
+
+	result = g_rmdir (path);
+
+fail:
+	g_free (filename);
+	g_dir_close (dir);
+
+	return result;
+}
+
+gboolean
+e_shell_migrate_attempt (EShell *shell)
+{
+	GConfClient *client;
+	const gchar *key;
+	const gchar *old_data_dir;
+	gint major, minor, micro;
+	gint last_major, last_minor, last_micro;
+	gint curr_major, curr_minor, curr_micro;
+	gboolean migrated = FALSE;
+	gchar *string;
+
+	g_return_val_if_fail (E_IS_SHELL (shell), FALSE);
+
+	old_data_dir = shell_migrate_get_old_data_dir ();
+
+	if (sscanf (BASE_VERSION, "%d.%d", &curr_major, &curr_minor) != 2) {
+		g_warning ("Could not parse BASE_VERSION (%s)", BASE_VERSION);
+		return TRUE;
+	}
+
+	curr_micro = atoi (UPGRADE_REVISION);
+
+	shell_migrate_get_version (&major, &minor, &micro);
+
+	if (!(curr_major > major ||
+		(curr_major == major && curr_minor > minor) ||
+		(curr_minor == minor && curr_micro > micro)))
+		goto check_old;
+
+	/* If upgrading from < 1.5, we need to copy most data from
+	 * ~/evolution to ~/.evolution.  Make sure we have the disk
+	 * space for it before proceeding. */
+	if (major == 1 && minor < 5) {
+		glong avail;
+		glong usage;
+
+		usage = e_fsutils_usage (old_data_dir);
+		avail = e_fsutils_avail (g_get_home_dir ());
+		if (usage >= 0 && avail >= 0 && avail < usage) {
+			gchar *need;
+			gchar *have;
+
+			need = g_strdup_printf (_("%ld KB"), usage);
+			have = g_strdup_printf (_("%ld KB"), avail);
+
+			e_error_run (
+				NULL, "shell:upgrade-nospace",
+				need, have, NULL);
+
+			g_free (need);
+			g_free (have);
+
+			_exit (EXIT_SUCCESS);
+		}
+	}
+
+	if (!shell_migrate_attempt (shell, major, minor, micro))
+		_exit (EXIT_SUCCESS);
+
+	/* Record a successful migration. */
+	client = gconf_client_get_default ();
+	string = g_strdup_printf ("%d.%d.%d", major, minor, micro);
+	gconf_client_set_string (client, GCONF_VERSION_KEY, string, NULL);
+	g_object_unref (client);
+	g_free (string);
+
+	migrated = TRUE;
+
+check_old:
+
+	key = GCONF_LAST_VERSION_KEY;
+	client = gconf_client_get_default ();
+
+	/* Try to retrieve the last migrated version from GConf. */
+	string = gconf_client_get_string (client, key, NULL);
+	if (migrated || string == NULL || sscanf (string, "%d.%d.%d",
+		&last_major, &last_minor, &last_micro) != 3) {
+		last_major = major;
+		last_minor = minor;
+		last_micro = micro;
+	}
+	g_free (string);
+
+	/* If the last migrated version was old, check for stuff to remove. */
+	if (last_major == 1 && last_minor < 5 &&
+		g_file_test (old_data_dir, G_FILE_TEST_IS_DIR)) {
+
+		gint response;
+
+		string = g_strdup_printf (
+			"%d.%d.%d", last_major, last_minor, last_micro);
+		response = e_error_run (
+			NULL, "shel:upgrade-remove-1-4", string, NULL);
+		g_free (string);
+
+		switch (response) {
+			case GTK_RESPONSE_OK:  /* delete */
+				response = e_error_run (
+					NULL,
+					"shell:upgrade-remove-1-4-confirm",
+					NULL);
+				if (response == GTK_RESPONSE_OK)
+					shell_migrate_remove_dir (
+						old_data_dir, old_data_dir);
+				else
+					break;
+				/* fall through */
+
+			case GTK_RESPONSE_ACCEPT:  /* keep */
+				last_major = curr_major;
+				last_minor = curr_minor;
+				last_micro = curr_micro;
+				break;
+
+			default:
+				break;
+		}
+	} else {
+		last_major = curr_major;
+		last_minor = curr_minor;
+		last_micro = curr_micro;
+	}
+
+	string = g_strdup_printf (
+		"%d.%d.%d", last_major, last_minor, last_micro);
+	gconf_client_set_string (client, key, string, NULL);
+	g_free (string);
+
+	g_object_unref (client);
+
+	return TRUE;
+}
+
+GQuark
+e_shell_migrate_error_quark (void)
+{
+	static GQuark quark = 0;
+
+	if (G_UNLIKELY (quark == 0))
+		quark = g_quark_from_static_string (
+			"e-shell-migrate-error-quark");
+
+	return quark;
+}

Added: branches/kill-bonobo/shell/e-shell-migrate.h
==============================================================================
--- (empty file)
+++ branches/kill-bonobo/shell/e-shell-migrate.h	Sun Oct  5 04:12:09 2008
@@ -0,0 +1,45 @@
+/*
+ * e-shell-migrate.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>  
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+/* This is an EShell extension that handles migrating from older versions. */
+
+#ifndef E_SHELL_MIGRATE_H
+#define E_SHELL_MIGRATE_H
+
+#include <shell/e-shell-common.h>
+#include <shell/e-shell.h>
+
+#define E_SHELL_MIGRATE_ERROR \
+	(e_shell_migrate_error_quark ())
+
+G_BEGIN_DECLS
+
+/* XXX Need more specific error codes? */
+typedef enum {
+	E_SHELL_MIGRATE_ERROR_FAILED
+} EShellMigrateError;
+
+gboolean	e_shell_migrate_attempt		(EShell *shell);
+GQuark		e_shell_migrate_error_quark	(void);
+
+G_END_DECLS
+
+#endif /* E_SHELL_MIGRATE_H */

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	Sun Oct  5 04:12:09 2008
@@ -499,6 +499,40 @@
 }
 
 /**
+ * e_shell_migrate:
+ * @shell_module: an #EShellModule
+ * @major: major part of version to migrate from
+ * @minor: minor part of version to migrate from
+ * @micro: micro part of version to migrate from
+ * @error: return location for a #GError, or %NULL
+ *
+ * Attempts to migrate data and settings from version %major.%minor.%micro.
+ * Returns %TRUE if the migration was successful or if no action was
+ * necessary.  Returns %FALSE and sets %error if the migration failed.
+ *
+ * Returns: %TRUE if successful, %FALSE otherwise
+ **/
+gboolean
+e_shell_module_migrate (EShellModule *shell_module,
+                        gint major,
+                        gint minor,
+                        gint micro,
+                        GError **error)
+{
+	EShellModuleInfo *module_info;
+
+	g_return_val_if_fail (E_IS_SHELL_MODULE (shell_module), TRUE);
+
+	module_info = &shell_module->priv->info;
+
+	if (module_info->migrate != NULL)
+		return module_info->migrate (
+			shell_module, major, minor, micro, error);
+
+	return TRUE;
+}
+
+/**
  * e_shell_module_set_info:
  * @shell_module: an #EShellModule
  * @info: an #EShellModuleInfo
@@ -535,6 +569,7 @@
 
 	module_info->is_busy = info->is_busy;
 	module_info->shutdown = info->shutdown;
+	module_info->migrate = info->migrate;
 
 	/* Determine the user data directory for this module. */
 	g_free (shell_module->priv->data_dir);

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	Sun Oct  5 04:12:09 2008
@@ -81,6 +81,10 @@
  * 		shutting down.  Returning %FALSE indicates there
  * 		are still unfinished operations and the #EShell
  * 		should check back shortly.
+ * @migrate:	Callback for notifying the module to migrate data and
+ * 		settings from the given version.  Returns %TRUE if the
+ * 		migration was successful or if no action was necessary.
+ * 		Returns %FALSE and sets a #GError if the migration failed.
  **/
 struct _EShellModuleInfo {
 	const gchar *name;
@@ -90,6 +94,11 @@
 
 	gboolean	(*is_busy)		(EShellModule *shell_module);
 	gboolean	(*shutdown)		(EShellModule *shell_module);
+	gboolean	(*migrate)		(EShellModule *shell_module,
+						 gint major,
+						 gint minor,
+						 gint micro,
+						 GError **error);
 };
 
 /**
@@ -120,6 +129,11 @@
 						 EActivity *activity);
 gboolean	e_shell_module_is_busy		(EShellModule *shell_module);
 gboolean	e_shell_module_shutdown		(EShellModule *shell_module);
+gboolean	e_shell_module_migrate		(EShellModule *shell_module,
+						 gint major,
+						 gint minor,
+						 gint micro,
+						 GError **error);
 void		e_shell_module_set_info		(EShellModule *shell_module,
 						 const EShellModuleInfo *info);
 

Modified: branches/kill-bonobo/shell/e-shell.c
==============================================================================
--- branches/kill-bonobo/shell/e-shell.c	(original)
+++ branches/kill-bonobo/shell/e-shell.c	Sun Oct  5 04:12:09 2008
@@ -26,6 +26,7 @@
 #include <e-util/e-util.h>
 
 #include <e-shell-module.h>
+#include <e-shell-upgrade.h>
 #include <e-shell-window.h>
 
 #define SHUTDOWN_TIMEOUT	500  /* milliseconds */
@@ -79,6 +80,31 @@
 	return !e_shell_quit (shell);
 }
 
+static gboolean
+shell_window_focus_in_event_cb (EShell *shell,
+                                GdkEventFocus *event,
+                                EShellWindow *shell_window)
+{
+	GList *list, *link;
+
+	/* Keep the active windows list sorted by most recently focused,
+	 * so the first item in the list should always be the currently
+	 * focused shell window. */
+
+	list = shell->priv->active_windows;
+	link = g_list_find (list, shell_window);
+	g_return_val_if_fail (link != NULL, FALSE);
+
+	if (link != list) {
+		list = g_list_remove_link (list, link);
+		list = g_list_concat (link, list);
+	}
+
+	shell->priv->active_windows = list;
+
+	return FALSE;
+}
+
 static void
 shell_window_weak_notify_cb (EShell *shell,
                              GObject *where_the_object_was)
@@ -300,6 +326,8 @@
 	}
 
 	g_dir_close (dir);
+
+	e_shell_upgrade_attempt (shell);
 }
 
 static void
@@ -493,6 +521,10 @@
 		shell_window, "delete-event",
 		G_CALLBACK (shell_window_delete_event_cb), shell);
 
+	g_signal_connect_swapped (
+		shell_window, "focus-in-event",
+		G_CALLBACK (shell_window_focus_in_event_cb), shell);
+
 	g_object_weak_ref (
 		G_OBJECT (shell_window), (GWeakNotify)
 		shell_window_weak_notify_cb, shell);
@@ -504,6 +536,17 @@
 	return shell_window;
 }
 
+GtkWidget *
+e_shell_get_focused_window (EShell *shell)
+{
+	g_return_val_if_fail (E_IS_SHELL (shell), NULL);
+
+	if (shell->priv->active_windows == NULL)
+		return NULL;
+
+	return GTK_WIDGET (shell->priv->active_windows->data);
+}
+
 gboolean
 e_shell_handle_uri (EShell *shell,
                     const gchar *uri)

Modified: branches/kill-bonobo/shell/e-shell.h
==============================================================================
--- branches/kill-bonobo/shell/e-shell.h	(original)
+++ branches/kill-bonobo/shell/e-shell.h	Sun Oct  5 04:12:09 2008
@@ -90,6 +90,7 @@
 EShellModule *	e_shell_get_module_by_scheme	(EShell *shell,
 						 const gchar *scheme);
 GtkWidget *	e_shell_create_window		(EShell *shell);
+GtkWidget *	e_shell_get_focused_window	(EShell *shell);
 gboolean	e_shell_handle_uri		(EShell *shell,
                                                  const gchar *uri);
 void		e_shell_send_receive		(EShell *shell,

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	Sun Oct  5 04:12:09 2008
@@ -86,8 +86,20 @@
 }
 
 static gboolean
-test_module_handle_uri (EShellModule *shell_module,
-                        const gchar *uri)
+test_module_migrate (EShellModule *shell_module,
+                     gint major,
+                     gint minor,
+                     gint micro,
+                     GError **error)
+{
+	g_debug ("%s (from %d.%d.%d)", G_STRFUNC, major, minor, micro);
+
+	return TRUE;
+}
+
+static gboolean
+test_module_handle_uri_cb (EShellModule *shell_module,
+                           const gchar *uri)
 {
 	g_debug ("%s (uri=%s)", G_STRFUNC, uri);
 
@@ -95,15 +107,15 @@
 }
 
 static void
-test_module_send_receive (EShellModule *shell_module,
-                          GtkWindow *parent_window)
+test_module_send_receive_cb (EShellModule *shell_module,
+                             GtkWindow *parent_window)
 {
 	g_debug ("%s (window=%p)", G_STRFUNC, parent_window);
 }
 
 static void
-test_module_window_created (EShellModule *shell_module,
-                            EShellWindow *shell_window)
+test_module_window_created_cb (EShellModule *shell_module,
+                               EShellWindow *shell_window)
 {
 	const gchar *module_name;
 
@@ -121,8 +133,8 @@
 }
 
 static void
-test_module_window_destroyed (EShellModule *shell_module,
-                              gboolean last_window)
+test_module_window_destroyed_cb (EShellModule *shell_module,
+                                 gboolean last_window)
 {
 	g_debug ("%s (last=%d)", G_STRFUNC, last_window);
 }
@@ -136,7 +148,8 @@
 
 	/* Methods */
 	test_module_is_busy,
-	test_module_shutdown
+	test_module_shutdown,
+	test_module_migrate
 };
 
 void
@@ -153,17 +166,17 @@
 
 	g_signal_connect_swapped (
 		shell, "handle-uri",
-		G_CALLBACK (test_module_handle_uri), shell_module);
+		G_CALLBACK (test_module_handle_uri_cb), shell_module);
 
 	g_signal_connect_swapped (
 		shell, "send-receive",
-		G_CALLBACK (test_module_send_receive), shell_module);
+		G_CALLBACK (test_module_send_receive_cb), shell_module);
 
 	g_signal_connect_swapped (
 		shell, "window-created",
-		G_CALLBACK (test_module_window_created), shell_module);
+		G_CALLBACK (test_module_window_created_cb), shell_module);
 
 	g_signal_connect_swapped (
 		shell, "window-destroyed",
-		G_CALLBACK (test_module_window_destroyed), shell_module);
+		G_CALLBACK (test_module_window_destroyed_cb), shell_module);
 }



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