diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index f9661046c8..184d41ca0b 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -421,8 +421,8 @@ void ChartView::signalUpdated(const cabana::Signal *sig) { } } -void ChartView::msgUpdated(uint32_t address) { - if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.msg_id.address == address; })) +void ChartView::msgUpdated(MessageId id) { + if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.msg_id == id; })) updateTitle(); } diff --git a/tools/cabana/chartswidget.h b/tools/cabana/chartswidget.h index adce1e0f4d..bdc924ff83 100644 --- a/tools/cabana/chartswidget.h +++ b/tools/cabana/chartswidget.h @@ -57,11 +57,11 @@ signals: void axisYLabelWidthChanged(int w); private slots: - void msgUpdated(uint32_t address); void signalUpdated(const cabana::Signal *sig); void manageSeries(); void handleMarkerClicked(); - void msgRemoved(uint32_t address) { removeIf([=](auto &s) { return s.msg_id.address == address; }); } + void msgUpdated(MessageId id); + void msgRemoved(MessageId id) { removeIf([=](auto &s) { return s.msg_id == id; }); } void signalRemoved(const cabana::Signal *sig) { removeIf([=](auto &s) { return s.sig == sig; }); } private: diff --git a/tools/cabana/dbcmanager.cc b/tools/cabana/dbcmanager.cc index edf0007ed2..651367ba57 100644 --- a/tools/cabana/dbcmanager.cc +++ b/tools/cabana/dbcmanager.cc @@ -144,19 +144,31 @@ void DBCManager::updateMsg(const MessageId &id, const QString &name, uint32_t si auto &m = msgs[id.address]; m.name = name; m.size = size; - emit msgUpdated(id.address); + + // This DBC applies to all active sources, emit for every source + for (uint8_t source : sources) { + emit msgUpdated({.source = source, .address = id.address}); + } } void DBCManager::removeMsg(const MessageId &id) { msgs.erase(id.address); - emit msgRemoved(id.address); + + // This DBC applies to all active sources, emit for every source + for (uint8_t source : sources) { + emit msgRemoved({.source = source, .address = id.address}); + } } void DBCManager::addSignal(const MessageId &id, const cabana::Signal &sig) { if (auto m = const_cast(msg(id.address))) { m->sigs.push_back(sig); auto s = &m->sigs.last(); - emit signalAdded(id.address, s); + + // This DBC applies to all active sources, emit for every source + for (uint8_t source : sources) { + emit signalAdded({.source = source, .address = id.address}, s); + } } } @@ -192,6 +204,10 @@ QStringList DBCManager::signalNames() { return ret; } +void DBCManager::updateSources(const QSet &s) { + sources = s; +} + DBCManager *dbc() { static DBCManager dbc_manager(nullptr); return &dbc_manager; diff --git a/tools/cabana/dbcmanager.h b/tools/cabana/dbcmanager.h index 4be7593808..dd3d9811c7 100644 --- a/tools/cabana/dbcmanager.h +++ b/tools/cabana/dbcmanager.h @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include "tools/cabana/dbc.h" @@ -20,30 +22,52 @@ public: void addSignal(const MessageId &id, const cabana::Signal &sig); void updateSignal(const MessageId &id, const QString &sig_name, const cabana::Signal &sig); void removeSignal(const MessageId &id, const QString &sig_name); + inline int msgCount() const { return msgs.size(); } inline QString name() const { return name_; } 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 std::map getMessages(uint8_t source) { + std::map ret; + for (auto &[address, msg] : msgs) { + MessageId id = {.source = source, .address = address}; + ret[id] = msg; + } + return ret; + } inline const cabana::Msg *msg(const MessageId &id) const { return msg(id.address); } - inline const cabana::Msg *msg(uint32_t address) const { - auto it = msgs.find(address); - return it != msgs.end() ? &it->second : nullptr; + inline const cabana::Msg* msg(uint8_t source, const QString &name) { + for (auto &[_, msg] : msgs) { + if (msg.name == name) { + return &msg; + } + } + + return nullptr; } QStringList signalNames(); +public slots: + void updateSources(const QSet &s); + signals: - void signalAdded(uint32_t address, const cabana::Signal *sig); + void signalAdded(MessageId id, const cabana::Signal *sig); void signalRemoved(const cabana::Signal *sig); void signalUpdated(const cabana::Signal *sig); - void msgUpdated(uint32_t address); - void msgRemoved(uint32_t address); + void msgUpdated(MessageId id); + void msgRemoved(MessageId id); void DBCFileChanged(); private: void parseExtraInfo(const QString &content); std::map msgs; QString name_; + QSet sources; + + inline const cabana::Msg *msg(uint32_t address) const { + auto it = msgs.find(address); + return it != msgs.end() ? &it->second : nullptr; + } }; DBCManager *dbc(); diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index 05a0528d0e..ab723fa0e2 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -177,7 +177,7 @@ void DetailWidget::removeMsg() { // EditMessageDialog EditMessageDialog::EditMessageDialog(const MessageId &msg_id, const QString &title, int size, QWidget *parent) - : original_name(title), QDialog(parent) { + : original_name(title), msg_id(msg_id), QDialog(parent) { setWindowTitle(tr("Edit message: %1").arg(msg_id.toString())); QFormLayout *form_layout = new QFormLayout(this); @@ -207,8 +207,7 @@ void EditMessageDialog::validateName(const QString &text) { bool valid = text.compare(UNTITLED, Qt::CaseInsensitive) != 0; error_label->setVisible(false); if (!text.isEmpty() && valid && text != original_name) { - valid = std::none_of(dbc()->messages().begin(), dbc()->messages().end(), - [&text](auto &m) { return m.second.name == text; }); + valid = dbc()->msg(msg_id.source, text) == nullptr; if (!valid) { error_label->setText(tr("Name already exists")); error_label->setVisible(true); diff --git a/tools/cabana/detailwidget.h b/tools/cabana/detailwidget.h index 0bfd8a74af..cc5bffd534 100644 --- a/tools/cabana/detailwidget.h +++ b/tools/cabana/detailwidget.h @@ -15,6 +15,7 @@ public: EditMessageDialog(const MessageId &msg_id, const QString &title, int size, QWidget *parent); void validateName(const QString &text); + MessageId msg_id; QString original_name; QDialogButtonBox *btn_box; QLineEdit *name_edit; diff --git a/tools/cabana/mainwin.cc b/tools/cabana/mainwin.cc index 1559700951..56ffe872d6 100644 --- a/tools/cabana/mainwin.cc +++ b/tools/cabana/mainwin.cc @@ -42,6 +42,7 @@ MainWindow::MainWindow() : QMainWindow() { messages_widget->restoreHeaderState(settings.message_header_state); qRegisterMetaType("uint64_t"); + qRegisterMetaType>("QSet"); qRegisterMetaType("ReplyMsgType"); installMessageHandler([this](ReplyMsgType type, const std::string msg) { // use queued connection to recv the log messages from replay. @@ -70,6 +71,7 @@ MainWindow::MainWindow() : QMainWindow() { QObject::connect(can, &AbstractStream::streamStarted, this, &MainWindow::loadDBCFromFingerprint); QObject::connect(can, &AbstractStream::eventsMerged, this, &MainWindow::updateStatus); QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &MainWindow::DBCFileChanged); + QObject::connect(can, &AbstractStream::sourcesUpdated, dbc(), &DBCManager::updateSources); QObject::connect(UndoStack::instance(), &QUndoStack::cleanChanged, this, &MainWindow::undoStackCleanChanged); QObject::connect(UndoStack::instance(), &QUndoStack::indexChanged, this, &MainWindow::undoStackIndexChanged); QObject::connect(&settings, &Settings::changed, this, &MainWindow::updateStatus); @@ -310,7 +312,7 @@ void MainWindow::loadDBCFromClipboard() { QString dbc_str = QGuiApplication::clipboard()->text(); QString error; bool ret = dbc()->open("clipboard", dbc_str, &error); - if (ret && dbc()->messages().size() > 0) { + if (ret && dbc()->msgCount() > 0) { QMessageBox::information(this, tr("Load From Clipboard"), tr("DBC Successfully Loaded!")); } else { QMessageBox msg_box(QMessageBox::Warning, tr("Failed to load DBC from clipboard"), tr("Make sure that you paste the text with correct format.")); diff --git a/tools/cabana/signaledit.cc b/tools/cabana/signaledit.cc index fd04a75f81..673a68a50b 100644 --- a/tools/cabana/signaledit.cc +++ b/tools/cabana/signaledit.cc @@ -239,8 +239,7 @@ void SignalModel::addSignal(int start_bit, int size, bool little_endian) { auto msg = dbc()->msg(msg_id); for (int i = 0; !msg; ++i) { QString name = QString("NEW_MSG_") + QString::number(msg_id.address, 16).toUpper(); - if (i > 0) name += QString("_%1").arg(i); - if (std::none_of(dbc()->messages().begin(), dbc()->messages().end(), [&](auto &m) { return m.second.name == name; })) { + if (!dbc()->msg(msg_id.source, name)) { UndoStack::push(new EditMsgCommand(msg_id, name, can->lastMessage(msg_id).dat.size())); msg = dbc()->msg(msg_id); } @@ -265,14 +264,14 @@ void SignalModel::removeSignal(const cabana::Signal *sig) { UndoStack::push(new RemoveSigCommand(msg_id, sig)); } -void SignalModel::handleMsgChanged(uint32_t address) { - if (address == msg_id.address) { +void SignalModel::handleMsgChanged(MessageId id) { + if (id == msg_id) { refresh(); } } -void SignalModel::handleSignalAdded(uint32_t address, const cabana::Signal *sig) { - if (address == msg_id.address) { +void SignalModel::handleSignalAdded(MessageId id, const cabana::Signal *sig) { + if (id == msg_id) { int i = 0; for (; i < root->children.size(); ++i) { if (sig->start_bit < root->children[i]->sig->start_bit) break; @@ -442,7 +441,7 @@ SignalView::SignalView(ChartsWidget *charts, QWidget *parent) : charts(charts), QObject::connect(model, &QAbstractItemModel::modelReset, this, &SignalView::rowsChanged); QObject::connect(model, &QAbstractItemModel::rowsInserted, this, &SignalView::rowsChanged); QObject::connect(model, &QAbstractItemModel::rowsRemoved, this, &SignalView::rowsChanged); - QObject::connect(dbc(), &DBCManager::signalAdded, [this](uint32_t address, const cabana::Signal *sig) { selectSignal(sig); }); + QObject::connect(dbc(), &DBCManager::signalAdded, [this](MessageId id, const cabana::Signal *sig) { selectSignal(sig); }); setWhatsThis(tr(R"( Signal view
diff --git a/tools/cabana/signaledit.h b/tools/cabana/signaledit.h index 39fe5f270f..ae73a7b3bc 100644 --- a/tools/cabana/signaledit.h +++ b/tools/cabana/signaledit.h @@ -48,10 +48,10 @@ public: private: void insertItem(SignalModel::Item *parent_item, int pos, const cabana::Signal *sig); - void handleSignalAdded(uint32_t address, const cabana::Signal *sig); + void handleSignalAdded(MessageId id, const cabana::Signal *sig); void handleSignalUpdated(const cabana::Signal *sig); void handleSignalRemoved(const cabana::Signal *sig); - void handleMsgChanged(uint32_t address); + void handleMsgChanged(MessageId id); void refresh(); void updateState(const QHash *msgs); diff --git a/tools/cabana/streams/abstractstream.cc b/tools/cabana/streams/abstractstream.cc index 40e9cbc8a5..c8ff449098 100644 --- a/tools/cabana/streams/abstractstream.cc +++ b/tools/cabana/streams/abstractstream.cc @@ -39,6 +39,11 @@ bool AbstractStream::updateEvent(const Event *event) { data.colors = tracker.colors; data.last_change_t = tracker.last_change_t; data.bit_change_counts = tracker.bit_change_counts; + + if (!sources.contains(id.source)) { + sources.insert(id.source); + emit sourcesUpdated(sources); + } } double ts = millis_since_boot(); diff --git a/tools/cabana/streams/abstractstream.h b/tools/cabana/streams/abstractstream.h index e582682971..de7c394303 100644 --- a/tools/cabana/streams/abstractstream.h +++ b/tools/cabana/streams/abstractstream.h @@ -52,9 +52,11 @@ signals: void updated(); void msgsReceived(const QHash *); void received(QHash *); + void sourcesUpdated(const QSet &s); public: QHash can_msgs; + QSet sources; protected: void process(QHash *); diff --git a/tools/cabana/tests/test_cabana.cc b/tools/cabana/tests/test_cabana.cc index 124eb7428a..8445867acb 100644 --- a/tools/cabana/tests/test_cabana.cc +++ b/tools/cabana/tests/test_cabana.cc @@ -15,11 +15,11 @@ TEST_CASE("DBCManager::generateDBC") { DBCManager dbc_from_generated(nullptr); dbc_from_generated.open("", dbc_origin.generateDBC()); - auto &msgs = dbc_origin.messages(); - auto &new_msgs = dbc_from_generated.messages(); - REQUIRE(msgs.size() == new_msgs.size()); - for (auto &[address, m] : msgs) { - auto &new_m = new_msgs.at(address); + REQUIRE(dbc_origin.msgCount() == dbc_from_generated.msgCount()); + auto msgs = dbc_origin.getMessages(0); + auto new_msgs = dbc_from_generated.getMessages(0); + for (auto &[id, m] : msgs) { + auto &new_m = new_msgs.at(id); REQUIRE(m.name == new_m.name); REQUIRE(m.size == new_m.size); REQUIRE(m.getSignals().size() == new_m.getSignals().size()); @@ -43,7 +43,7 @@ TEST_CASE("Parse can messages") { if (e->which == cereal::Event::Which::CAN) { std::map, std::vector> values_1; for (const auto &c : e->event.getCan()) { - const auto msg = dbc.msg(c.getAddress()); + const auto msg = dbc.msg({.source = c.getSrc(), .address = c.getAddress()}); if (c.getSrc() == 0 && msg) { for (auto sig : msg->getSignals()) { double val = get_raw_value((uint8_t *)c.getDat().begin(), c.getDat().size(), *sig); diff --git a/tools/cabana/tools/findsimilarbits.cc b/tools/cabana/tools/findsimilarbits.cc index ffb0e54b0e..7768359df4 100644 --- a/tools/cabana/tools/findsimilarbits.cc +++ b/tools/cabana/tools/findsimilarbits.cc @@ -29,8 +29,9 @@ FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::Wi bus_combo->setCurrentIndex(0); msg_cb = new QComboBox(this); - for (auto &[address, msg] : dbc()->messages()) { - msg_cb->addItem(msg.name, address); + // TODO: update when bus_combo changes + for (auto &[id, msg] : dbc()->getMessages(0)) { + msg_cb->addItem(msg.name, id.address); } msg_cb->model()->sort(0); msg_cb->setCurrentIndex(0);