Bug #672161: New CSV account and transaction importer

Patch by Robert Fewell:

Firstly, this patch allows for the creating and updating accounts based on the CSV file
being imported. New accounts are created if the commodity required exists and
existing accounts are updated for the four fields: code, description, notes and
colour. This can be used for doing bulk updates of these fields and also for
importing the account structure from another file.

The second part is the change of the existing CSV importer to use an assistant
to guide you through the import. Additional features added is the ability to
specify the start and end row to be imported allowing you to jump over a header
or footer or just import a few rows. A currency format option was added which
was requested in another bug to overcome a problem they were having with the
downloaded format from there bank. You can also associate the account name to a
GnuCash account using the 'online_id' kvp, not sure if this is Ok or whether it
should be a different one.

To achieve the above, I split the dialogs used in import_account_matcher and
import_main_matcher into the dialog and the content so I could load the content
into the assistant saving on duplication, hope this makes sense.

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@22086 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Christian Stimming 2012-03-16 20:26:22 +00:00
parent 725f25fb8a
commit c6141acc5a
34 changed files with 5294 additions and 548 deletions

View File

@ -1278,7 +1278,8 @@ AC_CONFIG_FILES(
src/import-export/schemas/Makefile
src/import-export/ofx/Makefile
src/import-export/ofx/test/Makefile
src/import-export/csv/Makefile
src/import-export/csv-import/Makefile
src/import-export/csv-import/schemas/Makefile
src/import-export/csv-export/Makefile
src/import-export/csv-export/schemas/Makefile
src/import-export/log-replay/Makefile

View File

@ -371,6 +371,18 @@ src/import-export/csv/gnc-csv-import.glade
src/import-export/csv/gnc-csv-model.c
src/import-export/csv/gncmod-csv-import.c
src/import-export/csv/gnc-plugin-csv.c
src/import-export/csv-import/assistant-csv-account-import.c
src/import-export/csv-import/assistant-csv-account-import.glade
src/import-export/csv-import/assistant-csv-trans-import.c
src/import-export/csv-import/assistant-csv-trans-import.glade
src/import-export/csv-import/csv-account-import.c
src/import-export/csv-import/gnc-csv-gnumeric-popup.c
src/import-export/csv-import/gnc-csv-import.c
src/import-export/csv-import/gnc-csv-import.glade
src/import-export/csv-import/gnc-csv-model.c
src/import-export/csv-import/gncmod-csv-import.c
src/import-export/csv-import/gnc-plugin-import-csv.c
src/import-export/csv-import/schemas/apps_gnucash_dialog_import.schemas.in
src/import-export/csv-export/assistant-csv-export.c
src/import-export/csv-export/assistant-csv-export.glade
src/import-export/csv-export/csv-transactions-export.c

View File

@ -569,7 +569,7 @@ load_gnucash_modules()
{ "gnucash/register/register-gnome", 0, FALSE },
{ "gnucash/import-export/qif-import", 0, FALSE },
{ "gnucash/import-export/ofx", 0, TRUE },
{ "gnucash/import-export/csv", 0, TRUE },
{ "gnucash/import-export/csv-import", 0, TRUE },
{ "gnucash/import-export/csv-export", 0, TRUE },
{ "gnucash/import-export/log-replay", 0, TRUE },
{ "gnucash/import-export/aqbanking", 0, TRUE },

View File

@ -5,7 +5,7 @@ if WITH_AQBANKING
AQBANKING_DIR=aqbanking
endif
SUBDIRS = . schemas qif qif-import \
${OFX_DIR} ${AQBANKING_DIR} log-replay test csv csv-export
${OFX_DIR} ${AQBANKING_DIR} log-replay test csv-import csv-export
pkglib_LTLIBRARIES=libgncmod-generic-import.la

View File

@ -1,23 +1,29 @@
SUBDIRS = .
SUBDIRS = . schemas
pkglib_LTLIBRARIES=libgncmod-csv.la
pkglib_LTLIBRARIES=libgncmod-csv-import.la
libgncmod_csv_la_SOURCES = \
libgncmod_csv_import_la_SOURCES = \
gncmod-csv-import.c \
gnc-plugin-csv.c \
gnc-csv-import.c \
assistant-csv-account-import.c \
assistant-csv-trans-import.c \
gnc-plugin-csv-import.c \
csv-account-import.c \
gnc-csv-model.c \
gnc-csv-gnumeric-popup.c
gnc-csv-gnumeric-popup.c \
gnc-csv-import.c
noinst_HEADERS = \
gnc-plugin-csv.h \
gnc-csv-import.h \
assistant-csv-account-import.h \
assistant-csv-trans-import.h \
gnc-plugin-csv-import.h \
csv-account-import.h \
gnc-csv-model.h \
gnc-csv-gnumeric-popup.h
gnc-csv-gnumeric-popup.h \
gnc-csv-import.h
libgncmod_csv_la_LDFLAGS = -avoid-version
libgncmod_csv_import_la_LDFLAGS = -avoid-version
libgncmod_csv_la_LIBADD = \
libgncmod_csv_import_la_LIBADD = \
${top_builddir}/src/import-export/libgncmod-generic-import.la \
${top_builddir}/src/gnome-utils/libgncmod-gnome-utils.la \
${top_builddir}/src/app-utils/libgncmod-app-utils.la \
@ -49,11 +55,13 @@ AM_CPPFLAGS = \
uidir = $(GNC_UI_DIR)
ui_DATA = \
gnc-plugin-csv-ui.xml
gnc-plugin-csv-import-ui.xml
gtkbuilderdir = ${GNC_GTKBUILDER_DIR}
gtkbuilder_DATA = \
gnc-csv-import.glade
assistant-csv-account-import.glade \
assistant-csv-trans-import.glade \
gnc-csv-import.glade
EXTRA_DIST = $(ui_DATA) $(gtkbuilder_DATA)

View File

@ -0,0 +1,599 @@
/*******************************************************************\
* assistant-csv-account-import.c -- An assistant for importing *
* Accounts from a file. *
* *
* Copyright (C) 2012 Robert Fewell *
* *
* 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 *
\********************************************************************/
/** @file assistant-csv-account-import.c
@brief CSV Import Assistant
@author Copyright (c) 2012 Robert Fewell
*/
#include "config.h"
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include "dialog-utils.h"
#include "gnc-ui.h"
#include "gnc-uri-utils.h"
#include "gnc-ui-util.h"
#include "gnc-component-manager.h"
#include "assistant-utils.h"
#include "assistant-csv-account-import.h"
#include "csv-account-import.h"
#define GCONF_SECTION "dialogs/import/csv"
#define ASSISTANT_CSV_IMPORT_CM_CLASS "assistant-csv-account-import"
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_ASSISTANT;
/*************************************************************************/
void csv_import_assistant_prepare (GtkAssistant *assistant, GtkWidget *page, gpointer user_data);
void csv_import_assistant_finish (GtkAssistant *gtkassistant, gpointer user_data);
void csv_import_assistant_cancel (GtkAssistant *gtkassistant, gpointer user_data);
void csv_import_assistant_close (GtkAssistant *gtkassistant, gpointer user_data);
void csv_import_assistant_start_page_prepare (GtkAssistant *gtkassistant, gpointer user_data);
void csv_import_assistant_account_page_prepare (GtkAssistant *gtkassistant, gpointer user_data);
void csv_import_assistant_file_page_prepare (GtkAssistant *assistant, gpointer user_data);
void csv_import_assistant_finish_page_prepare (GtkAssistant *assistant, gpointer user_data);
void csv_import_assistant_summary_page_prepare (GtkAssistant *assistant, gpointer user_data);
void csv_import_sep_cb (GtkWidget *radio, gpointer user_data );
void csv_import_hrows_cb (GtkWidget *spin, gpointer user_data );
void csv_import_file_chooser_confirm_cb (GtkWidget *button, CsvImportInfo *info);
static gchar *gnc_input_dialog (GtkWidget *parent, const gchar *title, const gchar *msg, const gchar *default_input);
static const gchar *finish_tree_string = N_(
"The accounts will be imported from the file '%s' when you click 'Apply'.\n\n"
"You can also go back and verify your selections by clicking on 'Back'"
" or 'Cancel' to Abort Import.\n");
/*************************************************************************/
/**************************************************
* csv_file_chooser_confirm_cb
*
* call back for ok button in file chooser widget
**************************************************/
void
csv_import_file_chooser_confirm_cb (GtkWidget *button, CsvImportInfo *info)
{
GtkAssistant *assistant = GTK_ASSISTANT(info->window);
gint num = gtk_assistant_get_current_page (assistant);
GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
gchar *file_name;
csv_import_result res;
gtk_assistant_set_page_complete (assistant, page, FALSE);
file_name = gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(info->file_chooser ));
if (file_name)
{
gchar *filepath = gnc_uri_get_path ( file_name );
gchar *filedir = g_path_get_dirname( filepath );
info->starting_dir = g_strdup(filedir);
g_free ( filedir );
g_free ( filepath );
info->file_name = g_strdup(file_name);
// generate preview
gtk_list_store_clear (info->store);
res = csv_import_read_file (info->file_name, info->regexp->str, info->store, 1 );
if (res == RESULT_OPEN_FAILED)
gnc_error_dialog (info->window, _("The input file can not be opened."));
else if (res == RESULT_OK)
gtk_assistant_set_page_complete (assistant, page, TRUE);
else if (res == MATCH_FOUND)
gtk_assistant_set_page_complete (assistant, page, TRUE);
}
g_free(file_name);
DEBUG("file_name selected is %s", info->file_name);
DEBUG("starting directory is %s", info->starting_dir);
}
/*******************************************************
* csv_import_hrows_cb
*
* call back for the start row / number of header rows
*******************************************************/
void csv_import_hrows_cb (GtkWidget *spin, gpointer user_data )
{
CsvImportInfo *info = user_data;
GtkTreeIter iter;
gboolean valid;
int num_rows;
/* Get number of rows for header */
info->header_rows = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spin));
/* Get number of rows displayed */
num_rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(info->store), NULL);
/* Modify background color for header rows */
if(info->header_rows == 0)
{
valid = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(info->store), &iter, NULL, 0 );
if(valid)
gtk_list_store_set (info->store, &iter, ROW_COLOR, NULL, -1);
}
else
{
if (info->header_rows - 1 < num_rows)
{
valid = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(info->store), &iter, NULL, info->header_rows - 1 );
if(valid)
gtk_list_store_set (info->store, &iter, ROW_COLOR, "pink", -1);
valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(info->store), &iter);
if(valid)
gtk_list_store_set (info->store, &iter, ROW_COLOR, NULL, -1);
}
}
}
/*******************************************************
* csv_import_sep_cb
*
* call back for type of separartor required
*******************************************************/
void csv_import_sep_cb (GtkWidget *radio, gpointer user_data )
{
CsvImportInfo *info = user_data;
const gchar *name;
gchar *temp;
if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio)))
{
LEAVE("1st callback of pair. Defer to 2nd callback.");
return;
}
name = gtk_buildable_get_name(GTK_BUILDABLE(radio));
if (g_strcmp0(name, g_strdup("radio_semi")) == 0)
g_string_assign (info->regexp, "^(?<type>[^;]*);(?<full_name>[^;]*);(?<name>[^;]*);(?<code>[^;]*);?(?<description>[^;]*);?(?<color>[^;]*);?(?<notes>[^;]*);?(?<commoditym>[^;]*);?(?<commodityn>[^;]*);?(?<hidden>[^;]*);?(?<tax>[^;]*);?(?<place_holder>[^;]*)$");
if (g_strcmp0(name, g_strdup("radio_comma")) == 0)
g_string_assign (info->regexp, "^(?<type>[^,]*),(?<full_name>[^,]*),(?<name>[^,]*),(?<code>[^,]*),?(?<description>[^,]*),?(?<color>[^,]*),?(?<notes>[^,]*),?(?<commoditym>[^,]*),?(?<commodityn>[^,]*),?(?<hidden>[^,]*),?(?<tax>[^,]*),?(?<place_holder>[^,]*)$");
if (g_strcmp0(name, g_strdup("radio_semiq")) == 0)
g_string_assign (info->regexp, "^((?<type>[^\";]*)|\"(?<type>[^\"]*)\");((?<full_name>[^\";]*)|\"(?<full_name>[^\"]*)\");((?<name>[^\";]*)|\"(?<name>[^\"]*)\");((?<code>[^\";]*)|\"(?<code>[^\"]*)\");((?<description>[^\";]*)|\"(?<description>[^\"]*)\");((?<color>[^\";]*)|\"(?<color>[^\"]*)\");((?<notes>[^\";]*)|\"(?<notes>[^\"]*)\");((?<commoditym>[^\";]*)|\"(?<commoditym>[^\"]*)\");((?<commodityn>[^\";]*)|\"(?<commodityn>[^\"]*)\");((?<hidden>[^\";]*)|\"(?<hidden>[^\"]*)\");((?<tax>[^\";]*)|\"(?<tax>[^\"]*)\");((?<place_holder>[^\";]*)|\"(?<place_holder>[^\"]*)\")$");
if (g_strcmp0(name, g_strdup("radio_commaq")) == 0)
g_string_assign (info->regexp, "^((?<type>[^\",]*)|\"(?<type>[^\"]*)\"),((?<full_name>[^\",]*)|\"(?<full_name>[^\"]*)\"),((?<name>[^\",]*)|\"(?<name>[^\"]*)\"),((?<code>[^\",]*)|\"(?<code>[^\"]*)\"),((?<description>[^\",]*)|\"(?<description>[^\"]*)\"),((?<color>[^\",]*)|\"(?<color>[^\"]*)\"),((?<notes>[^\",]*)|\"(?<notes>[^\"]*)\"),((?<commoditym>[^\",]*)|\"(?<commoditym>[^\"]*)\"),((?<commodityn>[^\",]*)|\"(?<commodityn>[^\"]*)\"),((?<hidden>[^\",]*)|\"(?<hidden>[^\"]*)\"),((?<tax>[^\",]*)|\"(?<tax>[^\"]*)\"),((?<place_holder>[^\",]*)|\"(?<place_holder>[^\"]*)\")$");
if (g_strcmp0(name, g_strdup("radio_custom")) == 0)
{
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"), info->regexp->str);
if (temp)
{
g_string_assign (info->regexp, temp);
g_free (temp);
}
}
/* Generate preview */
gtk_list_store_clear (info->store);
if(csv_import_read_file (info->file_name, info->regexp->str, info->store, 11 ) == MATCH_FOUND)
gtk_widget_set_sensitive (info->header_row_spin, TRUE);
else
gtk_widget_set_sensitive (info->header_row_spin, FALSE);
/* Reset Header spin to 0 */
gtk_spin_button_set_value( GTK_SPIN_BUTTON(info->header_row_spin), 0 );
}
/*******************************************************
* load_settings
*
* load the default settings for the assistant
*******************************************************/
static
void load_settings (CsvImportInfo *info)
{
info->header_rows = 0;
info->error = "";
info->starting_dir = NULL;
info->file_name = NULL;
info->error = "";
/* The default directory for the user to select files. */
info->starting_dir = gnc_get_default_directory(GCONF_SECTION);
}
/* =============================================================== */
/********************************************************************\
* 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);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
// 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;
}
/* =============================================================== */
/*******************************************************
* Assistant page prepare functions
*******************************************************/
void
csv_import_assistant_start_page_prepare (GtkAssistant *assistant,
gpointer user_data)
{
CsvImportInfo *info = user_data;
gint num = gtk_assistant_get_current_page (assistant);
GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
/* Enable the Assistant Buttons */
gtk_assistant_set_page_complete (assistant, page, TRUE);
}
void
csv_import_assistant_file_page_prepare (GtkAssistant *assistant,
gpointer user_data)
{
CsvImportInfo *info = user_data;
gint num = gtk_assistant_get_current_page (assistant);
GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
/* Set the default directory */
if (info->starting_dir)
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(info->file_chooser), info->starting_dir);
/* Disable the Forward Assistant Button */
gtk_assistant_set_page_complete (assistant, page, FALSE);
}
void
csv_import_assistant_account_page_prepare (GtkAssistant *assistant,
gpointer user_data)
{
CsvImportInfo *info = user_data;
gint num = gtk_assistant_get_current_page (assistant);
GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
gtk_list_store_clear (info->store);
if(csv_import_read_file (info->file_name, info->regexp->str, info->store, 11 ) == MATCH_FOUND)
gtk_widget_set_sensitive (info->header_row_spin, TRUE);
else
gtk_widget_set_sensitive (info->header_row_spin, FALSE);
}
void
csv_import_assistant_finish_page_prepare (GtkAssistant *assistant,
gpointer user_data)
{
CsvImportInfo *info = user_data;
gint num = gtk_assistant_get_current_page (assistant);
GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
gchar *text;
/* Set Finish page text */
text = g_strdup_printf (gettext (finish_tree_string), info->file_name);
gtk_label_set_text (GTK_LABEL(info->finish_label), text);
g_free(text);
/* Save the Window size and directory */
gnc_set_default_directory(GCONF_SECTION, info->starting_dir);
gnc_save_window_size(GCONF_SECTION, GTK_WINDOW(info->window));
/* Enable the Assistant Buttons */
gtk_assistant_set_page_complete (assistant, page, TRUE);
}
void
csv_import_assistant_summary_page_prepare (GtkAssistant *assistant,
gpointer user_data)
{
CsvImportInfo *info = user_data;
gchar *text, *errtext, *mtext;
if(!g_strcmp0(info->error,"") == 0)
{
text = g_strdup_printf(gettext ("Import completed but with errors!\n\nThe number of Accounts added was %u and "
"updated was %u.\n\nSee below for errors..." ), info->num_new, info->num_updates );
errtext = g_strdup_printf ( "%s", info->error);
gtk_label_set_text (GTK_LABEL(info->summary_error), errtext);
g_free(errtext);
g_free(info->error);
}
else
text = g_strdup_printf(gettext ("Import completed successfully!\n\nThe number of Accounts added was %u and "
"updated was %u.\n" ), info->num_new, info->num_updates );
mtext = g_strdup_printf("<span size=\"medium\"><b>%s</b></span>", text);
gtk_label_set_markup(GTK_LABEL(info->summary_label), mtext);
g_free(text);
g_free(mtext);
}
void
csv_import_assistant_prepare (GtkAssistant *assistant, GtkWidget *page,
gpointer user_data)
{
CsvImportInfo *info = user_data;
gint currentpage = gtk_assistant_get_current_page(assistant);
switch (currentpage)
{
case 0:
/* Current page is Import Start page */
csv_import_assistant_start_page_prepare (assistant, user_data);
break;
case 1:
/* Current page is File select page */
csv_import_assistant_file_page_prepare (assistant, user_data);
break;
case 2:
/* Current page is Account page */
csv_import_assistant_account_page_prepare (assistant, user_data);
break;
case 3:
/* Current page is Finish page */
csv_import_assistant_finish_page_prepare (assistant, user_data);
break;
case 4:
/* Current page is Summary page */
csv_import_assistant_summary_page_prepare (assistant, user_data);
break;
}
}
/*******************************************************
* Assistant call back functions
*******************************************************/
static void
csv_import_assistant_destroy_cb (GtkObject *object, gpointer user_data)
{
CsvImportInfo *info = user_data;
gnc_unregister_gui_component_by_data (ASSISTANT_CSV_IMPORT_CM_CLASS, info);
g_free (info);
}
void
csv_import_assistant_cancel (GtkAssistant *assistant, gpointer user_data)
{
CsvImportInfo *info = user_data;
gnc_close_gui_component_by_data (ASSISTANT_CSV_IMPORT_CM_CLASS, info);
}
void
csv_import_assistant_close (GtkAssistant *assistant, gpointer user_data)
{
CsvImportInfo *info = user_data;
gnc_close_gui_component_by_data (ASSISTANT_CSV_IMPORT_CM_CLASS, info);
}
void
csv_import_assistant_finish (GtkAssistant *assistant, gpointer user_data)
{
CsvImportInfo *info = user_data;
gtk_list_store_clear (info->store);
csv_import_read_file (info->file_name, info->regexp->str, info->store, 0 );
csv_account_import (info);
}
static void
csv_import_close_handler (gpointer user_data)
{
CsvImportInfo *info = user_data;
g_free(info->starting_dir);
g_free(info->file_name);
g_string_free(info->regexp, TRUE);
gtk_widget_destroy (info->window);
}
/*******************************************************
* Create the Assistant
*******************************************************/
static GtkWidget *
csv_import_assistant_create (CsvImportInfo *info)
{
GtkBuilder *builder;
GtkWidget *window;
GtkWidget *box;
GtkWidget *button;
GtkTreeIter iter;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
builder = gtk_builder_new();
gnc_builder_add_from_file (builder , "assistant-csv-account-import.glade", "num_hrows_adj");
gnc_builder_add_from_file (builder , "assistant-csv-account-import.glade", "CSV Account Import Assistant");
window = GTK_WIDGET(gtk_builder_get_object (builder, "CSV Account Import Assistant"));
info->window = window;
/* Set the assistant colors */
gnc_assistant_set_colors (GTK_ASSISTANT (info->window));
/* Load default settings */
load_settings (info);
/* Start Page */
/* File chooser Page */
info->file_chooser = gtk_file_chooser_widget_new (GTK_FILE_CHOOSER_ACTION_OPEN);
button = gtk_button_new_from_stock(GTK_STOCK_OK);
gtk_widget_show (button);
gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(info->file_chooser), button);
g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (csv_import_file_chooser_confirm_cb), info);
box = GTK_WIDGET(gtk_builder_get_object(builder, "file_page"));
gtk_box_pack_start (GTK_BOX (box), info->file_chooser, TRUE, TRUE, 6);
gtk_widget_show (info->file_chooser);
/* Account Tree Page */
info->header_row_spin = GTK_WIDGET(gtk_builder_get_object (builder, "num_hrows"));
info->tree_view = GTK_WIDGET(gtk_builder_get_object (builder, "treeview"));
info->regexp = g_string_new ( "^(?<type>[^;]*);(?<full_name>[^;]*);(?<name>[^;]*);(?<code>[^;]*);?(?<description>[^;]*);?(?<color>[^;]*);?(?<notes>[^;]*);?(?<commoditym>[^;]*);?(?<commodityn>[^;]*);?(?<hidden>[^;]*);?(?<tax>[^;]*);?(?<place_holder>[^;]*)$");
/* create model and bind to view */
info->store = gtk_list_store_new (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);
gtk_tree_view_set_model( GTK_TREE_VIEW(info->tree_view), GTK_TREE_MODEL(info->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_add_attribute(column, renderer, "background", ROW_COLOR); \
gtk_tree_view_column_set_resizable (column, TRUE); \
gtk_tree_view_append_column (GTK_TREE_VIEW (info->tree_view), column);
CREATE_COLUMN ("type", TYPE);
CREATE_COLUMN ("full__name", FULL_NAME);
CREATE_COLUMN ("name", NAME);
CREATE_COLUMN ("code", CODE);
CREATE_COLUMN ("description", DESCRIPTION);
CREATE_COLUMN ("color", COLOR);
CREATE_COLUMN ("notes", NOTES);
CREATE_COLUMN ("commoditym", COMMODITYM);
CREATE_COLUMN ("commodityn", COMMODITYN);
CREATE_COLUMN ("hidden", HIDDEN);
CREATE_COLUMN ("tax", TAX);
CREATE_COLUMN ("place__holder", PLACE_HOLDER);
/* Finish Page */
info->finish_label = GTK_WIDGET(gtk_builder_get_object(builder, "end_page"));
/* Summary Page */
info->summary_label = GTK_WIDGET(gtk_builder_get_object(builder, "summary_label"));
info->summary_error = GTK_WIDGET(gtk_builder_get_object(builder, "summary_error"));
g_signal_connect (G_OBJECT(window), "destroy",
G_CALLBACK (csv_import_assistant_destroy_cb), info);
gnc_restore_window_size (GCONF_SECTION, GTK_WINDOW(info->window));
gtk_builder_connect_signals(builder, info);
g_object_unref(G_OBJECT(builder));
return window;
}
/********************************************************************\
* gnc_file_csv_account_import *
* opens up a assistant to import accounts. *
* *
* Args: import_type *
* Return: nothing *
\********************************************************************/
void
gnc_file_csv_account_import(void)
{
CsvImportInfo *info;
gint component_id;
info = g_new0 (CsvImportInfo, 1);
csv_import_assistant_create (info);
component_id = gnc_register_gui_component (ASSISTANT_CSV_IMPORT_CM_CLASS,
NULL, csv_import_close_handler,
info);
gtk_widget_show_all (info->window);
gnc_window_adjust_for_screen (GTK_WINDOW(info->window));
}

View File

@ -0,0 +1,372 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkAssistant" id="CSV Account Import Assistant">
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="title" translatable="yes">CSV Import Assistant</property>
<property name="default_width">400</property>
<property name="default_height">500</property>
<signal name="close" handler="csv_import_assistant_close" swapped="no"/>
<signal name="apply" handler="csv_import_assistant_finish" swapped="no"/>
<signal name="prepare" handler="csv_import_assistant_prepare" swapped="no"/>
<signal name="cancel" handler="csv_import_assistant_cancel" swapped="no"/>
<child>
<object class="GtkVBox" id="start_page">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<child>
<object class="GtkLabel" id="start_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">
This assistant will help you import Accounts from a file.
The file must be in the same format as that exported as this is a fixed format import. If the account is missing, based on the full account name, it will be added as long as the security / currency specified exists. If the account exists, then four fields will be updated. These are code, description, notes and color.
Click on 'Forward' to proceed or 'Cancel' to Abort Import.
</property>
<property name="justify">center</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="page_type">intro</property>
<property name="title" translatable="yes">Import Account Assistant</property>
<property name="complete">True</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="file_page">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<child>
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">
Enter file name and location for the Import...
</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="page_type">progress</property>
<property name="title" translatable="yes">Choose File to Import</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="import_tree_page">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<child>
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xpad">6</property>
<property name="label" translatable="yes">Number of rows for the Header</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="num_hrows">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
<property name="invisible_char">&#x25CF;</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
<property name="adjustment">num_hrows_adj</property>
<signal name="value-changed" handler="csv_import_hrows_cb" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="separator_frame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTable" id="table4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="n_rows">4</property>
<property name="n_columns">4</property>
<child>
<object class="GtkRadioButton" id="radio_semi">
<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="active">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="csv_import_sep_cb" swapped="no"/>
</object>
</child>
<child>
<object class="GtkRadioButton" id="radio_semiq">
<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="draw_indicator">True</property>
<property name="group">radio_semi</property>
<signal name="toggled" handler="csv_import_sep_cb" swapped="no"/>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="radio_comma">
<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="draw_indicator">True</property>
<property name="group">radio_semi</property>
<signal name="toggled" handler="csv_import_sep_cb" swapped="no"/>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="radio_commaq">
<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="draw_indicator">True</property>
<property name="group">radio_semi</property>
<signal name="toggled" handler="csv_import_sep_cb" swapped="no"/>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="radio_custom">
<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="draw_indicator">True</property>
<property name="group">radio_semi</property>
<signal name="toggled" handler="csv_import_sep_cb" swapped="no"/>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Select Separator Type</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">7</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="preview_frame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkScrolledWindow" id="scroll_window">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="border_width">6</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<child>
<object class="GtkTreeView" id="treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label8">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Preview</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="page_type">progress</property>
<property name="title" translatable="yes">Import Account Preview, first 10 rows only</property>
<property name="complete">True</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="end_page">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Press Apply to create export file.
Cancel to abort.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="page_type">confirm</property>
<property name="title" translatable="yes">Import Accounts Now</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="summary_page">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<child>
<object class="GtkLabel" id="summary_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="summary_error">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="page_type">summary</property>
<property name="title" translatable="yes">Import Summary</property>
<property name="complete">True</property>
</packing>
</child>
</object>
<object class="GtkAdjustment" id="num_hrows_adj">
<property name="upper">100</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
</interface>

View File

@ -0,0 +1,68 @@
/*******************************************************************\
* assistant-csv-account-import.h -- An assistant for importing *
* Accounts from a file. *
* *
* Copyright (C) 2012 Robert Fewell *
* *
* 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 *
\********************************************************************/
/** @file assistant-csv-account-import.h
@brief CSV Import Assistant
@author Copyright (c) 2011 Robert Fewell
*/
#ifndef GNC_ASSISTANT_CSV_IMPORT_H
#define GNC_ASSISTANT_CSV_IMPORT_H
// Account tree model
enum tree_import_model_columns
{
TYPE, FULL_NAME, NAME, CODE, DESCRIPTION, COLOR,
NOTES, COMMODITYM, COMMODITYN, HIDDEN, TAX, PLACE_HOLDER, ROW_COLOR,
N_COLUMNS
};
typedef struct
{
GtkWidget *window;
GtkWidget *assistant;
GtkWidget *file_chooser;
GtkWidget *tree_view;
GtkListStore *store;
GString *regexp;
GtkWidget *header_row_spin;
GtkWidget *finish_label;
GtkWidget *summary_label;
GtkWidget *summary_error;
gchar *starting_dir;
gchar *file_name;
gchar *error;
int header_rows;
int num_new;
int num_updates;
} CsvImportInfo;
/** The gnc_file_csv_account_import() will let the user import
* accounts from a deliminated file.
*/
void gnc_file_csv_account_import (void);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,863 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkAssistant" id="CSV Transaction Assistant">
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="title" translatable="yes">CSV Transaction Import</property>
<property name="default_width">400</property>
<property name="default_height">500</property>
<signal name="close" handler="csv_import_trans_assistant_close" swapped="no"/>
<signal name="apply" handler="csv_import_trans_assistant_finish" swapped="no"/>
<signal name="prepare" handler="csv_import_trans_assistant_prepare" swapped="no"/>
<signal name="cancel" handler="csv_import_trans_assistant_cancel" swapped="no"/>
<child>
<object class="GtkLabel" id="start_page">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">This assistant will help you import a deliminated file containing a list of transactions.
All transactions imported will be associated to one account for each import and if you select the account column, the account in the first row will be used for all rows.
Various options exist for specifing the deliminator as well as a fixed width option. With the fixed width option, double click on the bar above the displayed rows to set the column width.
There is an option for specifying the start and end row which can be used if you have some header text or multiple accounts in the same file.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="page_type">intro</property>
<property name="title" translatable="yes">Transaction Import Assistant</property>
<property name="complete">True</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="file_page">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<child>
<object class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">
Enter file name and location for the Import...
</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="title" translatable="yes">Select File for Import</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="preview_page">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="border_width">12</property>
<property name="spacing">2</property>
<child>
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">12</property>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<object class="GtkHBox" id="hbox6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="label9">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Start import on row </property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="start_row">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
<property name="invisible_char">&#x25CF;</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
<property name="adjustment">start_row_adj</property>
<signal name="value-changed" handler="csv_import_trans_srow_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="GtkLabel" id="label10">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes"> and stop on row </property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="end_row">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
<property name="invisible_char">&#x25CF;</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
<property name="adjustment">end_row_adj</property>
<signal name="value-changed" handler="csv_import_trans_erow_cb" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkHSeparator" id="hseparator7">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">8</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Data type: </property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="csv_button">
<property name="label" translatable="yes">Separated</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="use_action_appearance">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="radiobutton2">
<property name="label" translatable="yes">Fixed-Width</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
<property name="group">csv_button</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkHSeparator" id="hseparator6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">10</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox7">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkFrame" id="frame2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="date_format_container">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="left_padding">12</property>
<child>
<placeholder/>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Date Format</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame3">
<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="currency_format_container">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">12</property>
<child>
<placeholder/>
</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">Currency format</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkHSeparator" id="hseparator3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">10</property>
<property name="position">5</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkTable" id="enctable">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Encoding: </property>
</object>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkHSeparator" id="hseparator1">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">5</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="left_padding">12</property>
<child>
<object class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="n_rows">3</property>
<property name="n_columns">3</property>
<property name="column_spacing">3</property>
<property name="row_spacing">3</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkCheckButton" id="space_cbutton">
<property name="label" translatable="yes">Space</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="tab_cbutton">
<property name="label" translatable="yes">Tab</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="comma_cbutton">
<property name="label" translatable="yes">Comma (,)</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="use_action_appearance">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="colon_cbutton">
<property name="label" translatable="yes">Colon (:)</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="semicolon_cbutton">
<property name="label" translatable="yes">Semicolon (;)</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="hyphen_cbutton">
<property name="label" translatable="yes">Hyphen (-)</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="custom_cbutton">
<property name="label" translatable="yes">Custom</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="custom_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="invisible_char">&#x25CF;</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Separators</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkHSeparator" id="hseparator2">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">6</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<object class="GtkImage" id="instructions_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-dialog-info</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">2</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="instructions_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Select the type of each column below.</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<child>
<object class="GtkViewport" id="viewport1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkVBox" id="vbox2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkTreeView" id="ctreeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="headers_visible">False</property>
<property name="enable_grid_lines">both</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkTreeView" id="treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="enable_grid_lines">both</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkCheckButton" id="check_butt">
<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="xalign">1</property>
<property name="image_position">right</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="csv_import_trans_auto_cb" swapped="no"/>
</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="GtkLabel" id="check_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xpad">5</property>
<property name="label" translatable="yes">Step over Account Page if Setup</property>
</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>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack_type">end</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="title" translatable="yes">Preview Settings</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="account_page">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<object class="GtkLabel" id="account_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Error text.</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack_type">end</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="title" translatable="yes">Account Selection</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="doc_page">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="label8">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">On the following page you will be able to associate each transaction to a category.
If this is the first time importing, you will find that all lines may need to be associated. On subsequent imports, the importer will try to associate the transactions based on previous imports.
The confidence of a correct association is displayed as a colored bar.
More infomation can be displayed by using the help button.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="page_type">progress</property>
<property name="title" translatable="yes">Transaction Information</property>
<property name="complete">True</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="match_page">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<child>
<object class="GtkLabel" id="match_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
</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>
</object>
<packing>
<property name="page_type">confirm</property>
<property name="title" translatable="yes">Match Transactions</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="summary_page">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<child>
<object class="GtkLabel" id="summary_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="page_type">summary</property>
<property name="title" translatable="yes">Import Summary</property>
<property name="complete">True</property>
</packing>
</child>
</object>
<object class="GtkAdjustment" id="end_row_adj">
<property name="lower">1</property>
<property name="upper">100</property>
<property name="value">100</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
<object class="GtkAdjustment" id="start_row_adj">
<property name="lower">1</property>
<property name="upper">100</property>
<property name="value">1</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
</interface>

View File

@ -0,0 +1,36 @@
/*******************************************************************\
* assistant-csv-trans-import.h -- An assistant for importing *
* Transactions from a file. *
* *
* Copyright (C) 2012 Robert Fewell *
* *
* 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 *
\********************************************************************/
/** @file assistant-csv-trans-import.h
@brief CSV Import Assistant
@author Copyright (c) 2011 Robert Fewell
*/
#ifndef GNC_ASSISTANT_CSV_IMPORT_TRANS_H
#define GNC_ASSISTANT_CSV_IMPORT_TRANS_H
/** The gnc_file_csv_trans_import() will let the user import thte
* account tree or transactions to a deliminated file.
*/
void gnc_file_csv_trans_import (void);
#endif

View File

@ -0,0 +1,349 @@
/*******************************************************************\
* csv-account-import.c -- Account importing from file *
* *
* Copyright (C) 2012 Robert Fewell *
* *
* Based on code from bi_import written by Sebastian Held and *
* Mike Evans. *
* *
* 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 *
\********************************************************************/
#include "config.h"
#include <glib.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include "gnc-ui-util.h"
#include <regex.h>
#include "gnc-exp-parser.h"
#include "Account.h"
#include "gnc-component-manager.h"
#include "csv-account-import.h"
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_ASSISTANT;
/* 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); \
}
/*******************************************************
* csv_import_read_file
*
* Parse the file for a correctly formatted file
*******************************************************/
csv_import_result
csv_import_read_file (const gchar *filename, const gchar *parser_regexp,
GtkListStore *store, guint max_rows )
{
FILE *f;
char *line;
gchar *line_utf8, *temp;
GMatchInfo *match_info;
GError *err;
GRegex *regexpat;
int row = 0;
gboolean match_found = FALSE;
// model
GtkTreeIter iter;
f = g_fopen (filename, "rt");
if (!f)
{
//gnc_error_dialog( 0, _("File %s cannot be opened."), filename );
return RESULT_OPEN_FAILED;
}
// 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 RESULT_ERROR_IN_REGEXP;
}
// start the import
#define buffer_size 1000
line = g_malloc0 (buffer_size);
while (!feof (f))
{
int l;
row++;
if(row == max_rows)
break;
// 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 = TRUE;
// fill in the values
gtk_list_store_append (store, &iter);
FILL_IN_HELPER ("type", TYPE);
FILL_IN_HELPER ("full_name", FULL_NAME);
FILL_IN_HELPER ("name", NAME);
FILL_IN_HELPER ("code", CODE);
FILL_IN_HELPER ("description", DESCRIPTION);
FILL_IN_HELPER ("color", COLOR);
FILL_IN_HELPER ("notes", NOTES);
FILL_IN_HELPER ("commoditym", COMMODITYM);
FILL_IN_HELPER ("commodityn", COMMODITYN);
FILL_IN_HELPER ("hidden", HIDDEN);
FILL_IN_HELPER ("tax", TAX);
FILL_IN_HELPER ("place_holder", PLACE_HOLDER);
gtk_list_store_set (store, &iter, ROW_COLOR, NULL, -1);
}
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);
if(match_found == TRUE)
return MATCH_FOUND;
else
return RESULT_OK;
}
/*******************************************************
* csv_account_import
*
* Parse the liststore for account updates
*******************************************************/
void
csv_account_import (CsvImportInfo *info)
{
QofBook *book;
Account *acc, *parent, *root;
gboolean valid;
GdkColor testcolor;
GtkTreeIter iter;
gchar *type, *full_name, *name, *code, *description, *color;
gchar *notes, *commoditym, *commodityn, *hidden, *tax, *place_holder;
int row;
ENTER("");
book = gnc_get_current_book();
root = gnc_book_get_root_account(book);
info->num_new = 0;
info->num_updates = 0;
/* Move to the first valid entry in store */
row = info->header_rows;
valid = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(info->store), &iter, NULL, row );
while (valid)
{
/* Walk through the list, reading each row */
gtk_tree_model_get (GTK_TREE_MODEL (info->store), &iter,
TYPE, &type,
FULL_NAME, &full_name,
NAME, &name,
CODE, &code,
DESCRIPTION, &description,
COLOR, &color,
NOTES, &notes,
COMMODITYM, &commoditym,
COMMODITYN, &commodityn,
HIDDEN, &hidden,
TAX, &tax,
PLACE_HOLDER, &place_holder, -1);
/* See if we can find the account by full name */
acc = gnc_account_lookup_by_full_name(root, full_name);
DEBUG("Row is %u and full name is %s", row, full_name);
if (acc == NULL)
{
/* Account does not exist, Lets try and add it */
if (g_strrstr(full_name, name) != NULL)
{
gint string_position;
gnc_commodity *commodity;
gnc_commodity_table *table;
gchar *full_parent;
/* Get full name of parent account, allow for separator */
string_position = strlen(full_name) - strlen(name) - 1;
if(string_position == -1)
full_parent = g_strdup(full_name);
else
full_parent = g_strndup(full_name, string_position);
parent = gnc_account_lookup_by_full_name(root, full_parent);
g_free (full_parent);
if (parent == NULL && string_position != -1)
{
gchar *text = g_strdup_printf( gettext("Row %u, path to account %s not found, added as top level\n"), row +1, name );
info->error = g_strconcat(info->error, text, NULL);
g_free(text);
PINFO("Unable to import Row %u for account %s, path not found!", row, name);
}
if (parent == NULL)
parent = root;
/* Do we have a valid commodity */
table = gnc_commodity_table_get_table (book);
commodity = gnc_commodity_table_lookup( table, commodityn, commoditym);
if (commodity)
{
DEBUG("We have a valid commodity and will add account %s", full_name);
info->num_new = info->num_new + 1;
gnc_suspend_gui_refresh ();
acc = xaccMallocAccount (book);
xaccAccountBeginEdit (acc);
xaccAccountSetName (acc, name);
xaccAccountSetType(acc, xaccAccountStringToEnum (type));
if(!g_strcmp0(notes, "") == 0)
xaccAccountSetNotes (acc, notes);
if(!g_strcmp0(description, "") == 0)
xaccAccountSetDescription (acc, description);
if(!g_strcmp0(code, "") == 0)
xaccAccountSetCode (acc, code);
if(!g_strcmp0(color, "") == 0)
{
if (gdk_color_parse(color, &testcolor))
xaccAccountSetColor (acc, color);
}
if(g_strcmp0(hidden, "T") == 0)
xaccAccountSetHidden (acc, TRUE);
if(g_strcmp0(place_holder, "T") == 0)
xaccAccountSetPlaceholder (acc, TRUE);
xaccAccountSetCommodity(acc, commodity);
xaccAccountBeginEdit (parent);
gnc_account_append_child (parent, acc);
xaccAccountCommitEdit (parent);
xaccAccountCommitEdit (acc);
gnc_resume_gui_refresh ();
}
else
{
gchar *err_string = g_strdup_printf( gettext("Row %u, commodity %s / %s not found\n"), row +1,
commoditym, commodityn);
info->error = g_strconcat(info->error, err_string, NULL);
g_free(err_string);
PINFO("Unable to import Row %u for account %s, commodity!", row, full_name);
}
}
else
{
gchar *err_string = g_strdup_printf( gettext("Row %u, account %s not in %s\n"), row +1, name, full_name);
info->error = g_strconcat(info->error, err_string, NULL);
g_free(err_string);
PINFO("Unable to import Row %u for account %s, name!", row, full_name);
}
}
else
{
/* Lets try and update the color, notes, description, code entries */
DEBUG("Existing account, will try and update account %s", full_name);
info->num_updates = info->num_updates +1;
if(!g_strcmp0(color, "") == 0)
{
if (gdk_color_parse(color, &testcolor))
xaccAccountSetColor (acc, color);
}
if(!g_strcmp0(notes, "") == 0)
{
/* Check for multiple lines */
gchar **parts;
parts = g_strsplit(notes, "\\n", -1);
notes = g_strjoinv("\n", parts);
g_strfreev(parts);
}
xaccAccountSetNotes (acc, notes);
if(!g_strcmp0(description, "") == 0)
xaccAccountSetDescription (acc, description);
if(!g_strcmp0(code, "") == 0)
xaccAccountSetCode (acc, code);
}
valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (info->store), &iter);
row++;
/* free resources */
g_free (type);
g_free (full_name);
g_free (name);
g_free (code);
g_free (description);
g_free (color);
g_free (notes);
g_free (commoditym);
g_free (commodityn);
g_free (hidden);
g_free (tax);
g_free (place_holder);
}
LEAVE("");
}

View File

@ -0,0 +1,50 @@
/*******************************************************************\
* csv-account-import.h -- Account importing from file *
* *
* Copyright (C) 2012 Robert Fewell *
* *
* Based on code from bi_import written by Sebastian Held and *
* Mike Evans. *
* *
* 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 *
\********************************************************************/
#ifndef CSV_ACCOUNT_IMPORT_H
#define CSV_ACCOUNT_IMPORT_H
#include <glib.h>
#include <gtk/gtk.h>
#include "assistant-csv-account-import.h"
enum _csv_import_result
{
RESULT_OK,
RESULT_OPEN_FAILED,
RESULT_ERROR_IN_REGEXP,
MATCH_FOUND,
};
typedef enum _csv_import_result csv_import_result;
csv_import_result
csv_import_read_file (const gchar *filename, const gchar *parser_regexp, GtkListStore *store, guint max_rows );
void csv_account_import(CsvImportInfo *info);
#endif /* CSV_ACCOUNT_IMPORT_H */

View File

@ -540,7 +540,7 @@ static GtkCellRenderer* gnc_csv_preview_get_cell_renderer(GncCsvPreview* preview
}
/* The following is code copied from Gnumeric 1.7.8 licensed under the
* GNU General Public License version 2 and/or version 3. It is from the file
* GNU General Public License version 2. It is from the file
* gnumeric/src/dialogs/dialog-stf-fixed-page.c, and it has been
* modified slightly to work within GnuCash. */

View File

@ -11,6 +11,8 @@
#endif
#include <goffice/utils/go-glib-extras.h>
#include "gnc-ui-util.h"
#include <string.h>
#include <sys/time.h>
@ -29,7 +31,6 @@
static QofLogModule log_module = GNC_MOD_IMPORT;
const int num_date_formats = 5;
const gchar* date_format_user[] = {N_("y-m-d"),
N_("d-m-y"),
N_("m-d-y"),
@ -37,10 +38,17 @@ const gchar* date_format_user[] = {N_("y-m-d"),
N_("m-d")
};
const int num_currency_formats = 3;
const gchar* currency_format_user[] = {N_("Locale"),
N_("Period: 123,456.78"),
N_("Comma: 123.456,78")
};
/* This array contains all of the different strings for different column types. */
gchar* gnc_csv_column_type_strs[GNC_CSV_NUM_COL_TYPES] = {N_("None"),
N_("Date"),
N_("Description"),
N_("Account"),
N_("Balance"),
N_("Deposit"),
N_("Withdrawal"),
@ -305,7 +313,7 @@ static time_t parse_date_without_year(const char* date_str, int format)
* @param format An index specifying a format in date_format_user
* @return The parsed value of date_str on success or -1 on failure
*/
static time_t parse_date(const char* date_str, int format)
time_t parse_date(const char* date_str, int format)
{
if (strchr(date_format_user[format], 'y'))
return parse_date_with_year(date_str, format);
@ -331,7 +339,10 @@ GncCsvParseData* gnc_csv_new_parse_data(void)
parse_data->error_lines = parse_data->transactions = NULL;
parse_data->options = default_parse_options();
parse_data->date_format = -1;
parse_data->currency_format = 0;
parse_data->chunk = g_string_chunk_new(100 * 1024);
parse_data->start_row = 0;
parse_data->end_row = 1000;
return parse_data;
}
@ -432,7 +443,7 @@ GError** error)
int gnc_csv_load_file(GncCsvParseData* parse_data, const char* filename,
GError** error)
{
const char* guess_enc;
const char* guess_enc = NULL;
/* Get the raw data first and handle an error if one occurs. */
parse_data->raw_mapping = g_mapped_file_new(filename, FALSE, error);
@ -441,6 +452,7 @@ GError** error)
/* TODO Handle file opening errors more specifically,
* e.g. inexistent file versus no read permission. */
parse_data->raw_str.begin = NULL;
g_clear_error (error);
g_set_error(error, 0, GNC_CSV_FILE_OPEN_ERR, "%s", _("File opening failed."));
return 1;
}
@ -450,15 +462,15 @@ GError** error)
parse_data->raw_str.end = parse_data->raw_str.begin + g_mapped_file_get_length(parse_data->raw_mapping);
/* Make a guess at the encoding of the data. */
guess_enc = go_guess_encoding((const char*)(parse_data->raw_str.begin),
(size_t)(parse_data->raw_str.end - parse_data->raw_str.begin),
"UTF-8", NULL);
if(!g_mapped_file_get_length(parse_data->raw_mapping) == 0)
guess_enc = go_guess_encoding((const char*)(parse_data->raw_str.begin),
(size_t)(parse_data->raw_str.end - parse_data->raw_str.begin),
"UTF-8", NULL);
if (guess_enc == NULL)
{
g_set_error(error, 0, GNC_CSV_ENCODING_ERR, "%s", _("Unknown encoding."));
return 1;
}
/* Convert using the guessed encoding into parse_data->file_str and
* handle any errors that occur. */
gnc_csv_convert_encoding(parse_data, guess_enc, error);
@ -512,7 +524,8 @@ int gnc_csv_parse(GncCsvParseData* parse_data, gboolean guessColTypes, GError**
g_array_free(parse_data->orig_row_lengths, FALSE);
parse_data->orig_row_lengths =
g_array_sized_new(FALSE, FALSE, sizeof(int), parse_data->orig_lines->len);
g_array_sized_new(FALSE, FALSE, sizeof(int), parse_data->orig_lines->len);
g_array_set_size(parse_data->orig_row_lengths, parse_data->orig_lines->len);
parse_data->orig_max_row = 0;
for (i = 0; i < parse_data->orig_lines->len; i++)
@ -576,6 +589,7 @@ int gnc_csv_parse(GncCsvParseData* parse_data, gboolean guessColTypes, GError**
typedef struct
{
int date_format; /**< The format for parsing dates */
int currency_format; /**< The format for currency */
Account* account; /**< The account the transaction belongs to */
GList* properties; /**< List of TransProperties */
} TransPropertyList;
@ -632,7 +646,7 @@ static void trans_property_free(TransProperty* prop)
static gboolean trans_property_set(TransProperty* prop, char* str)
{
char *endptr, *possible_currency_symbol, *str_dupe;
double value;
gnc_numeric val;
switch (prop->type)
{
case GNC_CSV_DATE:
@ -672,27 +686,40 @@ static gboolean trans_property_set(TransProperty* prop, char* str)
}
}
/* Translate the string (now clean of currency symbols) into a number. */
value = strtod(str_dupe, &endptr);
/* If this isn't a valid numeric string, this is an error. */
if (endptr != str_dupe + strlen(str_dupe))
/* Currency format */
switch (prop->list->currency_format)
{
g_free(str_dupe);
return FALSE;
case 0:
/* Currancy locale */
if(!(xaccParseAmount(str_dupe, TRUE, &val, &endptr)))
{
g_free(str_dupe);
return FALSE;
}
break;
case 1:
/* Currancy decimal period */
if(!(xaccParseAmountExtended(str_dupe, TRUE, '-', '.', ',', "\003\003", "$+", &val, &endptr)))
{
g_free(str_dupe);
return FALSE;
}
break;
case 2:
/* Currancy decimal comma */
if(!(xaccParseAmountExtended(str_dupe, TRUE, '-', ',', '.', "\003\003", "$+", &val, &endptr)))
{
g_free(str_dupe);
return FALSE;
}
break;
}
prop->value = g_new(gnc_numeric, 1);
*((gnc_numeric*)(prop->value)) = val;
g_free(str_dupe);
/* Change abs to fabs, to fix bug 586805 */
if (fabs(value) > 0.00001)
{
prop->value = g_new(gnc_numeric, 1);
*((gnc_numeric*)(prop->value)) =
double_to_gnc_numeric(value, xaccAccountGetCommoditySCU(prop->list->account),
GNC_HOW_RND_ROUND_HALF_UP);
}
return TRUE;
}
return FALSE; /* We should never actually get here. */
}
@ -702,11 +729,12 @@ static gboolean trans_property_set(TransProperty* prop, char* str)
* @param date_format An index from date_format_user for how date properties should be parsed
* @return A pointer to a new TransPropertyList
*/
static TransPropertyList* trans_property_list_new(Account* account, int date_format)
static TransPropertyList* trans_property_list_new(Account* account, int date_format, int currency_format)
{
TransPropertyList* list = g_new(TransPropertyList, 1);
list->account = account;
list->date_format = date_format;
list->currency_format = currency_format;
list->properties = NULL;
return list;
}
@ -1014,26 +1042,32 @@ int gnc_csv_parse_to_trans(GncCsvParseData* parse_data, Account* account,
{
/* The following while-loop effectively behaves like the following for-loop:
* for(i = 0; i < parse_data->orig_lines->len; i++). */
i = 0;
i = parse_data->start_row;
last_transaction = NULL;
}
while (i < parse_data->orig_lines->len)
/* set parse_data->end_row to number of lines */
if(parse_data->end_row > parse_data->orig_lines->len)
parse_data->end_row = parse_data->orig_lines->len;
while (i < parse_data->end_row)
{
GPtrArray* line = parse_data->orig_lines->pdata[i];
/* This flag is TRUE if there are any errors in this row. */
gboolean errors = FALSE;
gchar* error_message = NULL;
TransPropertyList* list = trans_property_list_new(account, parse_data->date_format);
TransPropertyList* list = trans_property_list_new(account, parse_data->date_format, parse_data->currency_format );
GncCsvTransLine* trans_line = NULL;
for (j = 0; j < line->len; j++)
{
/* We do nothing in "None" columns. */
if (column_types->data[j] != GNC_CSV_NONE)
/* We do nothing in "None" or "Account" columns. */
if ((column_types->data[j] != GNC_CSV_NONE) && (column_types->data[j] != GNC_CSV_ACCOUNT))
{
/* Affect the transaction appropriately. */
TransProperty* property = trans_property_new(column_types->data[j], list);
gboolean succeeded = trans_property_set(property, line->pdata[j]);
/* TODO Maybe move error handling to within TransPropertyList functions? */
if (succeeded)
{

View File

@ -20,7 +20,7 @@
/** @file
@brief CSV import GUI
*
gnc-csv-import.h
gnc-csv-model.h
@author Copyright (c) 2007 Benny Sperisen <lasindi@gmail.com>
*/
@ -41,6 +41,7 @@
enum GncCsvColumnType {GNC_CSV_NONE,
GNC_CSV_DATE,
GNC_CSV_DESCRIPTION,
GNC_CSV_ACCOUNT,
GNC_CSV_BALANCE,
GNC_CSV_DEPOSIT,
GNC_CSV_WITHDRAWAL,
@ -82,8 +83,12 @@ typedef struct
gboolean balance_set; /**< TRUE if balance has been set from user data, FALSE otherwise */
} GncCsvTransLine;
extern const int num_date_formats;
/* A set of currency formats that the user sees. */
extern const int num_currency_formats;
extern const gchar* currency_format_user[];
/* A set of date formats that the user sees. */
extern const int num_date_formats;
extern const gchar* date_format_user[];
/* This array contains all of the different strings for different column types. */
@ -93,19 +98,22 @@ extern gchar* gnc_csv_column_type_strs[];
typedef struct
{
gchar* encoding;
GMappedFile* raw_mapping; /**< The mapping containing raw_str */
GncCsvStr raw_str; /**< Untouched data from the file as a string */
GncCsvStr file_str; /**< raw_str translated into UTF-8 */
GPtrArray* orig_lines; /**< file_str parsed into a two-dimensional array of strings */
GArray* orig_row_lengths; /**< The lengths of rows in orig_lines
* before error messages are appended */
int orig_max_row; /**< Holds the maximum value in orig_row_lengths */
GStringChunk* chunk; /**< A chunk of memory in which the contents of orig_lines is stored */
GMappedFile* raw_mapping; /**< The mapping containing raw_str */
GncCsvStr raw_str; /**< Untouched data from the file as a string */
GncCsvStr file_str; /**< raw_str translated into UTF-8 */
GPtrArray* orig_lines; /**< file_str parsed into a two-dimensional array of strings */
GArray* orig_row_lengths; /**< The lengths of rows in orig_lines
before error messages are appended */
int orig_max_row; /**< Holds the maximum value in orig_row_lengths */
GStringChunk* chunk; /**< A chunk of memory in which the contents of orig_lines is stored */
StfParseOptions_t* options; /**< Options controlling how file_str should be parsed */
GArray* column_types; /**< Array of values from the GncCsvColumnType enumeration */
GList* error_lines; /**< List of row numbers in orig_lines that have errors */
GList* transactions; /**< List of GncCsvTransLine*s created using orig_lines and column_types */
int date_format; /**< The format of the text in the date columns from date_format_internal. */
GArray* column_types; /**< Array of values from the GncCsvColumnType enumeration */
GList* error_lines; /**< List of row numbers in orig_lines that have errors */
GList* transactions; /**< List of GncCsvTransLine*s created using orig_lines and column_types */
int date_format; /**< The format of the text in the date columns from date_format_internal. */
int start_row; /**< The start row to generate transactions from. */
int end_row; /**< The end row to generate transactions from. */
int currency_format; /**< The currency format, 0 for locale, 1 for comma dec and 2 for period */
} GncCsvParseData;
GncCsvParseData* gnc_csv_new_parse_data(void);
@ -121,4 +129,6 @@ int gnc_csv_parse(GncCsvParseData* parse_data, gboolean guessColTypes, GError**
int gnc_csv_parse_to_trans(GncCsvParseData* parse_data, Account* account, gboolean redo_errors);
time_t parse_date(const char* date_str, int format);
#endif

View File

@ -0,0 +1,13 @@
<ui>
<menubar>
<menu name="File" action="FileAction">
<menu name="FileImport" action="FileImportAction">
<placeholder name="FileImportPlaceholder">
<menuitem name="FileCsvImportAccounts" action="CsvImportAccountAction"/>
<menuitem name="FileCsvImportTransx" action="CsvImportTransActionx"/>
<menuitem name="FileCsvImportTrans" action="CsvImportTransAction"/>
</placeholder>
</menu>
</menu>
</menubar>
</ui>

View File

@ -0,0 +1,189 @@
/*
* gnc-plugin-csv-import.c -- csv import plugin
* Copyright (C) 2011 Robert Fewell
*
* 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
*/
#include "config.h"
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include "gnc-plugin-csv-import.h"
#include "gnc-plugin-manager.h"
#include "assistant-csv-account-import.h"
#include "assistant-csv-trans-import.h"
#include "gnc-csv-import.h"
static void gnc_plugin_csv_import_class_init (GncPluginCsvImportClass *klass);
static void gnc_plugin_csv_import_init (GncPluginCsvImport *plugin);
static void gnc_plugin_csv_import_finalize (GObject *object);
/* Command callbacks */
static void gnc_plugin_csv_import_tree_cmd (GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_csv_import_trans_cmd (GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_csv_import_transx_cmd (GtkAction *action, GncMainWindowActionData *data);
#define PLUGIN_ACTIONS_NAME "gnc-plugin-csv-import-actions"
#define PLUGIN_UI_FILENAME "gnc-plugin-csv-import-ui.xml"
static GtkActionEntry gnc_plugin_actions [] =
{
{
"CsvImportAccountAction", GTK_STOCK_CONVERT, N_("Import _Accounts from CSV..."), NULL,
N_("Import Accounts from a CSV file"),
G_CALLBACK (gnc_plugin_csv_import_tree_cmd)
},
{
"CsvImportTransActionx", GTK_STOCK_CONVERT, N_("Import _CSV/Fixed-Width..."), NULL,
N_("Import Transactions from a CSV file"),
G_CALLBACK (gnc_plugin_csv_import_transx_cmd)
},
{
"CsvImportTransAction", GTK_STOCK_CONVERT, N_("Import Transactions _New from CSV..."), NULL,
N_("Import Transactions New from a CSV file"),
G_CALLBACK (gnc_plugin_csv_import_trans_cmd)
},
};
static guint gnc_plugin_n_actions = G_N_ELEMENTS (gnc_plugin_actions);
typedef struct GncPluginCsvImportPrivate
{
gpointer dummy;
} GncPluginCsvImportPrivate;
#define GNC_PLUGIN_CSV_IMPORT_GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_PLUGIN_CSV_IMPORT, GncPluginCsvImportPrivate))
static GObjectClass *parent_class = NULL;
GType
gnc_plugin_csv_import_get_type (void)
{
static GType gnc_plugin_csv_import_type = 0;
if (gnc_plugin_csv_import_type == 0)
{
static const GTypeInfo our_info =
{
sizeof (GncPluginCsvImportClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gnc_plugin_csv_import_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GncPluginCsvImport),
0, /* n_preallocs */
(GInstanceInitFunc) gnc_plugin_csv_import_init,
};
gnc_plugin_csv_import_type = g_type_register_static (GNC_TYPE_PLUGIN,
"GncPluginCsvImport",
&our_info, 0);
}
return gnc_plugin_csv_import_type;
}
GncPlugin *
gnc_plugin_csv_import_new (void)
{
return GNC_PLUGIN (g_object_new (GNC_TYPE_PLUGIN_CSV_IMPORT, NULL));
}
static void
gnc_plugin_csv_import_class_init (GncPluginCsvImportClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GncPluginClass *plugin_class = GNC_PLUGIN_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
object_class->finalize = gnc_plugin_csv_import_finalize;
/* plugin info */
plugin_class->plugin_name = GNC_PLUGIN_CSV_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;
g_type_class_add_private(klass, sizeof(GncPluginCsvImportPrivate));
}
static void
gnc_plugin_csv_import_init (GncPluginCsvImport *plugin)
{
}
static void
gnc_plugin_csv_import_finalize (GObject *object)
{
GncPluginCsvImport *plugin;
GncPluginCsvImportPrivate *priv;
g_return_if_fail (GNC_IS_PLUGIN_CSV_IMPORT (object));
plugin = GNC_PLUGIN_CSV_IMPORT (object);
priv = GNC_PLUGIN_CSV_IMPORT_GET_PRIVATE(plugin);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
/************************************************************
* Plugin Function Implementation *
************************************************************/
/************************************************************
* Command Callbacks *
************************************************************/
static void
gnc_plugin_csv_import_tree_cmd (GtkAction *action,
GncMainWindowActionData *data)
{
gnc_file_csv_account_import ();
}
static void
gnc_plugin_csv_import_trans_cmd (GtkAction *action,
GncMainWindowActionData *data)
{
gnc_file_csv_trans_import ();
}
static void
gnc_plugin_csv_import_transx_cmd (GtkAction *action,
GncMainWindowActionData *data)
{
gnc_file_csv_import();
}
/************************************************************
* Plugin Bootstrapping *
************************************************************/
void
gnc_plugin_csv_import_create_plugin (void)
{
GncPlugin *plugin = gnc_plugin_csv_import_new ();
gnc_plugin_manager_add_plugin (gnc_plugin_manager_get (), plugin);
}

View File

@ -0,0 +1,62 @@
/*
* gnc-plugin-csv-import.h -- csv import plugin
* Copyright (C) 2011 Robert Fewell
*
* 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
*/
#ifndef __GNC_PLUGIN_CSV_IMPORT_H
#define __GNC_PLUGIN_CSV_IMPORT_H
#include <gtk/gtk.h>
#include "gnc-plugin.h"
G_BEGIN_DECLS
/* type macros */
#define GNC_TYPE_PLUGIN_CSV_IMPORT (gnc_plugin_csv_import_get_type ())
#define GNC_PLUGIN_CSV_IMPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_PLUGIN_CSV_IMPORT, GncPluginCsvImport))
#define GNC_PLUGIN_CSV_IMPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_PLUGIN_CSV_IMPORT, GncPluginCsvImportClass))
#define GNC_IS_PLUGIN_CSV_IMPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_PLUGIN_CSV_IMPORT))
#define GNC_IS_PLUGIN_CSV_IMPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_PLUGIN_CSV_IMPORT))
#define GNC_PLUGIN_CSV_IMPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_PLUGIN_CSV_IMPORT, GncPluginCsvImportClass))
#define GNC_PLUGIN_CSV_IMPORT_NAME "gnc-plugin-csv-import"
/* typedefs & structures */
typedef struct
{
GncPlugin gnc_plugin;
} GncPluginCsvImport;
typedef struct
{
GncPluginClass gnc_plugin;
} GncPluginCsvImportClass;
/* function prototypes */
GType gnc_plugin_csv_import_get_type (void);
GncPlugin *gnc_plugin_csv_import_new (void);
void gnc_plugin_csv_import_create_plugin (void);
G_END_DECLS
#endif /* __GNC_PLUGIN_CSV_IMPORT_H */

View File

@ -21,7 +21,7 @@
/**@internal
@file gncmod-csv-import.c
@brief module definition/initialization for the csv importer
@author Copyright (c) 2002 Benoit Grégoire bock@step.polymtl.ca
@author Copyright (c) 2012 Robert Fewell
*/
#include "config.h"
@ -29,36 +29,35 @@
#include "gnc-module.h"
#include "gnc-module-api.h"
#include "gnc-plugin-csv.h"
#include "gnc-plugin-csv-import.h"
GNC_MODULE_API_DECL(libgncmod_csv)
GNC_MODULE_API_DECL(libgncmod_csv_import)
/* version of the gnc module system interface we require */
int libgncmod_csv_gnc_module_system_interface = 0;
int libgncmod_csv_import_gnc_module_system_interface = 0;
/* module versioning uses libtool semantics. */
int libgncmod_csv_gnc_module_current = 0;
int libgncmod_csv_gnc_module_revision = 0;
int libgncmod_csv_gnc_module_age = 0;
int libgncmod_csv_import_gnc_module_current = 0;
int libgncmod_csv_import_gnc_module_revision = 0;
int libgncmod_csv_import_gnc_module_age = 0;
//static GNCModule bus_core;
//static GNCModule file;
char *
libgncmod_csv_gnc_module_path(void)
libgncmod_csv_import_gnc_module_path(void)
{
return g_strdup("gnucash/import-export/csv");
return g_strdup("gnucash/import-export/csv-import");
}
char *
libgncmod_csv_gnc_module_description(void)
libgncmod_csv_import_gnc_module_description(void)
{
return g_strdup("Gnome GUI and C code for CSV importer using libcsv");
return g_strdup("Gnome GUI and C code for CSV importer.");
}
int
libgncmod_csv_gnc_module_init(int refcount)
libgncmod_csv_import_gnc_module_init(int refcount)
{
if (!gnc_module_load("gnucash/engine", 0))
{
@ -78,13 +77,13 @@ libgncmod_csv_gnc_module_init(int refcount)
}
/* Add menu items with C callbacks */
gnc_plugin_csv_create_plugin();
gnc_plugin_csv_import_create_plugin();
return TRUE;
}
int
libgncmod_csv_gnc_module_end(int refcount)
libgncmod_csv_import_gnc_module_end(int refcount)
{
return TRUE;
}

View File

@ -0,0 +1,21 @@
schemadir = @GCONF_SCHEMA_FILE_DIR@
schemas_in_files = \
apps_gnucash_dialog_import_csv.schemas.in
schema_DATA = $(schemas_in_files:.schemas.in=.schemas)
@INTLTOOL_SCHEMAS_RULE@
EXTRA_DIST = $(schemas_in_files)
CLEANFILES = $(schema_DATA)
install-data-local:
if GCONF_SCHEMAS_INSTALL
-mkdir -p $(DESTDIR)$(GCONF_SCHEMA_CONFIG_SOURCE_DIRONLY)
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(schema_DATA)
endif
uninstall-local:
if GCONF_SCHEMAS_INSTALL
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-uninstall-rule $(schema_DATA)
endif

View File

@ -0,0 +1,50 @@
<?xml version="1.0"?>
<gconfschemafile>
<schemalist>
<schema>
<key>/schemas/apps/gnucash/dialogs/import/csv/position</key>
<applyto>/apps/gnucash/dialogs/import/csv/window_position</applyto>
<owner>gnucash</owner>
<type>list</type>
<list_type>int</list_type>
<locale name="C">
<short>Window position</short>
<long>
The X,Y coordinates of the top left corner of the window
when it was last closed.
</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gnucash/dialogs/import/csv/geometry</key>
<applyto>/apps/gnucash/dialogs/import/csv/window_geometry</applyto>
<owner>gnucash</owner>
<type>list</type>
<list_type>int</list_type>
<locale name="C">
<short>Window geometry</short>
<long>
The width and size of the window when it was last closed.
</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gnucash/dialogs/import/csv/last_path</key>
<applyto>/apps/gnucash/dialogs/import/csv/last_path</applyto>
<owner>gnucash</owner>
<type>string</type>
<locale name="C">
<short>Last pathname used</short>
<long>
This field contains the last pathname used by this window.
It will be used as the initial filename/pathname the next
time this window is opened.
</long>
</locale>
</schema>
</schemalist>
</gconfschemafile>

View File

@ -1,11 +0,0 @@
<ui>
<menubar>
<menu name="File" action="FileAction">
<menu name="FileImport" action="FileImportAction">
<placeholder name="FileImportPlaceholder">
<menuitem name="FileCsvImport" action="CsvImportAction"/>
</placeholder>
</menu>
</menu>
</menubar>
</ui>

View File

@ -1,165 +0,0 @@
/*
* gnc-plugin-csv.c --
* Copyright (C) 2003 David Hampton <hampton@employees.org>
*
* 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
*/
#include "config.h"
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include "gnc-plugin-csv.h"
#include "gnc-plugin-manager.h"
#include "gnc-csv-import.h"
static void gnc_plugin_csv_class_init (GncPluginCsvClass *klass);
static void gnc_plugin_csv_init (GncPluginCsv *plugin);
static void gnc_plugin_csv_finalize (GObject *object);
/* Command callbacks */
static void gnc_plugin_csv_cmd_import (GtkAction *action, GncMainWindowActionData *data);
#define PLUGIN_ACTIONS_NAME "gnc-plugin-csv-actions"
#define PLUGIN_UI_FILENAME "gnc-plugin-csv-ui.xml"
static GtkActionEntry gnc_plugin_actions [] =
{
{
"CsvImportAction", GTK_STOCK_CONVERT, N_("Import _CSV/Fixed-Width..."), NULL,
N_(" a CSV/Fixed-Width file"),
G_CALLBACK (gnc_plugin_csv_cmd_import)
},
};
static guint gnc_plugin_n_actions = G_N_ELEMENTS (gnc_plugin_actions);
typedef struct GncPluginCsvPrivate
{
gpointer dummy;
} GncPluginCsvPrivate;
#define GNC_PLUGIN_CSV_GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), GNC_TYPE_PLUGIN_CSV, GncPluginCsvPrivate))
static GObjectClass *parent_class = NULL;
GType
gnc_plugin_csv_get_type (void)
{
static GType gnc_plugin_csv_type = 0;
if (gnc_plugin_csv_type == 0)
{
static const GTypeInfo our_info =
{
sizeof (GncPluginCsvClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gnc_plugin_csv_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GncPluginCsv),
0, /* n_preallocs */
(GInstanceInitFunc) gnc_plugin_csv_init,
};
gnc_plugin_csv_type = g_type_register_static (GNC_TYPE_PLUGIN,
"GncPluginCsv",
&our_info, 0);
}
return gnc_plugin_csv_type;
}
GncPlugin *
gnc_plugin_csv_new (void)
{
return GNC_PLUGIN (g_object_new (GNC_TYPE_PLUGIN_CSV, NULL));
}
static void
gnc_plugin_csv_class_init (GncPluginCsvClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GncPluginClass *plugin_class = GNC_PLUGIN_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
object_class->finalize = gnc_plugin_csv_finalize;
/* plugin info */
plugin_class->plugin_name = GNC_PLUGIN_CSV_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;
g_type_class_add_private(klass, sizeof(GncPluginCsvPrivate));
}
static void
gnc_plugin_csv_init (GncPluginCsv *plugin)
{
}
static void
gnc_plugin_csv_finalize (GObject *object)
{
GncPluginCsv *plugin;
GncPluginCsvPrivate *priv;
g_return_if_fail (GNC_IS_PLUGIN_CSV (object));
plugin = GNC_PLUGIN_CSV (object);
priv = GNC_PLUGIN_CSV_GET_PRIVATE(plugin);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
/************************************************************
* Plugin Function Implementation *
************************************************************/
/************************************************************
* Command Callbacks *
************************************************************/
static void
gnc_plugin_csv_cmd_import (GtkAction *action,
GncMainWindowActionData *data)
{
gnc_file_csv_import();
}
/************************************************************
* Plugin Bootstrapping *
************************************************************/
void
gnc_plugin_csv_create_plugin (void)
{
GncPlugin *plugin = gnc_plugin_csv_new ();
gnc_plugin_manager_add_plugin (gnc_plugin_manager_get (), plugin);
}

View File

@ -1,62 +0,0 @@
/*
* gnc-plugin-csv.h --
* Copyright (C) 2003 David Hampton <hampton@employees.org>
*
* 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
*/
#ifndef __GNC_PLUGIN_CSV_H
#define __GNC_PLUGIN_CSV_H
#include <gtk/gtk.h>
#include "gnc-plugin.h"
G_BEGIN_DECLS
/* type macros */
#define GNC_TYPE_PLUGIN_CSV (gnc_plugin_csv_get_type ())
#define GNC_PLUGIN_CSV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNC_TYPE_PLUGIN_CSV, GncPluginCsv))
#define GNC_PLUGIN_CSV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNC_TYPE_PLUGIN_CSV, GncPluginCsvClass))
#define GNC_IS_PLUGIN_CSV(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNC_TYPE_PLUGIN_CSV))
#define GNC_IS_PLUGIN_CSV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNC_TYPE_PLUGIN_CSV))
#define GNC_PLUGIN_CSV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNC_TYPE_PLUGIN_CSV, GncPluginCsvClass))
#define GNC_PLUGIN_CSV_NAME "gnc-plugin-csv"
/* typedefs & structures */
typedef struct
{
GncPlugin gnc_plugin;
} GncPluginCsv;
typedef struct
{
GncPluginClass gnc_plugin;
} GncPluginCsvClass;
/* function prototypes */
GType gnc_plugin_csv_get_type (void);
GncPlugin *gnc_plugin_csv_new (void);
void gnc_plugin_csv_create_plugin (void);
G_END_DECLS
#endif /* __GNC_PLUGIN_CSV_H */

View File

@ -1,134 +1,7 @@
<?xml version="1.0"?>
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkDialog" id="Generic Import Account Picker">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">Select Account</property>
<property name="default_width">800</property>
<property name="default_height">600</property>
<property name="type_hint">dialog</property>
<signal name="map" handler="gnc_ui_generic_account_picker_map_cb" swapped="no"/>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox8">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area8">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="newbutton">
<property name="label">gnc-new-account</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
</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">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</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="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</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="GtkLabel" id="label847715">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xpad">5</property>
<property name="ypad">3</property>
<property name="label" translatable="yes">Please select or create an appropriate GnuCash account for:</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="online_id_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xpad">5</property>
<property name="ypad">3</property>
<property name="label" translatable="yes">Online account ID here...</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="account_tree_sw">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="1">newbutton</action-widget>
<action-widget response="-6">cancelbutton</action-widget>
<action-widget response="-5">okbutton</action-widget>
</action-widgets>
</object>
<object class="GtkWindow" id="Preferences">
<property name="visible">True</property>
<property name="can_focus">False</property>
@ -454,6 +327,149 @@
</object>
</child>
</object>
<object class="GtkDialog" id="account_picker">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">Select Account</property>
<property name="default_width">800</property>
<property name="default_height">600</property>
<property name="type_hint">dialog</property>
<signal name="map" handler="gnc_ui_generic_account_picker_map_cb" swapped="no"/>
<child internal-child="vbox">
<object class="GtkVBox" id="account_picker_vbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area8">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="newbutton">
<property name="label">gnc-new-account</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
</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">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</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="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</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>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
<action-widgets>
<action-widget response="1">newbutton</action-widget>
<action-widget response="-6">cancelbutton</action-widget>
<action-widget response="-5">okbutton</action-widget>
</action-widgets>
</object>
<object class="GtkVBox" id="account_picker_content">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="label847715">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xpad">5</property>
<property name="ypad">3</property>
<property name="label" translatable="yes">Please select or create an appropriate GnuCash account for:</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="online_id_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xpad">5</property>
<property name="ypad">3</property>
<property name="label" translatable="yes">Online account ID here...</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="account_tree_sw">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<object class="GtkAdjustment" id="atm_fee_adj">
<property name="upper">1000</property>
<property name="value">2</property>
@ -1206,7 +1222,7 @@
<property name="type_hint">dialog</property>
<signal name="close" handler="on_matcher_cancel_clicked" swapped="no"/>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox10">
<object class="GtkVBox" id="transaction_matcher_vbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child internal-child="action_area">
@ -1275,56 +1291,7 @@
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="heading_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xpad">5</property>
<property name="ypad">5</property>
<property name="label" translatable="yes">List of downloaded transactions (source split shown):</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow25">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="downloaded_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="reorderable">True</property>
<property name="rules_hint">True</property>
<property name="enable_search">False</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
<placeholder/>
</child>
</object>
</child>
@ -1334,4 +1301,49 @@
<action-widget response="-11">matcher__help</action-widget>
</action-widgets>
</object>
<object class="GtkVBox" id="transaction_matcher_content">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="heading_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xpad">5</property>
<property name="ypad">5</property>
<property name="label" translatable="yes">List of downloaded transactions (source split shown):</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow25">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="downloaded_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="reorderable">True</property>
<property name="rules_hint">True</property>
<property name="enable_search">False</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</interface>

View File

@ -1,4 +1,9 @@
/********************************************************************\
* import-account-matcher.c - flexible account picker/matcher *
* *
* Copyright (C) 2002 Benoit Grégoire <bock@step.polymtl.ca> *
* Copyright (C) 2012 Robert Fewell *
* *
* 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 *
@ -42,28 +47,60 @@ static QofLogModule log_module = GNC_MOD_IMPORT;
#define GCONF_SECTION "dialogs/import/generic_matcher/account_matcher"
/*-******************************************************************\
* Structs *
\********************************************************************/
struct _accountpickerdialog
{
GtkWidget * dialog;
GncTreeViewAccount *account_tree;
GtkWidget * account_tree_sw;
const gchar * account_human_description;
const gchar * account_online_id_value;
const gnc_commodity * new_account_default_commodity;
GNCAccountType new_account_default_type;
};
/*-******************************************************************\
* Functions needed by gnc_import_select_account
*
\********************************************************************/
/** Constructor for AccountPickerDialog.
* @return Pointer to a new AccountPickerDialog
*/
static AccountPickerDialog* gnc_import_new_account_picker(void)
{
AccountPickerDialog* picker = g_new(AccountPickerDialog, 1);
picker->dialog = NULL;
picker->assistant = NULL;
picker->account_tree = NULL;
picker->account_tree_sw = NULL;
picker->auto_create = TRUE;
picker->account_human_description = NULL;
picker->account_online_id_value = NULL;
picker->account_online_id_label = NULL;
picker->new_account_default_commodity = NULL;
picker->new_account_default_type = 0;
picker->default_account = NULL;
picker->retAccount =NULL;
return picker;
}
/**************************************************
* test_acct_online_id_match
*
* test for match of kvp_frame of account
**************************************************/
static gpointer test_acct_online_id_match(Account *acct, gpointer param_online_id)
{
const gchar * current_online_id = gnc_import_get_acc_online_id(acct);
if ( (current_online_id != NULL
&& param_online_id != NULL )
&& strcmp( current_online_id, param_online_id ) == 0 )
{
return (gpointer *) acct;
}
else
{
return NULL;
}
}
/***********************************************************
* build_acct_tree
*
* build the account tree with the custome column, online_id
************************************************************/
static void
build_acct_tree(struct _accountpickerdialog * picker)
build_acct_tree(AccountPickerDialog *picker)
{
GtkTreeView *account_tree;
GtkTreeViewColumn *col;
@ -73,7 +110,6 @@ build_acct_tree(struct _accountpickerdialog * picker)
account_tree = gnc_tree_view_account_new(FALSE);
picker->account_tree = GNC_TREE_VIEW_ACCOUNT(account_tree);
gtk_tree_view_set_headers_visible (account_tree, TRUE);
col = gnc_tree_view_find_column_by_name(GNC_TREE_VIEW(account_tree), "type");
g_object_set_data(G_OBJECT(col), DEFAULT_VISIBLE, GINT_TO_POINTER(1));
@ -93,14 +129,18 @@ build_acct_tree(struct _accountpickerdialog * picker)
(gchar*) NULL);
}
/* When user clicks to create a new account */
/*******************************************************
* gnc_import_add_account
*
* Callback for when user clicks to create a new account
*******************************************************/
static void
gnc_import_add_account(struct _accountpickerdialog * picker)
gnc_import_add_account(GtkWidget *button, AccountPickerDialog *picker)
{
Account *selected_account, *new_account;
GList * valid_types = NULL;
/*DEBUG("Begin"); */
if (picker->new_account_default_type != ACCT_TYPE_NONE)
{
/*Yes, this is weird, but we really DO want to pass the value instead of the pointer...*/
@ -115,32 +155,72 @@ gnc_import_add_account(struct _accountpickerdialog * picker)
gnc_tree_view_account_set_selected_account(picker->account_tree, new_account);
}
/* When user double-clicks an account */
/*******************************************************
* account_tree_row_activated_cb
*
* Callback for when user double clicks on an account
*******************************************************/
static void
account_tree_row_activated_cb(GtkTreeView *view, GtkTreePath *path,
GtkTreeViewColumn *column,
struct _accountpickerdialog *picker)
AccountPickerDialog *picker)
{
g_return_if_fail(picker && picker->dialog);
const gchar *retval_name = NULL;
Account *old_id_acc;
gtk_dialog_response(GTK_DIALOG(picker->dialog), GTK_RESPONSE_OK);
}
static gpointer test_acct_online_id_match(Account *acct, gpointer param_online_id)
{
const gchar * current_online_id = gnc_import_get_acc_online_id(acct);
if ( (current_online_id != NULL
&& param_online_id != NULL )
&& strcmp( current_online_id, param_online_id ) == 0 )
/* See if we have a dialog, if not we are an assistant */
if(picker->dialog == NULL)
{
return (gpointer *) acct;
GtkAssistant *assistant = GTK_ASSISTANT(picker->assistant);
gint num = gtk_assistant_get_current_page (assistant);
GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
picker->retAccount = gnc_tree_view_account_get_selected_account(picker->account_tree);
if (picker->retAccount)
retval_name = xaccAccountGetName(picker->retAccount);
if (!retval_name)
retval_name = "(null)";
DEBUG("Selected account %p, %s", picker->retAccount, retval_name);
/* See if the selected account is a placeholder. */
if (picker->retAccount && xaccAccountGetPlaceholder (picker->retAccount))
{
gnc_error_dialog (picker->dialog,
_("The account %s is a placeholder account and does not allow "
"transactions. Please choose a different account."),
retval_name);
}
else if ( picker->account_online_id_value != NULL)
{
/* find the old account for this on line id value and reset it */
old_id_acc =
gnc_account_foreach_descendant_until(gnc_get_current_root_account (),
test_acct_online_id_match,
/* This argument will only be used as a "const char*" */
(void*)picker->account_online_id_value);
if(old_id_acc != NULL)
gnc_import_set_acc_online_id(old_id_acc, "");
gnc_import_set_acc_online_id(picker->retAccount, picker->account_online_id_value);
gtk_assistant_set_page_complete (assistant, page, TRUE);
}
else
gtk_assistant_set_page_complete (assistant, page, TRUE);
}
else
{
return NULL;
gtk_dialog_response(GTK_DIALOG(picker->dialog), GTK_RESPONSE_OK);
}
}
/*******************************************************
* gnc_import_select_account
*
* Main call for use with a dialog
*******************************************************/
Account * gnc_import_select_account(GtkWidget *parent,
const gchar * account_online_id_value,
gboolean auto_create,
@ -151,18 +231,18 @@ Account * gnc_import_select_account(GtkWidget *parent,
gboolean * ok_pressed)
{
#define ACCOUNT_DESCRIPTION_MAX_SIZE 255
struct _accountpickerdialog * picker;
AccountPickerDialog * picker;
gint response;
Account * retval = NULL;
const gchar *retval_name = NULL;
GtkBuilder *builder;
GtkWidget * online_id_label, *button;
GtkWidget * online_id_label, *button, *box, *pbox;
gchar account_description_text[ACCOUNT_DESCRIPTION_MAX_SIZE] = "";
gboolean ok_pressed_retval = FALSE;
ENTER("Default commodity received: %s", gnc_commodity_get_fullname( new_account_default_commodity));
DEBUG("Default account type received: %s", xaccAccountGetTypeStr( new_account_default_type));
picker = g_new0(struct _accountpickerdialog, 1);
picker = g_new0(AccountPickerDialog, 1);
picker->account_online_id_value = account_online_id_value;
picker->account_human_description = account_human_description;
@ -175,25 +255,30 @@ Account * gnc_import_select_account(GtkWidget *parent,
retval =
gnc_account_foreach_descendant_until(gnc_get_current_root_account (),
test_acct_online_id_match,
/* This argument will only be
used as a "const char*" */
/* This argument will only be used as a "const char*" */
(void*)account_online_id_value);
}
if (retval == NULL && auto_create != 0)
{
/* load the interface */
builder = gtk_builder_new();
gnc_builder_add_from_file (builder,"dialog-import.glade", "Generic Import Account Picker");
gnc_builder_add_from_file (builder,"dialog-import.glade", "account_picker");
gnc_builder_add_from_file (builder,"dialog-import.glade", "account_picker_content");
/* connect the signals in the interface */
if (builder == NULL)
{
PERR("Error opening the glade builder interface");
}
picker->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "Generic Import Account Picker"));
picker->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker"));
if (parent)
gtk_window_set_transient_for (GTK_WINDOW (picker->dialog),
GTK_WINDOW (parent));
/* Pack the content into the dialog vbox */
pbox = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker_vbox"));
box = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker_content"));
gtk_box_pack_start( GTK_BOX(pbox), box, TRUE, TRUE,0);
picker->account_tree_sw = GTK_WIDGET(gtk_builder_get_object (builder, "account_tree_sw"));
online_id_label = GTK_WIDGET(gtk_builder_get_object (builder, "online_id_label"));
button = GTK_WIDGET(gtk_builder_get_object (builder, "newbutton"));
@ -256,7 +341,7 @@ Account * gnc_import_select_account(GtkWidget *parent,
ok_pressed_retval = TRUE;
break;
case GNC_RESPONSE_NEW:
gnc_import_add_account(picker);
gnc_import_add_account(NULL, picker);
ok_pressed_retval = TRUE;
break;
default:
@ -284,4 +369,115 @@ Account * gnc_import_select_account(GtkWidget *parent,
LEAVE("Selected account %p, %s", retval, retval_name ? retval_name : "(null)");
return retval;
}
/**********************************************************************
* These are the routines for use with an Assistant page
**********************************************************************/
/*******************************************************
* gnc_import_account_assist_setup
*
* Main call for page setup in an assistant
*******************************************************/
AccountPickerDialog* gnc_import_account_assist_setup(GtkWidget *parent)
{
AccountPickerDialog * picker;
GtkBuilder *builder;
GtkWidget *button, *box;
/* Init the account picker structure */
picker = gnc_import_new_account_picker();
/* load the interface */
builder = gtk_builder_new();
gnc_builder_add_from_file (builder,"dialog-import.glade", "account_picker_content");
/* connect the signals in the interface */
if (builder == NULL)
{
PERR("Error opening the glade builder interface");
}
picker->assistant = gtk_widget_get_parent(parent);
/* Pack content into Assistant page widget */
box = GTK_WIDGET(gtk_builder_get_object (builder, "account_picker_content"));
gtk_box_pack_start( GTK_BOX(parent), box, TRUE, TRUE, 6);
picker->account_tree_sw = GTK_WIDGET(gtk_builder_get_object (builder, "account_tree_sw"));
picker->account_online_id_label = GTK_WIDGET(gtk_builder_get_object (builder, "online_id_label"));
/* Add the New Account Button */
button = gtk_button_new_with_mnemonic ("_New Account");
gtk_box_pack_start( GTK_BOX(box), button, FALSE, FALSE, 6);
gtk_button_set_use_stock (GTK_BUTTON(button), TRUE);
gtk_widget_show (button);
g_signal_connect(button, "clicked",
G_CALLBACK(gnc_import_add_account), picker);
build_acct_tree(picker);
g_signal_connect(picker->account_tree, "row-activated",
G_CALLBACK(account_tree_row_activated_cb), picker);
g_object_unref(G_OBJECT(builder));
return picker;
}
/*******************************************************
* gnc_import_account_assist_update
*
* updates the page and returns account found.
*******************************************************/
Account * gnc_import_account_assist_update (AccountPickerDialog *picker)
{
#define ACCOUNT_DESCRIPTION_MAX_SIZE 255
const gchar *retval_name = NULL;
gchar account_description_text[ACCOUNT_DESCRIPTION_MAX_SIZE] = "";
ENTER("Default commodity received: %s", gnc_commodity_get_fullname( picker->new_account_default_commodity));
DEBUG("Default account type received: %s", xaccAccountGetTypeStr( picker->new_account_default_type));
/*DEBUG("Looking for account with online_id: %s", picker->account_online_id_value);*/
if (picker->account_online_id_value != NULL)
{
picker->retAccount =
gnc_account_foreach_descendant_until(gnc_get_current_root_account (),
test_acct_online_id_match,
/* This argument will only be used as a "const char*" */
(void*)picker->account_online_id_value);
}
if (picker->account_human_description != NULL)
{
strncat(account_description_text, picker->account_human_description,
ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
strncat(account_description_text, "\n",
ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
}
if (picker->account_online_id_value != NULL)
{
strncat(account_description_text, _("(Full account ID: "),
ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
strncat(account_description_text, picker->account_online_id_value,
ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
strncat(account_description_text, ")",
ACCOUNT_DESCRIPTION_MAX_SIZE - strlen(account_description_text));
}
gtk_label_set_text(GTK_LABEL( picker->account_online_id_label), account_description_text);
if(picker->default_account == NULL)
gnc_tree_view_account_set_selected_account(picker->account_tree, picker->retAccount);
else
gnc_tree_view_account_set_selected_account(picker->account_tree, picker->default_account);
/*FIXME: DEBUG("WRITEME: Here we should check if an account type is compatible, currency matches, etc.\n"); */
/*DEBUG("Return value: %p%s%s%s",picker->retAccount,", account name:",xaccAccountGetName(picker->retAccount),"\n");*/
retval_name = picker->retAccount ? xaccAccountGetName(picker->retAccount) : NULL;
LEAVE("Selected account %p, %s", picker->retAccount, retval_name ? retval_name : "(null)");
return picker->retAccount;
}
/**@}*/

View File

@ -1,4 +1,9 @@
/********************************************************************\
* import-account-matcher.h - flexible account picker/matcher *
* *
* Copyright (C) 2002 Benoit Grégoire <bock@step.polymtl.ca> *
* Copyright (C) 2012 Robert Fewell *
* *
* 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 *
@ -22,12 +27,30 @@
@brief Generic and very flexible account matcher/picker
@author Copyright (C) 2002 Benoit Grégoire <bock@step.polymtl.ca>
*/
#ifndef ACCOUNT_MATCHER_H
#define ACCOUNT_MATCHER_H
#ifndef IMPORT_ACCOUNT_MATCHER_H
#define IMPORT_ACCOUNT_MATCHER_H
#include "Account.h"
#include <gtk/gtk.h>
#include "gnc-tree-view-account.h"
typedef struct
{
GtkWidget *dialog; /* Dialog Widget */
GtkWidget *assistant; /* assistant Widget */
GncTreeViewAccount *account_tree; /* Account tree */
GtkWidget *account_tree_sw; /* Scroll Window for Account tree */
gboolean auto_create; /* Auto create retAccount, can be used to step over this stage */
const gchar *account_human_description; /* description for on line id, incoming */
const gchar *account_online_id_value; /* On line id value, incoming */
GtkWidget *account_online_id_label; /* the label Widget for the on line id, incoming */
const gnc_commodity *new_account_default_commodity; /* new account default commodity, incoming */
GNCAccountType new_account_default_type; /* new account default type, incoming */
Account *default_account; /* default account for selection, incoming */
Account *retAccount; /* Account value returned to caller */
}AccountPickerDialog;
/** Must be called with a string containing a unique identifier for the
account. If an account with a matching online_id kvp_frame is
found, the function immediately returns with a pointer to that
@ -99,5 +122,29 @@ Account * gnc_import_select_account(GtkWidget *parent,
gboolean * ok_pressed
);
/** Must be called with the parent widget, ie. a vbox that the
account picker dialog will be packed into. The data structure
AccountPickerDialog is initialised and default values populated.
@param parent The parent widget. This is the place the account picker dialog will
be packed into.
@return A pointer to the AccountPickerDialog which has been setup.
*/
AccountPickerDialog * gnc_import_account_assist_setup (GtkWidget *parent);
/** Must be called with an AccountPickerDialog structure allready setup.
If an account with a matching online_id kvp_frame is found, which is
allready present in the dialog structure, the function returns with a
pointer to that account or NULL if not found.
@param Account picker Dialog structure, AccountPickerDialog
@return A pointer to the found account, or NULL if account not found.
*/
Account * gnc_import_account_assist_update (AccountPickerDialog *picker);
#endif
/**@}*/

View File

@ -1,4 +1,11 @@
/********************************************************************\
* import-main-matcher.c - Transaction matcher main window *
* *
* Copyright (C) 2002 Benoit Grégoire <bock@step.polymtl.ca> *
* Copyright (C) 2002 Christian Stimming *
* Copyright (c) 2006 David Hampton <hampton@employees.org> *
* Copyright (C) 2012 Robert Fewell *
* *
* 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 *
@ -47,6 +54,7 @@
struct _main_matcher_info
{
GtkWidget *dialog;
GtkWidget *assistant;
GtkTreeView *view;
GNCImportSettings *user_settings;
GdkColor color_back_red;
@ -125,9 +133,15 @@ void gnc_gen_trans_list_delete (GNCImportMainMatcher *info)
while (gtk_tree_model_iter_next (model, &iter));
}
gnc_save_window_size(GCONF_SECTION, GTK_WINDOW(info->dialog));
gnc_import_Settings_delete (info->user_settings);
gtk_widget_destroy (GTK_WIDGET (info->dialog));
if(!(info->dialog == NULL))
{
gnc_save_window_size(GCONF_SECTION, GTK_WINDOW(info->dialog));
gnc_import_Settings_delete (info->user_settings);
gtk_widget_destroy (GTK_WIDGET (info->dialog));
}
else
gnc_import_Settings_delete (info->user_settings);
g_free (info);
}
@ -533,7 +547,7 @@ GNCImportMainMatcher *gnc_gen_trans_list_new (GtkWidget *parent,
GNCImportMainMatcher *info;
GtkBuilder *builder;
GtkWidget *heading_label;
GtkWidget *button;
GtkWidget *button, *box, *pbox;
gboolean show_update;
info = g_new0 (GNCImportMainMatcher, 1);
@ -545,9 +559,16 @@ GNCImportMainMatcher *gnc_gen_trans_list_new (GtkWidget *parent,
/* Initialize the GtkDialog. */
builder = gtk_builder_new();
gnc_builder_add_from_file (builder, "dialog-import.glade", "transaction_matcher");
gnc_builder_add_from_file (builder, "dialog-import.glade", "transaction_matcher_content");
info->dialog = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher"));
g_assert (info->dialog != NULL);
/* Pack the content into the dialog vbox */
pbox = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher_vbox"));
box = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher_content"));
gtk_box_pack_start( GTK_BOX(pbox), box, TRUE, TRUE,0);
/* Get the view */
info->view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "downloaded_view"));
g_assert (info->view != NULL);
@ -581,6 +602,74 @@ GNCImportMainMatcher *gnc_gen_trans_list_new (GtkWidget *parent,
return info;
}
/*****************************************************************
* Assistant routines Start *
*****************************************************************/
GNCImportMainMatcher * gnc_gen_trans_assist_new (GtkWidget *parent,
const gchar* heading,
gboolean all_from_same_account,
gint match_date_hardlimit)
{
GNCImportMainMatcher *info;
GtkBuilder *builder;
GtkWidget *heading_label;
GtkWidget *button, *box, *pbox;
gboolean show_update;
info = g_new0 (GNCImportMainMatcher, 1);
/* Initialize user Settings. */
info->user_settings = gnc_import_Settings_new ();
gnc_import_Settings_set_match_date_hardlimit (info->user_settings, match_date_hardlimit);
/* load the interface */
builder = gtk_builder_new();
gnc_builder_add_from_file (builder, "dialog-import.glade", "transaction_matcher_content");
if (builder == NULL)
{
PERR("Error opening the glade builder interface");
}
/* Pack content into Assistant page widget */
box = GTK_WIDGET(gtk_builder_get_object (builder, "transaction_matcher_content"));
gtk_box_pack_start( GTK_BOX(parent), box, TRUE, TRUE, 6);
/* Get the view */
info->view = GTK_TREE_VIEW(gtk_builder_get_object (builder, "downloaded_view"));
g_assert (info->view != NULL);
show_update = gnc_import_Settings_get_action_update_enabled(info->user_settings);
gnc_gen_trans_init_view(info, all_from_same_account, show_update);
heading_label = GTK_WIDGET(gtk_builder_get_object (builder, "heading_label"));
g_assert (heading_label != NULL);
/*Initialise the colors */
gdk_color_parse(COLOR_RED, &info->color_back_red);
gdk_color_parse(COLOR_YELLOW, &info->color_back_yellow);
gdk_color_parse(COLOR_GREEN, &info->color_back_green);
if (heading)
gtk_label_set_text (GTK_LABEL (heading_label), heading);
info->transaction_processed_cb = NULL;
/* Connect the signals */
gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, info);
g_object_unref(G_OBJECT(builder));
return info;
}
void gnc_gen_trans_assist_start (GNCImportMainMatcher *info)
{
on_matcher_ok_clicked (NULL, info);
}
/*****************************************************************
* Assistant routines End *
*****************************************************************/
void gnc_gen_trans_list_add_tp_cb(GNCImportMainMatcher *info,
GNCTransactionProcessedCB trans_processed_cb,
gpointer user_data)
@ -589,7 +678,6 @@ void gnc_gen_trans_list_add_tp_cb(GNCImportMainMatcher *info,
info->transaction_processed_cb = trans_processed_cb;
}
gboolean gnc_gen_trans_list_run (GNCImportMainMatcher *info)
{
gboolean result;
@ -604,7 +692,6 @@ gboolean gnc_gen_trans_list_run (GNCImportMainMatcher *info)
return result;
}
static void
refresh_model_row (GNCImportMainMatcher *gui,
GtkTreeModel *model,
@ -817,7 +904,6 @@ refresh_model_row (GNCImportMainMatcher *gui,
gtk_tree_selection_unselect_all(selection);
}
void gnc_gen_trans_list_add_trans(GNCImportMainMatcher *gui, Transaction *trans)
{
gnc_gen_trans_list_add_trans_with_ref_id(gui, trans, 0);

View File

@ -1,4 +1,10 @@
/********************************************************************\
* import-main-matcher.h - Transaction matcher main window *
* *
* Copyright (C) 2002 Benoit Grégoire <bock@step.polymtl.ca> *
* Copyright (C) 2002 Christian Stimming *
* Copyright (C) 2012 Robert Fewell *
* *
* 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 *
@ -55,12 +61,66 @@ typedef void (*GNCTransactionProcessedCB) (GNCImportTransInfo *trans_info,
* values like 14 (days) might be appropriate, whereas for use cases
* with paper checks (e.g. OFX, QIF), values like 42 (days) seem more
* appropriate.
*
* @return A pointer to the GNCImportMainMatcher which has been setup.
*/
GNCImportMainMatcher *gnc_gen_trans_list_new (GtkWidget *parent,
const gchar* heading,
gboolean all_from_same_account,
gint match_date_hardlimit);
/** Add the Transaction matcher to an existing page of an assistant.
* Must be called with the parent widget, ie. a vbox that the
* transaction matcher will be packed into. The data structure
* GNCImportMainMatcher is returned.
*
* @param parent The parent widget. This is the place the transaction
* matcher will be packed into.
*
* @param heading The heading label in the Importer window. May be NULL.
*
* @param all_from_same_account Set this to TRUE if ALL the
* transaction that will be added with gnc_gen_trans_list_add_trans
* are from the same source account. This will cause the account
* column to be hidden.
*
* @param match_date_hardlimit The number of days that a matching
* split may differ from the given transaction before it is discarded
* immediately. In other words, any split that is more distant from
* the given transaction than this match_date_hardlimit days will be
* ignored altogether. For use cases without paper checks (e.g. HBCI),
* values like 14 (days) might be appropriate, whereas for use cases
* with paper checks (e.g. OFX, QIF), values like 42 (days) seem more
* appropriate.
*
* @return A pointer to the GNCImportMainMatcher which has been setup.
*/
GNCImportMainMatcher * gnc_gen_trans_assist_new (GtkWidget *parent,
const gchar* heading,
gboolean all_from_same_account,
gint match_date_hardlimit);
/** This starts the import process for transaction from an assistant.
* assistant button callback.
*
* @param info. A pointer to a the GNCImportMainMatcher structure.
*/
void gnc_gen_trans_assist_start (GNCImportMainMatcher *info);
/** This allows for the transaction help dialog to be started from the
* assistant button callback.
*
* @param button. The button widget clicked on in the call back.
*
* @param user_data. A pointer to a structure.
*/
void on_matcher_help_clicked (GtkButton *button, gpointer user_data);
/** Add transaction processed callback to the transaction importer.
*
* @param info The Transaction Importer to use.
@ -71,10 +131,12 @@ void gnc_gen_trans_list_add_tp_cb(GNCImportMainMatcher *info,
GNCTransactionProcessedCB trans_processed_cb,
gpointer user_data);
/** Deletes the given object. */
void gnc_gen_trans_list_delete (GNCImportMainMatcher *info);
/** Add a newly imported Transaction to the Transaction Importer. The Importer takes over ownership of the passed transaction.
/** Add a newly imported Transaction to the Transaction Importer.
* The Importer takes over ownership of the passed transaction.
*
* @param gui The Transaction Importer to use.
*
@ -86,6 +148,7 @@ void gnc_gen_trans_list_delete (GNCImportMainMatcher *info);
*/
void gnc_gen_trans_list_add_trans(GNCImportMainMatcher *gui, Transaction *trans);
/** Add a newly imported Transaction to the Transaction Importer and provide an
* external reference id for it.
* The Importer takes over ownership of the passed transaction.
@ -102,12 +165,14 @@ void gnc_gen_trans_list_add_trans(GNCImportMainMatcher *gui, Transaction *trans)
*/
void gnc_gen_trans_list_add_trans_with_ref_id(GNCImportMainMatcher *gui, Transaction *trans, guint32 ref_id);
/** Run this dialog and return only after the user pressed Ok, Cancel,
or closed the window. This means that all actual importing will
have been finished upon returning.
*/
gboolean gnc_gen_trans_list_run (GNCImportMainMatcher *info);
/** Returns the widget of this dialog.
*/
GtkWidget *gnc_gen_trans_list_widget (GNCImportMainMatcher *info);