gnucash stable: Multiple changes pushed

John Ralls jralls at code.gnucash.org
Fri May 8 18:42:15 EDT 2026


Updated	 via  https://github.com/Gnucash/gnucash/commit/b8181871 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/99822a16 (commit)
	from  https://github.com/Gnucash/gnucash/commit/99208875 (commit)



commit b8181871dd61628ea82b464a0ee2a20cbfce5afe
Merge: 992088754f 99822a16c8
Author: John Ralls <jralls at ceridwen.us>
Date:   Fri May 8 15:41:57 2026 -0700

    Merge Sherlock's 'bug-436105' into stable


commit 99822a16c835ff76907df53ff245c3544b7f4bfb
Author: Sherlock <119709043+agwekixj at users.noreply.github.com>
Date:   Mon May 4 13:08:47 2026 -0700

    Bug 436105 - esc key not working as expected in register
    
    This patch enables the use of the Escape key to cancel an edit of a field in a transaction or a split restoring the value the field held when the user navigated to the transaction or split.

diff --git a/gnucash/register/register-core/basiccell.c b/gnucash/register/register-core/basiccell.c
index 850cf9239b..dd1afee20d 100644
--- a/gnucash/register/register-core/basiccell.c
+++ b/gnucash/register/register-core/basiccell.c
@@ -54,6 +54,22 @@ gnc_cell_name_equal (const char * cell_name_1,
     return (g_strcmp0 (cell_name_1, cell_name_2) == 0);
 }
 
+static void
+gnc_basic_cell_gui_realize (BasicCell* bcell, gpointer data)
+{
+     bcell->gui_private = data;
+     bcell->gui_realize = NULL;
+}
+
+static void
+gnc_basic_cell_gui_destroy (BasicCell* bcell)
+{
+    if (bcell->gui_realize == NULL)
+    {
+        bcell->gui_realize = gnc_basic_cell_gui_realize;
+    }
+}
+
 BasicCell *
 gnc_basic_cell_new (void)
 {
@@ -101,6 +117,9 @@ gnc_basic_cell_init (BasicCell *cell)
 {
     gnc_basic_cell_clear (cell);
 
+    cell->gui_realize = gnc_basic_cell_gui_realize;
+    cell->gui_destroy = gnc_basic_cell_gui_destroy;
+
     cell->value = g_strdup ("");
 }
 
diff --git a/gnucash/register/register-core/table-allgui.c b/gnucash/register/register-core/table-allgui.c
index e3fd5038f9..5a4d750460 100644
--- a/gnucash/register/register-core/table-allgui.c
+++ b/gnucash/register/register-core/table-allgui.c
@@ -242,59 +242,58 @@ gnc_table_get_header_cell (Table *table)
 }
 
 static const char *
-gnc_table_get_entry_internal (Table *table, VirtualLocation virt_loc,
-                              gboolean *conditionally_changed)
+table_get_model_entry (Table *table, VirtualLocation virt_loc,
+                       gboolean translate, gboolean *conditionally_changed, const char *cell_name)
 {
-    TableGetEntryHandler entry_handler;
-    const char *cell_name;
-    const char *entry;
+    TableGetEntryHandler entry_handler = gnc_table_model_get_entry_handler (
+            table->model, cell_name);
 
-    cell_name = gnc_table_get_cell_name (table, virt_loc);
+    if (entry_handler)
+    {
+        const char *entry = entry_handler (virt_loc, translate, conditionally_changed,
+                                           table->model->handler_user_data);
+        if (entry)
+            return entry;
+    }
 
-    entry_handler = gnc_table_model_get_entry_handler (table->model, cell_name);
-    if (!entry_handler) return "";
+    return "";
+}
 
-    entry = entry_handler (virt_loc, FALSE,
-                           conditionally_changed,
-                           table->model->handler_user_data);
-    if (!entry)
-        entry = "";
+static const char *
+table_get_entry (Table *table, VirtualLocation virt_loc,
+                 gboolean *conditionally_changed)
+{
+    const char *cell_name = gnc_table_get_cell_name (table, virt_loc);
 
-    return entry;
+    return table_get_model_entry (table, virt_loc, FALSE, conditionally_changed,
+                                  cell_name);
 }
 
 const char *
 gnc_table_get_entry (Table *table, VirtualLocation virt_loc)
 {
-    TableGetEntryHandler entry_handler;
-    const char *entry;
-    BasicCell *cell;
+    BasicCell *cell = gnc_table_get_cell (table, virt_loc);
 
-    cell = gnc_table_get_cell (table, virt_loc);
     if (!cell || !cell->cell_name)
         return "";
 
     if (virt_cell_loc_equal (table->current_cursor_loc.vcell_loc,
                              virt_loc.vcell_loc))
     {
-        CellIOFlags io_flags;
-
-        io_flags = gnc_table_get_io_flags (table, virt_loc);
+        CellIOFlags io_flags = gnc_table_get_io_flags (table, virt_loc);
 
         if (io_flags & XACC_CELL_ALLOW_INPUT)
             return cell->value;
     }
 
-    entry_handler = gnc_table_model_get_entry_handler (table->model,
-                    cell->cell_name);
-    if (!entry_handler) return "";
-
-    entry = entry_handler (virt_loc, TRUE, NULL,
-                           table->model->handler_user_data);
-    if (!entry)
-        entry = "";
+    return table_get_model_entry (table, virt_loc, TRUE, NULL, cell->cell_name);
+}
 
-    return entry;
+const char *
+gnc_table_get_model_entry (Table *table, const char *cell_name)
+{
+    return table_get_model_entry (table, table->current_cursor_loc, TRUE, NULL,
+                                  cell_name);
 }
 
 char *
@@ -307,8 +306,8 @@ gnc_table_get_tooltip (Table *table, VirtualLocation virt_loc)
     if (!cell || !cell->cell_name)
         return NULL;
 
-    tooltip_handler = gnc_table_model_get_tooltip_handler (table->model,
-                         cell->cell_name);
+    tooltip_handler =
+        gnc_table_model_get_tooltip_handler (table->model, cell->cell_name);
 
     if (!tooltip_handler)
         return NULL;
@@ -328,8 +327,8 @@ gnc_table_get_io_flags (Table *table, VirtualLocation virt_loc)
 
     cell_name = gnc_table_get_cell_name (table, virt_loc);
 
-    io_flags_handler = gnc_table_model_get_io_flags_handler (table->model,
-                       cell_name);
+    io_flags_handler =
+        gnc_table_model_get_io_flags_handler (table->model, cell_name);
     if (!io_flags_handler)
         return XACC_CELL_ALLOW_NONE;
 
@@ -366,7 +365,7 @@ gnc_table_get_label (Table *table, VirtualLocation virt_loc)
 
 guint32
 gnc_table_get_color (Table *table, VirtualLocation virt_loc,
-                                 gboolean *hatching)
+                     gboolean *hatching)
 {
     TableGetCellColorHandler color_handler;
     const char *handler_name;
@@ -379,8 +378,8 @@ gnc_table_get_color (Table *table, VirtualLocation virt_loc,
 
     handler_name = gnc_table_get_cell_name (table, virt_loc);
 
-    color_handler = gnc_table_model_get_cell_color_handler (table->model,
-                                                            handler_name);
+    color_handler =
+        gnc_table_model_get_cell_color_handler (table->model, handler_name);
 
     if (!color_handler)
         return COLOR_UNDEFINED;
@@ -401,8 +400,8 @@ gnc_table_get_borders (Table *table, VirtualLocation virt_loc,
 
     cell_name = gnc_table_get_cell_name (table, virt_loc);
 
-    cell_border_handler = gnc_table_model_get_cell_border_handler (table->model,
-                          cell_name);
+    cell_border_handler =
+        gnc_table_model_get_cell_border_handler (table->model, cell_name);
     if (!cell_border_handler)
         return;
 
@@ -860,8 +859,8 @@ gnc_table_move_cursor_internal (Table *table,
                     const char *entry;
                     gboolean conditionally_changed = FALSE;
 
-                    entry = gnc_table_get_entry_internal (table, virt_loc,
-                                                          &conditionally_changed);
+                    entry = table_get_entry (table, virt_loc,
+                                             &conditionally_changed);
 
                     gnc_basic_cell_set_value (cell, entry);
 
@@ -1333,16 +1332,21 @@ gnc_table_direct_update (Table *table,
 
     ENTER ("");
 
-    if (cell->direct_update == NULL)
+    gboolean changed = cell->changed;
+    old_value = g_strdup (cell->value);
+
+    CellDirectUpdateFunc du = cell->direct_update;
+
+    if (du == NULL)
+        du = table->gui_handlers.default_direct_update;
+
+    if (du == NULL)
     {
         LEAVE("no direct update");
         return FALSE;
     }
 
-    old_value = g_strdup (cell->value);
-
-    result = cell->direct_update (cell, cursor_position, start_selection,
-                                  end_selection, gui_data);
+    result = du (cell, cursor_position, start_selection, end_selection, gui_data);
 
     if (g_strcmp0 (old_value, cell->value) != 0)
     {
@@ -1354,7 +1358,8 @@ gnc_table_direct_update (Table *table,
         }
         else
         {
-            cell->changed = TRUE;
+            if (!changed)
+                cell->changed = TRUE;
             *newval_ptr = cell->value;
         }
     }
diff --git a/gnucash/register/register-core/table-allgui.h b/gnucash/register/register-core/table-allgui.h
index 03a0e08af2..52c1be9ae5 100644
--- a/gnucash/register/register-core/table-allgui.h
+++ b/gnucash/register/register-core/table-allgui.h
@@ -154,6 +154,8 @@ typedef struct
 
     TableRedrawHelpCB redraw_help;
     TableDestroyCB destroy;
+    
+    CellDirectUpdateFunc default_direct_update;
 } TableGUIHandlers;
 
 struct table
@@ -267,6 +269,8 @@ gboolean       gnc_table_get_cell_location (Table *table,
         VirtualCellLocation vcell_loc,
         VirtualLocation *virt_loc);
 
+const char *   gnc_table_get_model_entry (Table *table, const char *cell_name);
+
 void           gnc_table_save_cells (Table *table, gpointer save_data);
 
 
diff --git a/gnucash/register/register-gnome/combocell-gnome.c b/gnucash/register/register-gnome/combocell-gnome.c
index 9f8ee160b8..05b942c069 100644
--- a/gnucash/register/register-gnome/combocell-gnome.c
+++ b/gnucash/register/register-gnome/combocell-gnome.c
@@ -560,7 +560,8 @@ gnc_combo_cell_type_ahead_search (const gchar* newval,
     gtk_list_store_clear (box->tmp_store);
     unblock_list_signals (cell);
 
-    if (strlen (newval) == 0) {
+    if (strlen (newval) == 0)
+    {
         /* Deleting everything in the cell shouldn't provide a search result for
          * "" because that will just be the first MAX_NUM_MATCHES accounts which
          * isn't very useful.
@@ -737,6 +738,27 @@ gnc_combo_cell_direct_update (BasicCell* bcell,
     unicode_value = gdk_keyval_to_unicode (event->keyval);
     switch (event->keyval)
     {
+    case GDK_KEY_Escape:
+        if (bcell->changed)
+        {
+            const char *value = gnc_table_get_model_entry (box->sheet->table, bcell->cell_name);
+
+            if (cell->shared_store && gnc_item_list_using_temp (box->item_list))
+            {
+                gnc_item_list_set_temp_store (box->item_list, NULL);
+                gtk_list_store_clear (box->tmp_store);
+            }
+            gnc_basic_cell_set_value_internal (bcell, value);
+            bcell->changed = FALSE;
+            block_list_signals (cell);
+            gnc_item_list_select (box->item_list, value);
+            unblock_list_signals (cell);
+            *cursor_position = -1;
+            *start_selection = 0;
+            *end_selection = -1;
+            return TRUE;
+        }
+        break;
     case GDK_KEY_slash:
         if (! (event->state & GDK_MOD1_MASK))
         {
@@ -757,8 +779,7 @@ gnc_combo_cell_direct_update (BasicCell* bcell,
             g_free (string);
             return FALSE;
         }
-        if (! (event->state & GDK_CONTROL_MASK) &&
-            !keep_on_going)
+        if (! (event->state & GDK_CONTROL_MASK) && !keep_on_going)
             return FALSE;
 
         match = gnc_quickfill_get_string_len_match
diff --git a/gnucash/register/register-gnome/completioncell-gnome.c b/gnucash/register/register-gnome/completioncell-gnome.c
index 64235375c2..76e47ad6e7 100644
--- a/gnucash/register/register-gnome/completioncell-gnome.c
+++ b/gnucash/register/register-gnome/completioncell-gnome.c
@@ -765,6 +765,19 @@ gnc_completion_cell_direct_update (BasicCell* bcell,
 
     switch (event->keyval)
     {
+    case GDK_KEY_Escape:
+        if (bcell->changed)
+        {
+            const char *value = gnc_table_get_model_entry (box->sheet->table, bcell->cell_name);
+
+            gnc_basic_cell_set_value_internal (bcell, value);
+            bcell->changed = FALSE;
+            *cursor_position = 0;
+            *start_selection = 0;
+            *end_selection = -1;
+            return TRUE;
+        }
+        break;
     case GDK_KEY_Tab:
     case GDK_KEY_ISO_Left_Tab:
         {
diff --git a/gnucash/register/register-gnome/datecell-gnome.c b/gnucash/register/register-gnome/datecell-gnome.c
index 351019912b..97ab3a7039 100644
--- a/gnucash/register/register-gnome/datecell-gnome.c
+++ b/gnucash/register/register-gnome/datecell-gnome.c
@@ -499,6 +499,22 @@ gnc_date_cell_direct_update (BasicCell *bcell,
     GdkEventKey *event = gui_data;
     char buff[DATE_BUF];
 
+    if (event->keyval == GDK_KEY_Escape)
+    {
+        if (bcell->changed)
+        {
+            const char *value = gnc_table_get_model_entry (box->sheet->table, bcell->cell_name);
+
+            gnc_basic_cell_set_value_internal (bcell, value);
+            bcell->changed = FALSE;
+            *cursor_position = 0;
+            *start_selection = 0;
+            *end_selection = -1;
+            return TRUE;
+        }
+        return FALSE;
+    }
+
     if (!gnc_handle_date_accelerator (event, &(box->date), bcell->value))
         return FALSE;
 
diff --git a/gnucash/register/register-gnome/formulacell-gnome.c b/gnucash/register/register-gnome/formulacell-gnome.c
index 196d7d2099..810bb49fff 100644
--- a/gnucash/register/register-gnome/formulacell-gnome.c
+++ b/gnucash/register/register-gnome/formulacell-gnome.c
@@ -39,6 +39,9 @@
 #include "formulacell.h"
 #include "formulacell-gnome.h"
 #include "pricecell-gnome.h"
+#include "gnucash-sheet.h"
+#include "gnucash-sheetP.h"
+#include "table-allgui.h"
 
 #ifdef G_OS_WIN32
 # include <gdk/gdkwin32.h>
@@ -74,6 +77,21 @@ gnc_formula_cell_direct_update( BasicCell *bcell,
 
     switch (event->keyval)
     {
+    case GDK_KEY_Escape:
+        if (bcell->changed)
+        {
+            GnucashSheet *sheet = (GnucashSheet *) bcell->gui_private;
+            const char *value = gnc_table_get_model_entry (sheet->table, bcell->cell_name);
+
+            gnc_basic_cell_set_value_internal (bcell, value);
+            bcell->changed = FALSE;
+            *cursor_position = 0;
+            *start_selection = 0;
+            *end_selection = -1;
+            return TRUE;
+        }
+        return FALSE;
+
     case GDK_KEY_Return:
         if (!(event->state &
                 (GDK_MODIFIER_INTENT_DEFAULT_MOD_MASK)))
diff --git a/gnucash/register/register-gnome/pricecell-gnome.c b/gnucash/register/register-gnome/pricecell-gnome.c
index 5392b928dd..2f8c941893 100644
--- a/gnucash/register/register-gnome/pricecell-gnome.c
+++ b/gnucash/register/register-gnome/pricecell-gnome.c
@@ -36,6 +36,9 @@
 #include "gnc-ui-util.h"
 #include "pricecell.h"
 #include "pricecell-gnome.h"
+#include "gnucash-sheet.h"
+#include "gnucash-sheetP.h"
+#include "table-allgui.h"
 
 #ifdef G_OS_WIN32
 # include <gdk/gdkwin32.h>
@@ -62,6 +65,21 @@ gnc_price_cell_direct_update (BasicCell *bcell,
 
     switch (event->keyval)
     {
+    case GDK_KEY_Escape:
+        if (bcell->changed)
+        {
+            GnucashSheet *sheet = (GnucashSheet *) bcell->gui_private;
+            const char *value = gnc_table_get_model_entry (sheet->table, bcell->cell_name);
+
+            gnc_basic_cell_set_value_internal (bcell, value);
+            bcell->changed = FALSE;
+            *cursor_position = 0;
+            *start_selection = 0;
+            *end_selection = -1;
+            return TRUE;
+        }
+        return FALSE;
+
     case GDK_KEY_Return:
         if (!(event->state &
                 (GDK_MODIFIER_INTENT_DEFAULT_MOD_MASK)))
diff --git a/gnucash/register/register-gnome/quickfillcell-gnome.c b/gnucash/register/register-gnome/quickfillcell-gnome.c
index 3b581fd8e1..de1557d1cf 100644
--- a/gnucash/register/register-gnome/quickfillcell-gnome.c
+++ b/gnucash/register/register-gnome/quickfillcell-gnome.c
@@ -34,6 +34,9 @@
 
 #include "quickfillcell.h"
 #include "quickfillcell-gnome.h"
+#include "gnucash-sheet.h"
+#include "gnucash-sheetP.h"
+#include "table-allgui.h"
 
 
 static gboolean
@@ -54,6 +57,20 @@ gnc_quickfill_cell_direct_update (BasicCell *bcell,
 
     switch (event->keyval)
     {
+    case GDK_KEY_Escape:
+        if (bcell->changed)
+        {
+            GnucashSheet *sheet = (GnucashSheet *) bcell->gui_private;
+            const char *value = gnc_table_get_model_entry (sheet->table, bcell->cell_name);
+
+            gnc_basic_cell_set_value_internal (bcell, value);
+            bcell->changed = FALSE;
+            *cursor_position = 0;
+            *start_selection = 0;
+            *end_selection = -1;
+            return TRUE;
+        }
+        return FALSE;
     case GDK_KEY_slash:
         if (!(event->state & GDK_MOD1_MASK))
             return FALSE;
diff --git a/gnucash/register/register-gnome/table-gnome.c b/gnucash/register/register-gnome/table-gnome.c
index 825e772680..cf43b11e72 100644
--- a/gnucash/register/register-gnome/table-gnome.c
+++ b/gnucash/register/register-gnome/table-gnome.c
@@ -145,20 +145,36 @@ table_destroy_cb (Table *table)
     table->ui_data = NULL;
 }
 
+static gboolean
+table_default_direct_update (BasicCell *bcell,
+                             int *cursor_position,
+                             int *start_selection,
+                             int *end_selection,
+                             void *gui_data)
+{
+    GdkEventKey *event = gui_data;
 
-/* Um, this function checks that data is not null but never uses it.
-   Weird.  Also, since this function only works with a GnucashRegister
-   widget, maybe some of it should be moved to gnucash-sheet.c. */
-/* Adding to previous note:  Since data doesn't appear do anything and to
-   align the function with save_state() I've removed the check for
-   NULL and changed two calls in dialog_order.c and dialog_invoice.c
-   to pass NULL as second parameter. */
+    if (event->keyval == GDK_KEY_Escape && bcell->changed)
+    {
+        GnucashSheet *sheet = (GnucashSheet *) bcell->gui_private;
+        const char *value = gnc_table_get_model_entry (sheet->table, bcell->cell_name);
+
+        gnc_basic_cell_set_value_internal (bcell, value);
+        bcell->changed = FALSE;
+        *cursor_position = 0;
+        *start_selection = 0;
+        *end_selection = -1;
+        return TRUE;
+    }
+    return FALSE;
+}
 
 void
 gnc_table_init_gui (Table *table)
 {
     table->gui_handlers.redraw_help = table_ui_redraw_cb;
     table->gui_handlers.destroy = table_destroy_cb;
+    table->gui_handlers.default_direct_update = table_default_direct_update;
 }
 
 void



Summary of changes:
 gnucash/register/register-core/basiccell.c         | 19 +++++
 gnucash/register/register-core/table-allgui.c      | 99 ++++++++++++----------
 gnucash/register/register-core/table-allgui.h      |  4 +
 gnucash/register/register-gnome/combocell-gnome.c  | 27 +++++-
 .../register/register-gnome/completioncell-gnome.c | 13 +++
 gnucash/register/register-gnome/datecell-gnome.c   | 16 ++++
 .../register/register-gnome/formulacell-gnome.c    | 18 ++++
 gnucash/register/register-gnome/pricecell-gnome.c  | 18 ++++
 .../register/register-gnome/quickfillcell-gnome.c  | 17 ++++
 gnucash/register/register-gnome/table-gnome.c      | 30 +++++--
 10 files changed, 204 insertions(+), 57 deletions(-)



More information about the gnucash-changes mailing list