Initial support for OFX import.

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@6987 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
David Hampton
2002-06-21 00:46:36 +00:00
parent 42d3d079b6
commit 412aeab1cb
24 changed files with 1693 additions and 5 deletions

View File

@@ -1,3 +1,11 @@
2002-06-20 David Hampton <hampton@employees.org>
* src/engine/Transaction.[ch]: New function
* src/import-export/<blah>:
* src/import-export/ofx/<blah>: Benoit Gregoire's initial support
for OFX import.
2002-06-18 Joshua Sled <jsled@asynchronous.org>
* src/gnome-utils/gnc-dense-cal.[ch]: Added; a multiply-markable,

View File

@@ -412,7 +412,13 @@ AC_ARG_ENABLE( rpc,
AC_SUBST(RPC_DIR)
### --------------------------------------------------------------------------
### OFX
AC_ARG_ENABLE( ofx,
[ --enable-ofx compile with ofx support],
OFX_DIR=ofx)
AC_SUBST(OFX_DIR)
### --------------------------------------------------------------------------
### i18n
@@ -921,12 +927,15 @@ AC_OUTPUT( m4/Makefile intl/Makefile
src/gnome-utils/test/Makefile
src/gnome-search/Makefile
src/import-export/Makefile
src/import-export/test/Makefile
src/import-export/binary-import/Makefile
src/import-export/binary-import/test/Makefile
src/import-export/qif-import/Makefile
src/import-export/qif-import/test/Makefile
src/import-export/qif-io-core/Makefile
src/import-export/qif-io-core/test/Makefile
src/import-export/ofx/Makefile
src/import-export/ofx/test/Makefile
src/import-export/hbci/Makefile
src/import-export/hbci/test/Makefile
src/network-utils/Makefile

View File

@@ -20,9 +20,9 @@ GUI_SUBDIRS_1 = \
app-file
GUI_SUBDIRS_2 = \
import-export \
dialog-account \
register \
import-export \
gnome \
experimental \
business \

View File

@@ -2419,6 +2419,12 @@ xaccTransSetDateSecs (Transaction *trans, time_t secs)
xaccTransSetDateInternal(trans, TDATE_POSTED, secs, 0);
}
void
xaccTransSetDatePostedSecs (Transaction *trans, time_t secs)
{
xaccTransSetDateInternal(trans, TDATE_POSTED, secs, 0);
}
void
xaccTransSetDateEnteredSecs (Transaction *trans, time_t secs)
{

View File

@@ -159,6 +159,7 @@ void xaccTransSetSlots_nc(Transaction *t, kvp_frame *frm);
void xaccTransSetDate (Transaction *trans,
int day, int mon, int year);
void xaccTransSetDateSecs (Transaction *trans, time_t time);
void xaccTransSetDatePostedSecs (Transaction *trans, time_t time);
void xaccTransSetDatePostedTS (Transaction *trans,
const Timespec *ts);

View File

@@ -1,4 +1,6 @@
*.la
*.lo
.deps
.libs
Makefile
Makefile.in
*.lo
*.la

View File

@@ -1,4 +1,58 @@
SUBDIRS = binary-import qif-import
SUBDIRS = . binary-import qif-import ${OFX_DIR} test
pkglib_LTLIBRARIES=libgncmod-generic-import.la
libgncmod_generic_import_la_SOURCES = \
gnc-generic-import.c
noinst_HEADERS = \
gnc-generic-import.h
libgncmod_generic_import_la_LDFLAGS = -module
libgncmod_generic_import_la_LIBADD = \
${top_builddir}/src/gnome-utils/libgncmod-gnome-utils.la \
${top_builddir}/src/app-file/libgncmod-app-file.la \
${top_builddir}/src/gnc-module/libgncmodule.la \
${top_builddir}/src/engine/libgncmod-engine.la \
${top_builddir}/src/dialog-account/libdialog-account.la \
${top_builddir}/src/register/ledger-core/libgncmod-ledger-core.la \
${GLADE_LIBS} \
${GLIB_LIBS}
gladedir = ${GNC_GLADE_DIR}
glade_DATA = generic-import.glade
AM_CFLAGS = \
-I${top_srcdir}/src \
-I${top_srcdir}/src/engine \
-I${top_srcdir}/src/gnc-module \
-I${top_srcdir}/src/app-utils \
-I${top_srcdir}/src/app-file \
-I${top_srcdir}/src/gnome \
-I${top_srcdir}/src/gnome-utils \
-I${top_srcdir}/src/dialog-account \
${G_WRAP_COMPILE_ARGS} \
${GLIB_CFLAGS} \
${GLADE_CFLAGS} \
${GDK_PIXBUF_CFLAGS} \
${GTKHTML_CFLAGS}
EXTRA_DIST = \
.cvsignore
CLEANFILES =
#noinst_DATA = .scm-links
#.scm-links:
# rm -f g-wrapped gnucash import-export qif-import
# ln -sf . qif-import # to fix (load "qif-import/foo.scm")
# ln -sf . import-export
# ln -sf . gnucash
# ln -sf . g-wrapped
# touch .scm-links
CLEANFILES += generic-import import-export gnucash g-wrapped .scm-links
# FIXME remove this when qif-io-core is finished
DIST_SUBDIRS = binary-import qif-import qif-io-core
DIST_SUBDIRS = binary-import qif-import qif-io-core ofx

View File

@@ -0,0 +1,69 @@
This a draft a design proposal for a generic import architecture. The objective is to maximize code sharing between the QIF, HBCI and OFX modules.
The most important area of potential code sharing is the account and transaction matching code. This code has 3 distinct roles:
-Find the source account.
-Find and eliminate transaction downloaded twice in the source account.
-Find the destination account(s), and find the matching tansactions(s) if it/they exist(s).
The Online System specific, in addition to any steps necessary for obtaining and processing the data, should be responsible for:
-Identifying and if necessary creating the source account: The account is identified using the account number for ofx and HBCI, and the account description for qif, if available. The account number or identifier is stored in a kvp_string with key account_online_id. The online system can use and format this frame however it sees fit, but it must be a kvp_string. A function:
const char * gnc_import_get_acc_online_id(Account * account)
is provided for searching. If no account is found with a matching online_id, the function:
Account * gnc_import_select_account(char * account_online_id_value)
must be called. The user can then select an existing account from a list (the current account_online_id are displayed alongside the accounts), or create a new one. The account_online_id is then stored in the selected or created account's kvp_frame.
-Creating transaction and adding the source split (associated with the source account, possibly created above), and filling it with as much information as it has as it's disposal (much info is available for ofx, little for qif). If a unique transaction id is available from the online system, is is stored in the splits kvp_frame, using key transaction_online_id. No transaction matching is done at this stage.
The generic module receives the Transaction for the online system specific module using function:
void gnc_import_add_trans(Transaction *trans);
(We do not use GUID, because in all cases, the transaction was just created)
The functions defines the following enum:
enum gnc_match_probability{
CERTAIN,
PROBABLE,
LIKELY,
POSSIBLE,
UNLIKELY,
IMPOSSIBLE
}
Here is the pseudocode of the gnc_import_add_trans function:
Variables: matches (a list of possible match with likelyhood)
split_to_match = trans's first split.
In split_to_match's parent account; for each split where date >= split_to_match.date - 2 months:
if transaction_online_id match
add to matches using CERTAIN
if preferences dictate: end search here
if amount match
if transaction_online_id exists but doesn't match
add to matches using UNLIKELY (not IMPOSSIBLE, could be protocol change or prior error)
eles if memo match and date within 4 days
add to matches using PROBABLE
else if date within 24 hours
add to matches using LIKELY
else if date within 10 days
add to matches using POSSIBLE
else
add to matches using UNLIKELY
Present the list of matches to the user in decreasing order of likelyhood. User has the option of selecting one of the match or creating a new transaction.
Add transaction_online_id to selected split
Erase from other CERTAIN splits
if transaction not balanced
TODO: gnc_balance_transaction(Transaction *trans)
commit changes
return
gnc_balance_transaction((Transaction *trans) add's or matches other splits until the transaction is balanced, using whatever user interaction and heuristics are appropriate. Since I haven't really used gnucash's current transaction matching before, I would like someone else to contribute the description of the process to match unbalanced transactions.
Remarks and things to remember:
-Credit card transactions cans sometimes appear over a month after the purchase (clerk lost the paper, international transaction not always fast, etc.)
-void gnc_import_add_trans(Transaction *trans) should return as soon as possible (BEFORE user interaction) so that for systems that maintain a connection (such as HBCI) the user won't run into timeouts. For example, gnc_import_add_trans could check if it's main dialog is open, and open it if it isn't, add to the list and return immediately. The dialog is closed automatically once the list is empty.
-We may want to implement the function in such a way that it won't match any transaction that have been added as part of the current import process (flag them volatile or something). This will solve the problems of multiple interac withdrawals in the same day for QIF, (possibly HBCI too?).
-The transaction passed to gnc_import_add_trans will have only one split for OFX and HBCI, but 1 or more for QIF.

View File

@@ -0,0 +1,220 @@
<?xml version="1.0"?>
<GTK-Interface>
<project>
<name>generic-import</name>
<program_name>Gnucash</program_name>
<directory></directory>
<source_directory></source_directory>
<pixmaps_directory></pixmaps_directory>
<language>C</language>
<gnome_support>True</gnome_support>
<gettext_support>True</gettext_support>
<output_main_file>False</output_main_file>
<backup_source_files>False</backup_source_files>
</project>
<widget>
<class>GnomeDialog</class>
<name>Generic Import Account Picker</name>
<signal>
<name>map</name>
<handler>gnc_ui_generic_account_picker_map_cb</handler>
<last_modification_time>Fri, 07 Jun 2002 17:35:27 GMT</last_modification_time>
</signal>
<title>Select Account</title>
<type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_NONE</position>
<modal>False</modal>
<default_width>600</default_width>
<default_height>400</default_height>
<allow_shrink>True</allow_shrink>
<allow_grow>True</allow_grow>
<auto_shrink>True</auto_shrink>
<auto_close>False</auto_close>
<hide_on_close>False</hide_on_close>
<widget>
<class>GtkVBox</class>
<child_name>GnomeDialog:vbox</child_name>
<name>vbox1</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>1</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkHButtonBox</class>
<child_name>GnomeDialog:action_area</child_name>
<name>hbuttonbox1</name>
<layout_style>GTK_BUTTONBOX_SPREAD</layout_style>
<spacing>8</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
<pack>GTK_PACK_END</pack>
</child>
<widget>
<class>GtkButton</class>
<name>button1</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button2</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
</widget>
</widget>
<widget>
<class>GtkLabel</class>
<name>label847715</name>
<label>The following online account is unknown:</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>online_id_label</name>
<label>Online account ID here...</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>True</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkFrame</class>
<name>frame1</name>
<label>Please select or create matching Gnucash account:</label>
<label_xalign>0</label_xalign>
<shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkScrolledWindow</class>
<name>scrolledwindow24</name>
<hscrollbar_policy>GTK_POLICY_AUTOMATIC</hscrollbar_policy>
<vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
<hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
<vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
<widget>
<class>GtkCTree</class>
<name>account_tree</name>
<can_focus>True</can_focus>
<signal>
<name>tree_select_row</name>
<handler>gnc_ui_generic_account_picker_select_cb</handler>
<last_modification_time>Fri, 07 Jun 2002 17:33:51 GMT</last_modification_time>
</signal>
<signal>
<name>tree_unselect_row</name>
<handler>gnc_ui_generic_account_picker_unselect_cb</handler>
<last_modification_time>Fri, 07 Jun 2002 17:34:00 GMT</last_modification_time>
</signal>
<columns>3</columns>
<column_widths>215,48,80</column_widths>
<selection_mode>GTK_SELECTION_SINGLE</selection_mode>
<show_titles>True</show_titles>
<shadow_type>GTK_SHADOW_IN</shadow_type>
<widget>
<class>GtkLabel</class>
<child_name>CTree:title</child_name>
<name>label847711</name>
<label>Account</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>CTree:title</child_name>
<name>label847712</name>
<label>Type</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>CTree:title</child_name>
<name>label847713</name>
<label>Online ID</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
</widget>
</widget>
</widget>
<widget>
<class>GtkButton</class>
<name>button78</name>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>gnc_ui_generic_account_picker_new_cb</handler>
<data>QIF_Import_Account_Picker</data>
<last_modification_time>Fri, 07 Jun 2002 17:30:20 GMT</last_modification_time>
</signal>
<label>New Account (child of selected) ...</label>
<relief>GTK_RELIEF_NORMAL</relief>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
</widget>
</widget>
</GTK-Interface>

View File

@@ -0,0 +1,364 @@
/********************************************************************\
* generic-import.c -- Functions and utilities to help writing *
* import modules. See file generic-import-design.txt for *
* description *
* (GnuCash) *
* Copyright (C) 2002 Benoit Gr<47>goire <bock@step.polymtl.ca> *
* *
* 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 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
\********************************************************************/
#define _GNU_SOURCE
#include "config.h"
#include <glib.h>
#include <gmodule.h>
//#include <gtk/gtk.h>
#include <glade/glade.h>
#include "gnc-generic-import.h"
#include "Account.h"
#include "Transaction.h"
#include "dialog-commodity.h"
#include "dialog-utils.h"
#include "AccWindow.h"
//#include "druid-utils.h"
//#include "global-options.h"
//#include "gnc-component-manager.h"
//#include "gnc-engine-util.h"
//#include "gnc-file-dialog.h"
//#include "gnc-gui-query.h"
#include "gnc-ui-util.h"
//#include "gnc-ui.h"
//#include "messages.h"
//#include "window-help.h"
//#include <g-wrap-wct.h>
struct _accountpickerdialog {
GtkWidget * dialog;
GtkWidget * treeview;
AccountGroup * acct_group;
Account * selected_acct;
};
/* static gint
test_str_cmp(gconstpointer a, gconstpointer b) {
return strcmp(a, b);
}*/
/********************************************************************\
* Functions needed by gnc_import_select_account
*
\********************************************************************/
static void acct_tree_add_accts(AccountGroup * accts, GtkCTree * tree, GtkCTreeNode * parent)
{
GtkCTreeNode * node;
Account *current_acct;
guint i;
gchar * acctinfo[3];
for(i=0;i<xaccGroupGetNumAccounts(accts);i++)
{
current_acct = xaccGroupGetAccount(accts, i);
acctinfo[0]=(gchar *)xaccAccountGetName(current_acct);
acctinfo[1]=g_strdup(xaccAccountGetTypeStr(xaccAccountGetType(current_acct)));
acctinfo[2]=gnc_import_get_acc_online_id(current_acct);
//printf("acct_tree_add_acct(): %s%s",xaccAccountGetName(current_acct),"\n");
node = gtk_ctree_insert_node (tree,
parent,
NULL,
acctinfo,
2,
NULL,NULL,NULL,NULL,
FALSE,//isleaf
FALSE);
gtk_ctree_node_set_row_data (tree,
node,
current_acct);
acct_tree_add_accts(xaccAccountGetChildren(current_acct), tree, node);
}
}
static void
build_acct_tree(struct _accountpickerdialog * picker) {
GtkCTreeNode * new_sel;
//printf("build_acct_tree(): Start\n");
if(picker->acct_group==NULL)
{
printf("build_acct_tree():Error: acct_group is NULL\n");
}
gtk_clist_clear(GTK_CLIST(picker->treeview));
gtk_clist_set_column_justification (GTK_CLIST(picker->treeview),
1, GTK_JUSTIFY_CENTER);
acct_tree_add_accts(picker->acct_group, GTK_CTREE(picker->treeview), NULL);
if(picker->selected_acct!=NULL) {
new_sel = gtk_ctree_find_by_row_data(GTK_CTREE(picker->treeview),
NULL,
picker->selected_acct);
gtk_ctree_select(GTK_CTREE(picker->treeview), new_sel);
gtk_ctree_node_moveto(GTK_CTREE(picker->treeview), new_sel, 0,
0.5, 0.0);
}
gtk_clist_columns_autosize (GTK_CLIST (picker->treeview));
gtk_clist_column_titles_passive (GTK_CLIST (picker->treeview));
}
/*static void
new_child_string_cb(char * string, gpointer data) {
printf("new_child_string_cb(char * string, gpointer data)\n");
if(string) {
strncpy(data, string, 250);
}
else {
*(char *)data = 0;
}
}*/
/* When user clicks to create a new account */
static void
gnc_ui_generic_account_picker_new_cb(GtkButton * w, gpointer user_data) {
struct _accountpickerdialog * picker = user_data;
// printf(" gnc_ui_generic_account_picker_new_cb():Start\n");
printf("WRITEME: gnc_ui_generic_account_picker_new_cb() Write a more flexible function in dialog-account.c and AccWindow.h to fill in defaults\n");
picker->selected_acct = gnc_ui_new_accounts_from_name_window_with_types("New OFX account", NULL);
printf("WRITEME: gnc_ui_generic_account_picker_new_cb() Here we should check if account type is compatible, currency matches, etc.\n");
build_acct_tree(picker);
}
static void
gnc_ui_generic_account_picker_select_cb(GtkCTree * tree,
GtkCTreeNode * node,
gint column,
gpointer user_data) {
struct _accountpickerdialog * picker = user_data;
//printf("gnc_ui_generic_account_picker_select_cb()\n");
gtk_ctree_node_get_row_data(tree, node);
picker->selected_acct = gtk_ctree_node_get_row_data(tree, node);
}
/*Will be called when unselection an account, or when the user clicks cancel*/
static void
gnc_ui_generic_account_picker_unselect_cb(GtkCTree * tree,
GtkCTreeNode * node,
gint column,
gpointer user_data) {
struct _accountpickerdialog * picker = user_data;
//printf("gnc_ui_generic_account_picker_unselect_cb()\n");
picker->selected_acct = NULL;
}
static int
gnc_ui_generic_account_picker_map_cb(GtkWidget * w, gpointer user_data) {
printf("gnc_ui_generic_account_picker_map_cb()\n");
/* update the tree display */
build_acct_tree(user_data);
return FALSE;
}
static gpointer test_acct_online_id_match(Account *acct, gpointer param_online_id)
{
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;
}
}
Account * gnc_import_select_account(char * account_online_id_value)
{
struct _accountpickerdialog * picker = g_new0(struct _accountpickerdialog, 1);
gint ui_retval;
Account * retval = NULL;
GladeXML *xml;
GtkWidget * online_id_label;
picker->acct_group = gnc_get_current_group();
if(picker->acct_group == NULL)
{
printf("WARNING:gnc_import_select_account(): The account group is NULL\n");
}
//printf("gnc_import_select_account(): Looking for account with online_id: %s%s", account_online_id_value ,"\n");
retval = xaccGroupForEachAccount(picker->acct_group,
test_acct_online_id_match,
account_online_id_value,
TRUE);
if(retval==NULL)
{
/* load the interface */
xml = gnc_glade_xml_new ("generic-import.glade", "Generic Import Account Picker");
/* connect the signals in the interface */
if(xml==NULL)
{
printf("gnc_import_select_account(): Error opening the glade interface\n");
}
glade_xml_signal_connect_data(xml, "gnc_ui_generic_account_picker_new_cb", GTK_SIGNAL_FUNC (gnc_ui_generic_account_picker_new_cb), picker);
glade_xml_signal_connect_data(xml, "gnc_ui_generic_account_picker_select_cb", GTK_SIGNAL_FUNC(gnc_ui_generic_account_picker_select_cb), picker);
glade_xml_signal_connect_data(xml, "gnc_ui_generic_account_picker_unselect_cb", GTK_SIGNAL_FUNC(gnc_ui_generic_account_picker_unselect_cb), picker);
glade_xml_signal_connect_data(xml, "gnc_ui_generic_account_picker_map_cb", GTK_SIGNAL_FUNC(gnc_ui_generic_account_picker_map_cb), picker);
picker->dialog = glade_xml_get_widget (xml, "Generic Import Account Picker");
picker->treeview = glade_xml_get_widget (xml, "account_tree");
online_id_label = glade_xml_get_widget (xml, "online_id_label");
//printf("gnc_import_select_account(): Fin get widget\n");
gtk_label_set_text((GtkLabel*)online_id_label, account_online_id_value);
build_acct_tree(picker);
ui_retval = gnome_dialog_run_and_close(GNOME_DIALOG(picker->dialog));
if(ui_retval == 0) {
gnc_import_set_acc_online_id(picker->selected_acct, account_online_id_value);
retval=picker->selected_acct;
}
else {
retval=NULL;
}
}
g_free(picker);
// printf("gnc_import_select_account(): Return value: %p%s%s%s",retval,", account name:",xaccAccountGetName(retval),"\n");
return retval;
}
/********************************************************************\
* Setter and getter functions for the online_id kvp frame in
* Account and Transaction
\********************************************************************/
gchar * gnc_import_get_acc_online_id(Account * account)
{
gchar * string = NULL;
kvp_frame * frame;
kvp_value * value;
frame = xaccAccountGetSlots(account);
value = kvp_frame_get_slot(frame, "online_id");
string = kvp_value_get_string(value);
return string;
}
void gnc_import_set_acc_online_id(Account * account, gchar * string_value)
{
kvp_frame * frame;
kvp_value * value;
frame = xaccAccountGetSlots(account);
if(frame==NULL)
{
printf("gnc_import_set_acc_online_id():The kvp_frame was NULL, allocating new one\n");
frame = kvp_frame_new();
}
value = kvp_frame_get_slot(frame, "online_id");
//kvp_value_delete(value);
value = kvp_value_new_string(string_value);
kvp_frame_set_slot(frame,"online_id",value);
xaccAccountSetSlots_nc(account,frame);
return;
}
gchar * gnc_import_get_trans_online_id(Transaction * transaction)
{
gchar * string = NULL;
kvp_frame * frame;
kvp_value * value;
frame = xaccTransGetSlots(transaction);
value = kvp_frame_get_slot(frame, "online_id");
string = kvp_value_get_string(value);
return string;
}
void gnc_import_set_trans_online_id(Transaction * transaction, gchar * string_value)
{
kvp_frame * frame;
kvp_value * value;
printf("gnc_import_set_acc_online_id(): Start\n");
frame = xaccTransGetSlots(transaction);
if(frame==NULL)
{
printf("gnc_import_set_trans_online_id():The kvp_frame was NULL, allocating new one\n");
frame = kvp_frame_new();
}
value = kvp_frame_get_slot(frame, "online_id");
if(value != NULL)
{
kvp_value_delete(value);
}
value = kvp_value_new_string(string_value);
kvp_frame_set_slot(frame,"online_id",value);
xaccTransSetSlots_nc(transaction,frame);
return;
}
/********************************************************************\
* Functions used by gnc_import_add_trans(Transaction *trans)
\********************************************************************/
/********************************************************************\
* check_trans_online_id() Weird function, to be used by
* xaccAccountForEachTransaction. Takes to pointers to two
* and return TRUE if their online_id kvp_frame do NOT match or
* if both pointers point to the same transaction
\********************************************************************/
static gboolean check_trans_online_id(Transaction *trans1, void *trans2)
{
gchar * online_id1 = gnc_import_get_trans_online_id(trans1);
gchar * online_id2 = gnc_import_get_trans_online_id((Transaction *)trans2);
if(trans1==(Transaction *)trans2||strcmp(online_id1, online_id2)!=0)
{
return TRUE;
}
else
{
//printf("test_trans_online_id(): Duplicate found\n");
return FALSE;
}
}
void gnc_import_add_trans(Transaction *trans)
{
gint i;
Split * source_split;
Account * dest_acct;
gboolean trans_not_found=TRUE;
/*For each split in the transaction, check if the parent account contains a transaction with the same online id */
for(i=0;(source_split=xaccTransGetSplit(trans,i))!=NULL&&(trans_not_found==TRUE);i++)
{
printf("gnc_import_add_trans():Checking split %d%s",i," for duplicates\n");
dest_acct=xaccSplitGetAccount(source_split);
trans_not_found = xaccAccountForEachTransaction(dest_acct,
check_trans_online_id,
trans);
}
if(trans_not_found==FALSE)
{
printf("gnc_import_add_trans(): Transaction with same online ID exists, destroying current transaction\n");
xaccTransBeginEdit(trans);
xaccTransDestroy(trans);
xaccTransCommitEdit(trans);
}
return;
}

View File

@@ -0,0 +1,70 @@
/********************************************************************\
* generic-import.h -- Functions and utilities to help writing *
* import modules. See file generic-import-design.txt for *
* description *
* (GnuCash) *
* Copyright (C) 2002 Benoit Gr<47>goire <bock@step.polymtl.ca> *
* *
* 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 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
\********************************************************************/
#ifndef GENERIC_IMPORT_H
#define GENERIC_IMPORT_H
#include "Account.h"
/* The gnc_import_select_account() method should 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 account. Otherwise, the user is prompted to
select a GnuCash account or create a new one.
In both cases, the unique identifier is written to the account's
kvp_frame, so the user won't be prompted again.
*/
Account * gnc_import_select_account(char * account_online_id_value);
/* Your import module should create a new transaction in the current book,
add as many splits as it knows about, and associate each split with an
account. It should then call gnc_import_add_trans() with that transaction
if a transaction with the same online_id kvp_frame exists in any of the
transaction's split's accounts, the transaction will be destroyed.
Otherwise it will be added.
Not yet implemented: GUI to balance the transaction using heuristics
*/
void gnc_import_add_trans(Transaction *trans);
/* Setter and getter functions for the online_id kvp_frame for
Accounts and Transactions.
*/
gchar * gnc_import_get_acc_online_id(Account * account);
void gnc_import_set_acc_online_id(Account * account, gchar * string_value);
gchar * gnc_import_get_trans_online_id(Transaction * transaction);
void gnc_import_set_trans_online_id(Transaction * transaction, gchar * string_value);
typedef enum _gnc_match_probability{
CERTAIN,
PROBABLE,
LIKELY,
POSSIBLE,
UNLIKELY,
IMPOSSIBLE
} GNC_match_probability;
#endif

View File

@@ -0,0 +1,59 @@
/*********************************************************************
* gncmod-generic-import.c
* module definition/initialization for the generic import
* infrastructure
*
* Copyright (c) 2002 Benoit Gr<47>goire bock@step.polymtl.ca
*********************************************************************/
#include <glib.h>
#include <guile/gh.h>
#include "gnc-module.h"
#include "gnc-module-api.h"
/* version of the gnc module system interface we require */
int gnc_module_system_interface = 0;
/* module versioning uses libtool semantics. */
int gnc_module_current = 0;
int gnc_module_revision = 0;
int gnc_module_age = 0;
char *
gnc_module_path(void)
{
return g_strdup("gnucash/import-export");
}
char *
gnc_module_description(void)
{
return g_strdup("Gnome GUI and C code for the generic import functions");
}
int
gnc_module_init(int refcount)
{
if(!gnc_module_load("gnucash/engine", 0))
{
return FALSE;
}
if(!gnc_module_load("gnucash/app-utils", 0))
{
return FALSE;
}
if(!gnc_module_load("gnucash/gnome-utils", 0))
{
return FALSE;
}
if(!gnc_module_load("gnucash/import-export", 0))
{
return FALSE;
}
gh_eval_str("(use-modules (gnucash import-export))");
printf("Generic import module loaded\n");
return TRUE;
}
int
gnc_module_end(int refcount)
{
return TRUE;
}

View File

@@ -0,0 +1,6 @@
*.lo
*.la
.deps
.libs
Makefile
Makefile.in

View File

@@ -0,0 +1,38 @@
SUBDIRS = . test
pkglib_LTLIBRARIES=libgncmod-ofx.la
libgncmod_ofx_la_SOURCES = \
gnc-ofx-import.c \
gncmod-ofx-import.c
noinst_HEADERS = \
gnc-ofx-import.h
libgncmod_ofx_la_LDFLAGS = -module
libgncmod_ofx_la_LIBADD = \
${top_builddir}/src/gnc-module/libgncmodule.la \
${top_builddir}/src/engine/libgncmod-engine.la \
${top_builddir}/src/import-export/libgncmod-generic-import.la \
${GLIB_LIBS} \
-lofx -lstdc++
#gladedir = ${GNC_GLADE_DIR}
#glade_DATA = ofx.glade
AM_CFLAGS = \
-I${top_srcdir}/src \
-I${top_srcdir}/src/engine \
-I${top_srcdir}/src/gnc-module \
-I${top_srcdir}/src/app-utils \
-I${top_srcdir}/src/app-file \
-I${top_srcdir}/src/gnome \
-I${top_srcdir}/src/gnome-utils \
-I${top_srcdir}/src/import-export \
${GLIB_CFLAGS}
EXTRA_DIST = \
.cvsignore
CLEANFILES = ofx import-export gnucash g-wrapped .scm-links

View File

@@ -0,0 +1,286 @@
/********************************************************************\
* ofx-import.c -- OFX files import *
* (GnuCash) *
* Copyright (C) 2002 Benoit Gr<47>goire <bock@step.polymtl.ca> *
* *
* 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 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
\********************************************************************/
#define _GNU_SOURCE
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <glib.h>
#include <gmodule.h>
#include "libofx.h"
#include "gnc-generic-import.h"
#include "Account.h"
#include "Transaction.h"
#include "gnc-ofx-import.h"
#include "gnc-file-dialog.h"
/********************************************************************\
* gnc_file_ofx_import
* Entry point
\********************************************************************/
void gnc_file_ofx_import (void)
{
extern int ofx_PARSER_msg;
extern int ofx_DEBUG_msg;
extern int ofx_WARNING_msg;
extern int ofx_ERROR_msg;
extern int ofx_INFO_msg;
extern int ofx_STATUS_msg;
char *filenames[3];
char file[255] = "/home/bock/pfe/scratch/stmtrs_spec201.xml";
ofx_PARSER_msg = false;
ofx_DEBUG_msg = false;
ofx_WARNING_msg = true;
ofx_ERROR_msg = true;
ofx_INFO_msg = true;
ofx_STATUS_msg = false;
/* if (gnc_forall_gui_components (DRUID_QIF_IMPORT_CM_CLASS,
show_handler, NULL))
return;*/
/* pop up the QIF File Import dialog box */
/*gnc_ui_qif_import_druid_make();*/
printf("gnc_file_ofx_import(): Begin...\n");
strncpy(file,gnc_file_dialog ("Select an OFX/QFX file to process",
NULL,
NULL), 255);
filenames[0]=NULL;
filenames[1]=file;
filenames[2]=NULL;
ofx_proc_file(2, filenames);
}
int ofx_proc_status(struct OfxStatusData data)
{
return 0;
}
int ofx_proc_transaction(struct OfxTransactionData data)
{
char dest_string[255];
time_t current_time;
Account *account;
GNCBook *book;
Transaction *transaction;
Split *split;
gchar *notes, *tmp;
gnc_numeric gnc_amount;
if(data.account_id_valid==true){
account = gnc_import_select_account(data.account_id);
if(account!=NULL)
{
book = xaccAccountGetBook(account);
transaction = xaccMallocTransaction(book);
xaccTransBeginEdit(transaction);
if(data.fi_id_valid==true){
gnc_import_set_trans_online_id(transaction, data.fi_id);
}
if(data.date_initiated_valid==true){
xaccTransSetDateSecs(transaction, data.date_initiated);
}
else if(data.date_posted_valid==true){
xaccTransSetDateSecs(transaction, data.date_posted);
}
if(data.date_posted_valid==true){
xaccTransSetDatePostedSecs(transaction, data.date_posted);
}
current_time = time(NULL);
xaccTransSetDateEnteredSecs(transaction, mktime(localtime(&current_time)));
if(data.check_number_valid==true){
xaccTransSetNum(transaction, data.check_number);
}
else if(data.reference_number_valid==true){
xaccTransSetNum(transaction, data.reference_number);
}
/* Put the transaction name in Description, or memo if name is unavailable */
if(data.name_valid==true){
xaccTransSetDescription(transaction, data.name);
}
else if(data.memo_valid==true){
xaccTransSetDescription(transaction, data.memo);
}
/* Put everything else in the Notes field */
notes=g_strdup_printf("OFX ext. info: ");
if(data.transactiontype_valid==true){
switch(data.transactiontype){
case OFX_CREDIT: strncpy(dest_string, "Generic credit", sizeof(dest_string));
break;
case OFX_DEBIT: strncpy(dest_string, "Generic debit", sizeof(dest_string));
break;
case OFX_INT: strncpy(dest_string, "Interest earned or paid (Note: Depends on signage of amount)", sizeof(dest_string));
break;
case OFX_DIV: strncpy(dest_string, "Dividend", sizeof(dest_string));
break;
case OFX_FEE: strncpy(dest_string, "FI fee", sizeof(dest_string));
break;
case OFX_SRVCHG: strncpy(dest_string, "Service charge", sizeof(dest_string));
break;
case OFX_DEP: strncpy(dest_string, "Deposit", sizeof(dest_string));
break;
case OFX_ATM: strncpy(dest_string, "ATM debit or credit (Note: Depends on signage of amount)", sizeof(dest_string));
break;
case OFX_POS: strncpy(dest_string, "Point of sale debit or credit (Note: Depends on signage of amount)", sizeof(dest_string));
break;
case OFX_XFER: strncpy(dest_string, "Transfer", sizeof(dest_string));
break;
case OFX_CHECK: strncpy(dest_string, "Check", sizeof(dest_string));
break;
case OFX_PAYMENT: strncpy(dest_string, "Electronic payment", sizeof(dest_string));
break;
case OFX_CASH: strncpy(dest_string, "Cash withdrawal", sizeof(dest_string));
break;
case OFX_DIRECTDEP: strncpy(dest_string, "Direct deposit", sizeof(dest_string));
break;
case OFX_DIRECTDEBIT: strncpy(dest_string, "Merchant initiated debit", sizeof(dest_string));
break;
case OFX_REPEATPMT: strncpy(dest_string, "Repeating payment/standing order", sizeof(dest_string));
break;
case OFX_OTHER: strncpy(dest_string, "Other", sizeof(dest_string));
break;
default : strncpy(dest_string, "Unknown transaction type", sizeof(dest_string));
break;
}
tmp=notes;
notes=g_strdup_printf("%s%s%s",tmp,"|Trans type:", dest_string);
g_free(tmp);
}
printf("Label ok\n");
if(data.memo_valid==true){
tmp=notes;
notes=g_strdup_printf("%s%s%s",tmp, "|Memo:", data.memo);
g_free(tmp);
}
if(data.date_funds_available_valid==true){
strftime(dest_string,sizeof(dest_string),"%c %Z",localtime(&(data.date_funds_available)));
tmp=notes;
notes=g_strdup_printf("%s%s%s",tmp,"|Date funds available:", dest_string);
g_free(tmp);
}
if(data.server_transaction_id_valid==true){
tmp=notes;
notes=g_strdup_printf("%s%s%s",tmp, "|Server trans ID (conf. number):", data.server_transaction_id);
g_free(tmp);
}
if(data.standard_industrial_code_valid==true){
tmp=notes;
notes=g_strdup_printf("%s%s%ld",tmp, "|Standard Industrial Code:",data.standard_industrial_code);
g_free(tmp);
}
if(data.payee_id_valid==true){
tmp=notes;
notes=g_strdup_printf("%s%s%s",tmp,"|Payee ID:", data.payee_id);
g_free(tmp);
}
/*Add PAYEE and ADRESS here once supported by libofx*/
/* Ideally, gnucash should process the corrected transactions */
if(data.fi_id_corrected_valid==true){
printf("WRITEME: Gnucash ofx_proc_transaction(): This transaction corrected a previous transaction, but we created a new one instead!\n");
tmp=notes;
notes=g_strdup_printf("%s%s%s%s",tmp,"|This corrects transaction #",data.fi_id_corrected,"but Gnucash didn't process the correction!");
g_free(tmp);
}
xaccTransSetNotes(transaction, notes);
g_free(notes);
if(data.amount_valid==true){
split=xaccMallocSplit(book);
xaccTransAppendSplit(transaction,split);
xaccAccountInsertSplit(account,split);
gnc_amount = double_to_gnc_numeric(data.amount,xaccAccountGetCommoditySCU(account),GNC_RND_ROUND);
xaccSplitSetValue(split, gnc_amount);
}
xaccTransCommitEdit(transaction);
//printf("Now calling gnc_import_add_trans()\n");
gnc_import_add_trans(transaction);
}
else
{
printf("Gnucash: ofx_proc_transaction(): Unable to find the account!\n");
}
}
else
{
printf("Gnucash: ofx_proc_transaction(): account ID for this transaction is unavailable!\n");
}
return 0;
}//end ofx_proc_transaction()
int ofx_proc_statement(struct OfxStatementData data)
{
return 0;
}//end ofx_proc_statement()
int ofx_proc_account(struct OfxAccountData data)
{
Account *selected_account;
if(data.account_id_valid==true){
//printf("ofx_proc_account() Now calling gnc_import_select_account()\n");
selected_account = gnc_import_select_account(data.account_id);
}
else
{
printf("Gnucash ofx_proc_account():FATAL ERROR' account online ID not available\n");
}
/* if(data.account_type_valid==true){
switch(data.account_type){
case OFX_CHECKING : printf("!Type:Bank\n");
break;
case OFX_SAVINGS : printf("!Type:Bank\n");
break;
case OFX_MONEYMRKT : printf("!Type:Oth A\n");
break;
case OFX_CREDITLINE : printf("!Type:Oth L\n");
break;
case OFX_CMA : printf("!Type:Oth A\n");
break;
case OFX_CREDITCARD : printf("!Type:CCard\n");
break;
default: printf("WRITEME: ofx_proc_account() This is an unknown account type!");
}
}*/
return 0;
}

View File

@@ -0,0 +1,34 @@
/********************************************************************\
* gnc-ofx-import.h -- OFX file import *
* (GnuCash) *
* Copyright (C) 2002 Benoit Gr<47>goire <bock@step.polymtl.ca> *
* *
* 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 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
\********************************************************************/
#ifndef OFX_IMPORT_H
#define OFX_IMPORT_H
/* The gnc_file_ofx_import() routine will pop up a standard file
* selection dialogue asking the user to pick a OFX/QFX file. If one
* is selected the the OFX file is opened and read. It's contents
* are merged into the existing session (if any). The current
* session continues to remain open for editing. */
void gnc_file_ofx_import (void);
#endif

View File

@@ -0,0 +1,58 @@
/*********************************************************************
* gncmod-ofx-import.c
* module definition/initialization for ofx importer
*
* Copyright (c) 2002 Benoit Gr<47>goire bock@step.polymtl.ca
*********************************************************************/
#include <glib.h>
#include <guile/gh.h>
#include "gnc-module.h"
#include "gnc-module-api.h"
/* version of the gnc module system interface we require */
int gnc_module_system_interface = 0;
/* module versioning uses libtool semantics. */
int gnc_module_current = 0;
int gnc_module_revision = 0;
int gnc_module_age = 0;
char *
gnc_module_path(void)
{
return g_strdup("gnucash/import-export/ofx");
}
char *
gnc_module_description(void)
{
return g_strdup("Gnome GUI and C code for OFX importer using libofx");
}
int
gnc_module_init(int refcount)
{
if(!gnc_module_load("gnucash/engine", 0))
{
return FALSE;
}
if(!gnc_module_load("gnucash/app-utils", 0))
{
return FALSE;
}
if(!gnc_module_load("gnucash/gnome-utils", 0))
{
return FALSE;
}
if(!gnc_module_load("gnucash/import-export", 0))
{
return FALSE;
}
gh_eval_str("(use-modules (gnucash import-export ofx))");
printf("OFX module loaded\n");
return TRUE;
}
int
gnc_module_end(int refcount)
{
return TRUE;
}

View File

@@ -0,0 +1,368 @@
<?xml version="1.0"?>
<GTK-Interface>
<project>
<name>OFX import</name>
<program_name>ofx-import</program_name>
<directory></directory>
<source_directory></source_directory>
<pixmaps_directory></pixmaps_directory>
<language>C</language>
<gnome_support>True</gnome_support>
<gettext_support>True</gettext_support>
<output_main_file>False</output_main_file>
<output_support_files>False</output_support_files>
<output_build_files>False</output_build_files>
<backup_source_files>False</backup_source_files>
</project>
<widget>
<class>GtkWindow</class>
<name>OFX Import Druid</name>
<title>OFX Import</title>
<type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_NONE</position>
<modal>False</modal>
<allow_shrink>False</allow_shrink>
<allow_grow>True</allow_grow>
<auto_shrink>True</auto_shrink>
<widget>
<class>GnomeDruid</class>
<name>ofx_import_druid</name>
<signal>
<name>cancel</name>
<handler>gnc_ui_ofx_import_cancel_cb</handler>
<data>OFX_Import_Druid</data>
<last_modification_time>Wed, 30 Aug 2000 15:11:02 GMT</last_modification_time>
</signal>
<widget>
<class>GnomeDruidPageStart</class>
<name>start_page</name>
<signal>
<name>next</name>
<handler>gnc_ui_ofx_import_generic_next_cb</handler>
<data>OFX_Import_Druid</data>
<last_modification_time>Tue, 06 Feb 2001 17:04:30 GMT</last_modification_time>
</signal>
<title>Import OFX files</title>
<text>GnuCash can import financial data from OFX (Quicken
Interchange Format) files written by Quicken/QuickBooks,
MS Money, Moneydance, and many other programs.
The import process has several steps. Your GnuCash
accounts will not be changed until you click &quot;Finish&quot;
at the end of the process.
Click &quot;Next&quot; to start loading your OFX data, or &quot;Cancel&quot;
to abort the process. </text>
<title_color>255,255,255</title_color>
<text_color>0,0,0</text_color>
<background_color>153,191,153</background_color>
<logo_background_color>255,255,255</logo_background_color>
<textbox_color>255,255,255</textbox_color>
</widget>
<widget>
<class>GnomeDruidPageStandard</class>
<name>load_file_page</name>
<signal>
<name>next</name>
<handler>gnc_ui_ofx_import_load_file_next_cb</handler>
<data>OFX_Import_Druid</data>
<last_modification_time>Wed, 30 Aug 2000 14:30:37 GMT</last_modification_time>
</signal>
<signal>
<name>back</name>
<handler>gnc_ui_ofx_import_generic_back_cb</handler>
<data>OFX_Import_Druid</data>
<last_modification_time>Tue, 06 Feb 2001 17:05:58 GMT</last_modification_time>
</signal>
<title>Select a OFX file to load</title>
<title_color>255,255,255</title_color>
<background_color>153,191,154</background_color>
<logo_background_color>255,255,255</logo_background_color>
<widget>
<class>GtkVBox</class>
<child_name>GnomeDruidPageStandard:vbox</child_name>
<name>druid-vbox8</name>
<border_width>25</border_width>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label822</name>
<label>Please select a file to load. When you click &quot;Next&quot;, the file will be loaded
and analyzed. You may need to answer some questions about the account(s)
in the file.
You will have the opportunity to load as many files as you wish, so don't
worry if your data is in multiple files.
</label>
<justify>GTK_JUSTIFY_LEFT</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>5</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox69</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label821</name>
<label>OFX Filename:</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>1</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>4</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>ofx_filename_entry</name>
<can_default>True</can_default>
<has_default>True</has_default>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkButton</class>
<name>button71</name>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>gnc_ui_ofx_import_select_file_cb</handler>
<data>OFX_Import_Druid</data>
<last_modification_time>Wed, 30 Aug 2000 17:33:50 GMT</last_modification_time>
</signal>
<label>Select...</label>
<relief>GTK_RELIEF_NORMAL</relief>
<child>
<padding>3</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
</widget>
</widget>
</widget>
<widget>
<class>GnomeDruidPageStandard</class>
<name>loaded_files_page</name>
<signal>
<name>prepare</name>
<handler>gnc_ui_ofx_import_loaded_files_prepare_cb</handler>
<data>OFX_Import_Druid</data>
<last_modification_time>Wed, 30 Aug 2000 22:42:22 GMT</last_modification_time>
</signal>
<signal>
<name>next</name>
<handler>gnc_ui_ofx_import_generic_next_cb</handler>
<data>OFX_Import_Druid</data>
<last_modification_time>Fri, 09 Feb 2001 17:04:25 GMT</last_modification_time>
</signal>
<signal>
<name>back</name>
<handler>gnc_ui_ofx_import_generic_back_cb</handler>
<data>OFX_Import_Druid</data>
<last_modification_time>Tue, 06 Feb 2001 17:08:05 GMT</last_modification_time>
</signal>
<title>OFX files you have loaded</title>
<title_color>255,255,255</title_color>
<background_color>153,191,153</background_color>
<logo_background_color>255,255,255</logo_background_color>
<widget>
<class>GtkVBox</class>
<child_name>GnomeDruidPageStandard:vbox</child_name>
<name>druid-vbox1</name>
<border_width>25</border_width>
<homogeneous>False</homogeneous>
<spacing>4</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkFrame</class>
<name>frame33</name>
<label>OFX Files</label>
<label_xalign>0</label_xalign>
<shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkScrolledWindow</class>
<name>scrolledwindow10</name>
<hscrollbar_policy>GTK_POLICY_ALWAYS</hscrollbar_policy>
<vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
<hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
<vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
<widget>
<class>GtkCList</class>
<name>selected_file_list</name>
<can_focus>True</can_focus>
<signal>
<name>select_row</name>
<handler>gnc_ui_ofx_import_select_loaded_file_cb</handler>
<data>OFX_Import_Druid</data>
<last_modification_time>Wed, 30 Aug 2000 23:00:57 GMT</last_modification_time>
</signal>
<columns>1</columns>
<column_widths>80</column_widths>
<selection_mode>GTK_SELECTION_SINGLE</selection_mode>
<show_titles>False</show_titles>
<shadow_type>GTK_SHADOW_IN</shadow_type>
<widget>
<class>GtkLabel</class>
<child_name>CList:title</child_name>
<name>label827</name>
<label>label827</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
</widget>
</widget>
</widget>
<widget>
<class>GtkLabel</class>
<name>label816</name>
<label>Click &quot;Load another file&quot; if you have more data to import at this time.
Do this if you have saved your accounts to separate OFX files.
Click &quot;Next&quot; to finish loading files and move to the next step
of the OFX import process. </label>
<justify>GTK_JUSTIFY_LEFT</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>3</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox68</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkButton</class>
<name>button69</name>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>gnc_ui_ofx_import_load_another_cb</handler>
<data>OFX_Import_Druid</data>
<last_modification_time>Wed, 30 Aug 2000 15:32:12 GMT</last_modification_time>
</signal>
<label>Load another file</label>
<relief>GTK_RELIEF_NORMAL</relief>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkButton</class>
<name>button70</name>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>gnc_ui_ofx_import_unload_file_cb</handler>
<data>OFX_Import_Druid</data>
<last_modification_time>Wed, 30 Aug 2000 15:34:33 GMT</last_modification_time>
</signal>
<label>Unload selected file</label>
<relief>GTK_RELIEF_NORMAL</relief>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
</widget>
</widget>
</widget>
<widget>
<class>GnomeDruidPageFinish</class>
<name>druidpagefinish1</name>
<title></title>
<text>OFX import complete</text>
<background_color>153,191,153</background_color>
<logo_background_color>255,255,255</logo_background_color>
<textbox_color>255,255,255</textbox_color>
<text_color>0,0,0</text_color>
<title_color>255,255,255</title_color>
</widget>
</widget>
</widget>
</GTK-Interface>

View File

@@ -0,0 +1,5 @@
.deps
.libs
Makefile
Makefile.in
test-link

View File

@@ -0,0 +1,6 @@
TESTS=test-link
noinst_PROGRAMS=test-link
test_link_SOURCES=test-link.c
test_link_LDADD=../libgncmod-ofx.la

View File

@@ -0,0 +1,6 @@
int
main(int argc, char ** argv)
{
return 0;
}

View File

@@ -0,0 +1,7 @@
*.la
*.lo
.deps
.libs
Makefile
Makefile.in
test-link

View File

@@ -0,0 +1,6 @@
TESTS=test-link
noinst_PROGRAMS=test-link
test_link_SOURCES=test-link.c
test_link_LDADD=../libgncmod-generic-import.la

View File

@@ -0,0 +1,6 @@
int
main(int argc, char ** argv)
{
return 0;
}