gnucash maint: Multiple changes pushed

Christopher Lam clam at code.gnucash.org
Fri Mar 11 14:50:04 EST 2022


Updated	 via  https://github.com/Gnucash/gnucash/commit/19479c3a (commit)
	 via  https://github.com/Gnucash/gnucash/commit/9e44ef5c (commit)
	 via  https://github.com/Gnucash/gnucash/commit/2f9963b7 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/0052e3e4 (commit)
	from  https://github.com/Gnucash/gnucash/commit/b93a034b (commit)



commit 19479c3af44b6b73c7e4d324b2824141cf4eed26
Merge: b93a034ba 9e44ef5c0
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Fri Mar 11 23:04:32 2022 +0800

    Merge branch 'maint-stock-editor' into maint #818


commit 9e44ef5c02fb6e4e5dc0ec5bac9c28cf1d13356d
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Fri Mar 11 15:04:53 2022 +0800

    Add hook to stock transaction GtkAssistant

diff --git a/gnucash/gnome/gnc-plugin-page-register.c b/gnucash/gnome/gnc-plugin-page-register.c
index 80221d19e..ccdaeb4a3 100644
--- a/gnucash/gnome/gnc-plugin-page-register.c
+++ b/gnucash/gnome/gnc-plugin-page-register.c
@@ -59,6 +59,7 @@
 #include "dialog-transfer.h"
 #include "dialog-utils.h"
 #include "assistant-stock-split.h"
+#include "assistant-stock-transaction.h"
 #include "gnc-component-manager.h"
 #include "gnc-date.h"
 #include "gnc-date-edit.h"
@@ -218,6 +219,9 @@ static void gnc_plugin_page_register_cmd_style_double_line (
 
 static void gnc_plugin_page_register_cmd_reconcile (GtkAction* action,
                                                     GncPluginPageRegister* plugin_page);
+static void gnc_plugin_page_register_cmd_stock_assistant (GtkAction* action,
+                                                          GncPluginPageRegister* page);
+
 static void gnc_plugin_page_register_cmd_autoclear (GtkAction* action,
                                                     GncPluginPageRegister* plugin_page);
 static void gnc_plugin_page_register_cmd_transfer (GtkAction* action,
@@ -481,6 +485,11 @@ static GtkActionEntry gnc_plugin_page_register_actions [] =
         N_ ("Automatically clear individual transactions, so as to reach a certain cleared amount"),
         G_CALLBACK (gnc_plugin_page_register_cmd_autoclear)
     },
+    {
+        "ActionsStockAssistantAction", NULL, N_ ("Stock Ass_istant"), NULL,
+        N_ ("Stock Assistant"),
+        G_CALLBACK (gnc_plugin_page_register_cmd_stock_assistant)
+    },
     {
         "ActionsStockSplitAction", NULL, N_ ("Stoc_k Split..."), NULL,
         N_ ("Record a stock split or a stock merger"),
@@ -614,6 +623,18 @@ static const gchar* view_style_actions[] =
     NULL
 };
 
+static const gchar* actions_requiring_extra[] =
+{
+    "ActionsStockAssistantAction",
+    NULL
+};
+
+static const gchar* actions_requiring_priced_account[] =
+{
+    "ActionsStockAssistantAction",
+    NULL
+};
+
 /** Short labels for use on the toolbar buttons. */
 static action_toolbar_labels toolbar_labels[] =
 {
@@ -1267,6 +1288,12 @@ gnc_plugin_page_register_ui_initial_state (GncPluginPageRegister* page)
     gnc_plugin_update_actions (action_group, actions_requiring_account,
                                "sensitive", is_readwrite && account != NULL);
 
+    gnc_plugin_update_actions (action_group, actions_requiring_extra,
+                               "visible", gnc_prefs_is_extra_enabled ());
+
+    gnc_plugin_update_actions (action_group, actions_requiring_priced_account,
+                               "sensitive", xaccAccountIsPriced (account));
+
     /* Set "style" radio button */
     ledger_type = gnc_ledger_display_type (priv->ledger);
     gnc_plugin_update_actions (action_group, view_style_actions,
@@ -4539,6 +4566,23 @@ gnc_plugin_page_register_cmd_reconcile (GtkAction* action,
     LEAVE (" ");
 }
 
+static void
+gnc_plugin_page_register_cmd_stock_assistant (GtkAction* action,
+                                              GncPluginPageRegister* page)
+{
+    Account *account;
+    GtkWindow *window;
+
+    ENTER ("(action %p, plugin_page %p)", action, page);
+
+    g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (page));
+    window = gnc_window_get_gtk_window (GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window));
+    account = gnc_plugin_page_register_get_account (page);
+    gnc_stock_transaction_assistant (GTK_WIDGET (window), account);
+
+    LEAVE (" ");
+}
+
 static void
 gnc_plugin_page_register_cmd_autoclear (GtkAction* action,
                                         GncPluginPageRegister* page)
diff --git a/gnucash/ui/gnc-plugin-page-register-ui.xml b/gnucash/ui/gnc-plugin-page-register-ui.xml
index 5a240a5b2..ab1405a7f 100644
--- a/gnucash/ui/gnc-plugin-page-register-ui.xml
+++ b/gnucash/ui/gnc-plugin-page-register-ui.xml
@@ -46,6 +46,7 @@
         <menuitem name="ActionsReconcile" action="ActionsReconcileAction"/>
         <menuitem name="ActionsAutoClear" action="ActionsAutoClearAction"/>
         <menuitem name="ActionsStockSplit" action="ActionsStockSplitAction"/>
+        <menuitem name="ActionsStockAssistant" action="ActionsStockAssistantAction"/>
         <menuitem name="ActionLots" action="ActionsLotsAction"/>
         <separator name="ActionsSep4"/>
         <menuitem name="BlankTransaction" action="BlankTransactionAction"/>

commit 2f9963b70852087d5bb6f4154a68d0c40c27cd2f
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Fri Mar 11 14:44:35 2022 +0800

    Bug 798004 - Next gen UI for stock transactions
    
    A new assistant to create stock transactions

diff --git a/gnucash/gnome/CMakeLists.txt b/gnucash/gnome/CMakeLists.txt
index f5e2481a9..d3c22917f 100644
--- a/gnucash/gnome/CMakeLists.txt
+++ b/gnucash/gnome/CMakeLists.txt
@@ -4,6 +4,7 @@ set (gnc_gnome_noinst_HEADERS
   assistant-hierarchy.h
   assistant-loan.h
   assistant-stock-split.h
+  assistant-stock-transaction.h
   business-options-gnome.h
   business-urls.h
   business-gnome-utils.h
@@ -72,6 +73,7 @@ set (gnc_gnome_SOURCES
   assistant-hierarchy.c
   assistant-loan.cpp
   assistant-stock-split.c
+  assistant-stock-transaction.cpp
   business-options-gnome.c
   business-urls.c
   business-gnome-utils.c
diff --git a/gnucash/gnome/assistant-stock-transaction.cpp b/gnucash/gnome/assistant-stock-transaction.cpp
new file mode 100644
index 000000000..3fbfc8aa9
--- /dev/null
+++ b/gnucash/gnome/assistant-stock-transaction.cpp
@@ -0,0 +1,1225 @@
+/********************************************************************\
+ * assistant-stock-transaction.cpp -- stock assistant for GnuCash   *
+ * Copyright (C) 2022 Christopher Lam                               *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+
+#include <config.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <vector>
+#include <string>
+#include <numeric>
+#include <algorithm>
+
+extern "C" {
+#include "Transaction.h"
+#include "engine-helpers.h"
+#include "dialog-utils.h"
+#include "assistant-stock-transaction.h"
+#include "gnc-account-sel.h"
+#include "gnc-amount-edit.h"
+#include "gnc-component-manager.h"
+#include "gnc-date-edit.h"
+#include "gnc-tree-view-account.h"
+
+static QofLogModule log_module = GNC_MOD_ASSISTANT;
+
+void stock_assistant_prepare (GtkAssistant  *assistant, GtkWidget *page,
+                              gpointer user_data);
+void stock_assistant_finish  (GtkAssistant *assistant, gpointer user_data);
+void stock_assistant_cancel  (GtkAssistant *gtkassistant, gpointer user_data);
+}
+
+enum class FieldMask : unsigned;
+bool operator &(FieldMask lhs, FieldMask rhs);
+FieldMask operator |(FieldMask lhs, FieldMask rhs);
+FieldMask operator ^(FieldMask lhs, FieldMask rhs);
+
+static const char* ASSISTANT_STOCK_TRANSACTION_CM_CLASS = "assistant-stock-transaction";
+
+enum assistant_pages
+{
+    PAGE_INTRO = 0,
+    PAGE_TRANSACTION_TYPE,
+    PAGE_TRANSATION_DETAILS,
+    PAGE_STOCK_AMOUNT,
+    PAGE_STOCK_VALUE,
+    PAGE_CASH,
+    PAGE_FEES,
+    PAGE_DIVIDEND,
+    PAGE_CAPGAINS,
+    PAGE_FINISH
+};
+
+enum split_cols
+{
+    SPLIT_COL_ACCOUNT = 0,
+    SPLIT_COL_MEMO,
+    SPLIT_COL_DEBIT,
+    SPLIT_COL_CREDIT,
+    NUM_SPLIT_COLS
+};
+
+/** structures *********************************************************/
+
+enum class FieldMask : unsigned
+{
+    DISABLED = 0,
+    ENABLED_DEBIT,
+    ENABLED_CREDIT,
+    ALLOW_ZERO = 4,
+    ALLOW_NEGATIVE = 8
+};
+
+FieldMask operator |(FieldMask lhs, FieldMask rhs)
+{
+    return static_cast<FieldMask> (static_cast<unsigned>(lhs) |
+                                   static_cast<unsigned>(rhs));
+};
+
+bool operator &(FieldMask lhs, FieldMask rhs)
+{
+    return (static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs));
+};
+
+FieldMask operator ^(FieldMask lhs, FieldMask rhs)
+{
+    return static_cast<FieldMask> (static_cast<unsigned>(lhs) ^
+                                   static_cast<unsigned>(rhs));
+};
+
+struct TxnTypeInfo
+{
+    FieldMask stock_amount;
+    FieldMask stock_value;
+    FieldMask cash_value;
+    FieldMask fees_value;
+    bool fees_capitalize;
+    FieldMask dividend_value;
+    FieldMask capgains_value;
+    const char* friendly_name;
+    const char* explanation;
+};
+
+using StringVec = std::vector<std::string>;
+using TxnTypeVec = std::vector<TxnTypeInfo>;
+using AccountVec = std::vector<Account*>;
+
+static const TxnTypeVec starting_types
+{
+    {
+        FieldMask::ENABLED_DEBIT,          // stock_amt
+        FieldMask::ENABLED_DEBIT,          // stock_val
+        FieldMask::ENABLED_CREDIT,         // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        true,                   // fees_capitalize
+        FieldMask::DISABLED,               // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing an
+        // Initial stock purchase
+        NC_("Stock Assistant: Transaction Type", "Open buy"),
+        N_("Initial stock purchase")
+    },
+    {
+        FieldMask::ENABLED_CREDIT,         // stock_amt
+        FieldMask::ENABLED_CREDIT,         // stock_val
+        FieldMask::ENABLED_DEBIT,          // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        true,                   // fees_capitalize
+        FieldMask::DISABLED,               // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing an
+        // initial stock short-sale
+        NC_("Stock Assistant: Transaction Type", "Open short"),
+        N_("Initial stock short-sale")
+    }
+};
+
+static const TxnTypeVec long_types
+{
+    {
+        FieldMask::ENABLED_DEBIT,          // stock_amt
+        FieldMask::ENABLED_DEBIT,          // stock_val
+        FieldMask::ENABLED_CREDIT,         // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        true,                   // fees_capitalize
+        FieldMask::DISABLED,               // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing
+        // purchase of stock.
+        NC_("Stock Assistant: Transaction Type", "Buy"),
+        N_("Buying stock.")
+    },
+    {
+        FieldMask::ENABLED_CREDIT,         // stock_amt
+        FieldMask::ENABLED_CREDIT,         // stock_val
+        FieldMask::ENABLED_DEBIT,          // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        false,                  // fees_capitalize
+        FieldMask::DISABLED,               // dividend_amt
+        FieldMask::ENABLED_CREDIT | FieldMask::ALLOW_ZERO | FieldMask::ALLOW_NEGATIVE, // capgains_amt
+        // Translators: this is a stock transaction describing sale of
+        // stock, and recording capital gains/loss
+        NC_("Stock Assistant: Transaction Type", "Sell"),
+        N_("Selling stock, and record capital gains/loss")
+    },
+    {
+        FieldMask::DISABLED,               // stock_amt
+        FieldMask::DISABLED,               // stock_val
+        FieldMask::ENABLED_DEBIT,          // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        false,                  // fees_capitalize
+        FieldMask::ENABLED_CREDIT,         // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing
+        // dividends issued to holder
+        NC_("Stock Assistant: Transaction Type", "Dividend"),
+        N_("Company issues dividends to holder")
+    },
+    {
+        FieldMask::ENABLED_DEBIT,          // stock_amt
+        FieldMask::ENABLED_DEBIT,          // stock_val
+        FieldMask::ENABLED_DEBIT,          // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        true,                   // fees_capitalize
+        FieldMask::ENABLED_CREDIT,         // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing
+        // dividend issued to holder, and is reinvested. Some
+        // dividends are distributed as cash.
+        NC_("Stock Assistant: Transaction Type", "Dividend reinvestment (w/ remainder)"),
+        N_("Company issues dividend which is reinvested. Some dividends are paid to holder")
+    },
+    {
+        FieldMask::ENABLED_DEBIT,          // stock_amt
+        FieldMask::ENABLED_DEBIT,          // stock_val
+        FieldMask::DISABLED,               // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        true,                   // fees_capitalize
+        FieldMask::ENABLED_CREDIT,         // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing
+        // dividend which is wholly reinvested.
+        NC_("Stock Assistant: Transaction Type", "Dividend reinvestment (w/o remainder)"),
+        N_("Company issues dividend which is wholly reinvested.")
+    },
+    {
+        FieldMask::DISABLED,               // stock_amt
+        FieldMask::ENABLED_CREDIT,         // stock_val
+        FieldMask::ENABLED_DEBIT,          // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        true,                   // fees_capitalize
+        FieldMask::DISABLED,               // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing return
+        // of capital
+        NC_("Stock Assistant: Transaction Type", "Return of Capital"),
+        N_("Stock returns capital to holder")
+    },
+    {
+        FieldMask::DISABLED,               // stock_amt
+        FieldMask::ENABLED_DEBIT,          // stock_val
+        FieldMask::DISABLED,               // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        false,                  // fees_capitalize
+        FieldMask::ENABLED_CREDIT,         // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing a
+        // notional distribution
+        NC_("Stock Assistant: Transaction Type", "Notional distribution"),
+        N_("Stock returns a notional distribution")
+    },
+    {
+        FieldMask::ENABLED_DEBIT,          // stock_amt
+        FieldMask::DISABLED,               // stock_val
+        FieldMask::DISABLED,               // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        true,                   // fees_capitalize
+        FieldMask::DISABLED,               // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing a stock
+        // split
+        NC_("Stock Assistant: Transaction Type", "Stock split"),
+        N_("Stock price is fractionally reduced")
+    },
+    {
+        FieldMask::ENABLED_CREDIT,         // stock_amt
+        FieldMask::DISABLED,               // stock_val
+        FieldMask::DISABLED,               // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        true,                   // fees_capitalize
+        FieldMask::DISABLED,               // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing a reverse split
+        NC_("Stock Assistant: Transaction Type", "Reverse split"),
+        N_("Stock price is fractionally increased.")
+    },
+    {
+        FieldMask::ENABLED_CREDIT,         // stock_amt
+        FieldMask::ENABLED_CREDIT,         // stock_val
+        FieldMask::ENABLED_DEBIT,          // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        false,                  // fees_capitalize
+        FieldMask::DISABLED,               // dividend_amt
+        FieldMask::ENABLED_CREDIT | FieldMask::ALLOW_ZERO | FieldMask::ALLOW_NEGATIVE, // capgains_amt
+        // Translators: this is a stock transaction describing a
+        // reverse split. Some fractional stock is returned as cash.
+        NC_("Stock Assistant: Transaction Type", "Reverse split w/ cash in lieu for fractionals"),
+        N_("Stock price is fractionally increased. Fractional remaining stock is returned as cash.")
+    },
+};
+
+static const TxnTypeVec short_types
+{
+    {
+        FieldMask::ENABLED_DEBIT,          // stock_amt
+        FieldMask::ENABLED_DEBIT,          // stock_val
+        FieldMask::ENABLED_CREDIT,         // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        true,                   // fees_capitalize
+        FieldMask::DISABLED,               // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing
+        // shorting of stock.
+        NC_("Stock Assistant: Transaction Type", "Short sell"),
+        N_("Shorting stock.")
+    },
+    {
+        FieldMask::ENABLED_DEBIT,          // stock_amt
+        FieldMask::ENABLED_DEBIT,          // stock_val
+        FieldMask::ENABLED_CREDIT,         // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        false,                  // fees_capitalize
+        FieldMask::DISABLED,               // dividend_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO | FieldMask::ALLOW_NEGATIVE,          // capg_amt
+        // Translators: this is a stock transaction describing cover
+        // buying stock, and recording capital gains/loss
+        NC_("Stock Assistant: Transaction Type", "Cover buy"),
+        N_("Cover buying stock, and record capital gains/loss")
+    },
+    {
+        FieldMask::DISABLED,               // stock_amt
+        FieldMask::DISABLED,               // stock_val
+        FieldMask::ENABLED_CREDIT,         // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        false,                  // fees_capitalize
+        FieldMask::ENABLED_DEBIT,          // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing
+        // dividends retrieved from holder when shorting stock
+        NC_("Stock Assistant: Transaction Type", "Compensatory Dividend"),
+        N_("Company issues dividends to holder when shorting stock")
+    },
+    {
+        FieldMask::ENABLED_CREDIT,         // stock_amt
+        FieldMask::ENABLED_CREDIT,         // stock_val
+        FieldMask::ENABLED_DEBIT,          // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        true,                   // fees_capitalize
+        FieldMask::ENABLED_DEBIT,          // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing
+        // dividends retrieved from holder when shorting stock. Some
+        // dividends are recovered from holder
+        NC_("Stock Assistant: Transaction Type", "Dividend reinvestment (w/ remainder)"),
+        N_("Company issues dividends to holder when shorting stock. Some dividends are recovered from holder")
+    },
+    {
+        FieldMask::ENABLED_DEBIT,          // stock_amt
+        FieldMask::ENABLED_DEBIT,          // stock_val
+        FieldMask::DISABLED,               // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        true,                   // fees_capitalize
+        FieldMask::ENABLED_DEBIT,          // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing
+        // dividends retrieved from holder when shorting stock,
+        NC_("Stock Assistant: Transaction Type", "Dividend reinvestment (w/o remainder)"),
+        N_("Company issues dividend when shorting stock, which are wholly recovered from holder.")
+    },
+    {
+        FieldMask::DISABLED,               // stock_amt
+        FieldMask::ENABLED_DEBIT,          // stock_val
+        FieldMask::ENABLED_CREDIT,         // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        true,                   // fees_capitalize
+        FieldMask::DISABLED,               // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing return
+        // of capital retrieved from holder when shorting stock
+        NC_("Stock Assistant: Transaction Type", "Compensatory Return of Capital"),
+        N_("Return retrieves capital from holder when shorting stock")
+    },
+    {
+        FieldMask::DISABLED,               // stock_amt
+        FieldMask::ENABLED_CREDIT,         // stock_val
+        FieldMask::DISABLED,               // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        false,                  // fees_capitalize
+        FieldMask::ENABLED_DEBIT,          // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing a
+        // notional distribution when shorting stock
+        NC_("Stock Assistant: Transaction Type", "Compensatory Notional distribution"),
+        N_("Stock retrieves a notional distribution")
+    },
+    {
+        FieldMask::ENABLED_CREDIT,         // stock_amt
+        FieldMask::DISABLED,               // stock_val
+        FieldMask::DISABLED,               // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        true,                   // fees_capitalize
+        FieldMask::DISABLED,               // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing a stock
+        // split when shorting stock
+        NC_("Stock Assistant: Transaction Type", "Stock split"),
+        N_("Stock price is fractionally reduced when shorting stock")
+    },
+    {
+        FieldMask::ENABLED_DEBIT,          // stock_amt
+        FieldMask::DISABLED,               // stock_val
+        FieldMask::DISABLED,               // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        true,                   // fees_capitalize
+        FieldMask::DISABLED,               // dividend_amt
+        FieldMask::DISABLED,               // capg_amt
+        // Translators: this is a stock transaction describing a
+        // reverse split when shorting stock.
+        NC_("Stock Assistant: Transaction Type", "Reverse split"),
+        N_("Stock price is fractionally increased when shorting stock.")
+    },
+    {
+        FieldMask::ENABLED_DEBIT,          // stock_amt
+        FieldMask::ENABLED_DEBIT,          // stock_val
+        FieldMask::ENABLED_CREDIT,         // cash_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO,          // fees_amt
+        false,                  // fees_capitalize
+        FieldMask::DISABLED,               // dividend_amt
+        FieldMask::ENABLED_DEBIT | FieldMask::ALLOW_ZERO | FieldMask::ALLOW_NEGATIVE,          // capg_amt
+        // Translators: this is a stock transaction describing a
+        // reverse split when shorting stock. Fractional remaining
+        // stock is retrieved as cash.
+        NC_("Stock Assistant: Transaction Type", "Reverse split w/ cash in lieu for fractionals"),
+        N_("Stock price is fractionally increased when shorting stock. Fractional remaining stock is retrieved as cash.")
+    },
+};
+
+typedef struct
+{
+    GtkWidget * window;
+    GtkWidget * assistant;
+
+    const TxnTypeVec * txn_types;
+    Account   * acct;
+    gnc_commodity * currency;
+
+    // transaction type page
+    GtkWidget * transaction_type_page;
+    GtkWidget * transaction_type_combo;
+    GtkWidget * transaction_type_explanation;
+    const TxnTypeInfo * txn_type;
+
+    // transaction details page
+    GtkWidget * transaction_details_page;
+    GtkWidget * date_edit;
+    GtkWidget * transaction_description_entry;
+
+    // stock amount page
+    gnc_numeric balance_at_date;
+    GtkWidget * stock_amount_page;
+    GtkWidget * prev_amount;
+    GtkWidget * next_amount;
+    GtkWidget * stock_amount_edit;
+
+    // stock value page
+    GtkWidget * stock_value_page;
+    GtkWidget * stock_value_edit;
+    GtkWidget * price_value;
+    GtkWidget * stock_memo_edit;
+
+    // cash page
+    GtkWidget * cash_page;
+    GtkWidget * cash_account;
+    GtkWidget * cash_memo_edit;
+    GtkWidget * cash_value;
+
+    // fees page
+    GtkWidget * fees_page;
+    GtkWidget * capitalize_fees_checkbox;
+    GtkWidget * fees_account;
+    GtkWidget * fees_memo_edit;
+    GtkWidget * fees_value;
+
+    // dividend page
+    GtkWidget * dividend_page;
+    GtkWidget * dividend_account;
+    GtkWidget * dividend_memo_edit;
+    GtkWidget * dividend_value;
+
+    // capgains page
+    GtkWidget * capgains_page;
+    GtkWidget * capgains_account;
+    GtkWidget * capgains_memo_edit;
+    GtkWidget * capgains_value;
+
+    // finish page
+    GtkWidget * finish_page;
+    GtkWidget * finish_split_view;
+    GtkWidget * finish_summary;
+} StockTransactionInfo;
+
+
+/******* implementations ***********************************************/
+static void
+stock_assistant_window_destroy_cb (GtkWidget *object, gpointer user_data)
+{
+    auto info = static_cast<StockTransactionInfo*>(user_data);
+    gnc_unregister_gui_component_by_data (ASSISTANT_STOCK_TRANSACTION_CM_CLASS, info);
+    g_free (info);
+}
+
+static void
+refresh_page_transaction_type (GtkWidget *widget, gpointer user_data)
+{
+    auto info = static_cast<StockTransactionInfo*>(user_data);
+
+    auto type_idx = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
+    if (type_idx < 0)           // combo isn't initialized yet.
+        return;
+
+    info->txn_type = &(info->txn_types->at (type_idx));
+
+    gtk_label_set_text (GTK_LABEL (info->transaction_type_explanation),
+                        _(info->txn_type->explanation));
+
+    // set default capitalize fees setting
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (info->capitalize_fees_checkbox),
+                                  info->txn_type->fees_capitalize);
+}
+
+
+static void
+refresh_page_stock_amount (GtkWidget *widget, gpointer user_data)
+{
+    auto info = static_cast<StockTransactionInfo*>(user_data);
+
+    auto pinfo = gnc_commodity_print_info (xaccAccountGetCommodity (info->acct), true);
+    auto bal = info->balance_at_date;
+    gtk_label_set_text (GTK_LABEL(info->prev_amount), xaccPrintAmount (bal, pinfo));
+
+    gnc_numeric stock_amount;
+
+    if (gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT (info->stock_amount_edit),
+                                       &stock_amount, true, nullptr))
+        gtk_label_set_text (GTK_LABEL(info->next_amount), nullptr);
+    else
+    {
+        if (info->txn_type->stock_amount == FieldMask::ENABLED_CREDIT)
+            stock_amount = gnc_numeric_neg (stock_amount);
+        bal = gnc_numeric_add_fixed (bal, stock_amount);
+
+        gtk_label_set_text (GTK_LABEL(info->next_amount),
+                            xaccPrintAmount (bal, pinfo));
+    }
+}
+
+
+static void
+refresh_page_stock_value (GtkWidget *widget, gpointer user_data)
+{
+    auto info = static_cast<StockTransactionInfo*>(user_data);
+    gnc_numeric amount, value;
+
+    if (info->txn_type->stock_amount == FieldMask::DISABLED ||
+        info->txn_type->stock_value == FieldMask::DISABLED ||
+        gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT (info->stock_amount_edit), &amount, true, nullptr) ||
+        gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT (info->stock_value_edit),  &value,  true, nullptr) || 
+        gnc_numeric_zero_p (value))
+    {
+        // Translators: StockAssistant: N/A denotes stock price is not computable
+        const char* na_label =  N_("N/A");
+        gtk_label_set_text (GTK_LABEL (info->price_value), _(na_label));
+        return;
+    }
+
+    auto price = gnc_numeric_div (value, amount, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND);
+    auto pinfo = gnc_commodity_print_info (info->currency, true);
+    gtk_label_set_text (GTK_LABEL (info->price_value), xaccPrintAmount (price, pinfo));
+}
+
+static void
+refresh_page_cash (GtkWidget *widget, gpointer user_data)
+{
+    return;
+}
+
+static void
+refresh_page_fees (GtkWidget *widget, gpointer user_data)
+{
+    auto info = static_cast<StockTransactionInfo*>(user_data);
+    auto capitalize_fees = gtk_toggle_button_get_active
+        (GTK_TOGGLE_BUTTON (info->capitalize_fees_checkbox));
+    gtk_widget_set_sensitive (info->fees_account, !capitalize_fees);
+}
+
+static void
+refresh_page_dividend (GtkWidget *widget, gpointer user_data)
+{
+    return;
+}
+
+static void
+refresh_page_capgains (GtkWidget *widget, gpointer user_data)
+{
+    return;
+}
+
+static void
+add_error (StringVec& errors, const char* format_str, const char* arg)
+{
+    gchar *buf = g_strdup_printf (_(format_str),
+                                  g_dpgettext2 (nullptr, "Stock Assistant: Page name", arg));
+    errors.emplace_back (buf);
+    g_free (buf);
+}
+
+static void
+add_error_str (StringVec& errors, const char* str)
+{
+    errors.emplace_back (_(str));
+}
+
+static void
+check_page (GtkListStore *list, gnc_numeric& debit, gnc_numeric& credit,
+            FieldMask splitfield, Account *acct, GtkWidget *memo, GtkWidget *gae,
+            gnc_commodity *comm, bool ignore_account,
+            const char* page, StringVec& errors)
+{
+    if (splitfield == FieldMask::DISABLED)
+        return;
+    const char* missing_str = N_("(missing)");
+    const gchar* amtstr;
+    gnc_numeric amount;
+    bool debit_side = (splitfield & FieldMask::ENABLED_DEBIT);
+
+    if (gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT (gae), &amount, true, nullptr))
+    {
+        if (splitfield & FieldMask::ALLOW_ZERO)
+            amtstr = "";
+        else
+        {
+            add_error (errors, N_("Amount for %s is missing"), page);
+            amtstr = _(missing_str);
+        }
+    }
+    else
+    {
+        if (!(splitfield & FieldMask::ALLOW_NEGATIVE))
+        {
+            if ((splitfield & FieldMask::ALLOW_ZERO) && gnc_numeric_negative_p (amount))
+                add_error (errors, N_("Amount for %s must not be negative."), page);
+            else if (!(splitfield & FieldMask::ALLOW_ZERO) && !gnc_numeric_positive_p (amount))
+                add_error (errors, N_("Amount for %s must be positive."), page);
+        }
+        if (gnc_numeric_negative_p (amount))
+        {
+            amount = gnc_numeric_neg (amount);
+            debit_side = !debit_side;
+        }
+        if (debit_side)
+            debit = gnc_numeric_add_fixed (debit, amount);
+        else
+            credit = gnc_numeric_add_fixed (credit, amount);
+        amtstr = xaccPrintAmount (amount, gnc_commodity_print_info (comm, true));
+    }
+
+    auto memostr = gtk_entry_get_text (GTK_ENTRY (memo));
+    const gchar *acctstr;
+
+    if (ignore_account)
+        acctstr = "";
+    else if (acct)
+        acctstr = xaccAccountGetName (acct);
+    else
+    {
+        add_error (errors, N_("Account for %s is missing"), page);
+        acctstr = _(missing_str);
+    }
+
+    GtkTreeIter iter;
+    gtk_list_store_append (list, &iter);
+    gtk_list_store_set (list, &iter,
+                        SPLIT_COL_ACCOUNT, acctstr,
+                        SPLIT_COL_MEMO, memostr,
+                        SPLIT_COL_DEBIT, debit_side ? amtstr : "",
+                        SPLIT_COL_CREDIT, !debit_side ? amtstr : "",
+                        -1);
+}
+
+static inline Account*
+gas_account (GtkWidget *gas)
+{
+    return gnc_account_sel_get_account (GNC_ACCOUNT_SEL (gas));
+}
+
+static void
+refresh_page_finish (StockTransactionInfo *info)
+{
+    auto view = GTK_TREE_VIEW (info->finish_split_view);
+    auto list = GTK_LIST_STORE (gtk_tree_view_get_model(view));
+    gtk_list_store_clear (list);
+
+    gnc_numeric debit = gnc_numeric_zero ();
+    gnc_numeric credit = gnc_numeric_zero ();
+    StringVec errors;
+
+    if (info->txn_type->stock_amount != FieldMask::DISABLED)
+    {
+        auto stock_amount = gnc_amount_edit_get_amount
+            (GNC_AMOUNT_EDIT(info->stock_amount_edit));
+        if (info->txn_type->stock_amount & FieldMask::ENABLED_CREDIT)
+            stock_amount = gnc_numeric_neg (stock_amount);
+        auto new_bal = gnc_numeric_add_fixed (info->balance_at_date, stock_amount);
+        if (gnc_numeric_positive_p (info->balance_at_date) &&
+            gnc_numeric_negative_p (new_bal))
+            add_error_str (errors, N_("Cannot sell more units than owned"));
+        else if (gnc_numeric_negative_p (info->balance_at_date) &&
+                 gnc_numeric_positive_p (new_bal))
+            add_error_str (errors, N_("Cannot cover buy more units than owed"));
+    }
+
+    check_page (list, debit, credit, info->txn_type->stock_value, info->acct,
+                info->stock_memo_edit, info->stock_value_edit, info->currency,
+                false, NC_ ("Stock Assistant: Page name", "stock value"), errors);
+
+    check_page (list, debit, credit, info->txn_type->cash_value,
+                gas_account (info->cash_account), info->cash_memo_edit,
+                info->cash_value, info->currency, false,
+                NC_ ("Stock Assistant: Page name", "cash"), errors);
+
+    check_page (list, debit, credit, info->txn_type->fees_value,
+                gas_account (info->fees_account), info->fees_memo_edit,
+                info->fees_value, info->currency,
+                gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
+                                              (info->capitalize_fees_checkbox)),
+                NC_ ("Stock Assistant: Page name", "fees"), errors);
+
+    check_page (list, debit, credit, info->txn_type->dividend_value,
+                gas_account (info->dividend_account),
+                info->dividend_memo_edit, info->dividend_value, info->currency,
+                false, NC_ ("Stock Assistant: Page name", "dividend"), errors);
+
+    // the next two checks will involve the two capgains splits:
+    // income side and stock side. The capgains_value ^
+    // (FieldMask::ENABLED_CREDIT | FieldMask::ENABLED_DEBIT) will swap the debit/credit
+    // flags.
+    if (info->txn_type->capgains_value != FieldMask::DISABLED)
+    {
+        check_page (list, debit, credit, info->txn_type->capgains_value,
+                    gas_account (info->capgains_account),
+                    info->capgains_memo_edit, info->capgains_value, info->currency,
+                    false, NC_ ("Stock Assistant: Page name", "capital gains"), errors);
+
+        check_page (list, debit, credit,
+                    info->txn_type->capgains_value ^ (FieldMask::ENABLED_CREDIT | FieldMask::ENABLED_DEBIT),
+                    info->acct, info->capgains_memo_edit, info->capgains_value,
+                    info->currency, false,
+                    NC_ ("Stock Assistant: Page name", "capital gains"), errors);
+    }
+
+    if (!gnc_numeric_equal (debit, credit))
+        add_error_str (errors, N_("Debits and credits are not balanced"));
+
+    if (errors.empty())
+    {
+        auto success_msg = N_("No errors found. Click Apply to create transaction.");
+        gtk_assistant_set_page_complete (GTK_ASSISTANT (info->window),
+                                         info->finish_page, true);
+        gtk_label_set_text (GTK_LABEL (info->finish_summary), _(success_msg));
+    }
+    else
+    {
+        auto header_str = N_("The following errors must be fixed:");
+        auto header = std::string { _(header_str) };
+        auto fold = [](auto a, auto b) { return std::move(a) + '\n' + std::move(b); };
+        auto errmsg { std::accumulate (errors.begin(), errors.end(), header, fold) };
+        gtk_assistant_set_page_complete (GTK_ASSISTANT (info->window),
+                                         info->finish_page, false);
+        gtk_label_set_text (GTK_LABEL (info->finish_summary), errmsg.c_str());
+    }
+}
+
+void
+stock_assistant_prepare (GtkAssistant  *assistant, GtkWidget *page,
+                         gpointer user_data)
+{
+    auto info = static_cast<StockTransactionInfo*>(user_data);
+    gint currentpage = gtk_assistant_get_current_page(assistant);
+
+    switch (currentpage)
+    {
+    case PAGE_TRANSACTION_TYPE:
+        // initialize transaction types.
+        gtk_combo_box_text_remove_all (GTK_COMBO_BOX_TEXT (info->transaction_type_combo));
+        for (auto& it : *(info->txn_types))
+            gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (info->transaction_type_combo),
+                                            g_dpgettext2 (nullptr, "Stock Assistant: Transaction Type",
+                                                          it.friendly_name));
+        gtk_combo_box_set_active (GTK_COMBO_BOX (info->transaction_type_combo), 0);
+        refresh_page_transaction_type (info->transaction_type_combo, info);
+        gtk_widget_grab_focus (info->transaction_type_combo);
+        break;
+    case PAGE_STOCK_AMOUNT:
+        info->balance_at_date = xaccAccountGetBalanceAsOfDate
+            (info->acct, gnc_date_edit_get_date_end (GNC_DATE_EDIT (info->date_edit)));
+        refresh_page_stock_amount (info->stock_amount_edit, info);
+        // fixme: the following doesn't work???
+        gtk_widget_grab_focus (gnc_amount_edit_gtk_entry
+                               (GNC_AMOUNT_EDIT (info->stock_amount_edit)));
+        break;
+    case PAGE_STOCK_VALUE:
+        refresh_page_stock_value (info->stock_value_edit, info);
+        // fixme: ditto
+        gtk_widget_grab_focus (gnc_amount_edit_gtk_entry
+                               (GNC_AMOUNT_EDIT (info->stock_value_edit)));
+        break;
+    case PAGE_CASH:
+        refresh_page_cash (info->cash_value, info);
+        break;
+    case PAGE_FEES:
+        refresh_page_fees (info->fees_value, info);
+        break;
+    case PAGE_DIVIDEND:
+        refresh_page_dividend (info->fees_value, info);
+        break;
+    case PAGE_CAPGAINS:
+        refresh_page_capgains (info->capgains_value, info);
+        break;
+    case PAGE_FINISH:
+        refresh_page_finish (info);
+        break;
+    }
+}
+
+static gint
+forward_page_func (gint current_page, gpointer user_data)
+{
+    auto info = static_cast<StockTransactionInfo*>(user_data);
+    auto& txn_type = info->txn_type;
+
+    current_page++;
+    if (!txn_type)
+        return current_page;
+
+    if (txn_type->stock_amount == FieldMask::DISABLED && current_page == PAGE_STOCK_AMOUNT)
+        current_page++;
+    if (txn_type->stock_value == FieldMask::DISABLED && current_page == PAGE_STOCK_VALUE)
+        current_page++;
+    if (txn_type->cash_value == FieldMask::DISABLED && current_page == PAGE_CASH)
+        current_page++;
+    if (txn_type->fees_value == FieldMask::DISABLED && current_page == PAGE_FEES)
+        current_page++;
+    if (txn_type->dividend_value == FieldMask::DISABLED && current_page == PAGE_DIVIDEND)
+        current_page++;
+    if (txn_type->capgains_value == FieldMask::DISABLED && current_page == PAGE_CAPGAINS)
+        current_page++;
+
+    return current_page;
+}
+
+static void
+create_split (Transaction *trans, FieldMask splitfield,
+              const gchar *action, Account *account,
+              AccountVec& account_commits, GtkWidget *memo_entry,
+              GtkWidget *amount, GtkWidget *value,
+              bool skip_if_zero)
+{
+    auto amount_numeric = amount ? gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (amount)) : gnc_numeric_zero ();
+    auto value_numeric = value ? gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (value)) : gnc_numeric_zero ();
+
+    if (skip_if_zero && gnc_numeric_zero_p (value_numeric))
+        return;
+
+    if (splitfield & FieldMask::ENABLED_CREDIT)
+    {
+        amount_numeric = gnc_numeric_neg (amount_numeric);
+        value_numeric = gnc_numeric_neg (value_numeric);
+    }
+
+    auto split = xaccMallocSplit (gnc_get_current_book ());
+    xaccSplitSetParent (split, trans);
+    xaccAccountBeginEdit (account);
+    account_commits.emplace_back (account);
+    xaccSplitSetAccount (split, account);
+    xaccSplitSetMemo (split, gtk_entry_get_text (GTK_ENTRY (memo_entry)));
+    xaccSplitSetValue (split, value_numeric);
+    xaccSplitSetAmount (split, amount_numeric);
+    DEBUG ("creating %s split in Acct(%s): Val(%s), Amt(%s) => Val(%s), Amt(%s)",
+           action, xaccAccountGetName (account),
+           gnc_num_dbg_to_string (value_numeric),
+           gnc_num_dbg_to_string (amount_numeric),
+           gnc_num_dbg_to_string (xaccSplitGetValue (split)),
+           gnc_num_dbg_to_string (xaccSplitGetAmount (split)));
+    gnc_set_num_action (nullptr, split,
+                        nullptr, g_dpgettext2 (nullptr, "Stock Assistant: Action field", action));
+}
+
+static void
+add_price (GtkWidget *amount, GtkWidget *value,
+           gnc_commodity *commodity, gnc_commodity *currency, time64 date)
+{
+    auto amt = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (amount));
+    auto val = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (value));
+    auto p = gnc_numeric_div (val, amt, GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);
+    auto price = gnc_price_create (gnc_get_current_book ());
+
+    gnc_price_begin_edit (price);
+    gnc_price_set_commodity (price, commodity);
+    gnc_price_set_currency (price, currency);
+    gnc_price_set_time64 (price, date);
+    gnc_price_set_source (price, PRICE_SOURCE_STOCK_TRANSACTION);
+    gnc_price_set_typestr (price, PRICE_TYPE_UNK);
+    gnc_price_set_value (price, p);
+    gnc_price_commit_edit (price);
+
+    auto book = gnc_get_current_book ();
+    auto pdb = gnc_pricedb_get_db (book);
+
+    if (!gnc_pricedb_add_price (pdb, price))
+        PWARN ("error adding price");
+
+    gnc_price_unref (price);
+}
+
+void
+stock_assistant_finish (GtkAssistant *assistant, gpointer user_data)
+{
+    auto info = static_cast<StockTransactionInfo*>(user_data);
+    AccountVec account_commits;
+    auto book = gnc_get_current_book ();
+
+    gnc_suspend_gui_refresh ();
+
+    auto trans = xaccMallocTransaction (book);
+    xaccTransBeginEdit (trans);
+    xaccTransSetCurrency (trans, info->currency);
+    xaccTransSetDescription (trans, gtk_entry_get_text
+                             (GTK_ENTRY (info->transaction_description_entry)));
+
+    auto date = gnc_date_edit_get_date (GNC_DATE_EDIT (info->date_edit));
+    xaccTransSetDatePostedSecsNormalized (trans, date);
+
+    if (info->txn_type->stock_amount != FieldMask::DISABLED ||
+        info->txn_type->stock_value != FieldMask::DISABLED)
+        create_split (trans, info->txn_type->stock_value,
+                      NC_ ("Stock Assistant: Action field", "Stock"), info->acct,
+                      account_commits, info->stock_memo_edit, info->stock_amount_edit,
+                      info->stock_value_edit, false);
+
+    if (info->txn_type->cash_value != FieldMask::DISABLED)
+        create_split (trans, info->txn_type->cash_value,
+                      NC_ ("Stock Assistant: Action field", "Cash"),
+                      gas_account (info->cash_account),
+                      account_commits, info->cash_memo_edit, info->cash_value,
+                      info->cash_value, false);
+
+    if (info->txn_type->fees_value != FieldMask::DISABLED)
+    {
+        auto capitalize = gtk_toggle_button_get_active
+            (GTK_TOGGLE_BUTTON (info->capitalize_fees_checkbox));
+        create_split (trans, info->txn_type->fees_value,
+                      NC_ ("Stock Assistant: Action field", "Fees"),
+                      capitalize ? info->acct : gas_account (info->fees_account),
+                      account_commits, info->fees_memo_edit,
+                      capitalize ? nullptr : info->fees_value,
+                      info->fees_value, true);
+    }
+
+    if (info->txn_type->dividend_value != FieldMask::DISABLED)
+        create_split (trans, info->txn_type->dividend_value,
+                      NC_ ("Stock Assistant: Action field", "Dividend"),
+                      gas_account (info->dividend_account),
+                      account_commits, info->dividend_memo_edit,
+                      info->dividend_value, info->dividend_value, false);
+
+    if (info->txn_type->capgains_value != FieldMask::DISABLED)
+    {
+        create_split (trans, info->txn_type->capgains_value,
+                      NC_ ("Stock Assistant: Action field", "Capital Gains"),
+                      gas_account (info->capgains_account),
+                      account_commits, info->capgains_memo_edit,
+                      info->capgains_value, info->capgains_value, false);
+
+        create_split (trans,
+                      info->txn_type->capgains_value ^ (FieldMask::ENABLED_CREDIT | FieldMask::ENABLED_DEBIT),
+                      NC_ ("Stock Assistant: Action field", "Capital Gains"),
+                      info->acct, account_commits, info->capgains_memo_edit,
+                      nullptr, info->capgains_value, false);
+    }
+
+    if (info->txn_type->stock_amount != FieldMask::DISABLED &&
+        info->txn_type->stock_value != FieldMask::DISABLED)
+        add_price (info->stock_amount_edit, info->stock_value_edit,
+                   xaccAccountGetCommodity (info->acct), info->currency, date);
+
+    xaccTransCommitEdit (trans);
+
+    std::for_each (account_commits.begin(), account_commits.end(), xaccAccountCommitEdit);
+
+    gnc_resume_gui_refresh ();
+
+    gnc_close_gui_component_by_data (ASSISTANT_STOCK_TRANSACTION_CM_CLASS, info);
+}
+
+
+void
+stock_assistant_cancel (GtkAssistant *assistant, gpointer user_data)
+{
+    auto info = static_cast<StockTransactionInfo*>(user_data);
+    gnc_close_gui_component_by_data (ASSISTANT_STOCK_TRANSACTION_CM_CLASS, info);
+}
+
+static GtkWidget*
+get_widget (GtkBuilder *builder, const gchar * ID)
+{
+    g_return_val_if_fail (builder && ID, nullptr);
+    auto obj = gtk_builder_get_object (builder, ID);
+    if (!obj)
+        PWARN ("get_widget ID '%s' not found. it may be a typo?", ID);
+    return GTK_WIDGET (obj);
+}
+
+static GtkWidget*
+create_gas (GtkBuilder *builder, gint row,
+            std::vector<GNCAccountType> type, gnc_commodity *currency,
+            const gchar *table_ID, const gchar *label_ID)
+{
+    auto table = get_widget (builder, table_ID);
+    auto label = get_widget (builder, label_ID);
+    auto gas = gnc_account_sel_new ();
+    GList *acct_list = nullptr;
+    for (auto& it : type)
+        acct_list = g_list_prepend (acct_list, (gpointer)it);
+    auto curr_list = g_list_prepend (nullptr, currency);
+    gnc_account_sel_set_new_account_ability (GNC_ACCOUNT_SEL (gas), true);
+    gnc_account_sel_set_acct_filters (GNC_ACCOUNT_SEL (gas), acct_list, curr_list);
+    gtk_widget_show (gas);
+    gtk_grid_attach (GTK_GRID(table), gas, 1, row, 1, 1);
+    gtk_label_set_mnemonic_widget (GTK_LABEL(label), gas);
+    g_list_free (acct_list);
+    g_list_free (curr_list);
+    return gas;
+}
+
+static GtkWidget*
+create_gae (GtkBuilder *builder, gint row, gnc_commodity *comm,
+            const gchar *table_ID, const gchar *label_ID)
+{
+    // shares amount
+    auto table = get_widget (builder, table_ID);
+    auto label = get_widget (builder, label_ID);
+    auto info = gnc_commodity_print_info (comm, true);
+    auto gae = gnc_amount_edit_new ();
+    gnc_amount_edit_set_evaluate_on_enter (GNC_AMOUNT_EDIT (gae), TRUE);
+    gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT (gae), info);
+    gtk_grid_attach (GTK_GRID(table), gae, 1, row, 1, 1);
+    gtk_widget_show (gae);
+    gnc_amount_edit_make_mnemonic_target (GNC_AMOUNT_EDIT (gae), label);
+    return gae;
+}
+
+static GtkWidget*
+create_date (GtkBuilder *builder, guint row,
+             const gchar *date_label, const gchar *table_label)
+{
+    auto date = gnc_date_edit_new (gnc_time (NULL), FALSE, FALSE);
+    auto label = get_widget (builder, date_label);
+    gtk_grid_attach (GTK_GRID(get_widget (builder, table_label)), date, 1, row, 1, 1);
+    gtk_widget_show (date);
+    gnc_date_make_mnemonic_target (GNC_DATE_EDIT(date), label);
+    return date;
+}
+
+static GtkWidget*
+get_treeview (GtkBuilder *builder, const gchar *treeview_label)
+{
+    auto view = GTK_TREE_VIEW (get_widget (builder, "transaction_view"));
+    gtk_tree_view_set_grid_lines (GTK_TREE_VIEW(view), gnc_tree_view_get_grid_lines_pref ());
+
+    auto store = gtk_list_store_new (NUM_SPLIT_COLS, G_TYPE_STRING, G_TYPE_STRING,
+                                     G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+    gtk_tree_view_set_model(view, GTK_TREE_MODEL(store));
+    g_object_unref(store);
+
+    auto renderer = gtk_cell_renderer_text_new();
+    auto column = gtk_tree_view_column_new_with_attributes
+        (_("Account"), renderer, "text", SPLIT_COL_ACCOUNT, nullptr);
+    gtk_tree_view_append_column(view, column);
+
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes
+        (_("Memo"), renderer, "text", SPLIT_COL_MEMO, nullptr);
+    gtk_tree_view_append_column(view, column);
+
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes
+        (_("Debit"), renderer, "text", SPLIT_COL_DEBIT, nullptr);
+    gtk_tree_view_append_column(view, column);
+
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes
+        (_("Credit"), renderer, "text", SPLIT_COL_CREDIT, nullptr);
+    gtk_tree_view_append_column(view, column);
+
+    return GTK_WIDGET (view);
+}
+
+static GtkWidget *
+stock_assistant_create (StockTransactionInfo *info)
+{
+    auto builder = gtk_builder_new();
+    gnc_builder_add_from_file  (builder , "assistant-stock-transaction.glade", "stock_transaction_assistant");
+    info->window = get_widget (builder, "stock_transaction_assistant");
+
+    // Set the name for this assistant so it can be easily manipulated with css
+    gtk_widget_set_name (GTK_WIDGET(info->window), "gnc-id-assistant-stock-transaction");
+
+    auto balance = xaccAccountGetBalance (info->acct);
+    info->txn_types = gnc_numeric_zero_p (balance) ? &starting_types
+        : gnc_numeric_positive_p (balance) ? &long_types
+        : &short_types;
+
+    info->currency = gnc_account_get_currency_or_parent (info->acct);
+
+    /* Transaction Page Widgets */
+    info->transaction_type_page = get_widget (builder, "transaction_type_page");
+    info->transaction_type_combo = get_widget (builder, "transaction_type_page_combobox");
+    info->transaction_type_explanation = get_widget (builder, "transaction_type_page_explanation");
+    g_signal_connect (info->transaction_type_combo, "changed",
+                      G_CALLBACK (refresh_page_transaction_type), info);
+
+    /* Transaction Details Widgets */
+    info->transaction_details_page = get_widget (builder, "transaction_details_page");
+    info->date_edit = create_date (builder, 0, "transaction_date_label", "transaction_details_table");
+    info->transaction_description_entry = get_widget (builder, "transaction_description_entry");
+
+    /* Stock Amount Page Widgets */
+    info->stock_amount_page = get_widget (builder, "stock_amount_page");
+    info->prev_amount = get_widget (builder, "prev_balance_amount");
+    info->stock_amount_edit = create_gae (builder, 1, xaccAccountGetCommodity (info->acct), "stock_amount_table", "stock_amount_label");
+    info->next_amount = get_widget (builder, "next_balance_amount");
+    g_signal_connect (info->stock_amount_edit, "changed",
+                      G_CALLBACK (refresh_page_stock_amount), info);
+
+    /* Stock Value Page Widgets */
+    info->stock_value_page = get_widget (builder, "stock_value_page");
+    info->stock_value_edit = create_gae (builder, 0, info->currency, "stock_value_table", "stock_value_label");
+    info->price_value = get_widget (builder, "stock_price_amount");
+    info->stock_memo_edit = get_widget (builder, "stock_memo_entry");
+    g_signal_connect (info->stock_value_edit, "changed",
+                      G_CALLBACK (refresh_page_stock_value), info);
+
+    /* Cash Page Widgets */
+    info->cash_page = get_widget (builder, "cash_details_page");
+    info->cash_account = create_gas (builder, 0, { ACCT_TYPE_ASSET, ACCT_TYPE_BANK }, info->currency,  "cash_table", "cash_account_label");
+    info->cash_value = create_gae (builder, 1, info->currency, "cash_table", "cash_label");
+    info->cash_memo_edit = get_widget (builder, "cash_memo_entry");
+
+    /* Fees Page Widgets */
+    info->fees_page = get_widget (builder, "fees_details_page");
+    info->capitalize_fees_checkbox = get_widget (builder, "capitalize_fees_checkbutton");
+    info->fees_account = create_gas (builder, 1, { ACCT_TYPE_EXPENSE }, info->currency, "fees_table", "fees_account_label");
+    info->fees_value = create_gae (builder, 2, info->currency, "fees_table", "fees_label");
+    info->fees_memo_edit = get_widget (builder, "fees_memo_entry");
+    g_signal_connect (info->capitalize_fees_checkbox, "toggled",
+                      G_CALLBACK (refresh_page_fees), info);
+
+    /* Divi Page Widgets */
+    info->dividend_page = get_widget (builder, "dividend_details_page");
+    info->dividend_account = create_gas (builder, 0, { ACCT_TYPE_INCOME }, info->currency, "dividend_table", "dividend_account_label");
+    info->dividend_value = create_gae (builder, 1, info->currency, "dividend_table", "dividend_label");
+    info->dividend_memo_edit = get_widget (builder, "dividend_memo_entry");
+
+    /* Capgains Page Widgets */
+    info->capgains_page = get_widget (builder, "capgains_details_page");
+    info->capgains_account = create_gas (builder, 0, { ACCT_TYPE_INCOME }, info->currency, "capgains_table", "capgains_account_label");
+    info->capgains_value = create_gae (builder, 1, info->currency, "capgains_table", "capgains_label");
+    info->capgains_memo_edit = get_widget (builder, "capgains_memo_entry");
+
+    /* Finish Page Widgets */
+    info->finish_page = get_widget (builder, "finish_page");
+    info->finish_split_view = get_treeview (builder, "transaction_view");
+    info->finish_summary = get_widget (builder, "finish_summary");
+    g_signal_connect (G_OBJECT(info->window), "destroy",
+                      G_CALLBACK (stock_assistant_window_destroy_cb), info);
+
+    gtk_assistant_set_forward_page_func (GTK_ASSISTANT(info->window),
+                                         (GtkAssistantPageFunc)forward_page_func,
+                                         info, nullptr);
+    gtk_builder_connect_signals(builder, info);
+    g_object_unref(G_OBJECT(builder));
+
+    return info->window;
+}
+
+static void
+refresh_handler (GHashTable *changes, gpointer user_data)
+{
+    auto info = static_cast<StockTransactionInfo*>(user_data);
+
+    if (!GNC_IS_ACCOUNT (info->acct))
+    {
+        PWARN ("account %p does not exist anymore. abort", info->acct);
+        gnc_close_gui_component_by_data (ASSISTANT_STOCK_TRANSACTION_CM_CLASS, info);
+    }
+}
+
+static void
+close_handler (gpointer user_data)
+{
+    auto info = static_cast<StockTransactionInfo*>(user_data);
+    gtk_widget_destroy (info->window);
+}
+
+/********************************************************************\
+ * gnc_stock_transaction_assistant                                  *
+ *   opens up a assistant to record a stock transaction             *
+ *                                                                  *
+ * Args:   parent  - the parent ofthis window                       *
+ *         initial - the initial account to use                     *
+ * Return: nothing                                                  *
+\********************************************************************/
+void
+gnc_stock_transaction_assistant (GtkWidget *parent, Account *account)
+{
+    StockTransactionInfo *info = g_new0 (StockTransactionInfo, 1);
+    info->acct = account;
+    stock_assistant_create (info);
+    auto component_id = gnc_register_gui_component
+        (ASSISTANT_STOCK_TRANSACTION_CM_CLASS, refresh_handler, close_handler, info);
+    gnc_gui_component_watch_entity_type (component_id, GNC_ID_ACCOUNT,
+                                         QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
+    gtk_window_set_transient_for (GTK_WINDOW (info->window), GTK_WINDOW(parent));
+    gtk_widget_show_all (info->window);
+
+    // gnc_window_adjust_for_screen (GTK_WINDOW(info->window));
+}
diff --git a/gnucash/gnome/assistant-stock-transaction.h b/gnucash/gnome/assistant-stock-transaction.h
new file mode 100644
index 000000000..3173976a4
--- /dev/null
+++ b/gnucash/gnome/assistant-stock-transaction.h
@@ -0,0 +1,38 @@
+/********************************************************************\
+ * assistant-stock-transaction.h -- stock assistant for GnuCash     *
+ * Copyright (C) 2022 Christopher Lam                               *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, contact:                        *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+\********************************************************************/
+
+#ifndef GNC_ASSISTANT_STOCK_TRANSACTION_H
+#define GNC_ASSISTANT_STOCK_TRANSACTION_H
+
+#include "Account.h"
+
+/********************************************************************\
+ * gnc_stock_transaction_assistant                                  *
+ *   opens up a assistant to record a stock transaction             *
+ *                                                                  *
+ * Args:   parent  - the parent of this window                      *
+ *         account - the initial account to use                     *
+ * Return: nothing                                                  *
+\********************************************************************/
+void gnc_stock_transaction_assistant (GtkWidget *parent, Account * account);
+
+#endif
diff --git a/gnucash/gtkbuilder/CMakeLists.txt b/gnucash/gtkbuilder/CMakeLists.txt
index 348b7a3b6..2a5201bff 100644
--- a/gnucash/gtkbuilder/CMakeLists.txt
+++ b/gnucash/gtkbuilder/CMakeLists.txt
@@ -8,6 +8,7 @@ set (gtkbuilder_SOURCES
         assistant-loan.glade
         assistant-qif-import.glade
         assistant-stock-split.glade
+        assistant-stock-transaction.glade
         assistant-xml-encoding.glade
         business-options-gnome.glade
         business-prefs.glade
diff --git a/gnucash/gtkbuilder/assistant-stock-transaction.glade b/gnucash/gtkbuilder/assistant-stock-transaction.glade
new file mode 100644
index 000000000..ac49bdc71
--- /dev/null
+++ b/gnucash/gtkbuilder/assistant-stock-transaction.glade
@@ -0,0 +1,941 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface>
+  <requires lib="gtk+" version="3.22"/>
+  <object class="GtkAssistant" id="stock_transaction_assistant">
+    <property name="can-focus">False</property>
+    <property name="halign">start</property>
+    <property name="border-width">12</property>
+    <property name="title" translatable="yes">Stock Split Assistant</property>
+    <property name="window-position">center</property>
+    <property name="default-width">500</property>
+    <signal name="cancel" handler="stock_assistant_cancel" swapped="no"/>
+    <signal name="close" handler="stock_assistant_finish" swapped="no"/>
+    <signal name="prepare" handler="stock_assistant_prepare" swapped="no"/>
+    <child>
+      <object class="GtkLabel" id="intro_page_label">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="valign">start</property>
+        <property name="margin-start">12</property>
+        <property name="margin-end">12</property>
+        <property name="label" translatable="yes">This assistant will help you record a stock transaction. The transaction type (purchase, sale, dividend, distribution, return of capital, stock split) will determine the transaction splits involved in the transaction.</property>
+        <property name="wrap">True</property>
+      </object>
+      <packing>
+        <property name="page-type">intro</property>
+        <property name="title" translatable="yes">Stock Transaction Assistant</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="transaction_type_page">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="margin-start">12</property>
+        <property name="border-width">6</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkLabel" id="transaction_type_page_label">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="margin-bottom">6</property>
+            <property name="label" translatable="yes">Select the type of stock activity that you wish to record. The available types depend on whether the current stock balance is positive, nil, or negative (i.e. when shorting stock). The type will determine the component splits.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <!-- n-columns=2 n-rows=2 -->
+          <object class="GtkGrid" id="transaction_type_table">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="row-spacing">3</property>
+            <property name="column-spacing">6</property>
+            <child>
+              <object class="GtkLabel" id="transaction_type_combo_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes">Type</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkComboBoxText" id="transaction_type_page_combobox">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <items>
+                  <item translatable="yes">a1</item>
+                  <item translatable="yes">b2</item>
+                  <item translatable="yes">c3</item>
+                </items>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="transaction_type_page_explanation">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes">label</property>
+                <property name="wrap">True</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="title" translatable="yes">Transaction Type</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="transaction_details_page">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="margin-start">12</property>
+        <property name="border-width">6</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkLabel" id="transaction_details_label">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="margin-bottom">6</property>
+            <property name="label" translatable="yes">Select the type of transaction date and description for your records.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <!-- n-columns=2 n-rows=2 -->
+          <object class="GtkGrid" id="transaction_details_table">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="row-spacing">3</property>
+            <property name="column-spacing">6</property>
+            <child>
+              <object class="GtkLabel" id="transaction_date_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes">Date</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="transaction_description_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes">Description</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="transaction_description_entry">
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="title" translatable="yes">Transaction Details</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="stock_amount_page">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="border-width">6</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkLabel" id="stock_amount_title">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="margin-bottom">6</property>
+            <property name="label" translatable="yes">Enter the date and the number of shares you gained or lost in the transaction.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <!-- n-columns=2 n-rows=3 -->
+          <object class="GtkGrid" id="stock_amount_table">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="border-width">6</property>
+            <property name="row-spacing">6</property>
+            <property name="column-spacing">6</property>
+            <child>
+              <object class="GtkLabel" id="stock_amount_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">_Shares</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="prev_balance_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">Previous Balance</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="prev_balance_amount">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">(Previous Balance)</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="next_balance_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">Next Balance</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="next_balance_amount">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">(Next Balance)</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="title" translatable="yes">Stock Amount</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="stock_value_page">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="border-width">6</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkLabel" id="stock_value_title">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="margin-bottom">6</property>
+            <property name="label" translatable="yes">Enter the value of the shares.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <!-- n-columns=2 n-rows=3 -->
+          <object class="GtkGrid" id="stock_value_table">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="border-width">6</property>
+            <property name="row-spacing">6</property>
+            <property name="column-spacing">6</property>
+            <child>
+              <object class="GtkLabel" id="stock_price_amount">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">(autocalculated price)</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="stock_memo_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">_Memo</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="stock_memo_entry">
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="stock_price_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">Price</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="stock_value_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">_Stock Value</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="title" translatable="yes">Stock Value</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="cash_details_page">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="border-width">6</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child>
+          <object class="GtkLabel" id="stock_cash_title">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="margin-bottom">6</property>
+            <property name="label" translatable="yes">In this page, input the asset account, and the monetary amount received/spent. It may differ from the stock value from the last page, if there are broker fees associated with this transaction.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <!-- n-columns=2 n-rows=3 -->
+          <object class="GtkGrid" id="cash_table">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="row-spacing">3</property>
+            <property name="column-spacing">6</property>
+            <child>
+              <object class="GtkLabel" id="cash_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">_Amount</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="cash_memo_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">_Memo</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+                <property name="mnemonic-widget">cash_memo_entry</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="cash_memo_entry">
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="hexpand">True</property>
+                <property name="invisible-char">●</property>
+                <property name="text" translatable="yes">Cash</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox" id="cash_amount_box">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="hexpand">True</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="cash_account_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">Cash Account</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+                <property name="mnemonic-widget">cash_memo_entry</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="title" translatable="yes" comments="Dialog title for the remains of a stock split">Cash</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="fees_details_page">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="border-width">6</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child>
+          <object class="GtkLabel" id="stock_fees_title">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="margin-bottom">6</property>
+            <property name="label" translatable="yes">In this page, input any broker fees incurred in this transaction. The fee may be capitalized into the asset account, or expensed into a broker fees account. Typically fees on purchase are capitalized, and fees on sales are expensed. If there are no fees involved in this transaction, it can be left blank.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <!-- n-columns=2 n-rows=4 -->
+          <object class="GtkGrid" id="fees_table">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="row-spacing">3</property>
+            <property name="column-spacing">6</property>
+            <child>
+              <object class="GtkLabel" id="fees_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">_Amount</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="fees_memo_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">_Memo</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+                <property name="mnemonic-widget">fees_memo_entry</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="fees_memo_entry">
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="hexpand">True</property>
+                <property name="invisible-char">●</property>
+                <property name="text" translatable="yes">Fees</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox" id="fees_amount_box">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="hexpand">True</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="fees_account_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">Broker Fees</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+                <property name="mnemonic-widget">fees_memo_entry</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkCheckButton" id="capitalize_fees_checkbutton">
+                <property name="label" translatable="yes">Capitalize broker fees into stock account?</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="receives-default">False</property>
+                <property name="draw-indicator">True</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
+                <property name="width">2</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="title" translatable="yes" comments="Broker Fees">Fees</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="dividend_details_page">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="border-width">6</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child>
+          <object class="GtkLabel" id="stock_dividend_title">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="margin-bottom">6</property>
+            <property name="label" translatable="yes">In this page, input any dividend income received in this transaction.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <!-- n-columns=2 n-rows=3 -->
+          <object class="GtkGrid" id="dividend_table">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="row-spacing">3</property>
+            <property name="column-spacing">6</property>
+            <child>
+              <object class="GtkLabel" id="dividend_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">_Amount</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="dividend_memo_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">_Memo</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+                <property name="mnemonic-widget">dividend_memo_entry</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="dividend_memo_entry">
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="hexpand">True</property>
+                <property name="invisible-char">●</property>
+                <property name="text" translatable="yes">Dividend</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox" id="dividend_amount_box">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="hexpand">True</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="dividend_account_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">Dividend Account</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+                <property name="mnemonic-widget">dividend_memo_entry</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="title" translatable="yes" comments="Broker Fees">Dividend</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="capgains_details_page">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="border-width">6</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child>
+          <object class="GtkLabel" id="stock_capgains_title">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="margin-bottom">6</property>
+            <property name="label" translatable="yes">In this page, input any capital gains or losses incurred, and the associated income account. Capital gains are positive, and capital losses are negative.</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <!-- n-columns=2 n-rows=3 -->
+          <object class="GtkGrid" id="capgains_table">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="row-spacing">3</property>
+            <property name="column-spacing">6</property>
+            <child>
+              <object class="GtkLabel" id="capgains_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">_Amount</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="capgains_memo_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">_Memo</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+                <property name="mnemonic-widget">capgains_memo_entry</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="capgains_memo_entry">
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="hexpand">True</property>
+                <property name="invisible-char">●</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox" id="capgains_amount_box">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="hexpand">True</property>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="capgains_account_label">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">Capital Gains Account</property>
+                <property name="use-underline">True</property>
+                <property name="justify">center</property>
+                <property name="mnemonic-widget">capgains_memo_entry</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="title" translatable="yes">Capital Gains</property>
+        <property name="complete">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkBox" id="finish_page">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="border-width">6</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child>
+          <object class="GtkLabel" id="finish_page_label">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="margin-bottom">6</property>
+            <property name="label" translatable="yes">A summary of splits is shown as follows. If the summary is correct, and there are no errors, please press "Apply". You may also press "Back" to review your choices, or "Cancel" to quit without making any changes. </property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="finish_scrolled">
+            <property name="visible">True</property>
+            <property name="can-focus">True</property>
+            <child>
+              <object class="GtkTreeView" id="transaction_view">
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection" id="transaction_view_selection">
+                    <property name="mode">browse</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="finish_summary">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="label" translatable="yes">summary of errors</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="page-type">confirm</property>
+        <property name="title" translatable="yes">Finish</property>
+      </packing>
+    </child>
+    <child internal-child="action_area">
+      <object class="GtkBox">
+        <property name="can-focus">False</property>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6c9be8e2c..1fe34570f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -52,6 +52,7 @@ gnucash/gnome/assistant-acct-period.c
 gnucash/gnome/assistant-hierarchy.c
 gnucash/gnome/assistant-loan.cpp
 gnucash/gnome/assistant-stock-split.c
+gnucash/gnome/assistant-stock-transaction.cpp
 gnucash/gnome/business-gnome-utils.c
 gnucash/gnome/business-options-gnome.c
 gnucash/gnome/business-urls.c
@@ -243,6 +244,7 @@ gnucash/gtkbuilder/assistant-hierarchy.glade
 gnucash/gtkbuilder/assistant-loan.glade
 gnucash/gtkbuilder/assistant-qif-import.glade
 gnucash/gtkbuilder/assistant-stock-split.glade
+gnucash/gtkbuilder/assistant-stock-transaction.glade
 gnucash/gtkbuilder/assistant-xml-encoding.glade
 gnucash/gtkbuilder/business-options-gnome.glade
 gnucash/gtkbuilder/business-prefs.glade

commit 0052e3e48342e52ef622cd3752eba4f52eb59acf
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Fri Mar 11 14:29:56 2022 +0800

    [gnc-pricedb] add user:stock-transaction price source

diff --git a/libgnucash/engine/gnc-pricedb.c b/libgnucash/engine/gnc-pricedb.c
index 8e4abc405..777e9f8a4 100644
--- a/libgnucash/engine/gnc-pricedb.c
+++ b/libgnucash/engine/gnc-pricedb.c
@@ -126,6 +126,7 @@ static const char* source_names[(size_t)PRICE_SOURCE_INVALID + 1] =
     "user:split-register",
     "user:split-import",
     "user:stock-split",
+    "user:stock-transaction",
     "user:invoice-post", /* Retained for backwards compatibility */
     "temporary",
     "invalid"
diff --git a/libgnucash/engine/gnc-pricedb.h b/libgnucash/engine/gnc-pricedb.h
index d64768240..0d769c040 100644
--- a/libgnucash/engine/gnc-pricedb.h
+++ b/libgnucash/engine/gnc-pricedb.h
@@ -175,6 +175,7 @@ typedef enum
     PRICE_SOURCE_SPLIT_REG,        // "user:split-register"
     PRICE_SOURCE_SPLIT_IMPORT,     // "user:split-import"
     PRICE_SOURCE_STOCK_SPLIT,      // "user:stock-split"
+    PRICE_SOURCE_STOCK_TRANSACTION,// "user:stock-transaction"
     PRICE_SOURCE_INVOICE,          // "user:invoice-post"
     PRICE_SOURCE_TEMP,             // "temporary"
     PRICE_SOURCE_INVALID,          // "invalid"



Summary of changes:
 gnucash/gnome/CMakeLists.txt                       |    2 +
 gnucash/gnome/assistant-stock-transaction.cpp      | 1225 ++++++++++++++++++++
 ...acct-period.h => assistant-stock-transaction.h} |   20 +-
 gnucash/gnome/gnc-plugin-page-register.c           |   44 +
 gnucash/gtkbuilder/CMakeLists.txt                  |    1 +
 .../gtkbuilder/assistant-stock-transaction.glade   |  941 +++++++++++++++
 gnucash/ui/gnc-plugin-page-register-ui.xml         |    1 +
 libgnucash/engine/gnc-pricedb.c                    |    1 +
 libgnucash/engine/gnc-pricedb.h                    |    1 +
 po/POTFILES.in                                     |    2 +
 10 files changed, 2229 insertions(+), 9 deletions(-)
 create mode 100644 gnucash/gnome/assistant-stock-transaction.cpp
 copy gnucash/gnome/{assistant-acct-period.h => assistant-stock-transaction.h} (74%)
 create mode 100644 gnucash/gtkbuilder/assistant-stock-transaction.glade



More information about the gnucash-changes mailing list