2007-11-14 Matthew Barnes <mbarnes@redhat.com> ** Remove trailing whitespace from source code. svn path=/trunk/; revision=34537
641 lines
15 KiB
C
641 lines
15 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
|
/*
|
|
* Authors: Michael Zucchi <notzed@ximian.com>
|
|
*
|
|
* Copyright 2005 Novell Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_IMPORT_H
|
|
#include <import.h>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <glib.h>
|
|
|
|
#include <gtk/gtknotebook.h>
|
|
#include <gtk/gtkvbox.h>
|
|
#include <gtk/gtkhbox.h>
|
|
#include <gtk/gtktable.h>
|
|
#include <gtk/gtklabel.h>
|
|
#include <gtk/gtkframe.h>
|
|
#include <gtk/gtkalignment.h>
|
|
|
|
#include <libgnomeui/gnome-druid.h>
|
|
#include <libgnomeui/gnome-druid-page-standard.h>
|
|
#include <libgnomeui/gnome-druid-page-edge.h>
|
|
|
|
#include "e-import.h"
|
|
|
|
#include <e-util/e-icon-factory.h>
|
|
|
|
#include <glib/gi18n.h>
|
|
|
|
#define d(x)
|
|
|
|
#define _PRIVATE(o) (g_type_instance_get_private ((GTypeInstance *)o, e_import_get_type()))
|
|
|
|
struct _EImportImporters {
|
|
struct _EImportImporters *next, *prev;
|
|
|
|
EImportImporter *importer;
|
|
EImportImporterFunc free;
|
|
void *data;
|
|
};
|
|
|
|
struct _EImportPrivate {
|
|
int dummy;
|
|
};
|
|
|
|
static GObjectClass *ep_parent;
|
|
|
|
static void
|
|
ep_init(GObject *o)
|
|
{
|
|
/*EImport *emp = (EImport *)o;*/
|
|
}
|
|
|
|
static void
|
|
ep_finalise(GObject *o)
|
|
{
|
|
EImport *emp = (EImport *)o;
|
|
|
|
d(printf("finalising EImport %p\n", o));
|
|
|
|
g_free(emp->id);
|
|
|
|
((GObjectClass *)ep_parent)->finalize(o);
|
|
}
|
|
|
|
static void
|
|
ec_target_free(EImport *ep, EImportTarget *t)
|
|
{
|
|
switch (t->type) {
|
|
case E_IMPORT_TARGET_URI: {
|
|
EImportTargetURI *s = (EImportTargetURI *)t;
|
|
|
|
g_free(s->uri_src);
|
|
g_free(s->uri_dest);
|
|
break; }
|
|
case E_IMPORT_TARGET_HOME: {
|
|
EImportTargetHome *s = (EImportTargetHome *)t;
|
|
|
|
g_free(s->homedir);
|
|
break; }
|
|
}
|
|
|
|
g_datalist_clear(&t->data);
|
|
g_free(t);
|
|
g_object_unref(ep);
|
|
}
|
|
|
|
static void
|
|
ep_class_init(GObjectClass *klass)
|
|
{
|
|
d(printf("EImport class init %p '%s'\n", klass, g_type_name(((GObjectClass *)klass)->g_type_class.g_type)));
|
|
|
|
g_type_class_add_private(klass, sizeof(struct _EImportPrivate));
|
|
|
|
klass->finalize = ep_finalise;
|
|
((EImportClass *)klass)->target_free = ec_target_free;
|
|
}
|
|
|
|
static void
|
|
ep_base_init(GObjectClass *klass)
|
|
{
|
|
e_dlist_init(&((EImportClass *)klass)->importers);
|
|
}
|
|
|
|
/**
|
|
* e_import_get_type:
|
|
*
|
|
* Standard GObject method. Used to subclass for the concrete
|
|
* implementations.
|
|
*
|
|
* Return value: EImport type.
|
|
**/
|
|
GType
|
|
e_import_get_type(void)
|
|
{
|
|
static GType type = 0;
|
|
|
|
if (type == 0) {
|
|
static const GTypeInfo info = {
|
|
sizeof(EImportClass),
|
|
(GBaseInitFunc)ep_base_init, NULL,
|
|
(GClassInitFunc)ep_class_init, NULL, NULL,
|
|
sizeof(EImport), 0,
|
|
(GInstanceInitFunc)ep_init
|
|
};
|
|
ep_parent = g_type_class_ref(G_TYPE_OBJECT);
|
|
type = g_type_register_static(G_TYPE_OBJECT, "EImport", &info, 0);
|
|
}
|
|
|
|
return type;
|
|
}
|
|
|
|
/**
|
|
* e_import_construct:
|
|
* @ep: The instance to initialise.
|
|
* @id: The name of the instance.
|
|
*
|
|
* Used by implementing classes to initialise base parameters.
|
|
*
|
|
* Return value: @ep is returned.
|
|
**/
|
|
EImport *e_import_construct(EImport *ep, const char *id)
|
|
{
|
|
ep->id = g_strdup(id);
|
|
|
|
return ep;
|
|
}
|
|
|
|
EImport *e_import_new(const char *id)
|
|
{
|
|
EImport *ei = g_object_new(e_import_get_type(), NULL);
|
|
|
|
return e_import_construct(ei, id);
|
|
}
|
|
|
|
/**
|
|
* e_import_import:
|
|
* @ei:
|
|
* @t: Target to import.
|
|
* @im: Importer to use.
|
|
* @status: Status callback, called with progress information.
|
|
* @done: Complete callback, will always be called once complete.
|
|
* @data:
|
|
*
|
|
* Run the import function of the selected importer. Once the
|
|
* importer has finished, it MUST call the e_import_complete()
|
|
* function. This allows importers to run in synchronous or
|
|
* asynchronous mode.
|
|
*
|
|
* When complete, the @done callback will be called.
|
|
**/
|
|
void
|
|
e_import_import(EImport *ei, EImportTarget *t, EImportImporter *im, EImportStatusFunc status, EImportCompleteFunc done, void *data)
|
|
{
|
|
g_return_if_fail(im != NULL);
|
|
g_return_if_fail(im != NULL);
|
|
|
|
ei->status = status;
|
|
ei->done = done;
|
|
ei->done_data = data;
|
|
|
|
im->import(ei, t, im);
|
|
}
|
|
|
|
void e_import_cancel(EImport *ei, EImportTarget *t, EImportImporter *im)
|
|
{
|
|
if (im->cancel)
|
|
im->cancel(ei, t, im);
|
|
}
|
|
|
|
/**
|
|
* e_import_get_widget:
|
|
* @ei:
|
|
* @target: Target of interest
|
|
* @im: Importer to get widget of
|
|
*
|
|
* Gets a widget that the importer uses to configure its
|
|
* destination. This widget should be packed into a container
|
|
* widget. It should not be shown_all.
|
|
*
|
|
* Return value: NULL if the importer doesn't support/require
|
|
* a destination.
|
|
**/
|
|
struct _GtkWidget *
|
|
e_import_get_widget(EImport *ei, EImportTarget *target, EImportImporter *im)
|
|
{
|
|
g_return_val_if_fail(im != NULL, NULL);
|
|
g_return_val_if_fail(target != NULL, NULL);
|
|
|
|
return im->get_widget(ei, target, im);
|
|
}
|
|
|
|
/**
|
|
* e_import_complete:
|
|
* @ei:
|
|
* @target: Target just completed (unused currently)
|
|
*
|
|
* Signify that an import is complete. This must be called by
|
|
* importer implementations when they are done.
|
|
**/
|
|
void e_import_complete(EImport *ei, EImportTarget *target)
|
|
{
|
|
if (ei->done)
|
|
ei->done(ei, ei->done_data);
|
|
}
|
|
|
|
void e_import_status(EImport *ei, EImportTarget *target, const char *what, int pc)
|
|
{
|
|
if (ei->status)
|
|
ei->status(ei, what, pc, ei->done_data);
|
|
}
|
|
|
|
/**
|
|
* e_import_get_importers:
|
|
* @emp:
|
|
* @target:
|
|
*
|
|
* Get a list of importers. If @target is supplied, then only
|
|
* importers which support the type and location specified by the
|
|
* target are listed. If @target is NULL, then all importers are
|
|
* listed.
|
|
*
|
|
* Return value: A list of importers. The list should be freed when
|
|
* no longer needed.
|
|
**/
|
|
GSList *
|
|
e_import_get_importers(EImport *emp, EImportTarget *target)
|
|
{
|
|
EImportClass *k = (EImportClass *)G_OBJECT_GET_CLASS(emp);
|
|
struct _EImportImporters *ei;
|
|
GSList *importers = NULL;
|
|
|
|
for (ei = (struct _EImportImporters *)k->importers.head;
|
|
ei->next;
|
|
ei = ei->next) {
|
|
if (target == NULL
|
|
|| (ei->importer->type == target->type
|
|
&& ei->importer->supported(emp, target, ei->importer))) {
|
|
importers = g_slist_append(importers, ei->importer);
|
|
}
|
|
}
|
|
|
|
return importers;
|
|
}
|
|
|
|
/* ********************************************************************** */
|
|
|
|
/**
|
|
* e_import_class_add_importer:
|
|
* @ec: An initialised implementing instance of EImport.
|
|
* @importer: Importer to add.
|
|
* @freefunc: If supplied, called to free the importer node
|
|
* when it is no longer needed.
|
|
* @data: Data for the callback.
|
|
*
|
|
**/
|
|
void
|
|
e_import_class_add_importer(EImportClass *klass, EImportImporter *importer, EImportImporterFunc freefunc, void *data)
|
|
{
|
|
struct _EImportImporters *node, *ei, *en;
|
|
|
|
node = g_malloc(sizeof(*node));
|
|
node->importer = importer;
|
|
node->free = freefunc;
|
|
node->data = data;
|
|
ei = (struct _EImportImporters *)klass->importers.head;
|
|
en = ei->next;
|
|
while (en && ei->importer->pri < importer->pri) {
|
|
ei = en;
|
|
en = en->next;
|
|
}
|
|
|
|
if (en == NULL)
|
|
e_dlist_addtail(&klass->importers, (EDListNode *)node);
|
|
else {
|
|
node->next = ei->next;
|
|
node->next->prev = node;
|
|
node->prev = ei;
|
|
ei->next = node;
|
|
}
|
|
}
|
|
|
|
void e_import_class_remove_importer(EImportClass *klass, EImportImporter *f)
|
|
{
|
|
struct _EImportImporters *ei, *en;
|
|
|
|
ei = (struct _EImportImporters *)klass->importers.head;
|
|
en = ei->next;
|
|
while (en) {
|
|
if (ei->importer == f) {
|
|
e_dlist_remove((EDListNode *)ei);
|
|
if (ei->free)
|
|
ei->free(f, ei->data);
|
|
g_free(ei);
|
|
}
|
|
ei = en;
|
|
en = en->next;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* e_import_target_new:
|
|
* @ep: Parent EImport object.
|
|
* @type: type, up to implementor
|
|
* @size: Size of object to allocate.
|
|
*
|
|
* Allocate a new import target suitable for this class. Implementing
|
|
* classes will define the actual content of the target.
|
|
**/
|
|
void *e_import_target_new(EImport *ep, int type, size_t size)
|
|
{
|
|
EImportTarget *t;
|
|
|
|
if (size < sizeof(EImportTarget)) {
|
|
g_warning ("Size less than size of EImportTarget\n");
|
|
size = sizeof (EImportTarget);
|
|
}
|
|
|
|
t = g_malloc0(size);
|
|
t->import = ep;
|
|
g_object_ref(ep);
|
|
t->type = type;
|
|
g_datalist_init(&t->data);
|
|
|
|
return t;
|
|
}
|
|
|
|
/**
|
|
* e_import_target_free:
|
|
* @ep: Parent EImport object.
|
|
* @o: The target to fre.
|
|
*
|
|
* Free a target. The implementing class can override this method to
|
|
* free custom targets.
|
|
**/
|
|
void
|
|
e_import_target_free(EImport *ep, void *o)
|
|
{
|
|
EImportTarget *t = o;
|
|
|
|
((EImportClass *)G_OBJECT_GET_CLASS(ep))->target_free(ep, t);
|
|
}
|
|
|
|
EImportTargetURI *e_import_target_new_uri(EImport *ei, const char *suri, const char *duri)
|
|
{
|
|
EImportTargetURI *t = e_import_target_new(ei, E_IMPORT_TARGET_URI, sizeof(*t));
|
|
|
|
t->uri_src = g_strdup(suri);
|
|
t->uri_dest = g_strdup(duri);
|
|
|
|
return t;
|
|
}
|
|
|
|
EImportTargetHome *e_import_target_new_home(EImport *ei, const char *home)
|
|
{
|
|
EImportTargetHome *t = e_import_target_new(ei, E_IMPORT_TARGET_HOME, sizeof(*t));
|
|
|
|
t->homedir = g_strdup(home);
|
|
|
|
return t;
|
|
}
|
|
|
|
/* ********************************************************************** */
|
|
|
|
/* Import menu plugin handler */
|
|
|
|
/*
|
|
<e-plugin
|
|
class="org.gnome.mail.plugin.import:1.0"
|
|
id="org.gnome.mail.plugin.import.item:1.0"
|
|
type="shlib"
|
|
location="/opt/gnome2/lib/camel/1.0/libcamelimap.so"
|
|
name="imap"
|
|
description="IMAP4 and IMAP4v1 mail store">
|
|
<hook class="org.gnome.mail.importMenu:1.0"
|
|
handler="HandleImport">
|
|
<menu id="any" target="select">
|
|
<item
|
|
type="item|toggle|radio|image|submenu|bar"
|
|
active
|
|
path="foo/bar"
|
|
label="label"
|
|
icon="foo"
|
|
activate="ep_view_emacs"/>
|
|
</menu>
|
|
</extension>
|
|
|
|
*/
|
|
|
|
static void *emph_parent_class;
|
|
#define emph ((EImportHook *)eph)
|
|
|
|
static const EImportHookTargetMask eih_no_masks[] = {
|
|
{ NULL }
|
|
};
|
|
|
|
static const EImportHookTargetMap eih_targets[] = {
|
|
{ "uri", E_IMPORT_TARGET_URI, eih_no_masks },
|
|
{ "home", E_IMPORT_TARGET_HOME, eih_no_masks },
|
|
{ NULL }
|
|
};
|
|
|
|
static gboolean eih_supported(EImport *ei, EImportTarget *target, EImportImporter *im)
|
|
{
|
|
struct _EImportHookImporter *ihook = (EImportHookImporter *)im;
|
|
EImportHook *hook = im->user_data;
|
|
|
|
return e_plugin_invoke(hook->hook.plugin, ihook->supported, target) != NULL;
|
|
}
|
|
|
|
static struct _GtkWidget *eih_get_widget(EImport *ei, EImportTarget *target, EImportImporter *im)
|
|
{
|
|
struct _EImportHookImporter *ihook = (EImportHookImporter *)im;
|
|
EImportHook *hook = im->user_data;
|
|
|
|
return e_plugin_invoke(hook->hook.plugin, ihook->get_widget, target);
|
|
}
|
|
|
|
static void eih_import(EImport *ei, EImportTarget *target, EImportImporter *im)
|
|
{
|
|
struct _EImportHookImporter *ihook = (EImportHookImporter *)im;
|
|
EImportHook *hook = im->user_data;
|
|
|
|
e_plugin_invoke(hook->hook.plugin, ihook->import, target);
|
|
}
|
|
|
|
static void eih_cancel(EImport *ei, EImportTarget *target, EImportImporter *im)
|
|
{
|
|
struct _EImportHookImporter *ihook = (EImportHookImporter *)im;
|
|
EImportHook *hook = im->user_data;
|
|
|
|
e_plugin_invoke(hook->hook.plugin, ihook->cancel, target);
|
|
}
|
|
|
|
static void
|
|
eih_free_importer(EImportImporter *im, void *data)
|
|
{
|
|
EImportHookImporter *ihook = (EImportHookImporter *)im;
|
|
|
|
g_free(ihook->supported);
|
|
g_free(ihook->get_widget);
|
|
g_free(ihook->import);
|
|
g_free(ihook);
|
|
}
|
|
|
|
static struct _EImportHookImporter *
|
|
emph_construct_importer(EPluginHook *eph, xmlNodePtr root)
|
|
{
|
|
struct _EImportHookImporter *item;
|
|
EImportHookTargetMap *map;
|
|
EImportHookClass *klass = (EImportHookClass *)G_OBJECT_GET_CLASS(eph);
|
|
char *tmp;
|
|
|
|
d(printf(" loading import item\n"));
|
|
item = g_malloc0(sizeof(*item));
|
|
|
|
tmp = (char *)xmlGetProp(root, (const unsigned char *)"target");
|
|
if (tmp == NULL)
|
|
goto error;
|
|
map = g_hash_table_lookup(klass->target_map, tmp);
|
|
xmlFree(tmp);
|
|
if (map == NULL)
|
|
goto error;
|
|
|
|
item->importer.type = map->id;
|
|
item->supported = e_plugin_xml_prop(root, "supported");
|
|
item->get_widget = e_plugin_xml_prop(root, "get-widget");
|
|
item->import = e_plugin_xml_prop(root, "import");
|
|
item->cancel = e_plugin_xml_prop(root, "cancel");
|
|
|
|
item->importer.name = e_plugin_xml_prop(root, "name");
|
|
item->importer.description = e_plugin_xml_prop(root, "description");
|
|
|
|
item->importer.user_data = eph;
|
|
|
|
if (item->import == NULL || item->supported == NULL)
|
|
goto error;
|
|
|
|
item->importer.supported = eih_supported;
|
|
item->importer.import = eih_import;
|
|
if (item->get_widget)
|
|
item->importer.get_widget = eih_get_widget;
|
|
if (item->cancel)
|
|
item->importer.cancel = eih_cancel;
|
|
|
|
return item;
|
|
error:
|
|
d(printf("error!\n"));
|
|
eih_free_importer((EImportImporter *)item, NULL);
|
|
return NULL;
|
|
}
|
|
|
|
static int
|
|
emph_construct(EPluginHook *eph, EPlugin *ep, xmlNodePtr root)
|
|
{
|
|
xmlNodePtr node;
|
|
EImportClass *klass;
|
|
|
|
d(printf("loading import hook\n"));
|
|
|
|
if (((EPluginHookClass *)emph_parent_class)->construct(eph, ep, root) == -1)
|
|
return -1;
|
|
|
|
klass = ((EImportHookClass *)G_OBJECT_GET_CLASS(eph))->import_class;
|
|
|
|
node = root->children;
|
|
while (node) {
|
|
if (strcmp((char *)node->name, "importer") == 0) {
|
|
struct _EImportHookImporter *ihook;
|
|
|
|
ihook = emph_construct_importer(eph, node);
|
|
if (ihook) {
|
|
e_import_class_add_importer(klass, &ihook->importer, eih_free_importer, eph);
|
|
emph->importers = g_slist_append(emph->importers, ihook);
|
|
}
|
|
}
|
|
node = node->next;
|
|
}
|
|
|
|
eph->plugin = ep;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
emph_finalise(GObject *o)
|
|
{
|
|
/*EPluginHook *eph = (EPluginHook *)o;*/
|
|
|
|
/* free importers? */
|
|
|
|
((GObjectClass *)emph_parent_class)->finalize(o);
|
|
}
|
|
|
|
static void
|
|
emph_class_init(EPluginHookClass *klass)
|
|
{
|
|
int i;
|
|
|
|
((GObjectClass *)klass)->finalize = emph_finalise;
|
|
klass->construct = emph_construct;
|
|
|
|
/** @HookClass: Evolution Importers
|
|
* @Id: org.gnome.evolution.import:1.0
|
|
* @Target: EImportTarget
|
|
*
|
|
* A hook for data importers.
|
|
**/
|
|
|
|
klass->id = "org.gnome.evolution.import:1.0";
|
|
|
|
d(printf("EImportHook: init class %p '%s'\n", klass, g_type_name(((GObjectClass *)klass)->g_type_class.g_type)));
|
|
|
|
((EImportHookClass *)klass)->target_map = g_hash_table_new(g_str_hash, g_str_equal);
|
|
((EImportHookClass *)klass)->import_class = g_type_class_ref(e_import_get_type());
|
|
|
|
for (i=0;eih_targets[i].type;i++)
|
|
e_import_hook_class_add_target_map((EImportHookClass *)klass, &eih_targets[i]);
|
|
}
|
|
|
|
/**
|
|
* e_import_hook_get_type:
|
|
*
|
|
* Standard GObject function to get the object type.
|
|
*
|
|
* Return value: The EImportHook class type.
|
|
**/
|
|
GType
|
|
e_import_hook_get_type(void)
|
|
{
|
|
static GType type = 0;
|
|
|
|
if (!type) {
|
|
static const GTypeInfo info = {
|
|
sizeof(EImportHookClass), NULL, NULL, (GClassInitFunc) emph_class_init, NULL, NULL,
|
|
sizeof(EImportHook), 0, (GInstanceInitFunc) NULL,
|
|
};
|
|
|
|
emph_parent_class = g_type_class_ref(e_plugin_hook_get_type());
|
|
type = g_type_register_static(e_plugin_hook_get_type(), "EImportHook", &info, 0);
|
|
}
|
|
|
|
return type;
|
|
}
|
|
|
|
/**
|
|
* e_import_hook_class_add_target_map:
|
|
*
|
|
* @klass: The dervied EimportHook class.
|
|
* @map: A map used to describe a single EImportTarget type for this
|
|
* class.
|
|
*
|
|
* Add a targe tmap to a concrete derived class of EImport. The
|
|
* target map enumates the target types available for the implenting
|
|
* class.
|
|
**/
|
|
void e_import_hook_class_add_target_map(EImportHookClass *klass, const EImportHookTargetMap *map)
|
|
{
|
|
g_hash_table_insert(klass->target_map, (void *)map->type, (void *)map);
|
|
}
|