gnucash maint: Multiple changes pushed

John Ralls jralls at code.gnucash.org
Thu Sep 16 12:47:23 EDT 2021


Updated	 via  https://github.com/Gnucash/gnucash/commit/1170d7b0 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/34bd7b49 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/248a8504 (commit)
	from  https://github.com/Gnucash/gnucash/commit/93289006 (commit)



commit 1170d7b0d4630df569bb28727f7fa0aa99fa09f8
Merge: 93289006e 34bd7b49b
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Sep 16 09:31:41 2021 -0700

    Merge Jean Laroche's '105334_ofx_multiple_accounts' into maint.

diff --cc gnucash/import-export/ofx/gnc-ofx-import.c
index 2c98665e6,f1116c914..f4433b266
--- a/gnucash/import-export/ofx/gnc-ofx-import.c
+++ b/gnucash/import-export/ofx/gnc-ofx-import.c
@@@ -899,8 -903,8 +903,9 @@@ int ofx_proc_transaction_cb(struct OfxT
          /* Send transaction to importer GUI. */
          if (xaccTransCountSplits(transaction) > 0)
          {
--            DEBUG("%d splits sent to the importer gui", xaccTransCountSplits(transaction));
-             gnc_gen_trans_list_add_trans (info->gnc_ofx_importer_gui, transaction);
 -            info->trans_list = g_list_prepend(info->trans_list,transaction);
++            DEBUG("%d splits sent to the importer gui",
++                  xaccTransCountSplits(transaction));
++            info->trans_list = g_list_prepend (info->trans_list, transaction);
          }
          else
          {
@@@ -1098,14 -1102,32 +1103,36 @@@ gnc_ofx_process_next_file (GtkDialog *d
      }
  }
  
+ static void
+ gnc_ofx_on_match_click (GtkDialog *dialog, gint response_id, gpointer user_data)
+ {
+     // Record the response of the user. If cancel we won't go to the next file, etc.
 -    ofx_info* info = (ofx_info*) user_data;
++    ofx_info* info = (ofx_info*)user_data;
+     info->response = response_id;
+ }
  
- // 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)
+ gnc_ofx_match_done (GtkDialog *dialog, gpointer user_data)
  {
      ofx_info* info = (ofx_info*) user_data;
 -    
 -    // The the user did not click OK, don't process the rest of the transaction, don't go to the next of xfile.
 +
-     if (response_id == GTK_RESPONSE_OK && info->run_reconcile && info->statement)
++    /* The the user did not click OK, don't process the rest of the
++     * transaction, don't go to the next of xfile.
++     */
+     if (info->response != GTK_RESPONSE_OK) return;
 -    
 -    if (info->trans_list && g_list_length (info->trans_list))
++
++    if (info->trans_list)
+     {
 -        // Re-run the match dialog if there are transactions remaining in our list (happens if several accounts
 -        // exist in the same ofx).
++         /* Re-run the match dialog if there are transactions
++          * remaining in our list (happens if several accounts exist
++          * in the same ofx).
++          */
+         info->gnc_ofx_importer_gui = gnc_gen_trans_list_new (GTK_WIDGET (info->parent), NULL, FALSE, 42, FALSE);
+         runMatcher (info, NULL, true);
+         return;
+     }
 -    
++
+     if (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),
@@@ -1142,6 -1159,70 +1164,71 @@@ reconcile_when_close_toggled_cb (GtkTog
      info->run_reconcile = gtk_toggle_button_get_active (togglebutton);
  }
  
+ static void
+ runMatcher(ofx_info* info, char * selected_filename, gboolean go_to_next_file)
+ {
+     GtkWindow *parent = info->parent;
 -    GList* trans_list;
+     GList* trans_list_remain = NULL;
+     Account* first_account = NULL;
 -    
 -    // If we have multiple accounts in the ofx file, we need to process transactions one account at a time,
 -    // in case there are transfers between accounts.
 -    trans_list = info->trans_list;
++
++    /* If we have multiple accounts in the ofx file, we need to
++     * process transactions one account at a time, in case there are
++     * transfers between accounts.
++     */
+     info->num_trans_processed = 0;
 -    for(;trans_list;trans_list=trans_list->next)
++    for(GList* node = info->trans_list; node; node=node->next)
+     {
 -        Transaction* trans = trans_list->data;
++        Transaction* trans = node->data;
+         Split* split = xaccTransGetSplit (trans, 0);
+         if (first_account == NULL) first_account = xaccSplitGetAccount (split);
+         if (xaccSplitGetAccount (split) == first_account)
+         {
 -            gnc_gen_trans_list_add_trans (info->gnc_ofx_importer_gui, trans_list->data);
++            gnc_gen_trans_list_add_trans (info->gnc_ofx_importer_gui, trans);
+             info->num_trans_processed ++;
+         }
 -        else trans_list_remain = g_list_prepend (trans_list_remain, trans_list->data);
++        else trans_list_remain = g_list_prepend (trans_list_remain, trans);
+     }
+     g_list_free (info->trans_list);
 -    info->trans_list = trans_list_remain;
 -    
++    info->trans_list = g_list_reverse (trans_list_remain);
++    g_list_free (trans_list_remain);
++
+     // 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)
+         {
+             gchar* acct_name = gnc_get_account_name_for_register (first_account);
+             gnc_info_dialog (parent, _("OFX file '%s', imported transactions for account '%s'\n%d transactions processed, no transactions to match"),
+                              selected_filename, acct_name, info->num_trans_processed);
+             g_free (acct_name);
+             gnc_ofx_match_done (NULL,info);
+             return;
+         }
+     }
+     else
+     {
+         /* Show the match dialog and connect to the "destroy" signal so we can trigger a reconcile when
+          the user clicks OK when done matching transactions if required. Connecting to response isn't enough
+          because only when the matcher is destroyed do imported transactions get recorded */
+         g_signal_connect (G_OBJECT (gnc_gen_trans_list_widget (info->gnc_ofx_importer_gui)), "destroy",
+                           G_CALLBACK (gnc_ofx_match_done), info);
+         
+         // Connect to response so we know if the user pressed "cancel".
+         g_signal_connect (G_OBJECT (gnc_gen_trans_list_widget (info->gnc_ofx_importer_gui)), "response",
+                           G_CALLBACK (gnc_ofx_on_match_click), 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_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_after_close_button (info->gnc_ofx_importer_gui)), "toggled",
+                           G_CALLBACK (reconcile_when_close_toggled_cb), info);
+     }
+ }
+ 
  // Aux function to process the OFX file in info->file_list
  static void
  gnc_file_ofx_import_process_file (ofx_info* info)

commit 34bd7b49b2747c02310443f723b140a4e619c553
Author: jean <27791933+jeanlaroche at users.noreply.github.com>
Date:   Thu Sep 9 21:38:47 2021 -0700

    Restore previous behavior when the user cancels

diff --git a/gnucash/import-export/ofx/gnc-ofx-import.c b/gnucash/import-export/ofx/gnc-ofx-import.c
index d03c543d5..f1116c914 100644
--- a/gnucash/import-export/ofx/gnc-ofx-import.c
+++ b/gnucash/import-export/ofx/gnc-ofx-import.c
@@ -76,7 +76,8 @@ typedef struct _ofx_info
     struct OfxStatementData* statement;     // Statement, if any
     gboolean run_reconcile;                 // If TRUE the reconcile window is opened after matching.
     GSList* file_list;                      // List of OFX files to import
-    GList* trans_list;
+    GList* trans_list;                      // We store the processed ofx transactions here
+    gint response;                          // Response sent by the match gui
 } ofx_info ;
 
 static void runMatcher(ofx_info* info, char * selected_filename, gboolean go_to_next_file);
@@ -1101,11 +1102,22 @@ gnc_ofx_process_next_file (GtkDialog *dialog, gpointer user_data)
     }
 }
 
+static void
+gnc_ofx_on_match_click (GtkDialog *dialog, gint response_id, gpointer user_data)
+{
+    // Record the response of the user. If cancel we won't go to the next file, etc.
+    ofx_info* info = (ofx_info*) user_data;
+    info->response = response_id;
+}
+
 static void
 gnc_ofx_match_done (GtkDialog *dialog, gpointer user_data)
 {
     ofx_info* info = (ofx_info*) user_data;
     
+    // The the user did not click OK, don't process the rest of the transaction, don't go to the next of xfile.
+    if (info->response != GTK_RESPONSE_OK) return;
+    
     if (info->trans_list && g_list_length (info->trans_list))
     {
         // Re-run the match dialog if there are transactions remaining in our list (happens if several accounts
@@ -1191,10 +1203,15 @@ runMatcher(ofx_info* info, char * selected_filename, gboolean go_to_next_file)
     else
     {
         /* Show the match dialog and connect to the "destroy" signal so we can trigger a reconcile when
-         the user clicks OK when done matching transactions if required. */
+         the user clicks OK when done matching transactions if required. Connecting to response isn't enough
+         because only when the matcher is destroyed do imported transactions get recorded */
         g_signal_connect (G_OBJECT (gnc_gen_trans_list_widget (info->gnc_ofx_importer_gui)), "destroy",
                           G_CALLBACK (gnc_ofx_match_done), info);
         
+        // Connect to response so we know if the user pressed "cancel".
+        g_signal_connect (G_OBJECT (gnc_gen_trans_list_widget (info->gnc_ofx_importer_gui)), "response",
+                          G_CALLBACK (gnc_ofx_on_match_click), 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.
@@ -1311,6 +1328,7 @@ void gnc_file_ofx_import (GtkWindow *parent)
         info->run_reconcile = FALSE;
         info->file_list = selected_filenames;
         info->trans_list = NULL;
+        info->response = 0;
         // Call the aux import function.
         gnc_file_ofx_import_process_file (info);
     }

commit 248a8504b7b110a8b6a0795d2bad03872d814386
Author: jean <27791933+jeanlaroche at users.noreply.github.com>
Date:   Thu Sep 9 10:52:19 2021 -0700

    Add code to handle ofx files that include transfers between accounts

diff --git a/gnucash/import-export/ofx/gnc-ofx-import.c b/gnucash/import-export/ofx/gnc-ofx-import.c
index 2c98665e6..d03c543d5 100644
--- a/gnucash/import-export/ofx/gnc-ofx-import.c
+++ b/gnucash/import-export/ofx/gnc-ofx-import.c
@@ -76,8 +76,11 @@ typedef struct _ofx_info
     struct OfxStatementData* statement;     // Statement, if any
     gboolean run_reconcile;                 // If TRUE the reconcile window is opened after matching.
     GSList* file_list;                      // List of OFX files to import
+    GList* trans_list;
 } ofx_info ;
 
+static void runMatcher(ofx_info* info, char * selected_filename, gboolean go_to_next_file);
+
 /*
 int ofx_proc_status_cb(struct OfxStatusData data)
 {
@@ -900,7 +903,7 @@ int ofx_proc_transaction_cb(struct OfxTransactionData data, void *user_data)
         if (xaccTransCountSplits(transaction) > 0)
         {
             DEBUG("%d splits sent to the importer gui", xaccTransCountSplits(transaction));
-            gnc_gen_trans_list_add_trans (info->gnc_ofx_importer_gui, transaction);
+            info->trans_list = g_list_prepend(info->trans_list,transaction);
         }
         else
         {
@@ -1088,7 +1091,7 @@ gnc_ofx_process_next_file (GtkDialog *dialog, gpointer user_data)
     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);
+    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
@@ -1098,14 +1101,21 @@ gnc_ofx_process_next_file (GtkDialog *dialog, gpointer user_data)
     }
 }
 
-
-// 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)
+gnc_ofx_match_done (GtkDialog *dialog, gpointer user_data)
 {
     ofx_info* info = (ofx_info*) user_data;
-
-    if (response_id == GTK_RESPONSE_OK && info->run_reconcile && info->statement)
+    
+    if (info->trans_list && g_list_length (info->trans_list))
+    {
+        // Re-run the match dialog if there are transactions remaining in our list (happens if several accounts
+        // exist in the same ofx).
+        info->gnc_ofx_importer_gui = gnc_gen_trans_list_new (GTK_WIDGET (info->parent), NULL, FALSE, 42, FALSE);
+        runMatcher (info, NULL, true);
+        return;
+    }
+    
+    if (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),
@@ -1121,17 +1131,12 @@ gnc_ofx_match_done (GtkDialog *dialog, gint response_id, gpointer user_data)
                                                             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_window (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);
+            return;
         }
     }
-    else if (response_id == GTK_RESPONSE_HELP)
-        return;
-    else
-    {
-        gtk_widget_hide (GTK_WIDGET(dialog));
-        gnc_ofx_process_next_file (dialog, info);
-    }
+    gnc_ofx_process_next_file (NULL, info);
 }
 
 // This callback is triggered when the user checks or unchecks the reconcile after match
@@ -1142,6 +1147,65 @@ reconcile_when_close_toggled_cb (GtkToggleButton *togglebutton, ofx_info* info)
     info->run_reconcile = gtk_toggle_button_get_active (togglebutton);
 }
 
+static void
+runMatcher(ofx_info* info, char * selected_filename, gboolean go_to_next_file)
+{
+    GtkWindow *parent = info->parent;
+    GList* trans_list;
+    GList* trans_list_remain = NULL;
+    Account* first_account = NULL;
+    
+    // If we have multiple accounts in the ofx file, we need to process transactions one account at a time,
+    // in case there are transfers between accounts.
+    trans_list = info->trans_list;
+    info->num_trans_processed = 0;
+    for(;trans_list;trans_list=trans_list->next)
+    {
+        Transaction* trans = trans_list->data;
+        Split* split = xaccTransGetSplit (trans, 0);
+        if (first_account == NULL) first_account = xaccSplitGetAccount (split);
+        if (xaccSplitGetAccount (split) == first_account)
+        {
+            gnc_gen_trans_list_add_trans (info->gnc_ofx_importer_gui, trans_list->data);
+            info->num_trans_processed ++;
+        }
+        else trans_list_remain = g_list_prepend (trans_list_remain, trans_list->data);
+    }
+    g_list_free (info->trans_list);
+    info->trans_list = trans_list_remain;
+    
+    // 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)
+        {
+            gchar* acct_name = gnc_get_account_name_for_register (first_account);
+            gnc_info_dialog (parent, _("OFX file '%s', imported transactions for account '%s'\n%d transactions processed, no transactions to match"),
+                             selected_filename, acct_name, info->num_trans_processed);
+            g_free (acct_name);
+            gnc_ofx_match_done (NULL,info);
+            return;
+        }
+    }
+    else
+    {
+        /* Show the match dialog and connect to the "destroy" 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)), "destroy",
+                          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_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_after_close_button (info->gnc_ofx_importer_gui)), "toggled",
+                          G_CALLBACK (reconcile_when_close_toggled_cb), info);
+    }
+}
+
 // Aux function to process the OFX file in info->file_list
 static void
 gnc_file_ofx_import_process_file (ofx_info* info)
@@ -1182,33 +1246,7 @@ gnc_file_ofx_import_process_file (ofx_info* info)
 
     // Free the libofx context before recursing to process the next file
     libofx_free_context(libofx_context);
-
-    // 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"),
-                                     selected_filename, 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 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_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_after_close_button (info->gnc_ofx_importer_gui)), "toggled",
-                          G_CALLBACK(reconcile_when_close_toggled_cb), info);
-    }
+    runMatcher(info, selected_filename,true);
     g_free(selected_filename);
 }
 
@@ -1272,6 +1310,7 @@ void gnc_file_ofx_import (GtkWindow *parent)
         info->parent = parent;
         info->run_reconcile = FALSE;
         info->file_list = selected_filenames;
+        info->trans_list = NULL;
         // Call the aux import function.
         gnc_file_ofx_import_process_file (info);
     }



Summary of changes:
 gnucash/import-export/ofx/gnc-ofx-import.c | 147 ++++++++++++++++++++---------
 1 file changed, 105 insertions(+), 42 deletions(-)



More information about the gnucash-changes mailing list