diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc index 16df867d56..9085bf310a 100644 --- a/tools/cabana/binaryview.cc +++ b/tools/cabana/binaryview.cc @@ -94,7 +94,7 @@ void BinaryView::addShortcuts() { QObject::connect(shortcut_plot_c, &QShortcut::activated, shortcut_plot, &QShortcut::activated); QObject::connect(shortcut_plot, &QShortcut::activated, [=]{ if (hovered_sig != nullptr) { - emit showChart(model->msg_id, hovered_sig, true, false); + emit showChart(*model->msg_id, hovered_sig, true, false); } }); } @@ -189,14 +189,14 @@ void BinaryView::leaveEvent(QEvent *event) { QTableView::leaveEvent(event); } -void BinaryView::setMessage(const QString &message_id) { +void BinaryView::setMessage(const MessageId &message_id) { model->msg_id = message_id; verticalScrollBar()->setValue(0); refresh(); } void BinaryView::refresh() { - if (model->msg_id.isEmpty()) return; + if (!model->msg_id) return; clearSelection(); anchor_index = QModelIndex(); @@ -231,7 +231,7 @@ std::tuple BinaryView::getSelection(QModelIndex index) { void BinaryViewModel::refresh() { beginResetModel(); items.clear(); - if ((dbc_msg = dbc()->msg(msg_id))) { + if ((dbc_msg = dbc()->msg(*msg_id))) { row_count = dbc_msg->size; items.resize(row_count * column_count); for (auto sig : dbc_msg->getSignals()) { @@ -250,7 +250,7 @@ void BinaryViewModel::refresh() { } } } else { - row_count = can->lastMessage(msg_id).dat.size(); + row_count = can->lastMessage(*msg_id).dat.size(); items.resize(row_count * column_count); } endResetModel(); @@ -259,7 +259,7 @@ void BinaryViewModel::refresh() { void BinaryViewModel::updateState() { auto prev_items = items; - const auto &last_msg = can->lastMessage(msg_id); + const auto &last_msg = can->lastMessage(*msg_id); const auto &binary = last_msg.dat; // data size may changed. diff --git a/tools/cabana/binaryview.h b/tools/cabana/binaryview.h index 7cf9a8081c..6743b6cfac 100644 --- a/tools/cabana/binaryview.h +++ b/tools/cabana/binaryview.h @@ -1,5 +1,7 @@ #pragma once +#include + #include #include #include @@ -46,7 +48,7 @@ public: }; std::vector items; - QString msg_id; + std::optional msg_id; const DBCMsg *dbc_msg = nullptr; int row_count = 0; const int column_count = 9; @@ -57,7 +59,7 @@ class BinaryView : public QTableView { public: BinaryView(QWidget *parent = nullptr); - void setMessage(const QString &message_id); + void setMessage(const MessageId &message_id); void highlight(const Signal *sig); QSet getOverlappingSignals() const; inline void updateState() { model->updateState(); } @@ -70,7 +72,7 @@ signals: void resizeSignal(const Signal *sig, int from, int size); void removeSignal(const Signal *sig); void editSignal(const Signal *origin_s, Signal &s); - void showChart(const QString &name, const Signal *sig, bool show, bool merge); + void showChart(const MessageId &id, const Signal *sig, bool show, bool merge); private: void addShortcuts(); diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index 3f12c55ffc..9a085ec732 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -181,7 +181,7 @@ void ChartsWidget::settingChanged() { } } -ChartView *ChartsWidget::findChart(const QString &id, const Signal *sig) { +ChartView *ChartsWidget::findChart(const MessageId &id, const Signal *sig) { for (auto c : charts) if (c->hasSeries(id, sig)) return c; return nullptr; @@ -204,7 +204,7 @@ ChartView *ChartsWidget::createChart() { return chart; } -void ChartsWidget::showChart(const QString &id, const Signal *sig, bool show, bool merge) { +void ChartsWidget::showChart(const MessageId &id, const Signal *sig, bool show, bool merge) { setUpdatesEnabled(false); ChartView *chart = findChart(id, sig); if (show && !chart) { @@ -363,19 +363,18 @@ ChartView::ChartView(QWidget *parent) : QChartView(nullptr, parent) { QObject::connect(remove_btn, &QToolButton::clicked, this, &ChartView::remove); } -void ChartView::addSeries(const QString &msg_id, const Signal *sig) { +void ChartView::addSeries(const MessageId &msg_id, const Signal *sig) { if (hasSeries(msg_id, sig)) return; QXYSeries *series = createSeries(series_type, getColor(sig)); - auto [source, address] = DBCManager::parseId(msg_id); - sigs.push_back({.msg_id = msg_id, .address = address, .source = source, .sig = sig, .series = series}); + sigs.push_back({.msg_id = msg_id, .sig = sig, .series = series}); updateTitle(); updateSeries(sig); updateSeriesPoints(); emit seriesAdded(msg_id, sig); } -bool ChartView::hasSeries(const QString &msg_id, const Signal *sig) const { +bool ChartView::hasSeries(const MessageId &msg_id, const Signal *sig) const { return std::any_of(sigs.begin(), sigs.end(), [&](auto &s) { return s.msg_id == msg_id && s.sig == sig; }); } @@ -409,7 +408,7 @@ void ChartView::signalUpdated(const Signal *sig) { } void ChartView::msgUpdated(uint32_t address) { - if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.address == address; })) + if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.msg_id.address == address; })) updateTitle(); } @@ -455,7 +454,7 @@ void ChartView::updateTitle() { } for (auto &s : sigs) { auto decoration = s.series->isVisible() ? "none" : "line-through"; - s.series->setName(QString("%2 %3 %4").arg(decoration, s.sig->name.c_str(), msgName(s.msg_id), s.msg_id)); + s.series->setName(QString("%2 %3 %4").arg(decoration, s.sig->name.c_str(), msgName(s.msg_id), s.msg_id.toString())); } } @@ -517,7 +516,7 @@ void ChartView::updateSeries(const Signal *sig, const std::vector *even for (auto it = chunk.first; it != chunk.second; ++it) { if ((*it)->which == cereal::Event::Which::CAN) { for (const auto &c : (*it)->event.getCan()) { - if (s.address == c.getAddress() && s.source == c.getSrc()) { + if (s.msg_id.address == c.getAddress() && s.msg_id.source == c.getSrc()) { auto dat = c.getDat(); double value = get_raw_value((uint8_t *)dat.begin(), dat.size(), *s.sig); double ts = ((*it)->mono_time / (double)1e9) - route_start_time; // seconds @@ -847,7 +846,7 @@ SeriesSelector::SeriesSelector(QString title, QWidget *parent) : QDialog(parent) for (auto it = can->can_msgs.cbegin(); it != can->can_msgs.cend(); ++it) { if (auto m = dbc()->msg(it.key())) { - msgs_combo->addItem(QString("%1 (%2)").arg(m->name).arg(it.key()), it.key()); + msgs_combo->addItem(QString("%1 (%2)").arg(m->name).arg(it.key().toString()), QVariant::fromValue(it.key())); } } msgs_combo->model()->sort(0); @@ -872,7 +871,7 @@ void SeriesSelector::add(QListWidgetItem *item) { void SeriesSelector::remove(QListWidgetItem *item) { auto it = (ListItem *)item; - if (it->msg_id == msgs_combo->currentData().toString()) { + if (it->msg_id == msgs_combo->currentData().value()) { addItemToList(available_list, it->msg_id, it->sig); } delete item; @@ -881,7 +880,7 @@ void SeriesSelector::remove(QListWidgetItem *item) { void SeriesSelector::updateAvailableList(int index) { if (index == -1) return; available_list->clear(); - QString msg_id = msgs_combo->itemData(index).toString(); + MessageId msg_id = msgs_combo->itemData(index).value(); auto selected_items = seletedItems(); for (auto &[name, s] : dbc()->msg(msg_id)->sigs) { bool is_selected = std::any_of(selected_items.begin(), selected_items.end(), [=, sig=&s](auto it) { return it->msg_id == msg_id && it->sig == sig; }); @@ -891,9 +890,9 @@ void SeriesSelector::updateAvailableList(int index) { } } -void SeriesSelector::addItemToList(QListWidget *parent, const QString id, const Signal *sig, bool show_msg_name) { +void SeriesSelector::addItemToList(QListWidget *parent, const MessageId id, const Signal *sig, bool show_msg_name) { QString text = QString(" %1").arg(getColor(sig).name(), sig->name.c_str()); - if (show_msg_name) text += QString(" %0 %1").arg(msgName(id), id); + if (show_msg_name) text += QString(" %0 %1").arg(msgName(id), id.toString()); QLabel *label = new QLabel(text); label->setContentsMargins(5, 0, 5, 0); diff --git a/tools/cabana/chartswidget.h b/tools/cabana/chartswidget.h index 58ae7e3b4c..7569155d39 100644 --- a/tools/cabana/chartswidget.h +++ b/tools/cabana/chartswidget.h @@ -25,17 +25,15 @@ class ChartView : public QChartView { public: ChartView(QWidget *parent = nullptr); - void addSeries(const QString &msg_id, const Signal *sig); - bool hasSeries(const QString &msg_id, const Signal *sig) const; + void addSeries(const MessageId &msg_id, const Signal *sig); + bool hasSeries(const MessageId &msg_id, const Signal *sig) const; void updateSeries(const Signal *sig = nullptr, const std::vector *events = nullptr, bool clear = true); void updatePlot(double cur, double min, double max); void setSeriesType(QAbstractSeries::SeriesType type); void updatePlotArea(int left); struct SigItem { - QString msg_id; - uint8_t source = 0; - uint32_t address = 0; + MessageId msg_id; const Signal *sig = nullptr; QXYSeries *series = nullptr; QVector vals; @@ -43,8 +41,8 @@ public: }; signals: - void seriesRemoved(const QString &id, const Signal *sig); - void seriesAdded(const QString &id, const Signal *sig); + void seriesRemoved(const MessageId &id, const Signal *sig); + void seriesAdded(const MessageId &id, const Signal *sig); void zoomIn(double min, double max); void zoomReset(); void remove(); @@ -55,7 +53,7 @@ private slots: void signalUpdated(const Signal *sig); void manageSeries(); void handleMarkerClicked(); - void msgRemoved(uint32_t address) { removeIf([=](auto &s) { return s.address == address; }); } + void msgRemoved(uint32_t address) { removeIf([=](auto &s) { return s.msg_id.address == address; }); } void signalRemoved(const Signal *sig) { removeIf([=](auto &s) { return s.sig == sig; }); } private: @@ -99,8 +97,8 @@ class ChartsWidget : public QWidget { public: ChartsWidget(QWidget *parent = nullptr); - void showChart(const QString &id, const Signal *sig, bool show, bool merge); - inline bool hasSignal(const QString &id, const Signal *sig) { return findChart(id, sig) != nullptr; } + void showChart(const MessageId &id, const Signal *sig, bool show, bool merge); + inline bool hasSignal(const MessageId &id, const Signal *sig) { return findChart(id, sig) != nullptr; } public slots: void setColumnCount(int n); @@ -126,7 +124,7 @@ private: void updateLayout(); void settingChanged(); bool eventFilter(QObject *obj, QEvent *event) override; - ChartView *findChart(const QString &id, const Signal *sig); + ChartView *findChart(const MessageId &id, const Signal *sig); QLabel *title_label; QLabel *range_lb; @@ -152,18 +150,18 @@ private: class SeriesSelector : public QDialog { public: struct ListItem : public QListWidgetItem { - ListItem(const QString &msg_id, const Signal *sig, QListWidget *parent) : msg_id(msg_id), sig(sig), QListWidgetItem(parent) {} - QString msg_id; + ListItem(const MessageId &msg_id, const Signal *sig, QListWidget *parent) : msg_id(msg_id), sig(sig), QListWidgetItem(parent) {} + MessageId msg_id; const Signal *sig; }; SeriesSelector(QString title, QWidget *parent); QList seletedItems(); - inline void addSelected(const QString &id, const Signal *sig) { addItemToList(selected_list, id, sig, true); } + inline void addSelected(const MessageId &id, const Signal *sig) { addItemToList(selected_list, id, sig, true); } private: void updateAvailableList(int index); - void addItemToList(QListWidget *parent, const QString id, const Signal *sig, bool show_msg_name = false); + void addItemToList(QListWidget *parent, const MessageId id, const Signal *sig, bool show_msg_name = false); void add(QListWidgetItem *item); void remove(QListWidgetItem *item); diff --git a/tools/cabana/commands.cc b/tools/cabana/commands.cc index e4bf999062..b03f46b5d2 100644 --- a/tools/cabana/commands.cc +++ b/tools/cabana/commands.cc @@ -4,13 +4,13 @@ // EditMsgCommand -EditMsgCommand::EditMsgCommand(const QString &id, const QString &title, int size, QUndoCommand *parent) +EditMsgCommand::EditMsgCommand(const MessageId &id, const QString &title, int size, QUndoCommand *parent) : id(id), new_title(title), new_size(size), QUndoCommand(parent) { if (auto msg = dbc()->msg(id)) { old_title = msg->name; old_size = msg->size; } - setText(QObject::tr("Edit message %1:%2").arg(DBCManager::parseId(id).second).arg(title)); + setText(QObject::tr("Edit message %1:%2").arg(id.address).arg(title)); } void EditMsgCommand::undo() { @@ -26,10 +26,10 @@ void EditMsgCommand::redo() { // RemoveMsgCommand -RemoveMsgCommand::RemoveMsgCommand(const QString &id, QUndoCommand *parent) : id(id), QUndoCommand(parent) { +RemoveMsgCommand::RemoveMsgCommand(const MessageId &id, QUndoCommand *parent) : id(id), QUndoCommand(parent) { if (auto msg = dbc()->msg(id)) { message = *msg; - setText(QObject::tr("Remove message %1:%2").arg(DBCManager::parseId(id).second).arg(message.name)); + setText(QObject::tr("Remove message %1:%2").arg(id.address).arg(message.name)); } } @@ -48,9 +48,9 @@ void RemoveMsgCommand::redo() { // AddSigCommand -AddSigCommand::AddSigCommand(const QString &id, const Signal &sig, QUndoCommand *parent) +AddSigCommand::AddSigCommand(const MessageId &id, const Signal &sig, QUndoCommand *parent) : id(id), signal(sig), QUndoCommand(parent) { - setText(QObject::tr("Add signal %1 to %2").arg(sig.name.c_str()).arg(DBCManager::parseId(id).second)); + setText(QObject::tr("Add signal %1 to %2").arg(sig.name.c_str()).arg(id.address)); } void AddSigCommand::undo() { dbc()->removeSignal(id, signal.name.c_str()); } @@ -58,9 +58,9 @@ void AddSigCommand::redo() { dbc()->addSignal(id, signal); } // RemoveSigCommand -RemoveSigCommand::RemoveSigCommand(const QString &id, const Signal *sig, QUndoCommand *parent) +RemoveSigCommand::RemoveSigCommand(const MessageId &id, const Signal *sig, QUndoCommand *parent) : id(id), signal(*sig), QUndoCommand(parent) { - setText(QObject::tr("Remove signal %1 from %2").arg(signal.name.c_str()).arg(DBCManager::parseId(id).second)); + setText(QObject::tr("Remove signal %1 from %2").arg(signal.name.c_str()).arg(id.address)); } void RemoveSigCommand::undo() { dbc()->addSignal(id, signal); } @@ -68,7 +68,7 @@ void RemoveSigCommand::redo() { dbc()->removeSignal(id, signal.name.c_str()); } // EditSignalCommand -EditSignalCommand::EditSignalCommand(const QString &id, const Signal *sig, const Signal &new_sig, QUndoCommand *parent) +EditSignalCommand::EditSignalCommand(const MessageId &id, const Signal *sig, const Signal &new_sig, QUndoCommand *parent) : id(id), old_signal(*sig), new_signal(new_sig), QUndoCommand(parent) { setText(QObject::tr("Edit signal %1").arg(old_signal.name.c_str())); } diff --git a/tools/cabana/commands.h b/tools/cabana/commands.h index c07a00b760..46e9f0a030 100644 --- a/tools/cabana/commands.h +++ b/tools/cabana/commands.h @@ -7,57 +7,57 @@ class EditMsgCommand : public QUndoCommand { public: - EditMsgCommand(const QString &id, const QString &title, int size, QUndoCommand *parent = nullptr); + EditMsgCommand(const MessageId &id, const QString &title, int size, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: - const QString id; + const MessageId id; QString old_title, new_title; int old_size = 0, new_size = 0; }; class RemoveMsgCommand : public QUndoCommand { public: - RemoveMsgCommand(const QString &id, QUndoCommand *parent = nullptr); + RemoveMsgCommand(const MessageId &id, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: - const QString id; + const MessageId id; DBCMsg message; }; class AddSigCommand : public QUndoCommand { public: - AddSigCommand(const QString &id, const Signal &sig, QUndoCommand *parent = nullptr); + AddSigCommand(const MessageId &id, const Signal &sig, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: - const QString id; + const MessageId id; Signal signal = {}; }; class RemoveSigCommand : public QUndoCommand { public: - RemoveSigCommand(const QString &id, const Signal *sig, QUndoCommand *parent = nullptr); + RemoveSigCommand(const MessageId &id, const Signal *sig, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: - const QString id; + const MessageId id; Signal signal = {}; }; class EditSignalCommand : public QUndoCommand { public: - EditSignalCommand(const QString &id, const Signal *sig, const Signal &new_sig, QUndoCommand *parent = nullptr); + EditSignalCommand(const MessageId &id, const Signal *sig, const Signal &new_sig, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: - const QString id; + const MessageId id; Signal old_signal = {}; Signal new_signal = {}; }; diff --git a/tools/cabana/dbcmanager.cc b/tools/cabana/dbcmanager.cc index 3d565e7067..27f16c71e5 100644 --- a/tools/cabana/dbcmanager.cc +++ b/tools/cabana/dbcmanager.cc @@ -4,6 +4,10 @@ #include #include +uint qHash(const MessageId &item) { + return qHash(item.source) ^ qHash(item.address); +} + DBCManager::DBCManager(QObject *parent) : QObject(parent) {} DBCManager::~DBCManager() {} @@ -56,29 +60,27 @@ QString DBCManager::generateDBC() { return dbc_string; } -void DBCManager::updateMsg(const QString &id, const QString &name, uint32_t size) { - auto [_, address] = parseId(id); - auto &m = msgs[address]; +void DBCManager::updateMsg(const MessageId &id, const QString &name, uint32_t size) { + auto &m = msgs[id.address]; m.name = name; m.size = size; - emit msgUpdated(address); + emit msgUpdated(id.address); } -void DBCManager::removeMsg(const QString &id) { - uint32_t address = parseId(id).second; - msgs.erase(address); - emit msgRemoved(address); +void DBCManager::removeMsg(const MessageId &id) { + msgs.erase(id.address); + emit msgRemoved(id.address); } -void DBCManager::addSignal(const QString &id, const Signal &sig) { - if (auto m = const_cast(msg(id))) { +void DBCManager::addSignal(const MessageId &id, const Signal &sig) { + if (auto m = const_cast(msg(id.address))) { auto &s = m->sigs[sig.name.c_str()]; s = sig; - emit signalAdded(parseId(id).second, &s); + emit signalAdded(id.address, &s); } } -void DBCManager::updateSignal(const QString &id, const QString &sig_name, const Signal &sig) { +void DBCManager::updateSignal(const MessageId &id, const QString &sig_name, const Signal &sig) { if (auto m = const_cast(msg(id))) { // change key name QString new_name = QString::fromStdString(sig.name); @@ -91,7 +93,7 @@ void DBCManager::updateSignal(const QString &id, const QString &sig_name, const } } -void DBCManager::removeSignal(const QString &id, const QString &sig_name) { +void DBCManager::removeSignal(const MessageId &id, const QString &sig_name) { if (auto m = const_cast(msg(id))) { auto it = m->sigs.find(sig_name); if (it != m->sigs.end()) { @@ -101,12 +103,6 @@ void DBCManager::removeSignal(const QString &id, const QString &sig_name) { } } -std::pair DBCManager::parseId(const QString &id) { - const auto list = id.split(':'); - if (list.size() != 2) return {0, 0}; - return {list[0].toInt(), list[1].toUInt(nullptr, 16)}; -} - DBCManager *dbc() { static DBCManager dbc_manager(nullptr); return &dbc_manager; diff --git a/tools/cabana/dbcmanager.h b/tools/cabana/dbcmanager.h index 7571d1c44e..b766c837b6 100644 --- a/tools/cabana/dbcmanager.h +++ b/tools/cabana/dbcmanager.h @@ -5,6 +5,35 @@ #include #include "opendbc/can/common_dbc.h" +struct MessageId { + uint8_t source; + uint32_t address; + + QString toString() const { + return QString("%1:%2").arg(source).arg(address, 1, 16); + } + + bool operator==(const MessageId &other) const { + return source == other.source && address == other.address; + } + + bool operator!=(const MessageId &other) const { + return !(*this == other); + } + + bool operator<(const MessageId &other) const { + return std::pair{source, address} < std::pair{other.source, other.address}; + } + + bool operator>(const MessageId &other) const { + return std::pair{source, address} > std::pair{other.source, other.address}; + } +}; + +Q_DECLARE_METATYPE(MessageId); + +uint qHash(const MessageId &item); + struct DBCMsg { QString name; uint32_t size; @@ -24,17 +53,16 @@ public: void open(const QString &dbc_file_name); bool open(const QString &name, const QString &content, QString *error = nullptr); QString generateDBC(); - void addSignal(const QString &id, const Signal &sig); - void updateSignal(const QString &id, const QString &sig_name, const Signal &sig); - void removeSignal(const QString &id, const QString &sig_name); + void addSignal(const MessageId &id, const Signal &sig); + void updateSignal(const MessageId &id, const QString &sig_name, const Signal &sig); + void removeSignal(const MessageId &id, const QString &sig_name); - static std::pair parseId(const QString &id); inline static std::vector allDBCNames() { return get_dbc_names(); } inline QString name() const { return dbc ? dbc->name.c_str() : ""; } - void updateMsg(const QString &id, const QString &name, uint32_t size); - void removeMsg(const QString &id); + void updateMsg(const MessageId &id, const QString &name, uint32_t size); + void removeMsg(const MessageId &id); inline const std::map &messages() const { return msgs; } - inline const DBCMsg *msg(const QString &id) const { return msg(parseId(id).second); } + inline const DBCMsg *msg(const MessageId &id) const { return msg(id.address); } inline const DBCMsg *msg(uint32_t address) const { auto it = msgs.find(address); return it != msgs.end() ? &it->second : nullptr; @@ -65,7 +93,7 @@ int bigEndianBitIndex(int index); void updateSigSizeParamsFromRange(Signal &s, int start_bit, int size); std::pair getSignalRange(const Signal *s); DBCManager *dbc(); -inline QString msgName(const QString &id) { +inline QString msgName(const MessageId &id) { auto msg = dbc()->msg(id); return msg ? msg->name : UNTITLED; } diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index 2036912344..55ba0b9feb 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -85,11 +85,15 @@ DetailWidget::DetailWidget(ChartsWidget *charts, QWidget *parent) : charts(chart QObject::connect(UndoStack::instance(), &QUndoStack::indexChanged, this, &DetailWidget::refresh); QObject::connect(tabbar, &QTabBar::customContextMenuRequested, this, &DetailWidget::showTabBarContextMenu); QObject::connect(tabbar, &QTabBar::currentChanged, [this](int index) { - if (index != -1 && tabbar->tabText(index) != msg_id) { - setMessage(tabbar->tabText(index)); + if (index != -1) { + setMessage(tabbar_ids[index]); } }); - QObject::connect(tabbar, &QTabBar::tabCloseRequested, tabbar, &QTabBar::removeTab); + QObject::connect(tabbar, &QTabBar::tabCloseRequested, [this](int index) { + tabbar_ids.removeAt(index); + tabbar->removeTab(index); + assert(tabbar_ids.size() == tabbar->count()); + }); QObject::connect(charts, &ChartsWidget::seriesChanged, signal_view, &SignalView::updateChartState); } @@ -108,29 +112,32 @@ void DetailWidget::showTabBarContextMenu(const QPoint &pt) { } void DetailWidget::removeAll() { - msg_id = ""; + msg_id = std::nullopt; tabbar->blockSignals(true); while (tabbar->count() > 0) { tabbar->removeTab(0); } + tabbar_ids.clear(); tabbar->blockSignals(false); stacked_layout->setCurrentIndex(0); } -void DetailWidget::setMessage(const QString &message_id) { +void DetailWidget::setMessage(const MessageId &message_id) { msg_id = message_id; - int index = tabbar->count() - 1; - for (/**/; index >= 0 && tabbar->tabText(index) != msg_id; --index) { /**/ } + int index = tabbar_ids.indexOf(*msg_id); + if (index == -1) { - index = tabbar->addTab(message_id); + tabbar_ids.append(*msg_id); + index = tabbar->addTab(message_id.toString()); tabbar->setTabToolTip(index, msgName(message_id)); } + assert(tabbar->count() == tabbar_ids.size()); setUpdatesEnabled(false); - signal_view->setMessage(msg_id); - binary_view->setMessage(msg_id); - history_log->setMessage(msg_id); + signal_view->setMessage(*msg_id); + binary_view->setMessage(*msg_id); + history_log->setMessage(*msg_id); stacked_layout->setCurrentIndex(1); tabbar->setCurrentIndex(index); @@ -141,12 +148,12 @@ void DetailWidget::setMessage(const QString &message_id) { } void DetailWidget::refresh() { - if (msg_id.isEmpty()) return; + if (!msg_id) return; QStringList warnings; - const DBCMsg *msg = dbc()->msg(msg_id); + const DBCMsg *msg = dbc()->msg(*msg_id); if (msg) { - if (msg->size != can->lastMessage(msg_id).dat.size()) { + if (msg->size != can->lastMessage(*msg_id).dat.size()) { warnings.push_back(tr("Message size (%1) is incorrect.").arg(msg->size)); } for (auto s : binary_view->getOverlappingSignals()) { @@ -156,7 +163,7 @@ void DetailWidget::refresh() { warnings.push_back(tr("Drag-Select in binary view to create new signal.")); } remove_msg_act->setEnabled(msg != nullptr); - name_label->setText(msgName(msg_id)); + name_label->setText(msgName(*msg_id)); if (!warnings.isEmpty()) { warning_label->setText(warnings.join('\n')); @@ -165,9 +172,9 @@ void DetailWidget::refresh() { warning_widget->setVisible(!warnings.isEmpty()); } -void DetailWidget::updateState(const QHash *msgs) { +void DetailWidget::updateState(const QHash *msgs) { time_label->setText(QString::number(can->currentSec(), 'f', 3)); - if (msg_id.isEmpty() || (msgs && !msgs->contains(msg_id))) + if (!msg_id || (msgs && !msgs->contains(*msg_id))) return; if (tab_widget->currentIndex() == 0) @@ -177,24 +184,24 @@ void DetailWidget::updateState(const QHash *msgs) { } void DetailWidget::editMsg() { - QString id = msg_id; + MessageId id = *msg_id; auto msg = dbc()->msg(id); int size = msg ? msg->size : can->lastMessage(id).dat.size(); EditMessageDialog dlg(id, msgName(id), size, this); if (dlg.exec()) { - UndoStack::push(new EditMsgCommand(msg_id, dlg.name_edit->text(), dlg.size_spin->value())); + UndoStack::push(new EditMsgCommand(*msg_id, dlg.name_edit->text(), dlg.size_spin->value())); } } void DetailWidget::removeMsg() { - UndoStack::push(new RemoveMsgCommand(msg_id)); + UndoStack::push(new RemoveMsgCommand(*msg_id)); } // EditMessageDialog -EditMessageDialog::EditMessageDialog(const QString &msg_id, const QString &title, int size, QWidget *parent) +EditMessageDialog::EditMessageDialog(const MessageId &msg_id, const QString &title, int size, QWidget *parent) : original_name(title), QDialog(parent) { - setWindowTitle(tr("Edit message: %1").arg(msg_id)); + setWindowTitle(tr("Edit message: %1").arg(msg_id.toString())); QFormLayout *form_layout = new QFormLayout(this); form_layout->addRow("", error_label = new QLabel); diff --git a/tools/cabana/detailwidget.h b/tools/cabana/detailwidget.h index c5d5fe9a4d..949a8c9b8d 100644 --- a/tools/cabana/detailwidget.h +++ b/tools/cabana/detailwidget.h @@ -14,7 +14,7 @@ class EditMessageDialog : public QDialog { public: - EditMessageDialog(const QString &msg_id, const QString &title, int size, QWidget *parent); + EditMessageDialog(const MessageId &msg_id, const QString &title, int size, QWidget *parent); void validateName(const QString &text); QString original_name; @@ -34,7 +34,7 @@ class DetailWidget : public QWidget { public: DetailWidget(ChartsWidget *charts, QWidget *parent); - void setMessage(const QString &message_id); + void setMessage(const MessageId &message_id); void refresh(); void removeAll(); QSize minimumSizeHint() const override { return binary_view->minimumSizeHint(); } @@ -43,13 +43,14 @@ private: void showTabBarContextMenu(const QPoint &pt); void editMsg(); void removeMsg(); - void updateState(const QHash * msgs = nullptr); + void updateState(const QHash * msgs = nullptr); - QString msg_id; + std::optional msg_id; QLabel *time_label, *warning_icon, *warning_label; ElidedLabel *name_label; QWidget *warning_widget; QTabBar *tabbar; + QList tabbar_ids; QTabWidget *tab_widget; QAction *remove_msg_act; LogsWidget *history_log; diff --git a/tools/cabana/historylog.cc b/tools/cabana/historylog.cc index e4ad99758b..f7f02b06d8 100644 --- a/tools/cabana/historylog.cc +++ b/tools/cabana/historylog.cc @@ -22,14 +22,14 @@ QVariant HistoryLogModel::data(const QModelIndex &index, int role) const { return {}; } -void HistoryLogModel::setMessage(const QString &message_id) { +void HistoryLogModel::setMessage(const MessageId &message_id) { msg_id = message_id; } void HistoryLogModel::refresh() { beginResetModel(); sigs.clear(); - if (auto dbc_msg = dbc()->msg(msg_id)) { + if (auto dbc_msg = dbc()->msg(*msg_id)) { sigs = dbc_msg->getSignals(); } last_fetch_time = 0; @@ -78,8 +78,8 @@ void HistoryLogModel::setFilter(int sig_idx, const QString &value, std::function } void HistoryLogModel::updateState() { - if (!msg_id.isEmpty()) { - uint64_t current_time = (can->lastMessage(msg_id).ts + can->routeStartTime()) * 1e9 + 1; + if (msg_id) { + uint64_t current_time = (can->lastMessage(*msg_id).ts + can->routeStartTime()) * 1e9 + 1; auto new_msgs = dynamic_mode ? fetchData(current_time, last_fetch_time) : fetchData(0); if (!new_msgs.empty()) { beginInsertRows({}, 0, new_msgs.size() - 1); @@ -106,12 +106,11 @@ void HistoryLogModel::fetchMore(const QModelIndex &parent) { template std::deque HistoryLogModel::fetchData(InputIt first, InputIt last, uint64_t min_time) { std::deque msgs; - const auto [src, address] = DBCManager::parseId(msg_id); QVector values(sigs.size()); for (auto it = first; it != last && (*it)->mono_time > min_time; ++it) { if ((*it)->which == cereal::Event::Which::CAN) { for (const auto &c : (*it)->event.getCan()) { - if (address == c.getAddress() && src == c.getSrc()) { + if (msg_id->address == c.getAddress() && msg_id->source == c.getSrc()) { const auto dat = c.getDat(); for (int i = 0; i < sigs.size(); ++i) { values[i] = get_raw_value((uint8_t *)dat.begin(), dat.size(), *(sigs[i])); @@ -136,7 +135,7 @@ template std::deque HistoryLogModel::fetchData<>(std:: std::deque HistoryLogModel::fetchData(uint64_t from_time, uint64_t min_time) { auto events = can->events(); - const auto freq = can->lastMessage(msg_id).freq; + const auto freq = can->lastMessage(*msg_id).freq; const bool update_colors = !display_signals_mode || sigs.empty(); if (dynamic_mode) { @@ -241,13 +240,13 @@ LogsWidget::LogsWidget(QWidget *parent) : QWidget(parent) { QObject::connect(can, &AbstractStream::eventsMerged, model, &HistoryLogModel::segmentsMerged); } -void LogsWidget::setMessage(const QString &message_id) { +void LogsWidget::setMessage(const MessageId &message_id) { model->setMessage(message_id); refresh(); } void LogsWidget::refresh() { - if (model->msg_id.isEmpty()) return; + if (!model->msg_id) return; model->setFilter(0, "", nullptr); model->refresh(); diff --git a/tools/cabana/historylog.h b/tools/cabana/historylog.h index 2458fc1c31..00a8f73836 100644 --- a/tools/cabana/historylog.h +++ b/tools/cabana/historylog.h @@ -1,6 +1,8 @@ #pragma once #include +#include + #include #include #include @@ -22,7 +24,7 @@ class HistoryLogModel : public QAbstractTableModel { public: HistoryLogModel(QObject *parent) : QAbstractTableModel(parent) {} - void setMessage(const QString &message_id); + void setMessage(const MessageId &message_id); void updateState(); void setFilter(int sig_idx, const QString &value, std::function cmp); QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; @@ -52,7 +54,7 @@ public: std::deque fetchData(InputIt first, InputIt last, uint64_t min_time); std::deque fetchData(uint64_t from_time, uint64_t min_time = 0); - QString msg_id; + std::optional msg_id; ChangeTracker hex_colors; bool has_more_data = true; const int batch_size = 50; @@ -71,7 +73,7 @@ class LogsWidget : public QWidget { public: LogsWidget(QWidget *parent); - void setMessage(const QString &message_id); + void setMessage(const MessageId &message_id); void updateState() {if (dynamic_mode->isChecked()) model->updateState(); } void showEvent(QShowEvent *event) override { if (dynamic_mode->isChecked()) model->refresh(); } diff --git a/tools/cabana/messageswidget.cc b/tools/cabana/messageswidget.cc index 8279d08a5c..4f6bb92375 100644 --- a/tools/cabana/messageswidget.cc +++ b/tools/cabana/messageswidget.cc @@ -46,12 +46,12 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) { QObject::connect(dbc(), &DBCManager::DBCFileChanged, model, &MessageListModel::sortMessages); QObject::connect(dbc(), &DBCManager::msgUpdated, model, &MessageListModel::sortMessages); QObject::connect(dbc(), &DBCManager::msgRemoved, model, &MessageListModel::sortMessages); - QObject::connect(model, &MessageListModel::modelReset, [this]() { selectMessage(current_msg_id); }); + QObject::connect(model, &MessageListModel::modelReset, [this]() { selectMessage(*current_msg_id); }); QObject::connect(table_widget->selectionModel(), &QItemSelectionModel::currentChanged, [=](const QModelIndex ¤t, const QModelIndex &previous) { if (current.isValid() && current.row() < model->msgs.size()) { - if (model->msgs[current.row()] != current_msg_id) { + if (model->msgs[current.row()] != *current_msg_id) { current_msg_id = model->msgs[current.row()]; - emit msgSelectionChanged(current_msg_id); + emit msgSelectionChanged(*current_msg_id); } } }); @@ -67,7 +67,7 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) { updateSuppressedButtons(); } -void MessagesWidget::selectMessage(const QString &msg_id) { +void MessagesWidget::selectMessage(const MessageId &msg_id) { if (int row = model->msgs.indexOf(msg_id); row != -1) { table_widget->selectionModel()->setCurrentIndex(model->index(row, 0), QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect); } @@ -86,7 +86,7 @@ void MessagesWidget::updateSuppressedButtons() { void MessagesWidget::reset() { model->reset(); filter->clear(); - current_msg_id = ""; + current_msg_id = std::nullopt; updateSuppressedButtons(); } @@ -106,7 +106,7 @@ QVariant MessageListModel::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole) { switch (index.column()) { case 0: return msgName(id); - case 1: return id; + case 1: return id.toString(); // TODO: put source and address in separate columns case 2: return can_data.freq; case 3: return can_data.count; case 4: return toHex(can_data.dat); @@ -128,9 +128,9 @@ QVariant MessageListModel::data(const QModelIndex &index, int role) const { } void MessageListModel::setFilterString(const QString &string) { - auto contains = [](const QString &id, const QString &txt) { + auto contains = [](const MessageId &id, const QString &txt) { auto cs = Qt::CaseInsensitive; - if (id.contains(txt, cs) || msgName(id).contains(txt, cs)) return true; + if (id.toString().contains(txt, cs) || msgName(id).contains(txt, cs)) return true; // Search by signal name if (const auto msg = dbc()->msg(id)) { for (auto &signal : msg->getSignals()) { @@ -160,9 +160,7 @@ void MessageListModel::sortMessages() { }); } else if (sort_column == 1) { std::sort(msgs.begin(), msgs.end(), [this](auto &l, auto &r) { - auto ll = DBCManager::parseId(l); - auto rr = DBCManager::parseId(r); - return sort_order == Qt::AscendingOrder ? ll < rr : ll > rr; + return sort_order == Qt::AscendingOrder ? l < r : l > r; }); } else if (sort_column == 2) { std::sort(msgs.begin(), msgs.end(), [this](auto &l, auto &r) { @@ -180,7 +178,7 @@ void MessageListModel::sortMessages() { endResetModel(); } -void MessageListModel::msgsReceived(const QHash *new_msgs) { +void MessageListModel::msgsReceived(const QHash *new_msgs) { int prev_row_count = msgs.size(); if (filter_str.isEmpty() && msgs.size() != can->can_msgs.size()) { msgs = can->can_msgs.keys(); diff --git a/tools/cabana/messageswidget.h b/tools/cabana/messageswidget.h index 81ee36cd6f..562069c3ae 100644 --- a/tools/cabana/messageswidget.h +++ b/tools/cabana/messageswidget.h @@ -1,5 +1,7 @@ #pragma once +#include + #include #include #include @@ -20,13 +22,13 @@ public: int rowCount(const QModelIndex &parent = QModelIndex()) const override { return msgs.size(); } void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override; void setFilterString(const QString &string); - void msgsReceived(const QHash *new_msgs = nullptr); + void msgsReceived(const QHash *new_msgs = nullptr); void sortMessages(); void suppress(); void clearSuppress(); void reset(); - QStringList msgs; - QSet> suppressed_bytes; + QList msgs; + QSet> suppressed_bytes; private: QString filter_str; @@ -39,18 +41,18 @@ class MessagesWidget : public QWidget { public: MessagesWidget(QWidget *parent); - void selectMessage(const QString &message_id); + void selectMessage(const MessageId &message_id); QByteArray saveHeaderState() const { return table_widget->horizontalHeader()->saveState(); } bool restoreHeaderState(const QByteArray &state) const { return table_widget->horizontalHeader()->restoreState(state); } void updateSuppressedButtons(); void reset(); signals: - void msgSelectionChanged(const QString &message_id); + void msgSelectionChanged(const MessageId &message_id); protected: QTableView *table_widget; - QString current_msg_id; + std::optional current_msg_id; QLineEdit *filter; MessageListModel *model; QPushButton *suppress_add; diff --git a/tools/cabana/signaledit.cc b/tools/cabana/signaledit.cc index 0499b1be8a..98dd39204f 100644 --- a/tools/cabana/signaledit.cc +++ b/tools/cabana/signaledit.cc @@ -31,7 +31,7 @@ void SignalModel::insertItem(SignalModel::Item *parent_item, int pos, const Sign } } -void SignalModel::setMessage(const QString &id) { +void SignalModel::setMessage(const MessageId &id) { msg_id = id; filter_str = ""; refresh(); @@ -56,7 +56,7 @@ void SignalModel::refresh() { endResetModel(); } -void SignalModel::updateState(const QHash *msgs) { +void SignalModel::updateState(const QHash *msgs) { if (!msgs || (msgs->contains(msg_id))) { auto &dat = can->lastMessage(msg_id).dat; int row = 0; @@ -230,13 +230,13 @@ void SignalModel::removeSignal(const Signal *sig) { } void SignalModel::handleMsgChanged(uint32_t address) { - if (address == DBCManager::parseId(msg_id).second) { + if (address == msg_id.address) { refresh(); } } void SignalModel::handleSignalAdded(uint32_t address, const Signal *sig) { - if (address == DBCManager::parseId(msg_id).second) { + if (address == msg_id.address) { int i = 0; for (; i < root->children.size(); ++i) { if (sig->start_bit < root->children[i]->sig->start_bit) break; @@ -367,7 +367,7 @@ SignalView::SignalView(ChartsWidget *charts, QWidget *parent) : charts(charts), QObject::connect(dbc(), &DBCManager::signalAdded, [this](uint32_t address, const Signal *sig) { expandSignal(sig); }); } -void SignalView::setMessage(const QString &id) { +void SignalView::setMessage(const MessageId &id) { msg_id = id; filter_edit->clear(); model->setMessage(id); diff --git a/tools/cabana/signaledit.h b/tools/cabana/signaledit.h index c0b649209a..7e5015f707 100644 --- a/tools/cabana/signaledit.h +++ b/tools/cabana/signaledit.h @@ -37,7 +37,7 @@ public: QModelIndex parent(const QModelIndex &index) const override; Qt::ItemFlags flags(const QModelIndex &index) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; - void setMessage(const QString &id); + void setMessage(const MessageId &id); void setFilter(const QString &txt); void addSignal(int start_bit, int size, bool little_endian); bool saveSignal(const Signal *origin_s, Signal &s); @@ -54,9 +54,9 @@ private: void handleSignalRemoved(const Signal *sig); void handleMsgChanged(uint32_t address); void refresh(); - void updateState(const QHash *msgs); + void updateState(const QHash *msgs); - QString msg_id; + MessageId msg_id; QString filter_str; std::unique_ptr root; friend class SignalView; @@ -76,7 +76,7 @@ class SignalView : public QWidget { public: SignalView(ChartsWidget *charts, QWidget *parent); - void setMessage(const QString &id); + void setMessage(const MessageId &id); void signalHovered(const Signal *sig); void updateChartState(); void expandSignal(const Signal *sig); @@ -85,13 +85,13 @@ public: signals: void highlight(const Signal *sig); - void showChart(const QString &name, const Signal *sig, bool show, bool merge); + void showChart(const MessageId &id, const Signal *sig, bool show, bool merge); private: void rowsChanged(); void leaveEvent(QEvent *event); - QString msg_id; + MessageId msg_id; QTreeView *tree; QLineEdit *filter_edit; ChartsWidget *charts; diff --git a/tools/cabana/streams/abstractstream.cc b/tools/cabana/streams/abstractstream.cc index 13b154a7ea..5f12e0c42f 100644 --- a/tools/cabana/streams/abstractstream.cc +++ b/tools/cabana/streams/abstractstream.cc @@ -4,12 +4,12 @@ AbstractStream *can = nullptr; AbstractStream::AbstractStream(QObject *parent, bool is_live_streaming) : is_live_streaming(is_live_streaming), QObject(parent) { can = this; - new_msgs = std::make_unique>(); + new_msgs = std::make_unique>(); QObject::connect(this, &AbstractStream::received, this, &AbstractStream::process, Qt::QueuedConnection); QObject::connect(this, &AbstractStream::seekedTo, this, &AbstractStream::updateLastMsgsTo); } -void AbstractStream::process(QHash *messages) { +void AbstractStream::process(QHash *messages) { for (auto it = messages->begin(); it != messages->end(); ++it) { can_msgs[it.key()] = it.value(); } @@ -25,7 +25,7 @@ bool AbstractStream::updateEvent(const Event *event) { if (event->which == cereal::Event::Which::CAN) { double current_sec = event->mono_time / 1e9 - routeStartTime(); for (const auto &c : event->event.getCan()) { - QString id = QString("%1:%2").arg(c.getSrc()).arg(c.getAddress(), 1, 16); + MessageId id = {.source = c.getSrc(), .address = c.getAddress()}; CanData &data = (*new_msgs)[id]; data.ts = current_sec; data.dat = QByteArray((char *)c.getDat().begin(), c.getDat().size()); @@ -44,21 +44,21 @@ bool AbstractStream::updateEvent(const Event *event) { prev_update_ts = ts; // use pointer to avoid data copy in queued connection. emit received(new_msgs.release()); - new_msgs.reset(new QHash); + new_msgs.reset(new QHash); new_msgs->reserve(100); } } return true; } -const CanData &AbstractStream::lastMessage(const QString &id) { +const CanData &AbstractStream::lastMessage(const MessageId &id) { static CanData empty_data; auto it = can_msgs.find(id); return it != can_msgs.end() ? it.value() : empty_data; } void AbstractStream::updateLastMsgsTo(double sec) { - QHash, CanData> last_msgs; // Much faster than QHash + QHash last_msgs; last_msgs.reserve(can_msgs.size()); double route_start_time = routeStartTime(); uint64_t last_ts = (sec + route_start_time) * 1e9; @@ -66,7 +66,7 @@ void AbstractStream::updateLastMsgsTo(double sec) { for (auto it = last; it != events()->rend(); ++it) { if ((*it)->which == cereal::Event::Which::CAN) { for (const auto &c : (*it)->event.getCan()) { - auto &m = last_msgs[{c.getSrc(), c.getAddress()}]; + auto &m = last_msgs[{.source = c.getSrc(), .address = c.getAddress()}]; if (++m.count == 1) { m.ts = ((*it)->mono_time / 1e9) - route_start_time; m.dat = QByteArray((char *)c.getDat().begin(), c.getDat().size()); @@ -87,9 +87,8 @@ void AbstractStream::updateLastMsgsTo(double sec) { counters.clear(); can_msgs.clear(); for (auto it = last_msgs.cbegin(); it != last_msgs.cend(); ++it) { - QString msg_id = QString("%1:%2").arg(it.key().first).arg(it.key().second, 1, 16); - can_msgs[msg_id] = it.value(); - counters[msg_id] = it.value().count; + can_msgs[it.key()] = it.value(); + counters[it.key()] = it.value().count; } emit updated(); emit msgsReceived(&can_msgs); diff --git a/tools/cabana/streams/abstractstream.h b/tools/cabana/streams/abstractstream.h index 8c10d959cb..e582682971 100644 --- a/tools/cabana/streams/abstractstream.h +++ b/tools/cabana/streams/abstractstream.h @@ -5,6 +5,7 @@ #include #include +#include "tools/cabana/dbcmanager.h" #include "tools/cabana/settings.h" #include "tools/cabana/util.h" #include "tools/replay/replay.h" @@ -33,7 +34,7 @@ public: virtual double routeStartTime() const { return 0; } virtual double currentSec() const = 0; virtual QDateTime currentDateTime() const { return {}; } - virtual const CanData &lastMessage(const QString &id); + virtual const CanData &lastMessage(const MessageId &id); virtual VisionStreamType visionStreamType() const { return VISION_STREAM_ROAD; } virtual const Route *route() const { return nullptr; } virtual const std::vector *events() const = 0; @@ -49,22 +50,22 @@ signals: void streamStarted(); void eventsMerged(); void updated(); - void msgsReceived(const QHash *); - void received(QHash *); + void msgsReceived(const QHash *); + void received(QHash *); public: - QHash can_msgs; + QHash can_msgs; protected: - void process(QHash *); + void process(QHash *); bool updateEvent(const Event *event); void updateLastMsgsTo(double sec); bool is_live_streaming = false; std::atomic processing = false; - QHash counters; - std::unique_ptr> new_msgs; - QHash change_trackers; + QHash counters; + std::unique_ptr> new_msgs; + QHash change_trackers; }; // A global pointer referring to the unique AbstractStream object diff --git a/tools/cabana/tools/findsimilarbits.cc b/tools/cabana/tools/findsimilarbits.cc index 63d01b152d..ffb0e54b0e 100644 --- a/tools/cabana/tools/findsimilarbits.cc +++ b/tools/cabana/tools/findsimilarbits.cc @@ -20,10 +20,10 @@ FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::Wi bus_combo = new QComboBox(this); QSet bus_set; for (auto it = can->can_msgs.begin(); it != can->can_msgs.end(); ++it) { - bus_set << DBCManager::parseId(it.key()).first; + bus_set << it.key().source; } for (uint8_t bus : bus_set) { - bus_combo->addItem(QString::number(bus)); + bus_combo->addItem(QString::number(bus), bus); } bus_combo->model()->sort(0); bus_combo->setCurrentIndex(0); @@ -69,9 +69,11 @@ FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::Wi setMinimumSize({700, 500}); QObject::connect(search_btn, &QPushButton::clicked, this, &FindSimilarBitsDlg::find); + QObject::connect(table, &QTableWidget::doubleClicked, [this](const QModelIndex &index) { if (index.isValid()) { - emit openMessage(bus_combo->currentText() + ":" + table->item(index.row(), 0)->text()); + MessageId msg_id = {.source = (uint8_t)bus_combo->currentData().toUInt(), .address = table->item(index.row(), 0)->text().toUInt(0, 16)}; + emit openMessage(msg_id); } }); } diff --git a/tools/cabana/tools/findsimilarbits.h b/tools/cabana/tools/findsimilarbits.h index 30d78f0dea..53d7806a8f 100644 --- a/tools/cabana/tools/findsimilarbits.h +++ b/tools/cabana/tools/findsimilarbits.h @@ -6,6 +6,8 @@ #include #include +#include "tools/cabana/dbcmanager.h" + class FindSimilarBitsDlg : public QDialog { Q_OBJECT @@ -13,7 +15,7 @@ public: FindSimilarBitsDlg(QWidget *parent); signals: - void openMessage(const QString &msg_id); + void openMessage(const MessageId &msg_id); private: struct mismatched_struct {