Automatisierte Screenshot Aufnahme per [SCREENSHOT] datei implementiert
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(UARTScope VERSION 1.1.0 LANGUAGES CXX)
|
||||
project(UARTScope VERSION 1.2.0 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
144
README.md
144
README.md
@@ -8,21 +8,25 @@ Ein moderner UART-Monitor für Linux mit Qt6-Oberfläche. Gebaut als vollwertige
|
||||
|
||||
| Feature | Beschreibung |
|
||||
|---|---|
|
||||
| **Unbegrenzter Verlauf** | Kein Zeilenlimit – keine Daten gehen verloren, egal wie viel der Pi sendet |
|
||||
| **Serieller UND Netzwerk-Input** | Verbindung wahlweise über einen echten/virtuellen seriellen Port **oder** eine reine TCP-Verbindung – praktisch für Emulatoren wie FS-UAE, deren Debug-UART per `socat` auf einen TCP-Port gelegt wird |
|
||||
| **PTY-Erkennung** | Pseudo-Terminals unter `/dev/pts/` (z.B. von `qemu -serial pty`) werden im Port-Dropdown automatisch mitgelistet |
|
||||
| **Unbegrenzter Verlauf** | Kein Zeilenlimit – keine Daten gehen verloren, egal wie viel gesendet wird |
|
||||
| **Timestamps** | Jede Zeile im Raw-View bekommt automatisch einen `hh:mm:ss.zzz`-Timestamp |
|
||||
| **Auto-Scroll** | Standardmäßig aktiv – springt automatisch ans Ende neuer Ausgaben |
|
||||
| **H + V Scrolling** | Kein Zeilenumbruch, voller horizontaler Scrollbalken |
|
||||
| **Live-Logging** | Alle empfangenen Zeilen werden mit Timestamp in eine Datei geschrieben |
|
||||
| **Tag-Monitor** | Zeilen mit `[TAG]` werden in eigenen Panels angezeigt und aktualisiert |
|
||||
| **Tag-Monitor mit Verlauf** | Zeilen mit `[TAG]` werden in eigenen Panels angezeigt; jedes Panel hat einen „Aktuell"-Tab (Live-Stand) und einen „Verlauf"-Tab (alle je empfangenen Werte, timestamped) |
|
||||
| **Listen-Werte** | `;`-getrennte Werte in einem Tag werden als mehrzeilige Liste dargestellt |
|
||||
| **Tag-Filter** | Tags können aus dem Raw-View ausgeblendet werden – wird dauerhaft gespeichert |
|
||||
| **Tag-Filter** | Tags können aus dem Raw-View ausgeblendet werden – wird dauerhaft gespeichert; auch Tag-Namen mit Bindestrich (z.B. `I2C-BUS`) werden korrekt erkannt |
|
||||
| **Tabellenansicht** | CSV-formatierte UART-Zeilen werden in einer Tabelle dargestellt |
|
||||
| **Suche** | Inkrementelle Volltextsuche im Raw-View |
|
||||
| **Auto-Reconnect** | Bei Verbindungsabbruch wird automatisch neu verbunden (Intervall einstellbar) |
|
||||
| **Suche mit Navigation** | Inkrementelle Volltextsuche im Raw-View mit Weiter/Zurück (Buttons, Enter, F3/Shift+F3) und Wrap-Around |
|
||||
| **Auto-Reconnect** | Bei Verbindungsabbruch wird automatisch neu verbunden (Intervall einstellbar) – funktioniert für seriell und TCP gleichermaßen |
|
||||
| **ANSI Clear-Screen** | `\033[2J\033[H` aus der Firmware leert Raw-View, Tabelle, Tag-Monitor und Video-Vorschau gleichzeitig |
|
||||
| **Copy-Buttons** | Raw-View und jedes Tag-Panel haben einen „📋 Copy"-Button |
|
||||
| **Copy-Buttons** | Raw-View und jedes Tag-Panel (Aktuell- oder Verlauf-Tab) haben einen „📋 Copy"-Button |
|
||||
| **V4L2 Live Video** | HDMI-Grabber direkt eingebunden – Live-Vorschau unter dem Tag-Monitor |
|
||||
| **Video-Aufzeichnung (MP4)** | Live-Vorschau per Knopfdruck als MP4 aufzeichnen (H.264, via `ffmpeg`) |
|
||||
| **Screenshot** | Aktuellen Frame des HDMI-Grabbers als PNG/JPG speichern |
|
||||
| **Automatischer Screenshot-Trigger** | `[SCREENSHOT] dateiname` als Steuertag: der Frame wird exakt im Moment des Empfangs gespeichert – ideal um z.B. einen kurz angezeigten Memory-Dump zuverlässig zu erwischen |
|
||||
| **Format-Referenz** | Eingebauter Guide (mit Kopieren-Button) für KI-kompatible UART-Formatierung |
|
||||
| **Fensterlayout** | Fenstergröße, Position, Splitter-Positionen und Tag-Filter werden beim Beenden gespeichert |
|
||||
|
||||
@@ -32,16 +36,18 @@ Ein moderner UART-Monitor für Linux mit Qt6-Oberfläche. Gebaut als vollwertige
|
||||
|
||||
```bash
|
||||
# Arch (empfohlen)
|
||||
sudo pacman -S cmake qt6-base qt6-serialport
|
||||
sudo pacman -S cmake qt6-base qt6-serialport ffmpeg
|
||||
|
||||
# Ubuntu / Debian
|
||||
sudo apt install cmake qt6-base-dev qt6-serialport-dev libqt6serialport6-dev
|
||||
sudo apt install cmake qt6-base-dev qt6-serialport-dev libqt6serialport6-dev ffmpeg
|
||||
|
||||
# Fedora
|
||||
sudo dnf install cmake qt6-qtbase-devel qt6-qtserialport-devel
|
||||
sudo dnf install cmake qt6-qtbase-devel qt6-qtserialport-devel ffmpeg
|
||||
```
|
||||
|
||||
V4L2 benötigt keine zusätzliche Library – `linux/videodev2.h` ist Teil der Standard-Kernel-Header.
|
||||
V4L2 benötigt keine zusätzliche Library – `linux/videodev2.h` ist Teil der Standard-Kernel-Header. Das TCP-Netzwerk-Modul (`Qt6::Network`) ist üblicherweise Teil des `qt6-base`-Pakets und braucht keine separate Installation.
|
||||
|
||||
`ffmpeg` ist **nur** für die Video-Aufzeichnung (MP4) nötig – ohne installiertes `ffmpeg` funktioniert der Rest von UARTScope normal, nur der „⏺ Record"-Button zeigt dann eine Fehlermeldung.
|
||||
|
||||
---
|
||||
|
||||
@@ -62,6 +68,69 @@ sudo cmake --install build
|
||||
|
||||
---
|
||||
|
||||
## Verbindung: Seriell oder Netzwerk (TCP)
|
||||
|
||||
Im Connect-Dialog gibt es zwei Tabs:
|
||||
|
||||
### Seriell
|
||||
Wie gewohnt: Port aus der Liste wählen (echte Geräte **und** Pseudo-Terminals unter `/dev/pts/` werden angezeigt), Baudrate/Parität/Stopbits/Flow Control einstellen.
|
||||
|
||||
**Virtuelle serielle Geräte (z.B. QEMU):**
|
||||
```bash
|
||||
qemu-system-xxx -serial pty ...
|
||||
# QEMU gibt im Log den zugewiesenen Pfad aus, z.B.:
|
||||
# char device redirected to /dev/pts/4
|
||||
```
|
||||
Den ausgegebenen Pfad im Seriell-Tab auswählen (ggf. vorher ↻ zum Neuladen der Liste drücken). Baudrate & Co. werden von virtuellen PTYs ignoriert – das ist unschädlich.
|
||||
|
||||
### Netzwerk (TCP)
|
||||
Host/IP und Port angeben statt eines seriellen Ports. Gedacht für Firmware/Emulatoren, die ihre Debug-UART über TCP senden statt über ein echtes serielles Gerät – zum Beispiel FS-UAE, dessen serielle Schnittstelle per `socat` auf einen TCP-Port gelegt wird:
|
||||
|
||||
```bash
|
||||
# Beispiel: FS-UAEs serielle Ausgabe per socat auf TCP-Port 1234 legen
|
||||
socat /tmp/fs-uae-serial TCP-LISTEN:1234,reuseaddr,fork
|
||||
```
|
||||
|
||||
Danach im Netzwerk-Tab `localhost` und Port `1234` eintragen und verbinden. Auto-Reconnect funktioniert identisch zum seriellen Modus – bricht die TCP-Verbindung ab, wird automatisch neu verbunden.
|
||||
|
||||
---
|
||||
|
||||
## Video-Aufzeichnung (MP4)
|
||||
|
||||
Die Live-Vorschau im Video-Widget lässt sich per „⏺ Record"-Button als MP4-Datei aufzeichnen. Dazu wird intern ein `ffmpeg`-Prozess gestartet, dem die rohen Frames als BGRA über eine Pipe zugeführt werden; `ffmpeg` encodiert sie zu H.264/MP4.
|
||||
|
||||
- **Voraussetzung:** `ffmpeg` muss installiert und im `PATH` sein (siehe [Voraussetzungen](#voraussetzungen))
|
||||
- Die Aufzeichnung läuft unabhängig vom Freeze-Status weiter – Freeze pausiert nur die Vorschau, nicht die Aufnahme
|
||||
- Timestamps basieren auf der Systemuhr (`-use_wallclock_as_timestamps`), damit die Aufnahme auch bei schwankender Framerate des Grabbers die reale Dauer korrekt wiedergibt
|
||||
- Ein Auflösungswechsel während der Aufnahme, ein Stopp der Capture oder ein Fehler beenden die Aufzeichnung automatisch sauber
|
||||
|
||||
---
|
||||
|
||||
## Automatischer Screenshot-Trigger
|
||||
|
||||
Manuelles Klicken auf den Screenshot-Button trifft bei schnellen Hardware-Ereignissen (z.B. einem kurz angezeigten Memory-Dump) selten genau den richtigen Moment – menschliche Reaktionszeit liegt bei mehreren hundert Millisekunden, in der Hardware-Welt passieren in dieser Zeit unzählige Instruktionen. Dafür gibt es den Steuertag `[SCREENSHOT]`:
|
||||
|
||||
```c
|
||||
uart_printf("[SCREENSHOT] memdump_%lu.png\n", HAL_GetTick());
|
||||
```
|
||||
|
||||
Sobald diese Zeile empfangen wird, speichert UARTScope **sofort** den Frame, der zu diesem Zeitpunkt im V4L2-Vorschaupuffer liegt – kein Dialog, keine Nutzerinteraktion nötig. Die Verzögerung besteht nur noch aus UART-Übertragungszeit und einem Event-Loop-Tick (typischerweise einstellige Millisekunden), statt aus menschlicher Reaktionszeit.
|
||||
|
||||
**Einrichtung:**
|
||||
1. In der Toolbar auf „Screenshot folder…" klicken und den Zielordner wählen
|
||||
2. Die Einstellung wird sofort gespeichert und bei jedem Programmstart wiederhergestellt
|
||||
|
||||
**Verhalten:**
|
||||
- Ohne konfigurierten Ordner wird der Trigger zwar erkannt (erscheint im Tag-Monitor und Raw-View), aber es wird keine Datei geschrieben – das Ergebnis jedes Trigger-Versuchs (Erfolg oder Fehler, z.B. „kein Ordner konfiguriert" oder „noch kein Frame verfügbar") erscheint kurz in der Statusleiste **und** dauerhaft als `[UARTSCOPE] ...`-Zeile im Raw-View, direkt neben der eigentlichen `[SCREENSHOT]`-Zeile – so geht eine Fehlermeldung nie unbemerkt unter
|
||||
- `<dateiname>` kann die Endung weglassen (Standard: `.png`); eventuelle Pfadanteile in der Firmware-Angabe werden ignoriert – die Datei landet immer direkt im konfigurierten Ordner (kein Path-Traversal möglich)
|
||||
- Wird derselbe Dateiname mehrfach gesendet (z.B. immer `dump.png`), wird nichts überschrieben – UARTScope hängt automatisch `_1`, `_2`, … an
|
||||
- Die Zeile erscheint zusätzlich ganz normal im Tag-Monitor unter `[SCREENSHOT]` – inklusive „Verlauf"-Tab, der eine timestamped Liste aller Trigger-Ereignisse **und** deren Ergebnis zeigt: zuerst der angeforderte Dateiname, direkt danach das Resultat („Screenshot saved: /pfad/..." oder eine Fehlermeldung) – beides chronologisch im selben Panel
|
||||
- Funktioniert unabhängig vom Freeze-Status der Vorschau (wie der manuelle Screenshot-Button auch)
|
||||
|
||||
**Falls kein Bild erscheint:** die häufigsten zwei Ursachen sind (1) der Screenshot-Ordner wurde noch nicht gesetzt, oder (2) die V4L2-Vorschau läuft nicht (▶ Start im Video-Widget noch nicht geklickt, es gibt also noch keinen Frame zum Speichern). In beiden Fällen steht die genaue Ursache als `[UARTSCOPE] ...`-Zeile im Raw-View.
|
||||
|
||||
---
|
||||
|
||||
## Berechtigungen
|
||||
|
||||
```bash
|
||||
@@ -84,9 +153,11 @@ v4l2-ctl -d /dev/video0 --list-formats-ext # unterstützte Formate & Auflösung
|
||||
|
||||
## UART-Ausgabe formatieren
|
||||
|
||||
Alles Folgende gilt unabhängig davon, ob die Verbindung über einen seriellen Port oder über TCP läuft (siehe Abschnitt „Verbindung: Seriell oder Netzwerk (TCP)" weiter oben) – UARTScope interpretiert den empfangenen Text in beiden Fällen identisch.
|
||||
|
||||
### Raw-View (immer aktiv)
|
||||
|
||||
Jede UART-Zeile erscheint im Raw-View mit Timestamp. Keine besondere Formatierung nötig.
|
||||
Jede Zeile erscheint im Raw-View mit Timestamp. Keine besondere Formatierung nötig.
|
||||
|
||||
**Screen leeren** – von der Firmware aus Raw-View, Tabelle, Tag-Monitor und Video-Vorschau gleichzeitig leeren:
|
||||
```c
|
||||
@@ -99,10 +170,16 @@ Zeilen mit `[TAGNAME]` werden im Tag-Monitor-Panel angezeigt **und** im Raw-View
|
||||
|
||||
**Format:** `[TAGNAME] key1=value1 key2=value2 ...`
|
||||
|
||||
- Tag-Name: Buchstaben, Ziffern, Underscore – z.B. `WDG`, `VIDEO`, `KICKSTART`
|
||||
- Tag-Name: Buchstaben, Ziffern, Underscore **und Bindestrich** – z.B. `WDG`, `VIDEO`, `KICKSTART`, `I2C-BUS`
|
||||
- Key=Value-Paare: Leerzeichen-getrennt, Werte ohne Leerzeichen
|
||||
- Ohne Key=Value-Paare wird der rohe String angezeigt
|
||||
|
||||
Jedes Tag-Panel hat zwei Tabs:
|
||||
- **Aktuell** – der letzte empfangene Stand, aktualisiert sich in-place (wie bisher)
|
||||
- **Verlauf** – jeder je empfangene Wert dieses Tags, chronologisch mit Timestamp, mit eigenem „Verlauf leeren"-Button (löscht nur die Historie, das Panel bleibt bestehen)
|
||||
|
||||
Der Copy-Button kopiert je nach aktivem Tab entweder den aktuellen Stand oder den kompletten Verlauf.
|
||||
|
||||
**Listen-Werte:** Ein Wert mit `;`-getrennten Einträgen wird als mehrzeilige Liste unter dem Key dargestellt:
|
||||
|
||||
```c
|
||||
@@ -143,6 +220,14 @@ Optionale Header-Zeile mit `#`, dann CSV-Datenzeilen:
|
||||
|
||||
Delimiter per Dropdown umschaltbar: `,` `;` `\t` `|` `Space`
|
||||
|
||||
### Suche im Raw-View
|
||||
|
||||
Suchbegriff eingeben – der erste Treffer wird automatisch markiert. Weitere Treffer:
|
||||
|
||||
- **▼** / `Enter` / `F3` → nächster Treffer
|
||||
- **▲** / `Shift+F3` → vorheriger Treffer
|
||||
- Ist kein weiterer Treffer in Suchrichtung vorhanden, springt die Suche automatisch an den Anfang (bzw. bei Rückwärtssuche ans Ende) und macht dort weiter (Wrap-Around)
|
||||
|
||||
---
|
||||
|
||||
## Tag-Filter
|
||||
@@ -159,6 +244,7 @@ Beim Beenden werden folgende Einstellungen automatisch gespeichert und beim näc
|
||||
- Splitter-Positionen (Haupt-Splitter und Tag/Video-Splitter)
|
||||
- Auto-Reconnect ein/aus und Intervall
|
||||
- Tag-Filter (ausgeblendete Tags)
|
||||
- Screenshot-Ordner für den `[SCREENSHOT]`-Steuertag
|
||||
|
||||
Gespeichert unter `~/.config/ChicaDev/UARTScope.conf` (via `QSettings`).
|
||||
|
||||
@@ -174,15 +260,15 @@ uartscope/
|
||||
├── UartscopeLogo.png
|
||||
├── uartscope.desktop.in
|
||||
├── include/
|
||||
│ ├── mainwindow.h ← Hauptfenster, koordiniert alle Komponenten
|
||||
│ ├── serialworker.h ← UART-Empfang im eigenen QThread, Auto-Reconnect, ANSI-Erkennung
|
||||
│ ├── rawview.h ← Unbegrenzter Log mit Timestamps, Suche, Copy
|
||||
│ ├── mainwindow.h ← Hauptfenster, koordiniert alle Komponenten, Screenshot-Ordner-Einstellung
|
||||
│ ├── serialworker.h ← Empfang im eigenen QThread (seriell ODER TCP), Auto-Reconnect, ANSI-Erkennung, [SCREENSHOT]-Steuertag
|
||||
│ ├── rawview.h ← Unbegrenzter Log mit Timestamps, Suche (Weiter/Zurück, Wrap-Around), Copy
|
||||
│ ├── tableview.h ← CSV-Parser → QTableWidget
|
||||
│ ├── tagwidget.h ← Container für Tag-Panels
|
||||
│ ├── tagpanel.h ← Ein Panel pro [TAG], Key=Value-Tabelle mit Listen-Support, Copy
|
||||
│ ├── connectdialog.h ← Port-Konfiguration (Port, Baud, Log-Datei)
|
||||
│ ├── tagpanel.h ← Ein Panel pro [TAG]: Aktuell-Tab + Verlauf-Tab, Listen-Support, Copy
|
||||
│ ├── connectdialog.h ← Seriell- und Netzwerk(TCP)-Konfiguration, PTY-Erkennung, Log-Datei
|
||||
│ ├── v4l2worker.h ← V4L2-Capture in std::thread, MJPEG/YUYV/NV12
|
||||
│ └── videowidget.h ← Live-Vorschau, Freeze, Screenshot
|
||||
│ └── videowidget.h ← Live-Vorschau, Freeze, Screenshot (manuell + automatisch via Tag), MP4-Aufzeichnung (ffmpeg)
|
||||
└── src/
|
||||
├── main.cpp
|
||||
├── mainwindow.cpp
|
||||
@@ -205,3 +291,25 @@ uartscope/
|
||||
- **Hex-View**: rohe Bytes als Hex-Dump anzeigen
|
||||
- **Session-Replay**: gespeicherte Log-Dateien abspielen
|
||||
- **Regex-Filter**: Zeilen im Raw-View per regulärem Ausdruck ein-/ausblenden
|
||||
|
||||
---
|
||||
|
||||
## Changelog
|
||||
|
||||
**1.2.0**
|
||||
- Automatischer Screenshot-Trigger via `[SCREENSHOT] dateiname`-Steuertag – speichert den Video-Frame exakt im Moment des Empfangs (z.B. für Memory-Dumps)
|
||||
- Neue Toolbar-Option „Screenshot folder…" zur Konfiguration des Zielordners
|
||||
- Format-Referenz-Dialog um Dokumentation des neuen Steuertags ergänzt
|
||||
- Erfolg/Fehler eines Screenshot-Triggers wird zusätzlich zur Statusleiste dauerhaft als Zeile im Raw-View **und** direkt im `[SCREENSHOT]`-Tag-Panel selbst (Aktuell + Verlauf) protokolliert
|
||||
|
||||
**1.1.0**
|
||||
- Netzwerk-Input (TCP) als Alternative zum seriellen Port, inkl. Auto-Reconnect
|
||||
- PTY-Erkennung (`/dev/pts/`) im Seriell-Tab, z.B. für QEMU
|
||||
- Video-Aufzeichnung als MP4 (via `ffmpeg`)
|
||||
- Tag-Panels: zweiter „Verlauf"-Tab mit vollständiger, timestamped Historie
|
||||
- Suche im Raw-View: Weiter/Zurück-Navigation mit Wrap-Around
|
||||
- Tag-Namen mit Bindestrich werden jetzt korrekt erkannt und gefiltert
|
||||
- Bugfix: letzte Zeile ging bei einem ausbleibenden Folge-Byte-Strom manchmal verloren (Idle-Flush-Timer)
|
||||
|
||||
**1.0.0**
|
||||
- Erste Veröffentlichung
|
||||
|
||||
@@ -41,8 +41,10 @@ private slots:
|
||||
void onError(const QString &message);
|
||||
void onNewLine(const QString &line);
|
||||
void onTagDetected(const QString &tag, const QString &value);
|
||||
void onScreenshotRequested(const QString &filename);
|
||||
void showFormatReference();
|
||||
void configureTagFilter();
|
||||
void configureScreenshotDir();
|
||||
void showAbout();
|
||||
|
||||
private:
|
||||
@@ -53,6 +55,7 @@ private:
|
||||
void doShutdown();
|
||||
void saveSettings();
|
||||
void restoreSettings();
|
||||
void updateScreenshotDirTooltip();
|
||||
|
||||
QThread *m_thread = nullptr;
|
||||
SerialWorker *m_worker = nullptr;
|
||||
@@ -71,6 +74,7 @@ private:
|
||||
|
||||
QAction *m_connectAction = nullptr;
|
||||
QAction *m_disconnectAction = nullptr;
|
||||
QAction *m_screenshotDirAction = nullptr;
|
||||
|
||||
// Splitters (saved/restored via QSettings)
|
||||
QSplitter *m_mainSplitter = nullptr;
|
||||
@@ -78,5 +82,6 @@ private:
|
||||
|
||||
SerialConfig m_lastConfig;
|
||||
QSet<QString> m_suppressedTags; // tags hidden from Raw view
|
||||
QString m_screenshotDir; // target folder for [SCREENSHOT] tag captures
|
||||
bool m_shutdownDone = false;
|
||||
};
|
||||
|
||||
@@ -48,6 +48,11 @@ public slots:
|
||||
signals:
|
||||
void newLine(const QString &line);
|
||||
void tagDetected(const QString &tag, const QString &value);
|
||||
// Fired specifically for a [SCREENSHOT] control tag (in addition to the
|
||||
// normal tagDetected() above, so it still shows up in the Tag Monitor
|
||||
// history too). `filename` is whatever followed the tag, verbatim -
|
||||
// the receiver is responsible for sanitizing/defaulting it.
|
||||
void screenshotRequested(const QString &filename);
|
||||
void clearScreen();
|
||||
void portOpened();
|
||||
void portClosed();
|
||||
|
||||
@@ -27,10 +27,27 @@ public:
|
||||
|
||||
public:
|
||||
void shutdown(); // safe to call multiple times, called from MainWindow::closeEvent
|
||||
// Folder that saveAutoScreenshot() writes into. Empty = not configured
|
||||
// (saveAutoScreenshot() will report an error instead of silently
|
||||
// dropping the request).
|
||||
void setAutoScreenshotDir(const QString &dir) { m_autoScreenshotDir = dir; }
|
||||
|
||||
public slots:
|
||||
void onNewFrame(const QImage &frame);
|
||||
void clearFrame(); // blanks the preview (used on ANSI clear-screen)
|
||||
// Saves whichever frame is currently in m_frame under `filename` inside
|
||||
// m_autoScreenshotDir. Triggered by a [SCREENSHOT] control tag from the
|
||||
// firmware - the point is to grab the frame that's already in flight
|
||||
// the instant the tag arrives (no dialog, no user reaction time), e.g.
|
||||
// to reliably catch a video frame showing a memory dump.
|
||||
void saveAutoScreenshot(const QString &filename);
|
||||
|
||||
signals:
|
||||
// Emitted after every saveAutoScreenshot() attempt so the caller (the
|
||||
// main window) can surface a transient status message. Never blocks/
|
||||
// pops a dialog itself, since this can fire in rapid succession from
|
||||
// firmware-driven triggers.
|
||||
void autoScreenshotResult(bool success, const QString &message);
|
||||
|
||||
private slots:
|
||||
void onStartStop();
|
||||
@@ -76,4 +93,8 @@ private:
|
||||
QProcess *m_recordProcess = nullptr;
|
||||
bool m_recording = false;
|
||||
QSize m_recordSize;
|
||||
|
||||
// Folder for saveAutoScreenshot() ([SCREENSHOT] tag). Set via
|
||||
// setAutoScreenshotDir(), persisted/restored by MainWindow.
|
||||
QString m_autoScreenshotDir;
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
app.setApplicationName("UARTScope");
|
||||
app.setApplicationVersion("1.1.0");
|
||||
app.setApplicationVersion("1.2.0");
|
||||
app.setOrganizationName("ChicaDev");
|
||||
|
||||
app.setStyle(QStyleFactory::create("Fusion"));
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <QClipboard>
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFileDialog>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QMessageBox>
|
||||
@@ -35,6 +36,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
|
||||
connect(m_worker, &SerialWorker::newLine, this, &MainWindow::onNewLine);
|
||||
connect(m_worker, &SerialWorker::tagDetected, this, &MainWindow::onTagDetected);
|
||||
connect(m_worker, &SerialWorker::screenshotRequested, this, &MainWindow::onScreenshotRequested);
|
||||
connect(m_worker, &SerialWorker::clearScreen, this, &MainWindow::onClearScreen);
|
||||
connect(m_worker, &SerialWorker::portOpened, this, &MainWindow::onPortOpened);
|
||||
connect(m_worker, &SerialWorker::portClosed, this, &MainWindow::onPortClosed);
|
||||
@@ -100,6 +102,30 @@ void MainWindow::setupUi()
|
||||
m_videoWidget = new VideoWidget(rightSplitter);
|
||||
m_videoWidget->setMinimumHeight(160);
|
||||
|
||||
connect(m_videoWidget, &VideoWidget::autoScreenshotResult, this,
|
||||
[this](bool ok, const QString &message) {
|
||||
statusBar()->showMessage(message, ok ? 4000 : 6000);
|
||||
// The status bar message disappears after a few seconds and is
|
||||
// easy to miss (especially right after triggering a capture
|
||||
// and looking at the video preview, not the status bar). Also
|
||||
// log it as a normal Raw View line - permanent, scrollable,
|
||||
// and sitting right next to the [SCREENSHOT] tag line itself
|
||||
// for context - so a failure (no folder configured, no frame
|
||||
// yet, etc.) is never silently lost.
|
||||
m_rawView->appendLine(
|
||||
QStringLiteral("[UARTSCOPE] %1").arg(message), m_suppressedTags);
|
||||
|
||||
// Also surface the outcome directly in the Tag Monitor's
|
||||
// [SCREENSHOT] panel - both its "Aktuell" tab (so the latest
|
||||
// status is visible at a glance) and its "Verlauf" history
|
||||
// (so every past trigger's outcome, success or failure, stays
|
||||
// reviewable with a timestamp). tagDetected() for the request
|
||||
// itself is emitted before screenshotRequested() in
|
||||
// SerialWorker, so this result entry always lands after the
|
||||
// corresponding request entry.
|
||||
m_tagWidget->handleTag(QStringLiteral("SCREENSHOT"), message);
|
||||
});
|
||||
|
||||
rightSplitter->addWidget(m_tagWidget);
|
||||
rightSplitter->addWidget(m_videoWidget);
|
||||
rightSplitter->setStretchFactor(0, 1);
|
||||
@@ -168,6 +194,12 @@ void MainWindow::setupToolBar()
|
||||
|
||||
tb->addSeparator();
|
||||
|
||||
m_screenshotDirAction = tb->addAction(tr("Screenshot folder…"));
|
||||
connect(m_screenshotDirAction, &QAction::triggered, this, &MainWindow::configureScreenshotDir);
|
||||
updateScreenshotDirTooltip();
|
||||
|
||||
tb->addSeparator();
|
||||
|
||||
auto *helpAction = tb->addAction(tr("Format reference"));
|
||||
helpAction->setToolTip(tr("Show UARTScope output format guide (copy for AI)"));
|
||||
connect(helpAction, &QAction::triggered, this, &MainWindow::showFormatReference);
|
||||
@@ -309,6 +341,12 @@ void MainWindow::onTagDetected(const QString &tag, const QString &value)
|
||||
m_tagWidget->handleTag(tag, value);
|
||||
}
|
||||
|
||||
void MainWindow::onScreenshotRequested(const QString &filename)
|
||||
{
|
||||
if (m_videoWidget)
|
||||
m_videoWidget->saveAutoScreenshot(filename);
|
||||
}
|
||||
|
||||
void MainWindow::clearAllViews()
|
||||
{
|
||||
m_rawView->clear();
|
||||
@@ -403,7 +441,33 @@ Every received line is appended with a hh:mm:ss.zzz timestamp.
|
||||
No special firmware changes needed.
|
||||
|
||||
────────────────────────────────────────────────────────────
|
||||
5. COMPLETE EXAMPLE (Chica / Amiga hardware emulation)
|
||||
5. AUTOMATIC SCREENSHOT TRIGGER (V4L2 / HDMI grabber tab)
|
||||
────────────────────────────────────────────────────────────
|
||||
[SCREENSHOT] <filename> is a control tag: the instant this line is
|
||||
received, UARTScope saves whatever video frame is currently in the V4L2
|
||||
preview under <filename> - no dialog, no user reaction time needed. This
|
||||
is meant for catching a fast-changing signal (e.g. a memory dump flashed
|
||||
on an emulated display for only a moment) at the exact instant the
|
||||
firmware announces it, rather than relying on manually clicking the
|
||||
screenshot button and missing the window.
|
||||
|
||||
uart_printf("[SCREENSHOT] memdump_%lu.png\n", HAL_GetTick());
|
||||
|
||||
Notes:
|
||||
• Configure the target folder once via the toolbar
|
||||
("Screenshot folder…") - if unset, the trigger is reported but no
|
||||
file is written.
|
||||
• <filename> may omit the extension (defaults to .png); any directory
|
||||
components sent by the firmware are stripped for safety - the file
|
||||
always lands directly in the configured folder.
|
||||
• Reusing the same filename on every trigger is fine: UARTScope
|
||||
automatically appends _1, _2, … instead of overwriting.
|
||||
• The line is also still visible in the Tag Monitor's [SCREENSHOT]
|
||||
panel (with its own "Verlauf" history tab), so you get a timestamped
|
||||
log of every capture in addition to the saved image files.
|
||||
|
||||
────────────────────────────────────────────────────────────
|
||||
6. COMPLETE EXAMPLE (Chica / Amiga hardware emulation)
|
||||
────────────────────────────────────────────────────────────
|
||||
void uart_status_update(void) {
|
||||
uart_printf("[WDG] uptime=%lu free=%lu load=%d temp=%d\n",
|
||||
@@ -421,6 +485,12 @@ void uart_status_update(void) {
|
||||
HAL_GetTick(), vcc_mv / 1000.0f, cpu_load_percent, core_temp_c);
|
||||
}
|
||||
|
||||
// Grab the exact video frame when a memory dump is about to be shown:
|
||||
void trigger_memdump_capture(void) {
|
||||
uart_printf("[SCREENSHOT] memdump_%lu.png\n", HAL_GetTick());
|
||||
show_memory_dump_on_screen();
|
||||
}
|
||||
|
||||
// Clear screen from firmware when you want a fresh start:
|
||||
// uart_printf("\033[2J\033[H");
|
||||
)UARTSCOPE";
|
||||
@@ -511,6 +581,35 @@ void MainWindow::configureTagFilter()
|
||||
dlg->deleteLater();
|
||||
}
|
||||
|
||||
// ── Auto-screenshot folder ──────────────────────────────────────────────────
|
||||
|
||||
void MainWindow::configureScreenshotDir()
|
||||
{
|
||||
const QString dir = QFileDialog::getExistingDirectory(
|
||||
this, tr("Auto-screenshot folder for [SCREENSHOT] tag"), m_screenshotDir);
|
||||
if (dir.isEmpty())
|
||||
return;
|
||||
|
||||
m_screenshotDir = dir;
|
||||
if (m_videoWidget)
|
||||
m_videoWidget->setAutoScreenshotDir(m_screenshotDir);
|
||||
updateScreenshotDirTooltip();
|
||||
|
||||
// Persist immediately, consistent with the tag filter dialog above.
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
void MainWindow::updateScreenshotDirTooltip()
|
||||
{
|
||||
if (!m_screenshotDirAction)
|
||||
return;
|
||||
m_screenshotDirAction->setToolTip(
|
||||
m_screenshotDir.isEmpty()
|
||||
? tr("No folder set yet - click to choose where [SCREENSHOT]-tag "
|
||||
"captures are saved")
|
||||
: tr("[SCREENSHOT] tag captures are saved to: %1").arg(m_screenshotDir));
|
||||
}
|
||||
|
||||
// ── About dialog ──────────────────────────────────────────────────────────
|
||||
|
||||
void MainWindow::showAbout()
|
||||
@@ -572,7 +671,7 @@ void MainWindow::showAbout()
|
||||
grid->addWidget(v, row, 1);
|
||||
};
|
||||
|
||||
addRow(0, tr("Version"), "1.1.0");
|
||||
addRow(0, tr("Version"), "1.2.0");
|
||||
addRow(1, tr("Entwickler"), "Dany Thinnes");
|
||||
addRow(2, tr("Projekt"), "Projekt Hirnfrei");
|
||||
addRow(3, tr("Framework"), QString("Qt %1").arg(QT_VERSION_STR));
|
||||
@@ -619,6 +718,8 @@ void MainWindow::saveSettings()
|
||||
tags.sort();
|
||||
s.setValue("tagfilter/suppressed", tags);
|
||||
|
||||
s.setValue("screenshot/autoDir", m_screenshotDir);
|
||||
|
||||
s.sync(); // flush to disk immediately (important since we also call
|
||||
// this mid-session from configureTagFilter())
|
||||
}
|
||||
@@ -647,4 +748,9 @@ void MainWindow::restoreSettings()
|
||||
for (const QString &t : tags)
|
||||
if (!t.isEmpty())
|
||||
m_suppressedTags.insert(t);
|
||||
|
||||
m_screenshotDir = s.value("screenshot/autoDir").toString();
|
||||
if (m_videoWidget)
|
||||
m_videoWidget->setAutoScreenshotDir(m_screenshotDir);
|
||||
updateScreenshotDirTooltip();
|
||||
}
|
||||
|
||||
@@ -392,7 +392,24 @@ void SerialWorker::processLine(const QString &line)
|
||||
if (match.hasMatch()) {
|
||||
const QString tag = match.captured(1).toUpper();
|
||||
const QString value = match.captured(2).trimmed();
|
||||
|
||||
// Emit tagDetected() first so the request itself (the filename the
|
||||
// firmware sent) lands in the Tag Monitor's [SCREENSHOT] history
|
||||
// before the save outcome does. Both signals are queued to the GUI
|
||||
// thread; queued events are processed in the order they were
|
||||
// posted, so emission order here directly determines the order
|
||||
// the two entries appear in - swap it and the result would show
|
||||
// up "before" the request that caused it.
|
||||
emit tagDetected(tag, value);
|
||||
|
||||
// [SCREENSHOT] <filename> is a control tag: fire immediately, as
|
||||
// close in time as possible to this line arriving, so the caller
|
||||
// can grab whichever V4L2 frame is currently in flight - e.g. to
|
||||
// capture the exact video frame showing a memory dump the moment
|
||||
// the firmware announces it, rather than relying on a human's
|
||||
// reaction time with the manual screenshot button.
|
||||
if (tag == QLatin1String("SCREENSHOT"))
|
||||
emit screenshotRequested(value);
|
||||
}
|
||||
|
||||
emit newLine(line);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <QPainter>
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QDateTime>
|
||||
#include <QStandardPaths>
|
||||
@@ -164,6 +165,55 @@ void VideoWidget::onScreenshot()
|
||||
m_frame.save(path);
|
||||
}
|
||||
|
||||
void VideoWidget::saveAutoScreenshot(const QString &filename)
|
||||
{
|
||||
if (m_frame.isNull()) {
|
||||
emit autoScreenshotResult(false,
|
||||
tr("[SCREENSHOT] tag received, but no video frame is available yet."));
|
||||
return;
|
||||
}
|
||||
if (m_autoScreenshotDir.isEmpty()) {
|
||||
emit autoScreenshotResult(false,
|
||||
tr("[SCREENSHOT] tag received, but no auto-screenshot folder is "
|
||||
"configured (toolbar → \"Screenshot folder…\")."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Only take the bare filename from what the firmware sent - this
|
||||
// strips any directory components (incl. attempts at '../' path
|
||||
// traversal), so the firmware can never dictate where on disk we
|
||||
// write. Fall back to a timestamp if it sent nothing usable, and
|
||||
// default to .png if it didn't specify an extension.
|
||||
QString name = QFileInfo(filename.trimmed()).fileName();
|
||||
if (name.isEmpty()) {
|
||||
name = QStringLiteral("screenshot_%1.png")
|
||||
.arg(QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss_zzz"));
|
||||
} else if (QFileInfo(name).suffix().isEmpty()) {
|
||||
name += QStringLiteral(".png");
|
||||
}
|
||||
|
||||
const QDir dir(m_autoScreenshotDir);
|
||||
QString path = dir.filePath(name);
|
||||
|
||||
// Don't silently overwrite an earlier capture if the firmware reuses
|
||||
// the same filename on every trigger (e.g. a generic "dump.png") -
|
||||
// append a numeric suffix instead so nothing gets lost.
|
||||
if (QFileInfo::exists(path)) {
|
||||
const QString base = QFileInfo(name).completeBaseName();
|
||||
const QString suffix = QFileInfo(name).suffix();
|
||||
int n = 1;
|
||||
do {
|
||||
path = dir.filePath(QStringLiteral("%1_%2.%3").arg(base).arg(n).arg(suffix));
|
||||
++n;
|
||||
} while (QFileInfo::exists(path));
|
||||
}
|
||||
|
||||
if (m_frame.save(path))
|
||||
emit autoScreenshotResult(true, tr("Screenshot saved: %1").arg(path));
|
||||
else
|
||||
emit autoScreenshotResult(false, tr("Failed to save screenshot to %1").arg(path));
|
||||
}
|
||||
|
||||
void VideoWidget::onNewFrame(const QImage &frame)
|
||||
{
|
||||
// Feed the recorder regardless of freeze state, so pausing the preview
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Maintainer: diabolus <your@email.com>
|
||||
pkgname=uartscope
|
||||
pkgver=1.0.0.r6.ga942f83
|
||||
pkgver=1.1.0.r0.g36923e1
|
||||
pkgrel=1
|
||||
pkgdesc="Qt6-based UART serial monitor with tag monitoring, table view and auto-reconnect"
|
||||
arch=('x86_64' 'aarch64')
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
format = 2
|
||||
pkgname = uartscope
|
||||
pkgbase = uartscope
|
||||
pkgver = 1.0.0.r6.ga942f83-1
|
||||
pkgver = 1.1.0.r0.g36923e1-1
|
||||
pkgarch = x86_64
|
||||
pkgbuild_sha256sum = 838e01d91a8df5c30e4be619acfc3fe42d6b58ec89f227d9df94874ebfbed8c0
|
||||
pkgbuild_sha256sum = 69ca8218ddee1c9dbe0ee82d052da7cad987dcc52773078209494a1ff8b3c487
|
||||
packager = Unknown Packager
|
||||
builddate = 1787005573
|
||||
builddate = 1787031398
|
||||
builddir = /home/diabolus/Arbeit/Projekt-Hirnfrei/uartscope/uartscope-git
|
||||
startdir = /home/diabolus/Arbeit/Projekt-Hirnfrei/uartscope/uartscope-git
|
||||
buildtool = makepkg
|
||||
@@ -242,7 +242,7 @@ installed = compiler-rt20-20.1.8-1-x86_64
|
||||
installed = compiler-rt21-21.1.8-1-x86_64
|
||||
installed = composefs-1.0.8-1-x86_64
|
||||
installed = composer-2.10.2-1-any
|
||||
installed = confuse-3.3-5-x86_64
|
||||
installed = confuse-3.4-1-x86_64
|
||||
installed = containerd-2.3.4-1-x86_64
|
||||
installed = convertlit-1.8-13-x86_64
|
||||
installed = coolercontrol-4.3.1-2-x86_64
|
||||
@@ -281,7 +281,7 @@ installed = ddcutil-2.2.7-1-x86_64
|
||||
installed = debhelper-14.3-1-any
|
||||
installed = debtap-3.6.3-1-any
|
||||
installed = debugedit-5.3-2-x86_64
|
||||
installed = debuginfod-0.195-8-x86_64
|
||||
installed = debuginfod-0.196-1-x86_64
|
||||
installed = default-cursors-3-1-any
|
||||
installed = dejagnu-1.6.3-21-any
|
||||
installed = deno-2.9.5-1-x86_64
|
||||
@@ -303,7 +303,7 @@ installed = docbook-xml-4.5-11-any
|
||||
installed = docbook-xsl-1.79.2-9-any
|
||||
installed = docker-1:29.7.2-1-x86_64
|
||||
installed = docker-buildx-0.36.1-1-x86_64
|
||||
installed = docker-compose-5.4.0-1-x86_64
|
||||
installed = docker-compose-5.5.0-1-x86_64
|
||||
installed = dolphin-26.04.3-1-x86_64
|
||||
installed = dos2unix-7.5.6-1-x86_64
|
||||
installed = dosbox-0.74.3-4-x86_64
|
||||
@@ -342,7 +342,7 @@ installed = eigen-5.0.1-2-x86_64
|
||||
installed = electron-1:43-1-any
|
||||
installed = electron43-43.4.0-1-x86_64
|
||||
installed = elementary-icon-theme-8.2.0-2-any
|
||||
installed = elfutils-0.195-8-x86_64
|
||||
installed = elfutils-0.196-1-x86_64
|
||||
installed = embree-4.4.1-1-x86_64
|
||||
installed = enca-1.22-1-x86_64
|
||||
installed = enchant-2.8.15-2-x86_64
|
||||
@@ -393,7 +393,7 @@ installed = flashrom-1.7.0-1-x86_64
|
||||
installed = flat-remix-gnome-20250926-1-any
|
||||
installed = flatpak-1:1.18.1-1-x86_64
|
||||
installed = flex-2.6.4-6-x86_64
|
||||
installed = fltk-1.4.5-1-x86_64
|
||||
installed = fltk-1.4.5-2-x86_64
|
||||
installed = fltk1.3-1.3.11-4-x86_64
|
||||
installed = fluidsynth-2.6.0-1-x86_64
|
||||
installed = fmt-12.2.0-1-x86_64
|
||||
@@ -532,7 +532,7 @@ installed = gnupg-2.4.9-3-x86_64
|
||||
installed = gnutls-3.8.13-2-x86_64
|
||||
installed = go-2:1.26.6-1-x86_64
|
||||
installed = go-md2man-2.0.7-2-x86_64
|
||||
installed = go-tools-4:0.48.0-1-x86_64
|
||||
installed = go-tools-4:0.49.0-1-x86_64
|
||||
installed = gobject-introspection-1.86.0-2-x86_64
|
||||
installed = gobject-introspection-runtime-1.86.0-2-x86_64
|
||||
installed = gom-0.5.6-1-x86_64
|
||||
@@ -635,7 +635,7 @@ installed = hidapi-0.15.0-1-x86_64
|
||||
installed = highway-1.4.0-1-x86_64
|
||||
installed = hiredis-1.3.0-1-x86_64
|
||||
installed = hplip-1:3.26.4-1-x86_64
|
||||
installed = hspell-1.4-6-x86_64
|
||||
installed = hspell-1.4-7-x86_64
|
||||
installed = htdig-3.2.0b6-11.1-x86_64
|
||||
installed = htop-3.5.3-1-x86_64
|
||||
installed = http-parser-2.9.4-2-x86_64
|
||||
@@ -908,7 +908,7 @@ installed = lib32-libcups-2.4.19-1-x86_64
|
||||
installed = lib32-libdatrie-0.2.14-1-x86_64
|
||||
installed = lib32-libdrm-2.4.134-1-x86_64
|
||||
installed = lib32-libdv-1.0.0-9-x86_64
|
||||
installed = lib32-libelf-0.195-1-x86_64
|
||||
installed = lib32-libelf-0.196-1-x86_64
|
||||
installed = lib32-libepoxy-1.5.10-2-x86_64
|
||||
installed = lib32-libffi-3.8.0-1-x86_64
|
||||
installed = lib32-libgcrypt-1.12.2-1-x86_64
|
||||
@@ -1104,7 +1104,7 @@ installed = libebml-1.4.5-3-x86_64
|
||||
installed = libebur128-1.2.6-2-x86_64
|
||||
installed = libedit-20260512_3.1-1-x86_64
|
||||
installed = libei-1.6.0-1-x86_64
|
||||
installed = libelf-0.195-8-x86_64
|
||||
installed = libelf-0.196-1-x86_64
|
||||
installed = libepoxy-1.5.10-3-x86_64
|
||||
installed = libev-4.33-5-x86_64
|
||||
installed = libevdev-1.13.6-1-x86_64
|
||||
@@ -1267,7 +1267,7 @@ installed = libofx-0.10.9-2-x86_64
|
||||
installed = libogg-1.3.6-1-x86_64
|
||||
installed = liboggz-1.1.3-1-x86_64
|
||||
installed = libomxil-bellagio-0.9.3-5-x86_64
|
||||
installed = libopenmpt-0.8.7-1-x86_64
|
||||
installed = libopenmpt-0.8.8-1-x86_64
|
||||
installed = libosinfo-1.12.0-3-x86_64
|
||||
installed = libp11-0.4.20-1-x86_64
|
||||
installed = libp11-kit-0.26.5-1-x86_64
|
||||
@@ -1459,7 +1459,7 @@ installed = lightdm-slick-greeter-2.2.7-1-x86_64
|
||||
installed = lilv-0.28.0-1-x86_64
|
||||
installed = linphone-desktop-appimage-6.1.2-1-x86_64
|
||||
installed = linux-7.1.8.arch1-3-x86_64
|
||||
installed = linux-api-headers-7.1-1-x86_64
|
||||
installed = linux-api-headers-7.2-1-x86_64
|
||||
installed = linux-firmware-20260810-2-any
|
||||
installed = linux-firmware-amdgpu-20260810-2-any
|
||||
installed = linux-firmware-atheros-20260810-2-any
|
||||
@@ -1625,7 +1625,7 @@ installed = nettle-4.0-1-x86_64
|
||||
installed = network-manager-applet-1.36.0-2-x86_64
|
||||
installed = networkmanager-1.58.0-1-x86_64
|
||||
installed = networktablet-1.5-3-x86_64
|
||||
installed = nextcloud-34.0.2-1-any
|
||||
installed = nextcloud-34.0.3-1-any
|
||||
installed = nextcloud-app-spreed-1:24.0.3-1-any
|
||||
installed = nextcloud-app-talk_matterbridge-1.33.1026000-1-any
|
||||
installed = nextcloud-client-2:34.0.1-3-x86_64
|
||||
@@ -2001,7 +2001,7 @@ installed = python-html5lib-1.1-18-any
|
||||
installed = python-httpcore-1.0.9-3-any
|
||||
installed = python-httpx-0.28.1-7-any
|
||||
installed = python-huggingface-hub-1:1.27.0-1-any
|
||||
installed = python-hypothesis-6.165.3-1-x86_64
|
||||
installed = python-hypothesis-6.165.5-1-x86_64
|
||||
installed = python-idna-3.18-1-any
|
||||
installed = python-imagesize-2.0.0-1-any
|
||||
installed = python-importlib-metadata-9.0.0-1-any
|
||||
@@ -2021,8 +2021,8 @@ installed = python-jmespath-1.1.0-1-any
|
||||
installed = python-joblib-1.5.3-1-any
|
||||
installed = python-kiwisolver-1.5.0-1-x86_64
|
||||
installed = python-ko-speech-tools-0.1.0-1-any
|
||||
installed = python-ladybug-core-0.44.54-1-any
|
||||
installed = python-ladybug-geometry-1.35.2-1-any
|
||||
installed = python-ladybug-core-0.44.56-1-any
|
||||
installed = python-ladybug-geometry-1.35.3-1-any
|
||||
installed = python-lark-parser-1.3.1-2-any
|
||||
installed = python-lazy-loader-0.5-1-any
|
||||
installed = python-legacy-cgi-2.6.4-2-any
|
||||
@@ -2074,7 +2074,7 @@ installed = python-pillow-12.3.0-1-x86_64
|
||||
installed = python-pip-26.2.1-1-any
|
||||
installed = python-pipx-1.15.0-1-any
|
||||
installed = python-pkg_resources-81.0.0-1-any
|
||||
installed = python-platformdirs-4.11.2-1-any
|
||||
installed = python-platformdirs-4.11.3-1-any
|
||||
installed = python-pluggy-1.6.0-3-any
|
||||
installed = python-poetry-core-2.4.1-1-any
|
||||
installed = python-pooch-1.9.0-1-any
|
||||
@@ -2113,8 +2113,8 @@ installed = python-pytest-cov-7.1.0-1-any
|
||||
installed = python-pytest-freezer-0.4.9-2-any
|
||||
installed = python-pytest-subtests-0.15.0-2-any
|
||||
installed = python-pytest-sugar-1.1.1-2-any
|
||||
installed = python-pytest-timeout-2.4.0-2-any
|
||||
installed = python-python-discovery-1.5.1-1-any
|
||||
installed = python-pytest-timeout-2.5.0-1-any
|
||||
installed = python-python-discovery-1.5.2-1-any
|
||||
installed = python-pytokens-0.4.1-1-any
|
||||
installed = python-pytorch-cuda-2.13.0-4-x86_64
|
||||
installed = python-pytz-2026.1-1-any
|
||||
@@ -2192,7 +2192,7 @@ installed = python-tzlocal-1:5.4.4-1-any
|
||||
installed = python-uc-micro-py-2.0.0-1-any
|
||||
installed = python-ujson-5.13.0-1-x86_64
|
||||
installed = python-urllib3-2.7.0-1-any
|
||||
installed = python-urwid-4.0.9-1-any
|
||||
installed = python-urwid-4.0.10-1-any
|
||||
installed = python-userpath-1.9.2-4-any
|
||||
installed = python-uv-build-0.12.5-1-x86_64
|
||||
installed = python-vcs-versioning-2.2.4-1-any
|
||||
@@ -2797,7 +2797,7 @@ installed = tinysparql-3.11.1-1-x86_64
|
||||
installed = tinyxml-2.6.2-13-x86_64
|
||||
installed = tinyxml2-11.0.0-2-x86_64
|
||||
installed = tk-8.6.16-1-x86_64
|
||||
installed = tmux-3.7_b-1-x86_64
|
||||
installed = tmux-3.7_c-1-x86_64
|
||||
installed = topgrade-17.9.0-1-x86_64
|
||||
installed = tor-0.4.9.11-1-x86_64
|
||||
installed = torsocks-2.5.0-1-x86_64
|
||||
@@ -2820,7 +2820,7 @@ installed = ttf-ubuntu-font-family-1:0.83-2-any
|
||||
installed = tumbler-4.20.2-1-x86_64
|
||||
installed = twolame-0.4.0-4-x86_64
|
||||
installed = tzdata-2026c-1-x86_64
|
||||
installed = uartscope-1.0.0.r5.g1422efd-1-x86_64
|
||||
installed = uartscope-1.0.0.r6.ga942f83-1-x86_64
|
||||
installed = uchardet-0.0.8-4-x86_64
|
||||
installed = udisks2-2.11.2-1-x86_64
|
||||
installed = unifdef-2.12-4-x86_64
|
||||
|
||||
Binary file not shown.
@@ -3,12 +3,12 @@
|
||||
pkgname = uartscope
|
||||
pkgbase = uartscope
|
||||
xdata = pkgtype=pkg
|
||||
pkgver = 1.0.0.r6.ga942f83-1
|
||||
pkgver = 1.1.0.r0.g36923e1-1
|
||||
pkgdesc = Qt6-based UART serial monitor with tag monitoring, table view and auto-reconnect
|
||||
url = https://git.projekt-hirnfrei.de/diabolus/uartscope
|
||||
builddate = 1787005573
|
||||
builddate = 1787031398
|
||||
packager = Unknown Packager
|
||||
size = 406129
|
||||
size = 422641
|
||||
arch = x86_64
|
||||
license = MIT
|
||||
conflict = uartscope
|
||||
|
||||
Binary file not shown.
Submodule uartscope-git/src/uartscope updated: a942f8385b...36923e1646
@@ -1,2 +1,3 @@
|
||||
a942f8385b8b05f5ec9a097ebbb3ba61ad0690f6 not-for-merge branch 'main' of https://git.projekt-hirnfrei.de/diabolus/uartscope
|
||||
36923e16461bc15086c84187790dbcb5f0a5030f not-for-merge branch 'main' of https://git.projekt-hirnfrei.de/diabolus/uartscope
|
||||
cc102c93eb17f7b910d8e74c3505f198bed77f10 not-for-merge tag 'v1.0.0' of https://git.projekt-hirnfrei.de/diabolus/uartscope
|
||||
36923e16461bc15086c84187790dbcb5f0a5030f not-for-merge tag 'v1.1.0' of https://git.projekt-hirnfrei.de/diabolus/uartscope
|
||||
|
||||
Reference in New Issue
Block a user