/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * JP Rosevear * Copyright (C) 2005 Novell, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include "widgets/e-timezone-dialog/e-timezone-dialog.h" #include "e-util/e-icon-factory.h" #include "e-util/e-gtk-utils.h" #include "shell/es-event.h" #include "shell/importer/GNOME_Evolution_Importer.h" #include "mail/em-config.h" #include "mail/em-account-editor.h" #include "calendar/gui/calendar-config.h" typedef struct _IntelligentImporterData { CORBA_Object object; Bonobo_Control control; char *name; char *blurb; char *iid; } IntelligentImporterData; typedef struct _SelectedImporterData{ CORBA_Object importer; char *iid; } SelectedImporterData; #define IMPORT_PAGE_DATA "StartupWizard::ImportData" #define IMPORT_TIMEZONE_DIALOG "StartupWizard::TimezoneDialog" void startup_wizard (EPlugin *ep, ESEventTargetUpgrade *target); GtkWidget *startup_wizard_timezone_page (EPlugin *ep, EConfigHookItemFactoryData *hook_data); GtkWidget *startup_wizard_importer_page (EPlugin *ep, EConfigHookItemFactoryData *hook_data); gboolean startup_wizard_check (EPlugin *ep, EConfigHookPageCheckData *check_data); void startup_wizard_commit (EPlugin *ep, EMConfigTargetAccount *target); void startup_wizard_abort (EPlugin *ep, EMConfigTargetAccount *target); static GList *useable_importers = NULL; gboolean useable_importers_init = FALSE; static void free_importers () { GList *l; for (l = useable_importers; l; l = l->next) { IntelligentImporterData *iid; /* FIXME free the rest */ iid = l->data; if (iid->object != CORBA_OBJECT_NIL) bonobo_object_release_unref (iid->object, NULL); } g_list_free (useable_importers); useable_importers = NULL; } static GList * get_intelligent_importers (void) { Bonobo_ServerInfoList *info_list; GList *iids_ret = NULL; CORBA_Environment ev; char *query; int i; CORBA_exception_init (&ev); query = g_strdup_printf ("repo_ids.has ('IDL:GNOME/Evolution/IntelligentImporter:%s')", BASE_VERSION); info_list = bonobo_activation_query (query, NULL, &ev); g_free (query); if (BONOBO_EX (&ev) || info_list == CORBA_OBJECT_NIL) { g_warning ("Cannot find importers -- %s", BONOBO_EX_REPOID (&ev)); CORBA_exception_free (&ev); return NULL; } CORBA_exception_free (&ev); for (i = 0; i < info_list->_length; i++) { const Bonobo_ServerInfo *info; info = info_list->_buffer + i; iids_ret = g_list_prepend (iids_ret, g_strdup (info->iid)); } return iids_ret; } static void init_importers () { GList *importer_ids, *l; if (useable_importers_init) return; useable_importers_init = TRUE; importer_ids = get_intelligent_importers (); if (!importer_ids) return; for (l = importer_ids; l; l = l->next) { CORBA_Environment ev; CORBA_Object object; Bonobo_Control control; char *iid = l->data; char *name, *blurb; IntelligentImporterData *id; gboolean can_run; CORBA_exception_init (&ev); object = bonobo_activation_activate_from_id (iid, 0, NULL, &ev); if (BONOBO_EX (&ev)) { g_warning ("Could not start %s:%s", iid, CORBA_exception_id (&ev)); CORBA_exception_free (&ev); continue; } if (object == CORBA_OBJECT_NIL) { g_warning ("Could not activate component %s", iid); CORBA_exception_free (&ev); continue; } can_run = GNOME_Evolution_IntelligentImporter_canImport (object, &ev); if (BONOBO_EX (&ev)) { g_warning ("Could not call canImport(%s): %s", iid, CORBA_exception_id (&ev)); bonobo_object_release_unref (object, &ev); CORBA_exception_free (&ev); continue; } if (can_run == FALSE) { bonobo_object_release_unref (object, &ev); CORBA_exception_free (&ev); continue; } name = GNOME_Evolution_IntelligentImporter__get_importername (object, &ev); if (BONOBO_EX (&ev)) { g_warning ("Could not get name(%s): %s", iid, CORBA_exception_id (&ev)); bonobo_object_release_unref (object, &ev); CORBA_exception_free (&ev); continue; } blurb = GNOME_Evolution_IntelligentImporter__get_message (object, &ev); if (BONOBO_EX (&ev)) { g_warning ("Could not get message(%s): %s", iid, CORBA_exception_id (&ev)); bonobo_object_release_unref (object, &ev); CORBA_exception_free (&ev); CORBA_free (name); continue; } control = Bonobo_Unknown_queryInterface (object, "IDL:Bonobo/Control:1.0", &ev); if (BONOBO_EX (&ev)) { g_warning ("Could not QI for Bonobo/Control:1.0 %s:%s", iid, CORBA_exception_id (&ev)); bonobo_object_release_unref (object, &ev); CORBA_exception_free (&ev); CORBA_free (name); CORBA_free (blurb); continue; } if (control == CORBA_OBJECT_NIL) { g_warning ("Could not get importer control for %s", iid); bonobo_object_release_unref (object, &ev); CORBA_exception_free (&ev); CORBA_free (name); CORBA_free (blurb); continue; } CORBA_exception_free (&ev); id = g_new0 (IntelligentImporterData, 1); id->iid = g_strdup (iid); id->object = object; id->name = name; id->blurb = blurb; id->control = control; useable_importers = g_list_prepend (useable_importers, id); } } void startup_wizard (EPlugin *ep, ESEventTargetUpgrade *target) { GConfClient *client; GSList *accounts; EMAccountEditor *emae; GnomeDruidPageEdge *start_page; client = gconf_client_get_default (); accounts = gconf_client_get_list (client, "/apps/evolution/mail/accounts", GCONF_VALUE_STRING, NULL); g_object_unref (client); if (accounts != NULL) { g_slist_foreach (accounts, (GFunc) g_free, NULL); g_slist_free (accounts); return; } /** @HookPoint-EMConfig: New Mail Account Wizard * @Id: org.gnome.evolution.mail.config.accountWizard * @Type: E_CONFIG_DRUID * @Class: org.gnome.evolution.mail.config:1.0 * @Target: EMConfigTargetAccount * * The new mail account druid. */ emae = em_account_editor_new (NULL, EMAE_DRUID, "org.gnome.evolution.mail.config.accountWizard"); gtk_window_set_title (GTK_WINDOW (emae->editor), _("Evolution Setup Assistant")); gtk_window_set_type_hint (GTK_WINDOW (emae->editor), GDK_WINDOW_TYPE_HINT_NORMAL); gtk_window_set_wmclass (GTK_WINDOW (emae->editor), "startup-wizard", "Evolution:shell"); start_page = GNOME_DRUID_PAGE_EDGE (e_config_page_get ((EConfig *) emae->config, "0.start")); gnome_druid_page_edge_set_title (start_page, _("Welcome")); gnome_druid_page_edge_set_text (start_page, _("" "Welcome to Evolution. The next few screens will allow Evolution to connect " "to your email accounts, and to import files from other applications. \n" "\n" "Please click the \"Forward\" button to continue. ")); gtk_widget_show (emae->editor); gtk_main (); } GtkWidget * startup_wizard_timezone_page (EPlugin *ep, EConfigHookItemFactoryData *hook_data) { ETimezoneDialog *etd; GtkWidget *page; icaltimezone *zone; etd = e_timezone_dialog_new (); g_object_set_data (G_OBJECT (hook_data->config), IMPORT_TIMEZONE_DIALOG, etd); page = gnome_druid_page_standard_new_with_vals ("Timezone", NULL, NULL); e_timezone_dialog_reparent (etd, GNOME_DRUID_PAGE_STANDARD (page)->vbox); zone = calendar_config_get_icaltimezone (); if (zone) e_timezone_dialog_set_timezone (etd, zone); gnome_druid_append_page (GNOME_DRUID (hook_data->parent), GNOME_DRUID_PAGE (page)); return GTK_WIDGET (page); } GtkWidget * startup_wizard_importer_page (EPlugin *ep, EConfigHookItemFactoryData *hook_data) { GtkWidget *page, *label, *sep, *table; GList *l; int i; init_importers (); if (!useable_importers) return NULL; page = gnome_druid_page_standard_new_with_vals ("Importing files", NULL, NULL); label = gtk_label_new (_("Please select the information that you would like to import:")); gtk_box_pack_start (GTK_BOX (GNOME_DRUID_PAGE_STANDARD (page)->vbox), label, FALSE, FALSE, 3); sep = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (GNOME_DRUID_PAGE_STANDARD (page)->vbox), sep, FALSE, FALSE, 3); table = gtk_table_new (g_list_length (useable_importers), 2, FALSE); for (l = useable_importers, i = 0; l; l = l->next, i++) { IntelligentImporterData *id = l->data; GtkWidget *widget; char *str; CORBA_Environment ev; CORBA_exception_init (&ev); str = g_strdup_printf (_("From %s:"), id->name); label = gtk_label_new (str); g_free (str); gtk_misc_set_alignment (GTK_MISC (label), 0, .5); widget = bonobo_widget_new_control_from_objref (id->control, CORBA_OBJECT_NIL); gtk_table_attach (GTK_TABLE (table), label, 0, 1, i, i + 1, GTK_FILL, 0, 0, 0); gtk_table_attach (GTK_TABLE (table), widget, 1, 2, i, i + 1, GTK_FILL, 0, 3, 0); gtk_widget_show_all (table); gtk_box_pack_start (GTK_BOX (GNOME_DRUID_PAGE_STANDARD (page)->vbox), table, FALSE, FALSE, 0); } gnome_druid_append_page (GNOME_DRUID (hook_data->parent), GNOME_DRUID_PAGE (page)); return GTK_WIDGET (page); } static void start_importers (GList *p) { CORBA_Environment ev; for (; p; p = p->next) { SelectedImporterData *sid = p->data; CORBA_exception_init (&ev); GNOME_Evolution_IntelligentImporter_importData (sid->importer, &ev); if (BONOBO_EX (&ev)) { g_warning ("Error importing %s\n%s", sid->iid, CORBA_exception_id (&ev)); } CORBA_exception_free (&ev); } } static void do_import () { CORBA_Environment ev; GList *l, *selected = NULL; for (l = useable_importers; l; l = l->next) { IntelligentImporterData *importer_data; SelectedImporterData *sid; char *iid; importer_data = l->data; iid = g_strdup (importer_data->iid); sid = g_new (SelectedImporterData, 1); sid->iid = iid; CORBA_exception_init (&ev); sid->importer = bonobo_object_dup_ref (importer_data->object, &ev); if (BONOBO_EX (&ev)) { g_warning ("Error duplication %s\n(%s)", iid, CORBA_exception_id (&ev)); g_free (iid); CORBA_exception_free (&ev); g_free (sid); continue; } CORBA_exception_free (&ev); selected = g_list_prepend (selected, sid); } free_importers (); if (selected != NULL) { start_importers (selected); for (l = selected; l; l = l->next) { SelectedImporterData *sid = l->data; CORBA_exception_init (&ev); bonobo_object_release_unref (sid->importer, &ev); CORBA_exception_free (&ev); g_free (sid->iid); g_free (sid); } g_list_free (selected); } } void startup_wizard_commit (EPlugin *ep, EMConfigTargetAccount *target) { EConfig *ec = ((EConfigTarget *)target)->config; ETimezoneDialog *etd; icaltimezone *zone; /* This frees the importers */ do_import (); /* Set Timezone */ etd = g_object_get_data (G_OBJECT (ec), IMPORT_TIMEZONE_DIALOG); if (etd) { zone = e_timezone_dialog_get_timezone (E_TIMEZONE_DIALOG (etd)); if (zone) calendar_config_set_timezone (icaltimezone_get_display_name (zone)); /* Need to do this otherwise the timezone widget gets destroyed but the timezone object isn't, and we can get a crash like #22047. */ g_object_unref (etd); g_object_set_data (G_OBJECT (ec), IMPORT_TIMEZONE_DIALOG, NULL); } gtk_main_quit (); } void startup_wizard_abort (EPlugin *ep, EMConfigTargetAccount *target) { EConfig *ec = ((EConfigTarget *)target)->config; ETimezoneDialog *etd; free_importers (); etd = g_object_get_data (G_OBJECT (ec), IMPORT_TIMEZONE_DIALOG); if (etd) { /* Need to do this otherwise the timezone widget gets destroyed but the timezone object isn't, and we can get a crash like #22047. */ g_object_unref (etd); g_object_set_data (G_OBJECT (ec), IMPORT_TIMEZONE_DIALOG, NULL); } gtk_main_quit (); _exit (0); }