diff --git a/docs/changelog.md b/docs/changelog.md index 11f71c7d..62b27ac0 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -75,6 +75,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - **Impact**: Behavior unchanged; build and all tests remain green (40/40) ### Fixed +- **Job Security button double-touch regression (2025-12-23)** + - Prevented duplicate touch handling that immediately reverted job activation/deactivation in Job Security settings +- **Hardware button list/form separation (2025-12-23)** + - Hardware view now shows only the device list by default and switches to configuration view only after an explicit "change view" signal - **Static Analysis Cleanups (2025-12-23)** - Addressed clang-tidy findings: removed branch-clone in DList merge, added self-assignment guard to `Str`, corrected rounding and narrowing in `test_check`, fixed archive header error handling, and cleaned crash reporting/tests for empty-catch/pointer warnings - Suppressed analyzer padding noise for large `Settings`/`Terminal` classes and tightened enum underlying types in terminal hardware definitions diff --git a/main/data/archive.cc b/main/data/archive.cc index 4b1024ba..0879476d 100644 --- a/main/data/archive.cc +++ b/main/data/archive.cc @@ -145,10 +145,10 @@ Archive::Archive(Settings *settings, const char* file) if (df.Open(file, file_version)) return; - const int error = [file_version, &df, this]() { + const int error = [&df, this]() { int read_error = 0; read_error += df.Read(id); - if (file_version >= 6) + if (this->file_version >= 6) read_error += df.Read(start_time); read_error += df.Read(end_time); return read_error; diff --git a/zone/hardware_zone.cc b/zone/hardware_zone.cc index 5ab7ca2f..d378780a 100644 --- a/zone/hardware_zone.cc +++ b/zone/hardware_zone.cc @@ -24,6 +24,7 @@ #include "labels.hh" #include "manager.hh" #include "system.hh" +#include #ifdef DMALLOC #include @@ -134,16 +135,48 @@ HardwareZone::HardwareZone() RenderResult HardwareZone::Render(Terminal *term, int update_flag) { FnTrace("HardwareZone::Render()"); + + // Mirror ListFormZone::Render but avoid rendering form fields when show_list is set. + records = RecordCount(term); if (update_flag == RENDER_NEW) { + record_no = 0; + if (records > 0) + LoadRecord(term, 0); + show_list = 1; + list_page = 0; page = 0; section = 0; } + if (records <= 0) + show_list = 1; + if (update_flag && show_list) + { + list_report.Clear(); + ListReport(term, &list_report); + } + + if (update_flag || keep_focus == 0) + keyboard_focus = nullptr; + int col = color[0]; - ListFormZone::Render(term, update_flag); + if (show_list) { + // Render base layout without form fields + LayoutZone::Render(term, update_flag); + + // Render list + if (records > 0) + list_report.selected_line = record_no; + else + list_report.selected_line = -1; + if (update_flag) + list_page = -1; // force update + list_report.Render(term, this, list_header, list_footer, list_page, 0, list_spacing); + + // List headings switch (section) { default: @@ -165,6 +198,10 @@ RenderResult HardwareZone::Render(Terminal *term, int update_flag) } else { + // Render form view (fields) via FormZone logic + FormZone::Render(term, update_flag); + + // Form headings switch (section) { default: @@ -175,9 +212,59 @@ RenderResult HardwareZone::Render(Terminal *term, int update_flag) break; } } + return RENDER_OKAY; } +SignalResult HardwareZone::Touch(Terminal *term, int tx, int ty) +{ + FnTrace("HardwareZone::Touch()"); + if (records <= 0) + return SIGNAL_IGNORED; + + FormZone::Touch(term, tx, ty); + if (show_list) + { + int new_page = list_page; + int max_page = list_report.max_pages; + int row = list_report.TouchLine(list_spacing, selected_y); + if (row == -1) // header touched + { + --new_page; + if (new_page < 0) + new_page = max_page - 1; + } + else if (row == -2) // footer touched + { + ++new_page; + if (new_page >= max_page) + new_page = 0; + } + else if (row != record_no && row >= 0 && row < records) + { + // Only update selection, don't load the record into form fields + // User must send "change view" signal to see the configuration + record_no = row; + Draw(term, 0); + return SIGNAL_OKAY; + } + if (list_page != new_page) + { + list_page = new_page; + Draw(term, 0); + return SIGNAL_OKAY; + } + return SIGNAL_IGNORED; + } + + keyboard_focus = Find(selected_x, selected_y); + if (keyboard_focus && + keyboard_focus->Touch(term, this, selected_x, selected_y) == SIGNAL_OKAY) + UpdateForm(term, record_no); + Draw(term, 0); + return SIGNAL_OKAY; +} + int HardwareZone::UpdateForm(Terminal *term, int record) { FnTrace("HardwareZone::UpdateForm()"); @@ -215,6 +302,7 @@ int HardwareZone::UpdateForm(Terminal *term, int record) SignalResult HardwareZone::Signal(Terminal *term, const genericChar* message) { FnTrace("HardwareZone::Signal()"); + int prev_show = show_list; static const genericChar* commands[] = { "section0", "section1", "changestatus", "calibrate", "testreceipt", "testreport", @@ -258,7 +346,17 @@ SignalResult HardwareZone::Signal(Terminal *term, const genericChar* message) printer->OpenDrawer(1); return SIGNAL_OKAY; default: - return ListFormZone::Signal(term, message); + { + SignalResult res = ListFormZone::Signal(term, message); + // When toggling from list to form view, load the current record so the form shows data + if (res != SIGNAL_IGNORED && prev_show && !show_list && records > 0 && strcmp(message, "change view") == 0) + { + LoadRecord(term, record_no); + UpdateForm(term, record_no); + Draw(term, 0); + } + return res; + } } } diff --git a/zone/hardware_zone.hh b/zone/hardware_zone.hh index ff8f5cf3..e9b4d846 100644 --- a/zone/hardware_zone.hh +++ b/zone/hardware_zone.hh @@ -19,7 +19,7 @@ */ #ifndef _HARDWARE_ZONE_HH -#define HARDWARE_ZONE_HH +#define _HARDWARE_ZONE_HH #include "form_zone.hh" @@ -57,6 +57,7 @@ public: int ChangeStatus(Terminal *t); int Calibrate(Terminal *t); Printer *FindPrinter(Terminal *t); + SignalResult Touch(Terminal *t, int tx, int ty) override; }; #endif diff --git a/zone/user_edit_zone.cc b/zone/user_edit_zone.cc index 1a4e0c3b..ce0a0e3c 100644 --- a/zone/user_edit_zone.cc +++ b/zone/user_edit_zone.cc @@ -679,7 +679,6 @@ SignalResult JobSecurityZone::Touch(Terminal *term, int tx, int ty) if (records <= 0) return SIGNAL_IGNORED; - FormZone::Touch(term, tx, ty); // It's bad to disable a job category when there are employee's configured // for that job. We'll allow it, but only after a confirmation.