From ff4aae85fe39b6442c03963a6a8cbfc900ba61c3 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Fri, 9 Jun 2023 04:41:55 +0800 Subject: [PATCH] cabana: refactor dbc manager (#28445) * rafactor signal * cleanup * refacto dbcmanager * refactor dbcmanger --- tools/cabana/binaryview.cc | 9 +- tools/cabana/chart/chart.cc | 12 +- tools/cabana/chart/chart.h | 2 +- tools/cabana/chart/signalselector.cc | 2 +- tools/cabana/chart/sparkline.cc | 2 +- tools/cabana/dbc/dbc.cc | 113 ++++++++-- tools/cabana/dbc/dbc.h | 88 ++++---- tools/cabana/dbc/dbcfile.cc | 118 ++--------- tools/cabana/dbc/dbcfile.h | 33 +-- tools/cabana/dbc/dbcmanager.cc | 295 ++++++++------------------ tools/cabana/dbc/dbcmanager.h | 77 +++---- tools/cabana/historylog.cc | 2 +- tools/cabana/historylog.h | 2 +- tools/cabana/mainwin.cc | 58 ++--- tools/cabana/mainwin.h | 1 - tools/cabana/messageswidget.cc | 2 +- tools/cabana/signalview.cc | 10 +- tools/cabana/tests/test_cabana.cc | 28 +-- tools/cabana/tools/findsimilarbits.cc | 6 +- tools/cabana/util.cc | 20 +- tools/cabana/util.h | 5 +- 21 files changed, 353 insertions(+), 532 deletions(-) diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc index 13cd76af3a..9865907069 100644 --- a/tools/cabana/binaryview.cc +++ b/tools/cabana/binaryview.cc @@ -165,7 +165,7 @@ void BinaryView::mousePressEvent(QMouseEvent *event) { if (bit_idx == s->lsb || bit_idx == s->msb) { anchor_index = model->bitIndex(bit_idx == s->lsb ? s->msb : s->lsb, true); resize_sig = s; - delegate->selection_color = getColor(s); + delegate->selection_color = s->color; break; } } @@ -381,7 +381,7 @@ void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op if (item->sigs.size() > 0) { for (auto &s : item->sigs) { if (s == bin_view->hovered_sig) { - painter->fillRect(option.rect, getColor(bin_view->hovered_sig).darker(125)); // 4/5x brightness + painter->fillRect(option.rect, s->color.darker(125)); // 4/5x brightness } else { drawSignalCell(painter, option, index, s); } @@ -434,15 +434,14 @@ void BinaryItemDelegate::drawSignalCell(QPainter *painter, const QStyleOptionVie painter->setClipRegion(QRegion(rc).subtracted(subtract)); auto item = (const BinaryViewModel::Item *)index.internalPointer(); - auto sig_color = getColor(sig); - QColor color = sig_color; + QColor color = sig->color; color.setAlpha(item->bg_color.alpha()); // Mixing the signal colour with the Base background color to fade it painter->fillRect(rc, QApplication::palette().color(QPalette::Base)); painter->fillRect(rc, color); // Draw edges - color = sig_color.darker(125); + color = sig->color.darker(125); painter->setPen(QPen(color, 1)); if (draw_left) painter->drawLine(rc.topLeft(), rc.bottomLeft()); if (draw_right) painter->drawLine(rc.topRight(), rc.bottomRight()); diff --git a/tools/cabana/chart/chart.cc b/tools/cabana/chart/chart.cc index 353bb3fab3..622b79d806 100644 --- a/tools/cabana/chart/chart.cc +++ b/tools/cabana/chart/chart.cc @@ -38,7 +38,6 @@ ChartView::ChartView(const std::pair &x_range, ChartsWidget *par setChart(chart); createToolButtons(); - // TODO: enable zoomIn/seekTo in live streaming mode. setRubberBand(QChartView::HorizontalRubberBand); setMouseTracking(true); setTheme(settings.theme == DARK_THEME ? QChart::QChart::ChartThemeDark : QChart::ChartThemeLight); @@ -107,14 +106,14 @@ void ChartView::setTheme(QChart::ChartTheme theme) { chart()->legend()->setLabelColor(palette().color(QPalette::Text)); } for (auto &s : sigs) { - s.series->setColor(getColor(s.sig)); + s.series->setColor(s.sig->color); } } void ChartView::addSignal(const MessageId &msg_id, const cabana::Signal *sig) { if (hasSignal(msg_id, sig)) return; - QXYSeries *series = createSeries(series_type, getColor(sig)); + QXYSeries *series = createSeries(series_type, sig->color); sigs.push_back({.msg_id = msg_id, .sig = sig, .series = series}); updateSeries(sig); updateSeriesPoints(); @@ -154,8 +153,9 @@ void ChartView::signalUpdated(const cabana::Signal *sig) { } void ChartView::msgUpdated(MessageId id) { - if (std::any_of(sigs.cbegin(), sigs.cend(), [=](auto &s) { return s.msg_id == id; })) + if (std::any_of(sigs.cbegin(), sigs.cend(), [=](auto &s) { return s.msg_id.address == id.address; })) { updateTitle(); + } } void ChartView::manageSignals() { @@ -277,7 +277,7 @@ void ChartView::updateSeries(const cabana::Signal *sig, bool clear) { s.step_vals.clear(); s.last_value_mono_time = 0; } - s.series->setColor(getColor(s.sig)); + s.series->setColor(s.sig->color); const auto &msgs = can->events(s.msg_id); s.vals.reserve(msgs.capacity()); @@ -799,7 +799,7 @@ void ChartView::setSeriesType(SeriesType type) { s.series->deleteLater(); } for (auto &s : sigs) { - auto series = createSeries(series_type, getColor(s.sig)); + auto series = createSeries(series_type, s.sig->color); series->replace(series_type == SeriesType::StepLine ? s.step_vals : s.vals); s.series = series; } diff --git a/tools/cabana/chart/chart.h b/tools/cabana/chart/chart.h index 3bb191e5cd..272ea0d193 100644 --- a/tools/cabana/chart/chart.h +++ b/tools/cabana/chart/chart.h @@ -56,7 +56,7 @@ private slots: void manageSignals(); void handleMarkerClicked(); void msgUpdated(MessageId id); - void msgRemoved(MessageId id) { removeIf([=](auto &s) { return s.msg_id == id; }); } + void msgRemoved(MessageId id) { removeIf([=](auto &s) { return s.msg_id.address == id.address && !dbc()->msg(id); }); } void signalRemoved(const cabana::Signal *sig) { removeIf([=](auto &s) { return s.sig == sig; }); } private: diff --git a/tools/cabana/chart/signalselector.cc b/tools/cabana/chart/signalselector.cc index 1aa8fc5016..50fe861a03 100644 --- a/tools/cabana/chart/signalselector.cc +++ b/tools/cabana/chart/signalselector.cc @@ -91,7 +91,7 @@ void SignalSelector::updateAvailableList(int index) { } void SignalSelector::addItemToList(QListWidget *parent, const MessageId id, const cabana::Signal *sig, bool show_msg_name) { - QString text = QString(" %1").arg(getColor(sig).name(), sig->name); + QString text = QString(" %1").arg(sig->color.name(), sig->name); if (show_msg_name) text += QString(" %0 %1").arg(msgName(id), id.toString()); QLabel *label = new QLabel(text); diff --git a/tools/cabana/chart/sparkline.cc b/tools/cabana/chart/sparkline.cc index 6d7b35f3a9..bac867bd20 100644 --- a/tools/cabana/chart/sparkline.cc +++ b/tools/cabana/chart/sparkline.cc @@ -37,7 +37,7 @@ void Sparkline::update(const MessageId &msg_id, const cabana::Signal *sig, doubl max_val += 1; } } - render(getColor(sig), size); + render(sig->color, size); } else { pixmap = QPixmap(); min_val = -1; diff --git a/tools/cabana/dbc/dbc.cc b/tools/cabana/dbc/dbc.cc index aaa4a97ea9..1ac99ad464 100644 --- a/tools/cabana/dbc/dbc.cc +++ b/tools/cabana/dbc/dbc.cc @@ -1,32 +1,96 @@ #include "tools/cabana/dbc/dbc.h" + #include "tools/cabana/util.h" uint qHash(const MessageId &item) { return qHash(item.source) ^ qHash(item.address); } -std::vector cabana::Msg::getSignals() const { - std::vector ret; - ret.reserve(sigs.size()); - for (auto &sig : sigs) ret.push_back(&sig); - std::sort(ret.begin(), ret.end(), [](auto l, auto r) { - if (l->start_bit != r->start_bit) { - return l->start_bit < r->start_bit; - } - // For VECTOR__INDEPENDENT_SIG_MSG, many signals have same start bit - return l->name < r->name; - }); - return ret; +// cabana::Msg + +cabana::Msg::~Msg() { + for (auto s : sigs) { + delete s; + } +} + +cabana::Signal *cabana::Msg::addSignal(const cabana::Signal &sig) { + auto s = sigs.emplace_back(new cabana::Signal(sig)); + update(); + return s; +} + +cabana::Signal *cabana::Msg::updateSignal(const QString &sig_name, const cabana::Signal &new_sig) { + auto s = sig(sig_name); + if (s) { + *s = new_sig; + update(); + } + return s; +} + +void cabana::Msg::removeSignal(const QString &sig_name) { + auto it = std::find_if(sigs.begin(), sigs.end(), [&](auto &s) { return s->name == sig_name; }); + if (it != sigs.end()) { + delete *it; + sigs.erase(it); + update(); + } +} + +cabana::Msg &cabana::Msg::operator=(const cabana::Msg &other) { + address = other.address; + name = other.name; + size = other.size; + comment = other.comment; + + for (auto s : sigs) delete s; + sigs.clear(); + for (auto s : other.sigs) { + sigs.push_back(new cabana::Signal(*s)); + } + + update(); + return *this; +} + +cabana::Signal *cabana::Msg::sig(const QString &sig_name) const { + auto it = std::find_if(sigs.begin(), sigs.end(), [&](auto &s) { return s->name == sig_name; }); + return it != sigs.end() ? *it : nullptr; +} + +int cabana::Msg::indexOf(const cabana::Signal *sig) const { + for (int i = 0; i < sigs.size(); ++i) { + if (sigs[i] == sig) return i; + } + return -1; } -void cabana::Msg::updateMask() { +QString cabana::Msg::newSignalName() { + QString new_name; + for (int i = 1; /**/; ++i) { + new_name = QString("NEW_SIGNAL_%1").arg(i); + if (sig(new_name) == nullptr) break; + } + return new_name; +} + +void cabana::Msg::update() { mask = QVector(size, 0x00).toList(); + // sort signals + std::sort(sigs.begin(), sigs.end(), [](auto l, auto r) { + return std::tie(l->start_bit, l->name) < std::tie(r->start_bit, r->name); + }); + for (auto &sig : sigs) { - int i = sig.msb / 8; - int bits = sig.size; + sig->update(); + + // update mask + int i = sig->msb / 8; + int bits = sig->size; while (i >= 0 && i < size && bits > 0) { - int lsb = (int)(sig.lsb / 8) == i ? sig.lsb : i * 8; - int msb = (int)(sig.msb / 8) == i ? sig.msb : (i + 1) * 8 - 1; + int lsb = (int)(sig->lsb / 8) == i ? sig->lsb : i * 8; + int msb = (int)(sig->msb / 8) == i ? sig->msb : (i + 1) * 8 - 1; int sz = msb - lsb + 1; int shift = (lsb - (i * 8)); @@ -34,18 +98,27 @@ void cabana::Msg::updateMask() { mask[i] |= ((1ULL << sz) - 1) << shift; bits -= size; - i = sig.is_little_endian ? i - 1 : i + 1; + i = sig->is_little_endian ? i - 1 : i + 1; } } } -void cabana::Signal::updatePrecision() { +// cabana::Signal + +void cabana::Signal::update() { + float h = 19 * (float)lsb / 64.0; + h = fmod(h, 1.0); + size_t hash = qHash(name); + float s = 0.25 + 0.25 * (float)(hash & 0xff) / 255.0; + float v = 0.75 + 0.25 * (float)((hash >> 8) & 0xff) / 255.0; + + color = QColor::fromHsvF(h, s, v); precision = std::max(num_decimals(factor), num_decimals(offset)); } QString cabana::Signal::formatValue(double value) const { // Show enum string - for (auto &[val, desc] : val_desc) { + for (const auto &[val, desc] : val_desc) { if (std::abs(value - val) < 1e-6) { return desc; } diff --git a/tools/cabana/dbc/dbc.h b/tools/cabana/dbc/dbc.h index ad5f33a260..56a3ea9a65 100644 --- a/tools/cabana/dbc/dbc.h +++ b/tools/cabana/dbc/dbc.h @@ -1,9 +1,10 @@ #pragma once -#include +#include #include #include #include +#include #include "opendbc/can/common_dbc.h" @@ -45,41 +46,55 @@ struct std::hash { typedef QList> ValueDescription; namespace cabana { - struct Signal { - QString name; - int start_bit, msb, lsb, size; - bool is_signed; - double factor, offset; - bool is_little_endian; - double min, max; - QString unit; - QString comment; - ValueDescription val_desc; - int precision = 0; - void updatePrecision(); - QString formatValue(double value) const; - }; - - struct Msg { - uint32_t address; - QString name; - uint32_t size; - QString comment; - QList sigs; - - QList mask; - void updateMask(); - - std::vector getSignals() const; - const cabana::Signal *sig(const QString &sig_name) const { - auto it = std::find_if(sigs.begin(), sigs.end(), [&](auto &s) { return s.name == sig_name; }); - return it != sigs.end() ? &(*it) : nullptr; - } - }; - - bool operator==(const cabana::Signal &l, const cabana::Signal &r); - inline bool operator!=(const cabana::Signal &l, const cabana::Signal &r) { return !(l == r); } -} + +class Signal { +public: + Signal() = default; + Signal(const Signal &other) = default; + void update(); + QString formatValue(double value) const; + + QString name; + int start_bit, msb, lsb, size; + double factor, offset; + bool is_signed; + bool is_little_endian; + double min, max; + QString unit; + QString comment; + ValueDescription val_desc; + int precision = 0; + QColor color; +}; + +class Msg { +public: + Msg() = default; + Msg(const Msg &other) { *this = other; } + ~Msg(); + cabana::Signal *addSignal(const cabana::Signal &sig); + cabana::Signal *updateSignal(const QString &sig_name, const cabana::Signal &sig); + void removeSignal(const QString &sig_name); + Msg &operator=(const Msg &other); + int indexOf(const cabana::Signal *sig) const; + cabana::Signal *sig(const QString &sig_name) const; + QString newSignalName(); + inline const std::vector &getSignals() const { return sigs; } + + uint32_t address; + QString name; + uint32_t size; + QString comment; + std::vector sigs; + + QList mask; + void update(); +}; + +bool operator==(const cabana::Signal &l, const cabana::Signal &r); +inline bool operator!=(const cabana::Signal &l, const cabana::Signal &r) { return !(l == r); } + +} // namespace cabana // Helper functions double get_raw_value(const uint8_t *data, size_t data_size, const cabana::Signal &sig); @@ -89,4 +104,3 @@ void updateSigSizeParamsFromRange(cabana::Signal &s, int start_bit, int size); std::pair getSignalRange(const cabana::Signal *s); inline std::vector allDBCNames() { return get_dbc_names(); } inline QString doubleToString(double value) { return QString::number(value, 'g', std::numeric_limits::digits10); } - diff --git a/tools/cabana/dbc/dbcfile.cc b/tools/cabana/dbc/dbcfile.cc index 2a8d3d2d54..6de00fe77d 100644 --- a/tools/cabana/dbc/dbcfile.cc +++ b/tools/cabana/dbc/dbcfile.cc @@ -37,20 +37,18 @@ void DBCFile::open(const QString &content) { m.name = msg.name.c_str(); m.size = msg.size; for (auto &s : msg.sigs) { - m.sigs.push_back({}); - auto &sig = m.sigs.last(); - sig.name = s.name.c_str(); - sig.start_bit = s.start_bit; - sig.msb = s.msb; - sig.lsb = s.lsb; - sig.size = s.size; - sig.is_signed = s.is_signed; - sig.factor = s.factor; - sig.offset = s.offset; - sig.is_little_endian = s.is_little_endian; - sig.updatePrecision(); + auto sig = m.sigs.emplace_back(new cabana::Signal); + sig->name = s.name.c_str(); + sig->start_bit = s.start_bit; + sig->msb = s.msb; + sig->lsb = s.lsb; + sig->size = s.size; + sig->is_signed = s.is_signed; + sig->factor = s.factor; + sig->offset = s.offset; + sig->is_little_endian = s.is_little_endian; } - m.updateMask(); + m.update(); } parseExtraInfo(content); @@ -58,7 +56,7 @@ void DBCFile::open(const QString &content) { } bool DBCFile::save() { - assert (!filename.isEmpty()); + assert(!filename.isEmpty()); if (writeContents(filename)) { cleanupAutoSaveFile(); return true; @@ -90,41 +88,6 @@ bool DBCFile::writeContents(const QString &fn) { return false; } -cabana::Signal *DBCFile::addSignal(const MessageId &id, const cabana::Signal &sig) { - if (auto m = const_cast(msg(id.address))) { - m->sigs.push_back(sig); - m->updateMask(); - return &m->sigs.last(); - } - return nullptr; -} - - cabana::Signal *DBCFile::updateSignal(const MessageId &id, const QString &sig_name, const cabana::Signal &sig) { - if (auto m = const_cast(msg(id))) { - if (auto s = (cabana::Signal *)m->sig(sig_name)) { - *s = sig; - m->updateMask(); - return s; - } - } - return nullptr; -} - -cabana::Signal *DBCFile::getSignal(const MessageId &id, const QString &sig_name) { - auto m = msg(id); - return m ? (cabana::Signal *)m->sig(sig_name) : nullptr; -} - -void DBCFile::removeSignal(const MessageId &id, const QString &sig_name) { - if (auto m = const_cast(msg(id))) { - auto it = std::find_if(m->sigs.begin(), m->sigs.end(), [&](auto &s) { return s.name == sig_name; }); - if (it != m->sigs.end()) { - m->sigs.erase(it); - m->updateMask(); - } - } -} - void DBCFile::updateMsg(const MessageId &id, const QString &name, uint32_t size, const QString &comment) { auto &m = msgs[id.address]; m.address = id.address; @@ -133,60 +96,17 @@ void DBCFile::updateMsg(const MessageId &id, const QString &name, uint32_t size, m.comment = comment; } -void DBCFile::removeMsg(const MessageId &id) { - msgs.erase(id.address); -} - -QString DBCFile::newMsgName(const MessageId &id) { - return QString("NEW_MSG_") + QString::number(id.address, 16).toUpper(); -} - -QString DBCFile::newSignalName(const MessageId &id) { - auto m = msg(id); - assert(m != nullptr); - - QString name; - for (int i = 1; /**/; ++i) { - name = QString("NEW_SIGNAL_%1").arg(i); - if (m->sig(name) == nullptr) break; - } - return name; -} - -const QList& DBCFile::mask(const MessageId &id) const { - auto m = msg(id); - return m ? m->mask : empty_mask; -} - -const cabana::Msg *DBCFile::msg(uint32_t address) const { +cabana::Msg *DBCFile::msg(uint32_t address) { auto it = msgs.find(address); return it != msgs.end() ? &it->second : nullptr; } -const cabana::Msg* DBCFile::msg(const QString &name) { - auto it = std::find_if(msgs.cbegin(), msgs.cend(), [&name](auto &m) { return m.second.name == name; }); - return it != msgs.cend() ? &(it->second) : nullptr; -} - -QStringList DBCFile::signalNames() const { - // Used for autocompletion - QStringList ret; - for (auto const& [_, msg] : msgs) { - for (auto sig: msg.getSignals()) { - ret << sig->name; - } - } - ret.sort(); - ret.removeDuplicates(); - return ret; -} - -int DBCFile::signalCount(const MessageId &id) const { - if (msgs.count(id.address) == 0) return 0; - return msgs.at(id.address).sigs.size(); +cabana::Msg *DBCFile::msg(const QString &name) { + auto it = std::find_if(msgs.begin(), msgs.end(), [&name](auto &m) { return m.second.name == name; }); + return it != msgs.end() ? &(it->second) : nullptr; } -int DBCFile::signalCount() const { +int DBCFile::signalCount() { return std::accumulate(msgs.cbegin(), msgs.cend(), 0, [](int &n, const auto &m) { return n + m.second.sigs.size(); }); } @@ -194,8 +114,8 @@ void DBCFile::parseExtraInfo(const QString &content) { static QRegularExpression bo_regexp(R"(^BO_ (\w+) (\w+) *: (\w+) (\w+))"); static QRegularExpression sg_regexp(R"(^SG_ (\w+) : (\d+)\|(\d+)@(\d+)([\+|\-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] \"(.*)\" (.*))"); static QRegularExpression sgm_regexp(R"(^SG_ (\w+) (\w+) *: (\d+)\|(\d+)@(\d+)([\+|\-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] \"(.*)\" (.*))"); - static QRegularExpression msg_comment_regexp(R"(^CM_ BO_ *(\w+) *\"([^"]*)\";)"); - static QRegularExpression sg_comment_regexp(R"(^CM_ SG_ *(\w+) *(\w+) *\"([^"]*)\";)"); + static QRegularExpression msg_comment_regexp(R"(^CM_ BO_ *(\w+) *\"([^"]*)\"\s*;)"); + static QRegularExpression sg_comment_regexp(R"(^CM_ SG_ *(\w+) *(\w+) *\"([^"]*)\"\s*;)"); static QRegularExpression val_regexp(R"(VAL_ (\w+) (\w+) (\s*[-+]?[0-9]+\s+\".+?\"[^;]*))"); int line_num = 0; diff --git a/tools/cabana/dbc/dbcfile.h b/tools/cabana/dbc/dbcfile.h index 1ed9e9cd0a..76e71e189e 100644 --- a/tools/cabana/dbc/dbcfile.h +++ b/tools/cabana/dbc/dbcfile.h @@ -1,9 +1,7 @@ #pragma once #include -#include #include -#include #include "tools/cabana/dbc/dbc.h" @@ -26,30 +24,18 @@ public: void cleanupAutoSaveFile(); QString generateDBC(); - cabana::Signal *addSignal(const MessageId &id, const cabana::Signal &sig); - cabana::Signal *updateSignal(const MessageId &id, const QString &sig_name, const cabana::Signal &sig); - cabana::Signal *getSignal(const MessageId &id, const QString &sig_name); - void removeSignal(const MessageId &id, const QString &sig_name); - void updateMsg(const MessageId &id, const QString &name, uint32_t size, const QString &comment); - void removeMsg(const MessageId &id); - - QString newMsgName(const MessageId &id); - QString newSignalName(const MessageId &id); - - const QList& mask(const MessageId &id) const; + inline void removeMsg(const MessageId &id) { msgs.erase(id.address); } - inline std::map getMessages() const { return msgs; } - const cabana::Msg *msg(uint32_t address) const; - const cabana::Msg* msg(const QString &name); - inline const cabana::Msg *msg(const MessageId &id) const { return msg(id.address); }; + inline const std::map &getMessages() const { return msgs; } + cabana::Msg *msg(uint32_t address); + cabana::Msg *msg(const QString &name); + inline cabana::Msg *msg(const MessageId &id) { return msg(id.address); } - QStringList signalNames() const; - int signalCount(const MessageId &id) const; - int signalCount() const; - inline int msgCount() const { return msgs.size(); } - inline QString name() const { return name_.isEmpty() ? "untitled" : name_; } - inline bool isEmpty() const { return (signalCount() == 0) && name_.isEmpty(); } + int signalCount(); + inline int msgCount() { return msgs.size(); } + inline QString name() { return name_.isEmpty() ? "untitled" : name_; } + inline bool isEmpty() { return (signalCount() == 0) && name_.isEmpty(); } QString filename; @@ -57,5 +43,4 @@ private: void parseExtraInfo(const QString &content); std::map msgs; QString name_; - QList empty_mask; }; diff --git a/tools/cabana/dbc/dbcmanager.cc b/tools/cabana/dbc/dbcmanager.cc index 2176635caa..388844098a 100644 --- a/tools/cabana/dbc/dbcmanager.cc +++ b/tools/cabana/dbc/dbcmanager.cc @@ -1,21 +1,16 @@ #include "tools/cabana/dbc/dbcmanager.h" -#include - -bool DBCManager::open(SourceSet s, const QString &dbc_file_name, QString *error) { - for (int i = 0; i < dbc_files.size(); i++) { - auto [ss, dbc_file] = dbc_files[i]; - - // Check if file is already open, and merge sources - if (dbc_file->filename == dbc_file_name) { - dbc_files[i] = {ss | s, dbc_file}; - emit DBCFileChanged(); - return true; - } - } +#include +#include +bool DBCManager::open(const SourceSet &sources, const QString &dbc_file_name, QString *error) { try { - dbc_files.push_back({s, new DBCFile(dbc_file_name, this)}); + auto it = std::find_if(dbc_files.begin(), dbc_files.end(), + [&](auto &f) { return f.second && f.second->filename == dbc_file_name; }); + auto file = (it != dbc_files.end()) ? it->second : std::make_shared(dbc_file_name, this); + for (auto s : sources) { + dbc_files[s] = file; + } } catch (std::exception &e) { if (error) *error = e.what(); return false; @@ -25,9 +20,12 @@ bool DBCManager::open(SourceSet s, const QString &dbc_file_name, QString *error) return true; } -bool DBCManager::open(SourceSet s, const QString &name, const QString &content, QString *error) { +bool DBCManager::open(const SourceSet &sources, const QString &name, const QString &content, QString *error) { try { - dbc_files.push_back({s, new DBCFile(name, content, this)}); + auto file = std::make_shared(name, content, this); + for (auto s : sources) { + dbc_files[s] = file; + } } catch (std::exception &e) { if (error) *error = e.what(); return false; @@ -37,263 +35,154 @@ bool DBCManager::open(SourceSet s, const QString &name, const QString &content, return true; } -void DBCManager::close(SourceSet s) { - // Build new list of dbc files, removing the ones that match the sourceset - QList> new_dbc_files; - for (auto entry : dbc_files) { - if (entry.first == s) { - delete entry.second; - } else { - new_dbc_files.push_back(entry); - } +void DBCManager::close(const SourceSet &sources) { + for (auto s : sources) { + dbc_files[s] = nullptr; } - - dbc_files = new_dbc_files; emit DBCFileChanged(); } void DBCManager::close(DBCFile *dbc_file) { - assert(dbc_file != nullptr); - - // Build new list of dbc files, removing the one that matches dbc_file* - QList> new_dbc_files; - for (auto entry : dbc_files) { - if (entry.second == dbc_file) { - delete entry.second; - } else { - new_dbc_files.push_back(entry); - } + for (auto &[_, f] : dbc_files) { + if (f.get() == dbc_file) f = nullptr; } - - dbc_files = new_dbc_files; emit DBCFileChanged(); } void DBCManager::closeAll() { - if (dbc_files.isEmpty()) return; - - while (dbc_files.size()) { - DBCFile *dbc_file = dbc_files.back().second; - dbc_files.pop_back(); - delete dbc_file; - } + dbc_files.clear(); emit DBCFileChanged(); } -void DBCManager::removeSourcesFromFile(DBCFile *dbc_file, SourceSet s) { - assert(dbc_file != nullptr); - - // Build new list of dbc files, for the given dbc_file* remove s from the current sources - QList> new_dbc_files; - for (auto entry : dbc_files) { - if (entry.second == dbc_file) { - SourceSet ss = (entry.first == SOURCE_ALL) ? sources : entry.first; - ss -= s; - if (ss.empty()) { // Close file if no more sources remain - delete dbc_file; - } else { - new_dbc_files.push_back({ss, dbc_file}); - } - } else { - new_dbc_files.push_back(entry); - } - } - - dbc_files = new_dbc_files; - emit DBCFileChanged(); -} - - void DBCManager::addSignal(const MessageId &id, const cabana::Signal &sig) { - auto sources_dbc_file = findDBCFile(id); - assert(sources_dbc_file); // Create new DBC? - auto [dbc_sources, dbc_file] = *sources_dbc_file; - - cabana::Signal *s = dbc_file->addSignal(id, sig); - - if (s != nullptr) { - dbc_sources.insert(id.source); - for (uint8_t source : dbc_sources) { - emit signalAdded({.source = source, .address = id.address}, s); + if (auto m = msg(id)) { + if (auto s = m->addSignal(sig)) { + emit signalAdded(id, s); } } } void DBCManager::updateSignal(const MessageId &id, const QString &sig_name, const cabana::Signal &sig) { - auto sources_dbc_file = findDBCFile(id); - assert(sources_dbc_file); // This should be impossible - auto [_, dbc_file] = *sources_dbc_file; - - cabana::Signal *s = dbc_file->updateSignal(id, sig_name, sig); - - if (s != nullptr) { - emit signalUpdated(s); + if (auto m = msg(id)) { + if (auto s = m->updateSignal(sig_name, sig)) { + emit signalUpdated(s); + } } } void DBCManager::removeSignal(const MessageId &id, const QString &sig_name) { - auto sources_dbc_file = findDBCFile(id); - assert(sources_dbc_file); // This should be impossible - auto [_, dbc_file] = *sources_dbc_file; - - cabana::Signal *s = dbc_file->getSignal(id, sig_name); - - if (s != nullptr) { - emit signalRemoved(s); - dbc_file->removeSignal(id, sig_name); + if (auto m = msg(id)) { + if (auto s = m->sig(sig_name)) { + emit signalRemoved(s); + m->removeSignal(sig_name); + } } } void DBCManager::updateMsg(const MessageId &id, const QString &name, uint32_t size, const QString &comment) { - auto sources_dbc_file = findDBCFile(id); - assert(sources_dbc_file); // This should be impossible - auto [dbc_sources, dbc_file] = *sources_dbc_file; - + auto dbc_file = findDBCFile(id); + assert(dbc_file); // This should be impossible dbc_file->updateMsg(id, name, size, comment); - - for (uint8_t source : dbc_sources) { - emit msgUpdated({.source = source, .address = id.address}); - } + emit msgUpdated(id); } void DBCManager::removeMsg(const MessageId &id) { - auto sources_dbc_file = findDBCFile(id); - assert(sources_dbc_file); // This should be impossible - auto [dbc_sources, dbc_file] = *sources_dbc_file; - + auto dbc_file = findDBCFile(id); + assert(dbc_file); // This should be impossible dbc_file->removeMsg(id); - - for (uint8_t source : dbc_sources) { - emit msgRemoved({.source = source, .address = id.address}); - } + emit msgRemoved(id); } QString DBCManager::newMsgName(const MessageId &id) { - auto sources_dbc_file = findDBCFile(id); - assert(sources_dbc_file); // This should be impossible - auto [_, dbc_file] = *sources_dbc_file; - return dbc_file->newMsgName(id); + return QString("NEW_MSG_") + QString::number(id.address, 16).toUpper(); } QString DBCManager::newSignalName(const MessageId &id) { - auto sources_dbc_file = findDBCFile(id); - assert(sources_dbc_file); // This should be impossible - auto [_, dbc_file] = *sources_dbc_file; - return dbc_file->newSignalName(id); + auto m = msg(id); + return m ? m->newSignalName() : ""; } -const QList& DBCManager::mask(const MessageId &id) const { - auto sources_dbc_file = findDBCFile(id); - if (!sources_dbc_file) { - return empty_mask; - } - auto [_, dbc_file] = *sources_dbc_file; - return dbc_file->mask(id); +const QList &DBCManager::mask(const MessageId &id) { + static QList empty_mask; + auto m = msg(id); + return m ? m->mask : empty_mask; } -std::map DBCManager::getMessages(uint8_t source) { - std::map ret; - - auto sources_dbc_file = findDBCFile({.source = source, .address = 0}); - if (!sources_dbc_file) { - return ret; - } - - auto [_, dbc_file] = *sources_dbc_file; - - for (auto &[address, msg] : dbc_file->getMessages()) { - MessageId id = {.source = source, .address = address}; - ret[id] = msg; - } - return ret; +const std::map &DBCManager::getMessages(uint8_t source) { + static std::map empty_msgs; + auto dbc_file = findDBCFile(source); + return dbc_file ? dbc_file->getMessages() : empty_msgs; } -const cabana::Msg *DBCManager::msg(const MessageId &id) const { - auto sources_dbc_file = findDBCFile(id); - if (!sources_dbc_file) { - return nullptr; - } - auto [_, dbc_file] = *sources_dbc_file; - return dbc_file->msg(id); +cabana::Msg *DBCManager::msg(const MessageId &id) { + auto dbc_file = findDBCFile(id); + return dbc_file ? dbc_file->msg(id) : nullptr; } -const cabana::Msg* DBCManager::msg(uint8_t source, const QString &name) { - auto sources_dbc_file = findDBCFile({.source = source, .address = 0}); - if (!sources_dbc_file) { - return nullptr; - } - auto [_, dbc_file] = *sources_dbc_file; - return dbc_file->msg(name); +cabana::Msg *DBCManager::msg(uint8_t source, const QString &name) { + auto dbc_file = findDBCFile(source); + return dbc_file ? dbc_file->msg(name) : nullptr; } -QStringList DBCManager::signalNames() const { +QStringList DBCManager::signalNames() { + // Used for autocompletion QStringList ret; - - for (auto &[_, dbc_file] : dbc_files) { - ret << dbc_file->signalNames(); + for (auto &f : allDBCFiles()) { + for (auto &[_, m] : f->getMessages()) { + for (auto sig : m.getSignals()) { + ret << sig->name; + } + } } - ret.sort(); ret.removeDuplicates(); return ret; } -int DBCManager::signalCount(const MessageId &id) const { - auto sources_dbc_file = findDBCFile(id); - if (!sources_dbc_file) { - return 0; - } - - auto [_, dbc_file] = *sources_dbc_file; - return dbc_file->signalCount(id); -} - -int DBCManager::signalCount() const { - int ret = 0; - - for (auto &[_, dbc_file] : dbc_files) { - ret += dbc_file->signalCount(); - } - - return ret; +int DBCManager::signalCount(const MessageId &id) { + auto m = msg(id); + return m ? m->sigs.size() : 0; } -int DBCManager::msgCount() const { - int ret = 0; - - for (auto &[_, dbc_file] : dbc_files) { - ret += dbc_file->msgCount(); - } - - return ret; +int DBCManager::signalCount() { + auto files = allDBCFiles(); + return std::accumulate(files.cbegin(), files.cend(), 0, [](int &n, auto &f) { return n + f->signalCount(); }); } -int DBCManager::dbcCount() const { - return dbc_files.size(); +int DBCManager::msgCount() { + auto files = allDBCFiles(); + return std::accumulate(files.cbegin(), files.cend(), 0, [](int &n, auto &f) { return n + f->msgCount(); }); } -int DBCManager::nonEmptyDBCCount() const { - return std::count_if(dbc_files.cbegin(), dbc_files.cend(), [](auto &f) { return !f.second->isEmpty(); }); +int DBCManager::dbcCount() { + return allDBCFiles().size(); } -void DBCManager::updateSources(const SourceSet &s) { - sources = s; +int DBCManager::nonEmptyDBCCount() { + auto files = allDBCFiles(); + return std::count_if(files.cbegin(), files.cend(), [](auto &f) { return !f->isEmpty(); }); } -std::optional> DBCManager::findDBCFile(const uint8_t source) const { +DBCFile *DBCManager::findDBCFile(const uint8_t source) { // Find DBC file that matches id.source, fall back to SOURCE_ALL if no specific DBC is found + auto it = dbc_files.count(source) ? dbc_files.find(source) : dbc_files.find(-1); + return it != dbc_files.end() ? it->second.get() : nullptr; +} - for (auto &[source_set, dbc_file] : dbc_files) { - if (source_set.contains(source)) return {{source_set, dbc_file}}; +std::set DBCManager::allDBCFiles() { + std::set files; + for (const auto &[_, f] : dbc_files) { + if (f) files.insert(f.get()); } - for (auto &[source_set, dbc_file] : dbc_files) { - if (source_set == SOURCE_ALL) return {{sources, dbc_file}}; - } - return {}; + return files; } -std::optional> DBCManager::findDBCFile(const MessageId &id) const { - return findDBCFile(id.source); +const SourceSet DBCManager::sources(const DBCFile *dbc_file) const { + SourceSet sources; + for (auto &[s, f] : dbc_files) { + if (f.get() == dbc_file) sources.insert(s); + } + return sources; } DBCManager *dbc() { diff --git a/tools/cabana/dbc/dbcmanager.h b/tools/cabana/dbc/dbcmanager.h index ba590ee56e..9af4e0c1cc 100644 --- a/tools/cabana/dbc/dbcmanager.h +++ b/tools/cabana/dbc/dbcmanager.h @@ -1,20 +1,15 @@ #pragma once +#include #include -#include +#include -#include -#include -#include -#include -#include - -#include "tools/cabana/dbc/dbc.h" #include "tools/cabana/dbc/dbcfile.h" -typedef QSet SourceSet; -const SourceSet SOURCE_ALL = {}; +typedef std::set SourceSet; +const SourceSet SOURCE_ALL = {-1}; const int INVALID_SOURCE = 0xff; +inline bool operator<(const std::shared_ptr &l, const std::shared_ptr &r) { return l.get() < r.get(); } class DBCManager : public QObject { Q_OBJECT @@ -22,12 +17,11 @@ class DBCManager : public QObject { public: DBCManager(QObject *parent) {} ~DBCManager() {} - bool open(SourceSet s, const QString &dbc_file_name, QString *error = nullptr); - bool open(SourceSet s, const QString &name, const QString &content, QString *error = nullptr); - void close(SourceSet s); + bool open(const SourceSet &sources, const QString &dbc_file_name, QString *error = nullptr); + bool open(const SourceSet &sources, const QString &name, const QString &content, QString *error = nullptr); + void close(const SourceSet &sources); void close(DBCFile *dbc_file); void closeAll(); - void removeSourcesFromFile(DBCFile *dbc_file, SourceSet s); void addSignal(const MessageId &id, const cabana::Signal &sig); void updateSignal(const MessageId &id, const QString &sig_name, const cabana::Signal &sig); @@ -38,31 +32,23 @@ public: QString newMsgName(const MessageId &id); QString newSignalName(const MessageId &id); + const QList& mask(const MessageId &id); - const QList& mask(const MessageId &id) const; - - std::map getMessages(uint8_t source); - const cabana::Msg *msg(const MessageId &id) const; - const cabana::Msg* msg(uint8_t source, const QString &name); - - QStringList signalNames() const; - int signalCount(const MessageId &id) const; - int signalCount() const; - int msgCount() const; - int dbcCount() const; - int nonEmptyDBCCount() const; - - std::optional> findDBCFile(const uint8_t source) const; - std::optional> findDBCFile(const MessageId &id) const; + const std::map &getMessages(uint8_t source); + cabana::Msg *msg(const MessageId &id); + cabana::Msg* msg(uint8_t source, const QString &name); - QList> dbc_files; + QStringList signalNames(); + int signalCount(const MessageId &id); + int signalCount(); + int msgCount(); + int dbcCount(); + int nonEmptyDBCCount(); -private: - SourceSet sources; - QList empty_mask; - -public slots: - void updateSources(const SourceSet &s); + const SourceSet sources(const DBCFile *dbc_file) const; + DBCFile *findDBCFile(const uint8_t source); + inline DBCFile *findDBCFile(const MessageId &id) { return findDBCFile(id.source); } + std::set allDBCFiles(); signals: void signalAdded(MessageId id, const cabana::Signal *sig); @@ -71,6 +57,9 @@ signals: void msgUpdated(MessageId id); void msgRemoved(MessageId id); void DBCFileChanged(); + +private: + std::map> dbc_files; }; DBCManager *dbc(); @@ -80,16 +69,10 @@ inline QString msgName(const MessageId &id) { return msg ? msg->name : UNTITLED; } -inline QString toString(SourceSet ss) { - if (ss == SOURCE_ALL) { - return "all"; - } else { - QStringList ret; - QList source_list = ss.values(); - std::sort(source_list.begin(), source_list.end()); - for (auto s : source_list) { - ret << QString::number(s); - } - return ret.join(", "); +inline QString toString(const SourceSet &ss) { + QStringList ret; + for (auto s : ss) { + ret << (s == -1 ? QString("all") : QString::number(s)); } + return ret.join(", "); } diff --git a/tools/cabana/historylog.cc b/tools/cabana/historylog.cc index 01c1f31645..eb8bada69e 100644 --- a/tools/cabana/historylog.cc +++ b/tools/cabana/historylog.cc @@ -64,7 +64,7 @@ QVariant HistoryLogModel::headerData(int section, Qt::Orientation orientation, i } } else if (role == Qt::BackgroundRole && section > 0 && show_signals) { // Alpha-blend the signal color with the background to ensure contrast - QColor sigColor = getColor(sigs[section - 1]); + QColor sigColor = sigs[section - 1]->color; sigColor.setAlpha(128); return QBrush(sigColor); } diff --git a/tools/cabana/historylog.h b/tools/cabana/historylog.h index 1f8c157f21..2dea698f68 100644 --- a/tools/cabana/historylog.h +++ b/tools/cabana/historylog.h @@ -62,7 +62,7 @@ public: uint64_t last_fetch_time = 0; std::function filter_cmp = nullptr; std::deque messages; - std::vector sigs; + std::vector sigs; bool dynamic_mode = true; bool display_signals_mode = true; }; diff --git a/tools/cabana/mainwin.cc b/tools/cabana/mainwin.cc index 421bb9a5d7..3ae26106cf 100644 --- a/tools/cabana/mainwin.cc +++ b/tools/cabana/mainwin.cc @@ -353,7 +353,6 @@ void MainWindow::streamStarted() { QObject::connect(messages_widget, &MessagesWidget::msgSelectionChanged, center_widget, &CenterWidget::setMessage); QObject::connect(can, &AbstractStream::eventsMerged, this, &MainWindow::eventsMerged); - QObject::connect(can, &AbstractStream::sourcesUpdated, dbc(), &DBCManager::updateSources); QObject::connect(can, &AbstractStream::sourcesUpdated, this, &MainWindow::updateLoadSaveMenus); } @@ -374,7 +373,7 @@ void MainWindow::eventsMerged() { void MainWindow::save() { // Save all open DBC files - for (auto &[s, dbc_file] : dbc()->dbc_files) { + for (auto dbc_file : dbc()->allDBCFiles()) { if (dbc_file->isEmpty()) continue; saveFile(dbc_file); } @@ -382,7 +381,7 @@ void MainWindow::save() { void MainWindow::saveAs() { // Save as all open DBC files. Should not be called with more than 1 file open - for (auto &[s, dbc_file] : dbc()->dbc_files) { + for (auto dbc_file : dbc()->allDBCFiles()) { if (dbc_file->isEmpty()) continue; saveFileAs(dbc_file); } @@ -390,7 +389,7 @@ void MainWindow::saveAs() { void MainWindow::autoSave() { if (!UndoStack::instance()->isClean()) { - for (auto &[_, dbc_file] : dbc()->dbc_files) { + for (auto dbc_file : dbc()->allDBCFiles()) { if (!dbc_file->filename.isEmpty()) { dbc_file->autoSave(); } @@ -399,7 +398,7 @@ void MainWindow::autoSave() { } void MainWindow::cleanupAutoSaveFile() { - for (auto &[_, dbc_file] : dbc()->dbc_files) { + for (auto dbc_file : dbc()->allDBCFiles()) { dbc_file->cleanupAutoSaveFile(); } } @@ -436,9 +435,7 @@ void MainWindow::saveFile(DBCFile *dbc_file) { } void MainWindow::saveFileAs(DBCFile *dbc_file) { - auto it = std::find_if(dbc()->dbc_files.begin(), dbc()->dbc_files.end(), [=](auto &f) { return f.second == dbc_file; }); - assert(it != dbc()->dbc_files.end()); - QString title = tr("Save File (bus: %1)").arg(toString(it->first)); + QString title = tr("Save File (bus: %1)").arg(toString(dbc()->sources(dbc_file))); QString fn = QFileDialog::getSaveFileName(this, title, QDir::cleanPath(settings.last_dir + "/untitled.dbc"), tr("DBC (*.dbc)")); if (!fn.isEmpty()) { dbc_file->saveAs(fn); @@ -447,15 +444,9 @@ void MainWindow::saveFileAs(DBCFile *dbc_file) { } } -void MainWindow::removeBusFromFile(DBCFile *dbc_file, uint8_t source) { - assert(dbc_file != nullptr); - SourceSet ss = {source, uint8_t(source + 128), uint8_t(source + 192)}; - dbc()->removeSourcesFromFile(dbc_file, ss); -} - void MainWindow::saveToClipboard() { // Copy all open DBC files to clipboard. Should not be called with more than 1 file open - for (auto &[s, dbc_file] : dbc()->dbc_files) { + for (auto dbc_file : dbc()->allDBCFiles()) { if (dbc_file->isEmpty()) continue; saveFileToClipboard(dbc_file); } @@ -480,13 +471,10 @@ void MainWindow::updateLoadSaveMenus() { // TODO: Support clipboard for multiple files copy_dbc_to_clipboard->setEnabled(cnt == 1); - QList sources_sorted = can->sources.toList(); - std::sort(sources_sorted.begin(), sources_sorted.end()); - manage_dbcs_menu->clear(); manage_dbcs_menu->setEnabled(dynamic_cast(can) == nullptr); - for (uint8_t source : sources_sorted) { + for (uint8_t source : can->sources) { if (source >= 64) continue; // Sent and blocked buses are handled implicitly SourceSet ss = {source, uint8_t(source + 128), uint8_t(source + 192)}; @@ -497,32 +485,26 @@ void MainWindow::updateLoadSaveMenus() { bus_menu->addAction(tr("Load DBC From Clipboard..."), [=]() { loadFromClipboard(ss, false); }); // Show sub-menu for each dbc for this source. - QStringList bus_menu_fns; - for (auto it : dbc()->dbc_files) { - auto &[src, dbc_file] = it; - if (!src.contains(source) && (src != SOURCE_ALL)) { - continue; - } - + QString file_name = "No DBCs loaded"; + if (auto dbc_file = dbc()->findDBCFile(source)) { bus_menu->addSeparator(); - bus_menu->addAction(dbc_file->name() + " (" + toString(src) + ")")->setEnabled(false); - bus_menu->addAction(tr("Save..."), [=]() { saveFile(it.second); }); - bus_menu->addAction(tr("Save As..."), [=]() { saveFileAs(it.second); }); - bus_menu->addAction(tr("Copy to Clipboard..."), [=]() { saveFileToClipboard(it.second); }); - bus_menu->addAction(tr("Remove from this bus..."), [=]() { removeBusFromFile(it.second, source); }); - bus_menu->addAction(tr("Remove from all buses..."), [=]() { closeFile(it.second); }); - - bus_menu_fns << dbc_file->name(); + bus_menu->addAction(dbc_file->name() + " (" + toString(dbc()->sources(dbc_file)) + ")")->setEnabled(false); + bus_menu->addAction(tr("Save..."), [=]() { saveFile(dbc_file); }); + bus_menu->addAction(tr("Save As..."), [=]() { saveFileAs(dbc_file); }); + bus_menu->addAction(tr("Copy to Clipboard..."), [=]() { saveFileToClipboard(dbc_file); }); + bus_menu->addAction(tr("Remove from this bus..."), [=]() { closeFile(ss); }); + bus_menu->addAction(tr("Remove from all buses..."), [=]() { closeFile(dbc_file); }); + + file_name = dbc_file->name(); } manage_dbcs_menu->addMenu(bus_menu); - QString bus_menu_title = bus_menu_fns.size() ? bus_menu_fns.join(", ") : "No DBCs loaded"; - bus_menu->setTitle(tr("Bus %1 (%2)").arg(source).arg(bus_menu_title)); + bus_menu->setTitle(tr("Bus %1 (%2)").arg(source).arg(file_name)); } QStringList title; - for (auto &[src, dbc_file] : dbc()->dbc_files) { - title.push_back(tr("(%1) %2").arg(toString(src), dbc_file->name())); + for (auto f : dbc()->allDBCFiles()) { + title.push_back(tr("(%1) %2").arg(toString(dbc()->sources(f)), f->name())); } setWindowFilePath(title.join(" | ")); } diff --git a/tools/cabana/mainwin.h b/tools/cabana/mainwin.h index 77467e2e45..bbbe8730cb 100644 --- a/tools/cabana/mainwin.h +++ b/tools/cabana/mainwin.h @@ -50,7 +50,6 @@ protected: void saveFile(DBCFile *dbc_file); void saveFileAs(DBCFile *dbc_file); void saveFileToClipboard(DBCFile *dbc_file); - void removeBusFromFile(DBCFile *dbc_file, uint8_t source); void loadFromClipboard(SourceSet s = SOURCE_ALL, bool close_all = true); void autoSave(); void cleanupAutoSaveFile(); diff --git a/tools/cabana/messageswidget.cc b/tools/cabana/messageswidget.cc index e24e8ab291..94b539505c 100644 --- a/tools/cabana/messageswidget.cc +++ b/tools/cabana/messageswidget.cc @@ -273,7 +273,7 @@ bool MessageListModel::matchMessage(const MessageId &id, const CanData &data, co case Column::NAME: { const auto msg = dbc()->msg(id); match = re.match(msg ? msg->name : UNTITLED).hasMatch(); - match |= msg && std::any_of(msg->sigs.cbegin(), msg->sigs.cend(), [&re](const auto &s) { return re.match(s.name).hasMatch(); }); + match |= msg && std::any_of(msg->sigs.cbegin(), msg->sigs.cend(), [&re](const auto &s) { return re.match(s->name).hasMatch(); }); break; } case Column::SOURCE: diff --git a/tools/cabana/signalview.cc b/tools/cabana/signalview.cc index 98cd08a690..3fda5796d4 100644 --- a/tools/cabana/signalview.cc +++ b/tools/cabana/signalview.cc @@ -171,7 +171,6 @@ bool SignalModel::setData(const QModelIndex &index, const QVariant &value, int r case Item::Desc: s.val_desc = value.value(); break; default: return false; } - s.updatePrecision(); bool ret = saveSignal(item->sig, s); emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole, Qt::CheckStateRole}); return ret; @@ -249,17 +248,14 @@ void SignalModel::removeSignal(const cabana::Signal *sig) { } void SignalModel::handleMsgChanged(MessageId id) { - if (id == msg_id) { + if (id.address == msg_id.address) { refresh(); } } 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; - } + int i = dbc()->msg(msg_id)->indexOf(sig); beginInsertRows({}, i, i); insertItem(root.get(), i, sig); endInsertRows(); @@ -348,7 +344,7 @@ void SignalItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op path.addRoundedRect(icon_rect, 3, 3); painter->setPen(item->highlight ? Qt::white : Qt::black); painter->setFont(label_font); - painter->fillPath(path, getColor(item->sig).darker(item->highlight ? 125 : 0)); + painter->fillPath(path, item->sig->color.darker(item->highlight ? 125 : 0)); painter->drawText(icon_rect, Qt::AlignCenter, QString::number(item->row() + 1)); r.setLeft(icon_rect.right() + h_margin * 2); diff --git a/tools/cabana/tests/test_cabana.cc b/tools/cabana/tests/test_cabana.cc index abbb3dbf13..01b8dd7081 100644 --- a/tools/cabana/tests/test_cabana.cc +++ b/tools/cabana/tests/test_cabana.cc @@ -78,7 +78,7 @@ BO_ 160 message_1: 8 XXX VAL_ 160 signal_1 0 "disabled" 1.2 "initializing" 2 "fault"; -CM_ BO_ 160 "message comment"; +CM_ BO_ 160 "message comment" ; CM_ SG_ 160 signal_1 "signal comment"; CM_ SG_ 160 signal_2 "multiple line comment 1 @@ -94,19 +94,19 @@ CM_ SG_ 160 signal_2 "multiple line comment REQUIRE(msg->sigs.size() == 2); REQUIRE(file.msg("message_1") != nullptr); - auto &sig_1 = msg->sigs[0]; - REQUIRE(sig_1.name == "signal_1"); - REQUIRE(sig_1.start_bit == 0); - REQUIRE(sig_1.size == 12); - REQUIRE(sig_1.min == 0); - REQUIRE(sig_1.max == 4095); - REQUIRE(sig_1.unit == "unit"); - REQUIRE(sig_1.comment == "signal comment"); - REQUIRE(sig_1.val_desc.size() == 3); - REQUIRE(sig_1.val_desc[0] == std::pair{0, "disabled"}); - REQUIRE(sig_1.val_desc[1] == std::pair{1.2, "initializing"}); - REQUIRE(sig_1.val_desc[2] == std::pair{2, "fault"}); + auto sig_1 = msg->sigs[0]; + REQUIRE(sig_1->name == "signal_1"); + REQUIRE(sig_1->start_bit == 0); + REQUIRE(sig_1->size == 12); + REQUIRE(sig_1->min == 0); + REQUIRE(sig_1->max == 4095); + REQUIRE(sig_1->unit == "unit"); + REQUIRE(sig_1->comment == "signal comment"); + REQUIRE(sig_1->val_desc.size() == 3); + REQUIRE(sig_1->val_desc[0] == std::pair{0, "disabled"}); + REQUIRE(sig_1->val_desc[1] == std::pair{1.2, "initializing"}); + REQUIRE(sig_1->val_desc[2] == std::pair{2, "fault"}); auto &sig_2 = msg->sigs[1]; - REQUIRE(sig_2.comment == "multiple line comment\n1\n2"); + REQUIRE(sig_2->comment == "multiple line comment\n1\n2"); } diff --git a/tools/cabana/tools/findsimilarbits.cc b/tools/cabana/tools/findsimilarbits.cc index add4ee7928..5eb4d7fb86 100644 --- a/tools/cabana/tools/findsimilarbits.cc +++ b/tools/cabana/tools/findsimilarbits.cc @@ -24,14 +24,12 @@ FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::Wi for (uint8_t bus : can->sources) { cb->addItem(QString::number(bus), bus); } - cb->model()->sort(0); - cb->setCurrentIndex(0); } msg_cb = new QComboBox(this); // TODO: update when src_bus_combo changes - for (auto &[id, msg] : dbc()->getMessages(0)) { - msg_cb->addItem(msg.name, id.address); + for (auto &[address, msg] : dbc()->getMessages(0)) { + msg_cb->addItem(msg.name, address); } msg_cb->model()->sort(0); msg_cb->setCurrentIndex(0); diff --git a/tools/cabana/util.cc b/tools/cabana/util.cc index 2660ae6837..b0bba891db 100644 --- a/tools/cabana/util.cc +++ b/tools/cabana/util.cc @@ -1,5 +1,6 @@ #include "tools/cabana/util.h" +#include #include #include #include @@ -144,17 +145,6 @@ void TabBar::closeTabClicked() { } } -QColor getColor(const cabana::Signal *sig) { - float h = 19 * (float)sig->lsb / 64.0; - h = fmod(h, 1.0); - - size_t hash = qHash(sig->name); - float s = 0.25 + 0.25 * (float)(hash & 0xff) / 255.0; - float v = 0.75 + 0.25 * (float)((hash >> 8) & 0xff) / 255.0; - - return QColor::fromHsvF(h, s, v); -} - NameValidator::NameValidator(QObject *parent) : QRegExpValidator(QRegExp("^(\\w+)"), parent) {} QValidator::State NameValidator::validate(QString &input, int &pos) const { @@ -237,10 +227,6 @@ QString toHex(uint8_t byte) { int num_decimals(double num) { const QString string = QString::number(num); - const QStringList split = string.split('.'); - if (split.size() == 1) { - return 0; - } else { - return split[1].size(); - } + auto dot_pos = string.indexOf('.'); + return dot_pos == -1 ? 0 : string.size() - dot_pos - 1; } diff --git a/tools/cabana/util.h b/tools/cabana/util.h index fed8ba94c3..4358190bc3 100644 --- a/tools/cabana/util.h +++ b/tools/cabana/util.h @@ -2,12 +2,10 @@ #include -#include #include #include #include #include -#include #include #include #include @@ -22,7 +20,7 @@ class LogSlider : public QSlider { Q_OBJECT public: - LogSlider(double factor, Qt::Orientation orientation, QWidget *parent = nullptr) : factor(factor), QSlider(orientation, parent) {}; + LogSlider(double factor, Qt::Orientation orientation, QWidget *parent = nullptr) : factor(factor), QSlider(orientation, parent) {} void setRange(double min, double max) { log_min = factor * std::log10(min); @@ -81,7 +79,6 @@ private: inline QString toHex(const QByteArray &dat) { return dat.toHex(' ').toUpper(); } QString toHex(uint8_t byte); -QColor getColor(const cabana::Signal *sig); class NameValidator : public QRegExpValidator { Q_OBJECT