cabana: refactor message id from QString to struct (#27352)

* cabana: refactor message id from QString to struct

* fix tabbar

* fix findsimilarbits

* optimize hash function

* cleanup sorting

* use in updateLastMsgsTo
pull/27354/head
Willem Melching 2 years ago committed by GitHub
parent 00513f1001
commit 5078c91805
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      tools/cabana/binaryview.cc
  2. 8
      tools/cabana/binaryview.h
  3. 27
      tools/cabana/chartswidget.cc
  4. 28
      tools/cabana/chartswidget.h
  5. 18
      tools/cabana/commands.cc
  6. 20
      tools/cabana/commands.h
  7. 34
      tools/cabana/dbcmanager.cc
  8. 44
      tools/cabana/dbcmanager.h
  9. 51
      tools/cabana/detailwidget.cc
  10. 9
      tools/cabana/detailwidget.h
  11. 17
      tools/cabana/historylog.cc
  12. 8
      tools/cabana/historylog.h
  13. 22
      tools/cabana/messageswidget.cc
  14. 14
      tools/cabana/messageswidget.h
  15. 10
      tools/cabana/signaledit.cc
  16. 12
      tools/cabana/signaledit.h
  17. 19
      tools/cabana/streams/abstractstream.cc
  18. 17
      tools/cabana/streams/abstractstream.h
  19. 8
      tools/cabana/tools/findsimilarbits.cc
  20. 4
      tools/cabana/tools/findsimilarbits.h

@ -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<int, int, bool> 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.

@ -1,5 +1,7 @@
#pragma once
#include <optional>
#include <QApplication>
#include <QList>
#include <QSet>
@ -46,7 +48,7 @@ public:
};
std::vector<Item> items;
QString msg_id;
std::optional<MessageId> 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<const Signal*> 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();

@ -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("<span style=\"text-decoration:%1\"><b>%2</b> <font color=\"gray\">%3 %4</font></span>").arg(decoration, s.sig->name.c_str(), msgName(s.msg_id), s.msg_id));
s.series->setName(QString("<span style=\"text-decoration:%1\"><b>%2</b> <font color=\"gray\">%3 %4</font></span>").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<Event *> *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<MessageId>()) {
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<MessageId>();
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("<span style=\"color:%0;\">■ </span> %1").arg(getColor(sig).name(), sig->name.c_str());
if (show_msg_name) text += QString(" <font color=\"gray\">%0 %1</font>").arg(msgName(id), id);
if (show_msg_name) text += QString(" <font color=\"gray\">%0 %1</font>").arg(msgName(id), id.toString());
QLabel *label = new QLabel(text);
label->setContentsMargins(5, 0, 5, 0);

@ -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<Event*> *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<QPointF> 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<ListItem *> 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);

@ -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()));
}

@ -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 = {};
};

@ -4,6 +4,10 @@
#include <sstream>
#include <QVector>
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<DBCMsg *>(msg(id))) {
void DBCManager::addSignal(const MessageId &id, const Signal &sig) {
if (auto m = const_cast<DBCMsg *>(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<DBCMsg *>(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<DBCMsg *>(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<uint8_t, uint32_t> 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;

@ -5,6 +5,35 @@
#include <QString>
#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<uint8_t, uint32_t> parseId(const QString &id);
inline static std::vector<std::string> 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<uint32_t, DBCMsg> &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<int, int> 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;
}

@ -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<QString, CanData> *msgs) {
void DetailWidget::updateState(const QHash<MessageId, CanData> *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<QString, CanData> *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);

@ -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<QString, CanData> * msgs = nullptr);
void updateState(const QHash<MessageId, CanData> * msgs = nullptr);
QString msg_id;
std::optional<MessageId> msg_id;
QLabel *time_label, *warning_icon, *warning_label;
ElidedLabel *name_label;
QWidget *warning_widget;
QTabBar *tabbar;
QList<MessageId> tabbar_ids;
QTabWidget *tab_widget;
QAction *remove_msg_act;
LogsWidget *history_log;

@ -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 <class InputIt>
std::deque<HistoryLogModel::Message> HistoryLogModel::fetchData(InputIt first, InputIt last, uint64_t min_time) {
std::deque<HistoryLogModel::Message> msgs;
const auto [src, address] = DBCManager::parseId(msg_id);
QVector<double> 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::Message> HistoryLogModel::fetchData<>(std::
std::deque<HistoryLogModel::Message> 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();

@ -1,6 +1,8 @@
#pragma once
#include <deque>
#include <optional>
#include <QCheckBox>
#include <QComboBox>
#include <QHeaderView>
@ -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<bool(double, double)> cmp);
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
@ -52,7 +54,7 @@ public:
std::deque<HistoryLogModel::Message> fetchData(InputIt first, InputIt last, uint64_t min_time);
std::deque<Message> fetchData(uint64_t from_time, uint64_t min_time = 0);
QString msg_id;
std::optional<MessageId> 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(); }

@ -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 &current, 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<QString, CanData> *new_msgs) {
void MessageListModel::msgsReceived(const QHash<MessageId, CanData> *new_msgs) {
int prev_row_count = msgs.size();
if (filter_str.isEmpty() && msgs.size() != can->can_msgs.size()) {
msgs = can->can_msgs.keys();

@ -1,5 +1,7 @@
#pragma once
#include <optional>
#include <QAbstractTableModel>
#include <QHeaderView>
#include <QLineEdit>
@ -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<QString, CanData> *new_msgs = nullptr);
void msgsReceived(const QHash<MessageId, CanData> *new_msgs = nullptr);
void sortMessages();
void suppress();
void clearSuppress();
void reset();
QStringList msgs;
QSet<std::pair<QString, int>> suppressed_bytes;
QList<MessageId> msgs;
QSet<std::pair<MessageId, int>> 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<MessageId> current_msg_id;
QLineEdit *filter;
MessageListModel *model;
QPushButton *suppress_add;

@ -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<QString, CanData> *msgs) {
void SignalModel::updateState(const QHash<MessageId, CanData> *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);

@ -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<QString, CanData> *msgs);
void updateState(const QHash<MessageId, CanData> *msgs);
QString msg_id;
MessageId msg_id;
QString filter_str;
std::unique_ptr<Item> 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;

@ -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<QHash<QString, CanData>>();
new_msgs = std::make_unique<QHash<MessageId, CanData>>();
QObject::connect(this, &AbstractStream::received, this, &AbstractStream::process, Qt::QueuedConnection);
QObject::connect(this, &AbstractStream::seekedTo, this, &AbstractStream::updateLastMsgsTo);
}
void AbstractStream::process(QHash<QString, CanData> *messages) {
void AbstractStream::process(QHash<MessageId, CanData> *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<QString, CanData>);
new_msgs.reset(new QHash<MessageId, CanData>);
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<std::pair<uint8_t, uint32_t>, CanData> last_msgs; // Much faster than QHash<String, CanData>
QHash<MessageId, CanData> 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);

@ -5,6 +5,7 @@
#include <QColor>
#include <QHash>
#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<Event *> *events() const = 0;
@ -49,22 +50,22 @@ signals:
void streamStarted();
void eventsMerged();
void updated();
void msgsReceived(const QHash<QString, CanData> *);
void received(QHash<QString, CanData> *);
void msgsReceived(const QHash<MessageId, CanData> *);
void received(QHash<MessageId, CanData> *);
public:
QHash<QString, CanData> can_msgs;
QHash<MessageId, CanData> can_msgs;
protected:
void process(QHash<QString, CanData> *);
void process(QHash<MessageId, CanData> *);
bool updateEvent(const Event *event);
void updateLastMsgsTo(double sec);
bool is_live_streaming = false;
std::atomic<bool> processing = false;
QHash<QString, uint32_t> counters;
std::unique_ptr<QHash<QString, CanData>> new_msgs;
QHash<QString, ChangeTracker> change_trackers;
QHash<MessageId, uint32_t> counters;
std::unique_ptr<QHash<MessageId, CanData>> new_msgs;
QHash<MessageId, ChangeTracker> change_trackers;
};
// A global pointer referring to the unique AbstractStream object

@ -20,10 +20,10 @@ FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::Wi
bus_combo = new QComboBox(this);
QSet<uint8_t> 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);
}
});
}

@ -6,6 +6,8 @@
#include <QSpinBox>
#include <QTableWidget>
#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 {

Loading…
Cancel
Save