mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Merge Jean Laroche's branch 'add_multi_ofx_import_master' PR 697 to master
This commit is contained in:
commit
2dcc0b7a19
@ -60,29 +60,15 @@ static QofLogModule log_module = GNC_MOD_GUI;
|
||||
static GNCShutdownCB shutdown_cb = NULL;
|
||||
static gint save_in_progress = 0;
|
||||
|
||||
|
||||
/********************************************************************\
|
||||
* gnc_file_dialog *
|
||||
* Pops up a file selection dialog (either a "Save As" or an *
|
||||
* "Open"), and returns the name of the file the user selected. *
|
||||
* (This function does not return until the user selects a file *
|
||||
* or presses "Cancel" or the window manager destroy button) *
|
||||
* *
|
||||
* Args: title - the title of the window *
|
||||
* filters - list of GtkFileFilters to use, will be *
|
||||
freed automatically *
|
||||
* default_dir - start the chooser in this directory *
|
||||
* type - what type of dialog (open, save, etc.) *
|
||||
* Return: containing the name of the file the user selected *
|
||||
\********************************************************************/
|
||||
|
||||
char *
|
||||
gnc_file_dialog (GtkWindow *parent,
|
||||
const char * title,
|
||||
GList * filters,
|
||||
const char * starting_dir,
|
||||
GNCFileDialogType type
|
||||
)
|
||||
// gnc_file_dialog_int is used both by gnc_file_dialog and gnc_file_dialog_multi
|
||||
static GSList *
|
||||
gnc_file_dialog_int (GtkWindow *parent,
|
||||
const char * title,
|
||||
GList * filters,
|
||||
const char * starting_dir,
|
||||
GNCFileDialogType type,
|
||||
gboolean multi
|
||||
)
|
||||
{
|
||||
GtkWidget *file_box;
|
||||
const char *internal_name;
|
||||
@ -91,6 +77,7 @@ gnc_file_dialog (GtkWindow *parent,
|
||||
const gchar *ok_icon = NULL;
|
||||
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN;
|
||||
gint response;
|
||||
GSList* file_name_list = NULL;
|
||||
|
||||
ENTER(" ");
|
||||
|
||||
@ -130,6 +117,9 @@ gnc_file_dialog (GtkWindow *parent,
|
||||
action,
|
||||
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||
NULL);
|
||||
if (multi)
|
||||
gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (file_box), TRUE);
|
||||
|
||||
if (ok_icon)
|
||||
gnc_gtk_dialog_add_button(file_box, okbutton, ok_icon, GTK_RESPONSE_ACCEPT);
|
||||
else
|
||||
@ -174,23 +164,85 @@ gnc_file_dialog (GtkWindow *parent,
|
||||
|
||||
if (response == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
/* look for constructs like postgres://foo */
|
||||
internal_name = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER (file_box));
|
||||
if (internal_name != NULL)
|
||||
if (multi)
|
||||
{
|
||||
if (strstr (internal_name, "file://") == internal_name)
|
||||
file_name_list = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (file_box));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* look for constructs like postgres://foo */
|
||||
internal_name = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER (file_box));
|
||||
if (internal_name != NULL)
|
||||
{
|
||||
/* nope, a local file name */
|
||||
internal_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (file_box));
|
||||
if (strstr (internal_name, "file://") == internal_name)
|
||||
{
|
||||
/* nope, a local file name */
|
||||
internal_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (file_box));
|
||||
}
|
||||
file_name = g_strdup(internal_name);
|
||||
}
|
||||
file_name = g_strdup(internal_name);
|
||||
file_name_list = g_slist_append (file_name_list, file_name);
|
||||
}
|
||||
}
|
||||
gtk_widget_destroy(GTK_WIDGET(file_box));
|
||||
LEAVE("%s", file_name ? file_name : "(null)");
|
||||
return file_name_list;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* gnc_file_dialog *
|
||||
* Pops up a file selection dialog (either a "Save As" or an *
|
||||
* "Open"), and returns the name of the file the user selected. *
|
||||
* (This function does not return until the user selects a file *
|
||||
* or presses "Cancel" or the window manager destroy button) *
|
||||
* *
|
||||
* Args: title - the title of the window *
|
||||
* filters - list of GtkFileFilters to use, will be *
|
||||
* freed automatically *
|
||||
* default_dir - start the chooser in this directory *
|
||||
* type - what type of dialog (open, save, etc.) *
|
||||
* Return: containing the name of the file the user selected *
|
||||
\********************************************************************/
|
||||
char *
|
||||
gnc_file_dialog (GtkWindow *parent,
|
||||
const char * title,
|
||||
GList * filters,
|
||||
const char * starting_dir,
|
||||
GNCFileDialogType type
|
||||
)
|
||||
{
|
||||
gchar* file_name = NULL;
|
||||
GSList* ret = gnc_file_dialog_int (parent, title, filters, starting_dir, type, FALSE);
|
||||
if (ret)
|
||||
file_name = g_strdup (ret->data);
|
||||
g_slist_free_full (ret, g_free);
|
||||
return file_name;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* gnc_file_dialog_multi *
|
||||
* Pops up a file selection dialog (either a "Save As" or an *
|
||||
* "Open"), and returns the name of the files the user selected. *
|
||||
* Similar to gnc_file_dialog with allowing multi-file selection *
|
||||
* *
|
||||
* Args: title - the title of the window *
|
||||
* filters - list of GtkFileFilters to use, will be *
|
||||
* freed automatically *
|
||||
* default_dir - start the chooser in this directory *
|
||||
* type - what type of dialog (open, save, etc.) *
|
||||
* Return: GList containing the names of the selected files *
|
||||
\********************************************************************/
|
||||
|
||||
GSList *
|
||||
gnc_file_dialog_multi (GtkWindow *parent,
|
||||
const char * title,
|
||||
GList * filters,
|
||||
const char * starting_dir,
|
||||
GNCFileDialogType type
|
||||
)
|
||||
{
|
||||
return gnc_file_dialog_int (parent, title, filters, starting_dir, type, TRUE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
show_session_error (GtkWindow *parent,
|
||||
|
@ -149,6 +149,12 @@ char * gnc_file_dialog (GtkWindow *parent,
|
||||
const char * starting_dir,
|
||||
GNCFileDialogType type);
|
||||
|
||||
GSList * gnc_file_dialog_multi (GtkWindow *parent,
|
||||
const char * title,
|
||||
GList * filters,
|
||||
const char * starting_dir,
|
||||
GNCFileDialogType type);
|
||||
|
||||
gboolean gnc_file_open_file (GtkWindow *parent,
|
||||
const char *filename,
|
||||
gboolean open_readonly);
|
||||
|
@ -1800,7 +1800,6 @@ recnWindowWithBalance (GtkWidget *parent, Account *account, gnc_numeric new_endi
|
||||
gnc_register_gui_component (WINDOW_RECONCILE_CM_CLASS,
|
||||
refresh_handler, close_handler,
|
||||
recnData);
|
||||
// This window should close if we close the session.
|
||||
gnc_gui_component_set_session (recnData->component_id, gnc_get_current_session());
|
||||
|
||||
recn_set_watches (recnData);
|
||||
@ -2118,6 +2117,15 @@ gnc_ui_reconcile_window_raise(RecnWindow * recnData)
|
||||
gtk_window_present(GTK_WINDOW(recnData->window));
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
gnc_ui_reconcile_window_get_widget(RecnWindow * recnData)
|
||||
{
|
||||
if (recnData == NULL || recnData->window == NULL)
|
||||
return NULL;
|
||||
return recnData->window;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************************************************\
|
||||
* recn_destroy_cb *
|
||||
|
@ -63,5 +63,5 @@ RecnWindow *recnWindowWithBalance (GtkWidget *parent, Account *account,
|
||||
time64 statement_date);
|
||||
|
||||
void gnc_ui_reconcile_window_raise(RecnWindow * recnData);
|
||||
|
||||
GtkWidget* gnc_ui_reconcile_window_get_widget(RecnWindow * recnData);
|
||||
#endif /* WINDOW_RECONCILE_H */
|
||||
|
@ -945,6 +945,21 @@
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="reconcile_after_close_button">
|
||||
<property name="label" translatable="yes">Reconcile after match</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_indicator">True</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>
|
||||
|
@ -69,6 +69,7 @@ struct _main_matcher_info
|
||||
GtkTreeViewColumn *account_column;
|
||||
GtkWidget *show_account_column;
|
||||
GtkWidget *show_matched_info;
|
||||
GtkWidget *reconcile_after_close;
|
||||
gboolean add_toggled; // flag to indicate that add has been toggled to stop selection
|
||||
gint id;
|
||||
};
|
||||
@ -196,6 +197,8 @@ gboolean gnc_gen_trans_list_empty(GNCImportMainMatcher *info)
|
||||
void gnc_gen_trans_list_show_all(GNCImportMainMatcher *info)
|
||||
{
|
||||
gtk_widget_show_all (GTK_WIDGET (info->main_widget));
|
||||
// By default, do not show this check box.
|
||||
gnc_gen_trans_list_show_reconcile_after_close (info, FALSE, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1005,6 +1008,9 @@ GNCImportMainMatcher *gnc_gen_trans_list_new (GtkWidget *parent,
|
||||
g_signal_connect (G_OBJECT(info->show_matched_info), "toggled",
|
||||
G_CALLBACK(show_matched_info_toggled_cb), info);
|
||||
|
||||
// Create the checkbox, but do not show it by default.
|
||||
info->reconcile_after_close = GTK_WIDGET(gtk_builder_get_object (builder, "reconcile_after_close_button"));
|
||||
|
||||
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"));
|
||||
@ -1089,6 +1095,8 @@ GNCImportMainMatcher * gnc_gen_trans_assist_new (GtkWidget *parent,
|
||||
g_signal_connect (G_OBJECT(info->show_matched_info), "toggled",
|
||||
G_CALLBACK(show_matched_info_toggled_cb), info);
|
||||
|
||||
info->reconcile_after_close = GTK_WIDGET(gtk_builder_get_object (builder, "reconcile_when_close_button"));
|
||||
|
||||
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"));
|
||||
@ -1468,6 +1476,18 @@ void gnc_gen_trans_list_add_trans (GNCImportMainMatcher *gui, Transaction *trans
|
||||
return;
|
||||
}/* end gnc_import_add_trans() */
|
||||
|
||||
void gnc_gen_trans_list_show_reconcile_after_close(GNCImportMainMatcher *info, gboolean reconcile_after_close, gboolean active)
|
||||
{
|
||||
gtk_widget_set_visible (info->reconcile_after_close,reconcile_after_close);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (info->reconcile_after_close), active);
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
gnc_gen_trans_list_get_reconcile_widget(GNCImportMainMatcher *info)
|
||||
{
|
||||
return info->reconcile_after_close;
|
||||
}
|
||||
|
||||
void gnc_gen_trans_list_add_trans_with_ref_id (GNCImportMainMatcher *gui, Transaction *trans, guint32 ref_id)
|
||||
{
|
||||
GNCImportTransInfo * transaction_info = NULL;
|
||||
|
@ -196,5 +196,8 @@ gboolean gnc_gen_trans_list_empty(GNCImportMainMatcher *info);
|
||||
*/
|
||||
void gnc_gen_trans_list_show_all(GNCImportMainMatcher *info);
|
||||
|
||||
void gnc_gen_trans_list_show_reconcile_after_close(GNCImportMainMatcher *info, gboolean reconcile_after_close, gboolean active);
|
||||
GtkWidget* gnc_gen_trans_list_get_reconcile_widget(GNCImportMainMatcher *info);
|
||||
|
||||
#endif
|
||||
/**@}*/
|
||||
|
@ -67,16 +67,20 @@ static Account *ofx_parent_account = NULL;
|
||||
// Structure we use to gather information about statement balance/account etc.
|
||||
typedef struct _ofx_info
|
||||
{
|
||||
gint num_trans_processed;
|
||||
GSList* statement;
|
||||
GtkWindow* parent;
|
||||
GNCImportMainMatcher *gnc_ofx_importer_gui;
|
||||
Account *last_import_account;
|
||||
Account *last_investment_account;
|
||||
Account *last_income_account;
|
||||
GList *created_commodites ;
|
||||
gint num_trans_processed; // Number of transactions processed
|
||||
struct OfxStatementData* statement; // Statement, if any
|
||||
gboolean run_reconcile; // If TRUE the reconcile window is opened after matching.
|
||||
GList *created_commodites;
|
||||
GSList* file_list; // List of OFX files to import
|
||||
} ofx_info ;
|
||||
|
||||
GList *ofx_created_commodites = NULL;
|
||||
|
||||
/*
|
||||
int ofx_proc_status_cb(struct OfxStatusData data)
|
||||
{
|
||||
@ -118,13 +122,11 @@ set_associated_income_account(Account* investment_account,
|
||||
xaccAccountCommitEdit(investment_account);
|
||||
}
|
||||
|
||||
int ofx_proc_statement_cb(struct OfxStatementData data,
|
||||
void *statement_user_data);
|
||||
int ofx_proc_security_cb(const struct OfxSecurityData data,
|
||||
void *security_user_data);
|
||||
int ofx_proc_statement_cb (struct OfxStatementData data, void * statement_user_data);
|
||||
int ofx_proc_security_cb (const struct OfxSecurityData data, void * security_user_data);
|
||||
int ofx_proc_transaction_cb (struct OfxTransactionData data, void *user_data);
|
||||
int ofx_proc_account_cb(struct OfxAccountData data, void * account_user_data);
|
||||
static double ofx_get_investment_amount(const struct OfxTransactionData* data);
|
||||
int ofx_proc_account_cb (struct OfxAccountData data, void * account_user_data);
|
||||
static double ofx_get_investment_amount (const struct OfxTransactionData* data);
|
||||
|
||||
static const gchar *gnc_ofx_ttype_to_string(TransactionType t)
|
||||
{
|
||||
@ -917,11 +919,10 @@ int ofx_proc_transaction_cb(struct OfxTransactionData data, void *user_data)
|
||||
int ofx_proc_statement_cb (struct OfxStatementData data, void * statement_user_data)
|
||||
{
|
||||
ofx_info* info = (ofx_info*) statement_user_data;
|
||||
struct OfxStatementData* statement = g_new (struct OfxStatementData, 1);
|
||||
*statement = data;
|
||||
info->statement = g_slist_append (info->statement, statement);
|
||||
info->statement = g_new (struct OfxStatementData, 1);
|
||||
*info->statement = data;
|
||||
return 0;
|
||||
}//end ofx_proc_statement()
|
||||
}
|
||||
|
||||
|
||||
int ofx_proc_account_cb(struct OfxAccountData data, void * account_user_data)
|
||||
@ -1003,22 +1004,23 @@ int ofx_proc_account_cb(struct OfxAccountData data, void * account_user_data)
|
||||
|
||||
gnc_utf8_strip_invalid(data.account_name);
|
||||
gnc_utf8_strip_invalid(data.account_id);
|
||||
account_description = g_strdup_printf( /* This string is a default account
|
||||
account_description = g_strdup_printf (/* This string is a default account
|
||||
name. It MUST NOT contain the
|
||||
character ':' anywhere in it or
|
||||
in any translation. */
|
||||
"%s \"%s\"",
|
||||
account_type_name,
|
||||
data.account_name);
|
||||
/* use the info->parent as import-matcher is not displayed yet */
|
||||
account = gnc_import_select_account (GTK_WIDGET(info->parent),
|
||||
"%s \"%s\"",
|
||||
account_type_name,
|
||||
data.account_name);
|
||||
account = gnc_import_select_account (gnc_gen_trans_list_widget(info->gnc_ofx_importer_gui),
|
||||
data.account_id, 1,
|
||||
account_description, default_commodity,
|
||||
default_type, info->last_import_account, NULL);
|
||||
default_type, NULL, NULL);
|
||||
|
||||
if (account)
|
||||
{
|
||||
info->last_import_account = account;
|
||||
}
|
||||
|
||||
g_free(account_description);
|
||||
}
|
||||
else
|
||||
@ -1051,6 +1053,142 @@ double ofx_get_investment_amount(const struct OfxTransactionData* data)
|
||||
}
|
||||
}
|
||||
|
||||
// Forward declaration, required because several static functions depend on one-another.
|
||||
static void
|
||||
gnc_file_ofx_import_process_file (ofx_info* info);
|
||||
|
||||
// gnc_ofx_process_next_file processes the next file in the info->file_list.
|
||||
static void
|
||||
gnc_ofx_process_next_file (GtkDialog *dialog, gpointer user_data)
|
||||
{
|
||||
ofx_info* info = (ofx_info*) user_data;
|
||||
// Free the statement (if it was allocated)
|
||||
g_free (info->statement);
|
||||
info->statement = NULL;
|
||||
|
||||
// Done with the previous OFX file, process the next one if any.
|
||||
info->file_list = g_slist_delete_link(info->file_list, info->file_list);
|
||||
if (info->file_list)
|
||||
gnc_file_ofx_import_process_file (info);
|
||||
else
|
||||
{
|
||||
// Final cleanup.
|
||||
g_free (info);
|
||||
if (ofx_created_commodites)
|
||||
{
|
||||
/* FIXME: Present some result window about the newly created
|
||||
* commodities */
|
||||
g_warning ("Created %d new commodities during import", g_list_length(ofx_created_commodites));
|
||||
g_list_free (ofx_created_commodites);
|
||||
ofx_created_commodites = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
//g_warning("No new commodities created");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This callback is called when the user is done matching transactions.
|
||||
static void
|
||||
gnc_ofx_match_done (GtkDialog *dialog, gint response_id, gpointer user_data)
|
||||
{
|
||||
ofx_info* info = (ofx_info*) user_data;
|
||||
|
||||
if (response_id == GTK_RESPONSE_OK && info->run_reconcile && info->statement)
|
||||
{
|
||||
// Open a reconcile window.
|
||||
Account* account = gnc_import_select_account (gnc_gen_trans_list_widget(info->gnc_ofx_importer_gui),
|
||||
info->statement->account_id,
|
||||
0, NULL, NULL, ACCT_TYPE_NONE, NULL, NULL);
|
||||
if (account && info->statement->ledger_balance_valid)
|
||||
{
|
||||
gnc_numeric value = double_to_gnc_numeric (info->statement->ledger_balance,
|
||||
xaccAccountGetCommoditySCU (account),
|
||||
GNC_HOW_RND_ROUND_HALF_UP);
|
||||
RecnWindow* rec_window = recnWindowWithBalance (GTK_WIDGET (info->parent), account, value, info->statement->ledger_balance_date);
|
||||
// Connect to destroy, at which point we'll process the next OFX file..
|
||||
g_signal_connect (G_OBJECT (gnc_ui_reconcile_window_get_widget (rec_window)), "destroy", G_CALLBACK (gnc_ofx_process_next_file), info);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_hide (GTK_WIDGET(dialog));
|
||||
gnc_ofx_process_next_file (dialog, info);
|
||||
}
|
||||
}
|
||||
|
||||
// This callback is triggered when the user checks or unchecks the reconcile after match
|
||||
// check box in the matching dialog.
|
||||
static void
|
||||
reconcile_when_close_toggled_cb (GtkToggleButton *togglebutton, ofx_info* info)
|
||||
{
|
||||
info->run_reconcile = gtk_toggle_button_get_active (togglebutton);
|
||||
}
|
||||
|
||||
// Aux function to process the OFX file in info->file_list
|
||||
static void
|
||||
gnc_file_ofx_import_process_file (ofx_info* info)
|
||||
{
|
||||
LibofxContextPtr libofx_context = libofx_get_new_context();
|
||||
char* filename = NULL;
|
||||
char * selected_filename = NULL;
|
||||
GtkWindow *parent = info->parent;
|
||||
|
||||
if (info->file_list == NULL)
|
||||
return;
|
||||
|
||||
filename = info->file_list->data;
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
selected_filename = g_win32_locale_filename_from_utf8 (filename);
|
||||
g_free (filename);
|
||||
#else
|
||||
selected_filename = filename;
|
||||
#endif
|
||||
DEBUG("Filename found: %s", selected_filename);
|
||||
|
||||
// Reset the reconciliation information.
|
||||
info->num_trans_processed = 0;
|
||||
info->statement = NULL;
|
||||
|
||||
/* Initialize libofx and set the callbacks*/
|
||||
ofx_set_statement_cb (libofx_context, ofx_proc_statement_cb, info);
|
||||
ofx_set_account_cb (libofx_context, ofx_proc_account_cb, info);
|
||||
ofx_set_transaction_cb (libofx_context, ofx_proc_transaction_cb, info);
|
||||
ofx_set_security_cb (libofx_context, ofx_proc_security_cb, info);
|
||||
/*ofx_set_status_cb(libofx_context, ofx_proc_status_cb, 0);*/
|
||||
|
||||
// Create the match dialog, and run the ofx file through the importer.
|
||||
info->gnc_ofx_importer_gui = gnc_gen_trans_list_new (GTK_WIDGET(parent), NULL, TRUE, 42, FALSE);
|
||||
libofx_proc_file (libofx_context, selected_filename, AUTODETECT);
|
||||
|
||||
// See whether the view has anything in it and warn the user if not.
|
||||
if(gnc_gen_trans_list_empty (info->gnc_ofx_importer_gui))
|
||||
{
|
||||
gnc_gen_trans_list_delete (info->gnc_ofx_importer_gui);
|
||||
if(info->num_trans_processed)
|
||||
gnc_info_dialog (parent, _("OFX file(s) imported, %d transactions processed, no transactions to match"), info->num_trans_processed);
|
||||
// Process the next OFX file if any.
|
||||
gnc_ofx_process_next_file (NULL, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show the match dialog and connect to the "response" signal so we can trigger a reconcile if the user clicks OK when done matching transactions.
|
||||
g_signal_connect (G_OBJECT (gnc_gen_trans_list_widget (info->gnc_ofx_importer_gui)), "response", G_CALLBACK (gnc_ofx_match_done), info);
|
||||
gnc_gen_trans_list_show_all (info->gnc_ofx_importer_gui);
|
||||
|
||||
// Show or hide the check box for reconciling after match, depending on whether a statement was received.
|
||||
gnc_gen_trans_list_show_reconcile_after_close (info->gnc_ofx_importer_gui, info->statement != NULL, info->run_reconcile);
|
||||
// Finally connect to the reconcile after match check box so we can be notified if the user wants/does not want to reconcile.
|
||||
g_signal_connect (G_OBJECT (gnc_gen_trans_list_get_reconcile_widget (info->gnc_ofx_importer_gui)), "toggled",
|
||||
G_CALLBACK (reconcile_when_close_toggled_cb), info);
|
||||
}
|
||||
g_free(selected_filename);
|
||||
}
|
||||
|
||||
// The main import function. Starts the chain of file imports (if there are several)
|
||||
void gnc_file_ofx_import (GtkWindow *parent)
|
||||
{
|
||||
extern int ofx_PARSER_msg;
|
||||
@ -1059,14 +1197,14 @@ void gnc_file_ofx_import (GtkWindow *parent)
|
||||
extern int ofx_ERROR_msg;
|
||||
extern int ofx_INFO_msg;
|
||||
extern int ofx_STATUS_msg;
|
||||
char *selected_filename;
|
||||
GSList* selected_filenames = NULL;
|
||||
char *default_dir;
|
||||
LibofxContextPtr libofx_context = libofx_get_new_context();
|
||||
GList *filters = NULL;
|
||||
GSList* iter = NULL;
|
||||
ofx_info* info = NULL;
|
||||
GtkFileFilter* filter = gtk_file_filter_new ();
|
||||
GSList *iter = NULL;
|
||||
// Create the structure we're using to gather reconciliation information.
|
||||
ofx_info info = {0, NULL, parent, NULL, NULL, NULL, NULL, NULL};
|
||||
|
||||
|
||||
ofx_PARSER_msg = false;
|
||||
ofx_DEBUG_msg = false;
|
||||
@ -1082,97 +1220,34 @@ void gnc_file_ofx_import (GtkWindow *parent)
|
||||
gtk_file_filter_add_pattern (filter, "*.[oqOQ][fF][xX]");
|
||||
filters = g_list_prepend( filters, filter );
|
||||
|
||||
selected_filename = gnc_file_dialog(parent,
|
||||
_("Select an OFX/QFX file to process"),
|
||||
filters,
|
||||
default_dir,
|
||||
GNC_FILE_DIALOG_IMPORT);
|
||||
selected_filenames = gnc_file_dialog_multi (parent,
|
||||
_("Select one or multiple OFX/QFX file(s) to process"),
|
||||
filters,
|
||||
default_dir,
|
||||
GNC_FILE_DIALOG_IMPORT);
|
||||
g_free(default_dir);
|
||||
|
||||
if (selected_filename != NULL)
|
||||
if (selected_filenames)
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
gchar *conv_name;
|
||||
#endif
|
||||
|
||||
/* Remember the directory as the default. */
|
||||
default_dir = g_path_get_dirname(selected_filename);
|
||||
default_dir = g_path_get_dirname(selected_filenames->data);
|
||||
gnc_set_default_directory(GNC_PREFS_GROUP, default_dir);
|
||||
g_free(default_dir);
|
||||
|
||||
/*strncpy(file,selected_filename, 255);*/
|
||||
DEBUG("Filename found: %s", selected_filename);
|
||||
|
||||
/* Create the Generic transaction importer GUI. */
|
||||
info.gnc_ofx_importer_gui = gnc_gen_trans_list_new (GTK_WIDGET(parent), NULL, FALSE, 42, FALSE);
|
||||
|
||||
/* Look up the needed preferences */
|
||||
auto_create_commodity =
|
||||
gnc_prefs_get_bool (GNC_PREFS_GROUP_IMPORT, GNC_PREF_AUTO_COMMODITY);
|
||||
|
||||
/* Initialize libofx and set the callbacks*/
|
||||
ofx_set_statement_cb (libofx_context, ofx_proc_statement_cb, &info);
|
||||
ofx_set_account_cb (libofx_context, ofx_proc_account_cb, &info);
|
||||
ofx_set_transaction_cb (libofx_context, ofx_proc_transaction_cb, &info);
|
||||
ofx_set_security_cb (libofx_context, ofx_proc_security_cb, &info);
|
||||
/*ofx_set_status_cb(libofx_context, ofx_proc_status_cb, 0);*/
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
conv_name = g_win32_locale_filename_from_utf8(selected_filename);
|
||||
g_free(selected_filename);
|
||||
selected_filename = conv_name;
|
||||
#endif
|
||||
|
||||
DEBUG("Opening selected file");
|
||||
libofx_proc_file(libofx_context, selected_filename, AUTODETECT);
|
||||
// See whether the view has anything in it and warn the user if not.
|
||||
if(gnc_gen_trans_list_empty(info.gnc_ofx_importer_gui))
|
||||
{
|
||||
gnc_gen_trans_list_delete (info.gnc_ofx_importer_gui);
|
||||
if(info.num_trans_processed)
|
||||
gnc_info_dialog (parent, _("OFX file imported, %d transactions processed, no transactions to match"), info.num_trans_processed);
|
||||
}
|
||||
else
|
||||
{
|
||||
gnc_gen_trans_list_show_all(info.gnc_ofx_importer_gui);
|
||||
}
|
||||
// Open a reconcile window for each balance statement found.
|
||||
for (iter=info.statement; iter; iter=iter->next)
|
||||
{
|
||||
struct OfxStatementData* statement = (struct OfxStatementData*) iter->data;
|
||||
Account* account = gnc_import_select_account (gnc_gen_trans_list_widget(info.gnc_ofx_importer_gui),
|
||||
statement->account_id,
|
||||
0, NULL, NULL, ACCT_TYPE_NONE,
|
||||
NULL, NULL);
|
||||
if (account)
|
||||
{
|
||||
if (statement->ledger_balance_valid)
|
||||
{
|
||||
gnc_numeric value =
|
||||
double_to_gnc_numeric (statement->ledger_balance,
|
||||
xaccAccountGetCommoditySCU (account),
|
||||
GNC_HOW_RND_ROUND_HALF_UP);
|
||||
recnWindowWithBalance (GTK_WIDGET (parent),
|
||||
account,
|
||||
value,
|
||||
statement->ledger_balance_date);
|
||||
}
|
||||
}
|
||||
}
|
||||
g_free (selected_filename);
|
||||
g_slist_free_full (info.statement,g_free);
|
||||
}
|
||||
|
||||
if (info.created_commodites)
|
||||
{
|
||||
/* FIXME: Present some result window about the newly created
|
||||
* commodities */
|
||||
g_warning("Created %d new commodities during import", g_list_length(info.created_commodites));
|
||||
g_list_free(info.created_commodites);
|
||||
}
|
||||
else
|
||||
{
|
||||
//g_warning("No new commodities created");
|
||||
DEBUG("Opening selected file(s)");
|
||||
// Create the structure that holds the list of files to process and the statement info.
|
||||
info = g_new(ofx_info,1);
|
||||
info->num_trans_processed = 0;
|
||||
info->statement = NULL;
|
||||
info->parent = parent;
|
||||
info->run_reconcile = FALSE;
|
||||
info->file_list = selected_filenames;
|
||||
// Call the aux import function.
|
||||
gnc_file_ofx_import_process_file (info);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user