diff --git a/configure.ac b/configure.ac index d29788cf05..e85abd91c6 100644 --- a/configure.ac +++ b/configure.ac @@ -1337,6 +1337,11 @@ AC_CONFIG_FILES( 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 diff --git a/doc/examples/customers_import.csv b/doc/examples/customers_import.csv new file mode 100644 index 0000000000..d19b69676f --- /dev/null +++ b/doc/examples/customers_import.csv @@ -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,,,,,,,,,,,,,,, diff --git a/src/engine/gncIDSearch.c b/src/engine/gncIDSearch.c index 006e0e4a3a..0269c0b12c 100644 --- a/src/engine/gncIDSearch.c +++ b/src/engine/gncIDSearch.c @@ -83,7 +83,7 @@ static void * search(QofBook * book, const gchar *id, void * object, QofIdType t 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 @@ static void * search(QofBook * book, const gchar *id, void * object, QofIdType t 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 @@ static void * search(QofBook * book, const gchar *id, void * object, QofIdType t 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); } } diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index b599da21f3..a2374a698f 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -1 +1 @@ -SUBDIRS=bi_import +SUBDIRS=customer_import bi_import diff --git a/src/plugins/customer_import/Makefile.am b/src/plugins/customer_import/Makefile.am new file mode 100644 index 0000000000..dd02939132 --- /dev/null +++ b/src/plugins/customer_import/Makefile.am @@ -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\" diff --git a/src/plugins/customer_import/dialog-customer-import-gui.c b/src/plugins/customer_import/dialog-customer-import-gui.c new file mode 100644 index 0000000000..b8dfc69611 --- /dev/null +++ b/src/plugins/customer_import/dialog-customer-import-gui.c @@ -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@gnu.org + */ + +/** + * @internal + * @file gui.c + * @brief GUI handling for customer import plugin + * @author Copyright (C) 2009 Sebastian Held + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#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 ( "^(?[^;]+);(?[^;]*);(?[^;]+);(?[^;]+);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*)"); + 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, "^(?[^;]*);(?[^;]*);(?[^;]*);(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);?(?[^;]*);(?[^;]*);(?[^;]*)"); //;(?[^;]*);(?[^;]*);(?[^;]*)$"); + 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, "^(?[^,]*),(?[^,]*),(?[^,]*),(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),(?[^,]*),(?[^,]*)"); //,(?[^,]*),(?[^,]*),(?[^,]*)$"); + 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, "^((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\")$"); + g_string_assign (gui->regexp, "^((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\");((?[^\";]*)|\"(?[^\"]*)\")$"); + 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, "^(?[^,]*),(?[^,]*),(?[^,]*),(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),?(?[^,]*),(?[^,]*),(?[^,]*)"); //,(?[^,]*),(?[^,]*),(?[^,]*)$"); + g_string_assign (gui->regexp, "^((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\"),((?[^\",]*)|\"(?[^\"]*)\")$"); + 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); +} diff --git a/src/plugins/customer_import/dialog-customer-import-gui.h b/src/plugins/customer_import/dialog-customer-import-gui.h new file mode 100644 index 0000000000..9f6aabd4ba --- /dev/null +++ b/src/plugins/customer_import/dialog-customer-import-gui.h @@ -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@gnu.org + */ + +/** + * @addtogroup Tools + * @{ + * @file gui.h + * @brief GUI handling for customer import plugin + * @author Copyright (C) 2009 Sebastian Held + */ + +#ifndef GNC_PLUGIN_customer_import_gui_H +#define GNC_PLUGIN_customer_import_gui_H + +#include + +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 */ + +/** @} */ diff --git a/src/plugins/customer_import/dialog-customer-import.c b/src/plugins/customer_import/dialog-customer-import.c new file mode 100644 index 0000000000..4a5c2d1872 --- /dev/null +++ b/src/plugins/customer_import/dialog-customer-import.c @@ -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@gnu.org + */ + +/** + * @internal + * @brief core import functions for customer import plugin + * @author Copyright (C) 2009 Sebastian Held + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#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, ¬es, + 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); + } +} + diff --git a/src/plugins/customer_import/dialog-customer-import.h b/src/plugins/customer_import/dialog-customer-import.h new file mode 100644 index 0000000000..349a0f6ce4 --- /dev/null +++ b/src/plugins/customer_import/dialog-customer-import.h @@ -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@gnu.org + */ + +/** + * @addtogroup Tools + * @{ + * @file customer_import.h + * @brief core import functions for customer import plugin + * @author Copyright (C) 2009 Sebastian Held + */ + +#ifndef GNC_PLUGIN_customer_import_customer_import_H +#define GNC_PLUGIN_customer_import_customer_import_H + +#include +#include + +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 */ + +/** @} */ diff --git a/src/plugins/customer_import/gnc-plugin-customer_import.c b/src/plugins/customer_import/gnc-plugin-customer_import.c new file mode 100644 index 0000000000..b168e81b48 --- /dev/null +++ b/src/plugins/customer_import/gnc-plugin-customer_import.c @@ -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@gnu.org + */ + +/** + * @internal + * @file gnc-plugin-customer_import.c + * @brief Plugin registration of the customer_import plugin + * @author Copyright (C) 2009 Sebastian Held + */ + +#include "config.h" + +//#include +//#include +#include + +#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 (" "); +} diff --git a/src/plugins/customer_import/gnc-plugin-customer_import.h b/src/plugins/customer_import/gnc-plugin-customer_import.h new file mode 100644 index 0000000000..1b83f02782 --- /dev/null +++ b/src/plugins/customer_import/gnc-plugin-customer_import.h @@ -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@gnu.org + */ + +/** + * @addtogroup Tools + * @{ + * @file gnc-plugin-customer_import.h + * @brief Plugin registration of the customer_import module + * @author Copyright (C) 2009 Sebastian Held + */ + +#ifndef GNC_PLUGIN_customer_import_H +#define GNC_PLUGIN_customer_import_H + +#include + +#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 */ diff --git a/src/plugins/customer_import/gtkbuilder/Makefile.am b/src/plugins/customer_import/gtkbuilder/Makefile.am new file mode 100644 index 0000000000..da877a3aeb --- /dev/null +++ b/src/plugins/customer_import/gtkbuilder/Makefile.am @@ -0,0 +1,4 @@ +gtkbuilderdir = $(GNC_GTKBUILDER_DIR) +gtkbuilder_DATA = dialog-customer-import-gui.glade + +EXTRA_DIST = ${gtkbuilder_DATA} diff --git a/src/plugins/customer_import/gtkbuilder/dialog-customer-import-gui.glade b/src/plugins/customer_import/gtkbuilder/dialog-customer-import-gui.glade new file mode 100644 index 0000000000..3cfad08cc7 --- /dev/null +++ b/src/plugins/customer_import/gtkbuilder/dialog-customer-import-gui.glade @@ -0,0 +1,398 @@ + + + + + 500 + 500 + True + False + Import customers or vendors from text file + dialog + + + + True + False + vertical + 8 + + + True + False + end + + + gtk-help + True + True + False + False + True + top + + + + False + False + 0 + + + + + gtk-cancel + True + True + True + False + False + True + + + + False + False + 1 + + + + + gtk-ok + True + True + True + True + False + False + True + + + + False + False + 2 + + + + + False + False + end + 0 + + + + + True + False + 3 + 0 + + + True + False + 12 + + + True + False + + + True + True + + + + True + True + 0 + + + + + gtk-open + True + True + False + False + True + + + + False + False + end + 1 + + + + + + + + + True + False + <b>1. Choose the file to import</b> + True + + + + + False + True + 1 + + + + + True + False + 0 + none + + + True + False + 12 + + + True + False + + + Customer + True + True + False + For importing customer lists. + False + 0 + True + + + + False + True + 0 + + + + + Vendor + True + True + False + For importing vendor lists. + False + 0 + True + radiobutton_customer + + + + False + True + 1 + + + + + + + + + True + False + <b>2. Select Import Type</b> + True + + + + + False + True + 2 + + + + + True + False + 3 + 0 + + + True + False + 12 + + + True + False + + + Semicolon separated + True + True + False + False + True + 0 + True + + + + False + False + 0 + + + + + Comma separated + True + True + False + False + True + 0 + True + radiobutton1 + + + + False + False + 1 + + + + + Semicolon separated with quotes + True + True + False + False + True + 0 + True + radiobutton1 + + + + False + False + 2 + + + + + Comma separated with quotes + True + True + False + False + True + 0 + True + radiobutton1 + + + + False + False + 3 + + + + + Custom regular expression + True + True + False + False + True + 0 + True + radiobutton1 + + + + False + False + 4 + + + + + + + + + True + False + <b>3. Select import options</b> + True + + + + + False + True + 3 + + + + + True + False + 3 + 0 + + + True + False + 12 + + + True + True + in + + + 120 + True + True + + + + + + + + + + + + True + False + <b>3. Preview</b> + True + + + + + False + True + 4 + + + + + + helpbutton + cancelbutton + okbutton + + + diff --git a/src/plugins/customer_import/libgncmod-customer_import.c b/src/plugins/customer_import/libgncmod-customer_import.c new file mode 100644 index 0000000000..fe93d61075 --- /dev/null +++ b/src/plugins/customer_import/libgncmod-customer_import.c @@ -0,0 +1,105 @@ +/********************************************************************* + * gncmod-customer_import.c + * module definition/initialization for the customer_import GNOME UI module + * + * Copyright (c) 2009 Sebastian Held + * Copyright (c) 2001 Derek Atkins + * + * 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@gnu.org + * + *********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#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; +} diff --git a/src/plugins/customer_import/ui/Makefile.am b/src/plugins/customer_import/ui/Makefile.am new file mode 100644 index 0000000000..3535d5a449 --- /dev/null +++ b/src/plugins/customer_import/ui/Makefile.am @@ -0,0 +1,5 @@ +uidir = $(GNC_UI_DIR) +ui_DATA = \ + gnc-plugin-customer_import-ui.xml + +EXTRA_DIST = $(ui_DATA) diff --git a/src/plugins/customer_import/ui/gnc-plugin-customer_import-ui.xml b/src/plugins/customer_import/ui/gnc-plugin-customer_import-ui.xml new file mode 100644 index 0000000000..daa44d33f9 --- /dev/null +++ b/src/plugins/customer_import/ui/gnc-plugin-customer_import-ui.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + +