Merge beta to 1.16.0 - #664
Merged
Merged
Conversation
docs: refresh screenshots (v1.15.0)
- Document GSAK database import, GGZ export/send-to-GPS, double-click to open in browser, Trackables column/tab, custom icon packs, Support OpenSAK, and the hint-decode-by-default setting - Remove stale note claiming GGZ export wasn't available yet - Fix stale 'Last updated June 2026' footer date
Writing \\n (literal backslash-n) instead of \n (an actual newline escape) in a language file's source shows up in the UI as a raw backslash-n instead of a line break. Reported on Facebook for German; turned out to also affect Danish, French, Dutch, Portuguese, Swedish, and Czech (11 separate keys there) -- only English was unaffected. Added a language test (test_no_double_escaped_newlines) to catch this automatically going forward.
New 'Notify me about beta releases too' checkbox under Settings -> Updates, off by default. When enabled, a stable-running user is checked against both the latest stable and latest beta release, and offered whichever is objectively newer -- same dual-check logic already used for beta users discovering stable releases.
docs: refresh screenshots (v1.16.0-beta.1)
- Custom waypoint types (Parking Area, Trailhead, Stage, Final Location, Reference Point, Waypoint, Hotel/POI, Custom) each get their own distinct icon in the table, map and detail panel, instead of all sharing the generic "unknown" (?) icon. Icons are overridable via the same icons/cache_types/ user-icon mechanism as issue #519. - #593: removed the 12 unused found-smiley colour variants and the per-type colour-selection machinery (_FOUND_COLOR_MAP, _get_found_svg/_get_found_svg_for_key, the found= param on get_cache_type_icon/get_cache_type_pixmap). Only "gold" (Found overlay + "Found" column) and "dark_blue" (DNF overlay) were ever actually rendered by the app; the rest was dead code/assets. - Updated the bundled Custom Icon Guide (new waypoint-icon table, found-smiley table trimmed to 2 entries). - Version bumped via scripts/bump_version.py to 1.16.0-beta.2.
docs: refresh screenshots (v1.16.0-beta.2)
- Center point picker for the distance filter (#511): Home, saved home points, selected cache, or a manual coordinate; exposes the existing min-distance option alongside max. Built as a standalone widget for future reuse (#558). - "Set as center point" right-click action (#511): recompute Distance for all caches from any selected cache/custom waypoint, same mechanism as switching Home; shown in the info bar and Home dropdown. - Fix: hint markup ([br], [Étape], ...) was being ROT13-scrambled instead of left as literal markup; [br] now renders as a line break in both the cache detail hint tab and KML export (#595). - Fix: corrected GSAK's freeware date on the landing page, 2019 not 2021 (#589). - Bump version to 1.16.0-beta.3 (scripts/bump_version.py) + CHANGELOG.
docs: refresh screenshots (v1.16.0-beta.3)
…#601, #464) - DatabaseManager.databases now returns entries sorted alphabetically (case-insensitive) by name instead of insertion order. This single change fixes the dropdown/list ordering everywhere it's consumed: toolbar db combo, Manage Databases dialog, Move Caches dialog, GSAK import dialog, and the regular import dialog. - Underlying storage/insertion order in opensak.json is unchanged; only the public property's return order changed. - Added regression test test_databases_are_alphabetically_sorted. - Updated 3 existing tests in TestCopyDatabase that relied on databases[-1] (insertion order) to instead look up the db by name. - Fixes #601 (duplicate report), closes #531. - db_created_msg no longer tells the user to click "Switch to this" to activate the new database, since new_database() already calls switch_to() automatically right after creation. Updated wording in all 8 language files. Closes #464.
docs: refresh screenshots (v1.16.0-beta.4)
recalculate_distances() now persists the centre point + distance_method it was run with (per database). On startup, distances_up_to_date() compares this against the current centre/method and does a cheap single-row spot-check against the persisted Cache.distance column before deciding whether a full recalculation is needed. This makes normal startup skip the O(n) recalc entirely, since recalculate_distances() already runs on import, home-point change, and Settings dialog close. The spot-check guards against a database modified outside this OpenSAK install (e.g. synced from another machine with a different home point).
docs: refresh screenshots (v1.16.0-beta.5)
docs: refresh screenshots (v1.15.1)
…isplay Same fix as the v1.15.1 hotfix, applied here so the 1.16.0 line also carries it. See the hotfix-1.15.1 commit for full details. Fixes: #609
localization: update and fix french translation
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6 to 7. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](actions/setup-python@v6...v7) --- updated-dependencies: - dependency-name: actions/setup-python dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
…ta/actions/setup-python-7 ci(deps): bump actions/setup-python from 6 to 7
docs: refresh screenshots (v1.16.0-beta.11)
…inheritance (#617, #618, #606) #617: _parse_datetime() only handled a bare or 'Z'-suffixed ISO 8601 timestamp. Project-GC's GPX export instead uses an explicit UTC offset ("2026-03-16T00:00:00+00:00"), which silently failed to parse, dropping hidden_date (and any log dates using the same format). Now tries datetime.fromisoformat() first and converts properly to UTC, falling back to the previous strptime patterns. #618: Logs were deleted and fully rebuilt from the GPX file on every re-import, so any log not present in that particular file (a PQ only ever carries a cache's most recent handful of logs) was permanently lost. Logs are now merged: matching log_id's are updated in place, new ones are added, and existing logs absent from the current file are left untouched. log_count, last_log_date and dnf_date are now derived from the merged set so a partial re-import can no longer move them backwards or wipe them. #606: Column visibility/widths are saved per database name. A brand-new database had no such key yet and fell straight back to the hard-coded defaults, silently reverting any customisation (e.g. added Country/ State/County columns) made in another database. Added a global "last used" fallback key, updated on every save, that a new database falls back to before the hard-coded defaults. Tests added: - TestParseDatetimeOffsets + 2 import-level tests for #617 - 4 new tests covering log accumulation/update/last_log_date/dnf_date consistency across re-imports for #618 - TestLastUsedFallback (5 tests) for #606, using a fake DB manager fixture - cache_wpt() test helper gained an optional hidden_date parameter 2172 unit tests pass, mypy clean across src/opensak/.
…t Cache Confirmed with the real GC8T83E.gpx from the reporter (not reproducible as "Mystery"/"Unknown Cache" with today's beta on this file — that part of the original report couldn't be reproduced). The actual gap: Community Celebration Events (a limited-run program, May 2020 - Dec 2021) never got their own value in Groundspeak's machine-readable <groundspeak:type> field. geocaching.com's GPX always exports these as plain "Event Cache"; "Community Celebration Event" only appears in the free-text cache name (e.g. "Karlínská kasárna - Community Celebration Event"). Added a narrow fallback in _parse_wpt(): only when groundspeak:type is exactly "Event Cache" AND the cache name contains the literal phrase "Community Celebration Event", reclassify to "Community Celebration Event" — which already has its own icon/mapping in icon_provider.py and utils/constants.py, it just was never being reached. Tests added: - Real fixture (trimmed from Allan's GC8T83E.gpx) confirms correct reclassification - A plain Event Cache with an unrelated name is NOT reclassified - A non-Event-type cache that merely mentions the phrase in its name is NOT reclassified (fallback only fires on the exact groundspeak:type) 2175 unit tests pass, mypy clean across src/opensak/.
Promotes the [Unreleased] section to a dated v1.16.0-beta.12 heading covering the GPX-import fix cluster: #617 (hidden date lost from Project-GC), #618 (logs wiped on re-import instead of accumulating), #591 (CCE caches shown as generic Event Cache), and #606 (column settings not inherited by a new database). Version bumped via scripts/bump_version.py — updates src/opensak/__init__.py and the 5 hardcoded references in site/user-guide.html atomically.
docs: refresh screenshots (v1.16.0-beta.12)
The "Choose columns" dialog now supports named, saveable "Column Views" (visible columns, widths, container/type display), parallel to the existing saved filter profiles: a dropdown lists saved views, a Save button (💾) stores the current selection under a name, and a Delete button removes one. A new "Set as Default" button marks the currently selected saved view as the global default (shown with a ★ in the dropdown). Any database without its own explicit per-database column configuration — including brand-new databases — now falls back to the designated default view instead of the hard-coded factory defaults. Clicking OK still always locks the active database to the chosen configuration, unchanged from before. This replaces #606's implicit "last used" fallback (columns.__last_used__.*), which silently updated on every save regardless of which database the user actually meant to customise. Setting the default is now an explicit, deliberate action, and does not retroactively change databases that already have their own saved configuration. A quick-switch Column View dropdown has also been added to the main toolbar, next to the existing filter-profile dropdown, so a saved view can be applied to the active database with one click without opening the dialog. Unlike the filter dropdown, it resets to "(None)" after each use and on every database switch — it's a one-shot "apply" action, not a persistent per-database state indicator (there's no dynamic "follow this view" link, matching the earlier design decision that OK always locks in a static snapshot). - New ColumnView class (save/load/list_views), JSON-backed, mirroring FilterProfile in filters/engine.py - get_default_view_name()/set_default_view_name()/get_default_view() manage the global default reference - get_visible_columns(), get_column_widths(), get_container_display(), get_type_display() updated to fall back to the default view - mainwindow.py: new toolbar action + combo (_column_view_combo), _populate_column_view_combo()/_on_column_view_combo_changed(); reset on database switch (_on_database_switched) and after closing the Choose Columns dialog (_open_column_chooser) - Added 16 new translation keys across all 8 language files (reused existing filter_save_btn/filter_saved_title where identical, per test_no_globally_redundant_values) - Replaced TestLastUsedFallback with TestDefaultView in tests/unit-tests/test_column_dialog.py (8 tests) Full unit test suite: 2178 passed. mypy: no issues in 82 source files. e2e suite could not be run in this sandbox (QtWebEngine aborts at the qapp fixture here, unrelated to this change) — please run `xvfb-run pytest -v tests/e2e-tests/` locally as usual before pushing.
…603, #613, #624) #603 — Country/Region/County columns left-aligned instead of centered Fabio's #431 centered "similar short-value columns" (Placed By, dates, container, etc.) but missed Country, Region (the "state" field) and County — text values of the same kind, just not covered by that sweep. Added them to the same TextAlignmentRole list for consistency. Updated test_alignment_role to match (these three move from the "not centered" group to the "centered" group; Name/GC Code remain left-aligned, as before). #624 — Placeholder/hint text invisible in Dark theme QPalette's PlaceholderText role was never set explicitly in either _light_palette() or _dark_palette(), so Qt fell back to a derived default that turned out unreadable in dark mode (reported via Discussion #620 by @Flookfinders — Where filter, General filter, and other text boxes). Both palettes now set PlaceholderText explicitly: a mid-gray (#757575) for light, a lighter gray (#9E9E9E) for dark — legible against the Base background in both, and dimmer than full Text so it still reads as a hint rather than a value. Added TestPlaceholderText with contrast-margin assertions to test_theme.py. #613 — Where-filter SQL error box unreadable in Windows dark mode The error QPlainTextEdit in filter_dialog.py's Where tab had a hardcoded light-theme-only stylesheet (dark-red text on a "transparent" background). In dark mode that rendered as dark-red-on-dark-gray — exactly the screenshot in the report. Now picks an explicit, theme-appropriate style via the existing effective_theme() helper (already used the same way in settings_dialog.py): a brighter red on an opaque dark-tinted background for dark mode, unchanged style for light. Note: fixing this touched get_settings().theme at FilterDialog construction time, which meant the test suite's mocked SimpleNamespace settings objects needed a `theme` attribute added — done in both places in test_filter_dialog.py (the autouse `isolate` fixture and the TestDistanceUnitPref.dlg_mi fixture) so existing tests keep passing. Added TestWhereErrorBoxTheme with two new tests asserting the style actually differs (and no longer relies on "transparent") in dark mode. Full test suite: 2182 passed (4 new tests). mypy: no issues in 82 source files. e2e suite not run in this sandbox (QtWebEngine aborts at the qapp fixture here, unrelated to this change) — please run `xvfb-run pytest -v tests/e2e-tests/` locally as usual before pushing.
Ran scripts/bump_version.py 1.16.0-beta.13 (updates __init__.py and all 5 hardcoded references in site/user-guide.html atomically). Promoted the [Unreleased] CHANGELOG entries to a dated v1.16.0-beta.13 heading, covering everything merged since beta.12: - Default Column View (#607) — named, saveable Column Views with a toolbar quick-switch dropdown, replacing #606's implicit "last used" fallback - Country/Region/County columns now centered, consistent with #431 (#603) - Placeholder/hint text now legible in Dark theme (#624) - Where-filter SQL error box now readable in Windows dark mode (#613) Full test suite: 2182 passed. mypy: no issues in 82 source files. bump_version.py --check: consistent.
docs: refresh screenshots (v1.16.0-beta.13)
A beta tester on Facebook reported that columns switched correctly per
database, but the toolbar Column View quick-switch dropdown always
showed "(None)" — even right after applying a saved view, and even for
a database whose configuration matched a saved view exactly.
Root cause: the combo unconditionally reset itself to index 0 ("(None)")
after every apply and after every database switch. That was a
deliberate design choice at the time (a one-shot "apply" action, no
persistent per-database link to a view), but it meant the dropdown never
actually reflected reality.
Fix: _populate_column_view_combo() now compares the active database's
current column configuration (visible columns, widths, container/type
display) against every saved ColumnView, byte-for-byte, via the new
_current_column_view_match() helper, and selects the matching view if
one exists — otherwise "(None)", same as before. This is still a fresh
comparison computed on demand every time, not a stored "this database
follows view X" reference, so it doesn't reopen the dynamic-link design
question that was deliberately closed earlier in #607.
- _on_database_switched: repopulate (with match-detection) instead of
blindly resetting to index 0
- _on_column_view_combo_changed: after applying a view, repopulate
instead of forcing index 0 — the combo now naturally shows the
just-applied view as selected, since the configuration matches it
- New _current_column_view_match() helper on MainWindow
- Added Optional import (typing) for the new helper's return type
Added 3 new e2e tests to tests/e2e-tests/test_e2e_db_combo.py:
- combo shows the matching saved view for the active database
- combo shows "(None)" for a database with a different configuration,
and correctly re-matches when switching back
- combo reflects the view that was just applied from the toolbar
Full unit test suite: 2182 passed (unchanged — this fix is
MainWindow-level, which has no dedicated unit test file; coverage is
via e2e as usual). mypy: no issues in 82 source files. e2e suite could
not be run in this sandbox (QtWebEngine aborts at the qapp fixture here,
same known limitation as before, unrelated to this change) — please run
`xvfb-run pytest -v tests/e2e-tests/` locally as usual before pushing.
The database grid only ever separated rows vertically via alternating row colours (horizontal separation), with no visual separation between columns. This adds a thin vertical line at the right edge of every column boundary. setShowGrid() stays False, since it would also add horizontal grid lines on top of the existing alternating row colours. Instead, CacheTableView.paintEvent() is overridden: it calls the base implementation first, then draws a vertical line per column boundary onto the viewport using the theme's palette Mid colour, so it stays legible in both light and dark mode without any hardcoded colour. Lines are limited to the actual row content height, not drawn into empty space below the last row. (An earlier draft of this overrode drawRow() instead, which looked correct on paper but was never actually invoked — PySide6 doesn't expose drawRow as an overridable virtual. Verified with an instrumented offscreen render that the call count was 0. Rewritten to override paintEvent(), which is the standard, reliably-called hook for this kind of item-view decoration, and confirmed this time with pixel-level checks on an offscreen render that the lines actually appear at every column boundary, on every row.) User-configurable colours, per-user show/hide toggles, and the new Appearance settings tab proposed in #463 are deliberately out of scope for now (per Allan's comment on the issue) — basic functionality comes first. Only the vertical gridlines themselves are added here. Closes #463 (partially — colour/visibility settings remain open for a later date if still wanted).
Ran scripts/bump_version.py 1.16.0-beta.14 (updates __init__.py and all 5 hardcoded references in site/user-guide.html atomically). Adds a CHANGELOG entry for the vertical gridlines fix (#463) that was already committed on top of beta.13.
docs: refresh screenshots (v1.16.0-beta.14)
Bundles the #656 investigation's fixes into a beta release so testers without the source checkout can try it: - GPX/GGZ export was missing attributes, short/long description, state, and full log history (hardcoded to last 5 logs, 500-char text cap). All now exported in full, matching GC.com/GSAK. - Root cause of Garmin firmware not recognizing exported files as geocaches at all: switched export from GPX 1.1 (groundspeak:cache wrapped in <extensions>) to GPX 1.0 with groundspeak:cache as a direct child of <wpt>, matching GSAK's exact convention. Confirmed on a GPSMAP 64s: description, logs and hint now all display correctly, where previously only the hint displayed. Version bumped via scripts/bump_version.py (1.16.0-beta.14 -> 1.16.0-beta.15); --check confirms __init__.py and all 5 references in site/user-guide.html are consistent. CHANGELOG.md updated with a full entry under the new version heading. Related: #453, #454, #455, #502 (Send to GPS issue cluster)
docs: refresh screenshots (v1.16.0-beta.15)
…w-up) Community suggestion on issue #656: GSAK has a toggle that uses the active database's name as the default export filename instead of a fixed default, which avoids collisions when switching between multiple databases without having to manually rename each time. Added a new checkbox "Use database name as filename" to the GPS export dialog, checked by default (Allan's decision), applying to both file-mode export and Send to GPS (device-mode) — same toggle covers both, per Allan's decision. Behaviour: - Checked by default: on dialog open, if a database is currently active (get_db_manager().active), the filename field is pre-filled with that database's name (sanitized for filesystem safety) instead of the previous fixed "opensak" default. - Falls back to "opensak" if no active database is available. - Unchecking the box does NOT clear or reset the current filename — it only stops the auto-fill going forward, so a manual edit isn't clobbered. - Re-checking it re-fills from the currently active database's name. - Works alongside the filename-collision handling added in the previous commit: if the resulting filename still collides with an existing file (e.g. two databases with the same name, or re-exporting the same database twice), the existing rename-prompt / delete-checkbox flow still applies as before. New helper: _sanitize_db_name_for_filename() strips/replaces characters that are invalid in filenames on Windows/Linux/macOS (\ / : * ? " < > |) and trims surrounding whitespace/dots; falls back to "opensak" only for a truly empty result. New translation key gps_use_db_name_cb added to all 8 language files. Tests: - Added TestUseDatabaseNameCheckbox (5 tests): checked by default, autofill from active database, fallback to "opensak" with no active database, unchecking doesn't clear filename, re-checking re-fills. - Added TestSanitizeDbNameForFilename (5 tests) covering invalid-char replacement, normal names, whitespace/dot trimming, an all-invalid name (becomes underscores, not a fallback), and empty-string fallback. - Updated test_device_mode_prompts_on_collision to explicitly disable the new checkbox and set a deterministic filename, since it tests unrelated collision logic and would otherwise pick up the (now default-on) database-name autofill. - Full suite: 2217 unit tests passed, 258 e2e tests passed. - mypy: no issues. Related: #453, #454, #455, #502 (Send to GPS issue cluster)
Custom Waypoints (Hotel/POI, Parking Area, Trailhead, Stage, Final Location, Reference Point, Waypoint, Custom — issue #141) are stored as Cache rows for simplicity, but they aren't real geocaches. Exporting them wrapped in a full groundspeak:cache block made them show up on Garmin devices as a "fake geocache" with empty D/T stars and Size: (Not Chosen). Confirmed fixed on a GPSMAP 64s via GPX import: Hotel/POI and Parking Area waypoints now come in as plain waypoints with the correct native icon, instead of looking like empty geocaches. Adventure Lab stages (cache_type == "Lab Cache") keep their full groundspeak:cache content as before (description, D/T, hint all display correctly, confirmed earlier on GPSMAP 64s) — the intent was to also give them a distinct icon ("Flag, Blue") so they're visually distinguishable from regular geocaches. Tested on-device (GPSMAP 64s, both GPX and GGZ): the Lab Cache icon change had NO visible effect — it still displays with the standard geocache icon. Working theory: once groundspeak:cache is present, the device's dedicated geocache display module takes over icon selection based on groundspeak:type (or just always shows the standard geocache icon for anything in that module), ignoring the GPX <sym> field entirely — unlike plain waypoints (no groundspeak:cache), where <sym> clearly does drive the icon, as shown by the Custom Waypoint fix above working correctly. Decision: keep the Lab Cache <sym> change in place anyway (Allan, 2026-07-28) — it's harmless, costs nothing, and may help on other device models/firmware versions even though it had no effect on the GPSMAP 64s tested. Getting Lab stages to show a different icon while keeping full geocache-style content is not achievable without further investigation (would very likely require dropping groundspeak:cache entirely, at the cost of losing description/D-T/hint display, which is not considered a worthwhile trade-off) — not pursuing further for now. Changes to generate_gpx() (applies to GGZ too, since it embeds a generated GPX internally): - For CUSTOM_WP_TYPES cache_type values: skip the groundspeak:cache block entirely, export as a plain GPX waypoint (name/desc/url/sym/ type only), with <type> set to the plain type name (no misleading "Geocache|" prefix). - New _custom_wp_symbol() maps each CUSTOM_WP_TYPES value to a Garmin built-in icon symbol name: Parking Area -> "Parking Area", Trailhead -> "Trail Head", Hotel/POI -> "Lodging", Reference Point -> "Flag, Green", Stage -> "Flag, Blue", Final Location -> "Flag, Red", Waypoint/Custom -> "Waypoint" (also the fallback for anything unmapped). - _cache_symbol() now maps "Lab Cache" -> "Flag, Blue" instead of falling through to the generic "Geocache" icon (kept per above, even though it had no visible effect on the tested device/firmware). Not in scope (per earlier discussion): generating proper Garmin custom POI (.gpi) database files for these categories remains a separate, bigger effort (OpenSAK still doesn't generate .gpi files at all, unlike GSAK's Parking Area/Reference Point/Trailhead .gpi exports). Tests: - 9 new tests on generate_gpx() covering: custom waypoints have no groundspeak:cache block, still carry name/desc, correct symbol per type (Parking Area, Hotel/POI, Trailhead), fallback symbol for unmapped types, plain (non-prefixed) <type> element, a sanity check that regular geocaches are unaffected, and Lab Cache keeping full content with just a different <sym> value in the generated XML (even though this had no visible on-device effect for Lab Cache). - 10 new direct unit tests for _custom_wp_symbol() (one per CUSTOM_WP_TYPES entry plus fallback/empty-string cases). - 1 new test on _cache_symbol() confirming Lab Cache gets a distinct symbol value from Traditional Cache in the generated XML. - Full suite: 2237 unit tests passed, 258 e2e tests passed. - mypy: no issues.
…oint icons Bundles the recent #656 follow-up work and #660 into a beta release: - Send to GPS (device-mode) now runs the same filename-collision check as file-mode export, following CheminerWill's report that beta.15 still silently overwrote same-named files on the device. The "delete old files before upload" checkbox now also works for GGZ (previously GPX-only). - New "Use database name as filename" checkbox (community suggestion, GSAK has an equivalent), checked by default, for both file-mode and device-mode exports. - Custom Waypoints (Hotel/POI, Parking Area, Trailhead, etc.) now export as plain GPX waypoints with proper native Garmin icons instead of showing up as empty "fake geocaches". Confirmed fixed on a GPSMAP 64s via GPX import. - Adventure Lab stages given a distinct icon attempt (no visible effect on the tested device, but harmless and kept in place) — full description/D-T/hint content for Lab stages is unaffected either way. Version bumped via scripts/bump_version.py (1.16.0-beta.15 -> 1.16.0-beta.16); --check confirms __init__.py and all 5 references in site/user-guide.html are consistent. CHANGELOG.md updated with a full entry under the new version heading. Related: #453, #454, #455, #502, #660
docs: refresh screenshots (v1.16.0-beta.16)
CheminerWill's follow-up suggestion after testing beta.16: the "use database name as filename" checkbox always reset to checked on every export, but some workflows (frequently exporting named filtered subsets rather than the whole database) want it to stay unchecked once turned off, rather than fighting the auto-fill every time. The checkbox state is now persisted via the existing settings_store (same JSON-based mechanism used elsewhere, e.g. column_dialog.py) under the key "gps.use_db_name_as_filename", and restored the next time the GPS export dialog is opened. Defaults to checked (True) on first-ever use, when nothing has been saved yet, per Allan's original decision. Toggling the checkbox in either direction writes the new state immediately. The existing autofill-on-check behaviour (fills the filename field with the active database's name, sanitized) and non-destructive uncheck-doesn't-clear-filename behaviour are both unchanged. Tests: - Added 4 new tests to TestUseDatabaseNameCheckbox: unchecked state persists to a newly-opened dialog, checked state persists likewise, first-ever run (no stored value) defaults to checked, and toggling writes to the settings store immediately in both directions. - Relies on the existing autouse isolate_settings_store fixture in conftest.py, which gives every unit test a fresh in-memory settings store — no risk of cross-test leakage or touching real user config. - Full suite: 2241 unit tests passed, 258 e2e tests passed. - mypy: no issues. Related: #656
CheminerWill reported that newly created Custom Waypoints showed no distance from the center/home point and sorted to the bottom of the list (as if distance were unset), even though coordinates were entered correctly. Workaround noted in the issue: switching the center/home point away and back made the distance appear. Root cause: Cache.distance/bearing are precomputed, stored columns (not calculated on the fly at display time) — the cache table model just reads whatever value is already in the DB. recalculate_distances() is the function that actually computes and persists them, and it's called after import and after switching the center/home point, but _add_waypoint() never called it after inserting a newly created cache, leaving distance/bearing as their default None. Switching center point happened to "fix" it only because that action triggers a full recalculate_distances() pass over every cache in the database, including the new one. Fixed in two places (same root cause, same fix): - _add_waypoint(): recalculate_distances() is now called right after the new cache is added, using the same guarded pattern already used in _refresh_after_import() (only if a home point is set). - _edit_waypoint_from_cache(): had the identical issue — editing a cache's coordinates left its stored distance/bearing stale (pointing at the old location) until the center point was switched. Fixed the same way. recalculate_distances() does a full-table batch SQL update (not a per-row round trip), so calling it after a single add/edit is still a single fast query, not a performance concern. Tests: - test_add_waypoint_calculates_distance_immediately: confirms a newly added cache has non-None distance/bearing right after _add_waypoint(), without any extra user action. - test_edit_waypoint_recalculates_distance_after_coordinate_change: edits an existing cache's coordinates to a location far from the default home point (Sydney vs. Copenhagen) and confirms the stored distance matches a fresh distance_km() calculation, and differs from the pre-edit value. - Full suite: 2241 unit tests passed, 260 e2e tests passed (2 new). - mypy: no issues.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.