From 99822a16c835ff76907df53ff245c3544b7f4bfb Mon Sep 17 00:00:00 2001 From: Sherlock <119709043+agwekixj@users.noreply.github.com> Date: Mon, 4 May 2026 13:08:47 -0700 Subject: [PATCH] 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. --- gnucash/register/register-core/basiccell.c | 19 ++++ gnucash/register/register-core/table-allgui.c | 99 ++++++++++--------- gnucash/register/register-core/table-allgui.h | 4 + .../register/register-gnome/combocell-gnome.c | 27 ++++- .../register-gnome/completioncell-gnome.c | 13 +++ .../register/register-gnome/datecell-gnome.c | 16 +++ .../register-gnome/formulacell-gnome.c | 18 ++++ .../register/register-gnome/pricecell-gnome.c | 18 ++++ .../register-gnome/quickfillcell-gnome.c | 17 ++++ gnucash/register/register-gnome/table-gnome.c | 30 ++++-- 10 files changed, 204 insertions(+), 57 deletions(-) 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 ""; + return table_get_model_entry (table, virt_loc, TRUE, NULL, cell->cell_name); +} - entry = entry_handler (virt_loc, TRUE, NULL, - table->model->handler_user_data); - if (!entry) - entry = ""; - - 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 @@ -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 @@ -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