diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc index 4fc55077da..168edc75f4 100644 --- a/tools/cabana/binaryview.cc +++ b/tools/cabana/binaryview.cc @@ -3,7 +3,9 @@ #include #include #include +#include #include +#include #include "tools/cabana/canmessages.h" @@ -19,6 +21,7 @@ BinaryView::BinaryView(QWidget *parent) : QTableView(parent) { horizontalHeader()->hide(); verticalHeader()->setSectionResizeMode(QHeaderView::Stretch); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setMouseTracking(true); // replace selection model auto old_model = selectionModel(); @@ -30,6 +33,24 @@ BinaryView::BinaryView(QWidget *parent) : QTableView(parent) { }); } +void BinaryView::highlight(const Signal *sig) { + if (sig != hovered_sig) { + hovered_sig = sig; + model->dataChanged(model->index(0, 0), model->index(model->rowCount() - 1, model->columnCount() - 1)); + emit signalHovered(hovered_sig); + } +} + +void BinaryView::mouseMoveEvent(QMouseEvent *event) { + if (auto index = indexAt(event->pos()); index.isValid()) { + auto item = (BinaryViewModel::Item *)index.internalPointer(); + highlight(item->sig); + if (item->sig) + QToolTip::showText(event->globalPos(), item->sig->name.c_str(), this, rect()); + } + QTableView::mouseMoveEvent(event); +} + void BinaryView::mouseReleaseEvent(QMouseEvent *event) { QTableView::mouseReleaseEvent(event); @@ -40,6 +61,11 @@ void BinaryView::mouseReleaseEvent(QMouseEvent *event) { } } +void BinaryView::leaveEvent(QEvent *event) { + highlight(nullptr); + QTableView::leaveEvent(event); +} + void BinaryView::setMessage(const QString &message_id) { msg_id = message_id; model->setMessage(message_id); @@ -80,7 +106,8 @@ void BinaryViewModel::setMessage(const QString &message_id) { } else if (j == end) { sig.is_little_endian ? items[idx].is_msb = true : items[idx].is_lsb = true; } - items[idx].bg_color = QColor(getColor(i)); + items[idx].bg_color = getColor(i); + items[idx].sig = &dbc_msg->sigs[i]; } } } @@ -170,9 +197,17 @@ QSize BinaryItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { auto item = (const BinaryViewModel::Item *)index.internalPointer(); + BinaryView *bin_view = (BinaryView *)parent(); painter->save(); - // TODO: highlight signal cells on mouse over - painter->fillRect(option.rect, option.state & QStyle::State_Selected ? highlight_color : item->bg_color); + + // background + QColor bg_color = item->sig && bin_view->hoveredSignal() == item->sig ? hoverColor(item->bg_color) : item->bg_color; + if (option.state & QStyle::State_Selected) { + bg_color = highlight_color; + } + painter->fillRect(option.rect, bg_color); + + // text if (index.column() == 8) { painter->setFont(hex_font); } diff --git a/tools/cabana/binaryview.h b/tools/cabana/binaryview.h index 38f0ddf216..48eb5eff8a 100644 --- a/tools/cabana/binaryview.h +++ b/tools/cabana/binaryview.h @@ -37,6 +37,7 @@ public: bool is_msb = false; bool is_lsb = false; QString val = "0"; + const Signal *sig = nullptr; }; private: @@ -59,14 +60,21 @@ class BinaryView : public QTableView { public: BinaryView(QWidget *parent = nullptr); - void mouseReleaseEvent(QMouseEvent *event) override; void setMessage(const QString &message_id); void updateState(); + void highlight(const Signal *sig); + const Signal *hoveredSignal() const { return hovered_sig; } signals: void cellsSelected(int start_bit, int size); + void signalHovered(const Signal *sig); private: + void mouseMoveEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void leaveEvent(QEvent *event) override; + QString msg_id; BinaryViewModel *model; + const Signal *hovered_sig = nullptr; }; diff --git a/tools/cabana/canmessages.h b/tools/cabana/canmessages.h index 44131ad5c9..a468fb2956 100644 --- a/tools/cabana/canmessages.h +++ b/tools/cabana/canmessages.h @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -103,6 +104,12 @@ inline const QString &getColor(int i) { return SIGNAL_COLORS[i % std::size(SIGNAL_COLORS)]; } +inline QColor hoverColor(const QColor &color) { + QColor c = color.convertTo(QColor::Hsv); + c.setHsv(color.hue(), 180, 180); + return c; +} + // A global pointer referring to the unique CANMessages object extern CANMessages *can; extern Settings settings; diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index a92969d4d3..1f1b73638b 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -86,6 +86,8 @@ void DetailWidget::dbcMsgChanged() { QObject::connect(form, &SignalEdit::showFormClicked, this, &DetailWidget::showForm); QObject::connect(form, &SignalEdit::remove, this, &DetailWidget::removeSignal); QObject::connect(form, &SignalEdit::save, this, &DetailWidget::saveSignal); + QObject::connect(form, &SignalEdit::highlight, binary_view, &BinaryView::highlight); + QObject::connect(binary_view, &BinaryView::signalHovered, form, &SignalEdit::signalHovered); } msg_name = msg->name.c_str(); if (msg->size != can->lastMessage(msg_id).dat.size()) { diff --git a/tools/cabana/signaledit.cc b/tools/cabana/signaledit.cc index 050802d452..d5dccf0e6d 100644 --- a/tools/cabana/signaledit.cc +++ b/tools/cabana/signaledit.cc @@ -82,7 +82,7 @@ Signal SignalForm::getSignal() { // SignalEdit SignalEdit::SignalEdit(int index, const QString &msg_id, const Signal &sig, QWidget *parent) - : sig_name(sig.name.c_str()), QWidget(parent) { + : sig(&sig), form_idx(index), sig_name(sig.name.c_str()), QWidget(parent) { QVBoxLayout *main_layout = new QVBoxLayout(this); main_layout->setContentsMargins(0, 0, 0, 0); @@ -152,6 +152,21 @@ void SignalEdit::setFormVisible(bool visible) { icon->setText(visible ? "▼" : ">"); } +void SignalEdit::signalHovered(const Signal *s) { + auto color = sig == s ? hoverColor(getColor(form_idx)) : QColor(getColor(form_idx)); + title->setStyleSheet(QString("font-weight:bold; color:%1").arg(color.name())); +} + +void SignalEdit::enterEvent(QEvent *event) { + emit highlight(sig); + QWidget::enterEvent(event); +} + +void SignalEdit::leaveEvent(QEvent *event) { + emit highlight(nullptr); + QWidget::leaveEvent(event); +} + // AddSignalDialog AddSignalDialog::AddSignalDialog(const QString &id, int start_bit, int size, QWidget *parent) : QDialog(parent) { diff --git a/tools/cabana/signaledit.h b/tools/cabana/signaledit.h index f7611747ec..1213b3ec51 100644 --- a/tools/cabana/signaledit.h +++ b/tools/cabana/signaledit.h @@ -30,17 +30,24 @@ class SignalEdit : public QWidget { public: SignalEdit(int index, const QString &msg_id, const Signal &sig, QWidget *parent = nullptr); void setFormVisible(bool show); + void signalHovered(const Signal *sig); inline bool isFormVisible() const { return form_container->isVisible(); } QString sig_name; SignalForm *form; + int form_idx = 0; + const Signal *sig = nullptr; signals: + void highlight(const Signal *sig); void showChart(); void showFormClicked(); void remove(); void save(); protected: + void enterEvent(QEvent *event) override; + void leaveEvent(QEvent *event) override; + ElidedLabel *title; QWidget *form_container; QLabel *icon;