[GNC-dev] Fwd: gnucash master: Multiple changes pushed

Christopher Lam christopher.lck at gmail.com
Thu May 14 07:01:45 EDT 2020


Small warning/notice is warranted:
This will automatically modify datafile to add feature as follows.

      <slot>
        <slot:key>Register sort and filter settings stored in .gcm
file</slot:key>
        <slot:value type="string">Store the register sort and filter
settings in .gcm metadata file (requires at least GnuCash 3.3)</slot:value>
      </slot>

---------- Forwarded message ---------
From: Robert Fewell <bobit at code.gnucash.org>
Date: Thu, 14 May 2020 at 09:36
Subject: gnucash master: Multiple changes pushed
To: <gnucash-changes at gnucash.org>


Updated  via  https://github.com/Gnucash/gnucash/commit/6fb50d22 (commit)
         via  https://github.com/Gnucash/gnucash/commit/bf9c4441 (commit)
         via  https://github.com/Gnucash/gnucash/commit/b6de2981 (commit)
         via  https://github.com/Gnucash/gnucash/commit/2494ad1a (commit)
         via  https://github.com/Gnucash/gnucash/commit/74abd821 (commit)
         via  https://github.com/Gnucash/gnucash/commit/4c8ebfe1 (commit)
         via  https://github.com/Gnucash/gnucash/commit/2f5225ad (commit)
         via  https://github.com/Gnucash/gnucash/commit/b622518f (commit)
        from  https://github.com/Gnucash/gnucash/commit/a874483b (commit)



commit 6fb50d227a2a07acdfcf30194a949239bdb32ad3
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sat May 2 14:45:14 2020 +0100

    Complete the move of saving register filter/sort to .gcm

    This commit changes the saving of register filter and sort information
    from KVP entries to using the .gcm file. On register load these
    settings are transferred to the .gcm file and the KVP entries removed.
    A feature flag is also set when the first register is loaded by this
    version.

diff --git a/gnucash/gnome/gnc-plugin-page-register.c
b/gnucash/gnome/gnc-plugin-page-register.c
index 36ff606ac..5229de385 100644
--- a/gnucash/gnome/gnc-plugin-page-register.c
+++ b/gnucash/gnome/gnc-plugin-page-register.c
@@ -730,6 +730,10 @@ gnc_plugin_page_register_new_common (GNCLedgerDisplay*
ledger)
     gchar* label_color;
     QofQuery* q;

+    // added for version 4.0 onwards
+    if (!gnc_features_check_used (gnc_get_current_book(),
GNC_FEATURE_REG_SORT_FILTER))
+        gnc_features_set_used (gnc_get_current_book(),
GNC_FEATURE_REG_SORT_FILTER);
+
     /* Is there an existing page? */
     gsr = gnc_ledger_display_get_user_data (ledger);
     if (gsr)
@@ -1656,10 +1660,6 @@ static const gchar* style_names[] =
 #define KEY_REGISTER_STYLE      "RegisterStyle"
 #define KEY_DOUBLE_LINE         "DoubleLineMode"

-#define KEY_PAGE_SORT           "register_order"
-#define KEY_PAGE_SORT_REV       "register_reversed"
-#define KEY_PAGE_FILTER         "register_filter"
-
 #define LABEL_ACCOUNT       "Account"
 #define LABEL_SUBACCOUNT    "SubAccount"
 #define LABEL_GL            "GL"
@@ -2061,6 +2061,18 @@ gnc_plugin_page_register_get_tab_color
(GncPluginPage* plugin_page)
     return g_strdup (color ? color : "Not Set");
 }

+static void
+gnc_plugin_page_register_check_for_empty_group (GKeyFile *state_file,
const gchar *state_section)
+{
+    gsize num_keys;
+    gchar **keys = g_key_file_get_keys (state_file, state_section,
&num_keys, NULL);
+
+    if (num_keys == 0)
+        gnc_state_drop_sections_for (state_section);
+
+    g_strfreev (keys);
+}
+
 static const gchar*
 gnc_plugin_page_register_get_filter_gcm (Account* leader)
 {
@@ -2094,7 +2106,6 @@ gnc_plugin_page_register_get_filter (GncPluginPage*
plugin_page)
 {
     GncPluginPageRegisterPrivate* priv;
     GNCLedgerDisplayType ledger_type;
-    GNCLedgerDisplay* ld;
     Account* leader;
     const char* filter = NULL;

@@ -2102,19 +2113,12 @@ gnc_plugin_page_register_get_filter (GncPluginPage*
plugin_page)
                           _ ("unknown"));

     priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
-    ld = priv->ledger;
-    ledger_type = gnc_ledger_display_type (ld);
-    leader = gnc_ledger_display_leader (ld);

-    // load from gcm file for LD_GL or when feature is set
-    if (ledger_type == LD_GL ||
-        gnc_features_check_used (gnc_get_current_book(),
GNC_FEATURE_REG_SORT_FILTER))
-        filter = gnc_plugin_page_register_get_filter_gcm (leader);
-    else // load from kvp
-    {
-        if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
-            filter = xaccAccountGetFilter (leader);
-    }
+    ledger_type = gnc_ledger_display_type (priv->ledger);
+    leader = gnc_ledger_display_leader (priv->ledger);
+
+    // load from gcm file
+    filter = gnc_plugin_page_register_get_filter_gcm (leader);

     return filter ? g_strdup (filter) : g_strdup_printf ("%s,%s,%s,%s",
                                                          DEFAULT_FILTER,
@@ -2137,6 +2141,8 @@ gnc_plugin_page_register_set_filter_gcm (Account*
leader, const gchar* filter,
     {
         if (g_key_file_has_key (state_file, state_section,
KEY_PAGE_FILTER, NULL))
             g_key_file_remove_key (state_file, state_section,
KEY_PAGE_FILTER, NULL);
+
+        gnc_plugin_page_register_check_for_empty_group (state_file,
state_section);
     }
     else
     {
@@ -2156,32 +2162,20 @@ gnc_plugin_page_register_set_filter (GncPluginPage*
plugin_page,
 {
     GncPluginPageRegisterPrivate* priv;
     GNCLedgerDisplayType ledger_type;
-    GNCLedgerDisplay* ld;
     Account* leader;
     gchar* default_filter;

     priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
-    ld = priv->ledger;
-    ledger_type = gnc_ledger_display_type (ld);
-    leader = gnc_ledger_display_leader (ld);
+
+    ledger_type = gnc_ledger_display_type (priv->ledger);
+    leader = gnc_ledger_display_leader (priv->ledger);

     default_filter = g_strdup_printf ("%s,%s,%s,%s", DEFAULT_FILTER,
                                       "0", "0",
get_filter_default_num_of_days (ledger_type));

-    // save to gcm file for LD_GL or when feature is set
-    if (ledger_type == LD_GL ||
-        gnc_features_check_used (gnc_get_current_book(),
GNC_FEATURE_REG_SORT_FILTER))
-        gnc_plugin_page_register_set_filter_gcm (leader, filter,
default_filter);
-    else // save to kvp
-    {
-        if (leader != NULL)
-        {
-            if (!filter || (g_strcmp0 (filter, default_filter) == 0))
-                xaccAccountSetFilter (leader, NULL);
-            else
-                xaccAccountSetFilter (leader, filter);
-        }
-    }
+    // save to gcm file
+    gnc_plugin_page_register_set_filter_gcm (leader, filter,
default_filter);
+
     g_free (default_filter);
     return;
 }
@@ -2217,8 +2211,6 @@ static gchar*
 gnc_plugin_page_register_get_sort_order (GncPluginPage* plugin_page)
 {
     GncPluginPageRegisterPrivate* priv;
-    GNCLedgerDisplayType ledger_type;
-    GNCLedgerDisplay* ld;
     Account* leader;
     const char* sort_order = NULL;

@@ -2226,19 +2218,12 @@ gnc_plugin_page_register_get_sort_order
(GncPluginPage* plugin_page)
                           _ ("unknown"));

     priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
-    ld = priv->ledger;
-    ledger_type = gnc_ledger_display_type (ld);
-    leader = gnc_ledger_display_leader (ld);

-    // load from gcm file for LD_GL or when feature is set
-    if (ledger_type == LD_GL ||
-        gnc_features_check_used (gnc_get_current_book(),
GNC_FEATURE_REG_SORT_FILTER))
-        sort_order = gnc_plugin_page_register_get_sort_order_gcm (leader);
-    else // load from kvp
-    {
-        if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
-            sort_order = xaccAccountGetSortOrder (leader);
-    }
+    leader = gnc_ledger_display_leader (priv->ledger);
+
+    // load from gcm file
+    sort_order = gnc_plugin_page_register_get_sort_order_gcm (leader);
+
     return g_strdup (sort_order ? sort_order : DEFAULT_SORT_ORDER);
 }

@@ -2257,6 +2242,8 @@ gnc_plugin_page_register_set_sort_order_gcm (Account*
leader,
     {
         if (g_key_file_has_key (state_file, state_section, KEY_PAGE_SORT,
NULL))
             g_key_file_remove_key (state_file, state_section,
KEY_PAGE_SORT, NULL);
+
+        gnc_plugin_page_register_check_for_empty_group (state_file,
state_section);
     }
     else
         g_key_file_set_string (state_file, state_section, KEY_PAGE_SORT,
sort_order);
@@ -2268,30 +2255,14 @@ gnc_plugin_page_register_set_sort_order
(GncPluginPage* plugin_page,
                                          const gchar* sort_order)
 {
     GncPluginPageRegisterPrivate* priv;
-    GNCLedgerDisplayType ledger_type;
-    GNCLedgerDisplay* ld;
     Account* leader;

     priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
-    ld = priv->ledger;
-    ledger_type = gnc_ledger_display_type (ld);
-    leader = gnc_ledger_display_leader (ld);

-    // save to gcm file for LD_GL or when feature is set
-    if (ledger_type == LD_GL ||
-        gnc_features_check_used (gnc_get_current_book(),
GNC_FEATURE_REG_SORT_FILTER))
-        gnc_plugin_page_register_set_sort_order_gcm (leader, sort_order);
-    else // save to kvp
-    {
-        if (leader != NULL)
-        {
-            if (!sort_order || (g_strcmp0 (sort_order, DEFAULT_SORT_ORDER)
== 0))
-                xaccAccountSetSortOrder (leader, NULL);
-            else
-                xaccAccountSetSortOrder (leader, sort_order);
-        }
-    }
-    return;
+    leader = gnc_ledger_display_leader (priv->ledger);
+
+    // save to gcm file
+    gnc_plugin_page_register_set_sort_order_gcm (leader, sort_order);
 }

 static gboolean
@@ -2320,27 +2291,17 @@ static gboolean
 gnc_plugin_page_register_get_sort_reversed (GncPluginPage* plugin_page)
 {
     GncPluginPageRegisterPrivate* priv;
-    GNCLedgerDisplayType ledger_type;
-    GNCLedgerDisplay* ld;
     Account* leader;
     gboolean sort_reversed = FALSE;

     g_return_val_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page),
FALSE);

     priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
-    ld = priv->ledger;
-    ledger_type = gnc_ledger_display_type (ld);
-    leader = gnc_ledger_display_leader (ld);

-    // load from gcm file for LD_GL or when feature is set
-    if (ledger_type == LD_GL ||
-        gnc_features_check_used (gnc_get_current_book(),
GNC_FEATURE_REG_SORT_FILTER))
-        sort_reversed = gnc_plugin_page_register_get_sort_reversed_gcm
(leader);
-    else // load from kvp
-    {
-        if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
-            sort_reversed = xaccAccountGetSortReversed (leader);
-    }
+    leader = gnc_ledger_display_leader (priv->ledger);
+
+    // load from gcm file
+    sort_reversed = gnc_plugin_page_register_get_sort_reversed_gcm
(leader);
     return sort_reversed;
 }

@@ -2359,6 +2320,8 @@ gnc_plugin_page_register_set_sort_reversed_gcm
(Account* leader,
     {
         if (g_key_file_has_key (state_file, state_section,
KEY_PAGE_SORT_REV, NULL))
             g_key_file_remove_key (state_file, state_section,
KEY_PAGE_SORT_REV, NULL);
+
+        gnc_plugin_page_register_check_for_empty_group (state_file,
state_section);
     }
     else
         g_key_file_set_boolean (state_file, state_section,
KEY_PAGE_SORT_REV,
@@ -2372,25 +2335,13 @@ gnc_plugin_page_register_set_sort_reversed
(GncPluginPage* plugin_page,
                                             gboolean reverse_order)
 {
     GncPluginPageRegisterPrivate* priv;
-    GNCLedgerDisplayType ledger_type;
-    GNCLedgerDisplay* ld;
     Account* leader;

     priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (plugin_page);
-    ld = priv->ledger;
-    ledger_type = gnc_ledger_display_type (ld);
-    leader = gnc_ledger_display_leader (ld);
+    leader = gnc_ledger_display_leader (priv->ledger);

-    // save to gcm file for LD_GL or when feature is set
-    if (ledger_type == LD_GL ||
-        gnc_features_check_used (gnc_get_current_book(),
GNC_FEATURE_REG_SORT_FILTER))
-        gnc_plugin_page_register_set_sort_reversed_gcm (leader,
reverse_order);
-    else // save to kvp
-    {
-        if (leader != NULL)
-            xaccAccountSetSortReversed (leader, reverse_order);
-    }
-    return;
+    // save to gcm file
+    gnc_plugin_page_register_set_sort_reversed_gcm (leader, reverse_order);
 }

 static gchar*
@@ -2556,7 +2507,7 @@ gnc_plugin_page_register_sort_response_cb (GtkDialog*
dialog,
     else
     {
         // clear the sort when unticking the save option
-        if ((priv->sd.save_order == FALSE) &&
(priv->sd.original_save_order == TRUE))
+        if ((!priv->sd.save_order) && ((priv->sd.original_save_order) ||
(priv->sd.original_reverse_order)))
         {
             gnc_plugin_page_register_set_sort_order (plugin_page,
DEFAULT_SORT_ORDER);
             gnc_plugin_page_register_set_sort_reversed (plugin_page,
FALSE);
diff --git a/gnucash/gnome/gnc-split-reg.c b/gnucash/gnome/gnc-split-reg.c
index fd2a399f0..bc8b82571 100644
--- a/gnucash/gnome/gnc-split-reg.c
+++ b/gnucash/gnome/gnc-split-reg.c
@@ -447,6 +447,82 @@ gnc_split_reg_get_register_state_group (GNCSplitReg
*gsr)
     }
 }

+static void
+gsr_drop_register_width_state (GNCSplitReg *gsr, GKeyFile* state_file,
const gchar *state_section)
+{
+    GNCLedgerDisplayType ledger_type;
+    GNCLedgerDisplay* ld;
+
+    gboolean sort_reversed = FALSE;
+    gchar* sort_text = NULL;
+    gchar* filter_text = NULL;
+
+    // Look for any old kvp entries and add them to .gcm file
+    ledger_type = gnc_ledger_display_type (gsr->ledger);
+
+    // General ledger should already be using .gcm file
+    if ((ledger_type == LD_SINGLE) || (ledger_type == LD_SUBACCOUNT))
+    {
+        Account *leader = gnc_ledger_display_leader (gsr->ledger);
+        const char* kvp_filter = NULL;
+        const char* kvp_sort_order = NULL;
+        gboolean kvp_sort_reversed = FALSE;
+
+        kvp_filter = xaccAccountGetFilter (leader);
+        if (kvp_filter)
+        {
+            gchar *temp_filter_text = g_strdup (kvp_filter);
+            temp_filter_text = g_strdelimit (temp_filter_text, ",",
+                                             ';'); // make it conform to
.gcm file list
+            g_key_file_set_string (state_file, state_section,
KEY_PAGE_FILTER,
+                                   temp_filter_text);
+            g_free (temp_filter_text);
+            xaccAccountSetFilter (leader, NULL);
+        }
+
+        kvp_sort_order = xaccAccountGetSortOrder (leader);
+        if (kvp_sort_order)
+        {
+            g_key_file_set_string (state_file, state_section,
+                                   KEY_PAGE_SORT, kvp_sort_order);
+            xaccAccountSetSortOrder (leader, NULL);
+        }
+
+        kvp_sort_reversed = xaccAccountGetSortReversed (leader);
+        if (kvp_sort_reversed)
+        {
+            g_key_file_set_boolean (state_file, state_section,
+                                    KEY_PAGE_SORT_REV, kvp_sort_reversed);
+            xaccAccountSetSortReversed (leader, FALSE);
+        }
+    }
+
+    sort_reversed = g_key_file_get_boolean (state_file, state_section,
+                                            KEY_PAGE_SORT_REV, NULL);
+
+    sort_text = g_key_file_get_string (state_file, state_section,
+                                       KEY_PAGE_SORT, NULL);
+
+    filter_text = g_key_file_get_string (state_file, state_section,
+                                         KEY_PAGE_FILTER, NULL);
+
+    // drop the register state widths
+    gnc_state_drop_sections_for (state_section);
+
+    if (filter_text)
+        g_key_file_set_string (state_file, state_section, KEY_PAGE_FILTER,
+                               filter_text);
+    if (sort_text)
+        g_key_file_set_string (state_file, state_section, KEY_PAGE_SORT,
sort_text);
+
+    if (sort_reversed)
+        g_key_file_set_boolean (state_file, state_section,
KEY_PAGE_SORT_REV,
+                                sort_reversed);
+
+    g_free (filter_text);
+    g_free (sort_text);
+}
+
 static
 void
 gsr_create_table( GNCSplitReg *gsr )
@@ -457,9 +533,11 @@ gsr_create_table( GNCSplitReg *gsr )
     Account * account = gnc_ledger_display_leader(gsr->ledger);
     const GncGUID * guid = xaccAccountGetGUID(account);
     gchar guidstr[GUID_ENCODING_LENGTH+1];
+    GKeyFile* state_file = gnc_state_get_current();
     gchar *register_state_section;
     const gchar *default_state_section;
     const gchar *group;
+    gboolean has_date_width = FALSE;

     guid_to_string_buff (guid, guidstr);

@@ -470,9 +548,12 @@ gsr_create_table( GNCSplitReg *gsr )
     sr = gnc_ledger_display_get_split_register (gsr->ledger);
     default_state_section = gnc_split_reg_get_register_state_group (gsr);

+    // see if register group has the date_width key, old format pre 4.0
+    has_date_width = g_key_file_has_key (state_file,
register_state_section, "date_width", NULL);
+
     // if this is from a page recreate and no register state use those
settings,
-    // register state is dropped at the end of function.
-    if (gsr->page_state_name && !g_key_file_has_group
(gnc_state_get_current (), register_state_section))
+    // register state width information is dropped at the end of function.
+    if (gsr->page_state_name && !has_date_width)
         group = gsr->page_state_name;
     else
     {
@@ -505,12 +586,13 @@ gsr_create_table( GNCSplitReg *gsr )
                       G_CALLBACK(gsr_emit_show_popup_menu), gsr);

     // if no default state and register has state, copy it.
-    if (g_key_file_has_group (gnc_state_get_current (),
register_state_section))
+    if (has_date_width) // we have old register state section
     {
         if (!gnc_split_reg_register_has_user_state (gsr))
              gnc_table_save_state (sr->table, default_state_section);
-        // drop the register state
-        gnc_state_drop_sections_for (register_state_section);
+
+        // drop the register width state information
+        gsr_drop_register_width_state (gsr, state_file,
register_state_section);
     }
     g_free (register_state_section);
     LEAVE(" ");
diff --git a/gnucash/gnome/gnc-split-reg.h b/gnucash/gnome/gnc-split-reg.h
index 128e49ca6..dbd82f814 100644
--- a/gnucash/gnome/gnc-split-reg.h
+++ b/gnucash/gnome/gnc-split-reg.h
@@ -37,6 +37,9 @@
 #define IS_GNC_SPLIT_REG(obj)      G_TYPE_CHECK_INSTANCE_TYPE( obj,
gnc_split_reg_get_type() )

 #define STATE_SECTION_REG_PREFIX "Register"
+#define KEY_PAGE_SORT            "register_order"
+#define KEY_PAGE_SORT_REV        "register_reversed"
+#define KEY_PAGE_FILTER          "register_filter"

 typedef struct _GNCSplitReg GNCSplitReg;
 typedef struct _GNCSplitRegClass GNCSplitRegClass;

commit bf9c44416e2024caf0d2dac1078f5e085442e0bb
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sat May 2 14:41:35 2020 +0100

    Remove the setting of a comment for registers

diff --git a/gnucash/gnome/dialog-invoice.c b/gnucash/gnome/dialog-invoice.c
index 8cfcda510..0e3bf45ee 100644
--- a/gnucash/gnome/dialog-invoice.c
+++ b/gnucash/gnome/dialog-invoice.c
@@ -544,7 +544,7 @@ gnc_invoice_window_save_document_layout_to_user_state
(InvoiceWindow *iw)
     Table *table = gnc_entry_ledger_get_table (iw->ledger);
     const gchar *group = gnc_invoice_window_get_state_group (iw);

-    gnc_table_save_state (table, group, NULL);
+    gnc_table_save_state (table, group);
 }

 /* Removes the user state layout information for Invoice/Bill/Voucher
@@ -2368,7 +2368,7 @@ gnc_invoice_save_page (InvoiceWindow *iw,
         g_key_file_set_string(key_file, group_name, KEY_OWNER_GUID,
guidstr);
     }
     // save the open table layout
-    gnc_table_save_state (table, group_name, NULL);
+    gnc_table_save_state (table, group_name);
 }

 GtkWidget *
diff --git a/gnucash/gnome/gnc-plugin-page-register.c
b/gnucash/gnome/gnc-plugin-page-register.c
index c98ba9332..36ff606ac 100644
--- a/gnucash/gnome/gnc-plugin-page-register.c
+++ b/gnucash/gnome/gnc-plugin-page-register.c
@@ -1739,7 +1739,7 @@ gnc_plugin_page_register_save_page (GncPluginPage*
plugin_page,
                             reg->use_double_line);

     // save the open table layout
-    gnc_table_save_state (reg->table, group_name, NULL);
+    gnc_table_save_state (reg->table, group_name);

     LEAVE(" ");
 }
diff --git a/gnucash/gnome/gnc-split-reg.c b/gnucash/gnome/gnc-split-reg.c
index b8453bdd1..fd2a399f0 100644
--- a/gnucash/gnome/gnc-split-reg.c
+++ b/gnucash/gnome/gnc-split-reg.c
@@ -508,7 +508,7 @@ gsr_create_table( GNCSplitReg *gsr )
     if (g_key_file_has_group (gnc_state_get_current (),
register_state_section))
     {
         if (!gnc_split_reg_register_has_user_state (gsr))
-             gnc_table_save_state (sr->table, default_state_section, NULL);
+             gnc_table_save_state (sr->table, default_state_section);
         // drop the register state
         gnc_state_drop_sections_for (register_state_section);
     }
@@ -2008,7 +2008,7 @@ gnc_split_reg_save_register_layout_to_user_state
(GNCSplitReg *gsr)
     SplitRegister *split_reg = gnc_ledger_display_get_split_register
(gsr->ledger);
     const gchar *group = gnc_split_reg_get_register_state_group (gsr);

-    gnc_table_save_state (split_reg->table, group, NULL);
+    gnc_table_save_state (split_reg->table, group);
 }

 /* Removes the user state layout information for the register group
diff --git a/gnucash/register/register-core/table-allgui.h
b/gnucash/register/register-core/table-allgui.h
index 53d1b7f1d..03a0e08af 100644
--- a/gnucash/register/register-core/table-allgui.h
+++ b/gnucash/register/register-core/table-allgui.h
@@ -201,7 +201,7 @@ Table *     gnc_table_new (TableLayout *layout,
                            TableControl *control);
 void        gnc_virtual_location_init (VirtualLocation *vloc);

-void        gnc_table_save_state (Table *table, const gchar
*state_section, gchar *account_fullname);
+void        gnc_table_save_state (Table *table, const gchar
*state_section);
 void        gnc_table_destroy (Table *table);


diff --git a/gnucash/register/register-gnome/table-gnome.c
b/gnucash/register/register-gnome/table-gnome.c
index 73d2f2303..825e77268 100644
--- a/gnucash/register/register-gnome/table-gnome.c
+++ b/gnucash/register/register-gnome/table-gnome.c
@@ -68,7 +68,7 @@ static QofLogModule UNUSED_VAR log_module =
GNC_MOD_REGISTER;
 /** Implementation *****************************************************/

 void
-gnc_table_save_state (Table *table, const gchar * state_section, gchar *
account_fullname)
+gnc_table_save_state (Table *table, const gchar * state_section)
 {
     GnucashSheet *sheet;
     GNCHeaderWidths widths;
@@ -108,12 +108,6 @@ gnc_table_save_state (Table *table, const gchar *
state_section, gchar * account
             g_key_file_remove_key (state_file, state_section, key, NULL);
         g_free (key);
     }
-    if (account_fullname)
-    {
-        key = g_strdup_printf ("Register state for \"%s\"",
account_fullname);
-        g_key_file_set_comment (state_file, state_section, NULL, key,
NULL);
-        g_free (key);
-    }
     gnc_header_widths_destroy (widths);
 }


commit b6de2981b83d2f6fb480855b7f2522c87d2ea60a
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sat May 2 14:38:37 2020 +0100

    Remove the state key file comment for Account filter

diff --git a/gnucash/gnome-utils/gnc-tree-view-account.c
b/gnucash/gnome-utils/gnc-tree-view-account.c
index 921038462..9d1a7445d 100644
--- a/gnucash/gnome-utils/gnc-tree-view-account.c
+++ b/gnucash/gnome-utils/gnc-tree-view-account.c
@@ -2486,10 +2486,6 @@ gnc_tree_view_account_save_filter
(GncTreeViewAccount *view,
                            fd->show_zero_total);
     g_key_file_set_boolean (key_file, group_name, SHOW_UNUSED_ACCOUNTS,
                            fd->show_unused);
-
-    g_key_file_set_comment (key_file, group_name, ACCOUNT_TYPES,
-                            "Account Filter Section below, four lines",
NULL);
-
     LEAVE("");
 }


commit 2494ad1adf9bccccfae53b3b2924591da2a44113
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sat May 2 14:37:40 2020 +0100

    Add option to save Layout for Register items

    Add two menu items under windows, one to save an existing register
    layout based on the register type to there respective default layouts
    so the user set column widths will be used when opening registers. The
    second menu item will reset the column widths to defaults and remove
    the associated default layout.
    Open registers will also save there column widths to the page section
    so these could can temporarily have different widths.

diff --git a/gnucash/gnome/gnc-plugin-page-register.c
b/gnucash/gnome/gnc-plugin-page-register.c
index 032566c95..c98ba9332 100644
--- a/gnucash/gnome/gnc-plugin-page-register.c
+++ b/gnucash/gnome/gnc-plugin-page-register.c
@@ -253,6 +253,10 @@ static void
gnc_plugin_page_register_cmd_account_report (GtkAction* action,

GncPluginPageRegister* plugin_page);
 static void gnc_plugin_page_register_cmd_transaction_report (GtkAction*
action,
         GncPluginPageRegister* plugin_page);
+static void gnc_plugin_page_register_cmd_save_layout (GtkAction *action,
+
GncPluginPageRegister *plugin_page);
+static void gnc_plugin_page_register_cmd_reset_layout (GtkAction *action,
+
 GncPluginPageRegister *plugin_page);
 static void gnc_plugin_page_register_cmd_associate_file_transaction (
     GtkAction* action, GncPluginPageRegister* plugin_page);
 static void gnc_plugin_page_register_cmd_associate_location_transaction (
@@ -516,6 +520,18 @@ static GtkActionEntry gnc_plugin_page_register_actions
[] =
         N_ ("Open a register report for the selected Transaction"),
         G_CALLBACK (gnc_plugin_page_register_cmd_transaction_report)
     },
+
+    /* Windows menu */
+    {
+        "WindowsSaveLayoutAction", NULL, "_Use as Default Layout for this
Register Group", NULL,
+        N_("Use the current layout as default for all registers in the
group 'Currency account registers'"),
+        G_CALLBACK (gnc_plugin_page_register_cmd_save_layout)
+    },
+    {
+        "WindowsResetLayoutAction", NULL, "_Reset Default Layout for this
Register Group", NULL,
+        N_("Reset default layout for all registers in the group 'Currency
account registers' back to built-in defaults and update page accordingly"),
+        G_CALLBACK (gnc_plugin_page_register_cmd_reset_layout)
+    },
 };

 static guint gnc_plugin_page_register_n_actions = G_N_ELEMENTS (
@@ -640,6 +656,8 @@ typedef struct GncPluginPageRegisterPrivate

     GtkWidget* widget;

+    const gchar *page_state_name; /* Used for loading state information */
+
     gint event_handler_id;
     gint component_manager_id;
     GncGUID key;  /* The guid of the Account we're watching */
@@ -904,6 +922,7 @@ gnc_plugin_page_register_init (GncPluginPageRegister*
plugin_page)
     priv->enable_refresh    = TRUE;
     priv->search_query      = NULL;
     priv->filter_query      = NULL;
+    priv->page_state_name   = NULL;
 }

 static void
@@ -953,8 +972,10 @@ gnc_plugin_page_register_focus_widget (GncPluginPage*
register_plugin_page)
 {
     if (GNC_IS_PLUGIN_PAGE_REGISTER (register_plugin_page))
     {
-        GNCSplitReg* gsr = gnc_plugin_page_register_get_gsr
(GNC_PLUGIN_PAGE (
-
 register_plugin_page));
+        GNCSplitReg *gsr = gnc_plugin_page_register_get_gsr
(GNC_PLUGIN_PAGE(register_plugin_page));
+
+        gnc_plugin_page_register_ui_update (NULL,
GNC_PLUGIN_PAGE_REGISTER(register_plugin_page));
+
         gnc_split_reg_focus_on_sheet (gsr);
     }
     return FALSE;
@@ -1190,6 +1211,26 @@ gnc_plugin_page_register_ui_update (gpointer various,
             }
         }
     }
+
+    // update the register default layouts actions
+    {
+        gboolean has_default = FALSE;
+        const gchar *group = gnc_split_reg_get_register_state_group
(priv->gsr);
+        GtkAction *layout_action = gnc_plugin_page_get_action
(GNC_PLUGIN_PAGE(page), "WindowsSaveLayoutAction");
+        gchar *tt = g_strdup_printf (gettext ("Use the current layout as
default for all registers in the group '%s'"), _(group));
+        gtk_action_set_tooltip (layout_action, tt);
+        g_free (tt);
+
+        layout_action = gnc_plugin_page_get_action (GNC_PLUGIN_PAGE(page),
"WindowsResetLayoutAction");
+        tt = g_strdup_printf (gettext ("Reset default layout for all
registers in the group '%s' back to built-in defaults and update page
accordingly"), _(group));
+        gtk_action_set_tooltip (layout_action, tt);
+        g_free (tt);
+
+        // if there is no default layout do not enable reset action
+        if (gnc_split_reg_register_has_user_state (priv->gsr))
+            has_default = TRUE;
+        gtk_action_set_sensitive (layout_action, has_default);
+    }
 }

 static void
@@ -1330,11 +1371,12 @@ gnc_plugin_page_register_create_widget
(GncPluginPage* plugin_page)
     numRows = priv->lines_default;
     numRows = MIN (numRows, DEFAULT_LINES_AMOUNT);

-    gnc_window = GNC_WINDOW (GNC_PLUGIN_PAGE (page)->window);
+    gnc_window = GNC_WINDOW(GNC_PLUGIN_PAGE(page)->window);
     gsr = gnc_split_reg_new (priv->ledger,
                              gnc_window_get_gtk_window (gnc_window),
-                             numRows, priv->read_only);
-    priv->gsr = (GNCSplitReg*)gsr;
+                             numRows, priv->read_only,
priv->page_state_name);
+    priv->gsr = (GNCSplitReg *)gsr;
+
     gtk_widget_show (gsr);
     gtk_box_pack_start (GTK_BOX (priv->widget), gsr, TRUE, TRUE, 0);

@@ -1696,7 +1738,10 @@ gnc_plugin_page_register_save_page (GncPluginPage*
plugin_page,
     g_key_file_set_boolean (key_file, group_name, KEY_DOUBLE_LINE,
                             reg->use_double_line);

-    LEAVE (" ");
+    // save the open table layout
+    gnc_table_save_state (reg->table, group_name, NULL);
+
+    LEAVE(" ");
 }


@@ -1833,6 +1878,7 @@ gnc_plugin_page_register_recreate_page (GtkWidget*
window,
      * sort/filter updates and double line/style changes */
     priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (page);
     priv->enable_refresh = FALSE;
+    priv->page_state_name = group_name;

     /* Recreate page in given window */
     gnc_plugin_page_set_use_new_window (page, FALSE);
@@ -4977,6 +5023,46 @@ gnc_plugin_page_register_cmd_transaction_report
(GtkAction* action,
     LEAVE (" ");
 }

+static void
+gnc_plugin_page_register_cmd_save_layout (GtkAction *action,
GncPluginPageRegister *plugin_page)
+{
+    GNCSplitReg *gsr;
+    GtkAction *layout_action;
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER(plugin_page));
+
+    gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE(plugin_page));
+
+    gnc_split_reg_save_register_layout_to_user_state (gsr);
+
+    layout_action = gnc_plugin_page_get_action
(GNC_PLUGIN_PAGE(plugin_page),
+
"WindowsResetLayoutAction");
+    gtk_action_set_sensitive (layout_action, TRUE);
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_register_cmd_reset_layout (GtkAction *action,
GncPluginPageRegister *plugin_page)
+{
+    GNCSplitReg *gsr;
+    GtkAction *layout_action;
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+
+    g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER(plugin_page));
+
+    gsr = gnc_plugin_page_register_get_gsr (GNC_PLUGIN_PAGE(plugin_page));
+
+    gnc_split_reg_reset_register_layout_and_clear_user_state (gsr);
+
+    layout_action = gnc_plugin_page_get_action
(GNC_PLUGIN_PAGE(plugin_page),
+
"WindowsResetLayoutAction");
+    gtk_action_set_sensitive (layout_action, FALSE);
+    LEAVE(" ");
+}
+
 /************************************************************/
 /*                    Auxiliary functions                   */
 /************************************************************/
diff --git a/gnucash/gnome/gnc-split-reg.c b/gnucash/gnome/gnc-split-reg.c
index 7e2bbf4a8..b8453bdd1 100644
--- a/gnucash/gnome/gnc-split-reg.c
+++ b/gnucash/gnome/gnc-split-reg.c
@@ -56,6 +56,7 @@
 #include "gnucash-sheet.h"
 #include "gnucash-register.h"
 #include "table-allgui.h"
+#include "gnc-state.h"

 #include "dialog-utils.h"

@@ -325,7 +326,8 @@ GtkWidget*
 gnc_split_reg_new( GNCLedgerDisplay *ld,
                    GtkWindow *parent,
                    gint numberOfLines,
-                   gboolean read_only )
+                   gboolean read_only,
+                   const gchar *group_name )
 {
     GNCSplitReg *gsrToRet;

@@ -340,6 +342,8 @@ gnc_split_reg_new( GNCLedgerDisplay *ld,
     gsrToRet->ledger = ld;
     gsrToRet->window = GTK_WIDGET(parent);

+    gsrToRet->page_state_name = group_name;
+
     gnc_split_reg_init2( gsrToRet );

     LEAVE("%p", gsrToRet);
@@ -359,6 +363,7 @@ gnc_split_reg_init( GNCSplitReg *gsr )
     gsr->height = -1;
     gsr->numRows = 10;
     gsr->read_only = FALSE;
+    gsr->page_state_name = NULL;
 }

 static void
@@ -402,6 +407,46 @@ gsr_setup_table( GNCSplitReg *gsr )
     LEAVE(" ");
 }

+const gchar *
+gnc_split_reg_get_register_state_group (GNCSplitReg *gsr)
+{
+    SplitRegister *split_reg = gnc_ledger_display_get_split_register
(gsr->ledger);
+
+    switch (gnc_split_register_get_register_group (split_reg))
+    {
+        case REG_TYPE_GROUP_CURRENCY:
+        {
+            return N_("Currency account registers");
+            break;
+        }
+        case REG_TYPE_GROUP_APAR:
+        {
+            return N_("Business account registers");
+            break;
+        }
+        case REG_TYPE_GROUP_JOURNAL:
+        {
+            return N_("Journal registers");
+            break;
+        }
+        case REG_TYPE_GROUP_STOCK:
+        {
+            return N_("Stock account registers");
+            break;
+        }
+        case REG_TYPE_GROUP_PORTFOLIO:
+        {
+            return N_("Portfolio registers");
+            break;
+        }
+        default:
+        {
+            return N_("Register group Unknown");
+            break;
+        }
+    }
+}
+
 static
 void
 gsr_create_table( GNCSplitReg *gsr )
@@ -412,12 +457,31 @@ gsr_create_table( GNCSplitReg *gsr )
     Account * account = gnc_ledger_display_leader(gsr->ledger);
     const GncGUID * guid = xaccAccountGetGUID(account);
     gchar guidstr[GUID_ENCODING_LENGTH+1];
-    const gchar *state_section = NULL;
-    guid_to_string_buff(guid, guidstr);
-    state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", guidstr,
NULL);
+    gchar *register_state_section;
+    const gchar *default_state_section;
+    const gchar *group;
+
+    guid_to_string_buff (guid, guidstr);
+
+    register_state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ",
guidstr, NULL);

     ENTER("gsr=%p", gsr);

+    sr = gnc_ledger_display_get_split_register (gsr->ledger);
+    default_state_section = gnc_split_reg_get_register_state_group (gsr);
+
+    // if this is from a page recreate and no register state use those
settings,
+    // register state is dropped at the end of function.
+    if (gsr->page_state_name && !g_key_file_has_group
(gnc_state_get_current (), register_state_section))
+        group = gsr->page_state_name;
+    else
+    {
+        // if no default state, use register state if available
+        if (gnc_split_reg_register_has_user_state (gsr))
+            group = default_state_section;
+        else
+            group = register_state_section;
+    }
     gnc_ledger_display_set_user_data( gsr->ledger, (gpointer)gsr );
     gnc_ledger_display_set_handlers( gsr->ledger,
                                      gnc_split_reg_ld_destroy,
@@ -425,7 +489,7 @@ gsr_create_table( GNCSplitReg *gsr )

     /* FIXME: We'd really rather pass this down... */
     sr = gnc_ledger_display_get_split_register( gsr->ledger );
-    register_widget = gnucash_register_new( sr->table, state_section );
+    register_widget = gnucash_register_new( sr->table, group );
     gsr->reg = GNUCASH_REGISTER( register_widget );

     gtk_box_pack_start (GTK_BOX (gsr), GTK_WIDGET(gsr->reg), TRUE, TRUE,
0);
@@ -440,6 +504,15 @@ gsr_create_table( GNCSplitReg *gsr )
     g_signal_connect (gsr->reg, "show_popup_menu",
                       G_CALLBACK(gsr_emit_show_popup_menu), gsr);

+    // if no default state and register has state, copy it.
+    if (g_key_file_has_group (gnc_state_get_current (),
register_state_section))
+    {
+        if (!gnc_split_reg_register_has_user_state (gsr))
+             gnc_table_save_state (sr->table, default_state_section, NULL);
+        // drop the register state
+        gnc_state_drop_sections_for (register_state_section);
+    }
+    g_free (register_state_section);
     LEAVE(" ");
 }

@@ -721,37 +794,10 @@ gnc_split_reg_ld_destroy( GNCLedgerDisplay *ledger )
 {
     GNCSplitReg *gsr = gnc_ledger_display_get_user_data( ledger );

-    Account * account = gnc_ledger_display_leader(ledger);
-    const GncGUID * guid = xaccAccountGetGUID(account);
-    gchar guidstr[GUID_ENCODING_LENGTH+1];
-    gchar *state_section;
-    gchar *acct_fullname;
-    guid_to_string_buff(guid, guidstr);
-
-    state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", guidstr,
NULL);
-
-    if (g_strcmp0(guidstr, "00000000000000000000000000000000") == 0)
-        acct_fullname = g_strdup(_("General Journal"));
-    else
-        acct_fullname = gnc_account_get_full_name(account);
-
-    if (gsr)
-    {
-        SplitRegister *reg;
-
-        reg = gnc_ledger_display_get_split_register (ledger);
-
-        if (reg && reg->table)
-            gnc_table_save_state (reg->table, state_section,
acct_fullname);
-
-        /*
-         * Don't destroy the window here any more.  The register no longer
-         * owns it.
-         */
-    }
-    g_free (state_section);
-    g_free (acct_fullname);
-
+   /*
+    * Don't destroy the window here any more.  The register no longer
+    * owns it.
+    */
     gnc_ledger_display_set_user_data (ledger, NULL);
     g_object_unref (gsr);
 }
@@ -1952,6 +1998,44 @@ gnc_split_reg_set_sheet_focus (GNCSplitReg *gsr,
gboolean has_focus)
     gnucash_sheet_set_has_focus (sheet, has_focus);
 }

+/* Save user state layout information to the register group that
+ * this register belongs to so it can be used as the default
+ * user layout
+ */
+void
+gnc_split_reg_save_register_layout_to_user_state (GNCSplitReg *gsr)
+{
+    SplitRegister *split_reg = gnc_ledger_display_get_split_register
(gsr->ledger);
+    const gchar *group = gnc_split_reg_get_register_state_group (gsr);
+
+    gnc_table_save_state (split_reg->table, group, NULL);
+}
+
+/* Removes the user state layout information for the register group
+ * that this register belongs to and also resets the current layout to
+ * the built-in defaults
+ */
+void
+gnc_split_reg_reset_register_layout_and_clear_user_state (GNCSplitReg *gsr)
+{
+    GnucashRegister *reg = gsr->reg;
+    const gchar *group = gnc_split_reg_get_register_state_group (gsr);
+
+    gnucash_register_reset_sheet_layout (reg);
+    gnc_state_drop_sections_for (group);
+}
+
+/* Checks to see if there is user state layout information for the
+ * register group that this register belongs to.
+ */
+gboolean
+gnc_split_reg_register_has_user_state (GNCSplitReg *gsr)
+{
+    GKeyFile *state_file = gnc_state_get_current ();
+    const gchar *group = gnc_split_reg_get_register_state_group (gsr);
+    return g_key_file_has_group (state_file, group);
+}
+
 void
 gnc_split_reg_balancing_entry(GNCSplitReg *gsr, Account *account,
                               time64 statement_date, gnc_numeric
balancing_amount)
diff --git a/gnucash/gnome/gnc-split-reg.h b/gnucash/gnome/gnc-split-reg.h
index 8c0f78c24..128e49ca6 100644
--- a/gnucash/gnome/gnc-split-reg.h
+++ b/gnucash/gnome/gnc-split-reg.h
@@ -85,6 +85,8 @@ struct _GNCSplitReg
     /** The actual gnucash register widget. **/
     GnucashRegister *reg;

+    const gchar *page_state_name; /* Used for loading open state
information */
+
     gint numRows;

     guint    sort_type;
@@ -179,11 +181,13 @@ GType gnc_split_reg_get_type(void);
  * @param parent        The containing window.
  * @param numberOfLines The initial number of lines for the register.
  * @param read_only      If the contained register should be setup
read-only.
+ * @param group_name     The group name of the page state section for this
page
  **/
 GtkWidget* gnc_split_reg_new( GNCLedgerDisplay *ld,
                               GtkWindow *parent,
                               gint numberOfLines,
-                              gboolean read_only );
+                              gboolean read_only,
+                              const gchar *group_name );

 /**
  * Returns the GnucashRegister in effect for this GNCSplitReg.
@@ -250,6 +254,14 @@ void gnc_split_reg_jump_to_split_amount(GNCSplitReg
*gsr, Split *split);
 void gnc_split_reg_focus_on_sheet (GNCSplitReg *gsr);
 void gnc_split_reg_set_sheet_focus (GNCSplitReg *gsr, gboolean has_focus);

+/**
+ * Save/Reset/Has functions used for the user default register layouts.
+ **/
+void gnc_split_reg_save_register_layout_to_user_state (GNCSplitReg *gsr);
+void gnc_split_reg_reset_register_layout_and_clear_user_state (GNCSplitReg
*gsr);
+gboolean gnc_split_reg_register_has_user_state (GNCSplitReg *gsr);
+const gchar *gnc_split_reg_get_register_state_group (GNCSplitReg *gsr);
+
 /*
  * Create a transaction entry with given amount and date. One account is
  * specified, the other is undefined i.e. it defaults to orphan account.
diff --git a/gnucash/ui/gnc-plugin-page-register-ui.xml
b/gnucash/ui/gnc-plugin-page-register-ui.xml
index 517afcbca..dfbbcffbb 100644
--- a/gnucash/ui/gnc-plugin-page-register-ui.xml
+++ b/gnucash/ui/gnc-plugin-page-register-ui.xml
@@ -66,6 +66,13 @@
         <menuitem name="ReportsAcctTransReport"
action="ReportsAcctTransReportAction"/>
       </placeholder>
     </menu>
+
+    <menu name="Windows" action="WindowsAction">
+      <placeholder name="WindowsLayoutPlaceholder">
+        <menuitem name="WindowsSaveLayout"
 action="WindowsSaveLayoutAction"/>
+        <menuitem name="WindowsResetLayout"
action="WindowsResetLayoutAction"/>
+       </placeholder>
+    </menu>
   </menubar>

   <toolbar name="DefaultToolbar">

commit 74abd821b39736465e5a3dd792d6224c5812a7bc
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sat May 2 14:32:47 2020 +0100

    Add enum SplitRegisterTypeGroup to group registers

    Add SplitRegisterTypeGroup to group registers that have the same layout
    and it will also be used to get the default user state information for
    register cell widths.

diff --git a/gnucash/register/ledger-core/split-register-layout.c
b/gnucash/register/ledger-core/split-register-layout.c
index ffdb46523..ae5973e85 100644
--- a/gnucash/register/ledger-core/split-register-layout.c
+++ b/gnucash/register/ledger-core/split-register-layout.c
@@ -83,17 +83,9 @@ gnc_split_register_set_cells (SplitRegister* reg,
TableLayout* layout)
     CellBlock* curs;
     CellBlock* curs_last;

-    switch (reg->type)
+    switch (gnc_split_register_get_register_group (reg))
     {
-    case BANK_REGISTER:
-    case CASH_REGISTER:
-    case ASSET_REGISTER:
-    case CREDIT_REGISTER:
-    case LIABILITY_REGISTER:
-    case INCOME_REGISTER:
-    case EXPENSE_REGISTER:
-    case EQUITY_REGISTER:
-    case TRADING_REGISTER:
+    case REG_TYPE_GROUP_CURRENCY:
     {
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_SINGLE_LEDGER);
@@ -191,8 +183,7 @@ gnc_split_register_set_cells (SplitRegister* reg,
TableLayout* layout)
     }
     /* --------------------------------------------------------- */

-    case PAYABLE_REGISTER:
-    case RECEIVABLE_REGISTER:
+    case REG_TYPE_GROUP_APAR:
     {
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_SINGLE_LEDGER);
@@ -269,9 +260,7 @@ gnc_split_register_set_cells (SplitRegister* reg,
TableLayout* layout)
     }

     /* --------------------------------------------------------- */
-    case INCOME_LEDGER:
-    case GENERAL_JOURNAL:
-    case SEARCH_LEDGER:
+    case REG_TYPE_GROUP_JOURNAL:
     {
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_SINGLE_LEDGER);
@@ -391,8 +380,7 @@ gnc_split_register_set_cells (SplitRegister* reg,
TableLayout* layout)
     }

     /* --------------------------------------------------------- */
-    case STOCK_REGISTER:
-    case CURRENCY_REGISTER:
+    case REG_TYPE_GROUP_STOCK:
     {
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_SINGLE_LEDGER);
@@ -476,7 +464,7 @@ gnc_split_register_set_cells (SplitRegister* reg,
TableLayout* layout)
     }

     /* --------------------------------------------------------- */
-    case PORTFOLIO_LEDGER:
+    case REG_TYPE_GROUP_PORTFOLIO:
     {
         curs = gnc_table_layout_get_cursor (layout,
                                             CURSOR_SINGLE_LEDGER);
@@ -559,7 +547,7 @@ gnc_split_register_set_cells (SplitRegister* reg,
TableLayout* layout)

     /* --------------------------------------------------------- */
     default:
-        PERR ("unknown register type %d \n", reg->type);
+        PERR ("unknown register group type for %d \n", reg->type);
         break;
     }
 }
diff --git a/gnucash/register/ledger-core/split-register.c
b/gnucash/register/ledger-core/split-register.c
index 03adb2a1e..912d88106 100644
--- a/gnucash/register/ledger-core/split-register.c
+++ b/gnucash/register/ledger-core/split-register.c
@@ -3183,3 +3183,52 @@ gnc_split_register_set_read_only (SplitRegister*
reg, gboolean read_only)
 {
     gnc_table_model_set_read_only (reg->table->model, read_only);
 }
+
+SplitRegisterTypeGroup
+gnc_split_register_get_register_group (SplitRegister *reg)
+{
+    switch (reg->type)
+    {
+        case BANK_REGISTER:
+        case CASH_REGISTER:
+        case ASSET_REGISTER:
+        case CREDIT_REGISTER:
+        case LIABILITY_REGISTER:
+        case INCOME_REGISTER:
+        case EXPENSE_REGISTER:
+        case EQUITY_REGISTER:
+        case TRADING_REGISTER:
+        {
+            return REG_TYPE_GROUP_CURRENCY;
+            break;
+        }
+        case PAYABLE_REGISTER:
+        case RECEIVABLE_REGISTER:
+        {
+            return REG_TYPE_GROUP_APAR;
+            break;
+        }
+        case INCOME_LEDGER:
+        case GENERAL_JOURNAL:
+        case SEARCH_LEDGER:
+        {
+            return REG_TYPE_GROUP_JOURNAL;
+            break;
+        }
+        case STOCK_REGISTER:
+        case CURRENCY_REGISTER:
+        {
+            return REG_TYPE_GROUP_STOCK;
+            break;
+        }
+        case PORTFOLIO_LEDGER:
+        {
+            return REG_TYPE_GROUP_PORTFOLIO;
+            break;
+        }
+        default:
+            return REG_TYPE_GROUP_UNKNOWN;
+            PERR ("unknown register type %d \n", reg->type);
+        break;
+    }
+}
diff --git a/gnucash/register/ledger-core/split-register.h
b/gnucash/register/ledger-core/split-register.h
index 9192d8529..279e60a55 100644
--- a/gnucash/register/ledger-core/split-register.h
+++ b/gnucash/register/ledger-core/split-register.h
@@ -167,6 +167,19 @@ typedef enum
     NUM_REGISTER_TYPES
 } SplitRegisterType;

+/** @brief Register group types
+ *
+ * used for grouping registers that have the same layout */
+typedef enum
+{
+    REG_TYPE_GROUP_UNKNOWN,
+    REG_TYPE_GROUP_CURRENCY,
+    REG_TYPE_GROUP_APAR,
+    REG_TYPE_GROUP_STOCK,
+    REG_TYPE_GROUP_JOURNAL,
+    REG_TYPE_GROUP_PORTFOLIO,
+} SplitRegisterTypeGroup;
+
 /** Register styles */
 typedef enum
 {
@@ -327,6 +340,12 @@ void gnc_split_register_set_auto_complete
(SplitRegister* reg,
  */
 void gnc_split_register_set_read_only (SplitRegister* reg, gboolean
read_only);

+/** Group registers for common layouts.
+ *  @param reg a ::SplitRegister
+ *
+ *  @return the ::SplitRegisterTypeGroup that groups registers together
+ */
+SplitRegisterTypeGroup gnc_split_register_get_register_group
(SplitRegister *reg);

 /** Set the template account for use in a template register.
  *
diff --git a/gnucash/register/register-gnome/gnucash-register.c
b/gnucash/register/register-gnome/gnucash-register.c
index 91a0b94b8..6253a63b1 100644
--- a/gnucash/register/register-gnome/gnucash-register.c
+++ b/gnucash/register/register-gnome/gnucash-register.c
@@ -186,10 +186,6 @@ void
 gnucash_register_reset_sheet_layout (GnucashRegister *reg)
 {
     GNCHeaderWidths widths;
-    Table *table;
-    GList *node;
-    gchar *key;
-    guint value;
     GnucashSheet *sheet;
     gint current_width;


commit 4c8ebfe1710e28aad9ae9bb9351c802cd1065f9b
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sat May 2 14:32:04 2020 +0100

    Change state_section parameter for gnc_table_save_state

    Change state_section to a const gchar* and update where used as required

diff --git a/gnucash/gnome/dialog-invoice.c b/gnucash/gnome/dialog-invoice.c
index a71ca3837..8cfcda510 100644
--- a/gnucash/gnome/dialog-invoice.c
+++ b/gnucash/gnome/dialog-invoice.c
@@ -518,19 +518,19 @@ gnc_invoice_window_help_cb (GtkWidget *widget,
gpointer data)
     gnc_gnome_help(HF_HELP, HL_USAGE_INVOICE);
 }

-static gchar *
+static const gchar *
 gnc_invoice_window_get_state_group (InvoiceWindow *iw)
 {
     switch (gncOwnerGetType (gncOwnerGetEndOwner (&iw->owner)))
     {
         case GNC_OWNER_VENDOR:
-            return g_strdup ("Vendor documents");
+            return "Vendor documents";
             break;
         case GNC_OWNER_EMPLOYEE:
-            return g_strdup ("Employee documents");
+            return "Employee documents";
             break;
         default:
-            return g_strdup ("Customer documents");
+            return "Customer documents";
             break;
     }
 }
@@ -542,10 +542,9 @@ void
 gnc_invoice_window_save_document_layout_to_user_state (InvoiceWindow *iw)
 {
     Table *table = gnc_entry_ledger_get_table (iw->ledger);
-    gchar *group = gnc_invoice_window_get_state_group (iw);
+    const gchar *group = gnc_invoice_window_get_state_group (iw);

     gnc_table_save_state (table, group, NULL);
-    g_free (group);
 }

 /* Removes the user state layout information for Invoice/Bill/Voucher
@@ -555,11 +554,10 @@ void
 gnc_invoice_window_reset_document_layout_and_clear_user_state
(InvoiceWindow *iw)
 {
     GnucashRegister *reg = iw->reg;
-    gchar *group = gnc_invoice_window_get_state_group (iw);
+    const gchar *group = gnc_invoice_window_get_state_group (iw);

     gnucash_register_reset_sheet_layout (reg);
     gnc_state_drop_sections_for (group);
-    g_free (group);
 }

 /* Checks to see if there is user state layout information for
@@ -570,10 +568,8 @@ gboolean
 gnc_invoice_window_document_has_user_state (InvoiceWindow *iw)
 {
     GKeyFile *state_file = gnc_state_get_current ();
-    gchar *group = gnc_invoice_window_get_state_group (iw);
-    gboolean has_group = g_key_file_has_group (state_file, group);
-    g_free (group);
-    return has_group;
+    const gchar *group = gnc_invoice_window_get_state_group (iw);
+    return g_key_file_has_group (state_file, group);
 }

 void
@@ -2351,7 +2347,6 @@ gnc_invoice_save_page (InvoiceWindow *iw,
                        const gchar *group_name)
 {
     Table *table = gnc_entry_ledger_get_table (iw->ledger);
-    gchar *group = g_strdup (group_name);
     gchar guidstr[GUID_ENCODING_LENGTH+1];
     guid_to_string_buff(&iw->invoice_guid, guidstr);
     g_key_file_set_string(key_file, group_name, KEY_INVOICE_TYPE,
@@ -2373,8 +2368,7 @@ gnc_invoice_save_page (InvoiceWindow *iw,
         g_key_file_set_string(key_file, group_name, KEY_OWNER_GUID,
guidstr);
     }
     // save the open table layout
-    gnc_table_save_state (table, group, NULL);
-    g_free (group);
+    gnc_table_save_state (table, group_name, NULL);
 }

 GtkWidget *
@@ -2568,21 +2562,20 @@ gnc_invoice_create_page (InvoiceWindow *iw,
gpointer page)
     /* Create the register */
     {
         GtkWidget *regWidget, *frame, *window;
-        gchar *default_group = gnc_invoice_window_get_state_group (iw);
-        gchar *group;
+        const gchar *default_group = gnc_invoice_window_get_state_group
(iw);
+        const gchar *group;

         // if this is from a page recreate, use those settings
         if (iw->page_state_name)
-            group = g_strdup (iw->page_state_name);
+            group = iw->page_state_name;
         else
-            group = g_strdup (default_group);
+            group = default_group;

         /* Watch the order of operations, here... */
         regWidget = gnucash_register_new (gnc_entry_ledger_get_table
                                           (entry_ledger), group);
         gtk_widget_show(regWidget);
-        g_free (default_group);
-        g_free (group);
+
         frame = GTK_WIDGET (gtk_builder_get_object (builder,
"ledger_frame"));
         gtk_container_add (GTK_CONTAINER (frame), regWidget);

diff --git a/gnucash/gnome/gnc-split-reg.c b/gnucash/gnome/gnc-split-reg.c
index d8218d6a2..7e2bbf4a8 100644
--- a/gnucash/gnome/gnc-split-reg.c
+++ b/gnucash/gnome/gnc-split-reg.c
@@ -412,7 +412,7 @@ gsr_create_table( GNCSplitReg *gsr )
     Account * account = gnc_ledger_display_leader(gsr->ledger);
     const GncGUID * guid = xaccAccountGetGUID(account);
     gchar guidstr[GUID_ENCODING_LENGTH+1];
-    gchar *state_section = NULL;
+    const gchar *state_section = NULL;
     guid_to_string_buff(guid, guidstr);
     state_section = g_strconcat (STATE_SECTION_REG_PREFIX, " ", guidstr,
NULL);

@@ -427,7 +427,7 @@ gsr_create_table( GNCSplitReg *gsr )
     sr = gnc_ledger_display_get_split_register( gsr->ledger );
     register_widget = gnucash_register_new( sr->table, state_section );
     gsr->reg = GNUCASH_REGISTER( register_widget );
-    g_free (state_section);
+
     gtk_box_pack_start (GTK_BOX (gsr), GTK_WIDGET(gsr->reg), TRUE, TRUE,
0);
     gnucash_sheet_set_window (gnucash_register_get_sheet (gsr->reg),
gsr->window);
     gtk_widget_show ( GTK_WIDGET(gsr->reg) );
diff --git a/gnucash/register/register-core/table-allgui.h
b/gnucash/register/register-core/table-allgui.h
index 5c0396b20..53d1b7f1d 100644
--- a/gnucash/register/register-core/table-allgui.h
+++ b/gnucash/register/register-core/table-allgui.h
@@ -201,7 +201,7 @@ Table *     gnc_table_new (TableLayout *layout,
                            TableControl *control);
 void        gnc_virtual_location_init (VirtualLocation *vloc);

-void        gnc_table_save_state (Table *table, gchar *state_section,
gchar *account_fullname);
+void        gnc_table_save_state (Table *table, const gchar
*state_section, gchar *account_fullname);
 void        gnc_table_destroy (Table *table);


diff --git a/gnucash/register/register-gnome/gnucash-register.c
b/gnucash/register/register-gnome/gnucash-register.c
index bdd05936c..91a0b94b8 100644
--- a/gnucash/register/register-gnome/gnucash-register.c
+++ b/gnucash/register/register-gnome/gnucash-register.c
@@ -486,7 +486,7 @@ gnucash_register_attach_popup (GnucashRegister *reg,
  *  to pass NULL as second parameter. */

 static void
-gnucash_register_configure (GnucashSheet *sheet, gchar * state_section)
+gnucash_register_configure (GnucashSheet *sheet, const gchar *
state_section)
 {
     GNCHeaderWidths widths;
     Table *table;
@@ -644,7 +644,7 @@ gnucash_register_create_widget (Table *table)


 GtkWidget *
-gnucash_register_new (Table *table, gchar *state_section)
+gnucash_register_new (Table *table, const gchar *state_section)
 {
     GnucashRegister *reg;
     GtkWidget *widget;
diff --git a/gnucash/register/register-gnome/gnucash-register.h
b/gnucash/register/register-gnome/gnucash-register.h
index c512f149f..968dbd8cf 100644
--- a/gnucash/register/register-gnome/gnucash-register.h
+++ b/gnucash/register/register-gnome/gnucash-register.h
@@ -54,7 +54,7 @@ GType gnucash_register_get_type (void);
 void gnucash_register_add_cell_types (void);

 /** this already has scrollbars attached */
-GtkWidget *gnucash_register_new (Table *table, gchar *state_section);
+GtkWidget *gnucash_register_new (Table *table, const gchar *state_section);

 void gnucash_register_goto_virt_cell (GnucashRegister *reg,
                                       VirtualCellLocation vcell_loc);
diff --git a/gnucash/register/register-gnome/table-gnome.c
b/gnucash/register/register-gnome/table-gnome.c
index ee0145e74..73d2f2303 100644
--- a/gnucash/register/register-gnome/table-gnome.c
+++ b/gnucash/register/register-gnome/table-gnome.c
@@ -68,7 +68,7 @@ static QofLogModule UNUSED_VAR log_module =
GNC_MOD_REGISTER;
 /** Implementation *****************************************************/

 void
-gnc_table_save_state (Table *table, gchar * state_section, gchar *
account_fullname)
+gnc_table_save_state (Table *table, const gchar * state_section, gchar *
account_fullname)
 {
     GnucashSheet *sheet;
     GNCHeaderWidths widths;

commit 2f5225ad337486b510d8b72ad5e8ffcccb35b41c
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Sat May 2 14:30:21 2020 +0100

    Add option to save Layout for Business items

    Add two menu items under windows, one to save an existing layout for
    Invoices, Bills and Vouchers to there respective default layouts so the
    user set column widths will be used. The second menu item will reset the
    column widths to defaults and remove the default layout.
    Open Business items will also save there column widths to the page
    section so these can temporarily have different widths.

diff --git a/gnucash/gnome/dialog-invoice.c b/gnucash/gnome/dialog-invoice.c
index 37ce031ca..a71ca3837 100644
--- a/gnucash/gnome/dialog-invoice.c
+++ b/gnucash/gnome/dialog-invoice.c
@@ -71,6 +71,7 @@
 #include "gnc-plugin-business.h"
 #include "gnc-plugin-page-invoice.h"
 #include "gnc-main-window.h"
+#include "gnc-state.h"

 #include "dialog-transfer.h"

@@ -141,6 +142,7 @@ struct _invoice_window

     GtkWidget  * dialog;         /* Used by 'New Invoice Window' */
     GncPluginPage *page;        /* Used by 'Edit Invoice' Page */
+    const gchar * page_state_name;    /* Used for loading open state
information */

     /* Summary Bar Widgets */
     GtkWidget  * total_label;
@@ -516,6 +518,64 @@ gnc_invoice_window_help_cb (GtkWidget *widget,
gpointer data)
     gnc_gnome_help(HF_HELP, HL_USAGE_INVOICE);
 }

+static gchar *
+gnc_invoice_window_get_state_group (InvoiceWindow *iw)
+{
+    switch (gncOwnerGetType (gncOwnerGetEndOwner (&iw->owner)))
+    {
+        case GNC_OWNER_VENDOR:
+            return g_strdup ("Vendor documents");
+            break;
+        case GNC_OWNER_EMPLOYEE:
+            return g_strdup ("Employee documents");
+            break;
+        default:
+            return g_strdup ("Customer documents");
+            break;
+    }
+}
+
+/* Save user state layout information for Invoice/Bill/Voucher
+ * documents so it can be used for the default user set layout
+ */
+void
+gnc_invoice_window_save_document_layout_to_user_state (InvoiceWindow *iw)
+{
+    Table *table = gnc_entry_ledger_get_table (iw->ledger);
+    gchar *group = gnc_invoice_window_get_state_group (iw);
+
+    gnc_table_save_state (table, group, NULL);
+    g_free (group);
+}
+
+/* Removes the user state layout information for Invoice/Bill/Voucher
+ * documents and also resets the current layout to the built-in defaults
+ */
+void
+gnc_invoice_window_reset_document_layout_and_clear_user_state
(InvoiceWindow *iw)
+{
+    GnucashRegister *reg = iw->reg;
+    gchar *group = gnc_invoice_window_get_state_group (iw);
+
+    gnucash_register_reset_sheet_layout (reg);
+    gnc_state_drop_sections_for (group);
+    g_free (group);
+}
+
+/* Checks to see if there is user state layout information for
+ * Invoice/Bill/Voucher documents so it can be used for the
+ * default user layout
+ */
+gboolean
+gnc_invoice_window_document_has_user_state (InvoiceWindow *iw)
+{
+    GKeyFile *state_file = gnc_state_get_current ();
+    gchar *group = gnc_invoice_window_get_state_group (iw);
+    gboolean has_group = g_key_file_has_group (state_file, group);
+    g_free (group);
+    return has_group;
+}
+
 void
 gnc_invoice_window_destroy_cb (GtkWidget *widget, gpointer data)
 {
@@ -2122,7 +2182,7 @@ find_handler (gpointer find_data, gpointer user_data)
 static InvoiceWindow *
 gnc_invoice_new_page (QofBook *bookp, InvoiceDialogType type,
                       GncInvoice *invoice, const GncOwner *owner,
-                      GncMainWindow *window)
+                      GncMainWindow *window, const gchar *group_name)
 {
     InvoiceWindow *iw;
     GncOwner *billto;
@@ -2158,6 +2218,7 @@ gnc_invoice_new_page (QofBook *bookp,
InvoiceDialogType type,
     iw->invoice_guid = *gncInvoiceGetGUID (invoice);
     iw->is_credit_note = gncInvoiceGetIsCreditNote (invoice);
     iw->width = -1;
+    iw->page_state_name = group_name;

     /* Save this for later */
     gncOwnerCopy (gncOwnerGetEndOwner (owner), &(iw->owner));
@@ -2270,7 +2331,7 @@ gnc_invoice_recreate_page (GncMainWindow *window,
     g_free(tmp_string);
     g_free(owner_type);

-    iw = gnc_invoice_new_page (book, type, invoice, &owner, window);
+    iw = gnc_invoice_new_page (book, type, invoice, &owner, window,
group_name);
     return iw->page;

 give_up:
@@ -2289,6 +2350,8 @@ gnc_invoice_save_page (InvoiceWindow *iw,
                        GKeyFile *key_file,
                        const gchar *group_name)
 {
+    Table *table = gnc_entry_ledger_get_table (iw->ledger);
+    gchar *group = g_strdup (group_name);
     gchar guidstr[GUID_ENCODING_LENGTH+1];
     guid_to_string_buff(&iw->invoice_guid, guidstr);
     g_key_file_set_string(key_file, group_name, KEY_INVOICE_TYPE,
@@ -2309,6 +2372,9 @@ gnc_invoice_save_page (InvoiceWindow *iw,
         guid_to_string_buff(gncOwnerGetGUID(&iw->owner), guidstr);
         g_key_file_set_string(key_file, group_name, KEY_OWNER_GUID,
guidstr);
     }
+    // save the open table layout
+    gnc_table_save_state (table, group, NULL);
+    g_free (group);
 }

 GtkWidget *
@@ -2502,12 +2568,21 @@ gnc_invoice_create_page (InvoiceWindow *iw,
gpointer page)
     /* Create the register */
     {
         GtkWidget *regWidget, *frame, *window;
+        gchar *default_group = gnc_invoice_window_get_state_group (iw);
+        gchar *group;
+
+        // if this is from a page recreate, use those settings
+        if (iw->page_state_name)
+            group = g_strdup (iw->page_state_name);
+        else
+            group = g_strdup (default_group);

         /* Watch the order of operations, here... */
         regWidget = gnucash_register_new (gnc_entry_ledger_get_table
-                                          (entry_ledger), NULL);
+                                          (entry_ledger), group);
         gtk_widget_show(regWidget);
-
+        g_free (default_group);
+        g_free (group);
         frame = GTK_WIDGET (gtk_builder_get_object (builder,
"ledger_frame"));
         gtk_container_add (GTK_CONTAINER (frame), regWidget);

@@ -2779,7 +2854,7 @@ gnc_ui_invoice_edit (GtkWindow *parent, GncInvoice
*invoice)

     iw = gnc_invoice_new_page (gncInvoiceGetBook(invoice), type,
                                invoice, gncInvoiceGetOwner (invoice),
-                               GNC_MAIN_WINDOW(gnc_ui_get_main_window
(GTK_WIDGET (parent))));
+                               GNC_MAIN_WINDOW(gnc_ui_get_main_window
(GTK_WIDGET (parent))), NULL);

     return iw;
 }
diff --git a/gnucash/gnome/dialog-invoice.h b/gnucash/gnome/dialog-invoice.h
index a121b55c6..073268d40 100644
--- a/gnucash/gnome/dialog-invoice.h
+++ b/gnucash/gnome/dialog-invoice.h
@@ -110,6 +110,10 @@ void gnc_invoice_window_duplicateCB (GtkWidget
*widget, gpointer data);
 void gnc_invoice_window_payment_cb (GtkWindow *parent, gpointer data);
 void gnc_invoice_window_report_owner_cb (GtkWindow *parent, gpointer data);

+void gnc_invoice_window_save_document_layout_to_user_state (InvoiceWindow
*iw);
+void gnc_invoice_window_reset_document_layout_and_clear_user_state
(InvoiceWindow *iw);
+gboolean gnc_invoice_window_document_has_user_state (InvoiceWindow *iw);
+
 void gnc_invoice_window_entryUpCB (GtkWidget *widget, gpointer data);
 void gnc_invoice_window_entryDownCB (GtkWidget *widget, gpointer data);

diff --git a/gnucash/gnome/gnc-plugin-page-invoice.c
b/gnucash/gnome/gnc-plugin-page-invoice.c
index ead2a8236..fb74f75a2 100644
--- a/gnucash/gnome/gnc-plugin-page-invoice.c
+++ b/gnucash/gnome/gnc-plugin-page-invoice.c
@@ -83,6 +83,8 @@ static void gnc_plugin_page_invoice_cmd_delete (GtkAction
*action, GncPluginPage
 static void gnc_plugin_page_invoice_cmd_blank (GtkAction *action,
GncPluginPageInvoice *plugin_page);
 static void gnc_plugin_page_invoice_cmd_duplicateEntry (GtkAction *action,
GncPluginPageInvoice *plugin_page);
 static void gnc_plugin_page_invoice_cmd_pay_invoice (GtkAction *action,
GncPluginPageInvoice *plugin_page);
+static void gnc_plugin_page_invoice_cmd_save_layout (GtkAction *action,
GncPluginPageInvoice *plugin_page);
+static void gnc_plugin_page_invoice_cmd_reset_layout (GtkAction *action,
GncPluginPageInvoice *plugin_page);
 static void gnc_plugin_page_invoice_cmd_company_report (GtkAction *action,
GncPluginPageInvoice *plugin_page);

 static void gnc_plugin_page_redraw_help_cb( GnucashRegister *gsr,
GncPluginPageInvoice *invoice_page );
@@ -211,6 +213,18 @@ static GtkActionEntry gnc_plugin_page_invoice_actions
[] =
         "Open a company report window for the owner of this invoice",
         G_CALLBACK (gnc_plugin_page_invoice_cmd_company_report)
     },
+
+    /* Windows menu */
+    {
+        "WindowsSaveLayoutAction", NULL, "_Use as Default Layout for
Customer Documents", NULL,
+        "Use the current layout as default for all customer invoices and
credit notes",
+        G_CALLBACK (gnc_plugin_page_invoice_cmd_save_layout)
+    },
+    {
+        "WindowsResetLayoutAction", NULL, "_Reset Default Layout for
Customer Documents", NULL,
+        "Reset default layout for all customer invoices and credit notes
back to built-in defaults and update the current page accordingly",
+        G_CALLBACK (gnc_plugin_page_invoice_cmd_reset_layout)
+    },
 };
 static guint gnc_plugin_page_invoice_n_actions = G_N_ELEMENTS
(gnc_plugin_page_invoice_actions);

@@ -274,6 +288,13 @@ static action_toolbar_labels invoice_action_labels[] =
     {NULL, NULL},
 };

+static action_toolbar_labels invoice_action_layout_labels[] =
+{
+    {"WindowsSaveLayoutAction", N_("_Use as Default Layout for Customer
Documents")},
+    {"WindowsResetLayoutAction", N_("_Reset Default Layout for Customer
Documents")},
+    {NULL, NULL},
+};
+
 static action_toolbar_labels bill_action_labels[] =
 {
     {"FilePrintAction", N_("_Print Bill")},
@@ -286,6 +307,13 @@ static action_toolbar_labels bill_action_labels[] =
     {NULL, NULL},
 };

+static action_toolbar_labels bill_action_layout_labels[] =
+{
+    {"WindowsSaveLayoutAction", N_("_Use as Default Layout for Vendor
Documents")},
+    {"WindowsResetLayoutAction", N_("_Reset Default Layout for Vendor
Documents")},
+    {NULL, NULL},
+};
+
 static action_toolbar_labels voucher_action_labels[] =
 {
     {"FilePrintAction", N_("_Print Voucher")},
@@ -298,6 +326,13 @@ static action_toolbar_labels voucher_action_labels[] =
     {NULL, NULL},
 };

+static action_toolbar_labels voucher_action_layout_labels[] =
+{
+    {"WindowsSaveLayoutAction", N_("_Use as Default Layout for Employee
Documents")},
+    {"WindowsResetLayoutAction", N_("_Reset Default Layout for Employee
Documents")},
+    {NULL, NULL},
+};
+
 static action_toolbar_labels creditnote_action_labels[] =
 {
     {"FilePrintAction", N_("_Print Credit Note")},
@@ -324,6 +359,12 @@ static action_toolbar_labels invoice_action_tooltips[]
= {
     {NULL, NULL},
 };

+static action_toolbar_labels invoice_action_layout_tooltips[] = {
+    {"WindowsSaveLayoutAction", N_("Use the current layout as default for
all customer invoices and credit notes")},
+    {"WindowsResetLayoutAction", N_("Reset default layout for all customer
invoices and credit notes back to built-in defaults and update the current
page accordingly")},
+    {NULL, NULL},
+};
+
 static action_toolbar_labels bill_action_tooltips[] = {
     {"FilePrintAction", N_("Make a printable bill")},
     {"EditEditInvoiceAction", N_("Edit this bill")},
@@ -337,6 +378,12 @@ static action_toolbar_labels bill_action_tooltips[] = {
     {NULL, NULL},
 };

+static action_toolbar_labels bill_action_layout_tooltips[] = {
+    {"WindowsSaveLayoutAction", N_("Use the current layout as default for
all vendor bills and credit notes")},
+    {"WindowsResetLayoutAction", N_("Reset default layout for all vendor
bills and credit notes back to built-in defaults and update the current
page accordingly")},
+    {NULL, NULL},
+};
+
 static action_toolbar_labels voucher_action_tooltips[] = {
     {"FilePrintAction", N_("Make a printable voucher")},
     {"EditEditInvoiceAction", N_("Edit this voucher")},
@@ -350,6 +397,12 @@ static action_toolbar_labels voucher_action_tooltips[]
= {
     {NULL, NULL},
 };

+static action_toolbar_labels voucher_action_layout_tooltips[] = {
+    {"WindowsSaveLayoutAction", N_("Use the current layout as default for
all employee vouchers and credit notes")},
+    {"WindowsResetLayoutAction", N_("Reset default layout for all employee
vouchers and credit notes back to built-in defaults and update the current
page accordingly")},
+    {NULL, NULL},
+};
+
 static action_toolbar_labels creditnote_action_tooltips[] = {
     {"FilePrintAction", N_("Make a printable credit note")},
     {"EditEditInvoiceAction", N_("Edit this credit note")},
@@ -497,6 +550,39 @@ gnc_plugin_page_invoice_finalize (GObject *object)
     LEAVE(" ");
 }

+static void
+gnc_plugin_page_invoice_action_update (GtkActionGroup *action_group,
+                                       action_toolbar_labels *action_list,
+                                       void (*gtkfunc)(gpointer, gpointer))
+{
+    GtkAction *action;
+    gint i;
+
+    for (i = 0; action_list[i].action_name; i++)
+    {
+        /* update the action */
+        action = gtk_action_group_get_action (action_group,
+                                              action_list[i].action_name);
+        gtkfunc (action, _(action_list[i].label));
+    }
+}
+
+static void
+gnc_plugin_page_update_reset_layout_action (GncPluginPage *page)
+{
+    GncPluginPageInvoicePrivate *priv;
+    GtkAction *layout_action;
+    gboolean has_default = FALSE;
+
+    g_return_if_fail (GNC_IS_PLUGIN_PAGE_INVOICE(page));
+
+    priv = GNC_PLUGIN_PAGE_INVOICE_GET_PRIVATE(page);
+
+    layout_action = gnc_plugin_page_get_action (page,
"WindowsResetLayoutAction");
+    if (gnc_invoice_window_document_has_user_state (priv->iw))
+        has_default = TRUE;
+    gtk_action_set_sensitive (layout_action, has_default);
+}

 void
 gnc_plugin_page_invoice_update_menus (GncPluginPage *page, gboolean
is_posted, gboolean can_unpost)
@@ -504,12 +590,16 @@ gnc_plugin_page_invoice_update_menus (GncPluginPage
*page, gboolean is_posted, g
     GtkActionGroup *action_group;
     GncPluginPageInvoicePrivate *priv;
     GncInvoiceType invoice_type;
-    GtkAction *action;
     gint i, j;
     action_toolbar_labels *label_list;
     action_toolbar_labels *tooltip_list;
+    action_toolbar_labels *label_layout_list;
+    action_toolbar_labels *tooltip_layout_list;

     gboolean is_readonly = qof_book_is_readonly(gnc_get_current_book());
+
+    g_return_if_fail (GNC_IS_PLUGIN_PAGE_INVOICE(page));
+
     priv = GNC_PLUGIN_PAGE_INVOICE_GET_PRIVATE(page);
     invoice_type = gnc_invoice_get_type_from_window(priv->iw);

@@ -537,7 +627,27 @@ gnc_plugin_page_invoice_update_menus (GncPluginPage
*page, gboolean is_posted, g
             tooltip_list = invoice_action_tooltips;
     }

-    g_return_if_fail(GNC_IS_PLUGIN_PAGE_INVOICE(page));
+    // layout actions
+    switch (invoice_type) {
+        case GNC_INVOICE_CUST_INVOICE:
+        case GNC_INVOICE_CUST_CREDIT_NOTE:
+            label_layout_list = invoice_action_layout_labels;
+            tooltip_layout_list = invoice_action_layout_tooltips;
+            break;
+        case GNC_INVOICE_VEND_INVOICE:
+        case GNC_INVOICE_VEND_CREDIT_NOTE:
+            label_layout_list = bill_action_layout_labels;
+            tooltip_layout_list = bill_action_layout_tooltips;
+            break;
+        case GNC_INVOICE_EMPL_INVOICE:
+        case GNC_INVOICE_EMPL_CREDIT_NOTE:
+            label_layout_list = voucher_action_layout_labels;
+            tooltip_layout_list = voucher_action_layout_tooltips;
+            break;
+        default: // catches GNC_INVOICE_UNDEFINED, use invoice by default
+            label_layout_list = invoice_action_layout_labels;
+            tooltip_layout_list = invoice_action_layout_tooltips;
+    }

     if (is_readonly)
     {
@@ -556,21 +666,18 @@ gnc_plugin_page_invoice_update_menus (GncPluginPage
*page, gboolean is_posted, g
     gnc_plugin_update_actions (action_group,
invoice_book_readwrite_actions,
                                "sensitive", !is_readonly);

-    for (i = 0; label_list[i].action_name; i++)
-    {
-        /* update the action labels */
-        action = gtk_action_group_get_action(action_group,
-                                             label_list[i].action_name);
-        gtk_action_set_label(action, _(label_list[i].label));
-    }
+    /* update the action labels */
+    gnc_plugin_page_invoice_action_update (action_group, label_list,
(void*)gtk_action_set_label);
+    /* update the action tooltips */
+    gnc_plugin_page_invoice_action_update (action_group, tooltip_list,
(void*)gtk_action_set_tooltip);

-    for (i = 0; tooltip_list[i].action_name; i++)
-    {
-        /* update the action tooltips */
-        action = gtk_action_group_get_action(action_group,
-                                             tooltip_list[i].action_name);
-        gtk_action_set_tooltip(action, _(tooltip_list[i].label));
-    }
+    // if there is no default layout do not enable reset action
+    gnc_plugin_page_update_reset_layout_action (page);
+
+    /* update the layout action labels */
+    gnc_plugin_page_invoice_action_update (action_group,
label_layout_list, (void*)gtk_action_set_label);
+    /* update the layout action tooltips */
+    gnc_plugin_page_invoice_action_update (action_group,
tooltip_layout_list, (void*)gtk_action_set_tooltip);
 }


@@ -589,6 +696,9 @@ gnc_plugin_page_invoice_focus_widget (GncPluginPage
*invoice_plugin_page)
         GtkWidget *notes = gnc_invoice_get_notes(priv->iw);
         GnucashSheet *sheet;

+        // if there is no default layout do not enable reset action
+        gnc_plugin_page_update_reset_layout_action (invoice_plugin_page);
+
         if (!GNUCASH_IS_REGISTER(regWidget))
             return FALSE;

@@ -1117,6 +1227,48 @@ gnc_plugin_page_invoice_cmd_pay_invoice (GtkAction
*action,
     LEAVE(" ");
 }

+static void
+gnc_plugin_page_invoice_cmd_save_layout (GtkAction *action,
+        GncPluginPageInvoice *plugin_page)
+{
+    GncPluginPageInvoicePrivate *priv;
+    GtkWindow *parent;
+    GtkAction *layout_action;
+
+    g_return_if_fail (GNC_IS_PLUGIN_PAGE_INVOICE(plugin_page));
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+    priv = GNC_PLUGIN_PAGE_INVOICE_GET_PRIVATE(plugin_page);
+    gnc_invoice_window_save_document_layout_to_user_state (priv->iw);
+
+    layout_action = gnc_plugin_page_get_action
(GNC_PLUGIN_PAGE(plugin_page),
+
"WindowsResetLayoutAction");
+    gtk_action_set_sensitive (layout_action, TRUE);
+
+    LEAVE(" ");
+}
+
+static void
+gnc_plugin_page_invoice_cmd_reset_layout (GtkAction *action,
+        GncPluginPageInvoice *plugin_page)
+{
+    GncPluginPageInvoicePrivate *priv;
+    GtkWindow *parent;
+    GtkAction *layout_action;
+
+    g_return_if_fail (GNC_IS_PLUGIN_PAGE_INVOICE(plugin_page));
+
+    ENTER("(action %p, plugin_page %p)", action, plugin_page);
+    priv = GNC_PLUGIN_PAGE_INVOICE_GET_PRIVATE(plugin_page);
+    gnc_invoice_window_reset_document_layout_and_clear_user_state
(priv->iw);
+
+    layout_action = gnc_plugin_page_get_action
(GNC_PLUGIN_PAGE(plugin_page),
+
"WindowsResetLayoutAction");
+    gtk_action_set_sensitive (layout_action, FALSE);
+
+    LEAVE(" ");
+}
+
 static void
 gnc_plugin_page_invoice_cmd_company_report (GtkAction *action,
         GncPluginPageInvoice *plugin_page)
diff --git a/gnucash/register/register-gnome/gnucash-register.c
b/gnucash/register/register-gnome/gnucash-register.c
index 3cafe0870..bdd05936c 100644
--- a/gnucash/register/register-gnome/gnucash-register.c
+++ b/gnucash/register/register-gnome/gnucash-register.c
@@ -182,6 +182,37 @@ gnucash_register_refresh_from_prefs (GnucashRegister
*reg)
     gnc_header_request_redraw (GNC_HEADER(sheet->header_item));
 }

+void
+gnucash_register_reset_sheet_layout (GnucashRegister *reg)
+{
+    GNCHeaderWidths widths;
+    Table *table;
+    GList *node;
+    gchar *key;
+    guint value;
+    GnucashSheet *sheet;
+    gint current_width;
+
+    g_return_if_fail (reg != NULL);
+
+    sheet = GNUCASH_SHEET(reg->sheet);
+
+    g_return_if_fail (sheet != NULL);
+    g_return_if_fail (GNUCASH_IS_SHEET (sheet));
+
+    current_width = sheet->window_width - 1;
+
+    widths = gnc_header_widths_new ();
+    gnucash_sheet_set_header_widths (sheet, widths);
+
+    gnucash_sheet_styles_set_dimensions (sheet, current_width);
+
+    gnucash_sheet_compile_styles (sheet);
+    gnucash_sheet_table_load (sheet, TRUE);
+    gnucash_sheet_cursor_set_from_table (sheet, TRUE);
+    gnucash_sheet_redraw_all (sheet);
+    gnc_header_widths_destroy (widths);
+}

 void
 gnucash_register_goto_virt_cell (GnucashRegister *reg,
diff --git a/gnucash/register/register-gnome/gnucash-register.h
b/gnucash/register/register-gnome/gnucash-register.h
index 8fb4f7c1f..c512f149f 100644
--- a/gnucash/register/register-gnome/gnucash-register.h
+++ b/gnucash/register/register-gnome/gnucash-register.h
@@ -83,5 +83,6 @@ void gnucash_register_set_moved_cb (GnucashRegister *reg,
                                     GFunc cb, gpointer cb_data);

 GnucashSheet *gnucash_register_get_sheet (GnucashRegister *reg);
+void gnucash_register_reset_sheet_layout (GnucashRegister *reg);
 /** @} */
 #endif
diff --git a/gnucash/ui/gnc-plugin-page-invoice-ui.xml
b/gnucash/ui/gnc-plugin-page-invoice-ui.xml
index 8845d3205..8a823271e 100644
--- a/gnucash/ui/gnc-plugin-page-invoice-ui.xml
+++ b/gnucash/ui/gnc-plugin-page-invoice-ui.xml
@@ -49,6 +49,14 @@
         <menuitem name="ReportsCompanyReport"
 action="ReportsCompanyReportAction"/>
       </placeholder>
     </menu>
+
+    <menu name="Windows" action="WindowsAction">
+      <placeholder name="WindowsLayoutPlaceholder">
+        <menuitem name="WindowsSaveLayout"
 action="WindowsSaveLayoutAction"/>
+        <menuitem name="WindowsResetLayout"
action="WindowsResetLayoutAction"/>
+       </placeholder>
+    </menu>
+
   </menubar>

   <toolbar name="DefaultToolbar">
diff --git a/gnucash/ui/gnc-windows-menu-ui.xml
b/gnucash/ui/gnc-windows-menu-ui.xml
index a0aa24f8a..59d1c507f 100644
--- a/gnucash/ui/gnc-windows-menu-ui.xml
+++ b/gnucash/ui/gnc-windows-menu-ui.xml
@@ -5,6 +5,8 @@
     <menu name="Windows" action="WindowsAction">
       <menuitem name="WindowNew"      action="WindowNewAction"/>
       <menuitem name="WindowMovePage" action="WindowMovePageAction"/>
+      <separator name="ViewSep5"/>
+      <placeholder name="WindowsLayoutPlaceholder"/>
       <separator name="ViewSep4"/>
       <menuitem name="Window0"        action="Window0Action"/>
       <menuitem name="Window1"        action="Window1Action"/>
@@ -20,4 +22,4 @@
     </menu>

   </menubar>
-</ui>
\ No newline at end of file
+</ui>

commit b622518fcef9870eff07c4a642b326c9ec9d4c73
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Mon Mar 2 14:49:14 2020 +0000

    Test for a valid register state comment before trying
     to add it

diff --git a/gnucash/register/register-gnome/table-gnome.c
b/gnucash/register/register-gnome/table-gnome.c
index 53e53428b..ee0145e74 100644
--- a/gnucash/register/register-gnome/table-gnome.c
+++ b/gnucash/register/register-gnome/table-gnome.c
@@ -108,10 +108,12 @@ gnc_table_save_state (Table *table, gchar *
state_section, gchar * account_fulln
             g_key_file_remove_key (state_file, state_section, key, NULL);
         g_free (key);
     }
-    key = g_strdup_printf ("Register state for \"%s\"", account_fullname);
-    g_key_file_set_comment (state_file, state_section, NULL, key, NULL);
-    g_free (key);
-
+    if (account_fullname)
+    {
+        key = g_strdup_printf ("Register state for \"%s\"",
account_fullname);
+        g_key_file_set_comment (state_file, state_section, NULL, key,
NULL);
+        g_free (key);
+    }
     gnc_header_widths_destroy (widths);
 }




Summary of changes:
 gnucash/gnome-utils/gnc-tree-view-account.c        |   4 -
 gnucash/gnome/dialog-invoice.c                     |  76 ++++++-
 gnucash/gnome/dialog-invoice.h                     |   4 +
 gnucash/gnome/gnc-plugin-page-invoice.c            | 184 +++++++++++++--
 gnucash/gnome/gnc-plugin-page-register.c           | 247
++++++++++++---------
 gnucash/gnome/gnc-split-reg.c                      | 240
+++++++++++++++++---
 gnucash/gnome/gnc-split-reg.h                      |  17 +-
 .../register/ledger-core/split-register-layout.c   |  26 +--
 gnucash/register/ledger-core/split-register.c      |  49 ++++
 gnucash/register/ledger-core/split-register.h      |  19 ++
 gnucash/register/register-core/table-allgui.h      |   2 +-
 gnucash/register/register-gnome/gnucash-register.c |  31 ++-
 gnucash/register/register-gnome/gnucash-register.h |   3 +-
 gnucash/register/register-gnome/table-gnome.c      |   6 +-
 gnucash/ui/gnc-plugin-page-invoice-ui.xml          |   8 +
 gnucash/ui/gnc-plugin-page-register-ui.xml         |   7 +
 gnucash/ui/gnc-windows-menu-ui.xml                 |   4 +-
 17 files changed, 731 insertions(+), 196 deletions(-)

_______________________________________________
gnucash-changes mailing list
gnucash-changes at gnucash.org
https://lists.gnucash.org/mailman/listinfo/gnucash-changes


More information about the gnucash-devel mailing list