gnucash master: Multiple changes pushed
Robert Fewell
bobit at code.gnucash.org
Thu May 28 06:29:26 EDT 2020
Updated via https://github.com/Gnucash/gnucash/commit/3457dd15 (commit)
via https://github.com/Gnucash/gnucash/commit/8bf426e2 (commit)
via https://github.com/Gnucash/gnucash/commit/e69c8a23 (commit)
via https://github.com/Gnucash/gnucash/commit/2dcc0b7a (commit)
via https://github.com/Gnucash/gnucash/commit/55d73851 (commit)
from https://github.com/Gnucash/gnucash/commit/4fd5a2cd (commit)
commit 3457dd150b489088d2469133ff24954f748134d4
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Thu May 28 11:19:32 2020 +0100
Add file name to dialog used in ofx import
diff --git a/gnucash/import-export/ofx/gnc-ofx-import.c b/gnucash/import-export/ofx/gnc-ofx-import.c
index a1b7e2663..88456acf9 100644
--- a/gnucash/import-export/ofx/gnc-ofx-import.c
+++ b/gnucash/import-export/ofx/gnc-ofx-import.c
@@ -1173,7 +1173,8 @@ gnc_file_ofx_import_process_file (ofx_info* info)
{
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);
+ gnc_info_dialog (parent, _("OFX file '%s' imported, %d transactions processed, no transactions to match"),
+ selected_filename, info->num_trans_processed);
// Process the next OFX file if any.
gnc_ofx_process_next_file (NULL, info);
}
commit 8bf426e274fad91420b91d502c348fda0071fe5b
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Thu May 28 11:11:32 2020 +0100
Rename a couple of functions used in multiple OFX file import
diff --git a/gnucash/gnome/window-reconcile.c b/gnucash/gnome/window-reconcile.c
index 078e47bb2..b61df7561 100644
--- a/gnucash/gnome/window-reconcile.c
+++ b/gnucash/gnome/window-reconcile.c
@@ -2117,12 +2117,12 @@ gnc_ui_reconcile_window_raise(RecnWindow * recnData)
gtk_window_present(GTK_WINDOW(recnData->window));
}
-GtkWidget*
-gnc_ui_reconcile_window_get_widget(RecnWindow * recnData)
+GtkWindow *
+gnc_ui_reconcile_window_get_window (RecnWindow * recnData)
{
if (recnData == NULL || recnData->window == NULL)
return NULL;
- return recnData->window;
+ return GTK_WINDOW(recnData->window);
}
diff --git a/gnucash/gnome/window-reconcile.h b/gnucash/gnome/window-reconcile.h
index 5ca431b33..9f4695bd9 100644
--- a/gnucash/gnome/window-reconcile.h
+++ b/gnucash/gnome/window-reconcile.h
@@ -62,6 +62,8 @@ RecnWindow *recnWindowWithBalance (GtkWidget *parent, Account *account,
gnc_numeric new_ending,
time64 statement_date);
-void gnc_ui_reconcile_window_raise(RecnWindow * recnData);
-GtkWidget* gnc_ui_reconcile_window_get_widget(RecnWindow * recnData);
+void gnc_ui_reconcile_window_raise (RecnWindow * recnData);
+
+GtkWindow *gnc_ui_reconcile_window_get_window (RecnWindow * recnData);
+
#endif /* WINDOW_RECONCILE_H */
diff --git a/gnucash/import-export/import-main-matcher.c b/gnucash/import-export/import-main-matcher.c
index 6dafc2160..305c71a65 100644
--- a/gnucash/import-export/import-main-matcher.c
+++ b/gnucash/import-export/import-main-matcher.c
@@ -1475,14 +1475,17 @@ 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)
+void
+gnc_gen_trans_list_show_reconcile_after_close_button (GNCImportMainMatcher *info,
+ gboolean reconcile_after_close,
+ gboolean active)
{
- gtk_widget_set_visible (info->reconcile_after_close,reconcile_after_close);
+ 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)
+gnc_gen_trans_list_get_reconcile_after_close_button (GNCImportMainMatcher *info)
{
return info->reconcile_after_close;
}
diff --git a/gnucash/import-export/import-main-matcher.h b/gnucash/import-export/import-main-matcher.h
index fdb84a69d..06b98cf41 100644
--- a/gnucash/import-export/import-main-matcher.h
+++ b/gnucash/import-export/import-main-matcher.h
@@ -196,8 +196,19 @@ 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);
+/** Show and set the reconcile after close check button.
+ * @param info A pointer to a the GNCImportMainMatcher structure.
+ * @param reconcile_after_close A gboolean that shows or hides the button.
+ * @param active A gboolean to set or clear the check button.
+ */
+void gnc_gen_trans_list_show_reconcile_after_close_button (GNCImportMainMatcher *info,
+ gboolean reconcile_after_close,
+ gboolean active);
+/** Returns the reconcile after close check button.
+ * @param info A pointer to a the GNCImportMainMatcher structure.
+ * @return The check button.
+ */
+GtkWidget* gnc_gen_trans_list_get_reconcile_after_close_button (GNCImportMainMatcher *info);
#endif
/**@}*/
diff --git a/gnucash/import-export/ofx/gnc-ofx-import.c b/gnucash/import-export/ofx/gnc-ofx-import.c
index ff5292a1e..a1b7e2663 100644
--- a/gnucash/import-export/ofx/gnc-ofx-import.c
+++ b/gnucash/import-export/ofx/gnc-ofx-import.c
@@ -1107,9 +1107,13 @@ gnc_ofx_match_done (GtkDialog *dialog, gint response_id, gpointer user_data)
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);
+
+ 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);
+ g_signal_connect (G_OBJECT(gnc_ui_reconcile_window_get_window (rec_window)), "destroy",
+ G_CALLBACK(gnc_ofx_process_next_file), info);
}
}
else
@@ -1175,15 +1179,19 @@ gnc_file_ofx_import_process_file (ofx_info* 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);
+ /* Show the match dialog and connect to the "response" signal so we can trigger a reconcile when
+ the user clicks OK when done matching transactions if required. */
+ 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);
+ gnc_gen_trans_list_show_reconcile_after_close_button (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_signal_connect (G_OBJECT(gnc_gen_trans_list_get_reconcile_after_close_button (info->gnc_ofx_importer_gui)), "toggled",
+ G_CALLBACK(reconcile_when_close_toggled_cb), info);
}
g_free(selected_filename);
}
commit e69c8a237cca534ccfb957a709ecd8339d3858cd
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Thu May 28 10:49:56 2020 +0100
Set the reconcile after close button in import-main-matcher
Set the default visibility of the reconcile after close check button
to be hidden and set it so it does not respond to gtk_show_all.
diff --git a/gnucash/gtkbuilder/dialog-import.glade b/gnucash/gtkbuilder/dialog-import.glade
index 9fd5d95e7..d4762680d 100644
--- a/gnucash/gtkbuilder/dialog-import.glade
+++ b/gnucash/gtkbuilder/dialog-import.glade
@@ -946,19 +946,19 @@
</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>
+ <object class="GtkCheckButton" id="reconcile_after_close_button">
+ <property name="label" translatable="yes">Reconcile after match</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="no_show_all">True</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>
diff --git a/gnucash/import-export/import-main-matcher.c b/gnucash/import-export/import-main-matcher.c
index 6641a0f19..6dafc2160 100644
--- a/gnucash/import-export/import-main-matcher.c
+++ b/gnucash/import-export/import-main-matcher.c
@@ -197,8 +197,6 @@ 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
@@ -1095,7 +1093,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"));
+ // 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);
commit 2dcc0b7a192614e421ca6e44e4a3f5a99bece2eb
Merge: 4fd5a2cd5 55d73851e
Author: Robert Fewell <14uBobIT at gmail.com>
Date: Thu May 28 10:32:32 2020 +0100
Merge Jean Laroche's branch 'add_multi_ofx_import_master' PR 697 to master
commit 55d73851e239168a3d4deebca7b08e855650c0ee
Author: jean <you at example.com>
Date: Thu May 14 17:48:41 2020 -0700
Implement multiple-ofx import with reconcile
I had to rebase against master which included the reconcile after import and there were a few conflicts.
So this is the new version. It includes all the recommendations made in the original PR but the code now includes the reconcile part.
diff --git a/gnucash/gnome-utils/gnc-file.c b/gnucash/gnome-utils/gnc-file.c
index 5b1d67c20..33ea97f77 100644
--- a/gnucash/gnome-utils/gnc-file.c
+++ b/gnucash/gnome-utils/gnc-file.c
@@ -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,
diff --git a/gnucash/gnome-utils/gnc-file.h b/gnucash/gnome-utils/gnc-file.h
index eb38e705b..b038e0d00 100644
--- a/gnucash/gnome-utils/gnc-file.h
+++ b/gnucash/gnome-utils/gnc-file.h
@@ -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);
diff --git a/gnucash/gnome/window-reconcile.c b/gnucash/gnome/window-reconcile.c
index 1d553cec3..078e47bb2 100644
--- a/gnucash/gnome/window-reconcile.c
+++ b/gnucash/gnome/window-reconcile.c
@@ -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 *
diff --git a/gnucash/gnome/window-reconcile.h b/gnucash/gnome/window-reconcile.h
index dac318dd4..5ca431b33 100644
--- a/gnucash/gnome/window-reconcile.h
+++ b/gnucash/gnome/window-reconcile.h
@@ -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 */
diff --git a/gnucash/gtkbuilder/dialog-import.glade b/gnucash/gtkbuilder/dialog-import.glade
index 1490defd8..9fd5d95e7 100644
--- a/gnucash/gtkbuilder/dialog-import.glade
+++ b/gnucash/gtkbuilder/dialog-import.glade
@@ -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>
diff --git a/gnucash/import-export/import-main-matcher.c b/gnucash/import-export/import-main-matcher.c
index 786c160b8..551531276 100644
--- a/gnucash/import-export/import-main-matcher.c
+++ b/gnucash/import-export/import-main-matcher.c
@@ -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
@@ -985,6 +988,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"));
@@ -1006,7 +1012,7 @@ GNCImportMainMatcher *gnc_gen_trans_list_new (GtkWidget *parent,
gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, info);
g_object_unref (G_OBJECT(builder));
-
+
// Register this UI, it needs to be closed when the session is closed.
info->id = gnc_register_gui_component (IMPORT_MAIN_MATCHER_CM_CLASS,
NULL, /* no refresh handler */
@@ -1069,6 +1075,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"));
@@ -1448,6 +1456,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;
diff --git a/gnucash/import-export/import-main-matcher.h b/gnucash/import-export/import-main-matcher.h
index 7e1e33dd5..fdb84a69d 100644
--- a/gnucash/import-export/import-main-matcher.h
+++ b/gnucash/import-export/import-main-matcher.h
@@ -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
/**@}*/
diff --git a/gnucash/import-export/ofx/gnc-ofx-import.c b/gnucash/import-export/ofx/gnc-ofx-import.c
index 578f20d49..ff5292a1e 100644
--- a/gnucash/import-export/ofx/gnc-ofx-import.c
+++ b/gnucash/import-export/ofx/gnc-ofx-import.c
@@ -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);
}
}
Summary of changes:
gnucash/gnome-utils/gnc-file.c | 112 ++++++++---
gnucash/gnome-utils/gnc-file.h | 6 +
gnucash/gnome/window-reconcile.c | 10 +-
gnucash/gnome/window-reconcile.h | 4 +-
gnucash/gtkbuilder/dialog-import.glade | 15 ++
gnucash/import-export/import-main-matcher.c | 22 +++
gnucash/import-export/import-main-matcher.h | 14 ++
gnucash/import-export/ofx/gnc-ofx-import.c | 292 ++++++++++++++++++----------
8 files changed, 339 insertions(+), 136 deletions(-)
More information about the gnucash-changes
mailing list