From e7743b6acdf247d68f36fe6dc9f0492eee12cc8b Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Fri, 2 Jun 2023 01:36:40 +0800 Subject: [PATCH] cabana: support displaying&editing overlapping signals in the binary view (#28359) old-commit-hash: 2373f785560be95aa9a64e949466cf0929f7e6f9 --- tools/cabana/binaryview.cc | 93 +++++++++++++++++++++----------------- tools/cabana/binaryview.h | 6 +-- 2 files changed, 54 insertions(+), 45 deletions(-) diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc index 3a03ee0b70..50f66e5182 100644 --- a/tools/cabana/binaryview.cc +++ b/tools/cabana/binaryview.cc @@ -277,8 +277,12 @@ void BinaryViewModel::refresh() { } if (j == start) sig->is_little_endian ? items[idx].is_lsb = true : items[idx].is_msb = true; if (j == end) sig->is_little_endian ? items[idx].is_msb = true : items[idx].is_lsb = true; - items[idx].bg_color = getColor(sig); - items[idx].sigs.push_back(sig); + + auto &sigs = items[idx].sigs; + sigs.push_back(sig); + if (sigs.size() > 1) { + std::sort(sigs.begin(), sigs.end(), [](auto l, auto r) { return l->size > r->size; }); + } } } } else { @@ -353,15 +357,11 @@ BinaryItemDelegate::BinaryItemDelegate(QObject *parent) : QStyledItemDelegate(pa hex_font.setBold(true); } -bool BinaryItemDelegate::isSameColor(const QModelIndex &index, int dx, int dy) const { - QModelIndex index2 = index.sibling(index.row() + dy, index.column() + dx); - if (!index2.isValid()) { - return false; - } - auto color1 = ((const BinaryViewModel::Item *)index.internalPointer())->bg_color; - auto color2 = ((const BinaryViewModel::Item *)index2.internalPointer())->bg_color; - // Ignore alpha - return (color1.red() == color2.red()) && (color2.green() == color2.green()) && (color1.blue() == color2.blue()); +bool BinaryItemDelegate::hasSignal(const QModelIndex &index, int dx, int dy, const cabana::Signal *sig) const { + if (!index.isValid()) return false; + auto model = (const BinaryViewModel*)(index.model()); + int idx = (index.row() + dy) * model->columnCount() + index.column() + dx; + return (idx >=0 && idx < model->items.size()) ? model->items[idx].sigs.contains(sig) : false; } void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { @@ -370,28 +370,32 @@ void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op painter->save(); if (index.column() == 8) { - painter->setFont(hex_font); - painter->fillRect(option.rect, item->bg_color); + if (item->valid) { + painter->setFont(hex_font); + painter->fillRect(option.rect, item->bg_color); + } } else if (option.state & QStyle::State_Selected) { painter->fillRect(option.rect, selection_color); painter->setPen(option.palette.color(QPalette::BrightText)); - } else if (!bin_view->selectionModel()->hasSelection() || !item->sigs.contains(bin_view->resize_sig)) { // not resizing - QColor bg = item->bg_color; - if (bin_view->hovered_sig && item->sigs.contains(bin_view->hovered_sig)) { - bg.setAlpha(255); - painter->fillRect(option.rect, bg.darker(125)); // 4/5x brightness - painter->setPen(option.palette.color(QPalette::BrightText)); - } else { - if (item->sigs.size() > 0) { - drawBorder(painter, option, index); - bg.setAlpha(std::max(50, bg.alpha())); + } else if (!bin_view->selectionModel()->hasSelection() || !item->sigs.contains(bin_view->resize_sig)) { // not resizing + if (item->sigs.size() > 0) { + for (auto &s : item->sigs) { + if (s == bin_view->hovered_sig) { + painter->fillRect(option.rect, getColor(bin_view->hovered_sig).darker(125)); // 4/5x brightness + } else { + drawSignalCell(painter, option, index, s); + } } - painter->fillRect(option.rect, bg); - painter->setPen(option.palette.color(QPalette::Text)); + } else if (item->valid) { + painter->fillRect(option.rect, item->bg_color); } + auto color_role = item->sigs.contains(bin_view->hovered_sig) ? QPalette::BrightText : QPalette::Text; + painter->setPen(option.palette.color(color_role)); } - if (!item->valid) { + if (item->sigs.size() > 1) { + painter->fillRect(option.rect, QBrush(Qt::darkGray, Qt::Dense7Pattern)); + } else if (!item->valid) { painter->fillRect(option.rect, QBrush(Qt::darkGray, Qt::BDiagPattern)); } painter->drawText(option.rect, Qt::AlignCenter, item->val); @@ -403,44 +407,49 @@ void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op } // Draw border on edge of signal -void BinaryItemDelegate::drawBorder(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { - auto item = (const BinaryViewModel::Item *)index.internalPointer(); - QColor border_color = item->bg_color; - border_color.setAlphaF(1.0); - - bool draw_left = !isSameColor(index, -1, 0); - bool draw_top = !isSameColor(index, 0, -1); - bool draw_right = !isSameColor(index, 1, 0); - bool draw_bottom = !isSameColor(index, 0, 1); +void BinaryItemDelegate::drawSignalCell(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index, const cabana::Signal *sig) const { + bool draw_left = !hasSignal(index, -1, 0, sig); + bool draw_top = !hasSignal(index, 0, -1, sig); + bool draw_right = !hasSignal(index, 1, 0, sig); + bool draw_bottom = !hasSignal(index, 0, 1, sig); const int spacing = 2; QRect rc = option.rect.adjusted(draw_left * 3, draw_top * spacing, draw_right * -3, draw_bottom * -spacing); QRegion subtract; if (!draw_top) { - if (!draw_left && !isSameColor(index, -1, -1)) { + if (!draw_left && !hasSignal(index, -1, -1, sig)) { subtract += QRect{rc.left(), rc.top(), 3, spacing}; - } else if (!draw_right && !isSameColor(index, 1, -1)) { + } else if (!draw_right && !hasSignal(index, 1, -1, sig)) { subtract += QRect{rc.right() - 2, rc.top(), 3, spacing}; } } if (!draw_bottom) { - if (!draw_left && !isSameColor(index, -1, 1)) { + if (!draw_left && !hasSignal(index, -1, 1, sig)) { subtract += QRect{rc.left(), rc.bottom() - (spacing - 1), 3, spacing}; - } else if (!draw_right && !isSameColor(index, 1, 1)) { + } else if (!draw_right && !hasSignal(index, 1, 1, sig)) { subtract += QRect{rc.right() - 2, rc.bottom() - (spacing - 1), 3, spacing}; } } + painter->setClipRegion(QRegion(rc).subtracted(subtract)); - painter->setPen(QPen(border_color, 1)); + auto item = (const BinaryViewModel::Item *)index.internalPointer(); + auto sig_color = getColor(sig); + QColor color = sig_color; + color.setAlpha(item->bg_color.alpha()); + painter->fillRect(rc, Qt::white); + painter->fillRect(rc, color); + + color = sig_color.darker(125); + painter->setPen(QPen(color, 1)); if (draw_left) painter->drawLine(rc.topLeft(), rc.bottomLeft()); if (draw_right) painter->drawLine(rc.topRight(), rc.bottomRight()); if (draw_bottom) painter->drawLine(rc.bottomLeft(), rc.bottomRight()); if (draw_top) painter->drawLine(rc.topLeft(), rc.topRight()); - painter->setClipRegion(QRegion(rc).subtracted(subtract)); if (!subtract.isEmpty()) { // fill gaps inside corners. - painter->setPen(QPen(border_color, 2, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin)); + painter->setPen(QPen(color, 2, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin)); for (auto &r : subtract) { painter->drawRect(r); } diff --git a/tools/cabana/binaryview.h b/tools/cabana/binaryview.h index f80b4520ed..baeb79cba7 100644 --- a/tools/cabana/binaryview.h +++ b/tools/cabana/binaryview.h @@ -14,8 +14,8 @@ public: BinaryItemDelegate(QObject *parent); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void setSelectionColor(const QColor &color) { selection_color = color; } - bool isSameColor(const QModelIndex &index, int dx, int dy) const; - void drawBorder(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + bool hasSignal(const QModelIndex &index, int dx, int dy, const cabana::Signal *sig) const; + void drawSignalCell(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index, const cabana::Signal *sig) const; QFont small_font, hex_font; QColor selection_color; @@ -40,7 +40,7 @@ public: } struct Item { - QColor bg_color = QColor(102, 86, 169, 0); + QColor bg_color = QColor(102, 86, 169, 255); bool is_msb = false; bool is_lsb = false; QString val;