Add async auto-refresh with change detection and self-test harness

BBB
This commit is contained in:
sysadmin
2026-02-07 05:46:01 -07:00
parent 6232577f87
commit 60fda32af0
12 changed files with 406 additions and 68 deletions

View File

@@ -27,6 +27,7 @@ static constexpr int IND_HEX_DIM = 9;
static constexpr int IND_BASE_ADDR = 10; // Green color for base address
static constexpr int IND_HOVER_SPAN = 11; // Blue text on hover (link-like)
static constexpr int IND_CMD_PILL = 12; // Rounded chip behind command row spans
static constexpr int IND_DATA_CHANGED = 13; // Amber text for changed data values
static QString g_fontName = "Consolas";
@@ -168,6 +169,12 @@ void RcxEditor::setupScintilla() {
m_sci->SendScintilla(QsciScintillaBase::SCI_INDICSETUNDER,
IND_CMD_PILL, (long)1);
// Data-changed indicator — amber text for values that changed since last refresh
m_sci->SendScintilla(QsciScintillaBase::SCI_INDICSETSTYLE,
IND_DATA_CHANGED, 17 /*INDIC_TEXTFORE*/);
m_sci->SendScintilla(QsciScintillaBase::SCI_INDICSETFORE,
IND_DATA_CHANGED, QColor("#E5A00D"));
}
void RcxEditor::setupLexer() {
@@ -321,6 +328,7 @@ void RcxEditor::applyDocument(const ComposeResult& result) {
applyMarkers(result.meta);
applyFoldLevels(result.meta);
applyHexDimming(result.meta);
applyDataChangedHighlight(result.meta);
applyCommandRowPills();
// Reset hint line - applySelectionOverlay will repaint indicators
@@ -404,7 +412,7 @@ void RcxEditor::fillIndicatorCols(int indic, int line, int colA, int colB) {
void RcxEditor::applyHexDimming(const QVector<LineMeta>& meta) {
m_sci->SendScintilla(QsciScintillaBase::SCI_SETINDICATORCURRENT, IND_HEX_DIM);
for (int i = 0; i < meta.size(); i++) {
if (meta[i].nodeKind == NodeKind::Padding) {
if (isHexPreview(meta[i].nodeKind)) {
long pos, len; lineRangeNoEol(m_sci, i, pos, len);
if (len > 0)
m_sci->SendScintilla(QsciScintillaBase::SCI_INDICATORFILLRANGE, pos, len);
@@ -544,6 +552,20 @@ static QString getLineText(QsciScintilla* sci, int line) {
return text;
}
void RcxEditor::applyDataChangedHighlight(const QVector<LineMeta>& meta) {
for (int i = 0; i < meta.size(); i++) {
if (!meta[i].dataChanged) continue;
if (isSyntheticLine(meta[i])) continue;
QString lineText = getLineText(m_sci, i);
int typeW = meta[i].effectiveTypeW;
int nameW = meta[i].effectiveNameW;
ColumnSpan vs = valueSpan(meta[i], lineText.size(), typeW, nameW);
if (vs.valid)
fillIndicatorCols(IND_DATA_CHANGED, i, vs.start, vs.end);
}
}
void RcxEditor::applyBaseAddressColoring(const QVector<LineMeta>& meta) {
if (meta.isEmpty() || meta[0].lineKind != LineKind::CommandRow) return;
@@ -609,16 +631,20 @@ static ColumnSpan headerNameSpan(const LineMeta& lm, const QString& lineText) {
int ind = kFoldCol + lm.depth * 3;
int typeW = lm.effectiveTypeW;
int nameW = lm.effectiveNameW;
int nameStart = ind + typeW + kSepWidth;
int nameEnd = nameStart + nameW;
// Clamp to line length
if (nameStart >= lineText.size()) return {};
if (nameEnd > lineText.size()) nameEnd = lineText.size();
// Name ends before " {" suffix (expanded) or at line end (collapsed)
int nameEnd = lineText.size();
if (lineText.endsWith(QStringLiteral(" {")))
nameEnd = lineText.size() - 2;
if (nameEnd <= nameStart) return {};
// Don't allow editing array element names like "[0]", "[1]", etc.
QString name = lineText.mid(nameStart, nameEnd - nameStart).trimmed();
if (name.isEmpty()) return {};
if (name.startsWith('[') && name.endsWith(']'))
return {};
@@ -1678,7 +1704,7 @@ void RcxEditor::applyHoverCursor() {
bool inHexDataArea = false;
uint64_t hoverNodeId = 0;
if (hoverLine >= 0 && hoverLine < m_meta.size()
&& m_meta[hoverLine].nodeKind == NodeKind::Padding) {
&& isHexPreview(m_meta[hoverLine].nodeKind)) {
hoverNodeId = m_meta[hoverLine].nodeId;
if (hoverNodeId != 0 && h.col >= 0) {
int ind = kFoldCol + m_meta[hoverLine].depth * 3;