- Date pickers (entry form + edit dialog) now display TT.MM.JJJJ instead of
ISO (DATE_DISPLAY_FORMAT). Storage stays YYYY-MM-DD; parse_date() already
accepted both formats, so existing data and the self-updater are unaffected.
- New optional "Straße" field (street + house number) in the entry form and
edit dialog, backed by a new `street` CSV column. geocode_city() and
GeocoderWorker.enqueue() gained a street parameter: when set, a full-address
query is tried first for a much more precise map point, falling back
automatically to the existing city/PLZ search if it doesn't resolve.
- Tab 2 and the entry queue show a Straße column; Tab 2 search now also
matches on street.
- Fix: pandas turns a blank CSV cell into NaN even for a dtype=str column, so
every existing (blank-street) row would have shown literal "nan" in Tab 2.
DataStore._load now does street.fillna("") after every read.
Verified with a non-GUI test suite (date parsing, query construction, CSV
round-trip incl. the NaN case) and a full GUI build/drive test on Python
3.12/Tk 9. Docs updated (changelog, overview, architecture, data-model,
dev-notes, improvements).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
8.1 KiB
Changelog
Notable changes to the app. Newest first.
2026-09-12 — German date display + optional street address for geocoding
- Date fields now display
TT.MM.JJJJ(e.g.12.09.2026) instead of ISO, in both the entry form and the edit dialog (DATE_DISPLAY_FORMAT). Storage on disk is unchanged (YYYY-MM-DD) —parse_date()still accepts either format when typed, so nothing about existing data changes. - New optional "Straße" field (street + house number) on the entry form and
in the edit dialog, and a new
streetCSV column. When set, geocoding tries the full address first for a much more precise map point, falling back to the existing city/PLZ search if the address doesn't resolve — see overview.md.geocode_city()andGeocoderWorker.enqueue()both gained astreetparameter. - Tab 2 and the entry queue both show a Straße column; the Tab 2 search box now also matches on street.
- Fixed a bug this surfaced immediately: pandas turns a blank CSV cell into
NaN, even for a column forced todtype=str— every pre-existing row (all blank onstreet) would have displayed the literal textnan.DataStore._loadnow doesself.df["street"] = self.df["street"].fillna(""). See dev-notes.md. find_duplicatesintentionally still ignoresstreet(unchanged: date + city- PLZ only).
2026-09-07 — fix: right-click context menu instantly triggered its first item
On Linux the Tab 2 (and queue) right-click menu flashed and immediately ran
"Bearbeiten" / "Löschen", so entries couldn't be deleted. Cause: the menu was
bound to <Button-3> (press) and finally: menu.grab_release() dropped the
grab, so the following <ButtonRelease-3> selected the item under the cursor.
Fix: bind <ButtonRelease-3> (<ButtonRelease-2> on macOS), build each menu
once, and drop the premature grab_release().
2026-09-07 — map tiles → Esri (OSM 403s local files)
The switch to tiles="OpenStreetMap" worked on the dev machine but the target
laptop's browser got HTTP 403 "referer is required by tile usage policy" —
OSM's CDN blocks refererless requests, and a karte.html opened as file://
sends no Referer. Switched to Esri "World Light Gray" (base + labels
overlay, server.arcgisonline.com): no key, no Referer check, muted look
similar to the old positron. Constants MAP_TILES / MAP_TILES_LABELS /
MAP_TILES_ATTR.
2026-09-07 — install split for non-admin users
The target account has no sudo, so install is two scripts:
install-system.sh– admin runs once:apt install python3-tk python3-venv git.install.sh– user runs, no sudo: checks the system packages, creates.venv+ installsrequirements.txt, writes the.desktopmenu entry. If a package is missing and the account can't sudo, it prints the exact admin command and stops.
2026-09-07 — one-command install + launcher
install.sh– Linux Mint setup:.venv+requirements.txt, and a.desktopmenu entry with correct absolute paths.run.sh– launches the app from.venv; the menu entry calls this.icon.png– bundled red-cross launcher/window icon (256×256); the app now prefers this over the runtime-drawn one.requirements.txt– fully pinned (direct + transitive), tested on Python 3.12.numpycapped at 2.2.6 so it still installs on Python 3.10.
2026-09-07 — built-in self-update
New Hilfe menu:
- Nach Update suchen –
git fetch+ count of new commits on the server. - Version… – shows the installed commit (
<hash> · <date>).
On start, a quiet background check runs; if updates exist the status bar says so and the menu item becomes "Update installieren (N verfügbar)".
Installing runs git merge --ff-only (fast-forward only – never an automatic
merge), re-runs pip install -r requirements.txt if that file changed, then
restarts the app via os.execv. User data (data/) is git-ignored and
untouched. If the local checkout has diverged or the network is down, it shows a
clear message and does nothing.
Only active when the app runs from a git clone with git installed;
otherwise the menu just shows "Version: unbekannt". New Updater class,
app.py.
2026-09-07 — map tiles switched to OpenStreetMap
folium.Map(tiles="CartoDB positron") began showing an "API KEY REQUIRED"
watermark (Carto moved its basemaps behind a key). Switched to
tiles="OpenStreetMap" via a new MAP_TILES constant — no key required. OSM
standard tiles are more colourful than positron was; MAP_TILES makes swapping
the provider a one-line change.
2026-09-07 — UI/UX pass
A round of usability improvements aimed at the non-technical user (see improvements.md).
- Larger UI font (
UI_FONT_SIZE = 11) applied to all default fonts, menus, dialogs and the Treeview (taller rows). - DRK-red header bar with the app name; window title shows the total count
("… · 142 Einsätze"); simple red-cross window icon drawn at runtime (also
written to
data/icon.pngfor the launcher). - Status bar is now colour-coded by severity (grey/green/orange/red), and transient messages auto-clear after 8 s back to a neutral state; queue-count messages stay put.
- Tab 1: more spacing in the form; PLZ field accepts digits only; "+ Hinzufügen" is a solid button; explicit "Auswahl entfernen" button and Delete key for queue rows; "Warteschlange leeren" now asks for confirmation; duplicate save shows a modal (list + "trotzdem speichern?") instead of a transient hint.
- Tab 2: the raw
lat/loncolumns are replaced by a single "Karte" column (✓/ redfehlt); active sort column shows a ▲/▼ arrow; the hint line always shows the saved-entry count. - "Karte öffnen" with no coordinates now shows a dialog, not just a status line.
- Window size & position are remembered between sessions
(
data/window.json).
2026-09-07 — data safety, robustness, easier input
Addressed the top three findings from improvements.md.
Data safety (DataStore)
- All writes (append / update / delete) now rebuild the full DataFrame and go
through
_save_csv: rotating backup todata/backups/(startup + before every change, keep 20, skip if unchanged) then atomic write (tmp+fsync+os.replace). orte.csvmissing / empty (EmptyDataError) / unreadable now falls back to an empty table or the newest backup instead of crashing.
Geocoder robustness (GeocoderWorker, geocode_city)
- Each queue item runs inside
try/except; a failing lookup or callback logs a traceback and the worker keeps going (previously an unexpected error killed the thread and silently froze all further geocoding). geocode_cityraisesGeocodingUnavailablewhen every query failed on a service/network error. After 3 in a row the app shows a one-time "Standortdienst nicht erreichbar" dialog; entries still save without coordinates.
Easier, safer input
- Date fields (entry form + edit dialog) are now
ttkbootstrap.DateEntrycalendar pickers, validated/normalized to ISO byparse_date()(also acceptsTT.MM.JJJJ). Invalid dates are rejected with a dialog. - Edit dialog has manual Breitengrad / Längengrad fields for fixing coordinates by hand.
- Tab 2: rows without coordinates shown in red, "Nur ohne Koordinaten" filter, count in the hint line, right-click Koordinaten suchen.
Housekeeping
git init+.gitignore.- Rotating log file at
data/app.log(_setup_logging). - Shared helpers
filter_locations/split_city_plz/parse_coordreplace duplicated combobox code. - Config constants:
GEOCODE_REGIONS,MAP_DEFAULT_CENTER,MAP_DEFAULT_ZOOM,MAX_BACKUPS. generate_mapfits the view to the markers.
Verification
Non-GUI smoke tests (helpers, DataStore backup/atomic/recovery, geocoder
resilience) pass. The GUI now can be built and driven on the dev Mac via a
Homebrew Python with Tk 9 — see dev-notes.md.