Skip to content

Commit

Permalink
cabana: miscellaneous bug fixes and enhancements (#34297)
Browse files Browse the repository at this point in the history
* toHexString

* use QToolBar

* fix incorrect groove rect

* limit CAN_MAX_DATA_BYTES

* add series type selector to chart toolbar

* dim inactive messages

* rename

* add help to chart

* cleanup
  • Loading branch information
deanlee authored Dec 21, 2024
1 parent 484b96f commit 9e8815d
Show file tree
Hide file tree
Showing 15 changed files with 125 additions and 99 deletions.
2 changes: 1 addition & 1 deletion tools/cabana/binaryview.cc
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
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));
painter->setPen(option.palette.color(bin_view->is_message_active ? QPalette::Normal : QPalette::Disabled, color_role));
}

if (item->sigs.size() > 1) {
Expand Down
7 changes: 6 additions & 1 deletion tools/cabana/binaryview.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ class BinaryView : public QTableView {
void setMessage(const MessageId &message_id);
void highlight(const cabana::Signal *sig);
QSet<const cabana::Signal*> getOverlappingSignals() const;
inline void updateState() { model->updateState(); }
void updateState() { model->updateState(); }
void paintEvent(QPaintEvent *event) override {
is_message_active = can->isMessageActive(model->msg_id);
QTableView::paintEvent(event);
}
QSize minimumSizeHint() const override;
void setHeatmapLiveMode(bool live) { model->heatmap_live_mode = live; updateState(); }

Expand All @@ -93,6 +97,7 @@ class BinaryView : public QTableView {
QModelIndex anchor_index;
BinaryViewModel *model;
BinaryItemDelegate *delegate;
bool is_message_active = false;
const cabana::Signal *resize_sig = nullptr;
const cabana::Signal *hovered_sig = nullptr;
friend class BinaryItemDelegate;
Expand Down
2 changes: 2 additions & 0 deletions tools/cabana/chart/chart.cc
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,8 @@ void ChartView::setSeriesType(SeriesType type) {
}
updateSeriesPoints();
updateTitle();

menu->actions()[(int)type]->setChecked(true);
}
}

Expand Down
41 changes: 30 additions & 11 deletions tools/cabana/chart/chartswidget.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QFrame(parent) {
main_layout->setSpacing(0);

// toolbar
QToolBar *toolbar = new QToolBar(tr("Charts"), this);
toolbar = new QToolBar(tr("Charts"), this);
int icon_size = style()->pixelMetric(QStyle::PM_SmallIconSize);
toolbar->setIconSize({icon_size, icon_size});

Expand All @@ -34,6 +34,21 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QFrame(parent) {
toolbar->addWidget(title_label = new QLabel());
title_label->setContentsMargins(0, 0, style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing), 0);

auto chart_type_action = toolbar->addAction("");
QMenu *chart_type_menu = new QMenu(this);
auto types = std::array{tr("Line"), tr("Step"), tr("Scatter")};
for (int i = 0; i < types.size(); ++i) {
QString type_text = types[i];
chart_type_menu->addAction(type_text, this, [=]() {
settings.chart_series_type = i;
chart_type_action->setText("Type: " + type_text);
settingChanged();
});
}
chart_type_action->setText("Type: " + types[settings.chart_series_type]);
chart_type_action->setMenu(chart_type_menu);
qobject_cast<QToolButton *>(toolbar->widgetForAction(chart_type_action))->setPopupMode(QToolButton::InstantPopup);

QMenu *menu = new QMenu(this);
for (int i = 0; i < MAX_COLUMN_COUNT; ++i) {
menu->addAction(tr("%1").arg(i + 1), [=]() { setColumnCount(i + 1); });
Expand All @@ -42,13 +57,13 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QFrame(parent) {
columns_action->setMenu(menu);
qobject_cast<QToolButton*>(toolbar->widgetForAction(columns_action))->setPopupMode(QToolButton::InstantPopup);

QLabel *stretch_label = new QLabel(this);
stretch_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
toolbar->addWidget(stretch_label);
QWidget *spacer = new QWidget(this);
spacer->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
toolbar->addWidget(spacer);

range_lb_action = toolbar->addWidget(range_lb = new QLabel(this));
range_slider = new LogSlider(1000, Qt::Horizontal, this);
range_slider->setMaximumWidth(200);
range_slider->setFixedWidth(150 * qApp->devicePixelRatio());
range_slider->setToolTip(tr("Set the chart range"));
range_slider->setRange(1, settings.max_cached_minutes * 60);
range_slider->setSingleStep(1);
Expand Down Expand Up @@ -121,10 +136,12 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QFrame(parent) {
setIsDocked(true);
newTab();
qApp->installEventFilter(this);

setWhatsThis(tr(R"(
<b>Chart view</b><br />
<!-- TODO: add descprition here -->
<b>Chart View</b><br />
<b>Click</b>: Click to seek to a corresponding time.<br />
<b>Drag</b>: Zoom into the chart.<br />
<b>Shift + Drag</b>: Scrub through the chart to view values.<br />
<b>Right Mouse</b>: Open the context menu.<br />
)"));
}

Expand Down Expand Up @@ -219,7 +236,7 @@ void ChartsWidget::setIsDocked(bool docked) {

void ChartsWidget::updateToolBar() {
title_label->setText(tr("Charts: %1").arg(charts.size()));
columns_action->setText(tr("Column: %1").arg(column_count));
columns_action->setText(tr("Columns: %1").arg(column_count));
range_lb->setText(utils::formatSeconds(max_chart_range));

bool is_zoomed = can->timeRange().has_value();
Expand All @@ -241,7 +258,9 @@ void ChartsWidget::settingChanged() {
c->setTheme(theme);
}
}
range_slider->setRange(1, settings.max_cached_minutes * 60);
if (range_slider->maximum() != settings.max_cached_minutes * 60) {
range_slider->setRange(1, settings.max_cached_minutes * 60);
}
for (auto c : charts) {
c->setFixedHeight(settings.chart_height);
c->setSeriesType((SeriesType)settings.chart_series_type);
Expand Down Expand Up @@ -380,7 +399,7 @@ void ChartsWidget::doAutoScroll() {
}

QSize ChartsWidget::minimumSizeHint() const {
return QSize(CHART_MIN_WIDTH, QWidget::minimumSizeHint().height());
return QSize(CHART_MIN_WIDTH * 1.5 * qApp->devicePixelRatio(), QWidget::minimumSizeHint().height());
}

void ChartsWidget::newChart() {
Expand Down
2 changes: 2 additions & 0 deletions tools/cabana/chart/chartswidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <QLabel>
#include <QScrollArea>
#include <QTimer>
#include <QToolBar>
#include <QUndoCommand>
#include <QUndoStack>

Expand Down Expand Up @@ -88,6 +89,7 @@ public slots:
bool is_docked = true;
ToolButton *dock_btn;

QToolBar *toolbar;
QAction *undo_zoom_action;
QAction *redo_zoom_action;
QAction *reset_zoom_action;
Expand Down
4 changes: 2 additions & 2 deletions tools/cabana/dbc/dbc.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@
#include <QMetaType>
#include <QString>


const QString UNTITLED = "untitled";
const QString DEFAULT_NODE_NAME = "XXX";
constexpr int CAN_MAX_DATA_BYTES = 64;

struct MessageId {
uint8_t source = 0;
uint32_t address = 0;

QString toString() const {
return QString("%1:%2").arg(source).arg(address, 1, 16);
return QString("%1:%2").arg(source).arg(QString::number(address, 16).toUpper());
}

bool operator==(const MessageId &other) const {
Expand Down
3 changes: 1 addition & 2 deletions tools/cabana/detailwidget.cc
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,7 @@ EditMessageDialog::EditMessageDialog(const MessageId &msg_id, const QString &tit
name_edit->setValidator(new NameValidator(name_edit));

form_layout->addRow(tr("Size"), size_spin = new QSpinBox(this));
// TODO: limit the maximum?
size_spin->setMinimum(1);
size_spin->setRange(1, CAN_MAX_DATA_BYTES);
size_spin->setValue(size);

form_layout->addRow(tr("Node"), node = new QLineEdit(this));
Expand Down
23 changes: 4 additions & 19 deletions tools/cabana/messageswidget.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,6 @@

#include "tools/cabana/commands.h"

static bool isMessageActive(const MessageId &id) {
if (id.source == INVALID_SOURCE) {
return false;
}
// Check if the message is active based on time difference and frequency
const auto &m = can->lastMessage(id);
float delta = can->currentSec() - m.ts;

if (m.freq < std::numeric_limits<double>::epsilon()) {
return delta < 1.5;
}

return delta < (5.0 / m.freq) + (1.0 / settings.fps);
}

MessagesWidget::MessagesWidget(QWidget *parent) : menu(new QMenu(this)), QWidget(parent) {
QVBoxLayout *main_layout = new QVBoxLayout(this);
main_layout->setContentsMargins(0, 0, 0, 0);
Expand Down Expand Up @@ -207,7 +192,7 @@ QVariant MessageListModel::data(const QModelIndex &index, int role) const {
switch (index.column()) {
case Column::NAME: return item.name;
case Column::SOURCE: return item.id.source != INVALID_SOURCE ? QString::number(item.id.source) : NA;
case Column::ADDRESS: return QString::number(item.id.address, 16);
case Column::ADDRESS: return toHexString(item.id.address);
case Column::NODE: return item.node;
case Column::FREQ: return item.id.source != INVALID_SOURCE ? getFreq(can->lastMessage(item.id).freq) : NA;
case Column::COUNT: return item.id.source != INVALID_SOURCE ? QString::number(can->lastMessage(item.id).count) : NA;
Expand Down Expand Up @@ -300,7 +285,7 @@ bool MessageListModel::match(const MessageListModel::Item &item) {
match = parseRange(txt, item.id.source);
break;
case Column::ADDRESS:
match = QString::number(item.id.address, 16).contains(txt, Qt::CaseInsensitive);
match = toHexString(item.id.address).contains(txt, Qt::CaseInsensitive);
match = match || parseRange(txt, item.id.address, 16);
break;
case Column::NODE:
Expand Down Expand Up @@ -335,7 +320,7 @@ bool MessageListModel::filterAndSort() {
std::vector<Item> items;
items.reserve(all_messages.size());
for (const auto &id : all_messages) {
if (show_inactive_messages || isMessageActive(id)) {
if (show_inactive_messages || can->isMessageActive(id)) {
auto msg = dbc()->msg(id);
Item item = {.id = id,
.name = msg ? msg->name : UNTITLED,
Expand Down Expand Up @@ -378,7 +363,7 @@ void MessageListModel::sort(int column, Qt::SortOrder order) {

void MessageView::drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {
const auto &item = ((MessageListModel*)model())->items_[index.row()];
if (!isMessageActive(item.id)) {
if (!can->isMessageActive(item.id)) {
QStyleOptionViewItem custom_option = option;
custom_option.palette.setBrush(QPalette::Text, custom_option.palette.color(QPalette::Disabled, QPalette::Text));
auto color = QApplication::palette().color(QPalette::HighlightedText);
Expand Down
5 changes: 0 additions & 5 deletions tools/cabana/settings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,6 @@ SettingsDlg::SettingsDlg(QWidget *parent) : QDialog(parent) {

groupbox = new QGroupBox("Chart");
form_layout = new QFormLayout(groupbox);
form_layout->addRow(tr("Default Series Type"), chart_series_type = new QComboBox(this));
chart_series_type->addItems({tr("Line"), tr("Step Line"), tr("Scatter")});
chart_series_type->setCurrentIndex(settings.chart_series_type);

form_layout->addRow(tr("Chart Height"), chart_height = new QSpinBox(this));
chart_height->setRange(100, 500);
chart_height->setSingleStep(10);
Expand Down Expand Up @@ -132,7 +128,6 @@ void SettingsDlg::save() {
}
settings.fps = fps->value();
settings.max_cached_minutes = cached_minutes->value();
settings.chart_series_type = chart_series_type->currentIndex();
settings.chart_height = chart_height->value();
settings.log_livestream = log_livestream->isChecked();
settings.log_path = log_path->text();
Expand Down
2 changes: 1 addition & 1 deletion tools/cabana/signalview.cc
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ QWidget *SignalItemDelegate::createEditor(QWidget *parent, const QStyleOptionVie
} else if (item->type == SignalModel::Item::Size) {
QSpinBox *spin = new QSpinBox(parent);
spin->setFrame(false);
spin->setRange(1, 64);
spin->setRange(1, CAN_MAX_DATA_BYTES);
return spin;
} else if (item->type == SignalModel::Item::SignalType) {
QComboBox *c = new QComboBox(parent);
Expand Down
15 changes: 15 additions & 0 deletions tools/cabana/streams/abstractstream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,21 @@ const CanData &AbstractStream::lastMessage(const MessageId &id) const {
return it != last_msgs.end() ? it->second : empty_data;
}

bool AbstractStream::isMessageActive(const MessageId &id) const {
if (id.source == INVALID_SOURCE) {
return false;
}
// Check if the message is active based on time difference and frequency
const auto &m = lastMessage(id);
float delta = currentSec() - m.ts;

if (m.freq < std::numeric_limits<double>::epsilon()) {
return delta < 1.5;
}

return delta < (5.0 / m.freq) + (1.0 / settings.fps);
}

void AbstractStream::updateLastMsgsTo(double sec) {
std::lock_guard lk(mutex_);
current_sec_ = sec;
Expand Down
1 change: 1 addition & 0 deletions tools/cabana/streams/abstractstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class AbstractStream : public QObject {
inline double toSeconds(uint64_t mono_time) const { return std::max(0.0, (mono_time - beginMonoTime()) / 1e9); }

inline const std::unordered_map<MessageId, CanData> &lastMessages() const { return last_msgs; }
bool isMessageActive(const MessageId &id) const;
inline const MessageEventsMap &eventsMap() const { return events_; }
inline const std::vector<const CanEvent *> &allEvents() const { return all_events_; }
const CanData &lastMessage(const MessageId &id) const;
Expand Down
1 change: 1 addition & 0 deletions tools/cabana/utils/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,4 @@ public slots:

int num_decimals(double num);
QString signalToolTip(const cabana::Signal *sig);
inline QString toHexString(int value) { return QString("0x%1").arg(QString::number(value, 16).toUpper(), 2, '0'); }
Loading

0 comments on commit 9e8815d

Please sign in to comment.