source: trunk/third/evolution/shell/e-shell-importer.c @ 18142

Revision 18142, 32.4 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18141, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2/* importer.c
3 *
4 * Copyright (C) 2000  Ximian, Inc.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 * Author: Iain Holmes  <iain@ximian.com>
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <unistd.h>
30
31#include <glib.h>
32#include <libgnome/gnome-defs.h>
33#include <libgnome/gnome-i18n.h>
34#include <libgnomeui/gnome-druid.h>
35#include <libgnomeui/gnome-druid-page-finish.h>
36#include <libgnomeui/gnome-druid-page-standard.h>
37#include <libgnomeui/gnome-druid-page-start.h>
38#include <libgnomeui/gnome-file-entry.h>
39#include <libgnomeui/gnome-stock.h>
40#include <libgnomeui/gnome-dialog.h>
41
42#include <liboaf/liboaf.h>
43
44#include <bonobo/bonobo-exception.h>
45#include <bonobo/bonobo-widget.h>
46
47#include "e-shell.h"
48#include "e-shell-view.h"
49#include "e-shell-constants.h"
50#include "e-shell-folder-selection-dialog.h"
51
52#include "importer/evolution-importer-client.h"
53
54#include <glade/glade.h>
55#include <gtkhtml/gtkhtml.h>
56#include <gal/widgets/e-gui-utils.h>
57#include <gal/widgets/e-gui-utils.h>
58#include <gal/widgets/e-unicode.h>
59
60#include "e-util/e-html-utils.h"
61#include "e-util/e-gtk-utils.h"
62
63#include "e-shell-importer.h"
64#include "importer/GNOME_Evolution_Importer.h"
65
66typedef struct _ImportDialogFilePage {
67        GtkWidget *vbox;
68        GtkWidget *filename;
69        GtkWidget *filetype;
70        GtkWidget *menu;
71
72        gboolean need_filename;
73} ImportDialogFilePage;
74
75typedef struct _ImportDialogTypePage {
76        GtkWidget *vbox;
77        GtkWidget *intelligent;
78        GtkWidget *file;
79} ImportDialogTypePage;
80
81typedef struct _ImportDialogImporterPage {
82        GtkWidget *vbox;
83
84        GList *importers;
85        gboolean prepared;
86        int running;
87} ImportDialogImporterPage;
88
89typedef struct _ImportData {
90        EShell *shell;
91        EShellView *view;
92       
93        GladeXML *wizard;
94        GtkWidget *dialog;
95        GtkWidget *druid;
96        ImportDialogFilePage *filepage;
97        ImportDialogTypePage *typepage;
98        ImportDialogImporterPage *importerpage;
99
100        GtkWidget *filedialog;
101        GtkWidget *typedialog;
102        GtkWidget *intelligent;
103        GnomeDruidPageStart *start;
104        GnomeDruidPageFinish *finish;
105        GtkWidget *vbox;
106
107        char *choosen_iid;
108} ImportData;
109
110typedef struct _IntelligentImporterData {
111        CORBA_Object object;
112        Bonobo_Control control;
113        GtkWidget *widget;
114
115        char *name;
116        char *blurb;
117        char *iid;
118} IntelligentImporterData;
119
120typedef struct _SelectedImporterData{
121        CORBA_Object importer;
122        char *iid;
123} SelectedImporterData;
124
125/*
126  #define IMPORTER_DEBUG
127*/
128#ifdef IMPORTER_DEBUG
129#define IN g_print ("=====> %s (%d)\n", __FUNCTION__, __LINE__)
130#define OUT g_print ("<==== %s (%d)\n", __FUNCTION__, __LINE__)
131#else
132#define IN
133#define OUT
134#endif
135
136/* Some HTML helper functions copied from mail/mail-config-druid.c */
137static struct {
138        char *name;
139        char *text;
140} info[] = {
141        { "type_html",
142          N_("Choose the type of importer to run:")
143        },
144        { "file_html",
145          N_("Choose the file that you want to import into Evolution, "
146             "and select what type of file it is from the list.\n\n"
147             "You can select \"Automatic\" if you do not know, and "
148             "Evolution will attempt to work it out.")
149        },
150        { "intelligent_html",
151          N_("Please select the information that you would like to import:")
152        }
153};
154static int num_info = (sizeof (info) / sizeof (info[0]));
155
156static void
157html_size_req (GtkWidget *widget,
158               GtkRequisition *requisition)
159{
160        requisition->height = GTK_LAYOUT (widget)->height;
161}
162
163static GtkWidget *
164create_html (const char *name)
165{
166        GtkWidget *scrolled, *html;
167        GtkHTMLStream *stream;
168        GtkStyle *style;
169        char *utf8;
170        int i;
171
172        html = gtk_html_new ();
173        GTK_LAYOUT (html)->height = 0;
174        gtk_signal_connect (GTK_OBJECT (html), "size_request",
175                            GTK_SIGNAL_FUNC (html_size_req), NULL);
176        gtk_html_set_editable (GTK_HTML (html), FALSE);
177        style = gtk_rc_get_style (html);
178        if (!style)
179                style = gtk_widget_get_style (html);
180        if (style) {
181                gtk_html_set_default_background_color (GTK_HTML (html),
182                                                       &style->bg[0]);
183        }
184        gtk_widget_show (html);
185
186        scrolled = gtk_scrolled_window_new (NULL, NULL);
187        gtk_widget_show (scrolled);
188        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
189                                        GTK_POLICY_NEVER, GTK_POLICY_NEVER);
190        gtk_container_add (GTK_CONTAINER (scrolled), html);
191
192        for (i = 0; i < num_info; i++) {
193                if (!strcmp (name, info[i].name))
194                        break;
195        }
196        g_return_val_if_fail (i != num_info, scrolled);
197
198        stream = gtk_html_begin_content (GTK_HTML (html),
199                                         "text/html; charset=utf-8");
200        gtk_html_write (GTK_HTML (html), stream, "<html><p>", 9);
201        utf8 = e_utf8_from_locale_string (_(info[i].text));
202        gtk_html_write (GTK_HTML (html), stream, utf8, strlen (utf8));
203        g_free (utf8);
204        gtk_html_write (GTK_HTML (html), stream, "</p></html>", 11);
205        gtk_html_end (GTK_HTML (html), stream, GTK_HTML_STREAM_OK);
206
207        return scrolled;
208}
209
210/* Importing functions */
211
212/* Data to be passed around */
213typedef struct _ImporterComponentData {
214        EvolutionImporterClient *client;
215        EvolutionImporterListener *listener;
216        char *filename;
217
218        GnomeDialog *dialog;
219        GtkWidget *contents;
220
221        int item;
222
223        gboolean stop;
224        gboolean destroyed;
225} ImporterComponentData;
226
227static gboolean importer_timeout_fn (gpointer data);
228static void
229import_cb (EvolutionImporterListener *listener,
230           EvolutionImporterResult result,
231           gboolean more_items,
232           void *data)
233{
234        ImporterComponentData *icd = (ImporterComponentData *) data;
235        char *label;
236
237        IN;
238        if (icd->stop != TRUE) {
239                if (result == EVOLUTION_IMPORTER_NOT_READY) {
240                        gtk_timeout_add (500, importer_timeout_fn, data);
241                        OUT;
242                        return;
243                }
244               
245                if (result == EVOLUTION_IMPORTER_BUSY) {
246                        gtk_timeout_add (500, importer_timeout_fn, data);
247                        OUT;
248                        return;
249                }
250
251                if (more_items) {
252                        label = g_strdup_printf (_("Importing %s\nImporting item %d."),
253                                                 icd->filename, ++(icd->item));
254                        gtk_label_set_text (GTK_LABEL (icd->contents), label);
255                        g_free (label);
256                        while (gtk_events_pending ())
257                                gtk_main_iteration ();
258                       
259                        g_idle_add_full (G_PRIORITY_LOW, importer_timeout_fn,
260                                         data, NULL);
261                        OUT;
262                        return;
263                }
264        }
265       
266        g_free (icd->filename);
267        if (!icd->destroyed)
268                gtk_object_destroy (GTK_OBJECT (icd->dialog));
269        bonobo_object_unref (BONOBO_OBJECT (icd->listener));
270        gtk_object_unref (GTK_OBJECT (icd->client));
271        g_free (icd);
272
273        OUT;
274}
275
276static gboolean
277importer_timeout_fn (gpointer data)
278{
279        ImporterComponentData *icd = (ImporterComponentData *) data;
280        char *label;
281
282        IN;
283        label = g_strdup_printf (_("Importing %s\nImporting item %d."),
284                                 icd->filename, icd->item);
285        gtk_label_set_text (GTK_LABEL (icd->contents), label);
286        g_free (label);
287        while (gtk_events_pending ())
288                gtk_main_iteration ();
289       
290        evolution_importer_client_process_item (icd->client, icd->listener);
291        OUT;
292        return FALSE;
293}
294
295static void
296dialog_clicked_cb (GnomeDialog *dialog,
297                   int button_number,
298                   ImporterComponentData *icd)
299{
300        if (button_number != 0)
301                return; /* Interesting... */
302
303        icd->stop = TRUE;
304}
305
306static void
307dialog_destroy_cb (GtkObject *object,
308                   ImporterComponentData *icd)
309{
310        icd->stop = TRUE;
311        icd->destroyed = TRUE;
312}
313
314struct _IIDInfo {
315        char *iid;
316        char *name;
317};
318
319static void
320free_iid_list (GList *list)
321{
322        for (; list; list = list->next) {
323                struct _IIDInfo *iid = list->data;
324
325                g_free (iid->iid);
326                g_free (iid->name);
327                g_free (iid);
328        }
329}
330
331static const char *
332get_name_from_component_info (const OAF_ServerInfo *info)
333{
334        OAF_Property *property;
335        const char *name;
336
337        property = oaf_server_info_prop_find ((OAF_ServerInfo *) info,
338                                              "evolution:menu-name");
339        if (property == NULL || property->v._d != OAF_P_STRING)
340                return NULL;
341
342        name = property->v._u.value_string;
343
344        return name;
345}
346
347static char *
348choose_importer_from_list (GList *importer_list)
349{
350        GtkWidget *dialog, *clist;
351        GList *p;
352        int ans;
353        char *iid;
354
355        dialog = gnome_dialog_new (_("Select importer"),
356                                   GNOME_STOCK_BUTTON_OK,
357                                   GNOME_STOCK_BUTTON_CANCEL,
358                                   NULL);
359        clist = gtk_clist_new (1);
360        for (p = importer_list; p; p = p->next) {
361                struct _IIDInfo *iid;
362                char *text[1];
363                int row;
364
365                iid = p->data;
366                text[0] = iid->name;
367                row = gtk_clist_append (GTK_CLIST (clist), text);
368                gtk_clist_set_row_data (GTK_CLIST (clist), row, iid->iid);
369        }
370
371        gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), clist,
372                            TRUE, TRUE, 0);
373        gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_BROWSE);
374        gtk_widget_show (clist);
375       
376        switch (gnome_dialog_run (GNOME_DIALOG (dialog))) {
377        case 0:
378                ans = GPOINTER_TO_INT (GTK_CLIST (clist)->selection->data);
379                iid = gtk_clist_get_row_data (GTK_CLIST (clist), ans);
380                break;
381
382        case 1:
383        default:
384                iid = NULL;
385                break;
386        }
387       
388        gtk_widget_destroy (dialog);
389
390        return g_strdup (iid);
391}
392
393static char *
394get_iid_for_filetype (const char *filename)
395{
396        OAF_ServerInfoList *info_list;
397        CORBA_Environment ev;
398        GList *can_handle = NULL;
399        char *ret_iid;
400        int i, len = 0;
401
402        CORBA_exception_init (&ev);
403        info_list = oaf_query ("repo_ids.has ('IDL:GNOME/Evolution/Importer:1.0')", NULL, &ev);
404
405        for (i = 0; i < info_list->_length; i++) {
406                CORBA_Environment ev2;
407                CORBA_Object importer;
408                const OAF_ServerInfo *info;
409               
410                info = info_list->_buffer + i;
411
412                CORBA_exception_init (&ev2);
413                importer = oaf_activate_from_id ((char *) info->iid, 0, NULL, &ev2);
414                if (ev2._major != CORBA_NO_EXCEPTION) {
415                        g_warning ("Error activating %s", info->iid);
416                        CORBA_exception_free (&ev2);
417                        continue;
418                }
419
420                if (GNOME_Evolution_Importer_supportFormat (importer,
421                                                            filename, &ev2)) {
422                        struct _IIDInfo *iid;
423
424                        iid = g_new (struct _IIDInfo, 1);
425                        iid->iid = g_strdup (info->iid);
426                        iid->name = g_strdup (get_name_from_component_info (info));
427                       
428                        can_handle = g_list_prepend (can_handle, iid);
429                        len++;
430                }
431
432                bonobo_object_release_unref (importer, &ev2);
433                CORBA_exception_free (&ev2);
434        }
435
436        CORBA_free (info_list);
437
438        if (len == 1) {
439                struct _IIDInfo *iid;
440               
441                iid = can_handle->data;
442
443                ret_iid = g_strdup (iid->iid);
444               
445                free_iid_list (can_handle);
446                g_list_free (can_handle);
447               
448                return ret_iid;
449        } else if (len > 1) {
450                /* Display all the IIDs */
451                ret_iid = choose_importer_from_list (can_handle);
452               
453                free_iid_list (can_handle);
454                g_list_free (can_handle);
455
456                return ret_iid;
457        } else {
458                return NULL;
459        }
460}
461
462static void
463show_error (const char *message,
464            const char *title)
465{
466        GtkWidget *box;
467
468        box = gnome_message_box_new (message, GNOME_MESSAGE_BOX_ERROR, GNOME_STOCK_BUTTON_OK, NULL);
469        gtk_window_set_title (GTK_WINDOW (box), title);
470
471        gtk_widget_show (box);
472}
473
474static void
475start_import (const char *folderpath,
476              const char *filename,
477              const char *iid)
478{
479        ImporterComponentData *icd;
480        char *label;
481        char *real_iid;
482        struct stat buf;
483       
484        if (stat (filename, &buf) == -1) {
485                char *message;
486
487                message = g_strdup_printf (_("File %s does not exist"), filename);
488                show_error (message, _("Evolution Error"));
489                g_free (message);
490
491                return;
492        }
493
494        if (iid == NULL || strcmp (iid, "Automatic") == 0) {
495                /* Work out the component to use */
496                real_iid = get_iid_for_filetype (filename);
497        } else {
498                real_iid = g_strdup (iid);
499        }
500
501        if (real_iid == NULL) {
502                char *message;
503
504                message = g_strdup_printf (_("There is no importer that is able to handle\n%s"), filename);
505                show_error (message, _("Evolution Error"));
506                g_free (message);
507
508                return;
509        }
510
511        icd = g_new (ImporterComponentData, 1);
512        icd->stop = FALSE;
513        icd->destroyed = FALSE;
514        icd->dialog = GNOME_DIALOG (gnome_dialog_new (_("Importing"),
515                                                      GNOME_STOCK_BUTTON_CANCEL,
516                                                      NULL));
517        gtk_signal_connect (GTK_OBJECT (icd->dialog), "clicked",
518                            GTK_SIGNAL_FUNC (dialog_clicked_cb), icd);
519        gtk_signal_connect (GTK_OBJECT (icd->dialog), "destroy",
520                            GTK_SIGNAL_FUNC (dialog_destroy_cb), icd);
521       
522        label = g_strdup_printf (_("Importing %s.\nStarting %s"),
523                                 filename, real_iid);
524        icd->contents = gtk_label_new (label);
525        g_free (label);
526       
527        gtk_box_pack_start (GTK_BOX (icd->dialog->vbox), icd->contents,
528                            TRUE, TRUE, 0);
529        gtk_widget_show_all (GTK_WIDGET (icd->dialog));
530        while (gtk_events_pending ())
531                gtk_main_iteration ();
532       
533        icd->client = evolution_importer_client_new_from_id (real_iid);
534        if (icd->client == NULL) {
535                label = g_strdup_printf (_("Error starting %s"), real_iid);
536                g_free (real_iid);
537                gtk_label_set_text (GTK_LABEL (icd->contents), label);
538                g_free (label);
539                while (gtk_events_pending ())
540                        gtk_main_iteration ();
541
542                gtk_object_unref (GTK_OBJECT (icd->dialog));
543                g_free (icd);
544                return;
545        }
546        g_free (real_iid);
547
548        /* NULL for folderpath means use Inbox */
549        if (*folderpath == '/') {
550                folderpath = strchr (folderpath + 1, '/');
551        }
552
553        if (evolution_importer_client_load_file (icd->client, filename, folderpath) == FALSE) {
554                label = g_strdup_printf (_("Error loading %s"), filename);
555                show_error (label, _("Evolution Error"));
556
557                gtk_label_set_text (GTK_LABEL (icd->contents), label);
558                g_free (label);
559                while (gtk_events_pending ())
560                        gtk_main_iteration ();
561               
562                gtk_object_unref (GTK_OBJECT (icd->client));
563                gtk_object_unref (GTK_OBJECT (icd->dialog));
564                g_free (icd);
565                return;
566        }
567
568        icd->filename = g_strdup (filename);
569        icd->item = 1;
570       
571        label = g_strdup_printf (_("Importing %s\nImporting item 1."),
572                                 filename);
573        gtk_label_set_text (GTK_LABEL (icd->contents), label);
574        g_free (label);
575        while (gtk_events_pending ())
576                gtk_main_iteration ();
577
578        icd->listener = evolution_importer_listener_new (import_cb, icd);
579        evolution_importer_client_process_item (icd->client, icd->listener);
580}
581
582static void
583filename_changed (GtkEntry *entry,
584                  ImportData *data)
585{
586        ImportDialogFilePage *page;
587        char *filename;
588
589        page = data->filepage;
590
591        filename = gtk_entry_get_text (entry);
592        if (filename != NULL && *filename != '\0')
593                page->need_filename = FALSE;
594        else
595                page->need_filename = TRUE;
596
597        gnome_druid_set_buttons_sensitive (GNOME_DRUID (data->druid),
598                                           TRUE, !page->need_filename, TRUE);
599}
600
601static void
602item_selected (GtkWidget *item,
603               ImportData *data)
604{
605        char *iid;
606
607        g_free (data->choosen_iid);
608        iid = gtk_object_get_data (GTK_OBJECT (item), "oafiid");
609        if (iid == NULL)
610                data->choosen_iid = g_strdup ("Automatic");
611        else
612                data->choosen_iid = g_strdup (iid);
613}
614
615static GtkWidget *
616create_plugin_menu (ImportData *data)
617{
618        OAF_ServerInfoList *info_list;
619        CORBA_Environment ev;
620        int i;
621        GtkWidget *menu;
622        GtkWidget *item;
623
624        menu = gtk_menu_new ();
625        item = gtk_menu_item_new_with_label (_("Automatic"));
626        gtk_object_set_data_full (GTK_OBJECT (item), "oafiid",
627                                  g_strdup ("Automatic"), g_free);
628        gtk_menu_append (GTK_MENU (menu), item);
629
630        CORBA_exception_init (&ev);
631        info_list = oaf_query ("repo_ids.has ('IDL:GNOME/Evolution/Importer:1.0')", NULL, &ev);
632        for (i = 0; i < info_list->_length; i++) {
633                const OAF_ServerInfo *info;
634                char *name = NULL;
635
636                info = info_list->_buffer + i;
637
638                name = g_strdup (get_name_from_component_info (info));
639                if (name == NULL) {
640                        name = g_strdup (info->iid);
641                }
642
643                item = gtk_menu_item_new_with_label (name);
644                g_free (name);
645                gtk_widget_show (item);
646                gtk_signal_connect (GTK_OBJECT (item), "activate",
647                                    GTK_SIGNAL_FUNC (item_selected), data);
648
649                gtk_object_set_data_full (GTK_OBJECT (item), "oafiid",
650                                          g_strdup (info->iid), g_free);
651                gtk_menu_append (GTK_MENU (menu), item);
652        }
653        CORBA_free (info_list);
654
655        return menu;
656}
657
658static ImportDialogFilePage *
659importer_file_page_new (ImportData *data)
660{
661        ImportDialogFilePage *page;
662        GtkWidget *table, *label;
663        int row = 0;
664
665        page = g_new0 (ImportDialogFilePage, 1);
666
667        page->vbox = gtk_vbox_new (FALSE, 5);
668        page->need_filename = TRUE;
669
670        table = gtk_table_new (2, 2, FALSE);
671        gtk_table_set_row_spacings (GTK_TABLE (table), 2);
672        gtk_table_set_col_spacings (GTK_TABLE (table), 10);
673        gtk_container_set_border_width (GTK_CONTAINER (table), 8);
674        gtk_box_pack_start (GTK_BOX (page->vbox), table, TRUE, TRUE, 0);
675
676        label = gtk_label_new (_("Filename:"));
677        gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
678                          GTK_FILL, 0, 0, 0);
679        gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
680
681        page->filename = gnome_file_entry_new ("Evolution_Importer_FileName", _("Select a file"));
682        gtk_signal_connect (GTK_OBJECT (gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (page->filename))),
683                            "changed", GTK_SIGNAL_FUNC (filename_changed),
684                            data);
685
686        gtk_table_attach (GTK_TABLE (table), page->filename, 1, 2,
687                          row, row + 1, GTK_EXPAND | GTK_FILL, 0, 0, 0);
688
689        row++;
690
691        label = gtk_label_new (_("File type:"));
692        gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row + 1,
693                          GTK_FILL, 0, 0, 0);
694        gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);
695
696        page->filetype = gtk_option_menu_new ();
697        page->menu = create_plugin_menu (data);
698        gtk_option_menu_set_menu (GTK_OPTION_MENU (page->filetype), page->menu);
699        gtk_table_attach (GTK_TABLE (table), page->filetype, 1, 2,
700                          row, row + 1, GTK_EXPAND | GTK_FILL, 0, 0, 0);
701
702        gtk_widget_show_all (table);
703
704        return page;
705}
706
707static ImportDialogTypePage *
708importer_type_page_new (ImportData *data)
709{
710        ImportDialogTypePage *page;
711
712        page = g_new0 (ImportDialogTypePage, 1);
713
714        page->vbox = gtk_vbox_new (FALSE, 5);
715        page->intelligent = gtk_radio_button_new_with_label (NULL,
716                                                             _("Import data and settings from older programs"));
717        gtk_box_pack_start (GTK_BOX (page->vbox), page->intelligent, FALSE, FALSE, 0);
718
719        page->file = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (page->intelligent),
720                                                                  _("Import a single file"));
721        gtk_box_pack_start (GTK_BOX (page->vbox), page->file, FALSE, FALSE, 0);
722        gtk_widget_show_all (page->vbox);
723        return page;
724}
725
726static ImportDialogImporterPage *
727importer_importer_page_new (ImportData *data)
728{
729        ImportDialogImporterPage *page;
730        GtkWidget *sep;
731
732        page = g_new0 (ImportDialogImporterPage, 1);
733
734        page->vbox = gtk_vbox_new (FALSE, 5);
735        gtk_container_set_border_width (GTK_CONTAINER (page->vbox), 4);
736
737        sep = gtk_hseparator_new ();
738        gtk_box_pack_start (GTK_BOX (page->vbox), sep, FALSE, FALSE, 0);
739
740        page->prepared = FALSE;
741        gtk_widget_show_all (page->vbox);
742
743        return page;
744}
745
746static GList *
747get_intelligent_importers (void)
748{
749        OAF_ServerInfoList *info_list;
750        GList *iids_ret = NULL;
751        CORBA_Environment ev;
752        int i;
753
754        CORBA_exception_init (&ev);
755        info_list = oaf_query ("repo_ids.has ('IDL:GNOME/Evolution/IntelligentImporter:1.0')", NULL, &ev);
756        CORBA_exception_free (&ev);
757
758        for (i = 0; i < info_list->_length; i++) {
759                const OAF_ServerInfo *info;
760
761                info = info_list->_buffer + i;
762                iids_ret = g_list_prepend (iids_ret, g_strdup (info->iid));
763        }
764
765        return iids_ret;
766}
767
768static gboolean
769prepare_intelligent_page (GnomeDruid *druid,
770                          GnomeDruidPage *page,
771                          ImportData *data)
772{
773        GtkWidget *dialog;
774        ImportDialogImporterPage *import;
775        GList *l, *importers;
776        GtkWidget *table;
777        int running = 0;
778
779        if (data->importerpage->prepared == TRUE) {
780                return TRUE;
781        }
782
783        data->importerpage->prepared = TRUE;
784
785        dialog = gnome_message_box_new (_("Please wait...\nScanning for existing setups"), GNOME_MESSAGE_BOX_INFO, NULL);
786        e_make_widget_backing_stored (dialog);
787
788        gtk_window_set_title (GTK_WINDOW (dialog), _("Starting Intelligent Importers"));
789        gtk_widget_show_all (dialog);
790        gtk_widget_show_now (dialog);
791
792        gtk_widget_queue_draw (dialog);
793        gdk_flush ();
794
795        while (gtk_events_pending ()) {
796                gtk_main_iteration ();
797        }
798
799        import = data->importerpage;
800        importers = get_intelligent_importers ();
801        if (importers == NULL) {
802                /* No importers, go directly to finish, do not pass go
803                   Do not collect $200 */
804                import->running = 0;
805                gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->finish))
806;
807                gtk_widget_destroy (dialog);
808                return TRUE;
809        }
810
811        table = gtk_table_new (g_list_length (importers), 2, FALSE);
812        for (l = importers; l; l = l->next) {
813                GtkWidget *label;
814                IntelligentImporterData *id;
815                CORBA_Environment ev;
816                gboolean can_run;
817                char *str;
818               
819                id = g_new0 (IntelligentImporterData, 1);
820                id->iid = g_strdup (l->data);
821
822                CORBA_exception_init (&ev);
823                id->object = oaf_activate_from_id ((char *) id->iid, 0, NULL, &ev);
824                if (BONOBO_EX (&ev)) {
825                        g_warning ("Could not start %s:%s", id->iid,
826                                   CORBA_exception_id (&ev));
827
828                        CORBA_exception_free (&ev);
829                        /* Clean up the IID */
830                        g_free (id->iid);
831                        g_free (id);
832                        continue;
833                }
834
835                if (id->object == CORBA_OBJECT_NIL) {
836                        g_warning ("Could not activate component %s", id->iid);
837                        CORBA_exception_free (&ev);
838
839                        g_free (id->iid);
840                        g_free (id);
841                        continue;
842                }
843
844                can_run = GNOME_Evolution_IntelligentImporter_canImport (id->object, &ev);
845                if (BONOBO_EX (&ev)) {
846                        g_warning ("Could not call canImport(%s): %s", id->iid,
847                                   CORBA_exception_id (&ev));
848                        bonobo_object_release_unref (id->object, &ev);
849                        CORBA_exception_free (&ev);
850
851                        g_free (id->iid);
852                        g_free (id);
853                        continue;
854                }
855
856                if (can_run == FALSE) {
857                        bonobo_object_release_unref (id->object, &ev);
858                        CORBA_exception_free (&ev);
859                        g_free (id->iid);
860                        g_free (id);
861                        continue;
862                }
863
864                running++;
865                id->name = GNOME_Evolution_IntelligentImporter__get_importername (id->object, &ev);
866                if (BONOBO_EX (&ev)) {
867                        g_warning ("Could not get name(%s): %s", id->iid,
868                                   CORBA_exception_id (&ev));
869                        bonobo_object_release_unref (id->object, &ev);
870                        CORBA_exception_free (&ev);
871                        g_free (id->iid);
872                        g_free (id);
873                        continue;
874                }
875
876                id->blurb = GNOME_Evolution_IntelligentImporter__get_message (id->object, &ev);
877                if (BONOBO_EX (&ev)) {
878                        g_warning ("Could not get message(%s): %s",
879                                   id->iid, CORBA_exception_id (&ev));
880                        bonobo_object_release_unref (id->object, &ev);
881                        CORBA_exception_free (&ev);
882                        g_free (id->iid);
883                        CORBA_free (id->name);
884                        g_free (id);
885                        continue;
886                }
887
888                id->control = Bonobo_Unknown_queryInterface (id->object,
889                                                             "IDL:Bonobo/Control:1.0", &ev);
890                if (BONOBO_EX (&ev)) {
891                        g_warning ("Could not QI for Bonobo/Control:1.0 %s:%s",
892                                   id->iid, CORBA_exception_id (&ev));
893                        bonobo_object_release_unref (id->object, &ev);
894                        CORBA_exception_free (&ev);
895                        g_free (id->iid);
896                        CORBA_free (id->name);
897                        CORBA_free (id->blurb);
898                        continue;
899                }
900
901                if (id->control != CORBA_OBJECT_NIL) {
902                        id->widget = bonobo_widget_new_control_from_objref (id->control, CORBA_OBJECT_NIL);
903                        gtk_widget_show (id->widget);
904                } else {
905                        id->widget = gtk_label_new ("");
906                        gtk_widget_show (id->widget);
907                }
908
909                CORBA_exception_free (&ev);
910
911                import->importers = g_list_prepend (import->importers, id);
912                str = g_strdup_printf (_("From %s:"), id->name);
913                label = gtk_label_new (str);
914                g_free (str);
915               
916                gtk_misc_set_alignment (GTK_MISC (label), 0, .5);
917
918                gtk_table_attach (GTK_TABLE (table), label, 0, 1, running - 1,
919                                  running, GTK_FILL, 0, 0, 0);
920                gtk_table_attach (GTK_TABLE (table), id->widget, 1, 2,
921                                  running - 1, running, GTK_FILL, 0, 3, 0);
922                gtk_widget_show_all (table);
923
924                gtk_box_pack_start (GTK_BOX (data->importerpage->vbox), table,
925                                    FALSE, FALSE, 0);
926        }
927
928        if (running == 0) {
929                gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->finish));
930                gtk_widget_destroy (dialog);
931                return TRUE;
932        }
933
934        import->running = running;
935        gtk_widget_destroy (dialog);
936
937        return FALSE;
938}
939
940static void
941import_druid_cancel (GnomeDruid *druid,
942                     ImportData *data)
943{
944        gtk_widget_destroy (GTK_WIDGET (data->dialog));
945}
946
947static void
948import_druid_destroy (GtkObject *object,
949                      ImportData *data)
950{
951        gtk_object_unref (GTK_OBJECT (data->wizard));
952        g_free (data->choosen_iid);
953        g_free (data);
954}
955
956static void
957folder_selected (EShellFolderSelectionDialog *dialog,
958                 const char *path,
959                 ImportData *data)
960{
961        char *filename, *iid;
962
963        iid = g_strdup (data->choosen_iid);
964        filename = gnome_file_entry_get_full_path (GNOME_FILE_ENTRY (data->filepage->filename), FALSE);
965
966        gtk_widget_destroy (data->dialog);
967        gtk_widget_hide (GTK_WIDGET (dialog));
968
969        start_import (path, filename, iid);
970
971        g_free (iid);
972        g_free (filename);
973}
974
975static void
976folder_cancelled (EShellFolderSelectionDialog *dialog,
977                  ImportData *data)
978{
979        gtk_widget_destroy (data->dialog);
980}
981
982static void
983free_importers (ImportData *data)
984{
985        GList *l;
986
987        for (l = data->importerpage->importers; l; l = l->next) {
988                IntelligentImporterData *iid;
989
990                iid = l->data;
991                if (iid->object != CORBA_OBJECT_NIL) {
992                        bonobo_object_release_unref (iid->object, NULL);
993                }
994        }
995
996        g_list_free (data->importerpage->importers);
997}
998
999static void
1000start_importers (GList *p)
1001{
1002        CORBA_Environment ev;
1003       
1004        for (; p; p = p->next) {
1005                SelectedImporterData *sid = p->data;
1006
1007                CORBA_exception_init (&ev);
1008                GNOME_Evolution_IntelligentImporter_importData (sid->importer, &ev);
1009                if (BONOBO_EX (&ev)) {
1010                        g_warning ("Error importing %s\n%s", sid->iid,
1011                                   CORBA_exception_id (&ev));
1012                }
1013                CORBA_exception_free (&ev);
1014        }
1015}
1016
1017static void
1018do_import (ImportData *data)
1019{
1020        CORBA_Environment ev;
1021        GList *l, *selected = NULL;
1022
1023        for (l = data->importerpage->importers; l; l = l->next) {
1024                IntelligentImporterData *importer_data;
1025                SelectedImporterData *sid;
1026                char *iid;
1027
1028                importer_data = l->data;
1029                iid = g_strdup (importer_data->iid);
1030
1031                sid = g_new (SelectedImporterData, 1);
1032                sid->iid = iid;
1033
1034                CORBA_exception_init (&ev);
1035                sid->importer = bonobo_object_dup_ref (importer_data->object, &ev);
1036                if (BONOBO_EX (&ev)) {
1037                        g_warning ("Error duplication %s\n(%s)", iid,
1038                                   CORBA_exception_id (&ev));
1039                        g_free (iid);
1040                        CORBA_exception_free (&ev);
1041                        g_free (sid);
1042                        continue;
1043                }
1044                CORBA_exception_free (&ev);
1045
1046                selected = g_list_prepend (selected, sid);
1047        }
1048
1049        free_importers (data);
1050
1051        if (selected != NULL) {
1052                start_importers (selected);
1053
1054                for (l = selected; l; l = l->next) {
1055                        SelectedImporterData *sid = l->data;
1056
1057                        CORBA_exception_init (&ev);
1058                        bonobo_object_release_unref (sid->importer, &ev);
1059                        CORBA_exception_free (&ev);
1060
1061                        g_free (sid->iid);
1062                        g_free (sid);
1063                }
1064                g_list_free (selected);
1065        }
1066}
1067                               
1068static void
1069import_druid_finish (GnomeDruidPage *page,
1070                     GnomeDruid *druid,
1071                     ImportData *data)
1072{
1073        GtkWidget *folder;
1074
1075        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->typepage->intelligent))) {
1076                do_import (data);
1077                gtk_widget_destroy (data->dialog);
1078        } else {
1079                folder = e_shell_folder_selection_dialog_new (data->shell,
1080                                                              _("Select folder"),
1081                                                              _("Select a destination folder for importing this data"),
1082                                                              e_shell_view_get_current_uri (data->view),
1083                                                              NULL);
1084               
1085                gtk_signal_connect (GTK_OBJECT (folder), "folder_selected",
1086                                    GTK_SIGNAL_FUNC (folder_selected), data);
1087                gtk_signal_connect (GTK_OBJECT (folder), "cancelled",
1088                                    GTK_SIGNAL_FUNC (folder_cancelled), data);
1089               
1090                gtk_widget_hide (data->dialog);
1091                gtk_widget_show (folder);
1092        }
1093}
1094
1095static gboolean
1096prepare_file_page (GnomeDruidPage *page,
1097                   GnomeDruid *druid,
1098                   ImportData *data)
1099{
1100        gnome_druid_set_buttons_sensitive (druid, TRUE,
1101                                           !data->filepage->need_filename,
1102                                           TRUE);
1103        return FALSE;
1104}
1105
1106static gboolean
1107next_file_page (GnomeDruidPage *page,
1108                GnomeDruid *druid,
1109                ImportData *data)
1110{
1111        gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->finish));
1112        return TRUE;
1113}
1114
1115static gboolean
1116back_file_page (GnomeDruidPage *page,
1117                GnomeDruid *druid,
1118                ImportData *data)
1119{
1120        gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->typedialog));
1121        return TRUE;
1122}
1123
1124static gboolean
1125next_type_page (GnomeDruidPage *page,
1126                GnomeDruid *druid,
1127                ImportData *data)
1128{
1129        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->typepage->intelligent))) {
1130                gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->intelligent));
1131        } else {
1132                gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->filedialog));
1133        }
1134
1135        return TRUE;
1136}
1137
1138static gboolean
1139back_finish_page (GnomeDruidPage *page,
1140                GnomeDruid *druid,
1141                ImportData *data)
1142{
1143        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->typepage->intelligent))) {
1144                if (data->importerpage->running != 0) {
1145                        gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->intelligent));
1146                } else {
1147                        gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->typedialog));
1148                }
1149        } else {
1150                gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->filedialog));
1151        }
1152
1153        return TRUE;
1154}
1155
1156static gboolean
1157back_intelligent_page (GnomeDruidPage *page,
1158                       GnomeDruid *druid,
1159                       ImportData *data)
1160{
1161        gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->typedialog));
1162        return TRUE;
1163}
1164
1165static gboolean
1166next_intelligent_page (GnomeDruidPage *page,
1167                       GnomeDruid *druid,
1168                       ImportData *data)
1169{
1170        gnome_druid_set_page (druid, GNOME_DRUID_PAGE (data->finish));
1171        return TRUE;
1172}
1173
1174/* Hack to change the Finish button */
1175static void
1176druid_finish_button_change (GnomeDruid *druid)
1177{
1178        GtkWidget *button = druid->finish;
1179        GtkWidget *hbox = GTK_BIN (button)->child, *hbox2;
1180        GtkBoxChild *child;
1181        GtkWidget *label;
1182
1183        /* Get the second item from the children list */
1184        hbox2 = ((GtkBoxChild *)GTK_BOX (hbox)->children->data)->widget;
1185
1186        g_return_if_fail (GTK_IS_BOX (hbox2));
1187        child = (GtkBoxChild *)g_list_nth_data (GTK_BOX (hbox2)->children, 0);
1188        label = child->widget;
1189
1190        /* Safety check :) */
1191        g_return_if_fail (GTK_IS_LABEL (label));
1192
1193        gtk_label_set_text (GTK_LABEL (label), _("Import"));
1194}
1195
1196static void
1197close_dialog (GtkWidget *dialog,
1198              gboolean *dialog_open)
1199{
1200        *dialog_open = FALSE;
1201}
1202
1203void
1204show_import_wizard (BonoboUIComponent *component,
1205                    gpointer           user_data,
1206                    const char        *cname)
1207{
1208        ImportData *data = g_new0 (ImportData, 1);
1209        GtkWidget *html;
1210        static gboolean dialog_open = FALSE;
1211
1212        if (dialog_open) {
1213                return;
1214        }
1215
1216        dialog_open = TRUE;
1217        data->view = E_SHELL_VIEW (user_data);
1218        data->shell = e_shell_view_get_shell (data->view);
1219
1220        data->wizard = glade_xml_new (EVOLUTION_GLADEDIR "/import.glade", NULL);
1221        data->dialog = glade_xml_get_widget (data->wizard, "importwizard");
1222        gtk_window_set_wmclass (GTK_WINDOW (data->dialog), "importdruid",
1223                                "Evolution:shell");
1224        gtk_window_set_transient_for (GTK_WINDOW (data->dialog), GTK_WINDOW (user_data));
1225        gtk_signal_connect (GTK_OBJECT (data->dialog), "destroy",
1226                            GTK_SIGNAL_FUNC (close_dialog), &dialog_open);
1227        gnome_dialog_close_hides (GNOME_DIALOG (data->dialog), TRUE);
1228       
1229        data->druid = glade_xml_get_widget (data->wizard, "druid1");
1230        gtk_signal_connect (GTK_OBJECT (data->druid), "cancel",
1231                            GTK_SIGNAL_FUNC (import_druid_cancel), data);
1232
1233        druid_finish_button_change (GNOME_DRUID (data->druid));
1234        data->start = GNOME_DRUID_PAGE_START (glade_xml_get_widget (data->wizard, "page0"));
1235
1236        data->typedialog = glade_xml_get_widget (data->wizard, "page1");
1237        gtk_signal_connect (GTK_OBJECT (data->typedialog), "next",
1238                            GTK_SIGNAL_FUNC (next_type_page), data);
1239        data->typepage = importer_type_page_new (data);
1240        html = create_html ("type_html");
1241        gtk_box_pack_start (GTK_BOX (data->typepage->vbox), html, FALSE, TRUE, 0);
1242        gtk_box_reorder_child (GTK_BOX (data->typepage->vbox), html, 0);
1243
1244        gtk_box_pack_start (GTK_BOX (GNOME_DRUID_PAGE_STANDARD (data->typedialog)->vbox), data->typepage->vbox, TRUE, TRUE, 0);
1245
1246        data->intelligent = glade_xml_get_widget (data->wizard, "page2-intelligent");
1247        gtk_signal_connect (GTK_OBJECT (data->intelligent), "next",
1248                            GTK_SIGNAL_FUNC (next_intelligent_page), data);
1249        gtk_signal_connect (GTK_OBJECT (data->intelligent), "back",
1250                            GTK_SIGNAL_FUNC (back_intelligent_page), data);
1251        gtk_signal_connect (GTK_OBJECT (data->intelligent), "prepare",
1252                            GTK_SIGNAL_FUNC (prepare_intelligent_page), data);
1253
1254        data->importerpage = importer_importer_page_new (data);
1255        html = create_html ("intelligent_html");
1256        gtk_box_pack_start (GTK_BOX (data->importerpage->vbox), html, FALSE, TRUE, 0);
1257        gtk_box_reorder_child (GTK_BOX (data->importerpage->vbox), html, 0);
1258       
1259        gtk_box_pack_start (GTK_BOX (GNOME_DRUID_PAGE_STANDARD (data->intelligent)->vbox), data->importerpage->vbox, TRUE, TRUE, 0);
1260       
1261
1262        data->filedialog = glade_xml_get_widget (data->wizard, "page2-file");
1263        gtk_signal_connect (GTK_OBJECT (data->filedialog), "prepare",
1264                            GTK_SIGNAL_FUNC (prepare_file_page), data);
1265        gtk_signal_connect (GTK_OBJECT (data->filedialog), "next",
1266                            GTK_SIGNAL_FUNC (next_file_page), data);
1267        gtk_signal_connect (GTK_OBJECT (data->filedialog), "back",
1268                            GTK_SIGNAL_FUNC (back_file_page), data);
1269
1270        data->finish = GNOME_DRUID_PAGE_FINISH (glade_xml_get_widget (data->wizard, "page3"));
1271        gtk_signal_connect (GTK_OBJECT (data->finish), "back",
1272                            GTK_SIGNAL_FUNC (back_finish_page), data);
1273
1274        data->filepage = importer_file_page_new (data);
1275
1276        html = create_html ("file_html");
1277        gtk_box_pack_start (GTK_BOX (data->filepage->vbox), html, FALSE, TRUE, 0);
1278        gtk_box_reorder_child (GTK_BOX (data->filepage->vbox), html, 0);
1279
1280        gtk_box_pack_start (GTK_BOX (GNOME_DRUID_PAGE_STANDARD (data->filedialog)->vbox), data->filepage->vbox, TRUE, TRUE, 0);
1281
1282        /* Finish page */
1283        gtk_signal_connect (GTK_OBJECT (data->finish), "finish",
1284                            GTK_SIGNAL_FUNC (import_druid_finish), data);
1285        gtk_signal_connect (GTK_OBJECT (data->dialog), "destroy",
1286                            GTK_SIGNAL_FUNC (import_druid_destroy), data);
1287
1288        gtk_widget_show_all (data->dialog);
1289}
Note: See TracBrowser for help on using the repository browser.