Statusspalte nur so breit wie ihr Schild - #18
Merged
Merged
Conversation
Martin, 2026-09-29, mit Bild: "im chatroom 144 sind kurzwelleneinträge, bitte kontrolliere ob dieser chat auch wirklich den raum ändert." Zwei getrennte Dinge. **Der Raum.** Gesetzt wird er beim Login (LOGINC|...|chat_id|, bestätigt mit LOGSTAT|100|chat_id|). switchRoom() schickt dagegen "/CHAT 144" -- das steht so in der wtKST-Doku, die dieser Client selbst als "not verified live" kennzeichnet, und ist bis heute nicht nachgeprüft. Statt weiter zu glauben, wird jetzt gemessen: On4kstClient liest die chat_id aus jeder eingehenden CH|/CR|-Zeile und meldet sie als roomObserved(). Im Chatkopf steht beides nebeneinander -- welcher Raum angefordert wurde und aus welchem die Zeilen kommen. Weichen sie ab, war der Wechsel wirkungslos, und man sieht es sofort. Live zeigt es derzeit: "Raum 144 angefordert, Zeilen kommen aus Raum 2" -- Raum 2 ist der 144/432-Raum, das passt, gesetzt hat ihn das Login. **Die Kurzwelle.** Die Zeilen im Bild trugen CLU, nicht KST: sie kamen vom DX-Cluster, der weltweit alles spottet, auch 1,8 und 7 MHz. In einem UKW-Contest kann einen das nicht erreichen -- genau der Fall, den der Filter abdecken soll. Spots, deren Band der aktive Contest nicht kennt, bleiben jetzt draußen. Eine Chatzeile OHNE Frequenz bleibt (über die sagt die Frequenz nichts), ein unbekanntes Band ebenso, und unter "alle Zeilen zeigen" ist alles weiter einsehbar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Martin, 2026-09-29: "bitte kontrolliere ob dieser chat auch wirklich den raum ändert." Nein, tat er nicht: switchRoom() schickte "/CHAT 144" aus einer Doku, die dieser Client selbst als ungeprüft führt. Einen Raum setzt bei ON4KST nur das Login (LOGINC|...|chat_id|, bestätigt mit LOGSTAT|100|chat_id|). Also meldet sich der Client jetzt mit der gewünschten Raumnummer neu an. Am Prüfstand belegt: nach switchRoom(3) kommt beim Server "LOGINC|...|3|" an, die folgenden Zeilen tragen Raum 3, und roomObserved() meldet ihn. Derselbe Raum noch einmal löst KEIN zweites Login aus, sonst risse jeder Bandabgleich die Verbindung ohne Not ab. Dabei zwei Fallen: - Ein connectToHost() auf einem Socket, der gerade zumacht, wird stillschweigend verworfen -- der Socket ging brav in ConnectingState, beim Server kam aber nie etwas an. Der Neuaufbau hängt jetzt am disconnected-Signal, und abort() steht mit im verzögerten Teil. - Der PRÜFSTAND selbst war kaputt: der Mock-Server schrieb alles, was nach dem ersten CK| ankam, nur noch in einen Puffer und parste es nicht mehr. Ein zweites LOGINC sah er nie. Er hätte jeden Raumwechsel für kaputt erklärt, egal wie richtig der Code ist. Das Menü führt die Räume jetzt unter ihrer chat_id (1 = 50/70, 2 = 144/432, 3 = Mikrowelle, 4 = EME, 5 = Kurzwelle). Belegt ist davon nur die 2; ob eine andere Nummer den erwarteten Raum trifft, zeigt nach dem Wechsel der Chatkopf. Dazu eine Mitschrift für die Fehlersuche: CP_KST_MITSCHRIFT=<pfad> schreibt jede Protokollzeile roh mit. Ohne die Variable passiert nichts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Live erlebt am 2026-09-29: nach etlichen Neustarts blieb die
Statusleiste grau und der Chat leer -- bis zum nächsten
Programmstart. Der Grund stand im Code: JEDER Login-Fehlercode außer
100 galt als endgültig ("stop hammering it"). Gedacht war das gegen
falsche Zugangsdaten, es trifft aber genauso den vorübergehenden
Fall: Sitzung noch offen, Server überlastet, Netz kurz weg. Mitten im
Contest ist ein stiller Chat schlimmer als ein Versuch alle paar
Minuten.
Welcher Code was bedeutet, ist nicht belegt (nur 100 = Erfolg), also
wird nicht geraten, sondern langsam weiterprobiert: erster neuer
Anlauf nach einer Minute, dann verdoppelnd bis zehn. Kein Hämmern,
und der Chat kommt von allein wieder, sobald der Grund weg ist.
Prüfstand mit Gegenprobe: der Mock weist den ersten Login ab, danach
muss ein neuer Anlauf anstehen; mit der alten Fassung steht keiner an
und der Test ist rot.
Dabei ein eigener Fehler im Prüfstand: allein gelaufen war er grün,
in der Reihe rot. Der neue Anlauf wird erst gestellt, wenn die
Leitung wirklich unten ist -- sofort danach zu prüfen war ein
Zeitfehler im Prüfstand, nicht im Programm. Jetzt wartet er darauf.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Martin, 2026-09-29, mit Bild: "kann nicht anklicken". Das ganze Raummenü hing an "angemeldet", und angemeldet war er gerade nicht: ON4KST war an dem Morgen schlicht nicht erreichbar (aus seiner eigenen Shell: "connectx to www.on4kst.org port 23001 failed: Operation timed out"). Gerade dann will man den Raum wählen können. Jetzt gilt die Wahl für den nächsten Anlauf -- und der wird sofort genommen. Dazu ein Eintrag "Jetzt neu verbinden" im selben Menü, ebenfalls immer anklickbar: bei einem stillen Chat muss man nicht mehr das Programm neu starten. Away / Wieder da / CQ bleiben gesperrt, solange keine Verbindung steht; die brauchen sie wirklich. Der Prüfstand für das Menü sah bisher nur nach, dass die Einträge DA sind. Genau das war die Lücke -- sie waren da und ließen sich nicht anklicken. Er prüft jetzt beides. Dazu ein Prüfstand für den Weg selbst: getrennt Raum 3 gewählt, und der Server sieht einen Login für Raum 3. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Martin, 2026-09-29: "bitte viel schmäler machen, ich benötige platz!!!" -- über die letzte Spalte im Log. Sie wuchs bis 110 px in jede freie Lücke und stand auf fast jeder Zeile leer da. Jetzt wird gemessen statt geschätzt: die Breite kommt aus der Schrift, in der PillDelegate die Schilder zeichnet (UNGÜLTIG, DUPE, KST, CLU), mit demselben Innenabstand und Einzug. Das sind 71 statt 110 px, und es bleibt richtig, wenn sich die Schriftgröße ändert. Einen Zwischenschritt habe ich wieder verworfen: den frei gewordenen Platz an die Rufzeichenspalte zu geben, damit rechts kein Rand entsteht. Die wuchs damit auf 205 px -- derselbe breite Block, nur woanders. Jetzt dehnt sich keine Spalte mehr. Gefunden hat den Folgefehler die Suite, nicht ich: der Prüfstand für schmale Panels sah, dass die Eingabezeile bei der gewachsenen Spalte nicht mitging. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Martin, 2026-09-29: "dachte du hattest alles schon mehrmals getestet" -- und er hat recht. Dreimal am selben Tag dasselbe Muster: beim Herausziehen aus dem Seitenbereich (Menü ging, Ziehen nicht), beim Chat-Zahnrad (Menü da, Knopf fehlte) und jetzt beim Log. Die Prüfstände riefen jeweils die Funktion auf und bewiesen damit nur die halbe Strecke. Der Prüfstand für die Korrektur klickt jetzt doppelt auf die Zelle und sieht nach, ob ein Editor aufgeht. Dabei die eigentliche Lehre: QTest::mouseDClick geht über das Fenstersystem und VERPUFFT, solange das Fenster nicht wirklich auf einem Schirm liegt -- im Prüfstandslauf nie. Die erste Fassung meldete deshalb "kein Editor", und ich hätte beinahe einen Fehler gesucht, den es nicht gibt: clicked feuerte nicht einmal. Mit QMouseEvent + sendEvent kommt an, was ankommen soll -- dieselbe Technik, die beim Seitenbereich den Zug am Panelkopf nachgewiesen hat. Ergebnis: das Ändern per Doppelklick funktioniert (clicked 1, doubleClicked 1, Editor 1). Offen bleibt, dass nur Rufzeichen, Nr./Locator und Zeit überhaupt editierbar sind. Dazu eine Mitschrift für die Fehlersuche am Log (CP_LOG_MITSCHRIFT=<pfad>), die festhält, was beim Klicken wirklich ankommt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Martin, 2026-09-29: "beim contest kann ich mir keine fehler leisten" und "da muss einfach und alles perfekt laufen". Korrektur von Rufzeichen und Locator laufen nicht mehr über setData(), sondern wie im Contest: doppelt auf die Zelle, tippen, Enter -- und bei JEDEM dieser Schritte wird geprüft, dass der Editor überhaupt aufgeht. Dazu ein neuer Handgriff: Klick auf die Statuszelle, ungültig und wieder zurück. Die Mausereignisse gehen per sendEvent direkt an den Viewport. QTest::mouseClick geht über das Fenstersystem und verpufft, solange das Fenster nicht wirklich auf einem Schirm liegt -- im Prüfstandslauf nie. Jeder bisherige Maus-Prüfstand war damit blind. Die Länge je Folge ist einstellbar (CP_RUETTELN_SCHRITTE), Vorgabe 200 wie bisher. Ein Contest dauert 24 Stunden; was dabei schiefgeht, zeigt sich nicht in 200 Handgriffen. Belegt: - die ganze Suite unter AddressSanitizer + UBSan: 107/107, keine Zugriffe auf Gelöschtes, keine Überläufe, kein undefiniertes Verhalten - Dauerlauf unter denselben Prüfern: 5 Folgen x 2000 Handgriffen = 10.000 Schritte, 7/7 grün, am Ende 364 QSOs im Log Dazu build-asan/ in .gitignore: ohne die Zeile sammelt ein "git add -A" 4194 Objektdateien ein, und GitHub weist den Push ab -- genau so passiert, bevor dieser Commit stand. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Martin, 2026-09-29: "primäres ziel und das muss zu 100 % passen sind meine logs, die ich eingebe. die dürfen nicht weg sein." Die Datenbank lief auf PRAGMA synchronous = NORMAL. Das schützt bei einem Programmabsturz (dafür ist WAL da), aber NICHT bei Stromausfall oder einem stehenden Rechner: dann kann die zuletzt bestätigte Transaktion fehlen -- also genau das QSO, das man gerade geloggt hat. Jetzt FULL. Der neue Prüfstand test_log_haltbarkeit beweist es auf die harte Tour. Ein eigener Prozess schreibt QSOs und wird mit SIGKILL erschlagen: kein Beenden, kein Aufräumen, nichts wird nachträglich weggeschrieben. - 25 von 25 QSOs überleben den Abschuss - Abschuss MITTEN im Schreiben: alle bestätigten QSOs sind da - danach lässt sich weiterloggen - PRAGMA synchronous aus der laufenden Datei ausgelesen: 2 (FULL) - der Preis, gemessen statt behauptet: 0,08 ms je QSO Ein erster Versuch mit fork() endete mit SIGABRT -- die Datenbankschicht verträgt das Abspalten mitten im Betrieb nicht. Ein sauber gestarteter zweiter Prozess schon. Dazu der Chat-Dauerlauf (12 Abbrüche, jedes Mal kommt der Client zurück) und ein Fehler darin, den ich beinahe als Programmfehler gemeldet hätte: nach einer Login-Ablehnung wartet der Client ABSICHTLICH eine Minute, mein Prüfstand gab ihm acht Sekunden. 108/108 grün. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PR #17 (Chatraum, Kurzwellenfilter) ist inzwischen auf main, und dieser Zweig hatte an denselben Stellen gearbeitet -- GitHub meldete CONFLICTING und startete deshalb gar keine Prüfung. Zusammengeführt statt eine Seite wegzuwerfen: der Mock kann jetzt beides, einen Login abweisen (aus #17) und die Leitung kappen (von hier). test_on4kstprotocol läuft mit allen zwölf Fällen beider Zweige, die volle Suite mit 108/108. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Martin, 2026-09-29: "die dürfen nicht weg sein."
Die Datenbank ist seit heute gegen Stromausfall gesichert. Sie kann
aber auf andere Weise versagen: Platte voll, Datei gesperrt, Schema
kaputt, ein Fehler in diesem Programm. Dann stand das QSO in der
Eingabezeile und sonst nirgends -- mit einem Warnhinweis, aber ohne
Ausweg.
Jetzt hängt QsoJournal jedes QSO als ADIF-Zeile an eine Textdatei
neben der Datenbank an (<name>-journal.adi), mit flush und fsync, und
zwar BEVOR die Datenbank es zu sehen bekommt. Die Reihenfolge ist der
ganze Sinn.
Das Journal ist absichtlich das dümmste denkbare Verfahren: kein
Schema, keine Transaktion, kein Index, nichts, was kaputtgehen kann.
Eine Zeile, angehängt, auf Platte. Und weil es gültiges ADIF ist,
lässt es sich überall wieder einlesen.
Belegt im Prüfstand: bei schreibgeschützter Datenbank steht in der
Datenbank nichts ("false") und im Journal alles ("true"). Fünf QSOs,
fünf <EOR>-Zeilen, Rufzeichen und Locator drin.
Dazu toAdifRecord() aus dem anonymen Namensraum geholt -- dieselbe
Zeile, dasselbe Format wie der Export, keine zweite Rechnung daneben.
108/108 grün.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ein Journal, das man nicht zurückspielen kann, ist keine Sicherung. Der ADIF-Leser überging bis jetzt Seriennummern und Rapporte: er war für die Rufzeichen-/Locator-Kartei gebaut, nicht zum Wiederherstellen eines Contest-Logs. Damit wäre ein zurückgeholtes Log ohne Punkte gewesen. Jetzt liest er STX, SRX, RST_SENT, RST_RCVD und CONTEST_ID mit, und unter Datei > Sicherung steht "Aus dem Journal wiederherstellen...". Es ERGÄNZT nur und löscht nie etwas -- wer das braucht, hat schon genug verloren. Schon vorhandene QSOs (Rufzeichen + Band + Minute) werden übersprungen. Prüfstände, den ganzen Weg von hinten aufgezäumt: - Journal schreiben und vollständig zurücklesen: Rufzeichen, Band, Modus, Locator, RST 59/59, Nr. 1/1, Contest-Kennung, Zeit - Datenbank gelöscht, aus dem Journal wiederhergestellt: 12 von 12 QSOs zurück, alle mit beiden Nummern 108/108 grün. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Martin, 2026-09-30: "schreibe es in die liste für später mal zu testen." Drei Teile: was nur er am Gerät prüfen kann, was gebaut aber noch nicht am echten Gerät nachgefahren ist, und was noch zu bauen ist. Dazu die zwei Fallen, die diese Woche schon zugeschlagen haben. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Martin, 2026-09-30: "bitte version immer in die taskleiste legen, automatisch." Links in der Statusleiste steht jetzt "v0.1.1", im Tooltip die vollen Angaben: "Fassung 0.1.1 · Stand 2026-09-30 · d7ab9c7+". Das "+" sagt, dass beim Bauen noch ungespeicherte Änderungen im Arbeitsbaum lagen. Automatisch heißt wörtlich: die Werte kommen aus BuildInfo.h, das cmake/BuildInfo.cmake bei JEDEM Bau neu schreibt. Nichts von Hand zu pflegen, und keine Fassung kann behaupten, eine andere zu sein. Commit und Baudatum stehen bewusst nur im Tooltip -- auf der Leiste kosteten sie Platz, den die Verbindungsanzeigen brauchen; beim Melden eines Fehlers sind sie aber genau die Angabe, die zählt. Prüfstand vergleicht die angezeigte Fassung mit der gebauten, damit die Anzeige nicht stillschweigend veraltet. 108/108 grün. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Windows-CI brach schon beim Bauen ab. QsoJournal band <unistd.h> ein und rief fsync() -- beides POSIX, unter Windows nicht vorhanden. Dasselbe leistet dort _commit() auf demselben Dateideskriptor (<io.h>). Jetzt steht beides unter #ifdef. Dazu der neue Prüfstand für ein Journal, das nicht schreiben kann (gesperrter Ordner): es MUSS das melden -- still zu scheitern wäre das Schlimmste, man verließe sich auf ein Netz, das es nicht gibt -- und das Loggen in die Datenbank muss weiterlaufen. Ein kaputtes Journal darf den Contest nicht anhalten. Belegt: "geschrieben: false | Fehler: Permission denied", Datenbank nimmt das QSO trotzdem an. Unter Windows wird dieser eine Fall übersprungen: setPermissions() greift dort auf Ordnern nicht, das Schreiben gelänge trotzdem und der Prüfstand wäre rot, ohne dass etwas falsch wäre. Lieber ehrlich überspringen als eine Zusage prüfen, die dort nicht herstellbar ist. Lokal 108/108 grün. Ob der Windows-Bau jetzt durchgeht, sagt die CI -- prüfen kann ich es hier nicht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zweiter Windows-Fehler in Folge, diesmal beim Linken: "unresolved external symbol QsoJournal::schreibe". QsoJournal.h deklarierte ContestSettings als "class" vor -- es ist ein struct. MSVC nimmt das Schlüsselwort mit ins Namens-Mangling, clang und gcc nicht. Deshalb baute es hier und auf Linux anstandslos, und nur der Windows-Linker suchte ein Symbol, das so nie erzeugt wurde. Gegengeprüft, ob dieselbe Verwechslung anderswo steht: nein. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zwei Windows-Fehler hintereinander aus einer neuen Datei -- POSIX-only fsync und eine class/struct-Verwechslung in der Vorwärtsdeklaration. Beides hätte man beim Schreiben sehen können. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Martin, 2026-09-29: „bitte viel schmäler machen, ich benötige platz!!!" — über die letzte Spalte im Log. Sie wuchs bis 110 px in jede freie Lücke und stand auf fast jeder Zeile leer da.
Jetzt wird gemessen statt geschätzt: die Breite kommt aus der Schrift, in der
PillDelegatedie Schilder zeichnet (UNGÜLTIG, DUPE, KST, CLU), mit demselben Innenabstand und Einzug. 71 statt 110 px — und es bleibt richtig, wenn sich die Schriftgröße ändert.Einen Zwischenschritt habe ich wieder verworfen: den frei gewordenen Platz an die Rufzeichenspalte zu geben. Die wuchs damit auf 205 px — derselbe breite Block, nur woanders. Jetzt dehnt sich keine Spalte mehr.
Den Folgefehler fand die Suite: der Prüfstand für schmale Panels sah, dass die Eingabezeile bei der gewachsenen Spalte nicht mitging.
107/107 grün.
🤖 Generated with Claude Code