aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--addressbook/gui/component/Makefile.am4
-rw-r--r--addressbook/gui/component/e-book-shell-module-migrate.c (renamed from addressbook/gui/component/addressbook-migrate.c)28
-rw-r--r--addressbook/gui/component/e-book-shell-module-migrate.h (renamed from addressbook/gui/component/addressbook-migrate.h)13
-rw-r--r--addressbook/gui/component/e-book-shell-module.c52
-rw-r--r--addressbook/gui/component/e-book-shell-view-private.c2
-rw-r--r--calendar/gui/Makefile.am2
-rw-r--r--calendar/gui/e-cal-event.c22
-rw-r--r--calendar/gui/e-cal-event.h16
-rw-r--r--calendar/modules/e-cal-shell-module-migrate.c (renamed from calendar/gui/migration.c)800
-rw-r--r--calendar/modules/e-cal-shell-module-migrate.h (renamed from calendar/gui/migration.h)29
-rw-r--r--calendar/modules/e-cal-shell-module.c7
-rw-r--r--calendar/modules/e-memo-shell-module-migrate.c257
-rw-r--r--calendar/modules/e-memo-shell-module-migrate.h38
-rw-r--r--calendar/modules/e-memo-shell-module.c7
-rw-r--r--calendar/modules/e-task-shell-module-migrate.c664
-rw-r--r--calendar/modules/e-task-shell-module-migrate.h38
-rw-r--r--calendar/modules/e-task-shell-module.c7
-rw-r--r--calendar/modules/e-task-shell-sidebar.c2
-rw-r--r--doc/reference/shell/Makefile.am3
-rw-r--r--doc/reference/shell/eshell-sections.txt4
-rw-r--r--doc/reference/shell/tmpl/e-shell-module.sgml14
-rw-r--r--doc/reference/shell/tmpl/e-shell.sgml16
-rw-r--r--shell/Makefile.am2
-rw-r--r--shell/e-shell-migrate.c339
-rw-r--r--shell/e-shell-migrate.h45
-rw-r--r--shell/e-shell-module.c35
-rw-r--r--shell/e-shell-module.h14
-rw-r--r--shell/e-shell.c43
-rw-r--r--shell/e-shell.h1
-rw-r--r--shell/test/e-test-shell-module.c39
30 files changed, 1814 insertions, 729 deletions
diff --git a/addressbook/gui/component/Makefile.am b/addressbook/gui/component/Makefile.am
index 0df52c0336..9bfdabe13d 100644
--- a/addressbook/gui/component/Makefile.am
+++ b/addressbook/gui/component/Makefile.am
@@ -28,8 +28,6 @@ module_LTLIBRARIES = libevolution-addressbook.la
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 @@ libevolution_addressbook_la_SOURCES = \
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 \
diff --git a/addressbook/gui/component/addressbook-migrate.c b/addressbook/gui/component/e-book-shell-module-migrate.c
index c77c70e2b8..d0b41cf661 100644
--- a/addressbook/gui/component/addressbook-migrate.c
+++ b/addressbook/gui/component/e-book-shell-module-migrate.c
@@ -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 @@ migration_context_free (MigrationContext *context)
}
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 @@ addressbook_migrate (EShellModule *shell_module,
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 @@ addressbook_migrate (EShellModule *shell_module,
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 @@ addressbook_migrate (EShellModule *shell_module,
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 @@ addressbook_migrate (EShellModule *shell_module,
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 @@ addressbook_migrate (EShellModule *shell_module,
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 @@ addressbook_migrate (EShellModule *shell_module,
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 @@ addressbook_migrate (EShellModule *shell_module,
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;
diff --git a/addressbook/gui/component/addressbook-migrate.h b/addressbook/gui/component/e-book-shell-module-migrate.h
index 189978b212..8e19c73989 100644
--- a/addressbook/gui/component/addressbook-migrate.h
+++ b/addressbook/gui/component/e-book-shell-module-migrate.h
@@ -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 */
diff --git a/addressbook/gui/component/e-book-shell-module.c b/addressbook/gui/component/e-book-shell-module.c
index e533a1a864..276e6f0a24 100644
--- a/addressbook/gui/component/e-book-shell-module.c
+++ b/addressbook/gui/component/e-book-shell-module.c
@@ -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 @@ book_module_ensure_sources (EShellModule *shell_module)
}
static void
-book_module_init_importers (void)
+book_shell_module_init_importers (void)
{
EImportClass *import_class;
EImportImporter *importer;
@@ -206,9 +208,9 @@ book_module_init_importers (void)
}
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 @@ action_contact_new_cb (GtkAction *action,
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 GtkActionEntry source_entries[] = {
};
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 @@ book_module_handle_uri (EShellModule *shell_module,
}
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 @@ static EShellModuleInfo module_info = {
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_init (GTypeModule *type_module)
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 ();
}
diff --git a/addressbook/gui/component/e-book-shell-view-private.c b/addressbook/gui/component/e-book-shell-view-private.c
index bbabb6d1cd..c3eecb5a8a 100644
--- a/addressbook/gui/component/e-book-shell-view-private.c
+++ b/addressbook/gui/component/e-book-shell-view-private.c
@@ -70,7 +70,7 @@ selection_change (EBookShellView *book_shell_view,
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);
diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am
index 1edc28d0a7..4cc002fb8a 100644
--- a/calendar/gui/Makefile.am
+++ b/calendar/gui/Makefile.am
@@ -50,8 +50,6 @@ privsolib_LTLIBRARIES = libcal-gui.la
# cal-search-bar.c
# cal-search-bar.h
# main.c
-# migration.c
-# migration.h
libcal_gui_la_SOURCES = \
e-calendar-view.c \
diff --git a/calendar/gui/e-cal-event.c b/calendar/gui/e-cal-event.c
index 6e295ab9a8..ecd1ea5b7e 100644
--- a/calendar/gui/e-cal-event.c
+++ b/calendar/gui/e-cal-event.c
@@ -43,10 +43,10 @@ static void
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 @@ e_cal_event_peek (void)
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 @@ e_cal_event_target_new_component (ECalEvent *ece, struct _CalendarComponent *com
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 },
};
diff --git a/calendar/gui/e-cal-event.h b/calendar/gui/e-cal-event.h
index 4fbaa394ec..6aade251aa 100644
--- a/calendar/gui/e-cal-event.h
+++ b/calendar/gui/e-cal-event.h
@@ -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 _ECalEvent ECalEvent;
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 @@ struct _ECalEventClass {
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);
/* ********************************************************************** */
diff --git a/calendar/gui/migration.c b/calendar/modules/e-cal-shell-module-migrate.c
index b6174202d2..0c5d02ce26 100644
--- a/calendar/gui/migration.c
+++ b/calendar/modules/e-cal-shell-module-migrate.c
@@ -1,4 +1,6 @@
/*
+ * 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
@@ -13,14 +15,11 @@
* License along with the program; if not, see <http://www.gnu.org/licenses/>
*
*
- * Authors:
- * Rodrigo Moya <rodrigo@ximian.com>
- *
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
*/
-#include <config.h>
+#include "e-cal-shell-module-migrate.h"
#include <string.h>
#include <sys/types.h>
@@ -29,32 +28,25 @@
#include <fcntl.h>
#include <errno.h>
-#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
-
-#include <libecal/e-cal.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 <libedataserver/e-account-list.h>
-#include <camel/camel-url.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"
-#include "calendar-config-keys.h"
-#include "calendar-config.h"
-#include "e-cal-event.h"
-#include "migration.h"
-
-#ifndef G_OS_WIN32
-
-/* No previous versions have been available on Win32, so don't
- * bother with upgrade support from 1.x on Win32.
- */
+#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 */
@@ -77,22 +69,6 @@ static e_gconf_map_t calendar_display_map[] = {
{ NULL },
};
-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_t calendar_other_map[] = {
/* /Calendar/Other */
{ "ConfirmDelete", "calendar/prompts/confirm_delete", E_GCONF_MAP_BOOL },
@@ -127,20 +103,18 @@ static e_gconf_map_list_t calendar_remap_list[] = {
{ 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 (gboolean tasks)
+setup_progress_dialog (void)
{
GtkWidget *vbox, *hbox, *w;
@@ -153,14 +127,9 @@ setup_progress_dialog (gboolean tasks)
gtk_widget_show (vbox);
gtk_container_add ((GtkContainer *) window, vbox);
- if (tasks)
- 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..."));
- else
- 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..."));
+ 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);
@@ -380,11 +349,126 @@ migrate_ical_folder (char *old_path, ESourceGroup *dest_group, char *source_name
#endif /* !G_OS_WIN32 */
-#define WEBCAL_BASE_URI "webcal://"
-#define CONTACTS_BASE_URI "contacts://"
-#define BAD_CONTACTS_BASE_URI "contact://"
-#define PERSONAL_RELATIVE_URI "system"
-#define GROUPWISE_BASE_URI "groupwise://"
+#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)
@@ -407,8 +491,8 @@ create_calendar_contact_source (ESourceList *source_list)
}
static void
-create_calendar_sources (CalendarComponent *component,
- ESourceList *source_list,
+create_calendar_sources (EShellModule *shell_module,
+ ESourceList *source_list,
ESourceGroup **on_this_computer,
ESource **personal_source,
ESourceGroup **on_the_web,
@@ -424,7 +508,7 @@ create_calendar_sources (CalendarComponent *component,
*contacts = NULL;
*personal_source = NULL;
- base_dir = calendar_component_peek_base_directory (component);
+ 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);
@@ -518,233 +602,29 @@ create_calendar_sources (CalendarComponent *component,
g_free (base_uri);
}
-static void
-create_task_sources (TasksComponent *component,
- 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 = tasks_component_peek_base_directory (component);
- 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);
-}
-
-#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
-
gboolean
-migrate_calendars (CalendarComponent *component, int major, int minor, int revision, GError **err)
+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;
- ECalEventTargetComponent *target;
+ 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 (component, calendar_component_peek_source_list (component), &on_this_computer, &personal_source, &on_the_web, &contacts);
+ create_calendar_sources (
+ shell_module, source_list, &on_this_computer,
+ &personal_source, &on_the_web, &contacts);
#ifndef G_OS_WIN32
if (major == 1) {
@@ -772,7 +652,7 @@ migrate_calendars (CalendarComponent *component, int major, int minor, int revis
if (res != 0) {
/* FIXME: set proper domain/code */
- g_set_error(err, 0, 0, _("Unable to migrate old settings from evolution/config.xmldb"));
+ g_set_error(error, 0, 0, _("Unable to migrate old settings from evolution/config.xmldb"));
goto fail;
}
}
@@ -781,7 +661,7 @@ migrate_calendars (CalendarComponent *component, int major, int minor, int revis
GSList *migration_dirs, *l;
char *path, *local_cal_folder;
- setup_progress_dialog (FALSE);
+ setup_progress_dialog ();
path = g_build_filename (g_get_home_dir (), "evolution", "local", NULL);
migration_dirs = e_folder_map_local_folders (path, "calendar");
@@ -801,7 +681,7 @@ migrate_calendars (CalendarComponent *component, int major, int minor, int revis
if (!migrate_ical_folder (l->data, on_this_computer, source_name, E_CAL_SOURCE_TYPE_EVENT)) {
/* FIXME: domain/code */
- g_set_error(err, 0, 0, _("Unable to migrate calendar `%s'"), source_name);
+ g_set_error(error, 0, 0, _("Unable to migrate calendar `%s'"), source_name);
g_free(source_name);
goto fail;
}
@@ -814,7 +694,7 @@ migrate_calendars (CalendarComponent *component, int major, int minor, int revis
dialog_close ();
}
- if (minor <= 4 || (minor == 5 && revision < 5)) {
+ if (minor <= 4 || (minor == 5 && micro < 5)) {
GConfClient *gconf;
GConfValue *gconf_val;
int i;
@@ -840,11 +720,11 @@ migrate_calendars (CalendarComponent *component, int major, int minor, int revis
g_object_unref (gconf);
}
- if (minor < 5 || (minor == 5 && revision <= 10)) {
+ 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 (calendar_component_peek_base_directory (component),
+ 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);
@@ -857,9 +737,9 @@ migrate_calendars (CalendarComponent *component, int major, int minor, int revis
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 (calendar_component_peek_source_list (component)); g; g = g->next) {
+ for (g = e_source_list_peek_groups (source_list); g; g = g->next) {
ESourceGroup *group = g->data;
GSList *s;
@@ -873,7 +753,7 @@ migrate_calendars (CalendarComponent *component, int major, int minor, int revis
}
#endif /* !G_OS_WIN32 */
- e_source_list_sync (calendar_component_peek_source_list (component), NULL);
+ e_source_list_sync (source_list, NULL);
/** @Event: component.migration
* @Title: Migration step in component initialization
@@ -886,8 +766,8 @@ migrate_calendars (CalendarComponent *component, int major, int minor, int revis
*/
/* Fire off migration event */
ece = e_cal_event_peek ();
- target = e_cal_event_target_new_component (ece, calendar_component_peek (), 0);
- e_event_emit ((EEvent *) ece, "component.migration", (EEventTarget *) target);
+ target = e_cal_event_target_new_module (ece, shell_module, 0);
+ e_event_emit ((EEvent *) ece, "module.migration", (EEventTarget *) target);
retval = TRUE;
fail:
@@ -903,343 +783,3 @@ fail:
return retval;
}
-gboolean
-migrate_tasks (TasksComponent *component, int major, int minor, int revision, GError **err)
-{
- ESourceGroup *on_this_computer = NULL;
- ESourceGroup *on_the_web = NULL;
- ESource *personal_source = NULL;
- gboolean retval = FALSE;
-
- /* we call this unconditionally now - create_groups either
- creates the groups/sources or it finds the necessary
- groups/sources. */
- create_task_sources (component, tasks_component_peek_source_list (component), &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(err, 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 (TRUE);
-
- 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(err, 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 && revision <= 10)) {
- char *old_path, *new_path;
-
- old_path = g_build_filename (g_get_home_dir (), "evolution", "local", "Tasks", NULL);
- new_path = g_build_filename (tasks_component_peek_base_directory (component),
- "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 && revision <= 11) {
- GSList *g;
- for (g = e_source_list_peek_groups (tasks_component_peek_source_list (component)); 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 (tasks_component_peek_source_list (component), 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;
-}
-
-/********************************************************************************************************
- *
- * MEMOS
- *
- ********************************************************************************************************/
-
-static void
-create_memo_sources (MemosComponent *component,
- 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 = memos_component_peek_base_directory (component);
- 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
-migrate_memos (MemosComponent *component, int major, int minor, int revision, struct _GError **err)
-{
- ESourceGroup *on_this_computer = NULL;
- ESourceGroup *on_the_web = NULL;
- ESource *personal_source = NULL;
- ESourceList *source_list = NULL;
- gboolean retval = FALSE;
-
- source_list = memos_component_peek_source_list (component);
-
- /* we call this unconditionally now - create_groups either
- creates the groups/sources or it finds the necessary
- groups/sources. */
- create_memo_sources (component, 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;
-}
diff --git a/calendar/gui/migration.h b/calendar/modules/e-cal-shell-module-migrate.h
index 4073e31fac..afef469df8 100644
--- a/calendar/gui/migration.h
+++ b/calendar/modules/e-cal-shell-module-migrate.h
@@ -1,4 +1,5 @@
/*
+ * 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
@@ -14,24 +15,24 @@
* License along with the program; if not, see <http://www.gnu.org/licenses/>
*
*
- * Authors:
- * Rodrigo Moya <rodrigo@ximian.com>
- *
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
*
*/
-#ifndef MIGRATION_H
-#define MIGRATION_H
+#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
-#include <libedataserver/e-source-group.h>
-#include "calendar-component.h"
-#include "tasks-component.h"
-#include "memos-component.h"
+gboolean e_cal_shell_module_migrate (EShellModule *shell_module,
+ gint major,
+ gint minor,
+ gint micro,
+ GError **error);
-struct _GError;
+G_END_DECLS
-gboolean migrate_calendars (CalendarComponent *component, int major, int minor, int revision, struct _GError **err);
-gboolean migrate_tasks (TasksComponent *component, int major, int minor, int revision, struct _GError **err);
-gboolean migrate_memos (MemosComponent *component, int major, int minor, int revision, struct _GError **err);
-#endif
+#endif /* E_CAL_SHELL_MODULE_MIGRATE_H */
diff --git a/calendar/modules/e-cal-shell-module.c b/calendar/modules/e-cal-shell-module.c
index f5cdbe0f48..1dff363a0f 100644
--- a/calendar/modules/e-cal-shell-module.c
+++ b/calendar/modules/e-cal-shell-module.c
@@ -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 @@ static EShellModuleInfo module_info = {
MODULE_NAME,
MODULE_ALIASES,
MODULE_SCHEMES,
- MODULE_SORT_ORDER
+ MODULE_SORT_ORDER,
+
+ /* is_busy */ NULL,
+ /* shutdown */ NULL,
+ e_cal_shell_module_migrate
};
void
diff --git a/calendar/modules/e-memo-shell-module-migrate.c b/calendar/modules/e-memo-shell-module-migrate.c
new file mode 100644
index 0000000000..7fe9442d5e
--- /dev/null
+++ b/calendar/modules/e-memo-shell-module-migrate.c
@@ -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;
+}
diff --git a/calendar/modules/e-memo-shell-module-migrate.h b/calendar/modules/e-memo-shell-module-migrate.h
new file mode 100644
index 0000000000..e40e2ff00f
--- /dev/null
+++ b/calendar/modules/e-memo-shell-module-migrate.h
@@ -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 */
diff --git a/calendar/modules/e-memo-shell-module.c b/calendar/modules/e-memo-shell-module.c
index c63f0fd958..7f6df49691 100644
--- a/calendar/modules/e-memo-shell-module.c
+++ b/calendar/modules/e-memo-shell-module.c
@@ -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 @@ static EShellModuleInfo module_info = {
MODULE_NAME,
MODULE_ALIASES,
MODULE_SCHEMES,
- MODULE_SORT_ORDER
+ MODULE_SORT_ORDER,
+
+ /* is_busy */ NULL,
+ /* shutdown */ NULL,
+ e_memo_shell_module_migrate
};
void
diff --git a/calendar/modules/e-task-shell-module-migrate.c b/calendar/modules/e-task-shell-module-migrate.c
new file mode 100644
index 0000000000..2bd34e89a9
--- /dev/null
+++ b/calendar/modules/e-task-shell-module-migrate.c
@@ -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;
+}
diff --git a/calendar/modules/e-task-shell-module-migrate.h b/calendar/modules/e-task-shell-module-migrate.h
new file mode 100644
index 0000000000..b20a342e0d
--- /dev/null
+++ b/calendar/modules/e-task-shell-module-migrate.h
@@ -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 */
diff --git a/calendar/modules/e-task-shell-module.c b/calendar/modules/e-task-shell-module.c
index eba720ac6b..c5f268d131 100644
--- a/calendar/modules/e-task-shell-module.c
+++ b/calendar/modules/e-task-shell-module.c
@@ -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 @@ static EShellModuleInfo module_info = {
MODULE_NAME,
MODULE_ALIASES,
MODULE_SCHEMES,
- MODULE_SORT_ORDER
+ MODULE_SORT_ORDER,
+
+ /* is_busy */ NULL,
+ /* shutdown */ NULL,
+ e_task_shell_module_migrate
};
void
diff --git a/calendar/modules/e-task-shell-sidebar.c b/calendar/modules/e-task-shell-sidebar.c
index 52d28776b4..e36c05b879 100644
--- a/calendar/modules/e-task-shell-sidebar.c
+++ b/calendar/modules/e-task-shell-sidebar.c
@@ -434,7 +434,7 @@ task_shell_sidebar_constructed (GObject *object)
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);
}
diff --git a/doc/reference/shell/Makefile.am b/doc/reference/shell/Makefile.am
index 7a249b01f9..65d12055e5 100644
--- a/doc/reference/shell/Makefile.am
+++ b/doc/reference/shell/Makefile.am
@@ -76,12 +76,15 @@ GTKDOC_LIBS= \
$(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 \
diff --git a/doc/reference/shell/eshell-sections.txt b/doc/reference/shell/eshell-sections.txt
index 4e0474f0c2..e6cfb9cb4b 100644
--- a/doc/reference/shell/eshell-sections.txt
+++ b/doc/reference/shell/eshell-sections.txt
@@ -19,6 +19,8 @@ e_shell_get_preferences_window
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 @@ EShellClass
e_shell_get_type
<SUBSECTION Private>
EShellPrivate
+e_shell_upgrade_error_quirk
</SECTION>
<SECTION>
@@ -94,6 +97,7 @@ e_shell_module_get_shell
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
diff --git a/doc/reference/shell/tmpl/e-shell-module.sgml b/doc/reference/shell/tmpl/e-shell-module.sgml
index cd4fb930f5..decce2d34c 100644
--- a/doc/reference/shell/tmpl/e-shell-module.sgml
+++ b/doc/reference/shell/tmpl/e-shell-module.sgml
@@ -52,6 +52,7 @@ EShellModule
@sort_order:
@is_busy:
@shutdown:
+@upgrade:
<!-- ##### FUNCTION e_shell_module_new ##### -->
<para>
@@ -136,6 +137,19 @@ EShellModule
@Returns:
+<!-- ##### FUNCTION e_shell_module_upgrade ##### -->
+<para>
+
+</para>
+
+@shell_module:
+@major:
+@minor:
+@micro:
+@error:
+@Returns:
+
+
<!-- ##### FUNCTION e_shell_module_set_info ##### -->
<para>
diff --git a/doc/reference/shell/tmpl/e-shell.sgml b/doc/reference/shell/tmpl/e-shell.sgml
index db92be82ed..e2ed82e2b1 100644
--- a/doc/reference/shell/tmpl/e-shell.sgml
+++ b/doc/reference/shell/tmpl/e-shell.sgml
@@ -218,3 +218,19 @@ EShell
@Returns:
+<!-- ##### MACRO E_SHELL_UPGRADE_ERROR ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION e_shell_upgrade_attempt ##### -->
+<para>
+
+</para>
+
+@shell:
+@Returns:
+
+
diff --git a/shell/Makefile.am b/shell/Makefile.am
index 0603f603fa..f8510f9357 100644
--- a/shell/Makefile.am
+++ b/shell/Makefile.am
@@ -61,6 +61,7 @@ eshellincludedir = $(privincludedir)/shell
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 @@ eshellinclude_HEADERS = \
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 \
diff --git a/shell/e-shell-migrate.c b/shell/e-shell-migrate.c
new file mode 100644
index 0000000000..9979899563
--- /dev/null
+++ b/shell/e-shell-migrate.c
@@ -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;
+}
diff --git a/shell/e-shell-migrate.h b/shell/e-shell-migrate.h
new file mode 100644
index 0000000000..315a2904c5
--- /dev/null
+++ b/shell/e-shell-migrate.h
@@ -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 */
diff --git a/shell/e-shell-module.c b/shell/e-shell-module.c
index 1eea8188b6..64d5efc41e 100644
--- a/shell/e-shell-module.c
+++ b/shell/e-shell-module.c
@@ -499,6 +499,40 @@ e_shell_module_shutdown (EShellModule *shell_module)
}
/**
+ * 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 @@ e_shell_module_set_info (EShellModule *shell_module,
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);
diff --git a/shell/e-shell-module.h b/shell/e-shell-module.h
index 8b00660e91..8dff5a1425 100644
--- a/shell/e-shell-module.h
+++ b/shell/e-shell-module.h
@@ -81,6 +81,10 @@ typedef struct _EShellModulePrivate EShellModulePrivate;
* 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 @@ struct _EShellModuleInfo {
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 @@ void e_shell_module_add_activity (EShellModule *shell_module,
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);
diff --git a/shell/e-shell.c b/shell/e-shell.c
index 625285839b..7461329e1d 100644
--- a/shell/e-shell.c
+++ b/shell/e-shell.c
@@ -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 @@ shell_window_delete_event_cb (EShell *shell,
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 @@ shell_constructed (GObject *object)
}
g_dir_close (dir);
+
+ e_shell_upgrade_attempt (shell);
}
static void
@@ -493,6 +521,10 @@ e_shell_create_window (EShell *shell)
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 @@ e_shell_create_window (EShell *shell)
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)
diff --git a/shell/e-shell.h b/shell/e-shell.h
index d3d5b18f77..183028948c 100644
--- a/shell/e-shell.h
+++ b/shell/e-shell.h
@@ -90,6 +90,7 @@ EShellModule * e_shell_get_module_by_name (EShell *shell,
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,
diff --git a/shell/test/e-test-shell-module.c b/shell/test/e-test-shell-module.c
index 32de51a650..19b5d3bd96 100644
--- a/shell/test/e-test-shell-module.c
+++ b/shell/test/e-test-shell-module.c
@@ -86,8 +86,20 @@ test_module_shutdown (EShellModule *shell_module)
}
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 @@ test_module_handle_uri (EShellModule *shell_module,
}
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 @@ test_module_window_created (EShellModule *shell_module,
}
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 @@ static EShellModuleInfo module_info = {
/* Methods */
test_module_is_busy,
- test_module_shutdown
+ test_module_shutdown,
+ test_module_migrate
};
void
@@ -153,17 +166,17 @@ e_shell_module_init (GTypeModule *type_module)
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);
}