mirror of
https://github.com/praktimarc/kst4contest.git
synced 2026-10-19 13:53:01 +02:00
* Make DBController work on one database file per instance The controller was a static singleton: an eagerly created static instance opened the root database during class initialization, and both the connection and the path were static fields. A second operator profile in the same process was therefore impossible, and ChatController's own "new DBController()" never opened anything - it silently adopted the eagerly opened root connection. - drop the eager static instance in favour of a lazily created default instance - turn connection and path into instance state - add a constructor taking a database file name relative to the application directory plus a flag whether a missing file is seeded from the bundled template - create additional profile databases empty instead of seeding them: the bundled template carries 3452 foreign callsigns and user_version 0, which would show a new operator foreign data and trigger the full callsign normalization rebuild. The schema is created by the existing table setup. - remember the shutdown hook so closeDBConnection can deregister it; otherwise every profile switch would leave another hook holding a dead connection All SQL statements keep referencing the plain field and are unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hpa6bjie5qkeNG62y6FmXm * Allow preferences and chat controller to be bound to a file set ChatPreferences gains a constructor taking a preferences file name relative to the application directory, so "profiles/OP2/preferences.xml" is as valid as the historic flat "preferences.xml". A missing file is still seeded from the bundled template, which gives an additional operator the same clean defaults a first installation gets. ChatController gains a constructor that passes both relative file names and the seed flag through to ChatPreferences and DBController. The existing constructors delegate to the historic file names, so nothing changes yet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hpa6bjie5qkeNG62y6FmXm * Introduce the operator profile model and its registry Adds the descriptor, the path derivation and the registry persistence for operator profiles. Nothing calls them yet, so behaviour is unchanged. The descriptor stores only a shared/own flag, never a path. All file names are derived in OperatorProfilePaths, so a stored path can never drift apart from the flag that produced it. A profile identifier is a stable, file system safe slug assigned once, so renaming a profile never moves a directory. The registry is created lazily. An installation that only has the historic flat layout gets no registry file and no profiles directory; the root profile is synthesised in memory instead. That keeps a single operator installation byte for byte the one it was before, and it keeps a downgrade to an older release a no-op. A missing, unreadable or malformed registry is logged and treated like an installation without additional profiles, never as an error. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hpa6bjie5qkeNG62y6FmXm * Select the operator profile at startup Resolves the active operator profile before the chat controller is built and passes its two file names on, so preferences, layout and worked data follow the profile. The resolution is deliberately quiet for existing installations. With no registry or exactly one profile nothing is asked and nothing is written, so a single operator start is unchanged. Only from two profiles on does a small picker appear with the last used profile preselected, where Enter or a double click starts immediately. A "--profile" argument, or the equivalent system property, skips the picker; an unknown name warns and falls back to the normal selection instead of refusing to start. The startup decision itself lives in OperatorProfileBootstrap and contains no user interface code, so it is covered by headless tests. The window title gains the profile name only when a second profile exists. Command line parsing happens in init() and is kept in a process wide holder, because JavaFX only knows the parameters of the instance it launched itself. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hpa6bjie5qkeNG62y6FmXm * Release the background resources a discarded runtime owns Several resources outlived a disconnect on purpose, which was harmless while a process ran exactly one session for its whole life. They are now released when the controller itself is closed: - the ON4KST connection supervisor thread, which stopByUser did not touch - the sked reminder scheduler, which had no shutdown at all - the reachability executor, whose shutdown method existed but was never called - the PSTRotator retry scheduler and its pending retry - the map tile proxy, whose stop method existed but was never called, leaving a server socket and a twelve thread pool behind - the station map bridge listeners and its coalescing animation, which would otherwise keep firing into a dead user interface These are real leaks today; they only become visible when a second runtime is built in the same process. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hpa6bjie5qkeNG62y6FmXm * Switch the operator profile while the application is running Splits the teardown out of stop() into a reusable, idempotent shutdownRuntime() and adds File - Switch operator profile..., which tears the current runtime down and builds a fresh one for the selected profile. The new runtime is a new application instance rather than a second start() on the existing one. Many controls are instance fields created once, so reusing the instance would re-parent mounted nodes and register every listener twice. A fresh instance is safe because the class keeps no mutable static state. Closing every window during a switch would end the process under the JavaFX default, so the application takes over the exit decision: implicit exit is turned off, the main window gets an explicit close handler, and every exit path runs through the launcher. That also fixes losing the window layout on exit after a switch, because JavaFX only calls stop() on the instance it launched. The two view timers are now cancelled null-safe; stop() used to dereference them unguarded, which would fail if shutdown happened before they were created. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hpa6bjie5qkeNG62y6FmXm * Manage operator profiles from the settings window Adds a "Profiles" tab, appended last so no established tab position shifts, offering create, duplicate, rename, delete, a switch between shared and own worked stations, and activation of another profile. Duplicating copies the whole configuration except callsign and password. The antenna, locator, layout and integration settings are exactly the work nobody wants to enter twice, while the credentials belong to one operator only. The root profile can neither be deleted nor moved off the common station database, because its files are the installation itself. The login callsign and its raw form now default to empty instead of a real callsign. The XML reader treats an empty element as "not set" and falls back to the field default, so without this change a profile created without credentials would come up carrying the callsign compiled into the defaults - and an operator could transmit under someone else's call. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hpa6bjie5qkeNG62y6FmXm * Document operator profiles Adds a manual section in both languages covering where profile files live, the choice between shared and own worked stations, managing profiles, the startup selection and the --profile argument, switching while running, and the fact that passwords stay in clear text so profiles are not an access boundary. Records the architecture in PROJECT_CONTEXT: lazy registry, derived paths, why an additional profile database is created empty, why the login callsign default is empty, and the constraints of rebuilding the runtime for a switch. Adds a v1.50 changelog entry in both languages including the upgrade notes: no file is moved, and going back to an older release stays possible. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hpa6bjie5qkeNG62y6FmXm * Make the terrain profile cache multi operator safe The cache stored a single owner identity in a meta table and dropped the whole TerrainProfileCache table whenever the configured callsign or locator differed from it. With several operator profiles that turns the cache into a permanent miss: every switch between two operators with different locators would discard every computed profile. Entries are separated by owner identity through the primary key already, so the wipe is replaced by an owner table that simply records which identities are in use. A different owner now misses the cache instead of clearing everybody's. The cache also moves out of the worked station database into its own global terrainprofilecache.db. Terrain profiles are pure geometry derived from two locators and a sample count; at a multi operator station both operators share one location, so a per profile copy would only double the traffic against the terrain service. No migration is needed, the new file refills itself, and the old tables stay readable for older releases. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hpa6bjie5qkeNG62y6FmXm * Fail cleanly when the registry path has no directory SpotBugs flagged a null passed to Files.createTempFile: the null check guarded only createDirectories, while the temporary file creation would still have dereferenced it. The path is resolved absolute so this is practically unreachable, but bailing out with a log line is cheaper than the latent NPE. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hpa6bjie5qkeNG62y6FmXm * Code Version 1.50 * Add the in-app update concept for 1.50 Captures the agreed design so it can be handed over later: extended update feed with per-artifact metadata, a build-time package-type marker, a testable check service replacing the blocking call in the ChatController constructor, a non-modal hint suppressed while connected to ON4KST, verified downloads and platform-specific execution. Concept only, nothing implemented yet. Line anchors were verified against this branch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HT8R7zTMoQnmJj6dGbaqqf * Use one base font size and a per-profile startup design JavaFX picks a 13px default font on macOS and Linux but 12px on Windows, so labels in fixed-size controls were cut off outside Windows. Both stylesheets now set 12px on the root. Each operator profile now chooses light or dark mode for startup on the GUI settings tab. The Windows menu entries remain a quick switch for the running session. All windows, including the update window and the top candidates list, follow the design, and the main window no longer starts light while the station map starts dark. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Show a drag-to-install layout in the macOS DMG The DMG window now has a background with an arrow from the app to the Applications folder, in the KST4Contest colours. Finder applies the layout through AppleScript; if that fails, e.g. on a headless runner, the script warns and builds the plain DMG as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Use the macOS system menu bar in all windows On macOS the main menus move into the system menu bar and are shared with the secondary windows, so they stay available whichever window has the focus. The connection state indicator becomes a read-only LINK menu there instead of the status bar button. Other platforms are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * List direct commits on main in the release notes GitHub's generated release notes only cover merged pull requests, so commits pushed straight to main were missing. The release job now builds the notes itself: "What's Changed" holds "Commits on main" (first-parent, without bot and squash-merge commits) and GitHub's PR list as "Merged PRs". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Build with Gradle in two modules, and free core of JavaFX Etappen 1 and 2 of the Compose migration (43 commits). The Maven build, the single source tree and the JPMS module-info went together. core now holds the domain and app-desktop the user interface, both built by Gradle, packaged through jpackage from Gradle, with SpotBugs and PMD wired in. JavaFX moves to the classpath, which is why the launcher is Main and not the Application subclass. The PR check, the nightly artifacts, the release and the AUR packages all build from Gradle; the macOS DMG points at its output. Verified on Linux, macOS and Windows. core then loses JavaFX entirely. It observes through kst4contest.observe -- ObservableValue, ObservableRoster, and UiDispatcher as the one boundary a worker thread crosses to touch the interface. The controller collections become rosters and the visible station list a pure derivation rather than a FilteredList/SortedList chain, which is also what fixed two focus defects only a load test had exposed: the keyboard focus stays where the operator put it, and the send field keeps it after a row click. The rule that outlives this commit: ObservableRoster is the store and the list a view is bound to is a mirror of it, never the other way round. * Draw the whole interface in Compose Etappen 3 to 6a of the migration (129 commits). Every window the operator sees is Compose; the JavaFX ones still exist beside them so the two could be compared against a live session, which is the only way the differences came to light. The toolchain first, then the settings window with its eleven tabs and 72 real preferences; then the multi-column table as a component, and with it the rules it needs -- stable row identity, a selection that survives a refresh, column order the operator can drag, and a repaint when the rows change rather than when the list instance does. Then the update and monitor windows, and the main window: 22 station columns, the filter bar, the selected-station panel, the message tabs, the priority bar, the sked controls, the status indicators and the timeline, assembled behind a splitter because Compose has none. The map stops being a WebView. A Compose canvas projects WebMercator tiles itself, with the clustering in core and an asynchronous fetcher in place of the local tile proxy; derive() becomes a pure Kotlin reimplementation instead of a reflection call into com.sun.javafx. Most of the volume here is parity the operator would notice rather than new behaviour: desktop density instead of Material's phone minimums, colours taken from the JavaFX stylesheets instead of Material's palette, row dividers, band columns, grid-square labels and their colours, the home marker and antenna beam, pinch-to-zoom under Wayland, and layouts that survive a window narrower than the chart they stack. Two lessons are worth more than the diff. A control bound to a value Compose cannot observe writes through and never redraws -- that one shipped repeatedly with a green build, because no test drew anything. And a layout that clips instead of wrapping is worse than one that is merely too narrow: half a word is the worst available outcome. * Remove JavaFX The second half of Etappe 6 (61 commits). grep -rl "javafx\." over both main source trees is empty, nothing imports javafx, neither classpath resolves it, and org.openjfx is out of the build and the version catalog. The finding that shaped the work: the JavaFX main window was built on every start and never shown -- primaryStage's setScene and show were both commented out. Most of those 11,655 lines were dead weight rather than a port. But not all of them, and that is the trap this commit is really about: dead-looking methods still fed live Compose sinks. They were cut at their seams instead of deleted, and a sweep script that follows calls was written to find them, because reading the code does not reveal them. In order: the colour derivation frozen as checked-in test data, so the pin survives JavaFX being removed instead of silently comparing against itself; the live feeds lifted out of the never-shown window and given names and tests; the dead scaffolding deleted in slices; then the lifecycle. UiDispatcher now delivers to the AWT event dispatch thread, the ten Alerts are modal Compose dialogs, HostServices gives way to java.awt.Desktop with the mailto/http split JavaFX did not need, and extends Application, start(Stage), stop and launch are gone -- main builds the runtime and a shutdown hook replaces stop(). An independent review found two deadlocks in that move, both the same failure class, both invisible to the build: a blocking wait on the event thread for work that can only advance on the event thread. The profile picker waited on a latch and froze the client for good; ComposeWindowHost.close waited on Thread.join and returned with the window still marked open, which made a profile switch raise the dead runtime's window and leave the rebuilt profile without its Connect button. A third came out of fixing them: a ComposeDialog built off the event thread cannot create its GL context and never paints. Three defects only a GUI run showed, never the build: an NPE on a deleted field, a Compose menu still hanging on deleted MenuItems, and a category bookkeeping field that looked dead but is read by the outgoing-message category resolution -- deleting it would have sent messages in the wrong category. The binding docs and the manual no longer describe a JavaFX client. * Draw the menu bar in Compose, and give the drawing layer a net What the removal left open (4 commits). Compose's MenuBar is a javax.swing.JMenuBar set on the window, so Swing draws it and no theme reaches it; with no look-and-feel configured that meant the default Metal menu above a themed window. The bar is drawn in the window now, except on macOS, where the system bar is where that platform expects it. Two renderers read one description -- mainMenuModel is a plain function of the state, which also gives the menus their first tests. Closing the main window quits the application again, and the window writes its size back to the profile; both had quietly stopped working when the last JavaFX stage went. Then Etappe 7. Four faults shipped in the settings-window branch alongside a green suite of 382 tests, because not one of those tests drew anything: a control that never redrew, a tab strip that clipped mid-word, a form taller than its window with no way down, and colours that came from Material rather than the stylesheet. One regression test per class, and the spec's acceptance criterion is met rather than assumed -- each fault was put back deliberately and the matching test watched to fail. The CI had never run the suite at all; it does now, headless. What that took was not Xvfb: skiko's native library links against libGL and only has to be loadable, since the drawing tests render in software. Without the package the whole Compose half of the suite dies with a message that reads like a missing display. Found by running the job under act rather than on GitHub. The six tests that open a real window skip headless by their own guard. The summary step counts from the result XML and fails on failures there, because this project's rule is never to infer a green suite from an exit code. * Make the colours adjustable per operator profile Six colour roles per design, per profile: surface, window surface, field interior, text, accent and separator line. A change applies at once in every open window and survives a restart once the settings are saved, like any other preference. Three sources, later wins role by role: the shipped stylesheet from the classpath, then the profile's own stylesheet file if there is one, then the overrides stored in the profile's preferences. resolvePalette is a pure function and reports where every role's colour came from, which the tab shows per field -- with two sources able to decide one colour, that is the only thing keeping "why is this colour what it is" answerable, and the spec calls it mandatory rather than decorative. Four things this had to get right, each learned the hard way and each pinned: A role is a selector and a property, not a property alone. Three of the six are stated outside .root -- text on .label, the separator on .separator *.line -- and -fx-background-color alone appears a dozen times in the evening sheet. Measured: the shipped daylight sheet states no colour at all, the evening sheet states five and implies the sixth. Kst4ContestTheme reads the palette from the store's state and not from remember. That read is what makes a change repaint every open window; remember(darkMode) held the palette until somebody toggled day/evening, so a change reached nothing. A derived colour follows its source's value, never its provenance. The root profile's own stylesheet is the one copyResourceIfRequired writes at every startup -- the shipped sheet itself -- so layer 2 declares the accent on every existing installation with nobody having chosen anything. Keying textAccent on "does this come from a file" repainted the evening accent from green to blue on upgrade and made "reset to shipped" disagree with "discard my changes". The contrast guard measures where colours are actually drawn, read off Theme.kt's Material mapping rather than off the role names: background and surface are both the window surface, and primary is textAccent, not accent. It reports a pair only when it is both under WCAG AA and worse than the shipped sheet -- the shipped sheets have three pairs under 4.5 themselves, so an absolute floor would warn on an untouched client and teach the operator to ignore warnings. The way back out of an unreadable palette is deliberately overbuilt, because it is the one failure that locks itself in. "Reset to the shipped colours" takes the shipped palette as a required parameter and reads no composition local, so there is no path by which it could be drawn in the colours it exists to undo; it looks out of place under a customised palette, and that is what makes it findable. Ctrl+Z, Ctrl+D and Ctrl+R reach the three ways back even with the caret in a colour field. A mistyped colour is refused and the field snaps back. The profile's stylesheet is the hand-editing route the copy under ~/.praktiKST has been promising since it was first written and never read. It is read now. A button writes the shipped template as a starting point and never replaces a file that is already there. An unreadable, truncated or non-CSS file does not prevent startup -- the role falls back to the shipped design. A sheet stating -fx-base and no -fx-background states the derived window surface too, the way JavaFX does, or the most natural hand edit would leave every window the shipped light grey. 101 new tests. All of it runs headless. * Document the adjustable colours, and record the design and the plan Both manuals get the Colours tab in full: the six roles, that a change applies at once but survives a restart only after Save settings, the three ways back with their keyboard shortcuts, what each provenance label means, and the readability notice that warns without refusing. Two things an operator would otherwise have to discover. The reset button is always drawn in the shipped colours and works when nothing else can be read -- the risk section of the design says plainly that a keyboard path only helps whoever knows it, so the manual is where this has to be written down. And the root profile already has both stylesheet files, because KST4Contest has been writing them at startup for years, so most of its roles report "from file" rather than "shipped" with identical values. PROJECT_CONTEXT.md records the decisions that outlive this stage: the three sources and their precedence, that a role is a selector and a property, that the theme must read the store's state rather than remember, where the contrast pairs come from, why the root profile's file layer always exists, and why the lifeline refuses the active palette. Also corrects its claim that CSS stays global -- a profile now owns its stylesheets. The design document and the implementation plan are kept as they were written, including the plan's own corrections where measuring the code contradicted it. * Speak the operator's language The interface is German or English, chosen per operator profile on the GUI tab, in force at once in every open window, and remembered across restarts. 376 texts in both languages. The texts are ordinary .properties files that nobody has to compile: a contributor copies the English one, translates the values, and opens a pull request. A third module -- build tooling that never ships -- turns them into Kotlin before anything compiles, which is what makes a mistyped key and a wrong argument count compile errors rather than things an operator discovers. It lives in the main build rather than buildSrc because buildSrc's tests do not run on `./gradlew build`, measured, and a generator whose tests never run is the exact failure it exists to prevent. Incompleteness is allowed and incorrectness is not. A missing key warns and falls back to English, so a partial contributed language can be submitted at all; an orphan key, a placeholder the translation drops, a duplicate key or an unreadable file fail the build with the generator's own message naming the file. The argument count always comes from the English base. German is held complete by a test because it ships; a contributed language is not. What is deliberately not translated is the harder half. Protocol frames and chat commands would break the connection or go unread; the beacon texts, auto answers, snippets and shortcuts go to other radio amateurs and sit in every operator's stored profile; the 273 println calls in core are diagnostics, and a German stack trace is worse for whoever reads the bug report; and QRA, QRG, QTF, LOS, Fresnel and wkd read the same in either language. Three tests guard the boundary by measuring behaviour rather than text: the protocol frames built under three locales, every preference default compared by reflection, and no translation value being a protocol command. The reflective one is the only one that covers what nobody thought of. One insight turned up three times. Anything built outside a composition freezes the language it was built in: the window title, the settings tab strip and every column header are all constructed once at startup -- the columns from Java -- so each now holds a function read when it is drawn. That also fixed something older and unrelated to language: the main window's title was a fixed "KST4Contest (Compose)" for the whole session, where the JavaFX window had carried the live connection line. It carries it again. A column's id is never translated. It is what the remembered widths and order are keyed on. * Document the two languages, and how to contribute a third Both manuals get the language picker in full: where it sits, that it applies per profile and takes effect at once in every open window, and -- at more length -- what is deliberately left alone and why. An operator who sees an English beacon text in a German client should be able to read that it is meant that way. The contribution route is written down in both, because plain text files are only useful if somebody knows they are there: copy, translate, submit; a partial file is welcome; the build reports mistakes by file name and writes a worksheet of what is still missing. PROJECT_CONTEXT records the decisions that outlive this stage -- the four kinds of text and the rule that the addressee decides, that core produces no display text, that incompleteness is allowed and incorrectness is not, that anything built outside a composition needs its text read inside one, and that a column id is never translated. CLAUDE.md said two modules; there are three, and the third never ships. It also states the German orthography now, which this session got wrong across a spec and two plans: ss after a short vowel, so muss and dass. * Remove the implementation plans now that every stage is executed Thirteen plans, all of them step-by-step instructions for work that is committed. A plan left behind reads to the next person like an open intention, and these describe a build that no longer exists -- the first still explains how to introduce Gradle. The specifications stay. They say why the architecture is what it is, which the code cannot, and three of them are still argued from. The live-findings note stays too: CLAUDE.md sends people to it, and its hardest lesson -- that a blocking wait on the AWT event thread deadlocks the interface while the build stays green -- is written down nowhere else. Its sweep script stays as well. The note argues explicitly that the script belongs beside the finding so the next reader can measure rather than believe, and removing it would contradict the reasoning it illustrates. Two references in the note and one in the JavaFX-removal spec pointed at plans and now say where the reasoning went instead. * Point the JavaFX-removal spec at where its plan's reasoning went * Remove the stray release-metadata patch from the working tree A 416-line patch file that was applied long ago and has sat in the repository root since. It predates this branch and stays in the shared history, where rewriting it would mean rewriting commits that are already on main and on origin. * Check the translation files in CI and say what they hold classes already runs the generator, so an orphan key, a dropped placeholder or a duplicate fails the compile job with the generator's own message naming the file -- verified by breaking strings_de.properties on purpose. A step summary counts each language against the base, so the author of a translation PR sees what they covered without reading the build log. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Refuse a translation key that would not form a Kotlin name The generator escaped every translation value but emitted the key verbatim as the member identifier, and identifierFor strips only . _ - -- so a key carrying a space, a brace, a quote or a newline from a \uXXXX escape broke out of val <name>: String get() = lookup(...) into an init block or property initializer that runs when Strings is instantiated. Translation files are the contribution surface that arrives by pull request, so this was a path from a merged .properties change to code in every client. The generated identifier is now held to letters-then-letters-and-digits before any source is written, alongside the existing orphan and collision refusals. Proven by replaying a file-writing payload against the built generator: it now throws and writes nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Port the rebased diagnostics and session logging onto the modules origin/main landed replayable session logging (MessageHistoryRecorder), file logging (ApplicationFileLogging) and a user-list refresh split on the old flat layout. The rebase carried the new files, but three things needed the new architecture: - ChatController.fireUserListUpdate() used javafx Platform; core is toolkit-free now, so it dispatches through uiDispatcher like every other fire method. - Two new tests were left in the old src/test/java; moved into core. - ScoreServiceRefreshTest mocked javafx Platform statically; it now injects the DirectUiDispatcher the no-arg constructor installs. The Leaflet map performance work was dropped with the HTML map it optimised. classes testClasses and test are green: 1069 tests, 0 failures, 3 skipped. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Give the debug-to-file recording a home in the Compose settings origin/main added a checkbox to the old JavaFX settings that recorded the whole ON4KST session to file; the Compose redraw dropped the old settings UI, so the toggle had no control left even though the preference and its wiring survived the rebase. It returns to the message-handling tab: the state writes the preference and asks the application, through a new SettingsHost callback, to open or close the error-log handler and the history recorder in the order the old checkbox kept. The explanatory line and its German translation say that passwords are redacted. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Fix Codex review findings on PR 89: station row key, map selection, sort after filter - Station row key now includes the chat category, so the same callsign in two categories no longer collides. - Map marker click and Reset view go through the central station selection. - Sorting now operates on the filtered rows, so filters stay effective. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep the map drawing test off the network and the user's tile cache The test assumed no tile ever arrives, but it used the default TileFetcher, which reads the real disk cache and the OSM tile server. On CI a tile now and then landed before the frame was rendered and covered the background the 'unreachable tile source' test asserts on. An empty temporary cache and a source that always fails make the assumption hold by construction. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
510 lines
32 KiB
Markdown
510 lines
32 KiB
Markdown
# Benutzeroberfläche
|
||
|
||
> 🇬🇧 [English version](en-User-Interface) | 🇩🇪 Du liest gerade die deutsche Version
|
||
|
||
## Verbinden mit dem Chat
|
||
|
||
Vor dem ersten Verbindungsaufbau müssen im Einstellungsfenster das lokale Login-Rufzeichen und Passwort, der gemeinsame Locator der TCP-Sitzung sowie die primäre Chat-Kategorie konfiguriert werden. Soll zusätzlich eine zweite Kategorie verwendet werden, wird sie dort aktiviert und ausgewählt. KST4Contest meldet sich einmal an und ergänzt die zweite Kategorie per Single Sign-on innerhalb derselben TCP-Sitzung.
|
||
|
||
Die Verbindung kann auf zwei Wegen aufgebaut werden:
|
||
|
||
- Mit **Connect to …** im Einstellungsfenster werden die dort eingetragenen Werte übernommen und die Verbindung gestartet.
|
||
- **File → Connect to …** verwendet die bereits in KST4Contest übernommenen Einstellungen.
|
||
|
||
Geänderte Einstellungen müssen mit **Save Settings** gespeichert werden, wenn sie auch beim nächsten Programmstart verwendet werden sollen.
|
||
|
||
Eine bestehende Verbindung kann über **File → Disconnect** oder über **Disconnect** im Einstellungsfenster beendet werden. **Exit + disconnect** beendet zusätzlich das Programm.
|
||
|
||
Bei einem unerwarteten Verbindungsverlust versucht KST4Contest nach einer begrenzten Wartezeit, die ON4KST-Verbindung kontrolliert neu aufzubauen. Ein fehlgeschlagener Erstaufbau blockiert die Benutzeroberfläche nicht mehr.
|
||
|
||
Ob die Verbindung lediglich als TCP-Verbindung besteht oder bereits vollständig angemeldet und synchronisiert ist, zeigt der [`LINK`-Status](#statusleiste-und-hinweise) im Hauptfenster.
|
||
|
||
---
|
||
|
||
## Hauptfenster-Überblick
|
||
|
||
Das Hauptfenster besteht aus mehreren Bereichen:
|
||
|
||
|
||
### Statusleiste und Hinweise
|
||
|
||
Die Statusleiste befindet sich am oberen Rand des Hauptfensters neben dem Menü.
|
||
|
||

|
||
|
||
Der dauerhaft sichtbare `LINK`-Indikator zeigt den tatsächlichen Zustand der ON4KST-Verbindung:
|
||
|
||
| Anzeige | Bedeutung |
|
||
|---|---|
|
||
| grünes `LINK` | Login und Synchronisation der konfigurierten Chat-Kategorien sind vollständig abgeschlossen |
|
||
| gelbes `LINK…` | Verbindung, Anmeldung, Benutzerlistensynchronisation oder kontrolliertes Beenden läuft |
|
||
| rotes `LINK!` | keine Verbindung oder Wartezeit vor einem automatischen Neuaufbau |
|
||
|
||
Der Tooltip enthält den internen Verbindungsstatus und eine genauere Beschreibung des aktuellen Schritts. Der Indikator ist keine Schaltfläche.
|
||
|
||
`ONLINE` wird erst gemeldet, nachdem die Anmeldung bestätigt und die Benutzerlisten der konfigurierten Kategorien vollständig empfangen wurden. Während die Verbindung noch aufgebaut oder neu synchronisiert wird, bleiben Sendfeld und **TX** deaktiviert.
|
||
|
||
Bei bestimmten Ereignissen erscheinen vorübergehend weitere Hinweise:
|
||
|
||
- `SKED` weist auf eine fällige Sked-Erinnerung hin. Der Text enthält das vollständige Zielrufzeichen und die verbleibende Zeit.
|
||
- `BAND+` erscheint nach einem Logeintrag, wenn für die gearbeitete Station noch mindestens ein gemeinsames, aktiviertes und nicht gearbeitetes Band erkannt wurde.
|
||
|
||
Beide Hinweise blinken ungefähr zwölf Sekunden und verschwinden anschließend wieder. Der vollständige Inhalt beziehungsweise die Herleitung steht im jeweiligen Tooltip. Die Anzeigen sind nicht anklickbar.
|
||
|
||
|
||
### PM-Fenster (oben links)
|
||
|
||
Das PM-Fenster zeigt die an das lokale Login-Rufzeichen adressierten Privatnachrichten und die zugehörigen ausgehenden Antworten.
|
||
|
||
Nicht selbst gesendete Nachrichten erscheinen dort zusätzlich, wenn ihr Text ohne Beachtung der Groß- und Kleinschreibung das konfigurierte eigene Login-Rufzeichen enthält. Das gilt für öffentliche Nachrichten an `ALL` ebenso wie für gerichtete Nachrichten zwischen anderen Chatteilnehmern. Gerade im zweiten Fall lässt sich dieses PM-Catching flapsig als **„Lästererkennung“** bezeichnen.
|
||
|
||
Der tatsächliche Empfänger, der Nachrichtentext, die Chat-Kategorie und das Routing bleiben unverändert. Die Nachricht erhält lediglich eine zusätzliche Darstellung im PM-Fenster.
|
||
|
||
Ist das [QSO-Monitoring](de-Funktionen#qso-monitoring-ab-v131) aktiviert, erscheinen dort zusätzlich die erfassten Nachrichten der überwachten Basisrufzeichen. Diese Einträge erhalten eine `Sniffed:`-Kennzeichnung mit dem vollständigen sichtbaren Absender und Empfänger.
|
||
|
||
Neue, nicht selbst gesendete Zeilen durchlaufen sechs grüne Altersstufen und kehren nach fünf Minuten zur normalen Tabellenfarbe zurück. Eigene Nachrichten behalten ihre separate Hervorhebung. Die farbliche Darstellung ist nur ein zeitlicher Hinweis; sie verändert weder Inhalt noch Routing der Nachricht.
|
||
|
||
Die Auswahl einer eingehenden Zeile bereitet eine Antwort an den Absender vor. Bei einer eigenen ausgehenden Nachricht wird stattdessen der ursprüngliche Empfänger als Nachrichtenziel wiederhergestellt. Caught- und Monitoring-Zeilen lösen keine PM-Audioausgabe aus.
|
||
|
||
Altersstufen: [Farbige PM-Zeilen](de-Funktionen#farbige-pm-zeilen-ab-v125). Erkennung und Grenzen: [PM-Abfang](de-Funktionen#pm-abfang-catching-personal-messages-ab-v11).
|
||
|
||
### Benutzerliste (Chat Members)
|
||
|
||
Die zentrale Tabelle aller aktuell aktiven Chat-Nutzer. Spalten (je nach Konfiguration):
|
||
|
||
| Spalte | Inhalt |
|
||
|---|---|
|
||
| Callsign | Rufzeichen der Station |
|
||
| Name | Name beziehungsweise Zusatzinformationen aus dem Chat-Namensfeld |
|
||
| QRA | Maidenhead-Locator |
|
||
| QRB | Entfernung in km |
|
||
| QTF | Richtung in Grad |
|
||
| QRG | Zuletzt aus einer Chat-Nachricht erkannte Frequenz |
|
||
| Tropo | Ergebnis der bandbezogenen Tropo- beziehungsweise Streckenbewertung |
|
||
| Score | Aktueller, numerisch sortierbarer Prioritätswert des normalisierten Basisrufzeichens |
|
||
| Act | Minuten seit der letzten Aktivität |
|
||
| AP | AirScout-Flugzeugdaten, sofern aktiviert |
|
||
| worked | Bandbezogener Worked-, Bandmöglichkeits- und Großfeldstatus sowie `wkdany` |
|
||
| NOT QRV @ | Bänder, auf denen die Station manuell als nicht QRV markiert wurde |
|
||
| Category | Chat-Kategorie des Eintrags |
|
||
|
||
Die QRG-Spalte zeigt die zuletzt für eine Station erkannte Frequenz. Fehlende Nullen werden für die Anzeige ergänzt, sodass beispielsweise `144.21` als `144.210` erscheint. Erkennt KST4Contest nacheinander Frequenzen auf mehreren Bändern, zeigt die Spalte den letzten Treffer; die internen Bandinformationen können trotzdem mehrere aktuelle Bänder der Station enthalten.
|
||
|
||
Relative Angaben werden zunächst mit einem höchstens 30 Minuten alten Bandkontext desselben Absenders kombiniert. Nur wenn dieser fehlt, verwendet KST4Contest das globale Fallback-Band. Erkennungsregeln, Beispiele und Grenzen: [QRG-Erkennung](de-Funktionen#qrg-erkennung).
|
||
|
||
### Worked-, Band- und Großfeldstatus
|
||
|
||
Die Unterspalten unter **worked** sind kompakt, weil bei mehreren aktivierten Bändern kaum Platz für ausgeschriebene Zustände bleibt. `X` kennzeichnet ein auf diesem Band gearbeitetes Rufzeichen. `a` und `B+` weisen auf ein angebotenes, noch nicht gearbeitetes Band hin. Ein angehängtes `o` bedeutet, dass das vierstellige Großfeld auf diesem Band bereits gearbeitet wurde.
|
||
|
||
Die Unterspalte **wkdany** ist bandunabhängig: `x` steht für ein bereits gearbeitetes Rufzeichen, `o` für ein auf irgendeinem Band gearbeitetes Großfeld und `xo` für beides.
|
||
|
||
Jede Statuszelle besitzt einen Tooltip mit der Legende und dem für die betreffende Station ermittelten Zustand. Die vollständige Herleitung einschließlich NOT-QRV-Vorrang: [Gearbeitete Rufzeichen, neue Bänder und neue Großfelder](de-Funktionen#gearbeitete-rufzeichen-neue-bänder-und-neue-großfelder).
|
||
|
||

|
||
|
||
**Sortierung**: Klick auf Spaltenköpfe. QRB-Sortierung arbeitet numerisch (ab v1.22 korrigiert).
|
||
|
||
|
||
Ein grün und fett dargestelltes Rufzeichen kennzeichnet eine aus einer gerichteten Nachricht hergeleitete Richtungsgelegenheit. Die Markierung bezieht sich auf den Absender der Nachricht und bleibt höchstens fünf Minuten sichtbar. Herleitung und Grenzen: [Richtungsgelegenheiten aus gerichteten Nachrichten](de-Funktionen#richtungsgelegenheiten-aus-gerichteten-nachrichten).
|
||
### Sendfeld
|
||
|
||
Das Sendfeld enthält den vorbereiteten Text für die nächste ausgehende Nachricht.
|
||
|
||
Wird eine Station bewusst per Maus oder Tastatur in der Benutzerliste ausgewählt, bereitet KST4Contest eine gerichtete Nachricht vor:
|
||
|
||
```text
|
||
/cq RUFZEICHEN
|
||
```
|
||
|
||
Dabei werden das vollständige sichtbare Rufzeichen einschließlich eines vorhandenen Suffixes und die Chat-Kategorie der ausgewählten Station beibehalten. Ein Ziel wie `9A0BB-70` wird nicht auf `9A0BB` verkürzt.
|
||
|
||
Eine Hintergrundaktualisierung, Neusortierung oder Filteränderung darf einen bereits bearbeiteten Nachrichtentext nicht überschreiben. Nur eine tatsächliche Auswahl durch den Operator bereitet den `/cq`-Empfänger erneut vor.
|
||
|
||
- **TX** oder `Enter` sendet den vorbereiteten Text.
|
||
- `Esc` leert das Sendfeld.
|
||
- Während KST4Contest nicht vollständig mit ON4KST verbunden ist, bleiben Sendfeld und **TX** deaktiviert.
|
||
|
||
Shortcuts, Snippets und Variablen sind unter [Makros und Variablen](de-Makros-und-Variablen) beschrieben.
|
||
|
||
### MYQRG- und SECONDQRG-Feld
|
||
|
||
Die beiden QRG-Felder enthalten die eigenen Frequenzen der primären und sekundären Chat-Kategorie.
|
||
|
||
`MYQRG` kann von einer aktivierten TRX-Synchronisation aktualisiert oder – bei deaktivierten automatischen QRG-Quellen – von Hand eingetragen werden. `SECONDQRG` bleibt davon unabhängig und enthält die QRG der zweiten Kategorie.
|
||
|
||
Die Auswahl einer Station aus dem zweiten Chat verändert die Bedeutung der beiden Werte nicht: `MYQRG` gehört weiterhin zur primären, `SECONDQRG` zur sekundären Kategorie.
|
||
|
||
Weitere Einzelheiten: [TRX-Sync-Einstellungen](de-Konfiguration#trx-sync-einstellungen).
|
||
|
||
### MYQTF-Feld
|
||
|
||
Das MYQTF-Feld zeigt die aktuelle Antennenrichtung als numerischen Winkel in Grad.
|
||
|
||
Ist PSTRotator aktiviert, wird der Wert automatisch übernommen und das Feld ist nicht manuell bearbeitbar. Ohne aktive Rotatorsynchronisation kann die Antennenrichtung direkt eingetragen werden. Die Änderung wird beim Verlassen des Feldes übernommen.
|
||
|
||
Der Wert beeinflusst unter anderem:
|
||
|
||
- die QTF-Filterung,
|
||
- die Darstellung des Antennensektors auf der Stationskarte,
|
||
- die Prioritätsberechnung,
|
||
- die AP-Timeline und
|
||
- die Variable `MYQTF`.
|
||
|
||
---
|
||
|
||
## Tabellenbreiten und gekürzte Zellinhalte
|
||
|
||
Beim ersten brauchbaren Datenbestand richtet KST4Contest die Spalten der Benutzerliste, der Nachrichtenansichten, der DXCluster- und QSO-Tabellen sowie der Worked-Datenbank einmalig nach Überschrift und vorhandenem Inhalt aus. Bereits gespeicherte Breiten haben Vorrang. **Name**, **AP** und **NOT QRV @** werden dabei begrenzt, damit einzelne lange Werte nicht den restlichen Tabellenbereich verdrängen. **Message** und vergleichbare Freitextspalten bleiben flexibel und richten sich nicht nach der längsten Nachricht.
|
||
|
||
Manuell geänderte Spaltenbreiten werden automatisch gespeichert und beim nächsten Start wiederhergestellt. Spätere Nachrichten oder Stationsaktualisierungen überschreiben diese Auswahl nicht.
|
||
|
||
Passt ein normaler Textwert nicht vollständig in seine Zelle, zeigt ein Tooltip den vollständigen Wert. Der Tooltip erscheint nur bei tatsächlich gekürztem Text. Funktionale Tooltips, etwa für QRA-, Worked- oder Bandzustände, bleiben erhalten; bei gekürztem Zelltext stehen Volltext und Erklärung gemeinsam im Tooltip.
|
||
|
||
### Nachrichtentext und Links
|
||
|
||
KST4Contest zeigt Nachrichtentexte bewusst einzeilig an. So bleiben auch bei hohem Chat-Aufkommen viele Einträge gleichzeitig sichtbar. Der Nachteil liegt auf der Hand: Bei einer schmalen **Message**-Spalte passt nicht jede Nachricht vollständig in die Zeile.
|
||
|
||
Ist ein Nachrichtentext breiter als die sichtbare Zelle, zeigt KST4Contest den vollständigen Inhalt als Tooltip an. Dazu die Maus kurz über die betreffende **Message**-Zelle halten. Passt der Text vollständig in die Spalte, wird kein zusätzlicher Volltext-Tooltip eingeblendet.
|
||
|
||
Webadressen mit `http://`, `https://` oder dem Präfix `www.` werden innerhalb des Nachrichtentextes als Links dargestellt. Ein Klick öffnet die Adresse im Standardbrowser des Betriebssystems. Andere Protokolle werden nicht als Link behandelt.
|
||
|
||

|
||
|
||
Damit muss der Divider nicht allein deshalb verschoben werden, um eine einzelne längere Nachricht zu lesen. Für einen dauerhaft breiteren Nachrichtenbereich kann er selbstverständlich weiterhin angepasst werden.
|
||
|
||
---
|
||
|
||
## Filter und Reachability-Steuerung
|
||
|
||
Die Filterleiste befindet sich oberhalb der Chatmember-Tabelle. Filter können miteinander kombiniert werden; eine Station bleibt nur sichtbar, wenn sie alle aktiven Bedingungen erfüllt.
|
||
|
||

|
||
|
||
### Stationsfilter
|
||
|
||
| Bedienelement | Wirkung |
|
||
|---|---|
|
||
| **Show only QTF** | Zeigt nur Stationen innerhalb der gewählten Antennenrichtung und des konfigurierten Öffnungswinkels |
|
||
| **Show only QRB [km] <=** | Begrenzt die Liste auf die eingetragene maximale Entfernung |
|
||
| **Find** | Filtert nach einem vollständigen oder teilweisen Rufzeichen |
|
||
| **wkd** | Blendet Basisrufzeichen aus, die bereits auf mindestens einem unterstützten Band gearbeitet wurden |
|
||
| einzelne Band-Schaltflächen | Blenden Stationen aus, die auf dem betreffenden Band bereits gearbeitet oder dort als NOT QRV markiert wurden |
|
||
| **Inactive stations** | Blendet Stationen aus, deren letzte Chataktivität mehr als 20 Minuten zurückliegt |
|
||
| **Only new grids** | Zeigt nur Stationen aus vierstelligen Großfeldern, die bisher auf keinem Band gearbeitet wurden |
|
||
| **New bands** | Zeigt Stationen mit mindestens einer erkannten, lokal aktivierten und noch nicht gearbeiteten Bandmöglichkeit |
|
||
| **Tropo >=0dB** | Zeigt Stationen mit einer berechneten, nicht negativen SSB-Marge |
|
||
| **AS next 5m** | Zeigt Stationen mit einem aktuellen oder innerhalb der nächsten fünf Minuten erwarteten AirScout-Fenster |
|
||
|
||
Bei **New bands** werden aktuelle QRGs, Bandangaben im Namensfeld und aktive Rufzeichenvarianten gemeinsam ausgewertet. Manuelle NOT-QRV-Markierungen haben Vorrang.
|
||
|
||
Der Filter **Tropo >=0dB** entfernt nur Stationen, für die eine abgeschlossene Berechnung eine negative Marge ergeben hat. Noch nicht berechnete oder fehlgeschlagene Auswertungen bleiben sichtbar. Andernfalls würde ein fehlender API-Wert wie ein nachgewiesen ungeeigneter Funkweg behandelt.
|
||
|
||
### Grid color
|
||
|
||
**Grid color** ist kein Filter. Die Funktion verändert ausschließlich die Darstellung des QRA-Feldes und kennzeichnet bereits gearbeitete vierstellige Großfelder.
|
||
|
||
Die Station bleibt unabhängig von der Farbmarkierung in der Tabelle sichtbar. **Reset filters** deaktiviert diese Anzeige deshalb nicht.
|
||
|
||
### Reachability und Calc selected
|
||
|
||
Das Dropdown **Reachability** bestimmt das Band, auf das sich die Tropo-Spalte, der Tropo-Filter und eine ausdrücklich gestartete Streckenberechnung beziehen.
|
||
|
||
- **Auto** leitet das Band aus der aktuellen Stations-QRG, Bandangaben im Namensfeld und der unterstützten Chat-Kategorie her.
|
||
- Ein ausdrücklich gewähltes Band übersteuert diese automatische Auswahl für die Reachability-Auswertung.
|
||
|
||
Eine Änderung des Dropdowns startet keine Berechnung für die gesamte Benutzerliste. Das wäre bei einer Online-Höhendatenquelle unnötig langsam und würde externe API-Abfragen vervielfachen.
|
||
|
||
**Calc selected** berechnet ausschließlich die aktuell ausgewählte Station auf dem gewählten beziehungsweise automatisch hergeleiteten Band. Das Ergebnis wird anschließend in der Tropo-Spalte und den zugehörigen Ansichten verwendet.
|
||
|
||
### Filter zurücksetzen
|
||
|
||
**Reset filters** entfernt:
|
||
|
||
- den QTF-Filter,
|
||
- den QRB-Filter,
|
||
- den Inhalt des Rufzeichen-Suchfeldes,
|
||
- alle Worked- und Bandfilter,
|
||
- **Inactive stations**,
|
||
- **Only new grids**,
|
||
- **New bands**,
|
||
- **Tropo >=0dB** und
|
||
- **AS next 5m**.
|
||
|
||
Die internen Filterprädikate werden dabei ausdrücklich geleert. Es genügt nicht, lediglich die sichtbaren Toggle-Buttons zurückzusetzen.
|
||
|
||
Nicht verändert werden:
|
||
|
||
- **Grid color**, weil es sich um eine Darstellungsoption handelt, und
|
||
- die Auswahl im **Reachability**-Dropdown, weil sie das Berechnungsband festlegt und nicht unmittelbar die Tabelle filtert.
|
||
|
||
### Verhalten bei schmaler Ansicht
|
||
|
||
Die Filterleiste besitzt keine feste Breite. QTF-, Worked- und Reachability-Controls nutzen zunächst den verfügbaren Platz ihrer jeweiligen Zeile.
|
||
|
||
Wird der mittlere Divider nach rechts verschoben und die Chatmember-Ansicht dadurch schmaler, wechseln Bedienelemente erst dann in die nächste Zeile, wenn ihre tatsächlich benötigte Breite nicht mehr ausreicht. Wird der Bereich wieder breiter, ordnen sie sich unmittelbar neu an.
|
||
|
||
Im Klartext: Die Filter bestimmen den Tabelleninhalt, aber nicht mehr die Mindestbreite der gesamten rechten Programmseite.
|
||
|
||
---
|
||
|
||
## Stationsinfo-Panel (Further Info)
|
||
|
||
Rechts unten werden die Nachrichten der ausgewählten Station zusammengeführt. Dazu gehören öffentliche Nachrichten, Privatnachrichten an die eigene Station und – soweit im Chat sichtbar – Privatnachrichten an andere Stationen.
|
||
|
||
Der im Panel gewählte Filter bestimmt, welche dieser Nachrichten angezeigt werden. Unter **Settings → GUI** lässt sich festlegen, welcher Filter beim Öffnen einer Stationsinformation vorausgewählt ist:
|
||
|
||
- alle Nachrichten,
|
||
- Privatnachrichten an die eigene Station,
|
||
- Privatnachrichten an andere Stationen oder
|
||
- öffentliche Nachrichten.
|
||
|
||
Die Einstellung verändert nur die Darstellung im Stationsinfo-Panel. Nachrichten werden dadurch weder verworfen noch aus den übrigen Nachrichtentabellen entfernt. Der Filter kann im Panel jederzeit für die aktuell betrachtete Station gewechselt werden.
|
||
|
||
Im unteren Bereich können für die ausgewählte Station bandbezogene **Not QRV**-Markierungen gesetzt werden. Sichtbar sind die Bänder, die in den Stationseinstellungen für die eigene Station aktiviert wurden. **tag not qrv all** setzt beziehungsweise entfernt die Markierung für alle unterstützten Bänder gemeinsam, einschließlich momentan nicht eingeblendeter Bänder.
|
||
|
||
Die Änderung wirkt sofort auf die Spalte **NOT QRV @**, die Bandmöglichkeiten und die zugehörigen Filter. Sie wird in der internen Datenbank gespeichert und nach einem Neustart wiederhergestellt.
|
||
|
||

|
||
|
||
Im selben Bereich wird der aktuelle **Priority score** der ausgewählten Station angezeigt.
|
||
|
||
Mit **Sked fail** lässt sich ein fehlgeschlagener Versuch markieren. Der Score des normalisierten Basisrufzeichens wird dadurch stark reduziert. **Reset fail** entfernt diese Markierung wieder. Die Markierung gilt für alle aktiven Suffix- und Kategorievarianten der Station und bleibt innerhalb der laufenden Programmsitzung erhalten.
|
||
|
||
Darunter befinden sich die Bedienelemente zum Anlegen eines Skeds:
|
||
|
||
| Bedienelement | Bedeutung |
|
||
|---|---|
|
||
| **Sked in** | Zeit bis zum Sked |
|
||
| **Band** | vereinbartes Band aus den eigenen aktivierten Bändern |
|
||
| **Mode** | `SSB` oder `CW` für eine mögliche Win-Test-Übergabe |
|
||
| **Create sked** | internen Sked anlegen |
|
||
| **Remind-PM in** | automatische Reminder-PMs aktivieren |
|
||
| **2+1**, **5+2+1**, **10+5+2+1** | Zeitpunkte der Reminder-PMs vor dem Termin |
|
||
|
||

|
||
|
||
Das vorgeschlagene Band wird aus aktuellen QRG- und Namensinformationen der Station hergeleitet. Vor dem Anlegen kann es ausdrücklich geändert werden. Die Mode-Auswahl betrifft nur die Übergabe an Win-Test; der interne Sked und die Reminder-PMs funktionieren unabhängig davon.
|
||
|
||
**Create sked** legt den Termin immer zuerst in KST4Contest an. Ist der Win-Test-Netzwerk-Listener aktiv, wird anschließend zusätzlich eine Übergabe an Win-Test versucht. Kann keine zum ausgewählten Band passende QRG ermittelt werden oder ist Win-Test nicht erreichbar, bleiben der interne Sked, seine Priorisierung und gegebenenfalls angelegte Reminder erhalten.
|
||
|
||
Die vollständige Herleitung und die Grenzen der Funktion sind unter [Skeds und Sked-Erinnerungen](de-Funktionen#skeds-und-sked-erinnerungen) beschrieben.
|
||
|
||
---
|
||
|
||
## Prioritätsliste
|
||
|
||
Die kompakte Prioritätsleiste befindet sich rechts zwischen Benutzerliste und Further-Info-Bereich. Sie zeigt die beiden derzeit höchstbewerteten Kandidaten unmittelbar im Hauptfenster:
|
||
|
||
```text
|
||
Priority: 1 RUFZEICHEN SCORE 2 RUFZEICHEN SCORE more
|
||
```
|
||
|
||
Ein Klick auf einen der beiden Kandidaten wählt den dazugehörigen aktiven Chatmember aus. Dabei werden das vollständige Rufzeichen einschließlich Suffix und die zugehörige Chat-Kategorie verwendet.
|
||
|
||
Die Schaltfläche **more** öffnet ein separates Fenster mit bis zu 15 Kandidaten. Die Liste ist nach absteigendem Score sortiert. Ein Doppelklick wählt den betreffenden Kandidaten aus und schließt das Fenster.
|
||
|
||

|
||
|
||
Stationen mit einem Score von `0` werden nicht in die Prioritätsliste aufgenommen. In der Benutzerliste bleiben sie sichtbar, sodass der Ausschluss nachvollzogen und beispielsweise durch eine geänderte NOT-QRV-Markierung korrigiert werden kann.
|
||
|
||
Der Score wird für das normalisierte Basisrufzeichen berechnet. Mehrere aktive Varianten wie `9A0BB-2` und `9A0BB-70` können daher in der Benutzerliste denselben Wert anzeigen. Die Chatmember bleiben trotzdem getrennte Nachrichtenziele.
|
||
|
||
Neue Nachrichten, AirScout-Daten, Skeds und Statusänderungen lösen eine Neuberechnung aus. Zusätzlich erfolgt eine regelmäßige Aktualisierung im Hintergrund. Eine kurzzeitig noch nicht angepasste Reihenfolge ist deshalb kein Fehler.
|
||
|
||
Herleitung und Grenzen: [Prioritätsscore und Prioritätsliste](de-Funktionen#prioritätsscore-und-prioritätsliste-ab-v140).
|
||
|
||
---
|
||
|
||
## Stationskarte
|
||
|
||
Die Stationskarte kann auf zwei Wegen geöffnet werden:
|
||
|
||
- **Windows → Show / hide station map** öffnet oder schließt das Kartenfenster.
|
||
- **Show on map** im **Further Info**-Bereich öffnet die Karte und fokussiert die ausgewählte Station.
|
||
|
||
Die Karte verwendet die Stationen, die nach Anwendung der aktuellen Benutzerlistenfilter noch sichtbar sind. Die Kopfzeile zeigt die Anzahl der dargestellten Stationen und weist mit `filtered view active` auf eine gefilterte Ansicht hin.
|
||
|
||

|
||
|
||
### Station auswählen
|
||
|
||
Ein einzelner Stationsmarker kann direkt angeklickt werden. KST4Contest:
|
||
|
||
1. übernimmt den konkreten Chatmember als aktuelle Auswahl,
|
||
2. scrollt die Benutzerliste zum entsprechenden Eintrag,
|
||
3. aktualisiert den **Further Info**-Bereich und
|
||
4. bereitet das vollständige sichtbare Rufzeichen als `/cq`-Empfänger vor.
|
||
|
||
Ist **Group nearby stations** ausgewählt, werden Marker, die bei niedrigen Zoomstufen zu dicht beieinanderliegen, als Cluster mit einer Stationsanzahl dargestellt. Ein Klick auf einen Cluster vergrößert den betreffenden Kartenausschnitt. Erst ein anschließend sichtbarer einzelner Marker wählt eine konkrete Station aus. Wird die Checkbox ausgeschaltet, zeigt die Karte unabhängig von der Zoomstufe alle positionierbaren Stationen als einzelne Marker.
|
||
|
||
Das Umschalten wirkt sofort und verändert weder Zoom noch Kartenausschnitt oder Stationsauswahl. Die Einstellung wird automatisch gespeichert und beim nächsten Programmstart wiederhergestellt. Ohne gespeicherte Einstellung bleibt **Group nearby stations** ausgewählt, damit bestehende Installationen zunächst das bisherige Verhalten behalten.
|
||
|
||
Der Schalter betrifft nur die räumlichen Cluster auf dem Bildschirm. Aktive Chatvarianten desselben normalisierten Basisrufzeichens können weiterhin einen gemeinsamen geografischen Marker verwenden und bleiben unabhängig davon getrennte Nachrichtenziele.
|
||
|
||
Die Kopfzeile ergänzt bei ausgewählter Station:
|
||
|
||
- vollständiges Rufzeichen,
|
||
- Locator,
|
||
- QRB und QTF,
|
||
- erkannte aktive Bänder,
|
||
- eine gegebenenfalls vorhandene `B+`-Bandmöglichkeit und
|
||
- die zuletzt bekannten QRGs.
|
||
|
||
Lange Inhalte werden in der Kopfzeile gekürzt. Der vollständige Text steht im Tooltip.
|
||
|
||
### Auswahl mit Reset view löschen
|
||
|
||
**Reset view** löscht die Stationsauswahl, ohne die Kartenposition oder den Zoomlevel zu verändern.
|
||
|
||
Dabei werden:
|
||
|
||
- die ausgewählte Station zurückgesetzt,
|
||
- die Auswahl in der Benutzerliste aufgehoben,
|
||
- die Verbindungslinie zur Gegenstation entfernt,
|
||
- eine noch laufende Auswertung der vorherigen Station verworfen und
|
||
- der rechte Analysebereich entfernt.
|
||
|
||
Die Karte selbst bleibt im zuvor gewählten Ausschnitt. Die Funktion ist deshalb kein geografischer Reset auf den eigenen Standort.
|
||
|
||

|
||
|
||
Wird anschließend wieder ein einzelner Marker gewählt, erscheinen Stationsauswahl und Analysebereich erneut.
|
||
|
||
### DX-Cluster-Spot auslösen
|
||
|
||
**Trigger cluster spot** erscheint nur bei ausgewählter Station. Die Schaltfläche sendet einen einzelnen Spot an die mit dem integrierten DX-Cluster-Server verbundenen Logprogramme.
|
||
|
||
Vorausgesetzt werden:
|
||
|
||
- ein aktivierter lokaler DX-Cluster-Server,
|
||
- mindestens ein verbundener Cluster-Client und
|
||
- eine für die ausgewählte Station verwendbare QRG.
|
||
|
||
Der Spot wird nicht an einen öffentlichen Internet-Cluster gesendet.
|
||
|
||
### Streckenanalyse
|
||
|
||
Unterhalb der Karte befindet sich das Höhenprofil. Der rechte Analysebereich zeigt unter anderem:
|
||
|
||
- verwendete Datenquelle und Anzahl der Höhenpunkte,
|
||
- Analysefrequenz,
|
||
- Erdkrümmungs- beziehungsweise Refraktionsmodell,
|
||
- Radio- und Geländehorizont,
|
||
- Fresnel-Freiheit,
|
||
- erkannte Hindernisse,
|
||
- Link-Budget,
|
||
- geschätzten Empfangspegel und
|
||
- eine zusammenfassende Pfadbewertung.
|
||
|
||
Die Auswertung verwendet dasselbe zentral hergeleitete Band wie die Reachability-Funktionen. Ein im **Reachability**-Dropdown ausdrücklich gewähltes Band wird berücksichtigt.
|
||
|
||
Die Werte bleiben technische Abschätzungen. Gebäude, Bewuchs, lokale Abschattungen, aktuelle Ausbreitungsbedingungen und nicht bekannte Stationsparameter können das reale Ergebnis deutlich verändern.
|
||
|
||
### Streckenanalyse ausblenden
|
||
|
||
Mit **Hide path analysis** werden Höhenprofil und rechter Analysebereich gemeinsam ausgeblendet. Der Kartenbereich erhält dadurch mehr Platz.
|
||
|
||

|
||
|
||
Der Hinweis **Path analysis is hidden** und die Schaltfläche **Show path analysis** bleiben sichtbar. Die Funktion kann daher ohne Umweg wieder eingeschaltet werden.
|
||
|
||
Ist beim Wiedereinblenden keine Station ausgewählt, erscheint kein leerer rechter Bereich. Er wird erst wieder aufgebaut, nachdem eine konkrete Station gewählt wurde.
|
||
|
||
Die Auswahl wird gespeichert und beim nächsten Programmstart wiederhergestellt.
|
||
|
||
Der Divider zwischen Karte und Detailbereich lässt sich horizontal verschieben. Bei einem schmalen Detailbereich werden längere Angaben umgebrochen; reicht die verfügbare Höhe nicht aus, erscheint eine vertikale Scrollleiste.
|
||
|
||
Ausführliche Herleitung und Grenzen: [Stationskarte und Streckenanalyse](de-Funktionen#stationskarte-und-streckenanalyse-ab-v141).
|
||
|
||
---
|
||
|
||
## Globale Nachrichtentabs und Monitorfenster
|
||
|
||
Der untere Bereich des Hauptfensters enthält drei globale Nachrichtentabs. Ihr Inhalt ist nicht von der aktuell in der Benutzerliste ausgewählten Station abhängig.
|
||
|
||
| Tab | Inhalt |
|
||
|---|---|
|
||
| **Public messages** | Öffentliche Chatnachrichten, CQ-Rufe und Beacons |
|
||
| **DXCluster messages** | Über ON4KST empfangene DX-Cluster-Meldungen |
|
||
| **QSO of the other** | Gerichtete Nachrichten zwischen zwei anderen Stationen |
|
||
|
||

|
||
|
||
Im Tab **QSO of the other** werden Absender und Empfänger getrennt dargestellt. Die Spalten **Last QRG TX** und **Last QRG RX** enthalten die zuletzt für beide Stationen bekannten Frequenzen. Sie geben nicht zwingend die QRG der angezeigten Unterhaltung wieder.
|
||
|
||
**wkd TX?** und **wkd RX?** zeigen den globalen Worked-Status der beiden Basisrufzeichen. Die Angaben sind nicht bandbezogen.
|
||
|
||
Der Tab **DXCluster messages** zeigt den meldenden und den gemeldeten Teilnehmer, deren Locator, die QRG, den Meldungstext und den globalen Worked-Status der gemeldeten Station. Welche Felder tatsächlich gefüllt sind, hängt von der vom ON4KST-Server übertragenen Meldung ab.
|
||
|
||
Nachrichtentexte bleiben einzeilig. Ist eine Zelle zu schmal, erscheint der vollständige Inhalt als Tooltip. Webadressen im Meldungstext lassen sich anklicken.
|
||
|
||
### Separates Monitorfenster
|
||
|
||
Zusätzlich öffnet KST4Contest das Fenster **Cluster & QSO of the other**. Es zeigt oben die DX-Cluster-Meldungen und darunter die gerichteten Nachrichten zwischen anderen Stationen.
|
||
|
||

|
||
|
||
Die Position des vertikalen Dividers sowie die Fenstergröße werden automatisch gespeichert. Die DXCluster- und QSO-Tabellen besitzen hier eigene Spaltenbreiten; Änderungen im Monitorfenster verändern daher nicht das Tabellenlayout der Hauptfenster-Tabs.
|
||
|
||
Das Fenster lässt sich über das Menü aus- und wieder einblenden:
|
||
|
||
```text
|
||
Windows → Hide cluster / stranger QSOs
|
||
Windows → Show cluster / stranger QSOs
|
||
```
|
||
|
||
Die Tabellen im Hauptfenster und im Monitorfenster greifen auf dieselben Daten zu. Das Ausblenden des Monitorfensters beendet daher weder den Empfang noch die Darstellung in den unteren Tabs.
|
||
|
||
Herleitung und Grenzen: [Globale Nachrichtenansichten](de-Funktionen#globale-nachrichtenansichten).
|
||
|
||
---
|
||
|
||
## Menü
|
||
|
||
### File
|
||
|
||
- **Connect to …** startet die Verbindung mit den bereits übernommenen Einstellungen.
|
||
- **Disconnect** beendet die aktuelle ON4KST-Verbindung, ohne KST4Contest zu schließen.
|
||
- **Exit + disconnect** beendet die Verbindung und anschließend das Programm.
|
||
|
||
Die Connect- und Disconnect-Einträge werden entsprechend dem aktuellen Verbindungszustand aktiviert oder deaktiviert.
|
||
|
||
### Options
|
||
|
||
- **Set QRG as name in Chat (main category)** sendet `/SETNAME` mit der aktuellen `MYQRG` an die primäre Chat-Kategorie.
|
||
- **Show me as away in chat** sendet `/AWAY`.
|
||
- **Show me as active in chat** sendet `/BACK`.
|
||
- **Show options** blendet das Einstellungsfenster ein beziehungsweise aus.
|
||
|
||
Die serverbezogenen Funktionen sind nur bei vollständig aufgebauter ON4KST-Verbindung verfügbar.
|
||
|
||
### Windows
|
||
|
||
- **Hide cluster / stranger QSOs** beziehungsweise **Show cluster / stranger QSOs** blendet das zusätzliche Cluster- und QSO-Monitorfenster aus oder wieder ein.
|
||
- **hide options** beziehungsweise **show options** blendet das Einstellungsfenster aus oder wieder ein.
|
||
- **Use dark mode design** aktiviert das dunkle Farbschema für die laufende Sitzung.
|
||
- **Use default mode design** aktiviert das normale helle Farbschema für die laufende Sitzung.
|
||
Das Farbschema beim Start wird pro Profil im Einstellungsreiter **GUI** unter **Design** festgelegt.
|
||
- **Show / hide station map** öffnet beziehungsweise schließt das separate Fenster mit Stationskarte und Streckenanalyse.
|
||
|
||
---
|
||
|
||
## Fenstergrößen und Divider
|
||
|
||
KST4Contest speichert Größen und Positionen der Programmfenster, die relevanten Divider sowie manuell geänderte Tabellenbreiten automatisch nach einer kurzen Verzögerung in der Konfigurationsdatei. Ein ausstehender Layoutstand wird beim Programmende noch geschrieben. **Save Settings** ist dafür nicht erforderlich, speichert aber weiterhin den vollständigen aktuellen Stand einschließlich Layout.
|
||
|
||
Das Hauptfenster wird beim Start zusätzlich gegen den sichtbaren Bereich des primären Bildschirms geprüft. Ist die gespeicherte Größe zu groß, verkleinert und verschiebt KST4Contest das Fenster so, dass es wieder erreichbar bleibt. Die genaue Herleitung ist unter [Bildschirmgerechte Größe des Hauptfensters](de-Funktionen#bildschirmgerechte-größe-des-hauptfensters-ab-v141) beschrieben.
|
||
|
||
Für die übrigen Programmfenster gilt diese zusätzliche Größenbegrenzung derzeit nicht. Wird beispielsweise das separate Monitorfenster nach einem Wechsel auf einen kleineren Bildschirm zu groß dargestellt, genügt eine manuelle Korrektur; die neue Größe wird automatisch gespeichert.
|
||
|
||
Bei einer ungünstigen Aufteilung sollten zuerst die Divider und Spaltenbreiten wieder an brauchbare Positionen verschoben werden. Das Löschen der Konfigurationsdatei setzt zwar die UI-Werte zurück, entfernt aber auch die übrigen gespeicherten Programmeinstellungen und sollte deshalb nur verwendet werden, wenn sich die Oberfläche auf anderem Weg nicht mehr herstellen lässt.
|
||
|
||
---
|
||
|
||
## Tipps zur Bedienung
|
||
|
||
- **Einstellungsfenster geöffnet lassen**: Schneller Zugriff auf Beacon-Aktivierung/Deaktivierung.
|
||
- **Rechtsklick in der Benutzerliste**: Öffnet das Snippet-Menü und weitere Aktionen (QRZ.com-Profil, NOT-QRV-Tags setzen).
|
||
- **Enter aus dem Chat heraus**: Wenn im Sendfeld Text steht, sendet Enter direkt – auch wenn der Fokus woanders liegt.
|
||
- **Beacon stoppen**: Beim Scannen von Frequenzen den Beacon ausschalten, damit der Chat nicht mit Meldungen überflutet wird.
|