- Tags haben jetzt einen Verlauf

- Suchfunktion hat jetzt weiter und zurück
- Tags mit Bindestrich werden erkannt
This commit is contained in:
2026-08-18 00:24:43 +02:00
parent 1422efdc2f
commit a942f8385b
12 changed files with 415 additions and 224 deletions

View File

@@ -3,6 +3,10 @@
#include <QRegularExpression>
#include <QApplication>
#include <QClipboard>
#include <QDateTime>
#include <QScrollBar>
#include <QFont>
#include <QTextCursor>
TagPanel::TagPanel(const QString &tag, QWidget *parent)
: QGroupBox(QStringLiteral("[%1]").arg(tag), parent)
@@ -12,7 +16,15 @@ TagPanel::TagPanel(const QString &tag, QWidget *parent)
layout->setContentsMargins(6, 14, 6, 6);
layout->setSpacing(4);
m_table = new QTableWidget(0, 2, this);
m_tabs = new QTabWidget(this);
// ── "Aktuell" tab: latest value(s), updates in-place ───────────────
auto *currentTab = new QWidget(m_tabs);
auto *currentLayout = new QVBoxLayout(currentTab);
currentLayout->setContentsMargins(0, 4, 0, 0);
currentLayout->setSpacing(4);
m_table = new QTableWidget(0, 2, currentTab);
m_table->setHorizontalHeaderLabels({tr("Key"), tr("Value")});
m_table->horizontalHeader()->setStretchLastSection(true);
m_table->verticalHeader()->hide();
@@ -20,18 +32,48 @@ TagPanel::TagPanel(const QString &tag, QWidget *parent)
m_table->setAlternatingRowColors(true);
m_table->setMaximumHeight(220);
m_table->verticalHeader()->setDefaultSectionSize(22);
layout->addWidget(m_table);
currentLayout->addWidget(m_table);
m_rawLabel = new QLabel(this);
m_rawLabel = new QLabel(currentTab);
m_rawLabel->setWordWrap(true);
m_rawLabel->setStyleSheet("font-family: monospace;");
m_rawLabel->hide();
layout->addWidget(m_rawLabel);
currentLayout->addWidget(m_rawLabel);
m_tabs->addTab(currentTab, tr("Aktuell"));
// ── "Verlauf" tab: every value ever received, timestamped ──────────
auto *historyTab = new QWidget(m_tabs);
auto *historyLayout = new QVBoxLayout(historyTab);
historyLayout->setContentsMargins(0, 4, 0, 0);
historyLayout->setSpacing(4);
m_historyEdit = new QPlainTextEdit(historyTab);
m_historyEdit->setReadOnly(true);
m_historyEdit->setMaximumHeight(220);
m_historyEdit->setLineWrapMode(QPlainTextEdit::NoWrap);
QFont mono("Monospace");
mono.setStyleHint(QFont::Monospace);
mono.setPointSize(9);
m_historyEdit->setFont(mono);
historyLayout->addWidget(m_historyEdit);
auto *historyBtnRow = new QHBoxLayout();
auto *clearHistBtn = new QPushButton(tr("Verlauf leeren"), historyTab);
clearHistBtn->setToolTip(tr("Nur den Verlauf dieses Tags leeren (Panel bleibt bestehen)"));
connect(clearHistBtn, &QPushButton::clicked, this, &TagPanel::clearHistory);
historyBtnRow->addStretch();
historyBtnRow->addWidget(clearHistBtn);
historyLayout->addLayout(historyBtnRow);
m_tabs->addTab(historyTab, tr("Verlauf"));
layout->addWidget(m_tabs);
auto *btnRow = new QHBoxLayout();
btnRow->addStretch();
auto *copyBtn = new QPushButton(tr("📋 Copy"), this);
copyBtn->setToolTip(tr("Copy current tag values to clipboard"));
copyBtn->setToolTip(tr("Copy the active tab's content to clipboard"));
copyBtn->setMaximumWidth(90);
connect(copyBtn, &QPushButton::clicked, this, &TagPanel::copyToClipboard);
btnRow->addWidget(copyBtn);
@@ -40,6 +82,8 @@ TagPanel::TagPanel(const QString &tag, QWidget *parent)
void TagPanel::update(const QString &value)
{
appendHistory(value);
static const QRegularExpression kvRe(R"((\w+)=(\S+))");
if (kvRe.match(value).hasMatch()) {
parseKeyValue(value);
@@ -52,6 +96,31 @@ void TagPanel::update(const QString &value)
}
}
void TagPanel::appendHistory(const QString &value)
{
const QString ts = QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
m_historyEdit->appendPlainText(QStringLiteral("[%1] %2").arg(ts, value));
m_historyEdit->verticalScrollBar()->setValue(
m_historyEdit->verticalScrollBar()->maximum());
++m_historyCount;
if (m_historyCount > kMaxHistoryEntries) {
// Drop the oldest entry (topmost line) to keep memory use bounded
// for very chatty or long-running tags.
QTextCursor cursor(m_historyEdit->document());
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor);
cursor.removeSelectedText();
--m_historyCount;
}
}
void TagPanel::clearHistory()
{
m_historyEdit->clear();
m_historyCount = 0;
}
void TagPanel::parseKeyValue(const QString &value)
{
static const QRegularExpression kvRe(R"((\w+)=(\S+))");
@@ -124,6 +193,13 @@ void TagPanel::copyToClipboard()
QStringList lines;
lines << QStringLiteral("[%1]").arg(m_tag);
if (m_tabs->currentIndex() == 1) {
// "Verlauf" tab active - copy the full timestamped history as-is.
QApplication::clipboard()->setText(
lines.join('\n') + '\n' + m_historyEdit->toPlainText());
return;
}
if (m_table->isVisible()) {
QString lastKey;
for (int r = 0; r < m_table->rowCount(); ++r) {