Files
uartscope/src/tagpanel.cpp
Dany Thinnes d3229c7b64 - Auto-scroll standard aktiv
- Tag-Filter wird gespeichert
- Tag Monitor kann bei einem Tag jetzt pro Key mehrere Werte in einer Tabelle anzeigen
- Bug für Clear behoben
2026-06-23 23:19:06 +02:00

145 lines
4.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "tagpanel.h"
#include <QHeaderView>
#include <QRegularExpression>
#include <QApplication>
#include <QClipboard>
TagPanel::TagPanel(const QString &tag, QWidget *parent)
: QGroupBox(QStringLiteral("[%1]").arg(tag), parent)
, m_tag(tag)
{
auto *layout = new QVBoxLayout(this);
layout->setContentsMargins(6, 14, 6, 6);
layout->setSpacing(4);
m_table = new QTableWidget(0, 2, this);
m_table->setHorizontalHeaderLabels({tr("Key"), tr("Value")});
m_table->horizontalHeader()->setStretchLastSection(true);
m_table->verticalHeader()->hide();
m_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_table->setAlternatingRowColors(true);
m_table->setMaximumHeight(220);
m_table->verticalHeader()->setDefaultSectionSize(22);
layout->addWidget(m_table);
m_rawLabel = new QLabel(this);
m_rawLabel->setWordWrap(true);
m_rawLabel->setStyleSheet("font-family: monospace;");
m_rawLabel->hide();
layout->addWidget(m_rawLabel);
auto *btnRow = new QHBoxLayout();
btnRow->addStretch();
auto *copyBtn = new QPushButton(tr("📋 Copy"), this);
copyBtn->setToolTip(tr("Copy current tag values to clipboard"));
copyBtn->setMaximumWidth(90);
connect(copyBtn, &QPushButton::clicked, this, &TagPanel::copyToClipboard);
btnRow->addWidget(copyBtn);
layout->addLayout(btnRow);
}
void TagPanel::update(const QString &value)
{
static const QRegularExpression kvRe(R"((\w+)=(\S+))");
if (kvRe.match(value).hasMatch()) {
parseKeyValue(value);
m_rawLabel->hide();
m_table->show();
} else {
showRaw(value);
m_table->hide();
m_rawLabel->show();
}
}
void TagPanel::parseKeyValue(const QString &value)
{
static const QRegularExpression kvRe(R"((\w+)=(\S+))");
auto it = kvRe.globalMatch(value);
while (it.hasNext()) {
const auto match = it.next();
const QString key = match.captured(1);
const QString raw = match.captured(2);
// Split on ';' -> list of values. A plain (non-list) value yields
// a QStringList with exactly one element, which still goes through
// the same code path for consistency.
QStringList values = raw.split(';', Qt::SkipEmptyParts);
if (values.isEmpty())
values << raw; // preserve even an empty/odd value as-is
setKeyValues(key, values);
}
}
void TagPanel::setKeyValues(const QString &key, const QStringList &values)
{
const int newCount = values.size();
if (m_keyRanges.contains(key)) {
// Key already exists remove its current rows, then re-insert at
// the same starting position with the new row count.
const KeyRange old = m_keyRanges[key];
for (int i = 0; i < old.count; ++i)
m_table->removeRow(old.firstRow);
// Shift all OTHER key ranges that started after this one
for (auto it = m_keyRanges.begin(); it != m_keyRanges.end(); ++it) {
if (it.key() != key && it->firstRow > old.firstRow)
it->firstRow += (newCount - old.count);
}
int insertAt = old.firstRow;
for (int i = 0; i < newCount; ++i) {
m_table->insertRow(insertAt + i);
auto *keyItem = new QTableWidgetItem(i == 0 ? key : QString());
auto *valItem = new QTableWidgetItem(values[i]);
valItem->setBackground(QColor(0x2d, 0x5a, 0x2d)); // flash green on update
m_table->setItem(insertAt + i, 0, keyItem);
m_table->setItem(insertAt + i, 1, valItem);
}
m_keyRanges[key] = {insertAt, newCount};
} else {
// New key append at the bottom
const int insertAt = m_table->rowCount();
for (int i = 0; i < newCount; ++i) {
m_table->insertRow(insertAt + i);
auto *keyItem = new QTableWidgetItem(i == 0 ? key : QString());
auto *valItem = new QTableWidgetItem(values[i]);
valItem->setBackground(QColor(0x2d, 0x5a, 0x2d));
m_table->setItem(insertAt + i, 0, keyItem);
m_table->setItem(insertAt + i, 1, valItem);
}
m_keyRanges[key] = {insertAt, newCount};
}
}
void TagPanel::showRaw(const QString &value)
{
m_rawLabel->setText(value);
}
void TagPanel::copyToClipboard()
{
QStringList lines;
lines << QStringLiteral("[%1]").arg(m_tag);
if (m_table->isVisible()) {
QString lastKey;
for (int r = 0; r < m_table->rowCount(); ++r) {
const QString key = m_table->item(r, 0)->text();
const QString val = m_table->item(r, 1)->text();
if (!key.isEmpty()) {
lines << QStringLiteral(" %1 = %2").arg(key, val);
lastKey = key;
} else {
lines << QStringLiteral(" %1").arg(val); // continuation row
}
}
} else {
lines << QStringLiteral(" %1").arg(m_rawLabel->text());
}
QApplication::clipboard()->setText(lines.join('\n'));
}