diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc index d9b00f6882..120a85a330 100644 --- a/tools/cabana/binaryview.cc +++ b/tools/cabana/binaryview.cc @@ -293,7 +293,6 @@ void BinaryViewModel::updateState() { double max_f = 255.0; double factor = 0.25; double scaler = max_f / log2(1.0 + factor); - char hex[3] = {'\0'}; for (int i = 0; i < binary.size(); ++i) { for (int j = 0; j < 8; ++j) { auto &item = items[i * column_count + j]; @@ -305,9 +304,7 @@ void BinaryViewModel::updateState() { double alpha = std::clamp(offset + log2(1.0 + factor * (double)n / (double)last_msg.count) * scaler, min_f, max_f); item.bg_color.setAlpha(alpha); } - hex[0] = toHex(binary[i] >> 4); - hex[1] = toHex(binary[i] & 0xf); - items[i * column_count + 8].val = hex; + items[i * column_count + 8].val = toHex(binary[i]); items[i * column_count + 8].bg_color = last_msg.colors[i]; } for (int i = binary.size() * column_count; i < items.size(); ++i) { @@ -375,7 +372,7 @@ void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op bg.setAlpha(std::max(50, bg.alpha())); } painter->fillRect(option.rect, bg); - painter->setPen(Qt::black); + painter->setPen(option.palette.color(QPalette::Text)); } } diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index d895191d86..7982a5899c 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -25,11 +25,12 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QFrame(parent) { // toolbar QToolBar *toolbar = new QToolBar(tr("Charts"), this); - toolbar->setIconSize({16, 16}); + int icon_size = style()->pixelMetric(QStyle::PM_SmallIconSize); + toolbar->setIconSize({icon_size, icon_size}); QAction *new_plot_btn = toolbar->addAction(utils::icon("file-plus"), tr("New Plot")); toolbar->addWidget(title_label = new QLabel()); - title_label->setContentsMargins(0, 0, 12, 0); + title_label->setContentsMargins(0, 0, style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing), 0); QMenu *menu = new QMenu(this); for (int i = 0; i < MAX_COLUMN_COUNT; ++i) { @@ -77,8 +78,8 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QFrame(parent) { main_layout->addWidget(charts_scroll); // init settings - use_dark_theme = QApplication::style()->standardPalette().color(QPalette::WindowText).value() > - QApplication::style()->standardPalette().color(QPalette::Background).value(); + use_dark_theme = QApplication::palette().color(QPalette::WindowText).value() > + QApplication::palette().color(QPalette::Background).value(); column_count = std::clamp(settings.chart_column_count, 1, MAX_COLUMN_COUNT); max_chart_range = std::clamp(settings.chart_range, 1, settings.max_cached_minutes * 60); display_range = {0, max_chart_range}; @@ -322,7 +323,7 @@ ChartView::ChartView(QWidget *parent) : QChartView(nullptr, parent) { chart->setMargins({0, 0, 0, 0}); background = new QGraphicsRectItem(chart); - background->setBrush(Qt::white); + background->setBrush(QApplication::palette().color(QPalette::Base)); background->setPen(Qt::NoPen); background->setZValue(chart->zValue() - 1); @@ -443,10 +444,12 @@ void ChartView::manageSeries() { void ChartView::resizeEvent(QResizeEvent *event) { updatePlotArea(align_to); - int x = event->size().width() - close_btn_proxy->size().width() - 11; - close_btn_proxy->setPos(x, 8); - manage_btn_proxy->setPos(x - manage_btn_proxy->size().width() - 5, 8); - move_icon->setPos(11, 8); + int top_margin = style()->pixelMetric(QStyle::PM_LayoutTopMargin); + int spacing = style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing); + int x = event->size().width() - close_btn_proxy->size().width() - style()->pixelMetric(QStyle::PM_LayoutRightMargin); + close_btn_proxy->setPos(x, top_margin); + manage_btn_proxy->setPos(x - manage_btn_proxy->size().width() - spacing, top_margin); + move_icon->setPos(style()->pixelMetric(QStyle::PM_LayoutLeftMargin), top_margin); QChartView::resizeEvent(event); } diff --git a/tools/cabana/historylog.cc b/tools/cabana/historylog.cc index deee2f1724..57f65b97d8 100644 --- a/tools/cabana/historylog.cc +++ b/tools/cabana/historylog.cc @@ -15,8 +15,10 @@ QVariant HistoryLogModel::data(const QModelIndex &index, int role) const { return QString::number((m.mono_time / (double)1e9) - can->routeStartTime(), 'f', 2); } return show_signals ? QString::number(m.sig_values[index.column() - 1]) : toHex(m.data); - } else if (role == Qt::UserRole && index.column() == 1 && !show_signals) { + } else if (role == ColorsRole) { return QVariant::fromValue(m.colors); + } else if (role == BytesRole) { + return m.data; } return {}; } diff --git a/tools/cabana/mainwin.cc b/tools/cabana/mainwin.cc index 25e40e15aa..282a541244 100644 --- a/tools/cabana/mainwin.cc +++ b/tools/cabana/mainwin.cc @@ -58,6 +58,11 @@ MainWindow::MainWindow() : QMainWindow() { fingerprint_to_dbc = QJsonDocument::fromJson(json_file.readAll()); } + setStyleSheet(QString(R"(QMainWindow::separator { + width: %1px; /* when vertical */ + height: %1px; /* when horizontal */ + })").arg(style()->pixelMetric(QStyle::PM_SplitterWidth))); + QObject::connect(this, &MainWindow::showMessage, statusBar(), &QStatusBar::showMessage); QObject::connect(this, &MainWindow::updateProgressBar, this, &MainWindow::updateDownloadProgress); QObject::connect(messages_widget, &MessagesWidget::msgSelectionChanged, center_widget, &CenterWidget::setMessage); diff --git a/tools/cabana/messageswidget.cc b/tools/cabana/messageswidget.cc index cda3069ad9..b4a7ed7b34 100644 --- a/tools/cabana/messageswidget.cc +++ b/tools/cabana/messageswidget.cc @@ -129,7 +129,7 @@ QVariant MessageListModel::data(const QModelIndex &index, int role) const { case 4: return can_data.count; case 5: return toHex(can_data.dat); } - } else if (role == Qt::UserRole && index.column() == 5) { + } else if (role == ColorsRole) { QVector colors = can_data.colors; if (!suppressed_bytes.empty()) { for (int i = 0; i < colors.size(); i++) { @@ -139,6 +139,8 @@ QVariant MessageListModel::data(const QModelIndex &index, int role) const { } } return QVariant::fromValue(colors); + } else if (role == BytesRole) { + return can_data.dat; } return {}; } diff --git a/tools/cabana/signaledit.cc b/tools/cabana/signaledit.cc index d5cd4ae825..e425a13f82 100644 --- a/tools/cabana/signaledit.cc +++ b/tools/cabana/signaledit.cc @@ -322,19 +322,22 @@ void SignalItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op // color label auto bg_color = getColor(item->sig); - QRect rc{option.rect.left(), option.rect.top(), color_label_width, option.rect.height()}; + int h_margin = option.widget->style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1; + int v_margin = option.widget->style()->pixelMetric(QStyle::PM_FocusFrameVMargin); + QRect rc{option.rect.left() + h_margin, option.rect.top(), color_label_width, option.rect.height()}; painter->setPen(Qt::NoPen); painter->setBrush(item->highlight ? bg_color.darker(125) : bg_color); - painter->drawRoundedRect(rc.adjusted(0, 2, 0, -2), 3, 3); + painter->drawRoundedRect(rc.adjusted(0, v_margin, 0, -v_margin), 3, 3); painter->setPen(item->highlight ? Qt::white : Qt::black); painter->setFont(small_font); painter->drawText(rc, Qt::AlignCenter, QString::number(item->row() + 1)); // signal name painter->setFont(option.font); - painter->setPen((option.state & QStyle::State_Selected ? option.palette.highlightedText() : option.palette.text()).color()); + painter->setPen(option.palette.color(option.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text)); QString text = index.data(Qt::DisplayRole).toString(); - QRect text_rect = option.rect.adjusted(rc.width() + 6, 0, 0, 0); + QRect text_rect = option.rect; + text_rect.setLeft(rc.right() + h_margin * 2); text = painter->fontMetrics().elidedText(text, Qt::ElideRight, text_rect.width()); painter->drawText(text_rect, option.displayAlignment, text); painter->restore(); @@ -343,7 +346,7 @@ void SignalItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op if (option.state & QStyle::State_Selected) { painter->fillRect(option.rect, option.palette.highlight()); } - painter->setPen((option.state & QStyle::State_Selected ? option.palette.highlightedText() : option.palette.text()).color()); + painter->setPen(option.palette.color(option.state & QStyle::State_Selected ? QPalette::HighlightedText : QPalette::Text)); QRect rc = option.rect.adjusted(0, 0, -70, 0); auto text = painter->fontMetrics().elidedText(index.data(Qt::DisplayRole).toString(), Qt::ElideRight, rc.width()); painter->drawText(rc, Qt::AlignRight | Qt::AlignVCenter, text); @@ -442,8 +445,11 @@ void SignalView::rowsChanged() { if (!tree->indexWidget(index)) { QWidget *w = new QWidget(this); QHBoxLayout *h = new QHBoxLayout(w); - h->setContentsMargins(0, 2, 0, 2); - h->addStretch(1); + int v_margin = style()->pixelMetric(QStyle::PM_FocusFrameVMargin); + int h_margin = style()->pixelMetric(QStyle::PM_FocusFrameHMargin); + h->setContentsMargins(0, v_margin, -h_margin, v_margin); + h->setSpacing(style()->pixelMetric(QStyle::PM_ToolBarItemSpacing)); + h->addStretch(0); auto remove_btn = toolButton("x", tr("Remove signal")); auto plot_btn = toolButton("graph-up", ""); diff --git a/tools/cabana/util.cc b/tools/cabana/util.cc index 4f79f9a3ac..5e4f505d29 100644 --- a/tools/cabana/util.cc +++ b/tools/cabana/util.cc @@ -71,26 +71,26 @@ void ChangeTracker::clear() { MessageBytesDelegate::MessageBytesDelegate(QObject *parent) : QStyledItemDelegate(parent) { fixed_font = QFontDatabase::systemFont(QFontDatabase::FixedFont); + byte_width = QFontMetrics(fixed_font).width("00 "); } void MessageBytesDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { + auto colors = index.data(ColorsRole).value>(); + auto byte_list = index.data(BytesRole).toByteArray(); + + int v_margin = option.widget->style()->pixelMetric(QStyle::PM_FocusFrameVMargin); + int h_margin = option.widget->style()->pixelMetric(QStyle::PM_FocusFrameHMargin); + QRect rc{option.rect.left() + h_margin, option.rect.top() + v_margin, byte_width, option.rect.height() - 2 * v_margin}; + auto color_role = option.state & QStyle::State_Selected ? QPalette::HighlightedText: QPalette::Text; painter->setPen(option.palette.color(color_role)); painter->setFont(fixed_font); - int space = painter->boundingRect(option.rect, option.displayAlignment, " ").width(); - QRect pos = painter->boundingRect(option.rect, option.displayAlignment, "00").adjusted(0, 0, 2, 0); - pos.moveLeft(pos.x() + space); - int m = space / 2; - const QMargins margins(m, m, m, m); - - auto colors = index.data(Qt::UserRole).value>(); - auto byte_list = index.data(Qt::DisplayRole).toString().split(" "); for (int i = 0; i < byte_list.size(); ++i) { if (i < colors.size() && colors[i].alpha() > 0) { - painter->fillRect(pos.marginsAdded(margins), colors[i]); + painter->fillRect(rc, colors[i]); } - painter->drawText(pos, Qt::AlignCenter, byte_list[i]); - pos.moveLeft(pos.right() + space); + painter->drawText(rc, Qt::AlignCenter, toHex(byte_list[i])); + rc.moveLeft(rc.right() + 1); } } @@ -114,8 +114,8 @@ QValidator::State NameValidator::validate(QString &input, int &pos) const { namespace utils { QPixmap icon(const QString &id) { - static bool dark_theme = QApplication::style()->standardPalette().color(QPalette::WindowText).value() > - QApplication::style()->standardPalette().color(QPalette::Background).value(); + static bool dark_theme = QApplication::palette().color(QPalette::WindowText).value() > + QApplication::palette().color(QPalette::Background).value(); QPixmap pm; QString key = "bootstrap_" % id % (dark_theme ? "1" : "0"); if (!QPixmapCache::find(key, &pm)) { @@ -138,3 +138,13 @@ QToolButton *toolButton(const QString &icon, const QString &tooltip) { btn->setAutoRaise(true); return btn; }; + + +QString toHex(uint8_t byte) { + static std::array hex = []() { + std::array ret; + for (int i = 0; i < 256; ++i) ret[i] = QStringLiteral("%1").arg(i, 2, 16, QLatin1Char('0')).toUpper(); + return ret; + }(); + return hex[byte]; +} diff --git a/tools/cabana/util.h b/tools/cabana/util.h index b72ddfcaa0..5eb5c3c5aa 100644 --- a/tools/cabana/util.h +++ b/tools/cabana/util.h @@ -14,7 +14,6 @@ #include "tools/cabana/dbcmanager.h" using namespace dbcmanager; - class ChangeTracker { public: void compute(const QByteArray &dat, double ts, uint32_t freq); @@ -31,16 +30,22 @@ private: QByteArray prev_dat; }; +enum { + ColorsRole = Qt::UserRole + 1, + BytesRole = Qt::UserRole + 2 +}; + class MessageBytesDelegate : public QStyledItemDelegate { Q_OBJECT public: MessageBytesDelegate(QObject *parent); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; QFont fixed_font; + int byte_width; }; inline QString toHex(const QByteArray &dat) { return dat.toHex(' ').toUpper(); } -inline char toHex(uint value) { return "0123456789ABCDEF"[value & 0xF]; } +QString toHex(uint8_t byte); QColor getColor(const dbcmanager::Signal *sig); class NameValidator : public QRegExpValidator {