r22065 - gnucash/trunk - New plugin to import customers and vendors from a csv type file.

Mike Evans mikee at code.gnucash.org
Tue Feb 28 13:38:26 EST 2012


Author: mikee
Date: 2012-02-28 13:38:26 -0500 (Tue, 28 Feb 2012)
New Revision: 22065
Trac: http://svn.gnucash.org/trac/changeset/22065

Added:
   gnucash/trunk/doc/examples/customers_import.csv
   gnucash/trunk/src/plugins/customer_import/
   gnucash/trunk/src/plugins/customer_import/Makefile.am
   gnucash/trunk/src/plugins/customer_import/dialog-customer-import-gui.c
   gnucash/trunk/src/plugins/customer_import/dialog-customer-import-gui.h
   gnucash/trunk/src/plugins/customer_import/dialog-customer-import.c
   gnucash/trunk/src/plugins/customer_import/dialog-customer-import.h
   gnucash/trunk/src/plugins/customer_import/gnc-plugin-customer_import.c
   gnucash/trunk/src/plugins/customer_import/gnc-plugin-customer_import.h
   gnucash/trunk/src/plugins/customer_import/gtkbuilder/
   gnucash/trunk/src/plugins/customer_import/gtkbuilder/Makefile.am
   gnucash/trunk/src/plugins/customer_import/gtkbuilder/dialog-customer-import-gui.glade
   gnucash/trunk/src/plugins/customer_import/libgncmod-customer_import.c
   gnucash/trunk/src/plugins/customer_import/ui/
   gnucash/trunk/src/plugins/customer_import/ui/Makefile.am
   gnucash/trunk/src/plugins/customer_import/ui/gnc-plugin-customer_import-ui.xml
Modified:
   gnucash/trunk/configure.ac
   gnucash/trunk/src/engine/gncIDSearch.c
   gnucash/trunk/src/plugins/Makefile.am
Log:
New plugin to import customers and vendors from a csv type file.
>From a patch by Sebastian Held.
Again the CSV file is of fixed number of fields, similar to invoice/bill importer.
Please test this.
Field list:
id,  company,  name,  addr1,  addr2,  addr3,  addr4,  phone,  fax,  email,  notes,  shipname,  shipaddr1,  shipaddr2,  shipaddr3,  shipaddr4,  shipphone  shipfax,  shipemail
Vendors don't have shipping information so even though the fields have to exist, leave them empty.
The id field is optional, if empty a new id will be chosen. If an id is used this will UPDATE
a vendor/customer with the same id.  This may not be what the user wants.  Maybe this should
be optional/selectable behaviour.
To enable the plugin, add the line:
(gnc:module-load "gnucash/plugins/customer_import" 0)
to ~/.gnucash/config.user

Modified: gnucash/trunk/configure.ac
===================================================================
--- gnucash/trunk/configure.ac	2012-02-24 20:16:21 UTC (rev 22064)
+++ gnucash/trunk/configure.ac	2012-02-28 18:38:26 UTC (rev 22065)
@@ -1337,6 +1337,11 @@
   src/plugins/bi_import/Makefile
   src/plugins/bi_import/gtkbuilder/Makefile
   src/plugins/bi_import/ui/Makefile
+  dnl # Stuff for customer import.
+  src/plugins/customer_import/Makefile
+  src/plugins/customer_import/gtkbuilder/Makefile
+  src/plugins/customer_import/ui/Makefile
+
   dnl # non-makefiles
   dnl # Please read doc/build-system before adding *anything* here
 

Added: gnucash/trunk/doc/examples/customers_import.csv
===================================================================
--- gnucash/trunk/doc/examples/customers_import.csv	                        (rev 0)
+++ gnucash/trunk/doc/examples/customers_import.csv	2012-02-28 18:38:26 UTC (rev 22065)
@@ -0,0 +1,9 @@
+# This is a comment line
+# Good company has no ID and will be allocated one automajically
+,Good Company,Accounts Dept.,1 Rich drive,,,,,,,,,,,,,,,
+# Average company has an ID and will be used literally.  An already existing
+#company with the same ID will be UPDATED.  This may not be what you want!
+000099,Average Company,Accounts Dept,50 Poor Avenue,,,,,,,,,,,,,,,
+
+#Just another example after a blank line
+,"Bad Company",Accounts,99 Destutute street,,,,,,,,,,,,,,, 

Modified: gnucash/trunk/src/engine/gncIDSearch.c
===================================================================
--- gnucash/trunk/src/engine/gncIDSearch.c	2012-02-24 20:16:21 UTC (rev 22064)
+++ gnucash/trunk/src/engine/gncIDSearch.c	2012-02-28 18:38:26 UTC (rev 22065)
@@ -83,7 +83,7 @@
     g_return_val_if_fail (type, NULL);
     g_return_val_if_fail (id, NULL);
     g_return_val_if_fail (book, NULL);
-
+    
     // Build the query
     q = qof_query_create_for (type);
     qof_query_set_book (q, book);
@@ -105,7 +105,8 @@
         GncVendor *c = NULL;
         qof_query_add_term (q, qof_query_build_param_list("VENDOR_ID"), string_pred_data, QOF_QUERY_AND);
     }
-
+    
+    
     // Run the query
     result = qof_query_run (q);
 
@@ -114,15 +115,26 @@
     if (result && (len > 0))
     {
         result = g_list_first (result);
+
         while (result)
         {
             c = result->data;
-            if (strcmp(id, gncCustomerGetID(c)) == 0)
+            if (strcmp(type, GNC_CUSTOMER_MODULE_NAME) && strcmp(id, gncCustomerGetID(c)) == 0)
             {
                 // correct id found
                 object = c;
                 break;
             }
+            else if (strcmp(type, GNC_INVOICE_MODULE_NAME) && strcmp(id, gncInvoiceGetID(c)) == 0)
+            {
+                object = c;
+                break;
+            }
+            else if (strcmp(type, GNC_VENDOR_MODULE_NAME) && strcmp(id, gncVendorGetID(c)) == 0)
+            {
+                object = c;
+                break;
+            }            
             result = g_list_next (result);
         }
     }

Modified: gnucash/trunk/src/plugins/Makefile.am
===================================================================
--- gnucash/trunk/src/plugins/Makefile.am	2012-02-24 20:16:21 UTC (rev 22064)
+++ gnucash/trunk/src/plugins/Makefile.am	2012-02-28 18:38:26 UTC (rev 22065)
@@ -1 +1 @@
-SUBDIRS=bi_import
+SUBDIRS=customer_import bi_import

Added: gnucash/trunk/src/plugins/customer_import/Makefile.am
===================================================================
--- gnucash/trunk/src/plugins/customer_import/Makefile.am	                        (rev 0)
+++ gnucash/trunk/src/plugins/customer_import/Makefile.am	2012-02-28 18:38:26 UTC (rev 22065)
@@ -0,0 +1,54 @@
+SUBDIRS = ui gtkbuilder .
+
+pkglib_LTLIBRARIES = libgncmod-customer_import.la
+
+libgncmod_customer_import_la_SOURCES = \
+  gnc-plugin-customer_import.c \
+  libgncmod-customer_import.c \
+  dialog-customer-import-gui.c \
+  dialog-customer-import.c
+
+noinst_HEADERS = \
+  gnc-plugin-customer_import.h \
+  dialog-customer-import-gui.h \
+  dialog-customer-import.h
+
+libgncmod_customer_import_la_LDFLAGS = -avoid-version
+
+libgncmod_customer_import_la_LIBADD = \
+  ${top_builddir}/src/business/business-gnome/libgncmod-business-gnome.la \
+  ${top_builddir}/src/gnome-utils/libgncmod-gnome-utils.la \
+  ${top_builddir}/src/app-utils/libgncmod-app-utils.la \
+  ${top_builddir}/src/engine/libgncmod-engine.la \
+  ${top_builddir}/src/core-utils/libgnc-core-utils.la \
+  ${top_builddir}/src/gnc-module/libgnc-module.la \
+  ${top_builddir}/src/libqof/qof/libgnc-qof.la \
+  ${top_builddir}/lib/libc/libc-missing.la \
+  ${GCONF_LIBS} \
+  ${QOF_LIBS} \
+  ${GLIB_LIBS}
+
+AM_CFLAGS = \
+  -I${top_srcdir}/src \
+  -I${top_builddir}/src \
+  -I${top_srcdir}/src/gnome \
+  -I${top_srcdir}/src/business/business-gnome/ \
+  -I${top_srcdir}/src/report/report-gnome \
+  -I${top_srcdir}/src/gnome-search/ \
+  -I${top_srcdir}/src/register/ledger-core \
+  -I${top_srcdir}/src/business/business-ledger/ \
+  -I${top_srcdir}/src/register/register-gnome \
+  -I${top_srcdir}/src/register/register-core \
+  -I${top_srcdir}/src/business/dialog-tax-table \
+  -I${top_srcdir}/src/gnome-utils \
+  -I${top_srcdir}/src/app-utils \
+  -I${top_srcdir}/src/engine \
+  -I${top_srcdir}/src/core-utils \
+  -I${top_srcdir}/src/gnc-module \
+  -I${top_srcdir}/lib/libc \
+  ${GCONF_CFLAGS} \
+  ${GTK_CFLAGS} \
+  ${QOF_CFLAGS} \
+  ${GLIB_CFLAGS}
+
+INCLUDES = -DG_LOG_DOMAIN=\"gnc.plugin.customer_import\"

Added: gnucash/trunk/src/plugins/customer_import/dialog-customer-import-gui.c
===================================================================
--- gnucash/trunk/src/plugins/customer_import/dialog-customer-import-gui.c	                        (rev 0)
+++ gnucash/trunk/src/plugins/customer_import/dialog-customer-import-gui.c	2012-02-28 18:38:26 UTC (rev 22065)
@@ -0,0 +1,474 @@
+/*
+ * dialog-customer-import-gui.c --
+ *
+ * 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, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org
+ */
+
+/**
+ * @internal
+ * @file gui.c
+ * @brief GUI handling for customer import plugin
+ * @author Copyright (C) 2009 Sebastian Held <sebastian.held at gmx.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib/gi18n.h>
+
+#include "gnc-ui.h"
+#include "gnc-ui-util.h"
+#include "gnc-component-manager.h"
+#include "dialog-utils.h"
+#include "gnc-gui-query.h"
+#include "gnc-file.h"
+#include "gnc-gnome-utils.h"
+#include "dialog-customer-import.h"
+#include "dialog-customer-import-gui.h"
+
+struct _customer_import_gui
+{
+    GtkWidget    *dialog;
+    GtkWidget    *tree_view;
+    GtkWidget    *entryFilename;
+    GtkListStore *store;
+    gint          component_id;
+    GString      *regexp;
+    gchar       *type;
+    QofBook      *book;
+};
+
+// callback routines
+void gnc_customer_import_gui_ok_cb (GtkWidget *widget, gpointer data);
+void gnc_customer_import_gui_cancel_cb (GtkWidget *widget, gpointer data);
+void gnc_customer_import_gui_help_cb (GtkWidget *widget, gpointer data);
+void gnc_customer_import_gui_destroy_cb (GtkWidget *widget, gpointer data);
+static void gnc_customer_import_gui_close_handler (gpointer user_data);
+void gnc_customer_import_gui_buttonOpen_cb (GtkWidget *widget, gpointer data);
+void gnc_customer_import_gui_filenameChanged_cb (GtkWidget *widget, gpointer data);
+void gnc_customer_import_gui_option1_cb (GtkWidget *widget, gpointer data);
+void gnc_customer_import_gui_option2_cb (GtkWidget *widget, gpointer data);
+void gnc_customer_import_gui_option3_cb (GtkWidget *widget, gpointer data);
+void gnc_customer_import_gui_option4_cb (GtkWidget *widget, gpointer data);
+void gnc_customer_import_gui_option5_cb (GtkWidget *widget, gpointer data);
+void gnc_customer_import_gui_type_cb (GtkWidget *widget, gpointer data);
+
+// utils
+static gchar *gnc_input_dialog (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input);
+static void gnc_info2_dialog (GtkWidget *parent, const gchar *title, const gchar *msg);
+
+
+CustomerImportGui *
+gnc_plugin_customer_import_showGUI(void)
+{
+    CustomerImportGui *gui;
+    //gktbuilderXML *xml;
+    GtkBuilder *builder;
+    GList *glist;
+    GtkTreeIter iter;
+    GtkCellRenderer *renderer;
+    GtkTreeViewColumn *column;
+    
+    // if window exists already, activate it
+    glist = gnc_find_gui_components ("dialog-customer_import_gui", NULL, NULL);
+    if (glist)
+    {
+        // window found
+        gui = g_list_nth_data (glist, 0);
+        g_list_free (glist);
+        gtk_window_present (GTK_WINDOW(gui->dialog));
+        return gui;
+    }
+
+    // create new window
+    gui = g_new0 (CustomerImportGui, 1);
+
+    builder = gtk_builder_new();
+    gnc_builder_add_from_file (builder, "dialog-customer-import-gui.glade", "customer_import Dialog");
+    gui->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "customer_import Dialog"));
+    gui->tree_view = GTK_WIDGET(gtk_builder_get_object (builder, "treeview1"));
+    gui->entryFilename = GTK_WIDGET(gtk_builder_get_object (builder, "entryFilename"));
+    gui->type = "CUSTOMER"; // Set a default type to import
+
+    gui->regexp = g_string_new ( "^(?<id>[^;]+);(?<company>[^;]*);(?<name>[^;]+);(?<addr1>[^;]+);?(?<addr2>[^;]*);?(?<addr3>[^;]*);?(?<addr4>[^;]*);?(?<phone>[^;]*);?(?<fax>[^;]*);?(?<email>[^;]*);?(?<shipname>[^;]*);?(?<shipaddr1>[^;]*);?(?<shipaddr2>[^;]*);?(?<shipaddr3>[^;]*);?(?<shipaddr4>[^;]*);?(?<shipphone>[^;]*);?(?<shipfax>[^;]*);?(?<shipemail>[^;]*)");
+    gui->book = gnc_get_current_book();
+
+    // create model and bind to view
+    gui->store = gtk_list_store_new (CI_N_COLUMNS,
+                                     G_TYPE_STRING, G_TYPE_STRING,
+                                     G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+                                     G_TYPE_STRING,
+                                     G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+    gtk_tree_view_set_model( GTK_TREE_VIEW(gui->tree_view), GTK_TREE_MODEL(gui->store) );
+#define CREATE_COLUMN(description,column_id) \
+  renderer = gtk_cell_renderer_text_new (); \
+  column = gtk_tree_view_column_new_with_attributes (description, renderer, "text", column_id, NULL); \
+  gtk_tree_view_column_set_resizable (column, TRUE); \
+  gtk_tree_view_append_column (GTK_TREE_VIEW (gui->tree_view), column);
+    CREATE_COLUMN ("id", CI_ID);
+    CREATE_COLUMN ("company", CI_COMPANY);
+    CREATE_COLUMN ("name", CI_NAME);
+    CREATE_COLUMN ("addr1", CI_ADDR1);
+    CREATE_COLUMN ("addr2", CI_ADDR2);
+    CREATE_COLUMN ("addr3", CI_ADDR3);
+    CREATE_COLUMN ("addr4", CI_ADDR4);
+    CREATE_COLUMN ("phone", CI_PHONE);
+    CREATE_COLUMN ("fax", CI_FAX);
+    CREATE_COLUMN ("email", CI_EMAIL);
+    CREATE_COLUMN ("notes", CI_NOTES);
+    CREATE_COLUMN ("shipname", CI_SHIPNAME);
+    CREATE_COLUMN ("shipaddr1", CI_SHIPADDR1);
+    CREATE_COLUMN ("shipaddr2", CI_SHIPADDR2);
+    CREATE_COLUMN ("shipaddr3", CI_SHIPADDR3);
+    CREATE_COLUMN ("shipaddr4", CI_SHIPADDR4);
+    CREATE_COLUMN ("shipphone", CI_SHIPPHONE);
+    CREATE_COLUMN ("shipfax", CI_SHIPFAX);
+    CREATE_COLUMN ("shipemail", CI_SHIPEMAIL);
+
+    gui->component_id = gnc_register_gui_component ("dialog-customer_import_gui",
+                        NULL,
+                        gnc_customer_import_gui_close_handler,
+                        gui);
+
+    /* Setup signals */
+    gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, gui);
+    gtk_widget_show_all ( gui->dialog );
+    return gui;
+}
+
+static gchar *
+gnc_plugin_customer_import_getFilename(void)
+{
+    // prepare file import dialog
+    gchar *filename;
+    GList *filters;
+    GtkFileFilter *filter;
+    filters = NULL;
+    filter = gtk_file_filter_new ();
+    gtk_file_filter_set_name (filter, "comma separated values (*.csv)");
+    gtk_file_filter_add_pattern (filter, "*.csv");
+    filters = g_list_append( filters, filter );
+    filter = gtk_file_filter_new ();
+    gtk_file_filter_set_name (filter, "text files (*.txt)");
+    gtk_file_filter_add_pattern (filter, "*.txt");
+    filters = g_list_append( filters, filter );
+    filename = gnc_file_dialog(_("Import Customers from csv"), filters, NULL, GNC_FILE_DIALOG_IMPORT);
+
+    return filename;
+} 
+
+void
+gnc_customer_import_gui_ok_cb (GtkWidget *widget, gpointer data)
+{
+    CustomerImportGui *gui = data;
+    gchar *filename = g_strdup( gtk_entry_get_text( GTK_ENTRY(gui->entryFilename) ) );
+    customer_import_stats stats;
+    customer_import_result res;
+    guint n_fixed, n_deleted, n_customers_created, n_customers_updated;
+    gchar *cv_type_text;
+    
+    // import
+    if (g_ascii_strcasecmp (gui->type, "CUSTOMER") == 0) cv_type_text = _("customers");
+    else cv_type_text = _("vendors");
+    
+    gtk_list_store_clear (gui->store);
+    res = gnc_customer_import_read_file (filename, gui->regexp->str, gui->store, 0, &stats);
+    if (res == CI_RESULT_OK)
+    {
+        gnc_customer_import_fix_customers (gui->store, &n_fixed, &n_deleted, gui->type);
+        gnc_customer_import_create_customers (gui->store, gui->book, &n_customers_created, &n_customers_updated, gui->type);
+        gnc_info_dialog (gui->dialog, _("Import results:\n%i lines were ignored\n%i lines imported:\n   %u %s fixed\n   %u %s ignored (not fixable)\n\n   %u %s created\n   %u %s updated (based on id)"), \
+                                            stats.n_ignored, stats.n_imported, n_fixed, cv_type_text, n_deleted, cv_type_text, n_customers_created, cv_type_text, n_customers_updated,cv_type_text);
+
+        if (stats.n_ignored > 0)
+            gnc_info2_dialog (gui->dialog, _("These lines were ignored during import"), stats.ignored_lines->str);
+
+        g_string_free (stats.ignored_lines, TRUE);
+        gnc_close_gui_component (gui->component_id); 
+    }
+    else if (res == CI_RESULT_OPEN_FAILED)
+    {
+        gnc_error_dialog (gui->dialog, _("The input file can not be opened."));
+    }
+    else if (res == CI_RESULT_ERROR_IN_REGEXP)
+    {
+        //gnc_error_dialog (gui->dialog, "The regular expression is faulty:\n\n%s", stats.err->str);
+    }
+}
+
+void
+gnc_customer_import_gui_cancel_cb (GtkWidget *widget, gpointer data)
+{
+    CustomerImportGui *gui = data;
+
+    gnc_close_gui_component (gui->component_id);
+}
+
+void
+gnc_customer_import_gui_help_cb (GtkWidget *widget, gpointer data)
+{
+    gnc_gnome_help(HF_HELP, HL_USAGE);
+}
+
+static void
+gnc_customer_import_gui_close_handler (gpointer user_data)
+{
+    CustomerImportGui *gui = user_data;
+
+    gtk_widget_destroy (gui->dialog);
+    // gui has already been freed by this point.
+    // gui->dialog = NULL;
+}
+
+void
+gnc_customer_import_gui_destroy_cb (GtkWidget *widget, gpointer data)
+{
+    CustomerImportGui *gui = data;
+
+    gnc_suspend_gui_refresh ();
+    gnc_unregister_gui_component (gui->component_id);
+    gnc_resume_gui_refresh ();
+
+    g_object_unref (gui->store);
+    g_string_free (gui->regexp, TRUE);
+    g_free (gui);
+}
+
+void gnc_customer_import_gui_buttonOpen_cb (GtkWidget *widget, gpointer data)
+{
+    gchar *filename;
+    CustomerImportGui *gui = data;
+
+    filename = gnc_plugin_customer_import_getFilename();
+    if (filename)
+    {
+        gtk_entry_set_text( GTK_ENTRY(gui->entryFilename), filename );
+        g_free( filename );
+    }
+}
+
+void gnc_customer_import_gui_filenameChanged_cb (GtkWidget *widget, gpointer data)
+{
+    CustomerImportGui *gui = data;
+    gchar *filename = g_strdup( gtk_entry_get_text( GTK_ENTRY(gui->entryFilename) ) );
+
+    // generate preview
+    gtk_list_store_clear (gui->store);
+    gnc_customer_import_read_file (filename, gui->regexp->str, gui->store, 10, NULL);
+
+    g_free( filename ); 
+}
+// Semicolon separated.
+void gnc_customer_import_gui_option1_cb (GtkWidget *widget, gpointer data)
+{
+    CustomerImportGui *gui = data;
+    if (!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ))
+        return;
+    g_string_assign (gui->regexp, "^(?<id>[^;]*);(?<company>[^;]*);(?<name>[^;]*);(?<addr1>[^;]*);?(?<addr2>[^;]*);?(?<addr3>[^;]*);?(?<addr4>[^;]*);?(?<phone>[^;]*);?(?<fax>[^;]*);?(?<email>[^;]*);?(?<notes>[^;]*);?(?<shipname>[^;]*);?(?<shipaddr1>[^;]*);?(?<shipaddr2>[^;]*);?(?<shipaddr3>[^;]*);?(?<shipadddr4>[^;]*);?(?<shipphone>[^;]*);(?<shipfax>[^;]*);(?<shipemail>[^;]*)"); //;(?<account_posted>[^;]*);(?<memo_posted>[^;]*);(?<accu_splits>[^;]*)$");
+    gnc_customer_import_gui_filenameChanged_cb (gui->entryFilename, gui);
+}
+// Comma separated.
+void gnc_customer_import_gui_option2_cb (GtkWidget *widget, gpointer data)
+{
+    CustomerImportGui *gui = data;
+    if (!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ))
+        return;
+    g_string_assign (gui->regexp, "^(?<id>[^,]*),(?<company>[^,]*),(?<name>[^,]*),(?<addr1>[^,]*),?(?<addr2>[^,]*),?(?<addr3>[^,]*),?(?<addr4>[^,]*),?(?<phone>[^,]*),?(?<fax>[^,]*),?(?<email>[^,]*),?(?<notes>[^,]*),?(?<shipname>[^,]*),?(?<shipaddr1>[^,]*),?(?<shipaddr2>[^,]*),?(?<shipaddr3>[^,]*),?(?<shipadddr4>[^,]*),?(?<shipphone>[^,]*),(?<shipfax>[^,]*),(?<shipemail>[^,]*)"); //,(?<account_posted>[^,]*),(?<memo_posted>[^,]*),(?<accu_splits>[^,]*)$");
+    gnc_customer_import_gui_filenameChanged_cb (gui->entryFilename, gui);
+}
+// Semicolon separated with quoted strings.
+void gnc_customer_import_gui_option3_cb (GtkWidget *widget, gpointer data)
+{
+    CustomerImportGui *gui = data;
+    if (!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ))
+        return;
+    //g_string_assign (gui->regexp, "^((?<id>[^\";]*)|\"(?<id>[^\"]*)\");((?<company>[^\";]*)|\"(?<company>[^\"]*)\");((?<name>[^\";]*)|\"(?<name>[^\"]*)\");((?<addr1>[^\";]*)|\"(?<addr1>[^\"]*)\");((?<addr2>[^\";]*)|\"(?<addr2>[^\"]*)\");((?<addr3>[^\";]*)|\"(?<addr3>[^\"]*)\");((?<addr4>[^\";]*)|\"(?<addr4>[^\"]*)\");((?<phone>[^\";]*)|\"(?<phone>[^\"]*)\");((?<fax>[^\";]*)|\"(?<fax>[^\"]*)\");((?<email>[^\";]*)|\"(?<email>[^\"]*)\");((?<notes>[^\";]*)|\"(?<notes>[^\"]*)\");((?<shipname>[^\";]*)|\"(?<shipname>[^\"]*)\");((?<shipaddr1>[^\";]*)|\"(?<shipaddr1>[^\"]*)\");((?<shipaddr2>[^\";]*)|\"(?<shipaddr2>[^\"]*)\");((?<shipaddr3>[^\";]*)|\"(?<shipaddr3>[^\"]*)\");((?<shipaddr4>[^\";]*)|\"(?<shipaddr4>[^\"]*)\");((?<shipphone>[^\";]*)|\"(?<shipphone>[^\"]*)\");((?<shipfax>[^\";]*)|\"(?<shipfax>[^\"]*)\");((?<shipmail>[^\";]*)|\"(?<shipemail>[^\"]*)\")$");
+    g_string_assign (gui->regexp, "^((?<id>[^\";]*)|\"(?<id>[^\"]*)\");((?<company>[^\";]*)|\"(?<company>[^\"]*)\");((?<name>[^\";]*)|\"(?<name>[^\"]*)\");((?<addr1>[^\";]*)|\"(?<addr1>[^\"]*)\");((?<addr2>[^\";]*)|\"(?<addr2>[^\"]*)\");((?<addr3>[^\";]*)|\"(?<addr3>[^\"]*)\");((?<addr4>[^\";]*)|\"(?<addr4>[^\"]*)\");((?<phone>[^\";]*)|\"(?<phone>[^\"]*)\");((?<fax>[^\";]*)|\"(?<fax>[^\"]*)\");((?<email>[^\";]*)|\"(?<email>[^\"]*)\");((?<notes>[^\";]*)|\"(?<notes>[^\"]*)\");((?<shipname>[^\";]*)|\"(?<shipname>[^\"]*)\");((?<shipaddr1>[^\";]*)|\"(?<shipaddr1>[^\"]*)\");((?<shipaddr2>[^\";]*)|\"(?<shipaddr2>[^\"]*)\");((?<shipaddr3>[^\";]*)|\"(?<shipaddr3>[^\"]*)\");((?<shipaddr4>[^\";]*)|\"(?<shipaddr4>[^\"]*)\");((?<shipphone>[^\";]*)|\"(?<shipphone>[^\"]*)\");((?<shipfax>[^\";]*)|\"(?<shipfax>[^\"]*)\");((?<shipmail>[^\";]*)|\"(?<shipemail>[^\"]*)\")$");
+    gnc_customer_import_gui_filenameChanged_cb (gui->entryFilename, gui);
+}
+// Comma separated with quoted strings.
+void gnc_customer_import_gui_option4_cb (GtkWidget *widget, gpointer data)
+{
+    CustomerImportGui *gui = data;
+    if (!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ))
+        return;
+    //g_string_assign (gui->regexp, "^(?<id>[^,]*),(?<company>[^,]*),(?<name>[^,]*),(?<addr1>[^,]*),?(?<addr2>[^,]*),?(?<addr3>[^,]*),?(?<addr4>[^,]*),?(?<phone>[^,]*),?(?<fax>[^,]*),?(?<email>[^,]*),?(?<notes>[^,]*),?(?<shipname>[^,]*),?(?<shipaddr1>[^,]*),?(?<shipaddr2>[^,]*),?(?<shipaddr3>[^,]*),?(?<shipadddr4>[^,]*),?(?<shipphone>[^,]*),(?<shipfax>[^,]*),(?<shipemail>[^,]*)"); //,(?<account_posted>[^,]*),(?<memo_posted>[^,]*),(?<accu_splits>[^,]*)$");
+    g_string_assign (gui->regexp, "^((?<id>[^\",]*)|\"(?<id>[^\"]*)\"),((?<company>[^\",]*)|\"(?<company>[^\"]*)\"),((?<name>[^\",]*)|\"(?<name>[^\"]*)\"),((?<addr1>[^\",]*)|\"(?<addr1>[^\"]*)\"),((?<addr2>[^\",]*)|\"(?<addr2>[^\"]*)\"),((?<addr3>[^\",]*)|\"(?<addr3>[^\"]*)\"),((?<addr4>[^\",]*)|\"(?<addr4>[^\"]*)\"),((?<phone>[^\",]*)|\"(?<phone>[^\"]*)\"),((?<fax>[^\",]*)|\"(?<fax>[^\"]*)\"),((?<email>[^\",]*)|\"(?<email>[^\"]*)\"),((?<notes>[^\",]*)|\"(?<notes>[^\"]*)\"),((?<shipname>[^\",]*)|\"(?<shipname>[^\"]*)\"),((?<shipaddr1>[^\",]*)|\"(?<shipaddr1>[^\"]*)\"),((?<shipaddr2>[^\",]*)|\"(?<shipaddr2>[^\"]*)\"),((?<shipaddr3>[^\",]*)|\"(?<shipaddr3>[^\"]*)\"),((?<shipaddr4>[^\",]*)|\"(?<shipaddr4>[^\"]*)\"),((?<shipphone>[^\",]*)|\"(?<shipphone>[^\"]*)\"),((?<shipfax>[^\",]*)|\"(?<shipfax>[^\"]*)\"),((?<shipmail>[^\",]*)|\"(?<shipemail>[^\"]*)\")$");
+    gnc_customer_import_gui_filenameChanged_cb (gui->entryFilename, gui);
+}
+void gnc_customer_import_gui_option5_cb (GtkWidget *widget, gpointer data)
+{
+    CustomerImportGui *gui = data;
+    gchar *temp;
+    if (!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ))
+        return;
+    temp = gnc_input_dialog (0, _("Adjust regular expression used for import"), _("This regular expression is used to parse the import file. Modify according to your needs.\n"), gui->regexp->str);
+    if (temp)
+    {
+        g_string_assign (gui->regexp, temp);
+        g_free (temp);
+        gnc_customer_import_gui_filenameChanged_cb (gui->entryFilename, gui);
+    }
+}
+
+
+
+
+/*****************************************************************
+ * Set whether we are importing a Customer or Vendor
+ * ****************************************************************/
+void gnc_customer_import_gui_type_cb (GtkWidget *widget, gpointer data)
+{
+    CustomerImportGui *gui = data;
+    const gchar *name;
+    if (!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ))
+        return;
+    name = gtk_buildable_get_name(GTK_BUILDABLE(widget));
+    if(name)
+    {
+    if  (g_ascii_strcasecmp(name, "radiobutton_customer") == 0)gui->type = "CUSTOMER";
+    else if (g_ascii_strcasecmp(name, "radiobutton_vendor") == 0)gui->type = "VENDOR";
+    }
+    //printf ("TYPE set to, %s\n",gui->type); // DEBUG
+
+}
+
+
+
+/********************************************************************\
+ * gnc_input_dialog                                                 *
+ *   simple convenience dialog to get a single value from the user  *
+ *   user may choose between "Ok" and "Cancel"                      *
+ *                                                                  *
+ * NOTE: This function does not return until the dialog is closed   *
+ *                                                                  *
+ * Args:   parent  - the parent window or NULL                      *
+ *         title   - the title of the dialog                        *
+ *         msg     - the message to display                         *
+ *         default_input - will be displayed as default input       *
+ * Return: the input (text) the user entered, if pressed "Ok"       *
+ *         NULL, if pressed "Cancel"                                *
+\********************************************************************/
+static gchar *
+gnc_input_dialog (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input)
+{
+    GtkWidget *dialog, *label, *content_area;
+    gint result;
+    GtkWidget *view;
+    GtkTextBuffer *buffer;
+    gchar *user_input;
+    GtkTextIter start, end;
+
+    /* Create the widgets */
+    dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (parent),
+                                          GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                          GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+                                          GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+                                          NULL);
+#ifdef HAVE_GTK_2_14
+    content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+#else
+    content_area = GTK_DIALOG (dialog)->vbox;
+#endif
+
+    // add a label
+    label = gtk_label_new (msg);
+    gtk_container_add (GTK_CONTAINER (content_area), label);
+
+    // add a textview
+    view = gtk_text_view_new ();
+    gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD_CHAR);
+    buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+    gtk_text_buffer_set_text (buffer, default_input, -1);
+    gtk_container_add (GTK_CONTAINER (content_area), view);
+
+    // run the dialog
+    gtk_widget_show_all (dialog);
+    result = gtk_dialog_run (GTK_DIALOG (dialog));
+
+    if (result == GTK_RESPONSE_REJECT)
+        user_input = 0;
+    else
+    {
+        gtk_text_buffer_get_start_iter (buffer, &start);
+        gtk_text_buffer_get_end_iter (buffer, &end);
+        user_input = gtk_text_buffer_get_text (buffer,
+                                               &start, &end, FALSE);
+    }
+
+    gtk_widget_destroy (dialog);
+
+    return user_input;
+}
+
+/********************************************************************\
+ * gnc_info2_dialog                                                 *
+ *   displays an information dialog box (with scrollable text area) *
+ *                                                                  *
+ * NOTE: This function does not return until the dialog is closed   *
+ *                                                                  *
+ * Args:   parent  - the parent window or NULL                      *
+ *         title   - the title of the dialog                        *
+ *         msg     - the message to display                         *
+ * Return: none                                                     *
+\********************************************************************/
+static void
+gnc_info2_dialog (GtkWidget *parent, const gchar *title, const gchar *msg)
+{
+    GtkWidget *dialog, *scrolledwindow, *content_area;
+    gint result;
+    GtkWidget *view;
+    GtkTextBuffer *buffer;
+    gchar *user_input;
+    GtkTextIter start, end;
+    gint width, height;
+
+    /* Create the widgets */
+    dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (parent),
+                                          GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                          GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+                                          NULL);
+#ifdef HAVE_GTK_2_14
+    content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+#else
+    content_area = GTK_DIALOG (dialog)->vbox;
+#endif
+
+    // add a scroll area
+    scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
+    gtk_container_add (GTK_CONTAINER (content_area), scrolledwindow);
+
+    // add a textview
+    view = gtk_text_view_new ();
+//    gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD_CHAR);
+    gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
+    buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+    gtk_text_buffer_set_text (buffer, msg, -1);
+    gtk_container_add (GTK_CONTAINER (scrolledwindow), view);
+
+    // run the dialog
+    if (parent)
+    {
+        gtk_window_get_size (GTK_WINDOW(parent), &width, &height);
+        gtk_window_set_default_size (GTK_WINDOW(dialog), width, height);
+    }
+    gtk_widget_show_all (dialog);
+    gtk_dialog_run (GTK_DIALOG (dialog));
+    gtk_widget_destroy (dialog);
+}

Added: gnucash/trunk/src/plugins/customer_import/dialog-customer-import-gui.h
===================================================================
--- gnucash/trunk/src/plugins/customer_import/dialog-customer-import-gui.h	                        (rev 0)
+++ gnucash/trunk/src/plugins/customer_import/dialog-customer-import-gui.h	2012-02-28 18:38:26 UTC (rev 22065)
@@ -0,0 +1,48 @@
+/*
+ * gui.h --
+ *
+ * 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, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org
+ */
+
+/**
+ * @addtogroup Tools
+ * @{
+ * @file gui.h
+ * @brief GUI handling for customer import plugin
+ * @author Copyright (C) 2009 Sebastian Held <sebastian.held at gmx.de>
+ */
+
+#ifndef GNC_PLUGIN_customer_import_gui_H
+#define GNC_PLUGIN_customer_import_gui_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _customer_import_gui CustomerImportGui;
+
+/**
+ * File chooser
+ */
+CustomerImportGui *gnc_plugin_customer_import_showGUI(void);
+
+G_END_DECLS
+
+#endif /* GNC_PLUGIN_customer_import_gui_H */
+
+/** @} */

Added: gnucash/trunk/src/plugins/customer_import/dialog-customer-import.c
===================================================================
--- gnucash/trunk/src/plugins/customer_import/dialog-customer-import.c	                        (rev 0)
+++ gnucash/trunk/src/plugins/customer_import/dialog-customer-import.c	2012-02-28 18:38:26 UTC (rev 22065)
@@ -0,0 +1,432 @@
+/*
+ * customer_import.c --
+ *
+ * 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, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org
+ */
+
+/**
+ * @internal
+ * @brief core import functions for customer import plugin
+ * @author Copyright (C) 2009 Sebastian Held <sebastian.held at gmx.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib/gi18n.h>
+#include <regex.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include "gnc-ui.h"
+#include "gnc-ui-util.h"
+#include "gnc-gui-query.h"
+#include "gncAddress.h"
+#include "gncCustomerP.h"
+#include "gncVendorP.h"
+// query
+#include "Query.h"
+#include "qof.h"
+#include "GNCId.h"
+#include "gncIDSearch.h"
+
+#include "dialog-customer-import.h"
+
+// private prototypes
+//static GncCustomer *gnc_customer_import_searchCustomer (const gchar *id, QofBook *book);
+
+
+
+// perl regular expressions are available
+
+// this helper macro takes a regexp match and fills the model
+#define FILL_IN_HELPER(match_name,column) \
+            temp = g_match_info_fetch_named (match_info, match_name); \
+            if (temp) \
+            { \
+				g_strstrip( temp ); \
+                gtk_list_store_set (store, &iter, column, temp, -1); \
+                g_free (temp); \
+            }
+customer_import_result
+gnc_customer_import_read_file (const gchar *filename, const gchar *parser_regexp, GtkListStore *store, guint max_rows, customer_import_stats *stats)
+{
+    // some statistics
+    customer_import_stats stats_fallback;
+    FILE *f;
+
+    // regexp
+    char *line;
+    gchar *line_utf8, *temp;
+    GMatchInfo *match_info;
+    GError *err;
+    GRegex *regexpat;
+
+    // model
+    GtkTreeIter iter;
+
+    f = g_fopen( filename, "rt" );
+    if (!f)
+    {
+        //gnc_error_dialog( 0, _("File %s cannot be opened."), filename );
+        return CI_RESULT_OPEN_FAILED;
+    }
+
+    // set up statistics
+    if (!stats)
+        stats = &stats_fallback;
+
+    // compile the regular expression and check for errors
+    err = NULL;
+    regexpat = g_regex_new (parser_regexp, G_REGEX_EXTENDED | G_REGEX_OPTIMIZE | G_REGEX_DUPNAMES, 0, &err);
+    if (err != NULL)
+    {
+        GtkWidget *dialog;
+        gchar *errmsg;
+
+        errmsg = g_strdup_printf (_("Error in regular expression '%s':\n%s"),
+                                  parser_regexp, err->message);
+        g_error_free (err);
+        err = NULL;
+
+        dialog = gtk_message_dialog_new (NULL,
+                                         GTK_DIALOG_MODAL,
+                                         GTK_MESSAGE_ERROR,
+                                         GTK_BUTTONS_OK,
+                                         "%s", errmsg);
+        gtk_dialog_run (GTK_DIALOG (dialog));
+        gtk_widget_destroy(dialog);
+        g_free (errmsg);
+        errmsg = 0;
+
+        fclose (f);
+        return CI_RESULT_ERROR_IN_REGEXP;
+    }
+
+    // start the import
+    stats->n_imported = 0;
+    stats->n_ignored = 0;
+    stats->ignored_lines = g_string_new (NULL);
+#define buffer_size 1000
+    line = g_malloc0 (buffer_size);
+    while (!feof (f) && ((max_rows == 0) || (stats->n_imported + stats->n_ignored < max_rows)))
+    {
+        int l;
+        // read one line
+        if (!fgets (line, buffer_size, f))
+            break; // eof
+        // now strip the '\n' from the end of the line
+        l = strlen (line);
+        if ((l > 0) && (line[l - 1] == '\n'))
+            line[l - 1] = 0;
+
+        // convert line from locale into utf8
+        line_utf8 = g_locale_to_utf8 (line, -1, NULL, NULL, NULL);
+
+        // parse the line
+        match_info = NULL; // it seems, that in contrast to documentation, match_info is not alsways set -> g_match_info_free will segfault
+        if (g_regex_match (regexpat, line_utf8, 0, &match_info))
+        {
+            // match found
+            stats->n_imported++;
+
+            // fill in the values
+            gtk_list_store_append (store, &iter);
+            FILL_IN_HELPER ("id", CI_ID);
+            FILL_IN_HELPER ("company", CI_COMPANY);
+            FILL_IN_HELPER ("name", CI_NAME);
+            FILL_IN_HELPER ("addr1", CI_ADDR1);
+            FILL_IN_HELPER ("addr2", CI_ADDR2);
+            FILL_IN_HELPER ("addr3", CI_ADDR3);
+            FILL_IN_HELPER ("addr4", CI_ADDR4);
+            FILL_IN_HELPER ("phone", CI_PHONE);
+            FILL_IN_HELPER ("fax", CI_FAX);
+            FILL_IN_HELPER ("email", CI_EMAIL);
+            FILL_IN_HELPER ("shipname", CI_SHIPNAME);
+            FILL_IN_HELPER ("shipaddr1", CI_SHIPADDR1);
+            FILL_IN_HELPER ("shipaddr2", CI_SHIPADDR2);
+            FILL_IN_HELPER ("shipaddr3", CI_SHIPADDR3);
+            FILL_IN_HELPER ("shipaddr4", CI_SHIPADDR4);
+            FILL_IN_HELPER ("shipphone", CI_SHIPPHONE);
+            FILL_IN_HELPER ("shipfax", CI_SHIPFAX);
+            FILL_IN_HELPER ("shipemail", CI_SHIPEMAIL);
+        }
+        else
+        {
+            // ignore line
+            stats->n_ignored++;
+            g_string_append (stats->ignored_lines, line_utf8);
+            g_string_append_c (stats->ignored_lines, '\n');
+        }
+
+        g_match_info_free (match_info);
+        match_info = 0;
+        g_free (line_utf8);
+        line_utf8 = 0;
+    }
+    g_free (line);
+    line = 0;
+
+    g_regex_unref (regexpat);
+    regexpat = 0;
+    fclose (f);
+
+    //gnc_info_dialog (0, _("Import results:\n%i customers imported\n%i lines ignored"), n_imported, n_ignored);
+
+    if (stats == &stats_fallback)
+        // stats are not requested -> free the string
+        g_string_free (stats->ignored_lines, TRUE);
+
+    return CI_RESULT_OK;
+}
+
+
+
+
+
+
+void
+gnc_customer_import_fix_customers (GtkListStore *store, guint *fixed, guint *deleted, gchar * type)
+{
+    GtkTreeIter iter;
+    gboolean valid;
+    gchar *company, *name, *addr1, *addr2, *addr3, *addr4;
+    guint dummy;
+
+    // allow the call to this function with only GtkListeStore* specified
+    if (!fixed)
+        fixed = &dummy;
+    if (!deleted)
+        deleted = &dummy;
+
+    *fixed = 0;
+    *deleted = 0;
+
+    valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter);
+    while (valid)
+    {
+        // Walk through the list, reading each row
+        gtk_tree_model_get (GTK_TREE_MODEL(store), &iter,
+                            CI_COMPANY, &company,
+                            CI_NAME, &name,
+                            CI_ADDR1, &addr1,
+                            CI_ADDR2, &addr2,
+                            CI_ADDR3, &addr3,
+                            CI_ADDR4, &addr4,
+                            -1);
+
+        if (strlen(company) == 0)
+        {
+            if (strlen(name) == 0)
+            {
+                // no fix possible -> delete row
+                gtk_list_store_remove (store, &iter);
+                (*deleted)++;
+                g_free (company);
+                g_free (name);
+                g_free (addr1);
+                g_free (addr2);
+                g_free (addr3);
+                g_free (addr4);
+                continue;
+            }
+            else
+            {
+                // fix possible -> copy name to company
+                gtk_list_store_set (store, &iter, CI_COMPANY, name, -1);
+                (*fixed)++;
+            }
+        }
+        if ((strlen(addr1) == 0) && (strlen(addr2) == 0) &&
+                (strlen(addr3) == 0) && (strlen(addr4) == 0))
+        {
+            // no address given, no fix possible -> delete row
+            gtk_list_store_remove (store, &iter);
+            (*deleted)++;
+            if (strlen(company) == 0)
+                // the company cell was fixed -> decrement "fixed" counter
+                (*fixed)--;
+            g_free (company);
+            g_free (name);
+            g_free (addr1);
+            g_free (addr2);
+            g_free (addr3);
+            g_free (addr4);
+            continue;
+        }
+
+        g_free (company);
+        g_free (name);
+        g_free (addr1);
+        g_free (addr2);
+        g_free (addr3);
+        g_free (addr4);
+        valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
+    }
+}
+
+void
+gnc_customer_import_create_customers (GtkListStore *store, QofBook *book, guint *n_customers_created, guint *n_customers_updated, gchar * type)
+{
+    gboolean valid;
+    GtkTreeIter iter;
+    gchar *id, *company, *name, *addr1, *addr2, *addr3, *addr4, *phone, *fax, *email;
+    gchar *notes, *shipname, *shipaddr1, *shipaddr2, *shipaddr3, *shipaddr4, *shipphone, *shipfax, *shipemail;
+    GncAddress *addr, *shipaddr;
+    guint dummy;
+    GncCustomer *customer;
+    GncVendor *vendor;
+    customer = NULL;
+    vendor = NULL;
+    // these arguments are needed
+    g_return_if_fail (store && book);
+    printf("\nTYPE = %s\n", type);
+
+    // allow to call this function without statistics
+    if (!n_customers_created)
+        n_customers_created = &dummy;
+    if (!n_customers_updated)
+        n_customers_updated = &dummy;
+    *n_customers_created = 0;
+    *n_customers_updated = 0;
+
+    valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter);
+    while (valid)
+    {
+        // Walk through the list, reading each row
+        gtk_tree_model_get (GTK_TREE_MODEL(store), &iter,
+                            CI_ID, &id,
+                            CI_COMPANY, &company,
+                            CI_NAME, &name,
+                            CI_ADDR1, &addr1,
+                            CI_ADDR2, &addr2,
+                            CI_ADDR3, &addr3,
+                            CI_ADDR4, &addr4,
+                            CI_PHONE, &phone,
+                            CI_FAX, &fax,
+                            CI_EMAIL, &email,
+                            CI_NOTES, &notes,
+                            CI_SHIPNAME, &shipname,
+                            CI_SHIPADDR1, &shipaddr1,
+                            CI_SHIPADDR2, &shipaddr2,
+                            CI_SHIPADDR3, &shipaddr3,
+                            CI_SHIPADDR4, &shipaddr4,
+                            CI_SHIPPHONE, &shipphone,
+                            CI_SHIPFAX, &shipfax,
+                            CI_SHIPEMAIL, &shipemail,
+                            -1);
+
+        // Set the customer id if one has not been chosen
+        if (strlen (id) == 0)
+        {
+            g_free (id);
+            if (g_ascii_strcasecmp (type, "CUSTOMER") == 0) id = gncCustomerNextID (book);
+            else if (g_ascii_strcasecmp (type, "VENDOR") == 0)id = gncVendorNextID (book);
+            //printf("ASSIGNED ID = %s\n",id);
+        }
+
+        // Now save it off after checking if a vend/cust number doesn't already exist
+        {
+            if (g_ascii_strcasecmp (type, "CUSTOMER") == 0)customer = gnc_search_customer_on_id (book, id);
+            else if (g_ascii_strcasecmp (type, "VENDOR") == 0)vendor = gnc_search_vendor_on_id (book, id);
+            if (!customer || !vendor)
+            {
+                if (g_ascii_strcasecmp (type, "CUSTOMER") == 0)
+                {
+                  customer = gncCustomerCreate( book );
+                  gncCustomerSetCurrency( customer, gnc_default_currency() );
+                }
+                else if(g_ascii_strcasecmp (type, "VENDOR") == 0)
+                {
+                  vendor = gncVendorCreate( book );
+                  gncVendorSetCurrency( vendor, gnc_default_currency() );
+                }
+                
+                (*n_customers_created)++;
+            }
+            else
+                (*n_customers_updated)++;
+            if (g_ascii_strcasecmp (type, "CUSTOMER") == 0)
+            {
+                gncCustomerBeginEdit (customer);
+                gncCustomerSetID (customer, id);
+                gncCustomerSetName (customer, company);
+                gncCustomerSetNotes (customer, notes);
+                addr = gncCustomerGetAddr (customer);
+                shipaddr = gncCustomerGetShipAddr (customer);
+            }
+            else if (g_ascii_strcasecmp (type, "VENDOR") == 0)
+            {
+                gncVendorBeginEdit (vendor);
+                gncVendorSetID (vendor, id);
+                gncVendorSetName (vendor, company);
+                gncVendorSetNotes (vendor, notes);
+                addr = gncVendorGetAddr (vendor);
+            }
+            gncAddressSetName (addr, name);
+            gncAddressSetAddr1 (addr, addr1);
+            gncAddressSetAddr2 (addr, addr2);
+            gncAddressSetAddr3 (addr, addr3);
+            gncAddressSetAddr4 (addr, addr4);
+            gncAddressSetPhone (addr, phone);
+            gncAddressSetFax (addr, fax);
+            gncAddressSetEmail (addr, email);
+            if (g_ascii_strcasecmp (type, "CUSTOMER") == 0)
+            {
+                gncAddressSetName (shipaddr, shipname);
+                gncAddressSetAddr1 (shipaddr, shipaddr1);
+                gncAddressSetAddr2 (shipaddr, shipaddr2);
+                gncAddressSetAddr3 (shipaddr, shipaddr3);
+                gncAddressSetAddr4 (shipaddr, shipaddr4);
+                gncAddressSetPhone (shipaddr, shipphone);
+                gncAddressSetFax (shipaddr, shipfax);
+                gncAddressSetEmail (shipaddr, shipemail);
+                gncCustomerSetActive (customer, TRUE);
+                gncCustomerCommitEdit (customer);
+            }
+            else if (g_ascii_strcasecmp (type, "VENDOR") == 0)
+            {
+                gncVendorSetActive (vendor, TRUE);
+                gncVendorCommitEdit (vendor);
+            }
+            //printf("TYPE %s created with ID = %s.\n", type, id); // DEBUG
+        }
+
+        g_free (company);
+        g_free (name);
+        g_free (addr1);
+        g_free (addr2);
+        g_free (addr3);
+        g_free (addr4);
+        g_free (phone);
+        g_free (fax);
+        g_free (email);
+        g_free (notes);
+        g_free (shipname);
+        g_free (shipaddr1);
+        g_free (shipaddr2);
+        g_free (shipaddr3);
+        g_free (shipaddr4);
+        g_free (shipphone);
+        g_free (shipfax);
+        g_free (shipemail);
+        valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
+    }
+}
+

Added: gnucash/trunk/src/plugins/customer_import/dialog-customer-import.h
===================================================================
--- gnucash/trunk/src/plugins/customer_import/dialog-customer-import.h	                        (rev 0)
+++ gnucash/trunk/src/plugins/customer_import/dialog-customer-import.h	2012-02-28 18:38:26 UTC (rev 22065)
@@ -0,0 +1,78 @@
+/*
+ * customer_import.h --
+ *
+ * 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, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org
+ */
+
+/**
+ * @addtogroup Tools
+ * @{
+ * @file customer_import.h
+ * @brief core import functions for customer import plugin
+ * @author Copyright (C) 2009 Sebastian Held <sebastian.held at gmx.de>
+ */
+
+#ifndef GNC_PLUGIN_customer_import_customer_import_H
+#define GNC_PLUGIN_customer_import_customer_import_H
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+// model
+enum customer_import_model_columns
+{
+    CI_ID, CI_COMPANY,
+    CI_NAME, CI_ADDR1, CI_ADDR2, CI_ADDR3, CI_ADDR4, CI_PHONE, CI_FAX, CI_EMAIL,
+    CI_NOTES,
+    CI_SHIPNAME, CI_SHIPADDR1, CI_SHIPADDR2, CI_SHIPADDR3, CI_SHIPADDR4, CI_SHIPPHONE, CI_SHIPFAX, CI_SHIPEMAIL,
+    CI_N_COLUMNS
+};
+
+enum _customer_import_result
+{
+    CI_RESULT_OK,
+    CI_RESULT_OPEN_FAILED,
+    CI_RESULT_ERROR_IN_REGEXP,
+};
+typedef enum _customer_import_result customer_import_result;
+
+struct _customer_import_stats
+{
+    int n_imported, n_ignored;
+    GString *ignored_lines;
+};
+typedef struct _customer_import_stats customer_import_stats;
+
+
+customer_import_result
+gnc_customer_import_read_file (const gchar *filename, const gchar *parser_regexp, GtkListStore *store, guint max_rows, customer_import_stats *stats);
+
+void
+gnc_customer_import_fix_customers (GtkListStore *store, guint *fixed, guint *deleted, gchar * type);
+
+void
+gnc_customer_import_create_customers (GtkListStore *store, QofBook *book, guint *n_customers_created, guint *n_customers_updated, gchar * type);
+
+
+G_END_DECLS
+
+#endif /* GNC_PLUGIN_customer_import_customer_import_H */
+
+/** @} */

Added: gnucash/trunk/src/plugins/customer_import/gnc-plugin-customer_import.c
===================================================================
--- gnucash/trunk/src/plugins/customer_import/gnc-plugin-customer_import.c	                        (rev 0)
+++ gnucash/trunk/src/plugins/customer_import/gnc-plugin-customer_import.c	2012-02-28 18:38:26 UTC (rev 22065)
@@ -0,0 +1,115 @@
+/*
+ * gnc-plugin-customer_import.c --
+ *
+ * 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, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org
+ */
+
+/**
+ * @internal
+ * @file gnc-plugin-customer_import.c
+ * @brief Plugin registration of the customer_import plugin
+ * @author Copyright (C) 2009 Sebastian Held <sebastian.held at gmx.de>
+ */
+
+#include "config.h"
+
+//#include <glade/glade.h>
+//#include <glade/glade-xml.h>
+#include <glib/gi18n.h>
+
+#include "dialog-utils.h"
+
+#include "gnc-plugin-customer_import.h"
+#include "dialog-customer-import-gui.h"
+
+/* This static indicates the debugging module that this .o belongs to.  */
+static QofLogModule log_module = G_LOG_DOMAIN;
+
+static void gnc_plugin_customer_import_class_init         (GncPlugincustomer_importClass *klass);
+static void gnc_plugin_customer_import_init               (GncPlugincustomer_import *plugin);
+static void gnc_plugin_customer_import_finalize           (GObject *object);
+
+/* Command callbacks */
+static void gnc_plugin_customer_import_cmd_test (GtkAction *action, GncMainWindowActionData *data);
+
+#define PLUGIN_ACTIONS_NAME "gnc-plugin-customer_import-actions"
+#define PLUGIN_UI_FILENAME  "gnc-plugin-customer_import-ui.xml"
+
+static GtkActionEntry gnc_plugin_actions [] =
+{
+    /* Menu Items */
+    { "ImportMenuAction", NULL, N_("I_mport"), NULL, NULL, NULL },
+    { "customer_importAction", NULL, N_("Import Customers and Vendors"), NULL, N_("customer_import tooltip"),  G_CALLBACK(gnc_plugin_customer_import_cmd_test) },
+};
+static guint gnc_plugin_n_actions = G_N_ELEMENTS(gnc_plugin_actions);
+
+
+/************************************************************
+ *                   Object Implementation                  *
+ ************************************************************/
+
+G_DEFINE_TYPE(GncPlugincustomer_import, gnc_plugin_customer_import, GNC_TYPE_PLUGIN);
+
+GncPlugin *
+gnc_plugin_customer_import_new (void)
+{
+    return GNC_PLUGIN (g_object_new (GNC_TYPE_PLUGIN_customer_import, (gchar*) NULL));
+}
+
+static void
+gnc_plugin_customer_import_class_init (GncPlugincustomer_importClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+    GncPluginClass *plugin_class = GNC_PLUGIN_CLASS(klass);
+
+    object_class->finalize = gnc_plugin_customer_import_finalize;
+
+    /* plugin info */
+    plugin_class->plugin_name  = GNC_PLUGIN_customer_import_NAME;
+
+    /* widget addition/removal */
+    plugin_class->actions_name       = PLUGIN_ACTIONS_NAME;
+    plugin_class->actions            = gnc_plugin_actions;
+    plugin_class->n_actions          = gnc_plugin_n_actions;
+    plugin_class->ui_filename        = PLUGIN_UI_FILENAME;
+}
+
+static void
+gnc_plugin_customer_import_init (GncPlugincustomer_import *plugin)
+{
+}
+
+static void
+gnc_plugin_customer_import_finalize (GObject *object)
+{
+}
+
+/************************************************************
+ *                    Command Callbacks                     *
+ ************************************************************/
+
+static void
+gnc_plugin_customer_import_cmd_test (GtkAction *action, GncMainWindowActionData *data)
+{
+    ENTER ("action %p, main window data %p", action, data);
+    g_message ("customer_import");
+
+    gnc_plugin_customer_import_showGUI();
+
+    LEAVE (" ");
+}

Added: gnucash/trunk/src/plugins/customer_import/gnc-plugin-customer_import.h
===================================================================
--- gnucash/trunk/src/plugins/customer_import/gnc-plugin-customer_import.h	                        (rev 0)
+++ gnucash/trunk/src/plugins/customer_import/gnc-plugin-customer_import.h	2012-02-28 18:38:26 UTC (rev 22065)
@@ -0,0 +1,80 @@
+/*
+ * gnc-plugin-customer_import.h --
+ *
+ * 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, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org
+ */
+
+/**
+ * @addtogroup Tools
+ * @{
+ * @file gnc-plugin-customer_import.h
+ * @brief Plugin registration of the customer_import module
+ * @author Copyright (C) 2009 Sebastian Held <sebastian.held at gmx.de>
+ */
+
+#ifndef GNC_PLUGIN_customer_import_H
+#define GNC_PLUGIN_customer_import_H
+
+#include <glib.h>
+
+#include "gnc-plugin.h"
+
+G_BEGIN_DECLS
+
+/* type macros */
+#define GNC_TYPE_PLUGIN_customer_import            (gnc_plugin_customer_import_get_type())
+#define GNC_PLUGIN_customer_import(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), GNC_TYPE_PLUGIN_customer_import, GncPlugincustomer_import))
+#define GNC_PLUGIN_customer_import_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),  GNC_TYPE_PLUGIN_customer_import, GncPlugincustomer_importClass))
+#define GNC_IS_PLUGIN_customer_import(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNC_TYPE_PLUGIN_customer_import))
+#define GNC_IS_PLUGIN_customer_import_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),  GNC_TYPE_PLUGIN_customer_import))
+#define GNC_PLUGIN_customer_import_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj),  GNC_TYPE_PLUGIN_customer_import, GncPlugincustomer_importClass))
+
+#define GNC_PLUGIN_customer_import_NAME "gnc-plugin-customer_import"
+
+/* typedefs & structures */
+typedef struct
+{
+    GncPlugin gnc_plugin;
+} GncPlugincustomer_import;
+
+typedef struct
+{
+    GncPluginClass gnc_plugin;
+} GncPlugincustomer_importClass;
+
+/* function prototypes */
+/**
+ * @return The glib runtime type of an customer_import plugin page
+ **/
+GType gnc_plugin_customer_import_get_type (void);
+
+/**
+ * @return A new GncPlugincustomer_import object
+ */
+GncPlugin* gnc_plugin_customer_import_new (void);
+
+/**
+ * Create a new GncPlugincustomer_import object and register it.
+ */
+void gnc_plugin_customer_import_create_plugin (void);
+
+G_END_DECLS
+
+/** @} */
+
+#endif /* GNC_PLUGIN_customer_import_H */

Added: gnucash/trunk/src/plugins/customer_import/gtkbuilder/Makefile.am
===================================================================
--- gnucash/trunk/src/plugins/customer_import/gtkbuilder/Makefile.am	                        (rev 0)
+++ gnucash/trunk/src/plugins/customer_import/gtkbuilder/Makefile.am	2012-02-28 18:38:26 UTC (rev 22065)
@@ -0,0 +1,4 @@
+gtkbuilderdir = $(GNC_GTKBUILDER_DIR)
+gtkbuilder_DATA = dialog-customer-import-gui.glade
+
+EXTRA_DIST = ${gtkbuilder_DATA}

Added: gnucash/trunk/src/plugins/customer_import/gtkbuilder/dialog-customer-import-gui.glade
===================================================================
--- gnucash/trunk/src/plugins/customer_import/gtkbuilder/dialog-customer-import-gui.glade	                        (rev 0)
+++ gnucash/trunk/src/plugins/customer_import/gtkbuilder/dialog-customer-import-gui.glade	2012-02-28 18:38:26 UTC (rev 22065)
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="2.20"/>
+  <object class="GtkDialog" id="customer_import Dialog">
+    <property name="width_request">500</property>
+    <property name="height_request">500</property>
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes">Import customers or vendors from text file</property>
+    <property name="type_hint">dialog</property>
+    <signal name="destroy" handler="gnc_customer_import_gui_destroy_cb" swapped="no"/>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">8</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="helpbutton">
+                <property name="label">gtk-help</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+                <property name="image_position">top</property>
+                <signal name="clicked" handler="gnc_customer_import_gui_help_cb" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="cancelbutton">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+                <signal name="clicked" handler="gnc_customer_import_gui_cancel_cb" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="okbutton">
+                <property name="label">gtk-ok</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="has_default">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+                <signal name="clicked" handler="gnc_customer_import_gui_ok_cb" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFrame" id="frame1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="border_width">3</property>
+            <property name="label_xalign">0</property>
+            <child>
+              <object class="GtkAlignment" id="alignment1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <object class="GtkHBox" id="hbox1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkEntry" id="entryFilename">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <signal name="changed" handler="gnc_customer_import_gui_filenameChanged_cb" swapped="no"/>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="buttonOpen">
+                        <property name="label">gtk-open</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_stock">True</property>
+                        <signal name="clicked" handler="gnc_customer_import_gui_buttonOpen_cb" swapped="no"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="pack_type">end</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes"><b>1. Choose the file to import</b></property>
+                <property name="use_markup">True</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFrame" id="frame2">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">none</property>
+            <child>
+              <object class="GtkAlignment" id="alignment4">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <object class="GtkVBox" id="box1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkRadioButton" id="radiobutton_customer">
+                        <property name="label" translatable="yes">Customer</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="tooltip_text" translatable="yes">For importing customer lists.</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="xalign">0</property>
+                        <property name="draw_indicator">True</property>
+                        <signal name="clicked" handler="gnc_customer_import_gui_type_cb" swapped="no"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRadioButton" id="radiobutton_vendor">
+                        <property name="label" translatable="yes">Vendor</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="tooltip_text" translatable="yes">For importing vendor lists.</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="xalign">0</property>
+                        <property name="draw_indicator">True</property>
+                        <property name="group">radiobutton_customer</property>
+                        <signal name="clicked" handler="gnc_customer_import_gui_type_cb" swapped="no"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel" id="label4">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes"><b>2. Select Import Type</b></property>
+                <property name="use_markup">True</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFrame" id="frame3">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="border_width">3</property>
+            <property name="label_xalign">0</property>
+            <child>
+              <object class="GtkAlignment" id="alignment2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <object class="GtkVBox" id="vbox1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkRadioButton" id="radiobutton1">
+                        <property name="label" translatable="yes">Semicolon separated</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="xalign">0</property>
+                        <property name="draw_indicator">True</property>
+                        <signal name="toggled" handler="gnc_customer_import_gui_option1_cb" swapped="no"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRadioButton" id="radiobutton2">
+                        <property name="label" translatable="yes">Comma separated</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="xalign">0</property>
+                        <property name="draw_indicator">True</property>
+                        <property name="group">radiobutton1</property>
+                        <signal name="toggled" handler="gnc_customer_import_gui_option2_cb" swapped="no"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRadioButton" id="radiobutton3">
+                        <property name="label" translatable="yes">Semicolon separated with quotes</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="xalign">0</property>
+                        <property name="draw_indicator">True</property>
+                        <property name="group">radiobutton1</property>
+                        <signal name="toggled" handler="gnc_customer_import_gui_option3_cb" swapped="no"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRadioButton" id="radiobutton4">
+                        <property name="label" translatable="yes">Comma separated with quotes</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="xalign">0</property>
+                        <property name="draw_indicator">True</property>
+                        <property name="group">radiobutton1</property>
+                        <signal name="toggled" handler="gnc_customer_import_gui_option4_cb" swapped="no"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">3</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRadioButton" id="radiobutton5">
+                        <property name="label" translatable="yes">Custom regular expression</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_action_appearance">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="xalign">0</property>
+                        <property name="draw_indicator">True</property>
+                        <property name="group">radiobutton1</property>
+                        <signal name="clicked" handler="gnc_customer_import_gui_option5_cb" swapped="no"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">4</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel" id="label2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes"><b>3. Select import options</b></property>
+                <property name="use_markup">True</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">3</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFrame" id="frame4">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="border_width">3</property>
+            <property name="label_xalign">0</property>
+            <child>
+              <object class="GtkAlignment" id="alignment3">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <object class="GtkScrolledWindow" id="scrolledwindow2">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="shadow_type">in</property>
+                    <child>
+                      <object class="GtkTreeView" id="treeview1">
+                        <property name="height_request">120</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <child internal-child="selection">
+                          <object class="GtkTreeSelection" id="treeview-selection1"/>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel" id="label3">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes"><b>3. Preview</b></property>
+                <property name="use_markup">True</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">4</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-11">helpbutton</action-widget>
+      <action-widget response="-6">cancelbutton</action-widget>
+      <action-widget response="-5">okbutton</action-widget>
+    </action-widgets>
+  </object>
+</interface>

Added: gnucash/trunk/src/plugins/customer_import/libgncmod-customer_import.c
===================================================================
--- gnucash/trunk/src/plugins/customer_import/libgncmod-customer_import.c	                        (rev 0)
+++ gnucash/trunk/src/plugins/customer_import/libgncmod-customer_import.c	2012-02-28 18:38:26 UTC (rev 22065)
@@ -0,0 +1,105 @@
+/*********************************************************************
+ * gncmod-customer_import.c
+ * module definition/initialization for the customer_import GNOME UI module
+ *
+ * Copyright (c) 2009 Sebastian Held <sebastian.held at gmx.de>
+ * Copyright (c) 2001 Derek Atkins <warlord at MIT.EDU>
+ *
+ * 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, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org
+ *
+ *********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gmodule.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <libguile.h>
+
+#include "gnc-hooks.h"
+#include "gnc-module.h"
+#include "gnc-module-api.h"
+
+#include "gnc-plugin-manager.h"
+#include "gnc-plugin-customer_import.h"
+
+GNC_MODULE_API_DECL(libgncmod_customer_import);
+
+/* version of the gnc module system interface we require */
+int libgncmod_customer_import_gnc_module_system_interface = 0;
+
+/* module versioning uses libtool semantics. */
+int libgncmod_customer_import_gnc_module_current  = 0;
+int libgncmod_customer_import_gnc_module_revision = 0;
+int libgncmod_customer_import_gnc_module_age      = 0;
+
+
+char *
+libgncmod_customer_import_gnc_module_path (void)
+{
+    return g_strdup("gnucash/plugins/customer_import");
+}
+
+char *
+libgncmod_customer_import_gnc_module_description (void)
+{
+    return g_strdup("The GnuCash customer_import plugin");
+}
+
+int
+libgncmod_customer_import_gnc_module_init (int refcount)
+{
+    if (!gnc_module_load ("gnucash/app-utils", 0))
+    {
+        return FALSE;
+    }
+    if (!gnc_module_load ("gnucash/gnome-utils", 0))
+    {
+        return FALSE;
+    }
+    //if (!gnc_module_load ("gnucash/business-core", 0)) {
+    //    return FALSE;
+    //}
+    if (!gnc_module_load ("gnucash/engine", 0))
+    {
+        return FALSE;
+    }
+
+    if (refcount == 0)
+    {
+        /* this is the first time the module is loaded */
+
+        gnc_plugin_manager_add_plugin ( gnc_plugin_manager_get (),
+                                        gnc_plugin_customer_import_new ());
+    }
+
+    return TRUE;
+}
+
+int
+libgncmod_customer_import_gnc_module_end (int refcount)
+{
+    if (refcount == 0)
+    {
+        /* this is the last time the module is unloaded */
+    }
+
+    return TRUE;
+}

Added: gnucash/trunk/src/plugins/customer_import/ui/Makefile.am
===================================================================
--- gnucash/trunk/src/plugins/customer_import/ui/Makefile.am	                        (rev 0)
+++ gnucash/trunk/src/plugins/customer_import/ui/Makefile.am	2012-02-28 18:38:26 UTC (rev 22065)
@@ -0,0 +1,5 @@
+uidir = $(GNC_UI_DIR)
+ui_DATA = \
+	gnc-plugin-customer_import-ui.xml
+
+EXTRA_DIST = $(ui_DATA)

Added: gnucash/trunk/src/plugins/customer_import/ui/gnc-plugin-customer_import-ui.xml
===================================================================
--- gnucash/trunk/src/plugins/customer_import/ui/gnc-plugin-customer_import-ui.xml	                        (rev 0)
+++ gnucash/trunk/src/plugins/customer_import/ui/gnc-plugin-customer_import-ui.xml	2012-02-28 18:38:26 UTC (rev 22065)
@@ -0,0 +1,13 @@
+<ui>
+	<menubar>
+		<placeholder name="AdditionalMenusPlaceholder">
+			<menu name="Business" action="BusinessAction">
+				<placeholder name="BusinessPlaceholderBottom">
+					<menu name="ImportMenu" action="ImportMenuAction">
+						<menuitem name="customer_import" action="customer_importAction"/>
+					</menu>
+				</placeholder>
+			</menu>
+		</placeholder>
+	</menubar>
+</ui>



More information about the gnucash-changes mailing list