fix(plugin): missed-update fixes, server re-check, and bold Building Will results (v0.3.2)

Revert the v0.3.1 double-invalidation change (it caused an inheritance-list
regression: stale/invalidated wills lingered and heir/date updates became
incoherent) and add several targeted missed-update fixes plus a UI refinement.

Revert (v0.3.1 -> v0.3.2):
- Remove Will.mark_invalidated_by_tx() and its call in
  loop_broadcast_invalidating. core/will.py and gui/qt/dialogs.py are restored
  to the working v0.3.0 behaviour. The postpone double-invalidation issue is
  intentionally left open, to be addressed without touching the shared
  broadcast path.

FIX 1 - detect heir removal on Check / Electrum close:
- core/will.py (check_willexecutors_and_heirs): the else-branch now raises
  HeirNotFoundException when a will still carries an heir that is no longer in
  the current heirs set (heir removed), mirroring the existing 'heir added'
  path. Rebuild therefore triggers on Check and on_close (same build_will_task
  path), as decided by the user (manual update only, no auto-rebuild).

FIX 2 - Check queries servers for already-sent wills:
- core/will.py: new Will.needs_server_check(w) returns True for any VALID will
  with a will-executor that is not yet CHECKED (no longer limited to PUSHED).
- gui/qt/lists.py (PreviewList.check): use needs_server_check so wills stuck on
  'New / Not sent' are re-checked instead of reporting 'nothing to do'.

FIX 3 - Settings-dialog hide toggles refresh the list:
- core/plugin_base.py: new sync_hide_filters() re-reads the cached
  _hide_invalidated / _hide_replaced flags from the persisted config.
- gui/qt/window.py (update_all): call sync_hide_filters() before refreshing, so
  toggling 'Hide Invalidated' / 'Hide Replaced' in the Settings dialog (which
  writes the config directly) updates the transaction list immediately instead
  of requiring an Electrum restart.

UI - bold results in the Building Will dialog:
- gui/qt/dialogs.py (BalBuildWillDialog): render the right-side results in bold
  (Ok, Ko, Nothing to do, Skipped, Wait, Timeout, ...) keeping the left-side
  state labels in normal weight. Centralised in msg_ok/msg_error/msg_warning/
  msg_set_status, plus the will-executor push/check rows now show Ok/Ko and
  True/False in bold + colour (green/red).

Tests/tooling:
- tests/test_core_will.py: add test_check_heirs_unchanged_is_coherent,
  test_check_heir_removed_triggers_rebuild, test_check_heir_added_triggers_rebuild,
  test_needs_server_check.
- tests/sim_update_flows.py: real-world update-scenario simulation.
- tests/preview_build_will_dialog.py, tests/preview_we_rows.py: GUI-only
  before/after previews of the bold formatting.
- Bump version to 0.3.2 (VERSION, manifest.json, __init__.py, plugin_base.py).

186 tests pass; smoke test, external-zip test and update-flow simulation OK;
ruff reports only pre-existing star-import false positives.
This commit is contained in:
GenSpark AI Developer
2026-06-16 07:56:11 +00:00
parent d0947f7e50
commit a1c6710d87
14 changed files with 669 additions and 163 deletions

View File

@@ -91,7 +91,7 @@ class BalPlugin(BasePlugin):
"""
_version = None
__version__ = "0.3.1" # AUTOMATICALLY GENERATED DO NOT EDIT
__version__ = "0.3.2" # AUTOMATICALLY GENERATED DO NOT EDIT
# Command used to open an .ics calendar file, per operating system.
default_app = {
@@ -237,6 +237,29 @@ class BalPlugin(BasePlugin):
"""Absolute path to a file bundled inside the plugin directory."""
return os.path.join(self.plugin_dir, *parts)
def sync_hide_filters(self):
"""Re-read the "hide" filter flags from the persisted config.
The cached ``_hide_invalidated`` / ``_hide_replaced`` flags are used by
the GUI list to decide which rows to skip. They can be changed from two
different places:
* the list toolbar buttons, which call :meth:`hide_invalidated` /
:meth:`hide_replaced` (a toggle that updates both the cache and the
config), and
* the Settings dialog checkboxes, which write the config directly
(``BalConfig.set``) without touching the cached flags.
In the second case the cache and the config would drift apart and the
transaction list would keep filtering with the *old* value, so the
toggled rows never appear/disappear until Electrum is restarted.
Re-syncing the cache from the config here (called by ``update_all``)
keeps every code path coherent regardless of where the change came
from.
"""
self._hide_invalidated = self.HIDE_INVALIDATED.get()
self._hide_replaced = self.HIDE_REPLACED.get()
def hide_invalidated(self):
"""Toggle (and persist) the "hide invalidated transactions" filter."""
self._hide_invalidated = not self._hide_invalidated