cabana: support displaying&editing overlapping signals in the binary view (#28359)

pull/28343/head^2
Dean Lee 2 years ago committed by GitHub
parent 702e4120e6
commit 2373f78556
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 93
      tools/cabana/binaryview.cc
  2. 6
      tools/cabana/binaryview.h

@ -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 == 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; 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 { } else {
@ -353,15 +357,11 @@ BinaryItemDelegate::BinaryItemDelegate(QObject *parent) : QStyledItemDelegate(pa
hex_font.setBold(true); hex_font.setBold(true);
} }
bool BinaryItemDelegate::isSameColor(const QModelIndex &index, int dx, int dy) const { bool BinaryItemDelegate::hasSignal(const QModelIndex &index, int dx, int dy, const cabana::Signal *sig) const {
QModelIndex index2 = index.sibling(index.row() + dy, index.column() + dx); if (!index.isValid()) return false;
if (!index2.isValid()) { auto model = (const BinaryViewModel*)(index.model());
return false; int idx = (index.row() + dy) * model->columnCount() + index.column() + dx;
} return (idx >=0 && idx < model->items.size()) ? model->items[idx].sigs.contains(sig) : 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());
} }
void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { 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(); painter->save();
if (index.column() == 8) { if (index.column() == 8) {
painter->setFont(hex_font); if (item->valid) {
painter->fillRect(option.rect, item->bg_color); painter->setFont(hex_font);
painter->fillRect(option.rect, item->bg_color);
}
} else if (option.state & QStyle::State_Selected) { } else if (option.state & QStyle::State_Selected) {
painter->fillRect(option.rect, selection_color); painter->fillRect(option.rect, selection_color);
painter->setPen(option.palette.color(QPalette::BrightText)); painter->setPen(option.palette.color(QPalette::BrightText));
} else if (!bin_view->selectionModel()->hasSelection() || !item->sigs.contains(bin_view->resize_sig)) { // not resizing } else if (!bin_view->selectionModel()->hasSelection() || !item->sigs.contains(bin_view->resize_sig)) { // not resizing
QColor bg = item->bg_color; if (item->sigs.size() > 0) {
if (bin_view->hovered_sig && item->sigs.contains(bin_view->hovered_sig)) { for (auto &s : item->sigs) {
bg.setAlpha(255); if (s == bin_view->hovered_sig) {
painter->fillRect(option.rect, bg.darker(125)); // 4/5x brightness painter->fillRect(option.rect, getColor(bin_view->hovered_sig).darker(125)); // 4/5x brightness
painter->setPen(option.palette.color(QPalette::BrightText)); } else {
} else { drawSignalCell(painter, option, index, s);
if (item->sigs.size() > 0) { }
drawBorder(painter, option, index);
bg.setAlpha(std::max(50, bg.alpha()));
} }
painter->fillRect(option.rect, bg); } else if (item->valid) {
painter->setPen(option.palette.color(QPalette::Text)); 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->fillRect(option.rect, QBrush(Qt::darkGray, Qt::BDiagPattern));
} }
painter->drawText(option.rect, Qt::AlignCenter, item->val); 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 // Draw border on edge of signal
void BinaryItemDelegate::drawBorder(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { void BinaryItemDelegate::drawSignalCell(QPainter *painter, const QStyleOptionViewItem &option,
auto item = (const BinaryViewModel::Item *)index.internalPointer(); const QModelIndex &index, const cabana::Signal *sig) const {
QColor border_color = item->bg_color; bool draw_left = !hasSignal(index, -1, 0, sig);
border_color.setAlphaF(1.0); bool draw_top = !hasSignal(index, 0, -1, sig);
bool draw_right = !hasSignal(index, 1, 0, sig);
bool draw_left = !isSameColor(index, -1, 0); bool draw_bottom = !hasSignal(index, 0, 1, sig);
bool draw_top = !isSameColor(index, 0, -1);
bool draw_right = !isSameColor(index, 1, 0);
bool draw_bottom = !isSameColor(index, 0, 1);
const int spacing = 2; const int spacing = 2;
QRect rc = option.rect.adjusted(draw_left * 3, draw_top * spacing, draw_right * -3, draw_bottom * -spacing); QRect rc = option.rect.adjusted(draw_left * 3, draw_top * spacing, draw_right * -3, draw_bottom * -spacing);
QRegion subtract; QRegion subtract;
if (!draw_top) { 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}; 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}; subtract += QRect{rc.right() - 2, rc.top(), 3, spacing};
} }
} }
if (!draw_bottom) { 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}; 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}; 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_left) painter->drawLine(rc.topLeft(), rc.bottomLeft());
if (draw_right) painter->drawLine(rc.topRight(), rc.bottomRight()); if (draw_right) painter->drawLine(rc.topRight(), rc.bottomRight());
if (draw_bottom) painter->drawLine(rc.bottomLeft(), rc.bottomRight()); if (draw_bottom) painter->drawLine(rc.bottomLeft(), rc.bottomRight());
if (draw_top) painter->drawLine(rc.topLeft(), rc.topRight()); if (draw_top) painter->drawLine(rc.topLeft(), rc.topRight());
painter->setClipRegion(QRegion(rc).subtracted(subtract));
if (!subtract.isEmpty()) { if (!subtract.isEmpty()) {
// fill gaps inside corners. // 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) { for (auto &r : subtract) {
painter->drawRect(r); painter->drawRect(r);
} }

@ -14,8 +14,8 @@ public:
BinaryItemDelegate(QObject *parent); BinaryItemDelegate(QObject *parent);
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void setSelectionColor(const QColor &color) { selection_color = color; } void setSelectionColor(const QColor &color) { selection_color = color; }
bool isSameColor(const QModelIndex &index, int dx, int dy) const; bool hasSignal(const QModelIndex &index, int dx, int dy, const cabana::Signal *sig) const;
void drawBorder(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; void drawSignalCell(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index, const cabana::Signal *sig) const;
QFont small_font, hex_font; QFont small_font, hex_font;
QColor selection_color; QColor selection_color;
@ -40,7 +40,7 @@ public:
} }
struct Item { struct Item {
QColor bg_color = QColor(102, 86, 169, 0); QColor bg_color = QColor(102, 86, 169, 255);
bool is_msb = false; bool is_msb = false;
bool is_lsb = false; bool is_lsb = false;
QString val; QString val;

Loading…
Cancel
Save