aboutsummaryrefslogblamecommitdiffstats
path: root/shell/e-shell-importer.c
blob: 7fcb1c06664519dd2ebb43d253cb21179ddb74a0 (plain) (tree)
1
2
3
4
5
6
7
8


                                                                           
                                   

                                                                
                                                                   
                                                        










                                                                    
                                         





                    



                      

                   
                 
                           

                                   

                                                 
                                        
 
                                                
 


                                    
                    
                           
                              

                                               

                        
                                    
 

                                  
                                  
 

                                              









                                      



                                      













                                          
                            
                      
                             
        


                          
                           
                                       
                                       


                                               
                              
                              
                              
                               

                                   

                        
                       
                          
                                        

             














                                         
                                                                                               
                                                                                                                
                          
 
                     

                                                                  




           



                   
                      
                                                   
          
                      



                                                                       
          


                                                      
                             
                                                                            


                                                                            

                                                                            
                                                              

         
                                                   
 
                  
                              
 
                         
              
 



                                                 
                                
 


                                                         
 
                     






                                        
                                            

                       
                          


                            

                      



                                                    
                                               






                                                                    
           

                                                             
                                                                       
                            

                               
                
                                                        
                                                                       
                            


                               
                                 


                                                                                                 
                                                                                       
                                                                               

                                                                              
                                               


                                                      

                                                                              
                            

                               


                               
                                
                                                              
                                                            
                                     
                     

            





                                                                    
                                    
 
           

                                                                                 
                                                                       
                                                           

                                                              
                               


                                      
                                                                            
            



                     
                                      


                                              
                                                 





                                            

                                                     
 


                                                                    
                         

 

















                                                  
                                                            
 
                                
 

                                                                     
 








                                                                                  











                                                
                                                                                                        
                                                                                   
                                                                           
                                                   
                                                                  

                                                                               











                                                                          
                                                                                       
                                                                               
                                



                                                  














                                                                           

                                                           
 
                                         
                             
                                 


                                   
                                                                                


                                                  
                                      
                                              
                


                                              
                                                                                                  





                                                                     

                                                                              






                                                                                   


                              
                                                             

                                            
 
                               

                       



                                       
                                               

                                           
                                         
                
                            
                             
                                          
                                                                  
                
                                           
                                         
 
                                               
                


                                

         
 
           
                                                                                     
 
                                   
                    
                            
        
                                                                            
                                                                                   
 

                                                                                                 


                       
                                               
                                            
                          
                                                                                      

                                                                                                    
                                                          
                                                                                         
 
                                                                              
 
                                                                      


                                              
                                                                                       


                                                       
 
                                                                                   
                                                                               
                                                                                           
 



                                                                      
                
                                             
                                
                                                                      
                             
                                       
                       
         
 



                                                                      
                                                

                                                              
                               

                                      


                                                                            






                                   
                             









                                                                      
                                                                                    

 






                                   
                                                               





                                                           




















                                                                      


                                     
                                         






                                                             
                                                                                              
                                                          

                                   
                                                                                






                                                                          
                                                  
                                              










                                                                      
                                       

                                                                    
 
                                                                                                    
                                                                  
         
                               







                                         
                                         












                                                                        
                                                              



                                                                        
                                                                                                  
                                                                                


                                                                                 


                                                                        
                                                                        


              
                                                               






                                                                                

                                                                        
                                                                        
 




                                    












                                                







                                                

                                                                                                                 
                                                                                      

                                                                                                          



























                                                                               
                                         




                                   
                                                                                      


                                                  
                                              








                                                                           

                                               




                                           
                                   


                                                   

                                                                                           




                                            

                                                                                           
                                              

                                                         
                                                                  
      
 

                                                                                        
                                     



                                       









                                                                      



                                                                                   















                                                                    
                                                                                                 


























































































                                                                                                           


                                                                  
                                                                              
                                                              
                                                                      
                                                                           



                                                                              

                                    
                           



                                                                                   









                                            



                                       


                                                       











                                                               
           
                                     
                                                        
 
                                               
 
                                      




                                   





















































































                                                                                    



                                          

                                                                                             
                
                                                                   
         

                                          






                                        

                                                                           
                                                        


                     




                                     
                              
                            



                                        

                                                                                                            
        
                                                                                         
                                                                                                
                                                                                  
                                       




                                                                                        


                                                                                          
                                               

                                                        




                                                        
                                                                                                           

                                                                                  
                                       






                                                                        
                               

                            
                                                                                     




                                                                                  
                     


               







                                                                                           
                                                                                           






                                                   


                                  
                                                                      


















                                                                                             

                                    







                                                                                             
                                                                                  













                                                                          
           

                                                  
 

                                                  


                             
    
                                                          

                                                  
                        
                                            
                        



                          
        
                                                                                 
        
                           

                                                               
 
                                                                                      
                                                                           
                                                                          

                                                                         
                                                                                          
                                                                                      
        
                                                                    

                                                                  

                                                               
 

                                                                                              
 
                        
                                                                                           
                                                           
 
                                               
                                                                        
                                                                                                

                                                             
                                                       
                                         




                                                                                                                               
                                              
                                                                                     
                                                                                                 

                                                                    
                                                             
                                                                       

                                                               
                                                





                                                                                                                                    
                                               
                                                                             
                                                                                                
                                                            


                                                                
                                                       
 
                                         

                                                                                  
 
                                                                                                                               
 










                                                                                                                               
                         
                                                                                            
                                                            


                                                               

                                                                  
 
                                                                                    
 

                              

                                           
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/* importer.c
 *
 * Copyright (C) 2000  Ximian, Inc.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * 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
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Author: Iain Holmes  <iain@ximian.com>
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <string.h>

#include <glib.h>
#include <gdk/gdkkeysyms.h>
#include <libgnome/gnome-i18n.h>
#include <libgnomeui/gnome-druid.h>
#include <libgnomeui/gnome-druid-page-edge.h>
#include <libgnomeui/gnome-druid-page-standard.h>
#include <libgnomeui/gnome-file-entry.h>

#include <bonobo-activation/bonobo-activation.h>

#include <bonobo/bonobo-exception.h>
#include <bonobo/bonobo-widget.h>

#include "e-shell.h"
#include "e-shell-window.h"
#include "e-shell-constants.h"

#include "importer/evolution-importer-client.h"

#include <glade/glade.h>
#include <gal/widgets/e-gui-utils.h>

#include <e-util/e-gtk-utils.h>
#include <e-util/e-dialog-utils.h>
#include <e-util/e-icon-factory.h>

#include "e-shell-importer.h"
#include "importer/GNOME_Evolution_Importer.h"

typedef struct _ImportDialogFilePage {
    GtkWidget *vbox;
    GtkWidget *filename;
    GtkWidget *filetype;
    GtkWidget *menu;

    gboolean need_filename;
} ImportDialogFilePage;

typedef struct _ImportDialogDestPage {
    GtkWidget *vbox;
} ImportDialogDestPage;

typedef struct _ImportDialogTypePage {
    GtkWidget *vbox;
    GtkWidget *intelligent;
    GtkWidget *file;
} ImportDialogTypePage;

typedef struct _ImportDialogImporterPage {
    GtkWidget *vbox;

    GList *importers;
    gboolean prepared;
    int running;
} ImportDialogImporterPage;

typedef struct _ImportData {
    EShell *shell;
    EShellWindow *window;
    
    GladeXML *wizard;
    GtkWidget *dialog;
    GtkWidget *druid;
    GtkWidget *control;
    ImportDialogFilePage *filepage;
    ImportDialogDestPage *destpage;
    ImportDialogTypePage *typepage;
    ImportDialogImporterPage *importerpage;

    GtkWidget *filedialog;
    GtkWidget *typedialog;
    GtkWidget *destdialog;
    GtkWidget *intelligent;
    GnomeDruidPageEdge *start;
    GnomeDruidPageEdge *finish;
    GtkWidget *vbox;

    char *filename;
    char *choosen_iid;
    EvolutionImporterClient *client;
} ImportData;

typedef struct _IntelligentImporterData {
    CORBA_Object object;
    Bonobo_Control control;
    GtkWidget *widget;

    char *name;
    char *blurb;
    char *iid;
} IntelligentImporterData;

typedef struct _SelectedImporterData{
    CORBA_Object importer;
    char *iid;
} SelectedImporterData;

#define IMPORTER_REPO_ID_QUERY "repo_ids.has ('IDL:GNOME/Evolution/Importer:" BASE_VERSION "')"
#define IMPORTER_INTEL_REPO_ID_QUERY "repo_ids.has ('IDL:GNOME/Evolution/IntelligentImporter:" BASE_VERSION "')"
/*#define IMPORTER_DEBUG*/

#ifdef IMPORTER_DEBUG
#define IN g_print ("=====> %s (%d)\n", G_GNUC_FUNCTION, __LINE__)
#define OUT g_print ("<==== %s (%d)\n", G_GNUC_FUNCTION, __LINE__)
#else
#define IN
#define OUT
#endif

static struct {
    char *name;
    char *text;
} info[] = {
    { "type_html",
      N_("Choose the type of importer to run:")
    },
    { "file_html",
      N_("Choose the file that you want to import into Evolution, "
         "and select what type of file it is from the list.\n\n"
         "You can select \"Automatic\" if you do not know, and "
         "Evolution will attempt to work it out.")
    },
    { "dest_html",
      N_("Choose the destination for this import")
    },
    { "intelligent_html",
      N_("Please select the information that you would like to import:")
    },
    { "nodata_html",
      N_("Evolution checked for settings to import from the following\n"
         "applications: Pine, Netscape, Elm, iCalendar. No importable\n"
         "settings found. If you would like to\n"
         "try again, please click the \"Back\" button.\n")
    }
};
#define num_info (sizeof (info) / sizeof (info[0]))

static GtkWidget *
create_help (const char *name)
{
    GtkWidget *label;
    int i;

    for (i = 0; i < num_info; i++) {
        if (!strcmp (name, info[i].name))
            break;
    }
    g_assert(i != num_info);

    label = gtk_label_new(_(info[i].text));
    gtk_widget_show (label);
    gtk_label_set_line_wrap((GtkLabel *)label, TRUE);

    return label;
}

/* Importing functions */

/* Data to be passed around */
typedef struct _ImporterComponentData {
    EvolutionImporterClient *client;
    EvolutionImporterListener *listener;
    char *filename;

    GtkDialog *dialog;
    GtkWidget *contents;

    int item;

    gboolean stop;
} ImporterComponentData;

static gboolean importer_timeout_fn (gpointer data);
static void
import_cb (EvolutionImporterListener *listener,
       EvolutionImporterResult result,
       gboolean more_items,
       void *data)
{
    ImporterComponentData *icd = (ImporterComponentData *) data;
    char *label;

    IN;
    if (icd->stop != TRUE) {
        if (result == EVOLUTION_IMPORTER_NOT_READY) {
            g_timeout_add (500, importer_timeout_fn, data);
            OUT;
            return;
        }
        
        if (result == EVOLUTION_IMPORTER_BUSY) {
            g_timeout_add (500, importer_timeout_fn, data);
            OUT;
            return;
        }

        if (more_items) {
            char *utf8_filename;

            utf8_filename = g_filename_to_utf8 (icd->filename, -1, NULL, NULL, NULL);
            label = g_strdup_printf (_("Importing %s\nImporting item %d."),
                         utf8_filename, ++(icd->item));
            gtk_label_set_text (GTK_LABEL (icd->contents), label);
            g_free (label);
            g_free (utf8_filename);
            while (gtk_events_pending ())
                gtk_main_iteration ();
            
            g_idle_add_full (G_PRIORITY_LOW, importer_timeout_fn, 
                     data, NULL);
            OUT;
            return;
        }
    }
    
    g_free (icd->filename);
    if (icd->dialog != NULL)
        gtk_widget_destroy ((GtkWidget *)icd->dialog);
    bonobo_object_unref (BONOBO_OBJECT (icd->listener));
    g_object_unref (icd->client);
    g_free (icd);

    OUT;
}

static gboolean
importer_timeout_fn (gpointer data)
{
    ImporterComponentData *icd = (ImporterComponentData *) data;
    char *label, *utf8_filename;

    IN;

    utf8_filename = g_filename_to_utf8 (icd->filename, -1, NULL, NULL, NULL);
    label = g_strdup_printf (_("Importing %s\nImporting item %d."),
                 utf8_filename, icd->item);
    gtk_label_set_text (GTK_LABEL (icd->contents), label);
    g_free (label);
    g_free (utf8_filename);
    while (gtk_events_pending ())
        gtk_main_iteration ();
    
    evolution_importer_client_process_item (icd->client, icd->listener);
    OUT;
    return FALSE;
}

static void
dialog_response_cb (GtkDialog *dialog,
           int button_number,
           ImporterComponentData *icd)
{
    if (button_number != GTK_RESPONSE_CANCEL)
        return; /* Interesting... */

    icd->stop = TRUE;
}

static void
dialog_destroy_notify (void *data,
               GObject *where_the_dialog_was)
{
    ImporterComponentData *icd = (ImporterComponentData *) data;

    icd->dialog = NULL;
    icd->stop = TRUE;
}

struct _IIDInfo {
    char *iid;
    char *name;
};

static void
free_iid_list (GList *list)
{
    for (; list; list = list->next) {
        struct _IIDInfo *iid = list->data;

        g_free (iid->iid);
        g_free (iid->name);
        g_free (iid);
    }
}

static const char *
get_name_from_component_info (const Bonobo_ServerInfo *info)
{
    const char *name = NULL;

    GSList *language_list = NULL;
    const GList *l = gnome_i18n_get_language_list("LC_MESSAGES");

    /* copy this piece of code from e-shell-settings-dialog.c:load_pages () */
    for (language_list=NULL;l;l=l->next)
        language_list = g_slist_append(language_list, l->data);

    name = bonobo_server_info_prop_lookup ((Bonobo_ServerInfo *) info,
                        "evolution:menu_name",
                        language_list);

    g_slist_free (language_list);

    return name;
}

static char *
choose_importer_from_list (GList *importer_list)
{
    GtkWidget *dialog, *clist;
    GList *p;
    int ans;
    char *iid;

    dialog = gtk_dialog_new_with_buttons(_("Select importer"), NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                         GTK_STOCK_OK, GTK_RESPONSE_OK,
                         NULL);
    gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
    gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);

    clist = gtk_clist_new (1);
    for (p = importer_list; p; p = p->next) {
        struct _IIDInfo *iid;
        char *text[1];
        int row;

        iid = p->data;
        text[0] = iid->name;
        row = gtk_clist_append (GTK_CLIST (clist), text);
        gtk_clist_set_row_data (GTK_CLIST (clist), row, iid->iid);
    }

    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), clist, TRUE, TRUE, 0);
    gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_BROWSE);
    gtk_widget_show (clist);

    ans = gtk_dialog_run((GtkDialog *)dialog);
    switch (ans) {
    case GTK_RESPONSE_OK:
        ans = GPOINTER_TO_INT (GTK_CLIST (clist)->selection->data);
        iid = gtk_clist_get_row_data (GTK_CLIST (clist), ans);
        break;

    case 1:
    default:
        iid = NULL;
        break;
    }
    
    gtk_widget_destroy (dialog);

    return g_strdup (iid);
}

static gboolean
get_iid_for_filetype (const char *filename, char **ret_iid)
{
    Bonobo_ServerInfoList *info_list;
    CORBA_Environment ev;
    GList *can_handle = NULL;
    int i, len = 0;

    CORBA_exception_init (&ev);
    info_list = bonobo_activation_query (IMPORTER_REPO_ID_QUERY, NULL, &ev);

    for (i = 0; i < info_list->_length; i++) {
        CORBA_Environment ev2;
        CORBA_Object importer;
        const Bonobo_ServerInfo *info;
        
        info = info_list->_buffer + i;

        CORBA_exception_init (&ev2);
        importer = bonobo_activation_activate_from_id ((char *) info->iid, 0, NULL, &ev2);
        if (ev2._major != CORBA_NO_EXCEPTION) {
            g_warning ("Error activating %s", info->iid);
            CORBA_exception_free (&ev2);
            continue;
        }

        if (GNOME_Evolution_Importer_supportFormat (importer,
                                filename, &ev2)) {
            struct _IIDInfo *iid;

            iid = g_new (struct _IIDInfo, 1);
            iid->iid = g_strdup (info->iid);
            iid->name = g_strdup (get_name_from_component_info (info));
            
            can_handle = g_list_prepend (can_handle, iid);
            len++;
        }

        bonobo_object_release_unref (importer, &ev2);
        CORBA_exception_free (&ev2);
    }

    CORBA_free (info_list);

    if (len == 1) {
        struct _IIDInfo *iid;
        
        iid = can_handle->data;

        *ret_iid = g_strdup (iid->iid);
        
        free_iid_list (can_handle);
        g_list_free (can_handle);
        
        return TRUE;
    } else if (len > 1) {
        /* Display all the IIDs */
        *ret_iid = choose_importer_from_list (can_handle);
        
        free_iid_list (can_handle);
        g_list_free (can_handle);

        return *ret_iid ? TRUE : FALSE;
    } else {
        *ret_iid = NULL;
        
        return TRUE;
    }
}

static void
start_import (gpointer parent, const char *filename, EvolutionImporterClient *client)
{
    ImporterComponentData *icd;
    char *label;
    char *utf8_filename;
    
    utf8_filename = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
    if (!g_file_test (filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {

        e_notice (parent, GTK_MESSAGE_ERROR, _("File %s does not exist"), utf8_filename);
        g_free (utf8_filename);
        return;
    }

    icd = g_new (ImporterComponentData, 1);
    icd->client = g_object_ref (client);
    icd->stop = FALSE;
    icd->dialog = GTK_DIALOG (gtk_dialog_new_with_buttons(_("Importing"), NULL, 0,
                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                  NULL));
    gtk_dialog_set_has_separator (icd->dialog, FALSE);
    g_signal_connect (icd->dialog, "response", G_CALLBACK (dialog_response_cb), icd);

    g_object_weak_ref (G_OBJECT(icd->dialog), dialog_destroy_notify, icd);

    label = g_strdup_printf (_("Importing %s.\n"), utf8_filename);
    icd->contents = gtk_label_new (label);
    g_free (label);
    
    gtk_box_pack_start (GTK_BOX (icd->dialog->vbox), icd->contents, TRUE, TRUE, 0);
    gtk_widget_show_all (GTK_WIDGET (icd->dialog));
    while (gtk_events_pending ())
        gtk_main_iteration ();

    if (evolution_importer_client_load_file (icd->client, filename) == FALSE) {
        label = g_strdup_printf (_("Error loading %s"), utf8_filename);
        e_notice (icd->dialog, GTK_MESSAGE_ERROR, _("Error loading %s"), filename);

        gtk_label_set_text (GTK_LABEL (icd->contents), label);
        g_free (label);
        while (gtk_events_pending ())
            gtk_main_iteration ();
        
        g_object_unref (icd->client);
        if (icd->dialog)
            gtk_widget_destroy (GTK_WIDGET (icd->dialog));
        g_free (icd);
        g_free (utf8_filename);
        return;
    }

    icd->filename = g_strdup (filename);
    icd->item = 1;
    
    label = g_strdup_printf (_("Importing %s\nImporting item 1."),
                 utf8_filename);
    gtk_label_set_text (GTK_LABEL (icd->contents), label);
    g_free (label);
    g_free (utf8_filename);
    while (gtk_events_pending ())
        gtk_main_iteration ();

    icd->listener = evolution_importer_listener_new (import_cb, icd);
    evolution_importer_client_process_item (icd->client, icd->listener);
}

static void
filename_changed (GtkEntry *entry,
          ImportData *data)
{
    ImportDialogFilePage *page;
    const char *filename;

    page = data->filepage;

    filename = gtk_entry_get_text (entry);
    if (filename != NULL && *filename != '\0')
        page->need_filename = FALSE;
    else
        page->need_filename = TRUE;

    gnome_druid_set_buttons_sensitive (GNOME_DRUID (data->druid), 
                       TRUE, !page->need_filename, TRUE, FALSE);
}

static void
item_selected (GtkWidget *item,
           ImportData *data)
{
    char *iid;

    g_free (data->choosen_iid);
    iid = g_object_get_data (G_OBJECT (item), "bonoboiid");
    if (iid == NULL)
        data->choosen_iid = g_strdup ("Automatic");
    else
        data->choosen_iid = g_strdup (iid);
}

static int
compare_info_name (const void *data1, const void  *data2)
{
    const Bonobo_ServerInfo *info1 = (Bonobo_ServerInfo *)data1;
    const Bonobo_ServerInfo *info2 = (Bonobo_ServerInfo *)data2;
    const char *name1 = get_name_from_component_info (info1);
    const char *name2 = get_name_from_component_info (info2);

    /* If we can't find a name for a plug-in, its iid will be used
     * for display. Put such plug-ins at the end of the list since
     * their displayed name won't be really user-friendly
     */
    if (name1 == NULL) {
        return -1;
    }
    if (name2 == NULL) {
        return 1;
    }
    return g_utf8_collate (name1, name2);
}

static GtkWidget *
create_plugin_menu (ImportData *data)
{
    Bonobo_ServerInfoList *info_list;
    CORBA_Environment ev;
    int i;
    GtkWidget *menu;
    GtkWidget *item;

    menu = gtk_menu_new ();
    item = gtk_menu_item_new_with_label (_("Automatic"));
    g_object_set_data_full ((GObject *)item, "bonoboiid", g_strdup ("Automatic"), g_free);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);

    CORBA_exception_init (&ev);
    info_list = bonobo_activation_query (IMPORTER_REPO_ID_QUERY, NULL, &ev);
    /* Sort info list to get a consistent ordering of the items in the
     * combo box from one run of evolution to another.
     */
    qsort (info_list->_buffer, info_list->_length, 
           sizeof (Bonobo_ServerInfo),
           compare_info_name);

    for (i = 0; i < info_list->_length; i++) {
        const Bonobo_ServerInfo *info;
        char *name = NULL;

        info = info_list->_buffer + i;

        name = g_strdup (get_name_from_component_info (info));
        if (name == NULL) {
            name = g_strdup (info->iid);
        }

        item = gtk_menu_item_new_with_label (name);
        g_free (name);
        gtk_widget_show (item);
        g_signal_connect (item, "activate",
                  G_CALLBACK (item_selected), data);

        g_object_set_data_full ((GObject *)item, "bonoboiid", g_strdup (info->iid), g_free);
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
    }
    CORBA_free (info_list);

    return menu;
}

static ImportDialogFilePage *
importer_file_page_new (ImportData *data)
{
    ImportDialogFilePage *page;
    GtkWidget *table, *label, *entry;
    int row = 0;

    page = g_new0 (ImportDialogFilePage, 1);

    page->vbox = gtk_vbox_new (FALSE, 5);
    page->need_filename = TRUE;

    table = gtk_table_new (2, 2, FALSE);
    gtk_table_set_row_spacings (GTK_TABLE (table), 2);
    gtk_table_set_col_spacings (GTK_TABLE (table), 10);
    gtk_container_set_border_width (GTK_CONTAINER (table), 8);
    gtk_box_pack_start (GTK_BOX (page->vbox), table, TRUE, TRUE, 0);

    label = gtk_label_new_with_mnemonic (_("F_ilename:"));
    gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1, 
              GTK_FILL, 0, 0, 0);
    gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);

    page->filename = gnome_file_entry_new ("Evolution_Importer_FileName", _("Select a file"));
    g_object_set (G_OBJECT (page->filename), "use_filechooser", TRUE, NULL);
    entry = gnome_file_entry_gtk_entry((GnomeFileEntry *)page->filename);
    g_signal_connect (entry, "changed", G_CALLBACK (filename_changed), data);
    gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);

    gtk_table_attach (GTK_TABLE (table), page->filename, 1, 2, 
              row, row + 1, GTK_EXPAND | GTK_FILL, 0, 0, 0);
    gtk_label_set_mnemonic_widget(GTK_LABEL(label), page->filename);

    row++;

    label = gtk_label_new_with_mnemonic (_("File _type:"));
    gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
              GTK_FILL, 0, 0, 0);
    gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);

    page->filetype = gtk_option_menu_new ();
    page->menu = create_plugin_menu (data);
    gtk_option_menu_set_menu (GTK_OPTION_MENU (page->filetype), page->menu);
    gtk_table_attach (GTK_TABLE (table), page->filetype, 1, 2, 
              row, row + 1, GTK_EXPAND | GTK_FILL, 0, 0, 0);
    gtk_label_set_mnemonic_widget(GTK_LABEL(label), page->filetype);

    gtk_widget_show_all (table);

    return page;
}


static ImportDialogDestPage *
importer_dest_page_new (ImportData *data)
{
    ImportDialogDestPage *page;

    page = g_new0 (ImportDialogDestPage, 1);

    page->vbox = gtk_vbox_new (FALSE, 5);

    return page;
}

static ImportDialogTypePage *
importer_type_page_new (ImportData *data)
{
    ImportDialogTypePage *page;

    page = g_new0 (ImportDialogTypePage, 1);

    page->vbox = gtk_vbox_new (FALSE, 5);
    page->intelligent = gtk_radio_button_new_with_mnemonic (NULL, 
                                 _("Import data and settings from _older programs"));
    gtk_box_pack_start (GTK_BOX (page->vbox), page->intelligent, FALSE, FALSE, 0);
    page->file = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (page->intelligent),
                                  _("Import a _single file"));
    gtk_box_pack_start (GTK_BOX (page->vbox), page->file, FALSE, FALSE, 0);
    gtk_widget_show_all (page->vbox);
    return page;
}

static ImportDialogImporterPage *
importer_importer_page_new (ImportData *data)
{
    ImportDialogImporterPage *page;
    GtkWidget *sep;

    page = g_new0 (ImportDialogImporterPage, 1);

    page->vbox = gtk_vbox_new (FALSE, 5);
    gtk_container_set_border_width (GTK_CONTAINER (page->vbox), 4);

    sep = gtk_hseparator_new ();
    gtk_box_pack_start (GTK_BOX (page->vbox), sep, FALSE, FALSE, 0);

    page->prepared = FALSE;
    gtk_widget_show_all (page->vbox);

    return page;
}

static GList *
get_intelligent_importers (void)
{
    Bonobo_ServerInfoList *info_list;
    GList *iids_ret = NULL;
    CORBA_Environment ev;
    int i;

    CORBA_exception_init (&ev);
    info_list = bonobo_activation_query (IMPORTER_INTEL_REPO_ID_QUERY, NULL, &ev);
    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 gboolean
prepare_intelligent_page (GnomeDruidPage *page,
              GnomeDruid *druid,
              ImportData *data)
{
    GtkWidget *dialog;
    ImportDialogImporterPage *import;
    GList *l, *importers;
    GtkWidget *table, *no_data;
    int running = 0;

    if (data->importerpage->prepared == TRUE) {
        if (data->importerpage->running == 0)
            gnome_druid_set_buttons_sensitive(druid, TRUE, FALSE, TRUE, FALSE);
        return TRUE;
    }

    data->importerpage->prepared = TRUE;

    dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_NONE, "%s",
                    _("Please wait...\nScanning for existing setups"));
    e_make_widget_backing_stored (dialog);
#if !GTK_CHECK_VERSION(2,4,0)
    /* not needed for message_dialog with GTK+ 2.4 */
    gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
#endif

    gtk_window_set_title (GTK_WINDOW (dialog), _("Starting Intelligent Importers"));
    gtk_widget_show_all (dialog);
    gtk_widget_show_now (dialog);

    gtk_widget_queue_draw (dialog);
    gdk_flush ();

    while (gtk_events_pending ()) {
        gtk_main_iteration ();
    }

    import = data->importerpage;
    importers = get_intelligent_importers ();
    if (importers == NULL) {
        /* No importers, go directly to finish, do not pass go
           Do not collect $200 */
        import->running = 0;
        no_data = create_help ("nodata_html");
        gtk_box_pack_start (GTK_BOX (data->importerpage->vbox), no_data,
                    FALSE, TRUE, 0);
        gnome_druid_set_buttons_sensitive(druid, TRUE, FALSE, TRUE, FALSE);
        gtk_widget_destroy (dialog);
        return TRUE;
    }

    table = gtk_table_new (g_list_length (importers), 2, FALSE);
    for (l = importers; l; l = l->next) {
        GtkWidget *label;
        IntelligentImporterData *id;
        CORBA_Environment ev;
        gboolean can_run;
        char *str;
        
        id = g_new0 (IntelligentImporterData, 1);
        id->iid = g_strdup (l->data);

        CORBA_exception_init (&ev);
        id->object = bonobo_activation_activate_from_id ((char *) id->iid, 0, NULL, &ev);
        if (BONOBO_EX (&ev)) {
            g_warning ("Could not start %s:%s", id->iid,
                   CORBA_exception_id (&ev));

            CORBA_exception_free (&ev);
            /* Clean up the IID */
            g_free (id->iid);
            g_free (id);
            continue;
        }

        if (id->object == CORBA_OBJECT_NIL) {
            g_warning ("Could not activate component %s", id->iid);
            CORBA_exception_free (&ev);

            g_free (id->iid);
            g_free (id);
            continue;
        }

        can_run = GNOME_Evolution_IntelligentImporter_canImport (id->object, &ev);
        if (BONOBO_EX (&ev)) {
            g_warning ("Could not call canImport(%s): %s", id->iid,
                   CORBA_exception_id (&ev));
            bonobo_object_release_unref (id->object, &ev);
            CORBA_exception_free (&ev);

            g_free (id->iid);
            g_free (id);
            continue;
        }

        if (can_run == FALSE) {
            bonobo_object_release_unref (id->object, &ev);
            CORBA_exception_free (&ev);
            g_free (id->iid);
            g_free (id);
            continue;
        }

        running++;
        id->name = GNOME_Evolution_IntelligentImporter__get_importername (id->object, &ev);
        if (BONOBO_EX (&ev)) {
            g_warning ("Could not get name(%s): %s", id->iid,
                   CORBA_exception_id (&ev));
            bonobo_object_release_unref (id->object, &ev);
            CORBA_exception_free (&ev);
            g_free (id->iid);
            g_free (id);
            continue;
        }

        id->blurb = GNOME_Evolution_IntelligentImporter__get_message (id->object, &ev);
        if (BONOBO_EX (&ev)) {
            g_warning ("Could not get message(%s): %s",
                   id->iid, CORBA_exception_id (&ev));
            bonobo_object_release_unref (id->object, &ev);
            CORBA_exception_free (&ev);
            g_free (id->iid);
            CORBA_free (id->name);
            g_free (id);
            continue;
        }

        id->control = Bonobo_Unknown_queryInterface (id->object,
                                 "IDL:Bonobo/Control:1.0", &ev);
        if (BONOBO_EX (&ev)) {
            g_warning ("Could not QI for Bonobo/Control:1.0 %s:%s",
                   id->iid, CORBA_exception_id (&ev));
            bonobo_object_release_unref (id->object, &ev);
            CORBA_exception_free (&ev);
            g_free (id->iid);
            CORBA_free (id->name);
            CORBA_free (id->blurb);
            continue;
        }

        if (id->control != CORBA_OBJECT_NIL) {
            id->widget = bonobo_widget_new_control_from_objref (id->control, CORBA_OBJECT_NIL);
            gtk_widget_show (id->widget);
        } else {
            id->widget = gtk_label_new ("");
            gtk_widget_show (id->widget);
        }

        CORBA_exception_free (&ev);

        import->importers = g_list_prepend (import->importers, id);
        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); 

        gtk_table_attach (GTK_TABLE (table), label, 0, 1, running - 1,
                  running, GTK_FILL, 0, 0, 0);
        gtk_table_attach (GTK_TABLE (table), id->widget, 1, 2,
                  running - 1, running, GTK_FILL, 0, 3, 0);
        gtk_box_pack_start (GTK_BOX (data->importerpage->vbox), table,
                    FALSE, FALSE, 0);
    }

    gtk_widget_show_all (table);

    if (running == 0) {
        no_data = create_help ("nodata_html");
        gtk_box_pack_start (GTK_BOX (data->importerpage->vbox), no_data,
                    FALSE, TRUE, 0);
        gnome_druid_set_buttons_sensitive(druid, TRUE, FALSE, TRUE, FALSE);
        gtk_widget_destroy (dialog);
        return TRUE;
    }

    import->running = running;
    gtk_widget_destroy (dialog);

    return FALSE;
}

static void
import_druid_cancel (GnomeDruid *druid,
             ImportData *data)
{
    gtk_widget_destroy (GTK_WIDGET (data->dialog));
}

static gboolean
import_druid_esc (GnomeDruid *druid, 
          GdkEventKey *event, 
          ImportData *data)
{
    if (event->keyval == GDK_Escape) {
        gtk_widget_destroy (GTK_WIDGET (data->dialog));
        return TRUE;
    } else
        return FALSE;
}

static void
import_druid_weak_notify (void *blah,
              GObject *where_the_object_was)
{
    ImportData *data = (ImportData *) blah;

    g_object_unref (data->wizard);
    g_free (data->choosen_iid);
    g_free (data);
}

static void
free_importers (ImportData *data)
{
    GList *l;

    for (l = data->importerpage->importers; l; l = l->next) {
        IntelligentImporterData *iid;

        iid = l->data;
        if (iid->object != CORBA_OBJECT_NIL) {
            bonobo_object_release_unref (iid->object, NULL);
        }
    }

    g_list_free (data->importerpage->importers);
}

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 (ImportData *data)
{
    CORBA_Environment ev;
    GList *l, *selected = NULL;

    for (l = data->importerpage->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 (data);

    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);
    }
}
                
static void
import_druid_finish (GnomeDruidPage *page,
             GnomeDruid *druid,
             ImportData *data)
{
    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->typepage->intelligent))) {
        do_import (data);
    } else {
        start_import (druid, data->filename, data->client);
    }

    gtk_widget_destroy (data->dialog);
}

static gboolean
prepare_file_page (GnomeDruidPage *page,
           GnomeDruid *druid,
           ImportData *data)
{
    gnome_druid_set_buttons_sensitive (druid, TRUE, 
                       !data->filepage->need_filename, 
                       TRUE, FALSE);
    return FALSE;
}

static gboolean
next_file_page (GnomeDruidPage *page,
        GnomeDruid *druid,
        ImportData *data)
{
    char *real_iid = NULL;
    char *utf8_filename;

    /* Get and test the file name */
    if (data->filename)
        g_free (data->filename);
    utf8_filename = gnome_file_entry_get_full_path (GNOME_FILE_ENTRY (data->filepage->filename), FALSE);
    data->filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
    
    if (!g_file_test (data->filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
        e_notice (druid, GTK_MESSAGE_ERROR, _("File %s does not exist"), utf8_filename);
        gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->filedialog));
        g_free (utf8_filename);
        return TRUE;
    }

    /* Work out the component to use */
    if (data->choosen_iid == NULL || strcmp (data->choosen_iid, "Automatic") == 0) {
        if (!get_iid_for_filetype (data->filename, &real_iid)) {
            gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->filedialog));

            g_free (utf8_filename);
            return TRUE;            
        }   
    } else {
        real_iid = g_strdup (data->choosen_iid);
    }

    if (!real_iid) {
        e_notice (druid, GTK_MESSAGE_ERROR, _("No importer available for file %s"), utf8_filename);
        gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->filedialog));

        g_free (utf8_filename);
        return TRUE;
    }

    if (data->client)
        g_object_unref (data->client);
    data->client = evolution_importer_client_new_from_id (real_iid);
    g_free (real_iid);
    g_free (utf8_filename);

    if (!data->client) {
        e_notice (druid, GTK_MESSAGE_ERROR, _("Unable to execute importer"));
        gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->filedialog));

        return TRUE;
    }
    
    return FALSE;
}

static gboolean
prepare_dest_page (GnomeDruidPage *page,
           GnomeDruid *druid,
           ImportData *data)
{   
    /* Add the widget */
    if (data->control)
        gtk_container_remove (GTK_CONTAINER (data->destpage->vbox), data->control);
    data->control = evolution_importer_client_create_control (data->client);
    gtk_box_pack_start((GtkBox *)data->destpage->vbox, data->control, FALSE, FALSE, 0);
    gtk_widget_show_all (data->destpage->vbox);

    return FALSE;
}

static gboolean
next_dest_page (GnomeDruidPage *page,
        GnomeDruid *druid,
        ImportData *data)
{
    gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->finish));
    return TRUE;
}

static gboolean
next_type_page (GnomeDruidPage *page,
        GnomeDruid *druid,
        ImportData *data)
{
    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->typepage->intelligent))) {
        gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->intelligent));
    } else {
        gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->filedialog));
    }

    return TRUE;
}

static gboolean
back_finish_page (GnomeDruidPage *page,
          GnomeDruid *druid,
          ImportData *data)
{
    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->typepage->intelligent))) {
        if (data->importerpage->running != 0) {
            gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->intelligent));
        } else {
            gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->typedialog));
        }
    } else {
        gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->destdialog));
    }

    return TRUE;
}

static gboolean
back_intelligent_page (GnomeDruidPage *page,
               GnomeDruid *druid,
               ImportData *data)
{
    gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->typedialog));
    return TRUE;
}

static void
dialog_weak_notify (void *data,
            GObject *where_the_dialog_was)
{
    gboolean *dialog_open = (gboolean *) data;

    *dialog_open = FALSE;
}

void
e_shell_importer_start_import (EShellWindow *shell_window)
{
    ImportData *data = g_new0 (ImportData, 1);
    GtkWidget *html;
    static gboolean dialog_open = FALSE;
    GdkPixbuf *icon;

    if (dialog_open) {
        return;
    }
    
    icon = e_icon_factory_get_icon ("stock_mail-import", E_ICON_SIZE_DIALOG);
    
    dialog_open = TRUE;
    data->window = shell_window;
    data->shell = e_shell_window_peek_shell (data->window);

    data->wizard = glade_xml_new (EVOLUTION_GLADEDIR "/import.glade", NULL, NULL);
    data->dialog = glade_xml_get_widget (data->wizard, "importwizard");
    gtk_window_set_default_size (GTK_WINDOW (data->dialog), 480, 320);
    gtk_window_set_wmclass (GTK_WINDOW (data->dialog), "importdruid",
                "Evolution:shell");
    e_dialog_set_transient_for (GTK_WINDOW (data->dialog), GTK_WIDGET (shell_window));
    g_object_weak_ref ((GObject *)data->dialog, dialog_weak_notify, &dialog_open);
    
    data->druid = glade_xml_get_widget (data->wizard, "druid1");
    g_signal_connect (data->druid, "cancel",
              G_CALLBACK (import_druid_cancel), data);
    g_signal_connect (data->druid, "key_press_event",
              G_CALLBACK (import_druid_esc), data);

    gtk_button_set_use_underline ((GtkButton *)((GnomeDruid *)data->druid)->finish, TRUE);
    gtk_button_set_label((GtkButton *)((GnomeDruid *)data->druid)->finish, _("_Import"));

    /* Start page */
    data->start = GNOME_DRUID_PAGE_EDGE (glade_xml_get_widget (data->wizard, "page0"));
    gnome_druid_page_edge_set_logo (data->start, icon);

    /* Intelligent or direct import page */
    data->typedialog = glade_xml_get_widget (data->wizard, "page1");
    gnome_druid_page_standard_set_logo (GNOME_DRUID_PAGE_STANDARD (data->typedialog), icon);
    g_signal_connect (data->typedialog, "next",
              G_CALLBACK (next_type_page), data);
    data->typepage = importer_type_page_new (data);
    html = create_help ("type_html");
    gtk_box_pack_start (GTK_BOX (data->typepage->vbox), html, FALSE, TRUE, 0);
    gtk_box_reorder_child (GTK_BOX (data->typepage->vbox), html, 0);

    gtk_box_pack_start (GTK_BOX (GNOME_DRUID_PAGE_STANDARD (data->typedialog)->vbox), data->typepage->vbox, TRUE, TRUE, 0);

    /* Intelligent importer source page */
    data->intelligent = glade_xml_get_widget (data->wizard, "page2-intelligent");
    gnome_druid_page_standard_set_logo (GNOME_DRUID_PAGE_STANDARD (data->intelligent), icon);
    g_signal_connect (data->intelligent, "back",
              G_CALLBACK (back_intelligent_page), data);
    g_signal_connect_after (data->intelligent, "prepare",
              G_CALLBACK (prepare_intelligent_page), data);

    data->importerpage = importer_importer_page_new (data);
    html = create_help ("intelligent_html");
    gtk_box_pack_start (GTK_BOX (data->importerpage->vbox), html, FALSE, TRUE, 0);
    gtk_box_reorder_child (GTK_BOX (data->importerpage->vbox), html, 0);
    
    gtk_box_pack_start (GTK_BOX (GNOME_DRUID_PAGE_STANDARD (data->intelligent)->vbox), data->importerpage->vbox, TRUE, TRUE, 0);
    

    /* File selection and file type page */
    data->filedialog = glade_xml_get_widget (data->wizard, "page2-file");
    gnome_druid_page_standard_set_logo (GNOME_DRUID_PAGE_STANDARD (data->filedialog), icon);
    g_signal_connect_after (data->filedialog, "prepare",
              G_CALLBACK (prepare_file_page), data);
    g_signal_connect (data->filedialog, "next",
              G_CALLBACK (next_file_page), data);
    data->filepage = importer_file_page_new (data);

    html = create_help ("file_html");
    gtk_box_pack_start (GTK_BOX (data->filepage->vbox), html, FALSE, TRUE, 0);
    gtk_box_reorder_child (GTK_BOX (data->filepage->vbox), html, 0);

    gtk_box_pack_start (GTK_BOX (GNOME_DRUID_PAGE_STANDARD (data->filedialog)->vbox), data->filepage->vbox, TRUE, TRUE, 0);

    /* File destination page */
    data->destdialog = glade_xml_get_widget (data->wizard, "page3-file");
    g_signal_connect_after (data->destdialog, "prepare",
              G_CALLBACK (prepare_dest_page), data);
    g_signal_connect (data->destdialog, "next",
              G_CALLBACK (next_dest_page), data);

    data->destpage = importer_dest_page_new (data);

    gtk_box_pack_start (GTK_BOX (GNOME_DRUID_PAGE_STANDARD (data->destdialog)->vbox), data->destpage->vbox, TRUE, TRUE, 0);

    /* Finish page */
    data->finish = GNOME_DRUID_PAGE_EDGE (glade_xml_get_widget (data->wizard, "page4"));
    gnome_druid_page_edge_set_logo (data->finish, icon);
    g_signal_connect (data->finish, "back",
              G_CALLBACK (back_finish_page), data);

    g_signal_connect (data->finish, "finish",
              G_CALLBACK (import_druid_finish), data);

    g_object_weak_ref ((GObject *)data->dialog, import_druid_weak_notify, data);

    g_object_unref (icon);

    gtk_widget_show_all (data->dialog);
}