diff --git a/tools/cabana/dbc/dbc.cc b/tools/cabana/dbc/dbc.cc index ac91922e01..cb5ebff602 100644 --- a/tools/cabana/dbc/dbc.cc +++ b/tools/cabana/dbc/dbc.cc @@ -40,7 +40,7 @@ void cabana::Signal::updatePrecision() { QString cabana::Signal::formatValue(double value) const { // Show enum string for (auto &[val, desc] : val_desc) { - if (std::abs(value - val.toInt()) < 1e-6) { + if (std::abs(value - val) < 1e-6) { return desc; } } diff --git a/tools/cabana/dbc/dbc.h b/tools/cabana/dbc/dbc.h index b43d9cdecc..ad5f33a260 100644 --- a/tools/cabana/dbc/dbc.h +++ b/tools/cabana/dbc/dbc.h @@ -42,7 +42,7 @@ struct std::hash { std::size_t operator()(const MessageId &k) const noexcept { return qHash(k); } }; -typedef QList> ValueDescription; +typedef QList> ValueDescription; namespace cabana { struct Signal { diff --git a/tools/cabana/dbc/dbcfile.cc b/tools/cabana/dbc/dbcfile.cc index 4679831ddc..e1b31489b9 100644 --- a/tools/cabana/dbc/dbcfile.cc +++ b/tools/cabana/dbc/dbcfile.cc @@ -196,7 +196,13 @@ void DBCFile::parseExtraInfo(const QString &content) { 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 val_regexp(R"(VAL_ (\w+) (\w+) (.*);)"); + static QRegularExpression val_regexp(R"(VAL_ (\w+) (\w+) (\s*[-+]?[0-9]+\s+\".+?\"[^;]*))"); + + int line_num = 0; + QString line; + auto dbc_assert = [&line_num, &line, this](bool condition) { + if (!condition) throw std::runtime_error(QString("[%1:%2]: %3").arg(filename).arg(line_num).arg(line).toStdString()); + }; auto get_sig = [this](uint32_t address, const QString &name) -> cabana::Signal * { auto m = (cabana::Msg *)msg(address); return m ? (cabana::Signal *)m->sig(name) : nullptr; @@ -205,11 +211,12 @@ void DBCFile::parseExtraInfo(const QString &content) { QTextStream stream((QString *)&content); uint32_t address = 0; while (!stream.atEnd()) { - QString line = stream.readLine().trimmed(); + ++line_num; + line = stream.readLine().trimmed(); if (line.startsWith("BO_ ")) { - if (auto match = bo_regexp.match(line); match.hasMatch()) { - address = match.captured(1).toUInt(); - } + auto match = bo_regexp.match(line); + dbc_assert(match.hasMatch()); + address = match.captured(1).toUInt(); } else if (line.startsWith("SG_ ")) { int offset = 0; auto match = sg_regexp.match(line); @@ -217,37 +224,36 @@ void DBCFile::parseExtraInfo(const QString &content) { match = sgm_regexp.match(line); offset = 1; } - if (match.hasMatch()) { - if (auto s = get_sig(address, match.captured(1))) { - s->min = match.captured(8 + offset).toDouble(); - s->max = match.captured(9 + offset).toDouble(); - s->unit = match.captured(10 + offset); - } + dbc_assert(match.hasMatch()); + if (auto s = get_sig(address, match.captured(1))) { + s->min = match.captured(8 + offset).toDouble(); + s->max = match.captured(9 + offset).toDouble(); + s->unit = match.captured(10 + offset); } } else if (line.startsWith("VAL_ ")) { - if (auto match = val_regexp.match(line); match.hasMatch()) { - if (auto s = get_sig(match.captured(1).toUInt(), match.captured(2))) { - QStringList desc_list = match.captured(3).trimmed().split('"'); - for (int i = 0; i < desc_list.size(); i += 2) { - auto val = desc_list[i].trimmed(); - if (!val.isEmpty() && (i + 1) < desc_list.size()) { - auto desc = desc_list[i+1].trimmed(); - s->val_desc.push_back({val, desc}); - } + auto match = val_regexp.match(line); + dbc_assert(match.hasMatch()); + if (auto s = get_sig(match.captured(1).toUInt(), match.captured(2))) { + QStringList desc_list = match.captured(3).trimmed().split('"'); + for (int i = 0; i < desc_list.size(); i += 2) { + auto val = desc_list[i].trimmed(); + if (!val.isEmpty() && (i + 1) < desc_list.size()) { + auto desc = desc_list[i + 1].trimmed(); + s->val_desc.push_back({val.toDouble(), desc}); } } } } else if (line.startsWith("CM_ BO_")) { - if (auto match = msg_comment_regexp.match(line); match.hasMatch()) { - if (auto m = (cabana::Msg *)msg(match.captured(1).toUInt())) { - m->comment = match.captured(2).trimmed(); - } + auto match = msg_comment_regexp.match(line); + dbc_assert(match.hasMatch()); + if (auto m = (cabana::Msg *)msg(match.captured(1).toUInt())) { + m->comment = match.captured(2).trimmed(); } } else if (line.startsWith("CM_ SG_ ")) { - if (auto match = sg_comment_regexp.match(line); match.hasMatch()) { - if (auto s = get_sig(match.captured(1).toUInt(), match.captured(2))) { - s->comment = match.captured(3).trimmed(); - } + auto match = sg_comment_regexp.match(line); + dbc_assert(match.hasMatch()); + if (auto s = get_sig(match.captured(1).toUInt(), match.captured(2))) { + s->comment = match.captured(3).trimmed(); } } } @@ -278,7 +284,7 @@ QString DBCFile::generateDBC() { if (!sig->val_desc.isEmpty()) { QStringList text; for (auto &[val, desc] : sig->val_desc) { - text << QString("%1 \"%2\"").arg(val, desc); + text << QString("%1 \"%2\"").arg(val).arg(desc); } val_desc += QString("VAL_ %1 %2 %3;\n").arg(address).arg(sig->name).arg(text.join(" ")); } diff --git a/tools/cabana/historylog.cc b/tools/cabana/historylog.cc index 13e8f70a8f..51abc3d50f 100644 --- a/tools/cabana/historylog.cc +++ b/tools/cabana/historylog.cc @@ -224,7 +224,7 @@ LogsWidget::LogsWidget(QWidget *parent) : QFrame(parent) { display_type_cb->setToolTip(tr("Display signal value or raw hex value")); comp_box->addItems({">", "=", "!=", "<"}); value_edit->setClearButtonEnabled(true); - value_edit->setValidator(new QDoubleValidator(-500000, 500000, 6, this)); + value_edit->setValidator(new DoubleValidator(this)); dynamic_mode->setChecked(true); dynamic_mode->setEnabled(!can->liveStreaming()); diff --git a/tools/cabana/signalview.cc b/tools/cabana/signalview.cc index b501f14a7c..762b494f35 100644 --- a/tools/cabana/signalview.cc +++ b/tools/cabana/signalview.cc @@ -133,7 +133,7 @@ QVariant SignalModel::data(const QModelIndex &index, int role) const { case Item::Desc: { QStringList val_desc; for (auto &[val, desc] : item->sig->val_desc) { - val_desc << QString("%1 \"%2\"").arg(val, desc); + val_desc << QString("%1 \"%2\"").arg(val).arg(desc); } return val_desc.join(" "); } @@ -284,11 +284,7 @@ void SignalModel::handleSignalRemoved(const cabana::Signal *sig) { SignalItemDelegate::SignalItemDelegate(QObject *parent) : QStyledItemDelegate(parent) { name_validator = new NameValidator(this); - - QLocale locale(QLocale::C); - locale.setNumberOptions(QLocale::RejectGroupSeparator); - double_validator = new QDoubleValidator(this); - double_validator->setLocale(locale); // Match locale of QString::toDouble() instead of system + double_validator = new DoubleValidator(this); label_font.setPointSize(8); minmax_font.setPixelSize(10); @@ -666,7 +662,7 @@ ValueDescriptionDlg::ValueDescriptionDlg(const ValueDescription &descriptions, Q int row = 0; for (auto &[val, desc] : descriptions) { - table->setItem(row, 0, new QTableWidgetItem(val)); + table->setItem(row, 0, new QTableWidgetItem(QString::number(val))); table->setItem(row, 1, new QTableWidgetItem(desc)); ++row; } @@ -696,7 +692,7 @@ void ValueDescriptionDlg::save() { QString val = table->item(i, 0)->text().trimmed(); QString desc = table->item(i, 1)->text().trimmed(); if (!val.isEmpty() && !desc.isEmpty()) { - val_desc.push_back({val, desc}); + val_desc.push_back({val.toDouble(), desc}); } } QDialog::accept(); @@ -706,7 +702,7 @@ QWidget *ValueDescriptionDlg::Delegate::createEditor(QWidget *parent, const QSty QLineEdit *edit = new QLineEdit(parent); edit->setFrame(false); if (index.column() == 0) { - edit->setValidator(new QIntValidator(edit)); + edit->setValidator(new DoubleValidator(parent)); } return edit; } diff --git a/tools/cabana/tools/findsignal.cc b/tools/cabana/tools/findsignal.cc index 7b4a5633f6..b7d2f4c015 100644 --- a/tools/cabana/tools/findsignal.cc +++ b/tools/cabana/tools/findsignal.cc @@ -1,6 +1,5 @@ #include "tools/cabana/tools/findsignal.h" -#include #include #include #include @@ -138,8 +137,7 @@ FindSignalDlg::FindSignalDlg(QWidget *parent) : QDialog(parent, Qt::WindowFlags( undo_btn->setEnabled(false); reset_btn->setEnabled(false); - auto double_validator = new QDoubleValidator(this); - double_validator->setLocale(QLocale::C); + auto double_validator = new DoubleValidator(this); for (auto edit : {value1, value2, factor_edit, offset_edit, first_time_edit, last_time_edit}) { edit->setValidator(double_validator); } diff --git a/tools/cabana/util.cc b/tools/cabana/util.cc index a75d10139d..2660ae6837 100644 --- a/tools/cabana/util.cc +++ b/tools/cabana/util.cc @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -161,6 +162,13 @@ QValidator::State NameValidator::validate(QString &input, int &pos) const { return QRegExpValidator::validate(input, pos); } +DoubleValidator::DoubleValidator(QObject *parent) : QDoubleValidator(parent) { + // Match locale of QString::toDouble() instead of system + QLocale locale(QLocale::C); + locale.setNumberOptions(QLocale::RejectGroupSeparator); + setLocale(locale); +} + namespace utils { QPixmap icon(const QString &id) { bool dark_theme = settings.theme == DARK_THEME; diff --git a/tools/cabana/util.h b/tools/cabana/util.h index 3955ab82c5..fed8ba94c3 100644 --- a/tools/cabana/util.h +++ b/tools/cabana/util.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -84,12 +85,17 @@ QColor getColor(const cabana::Signal *sig); class NameValidator : public QRegExpValidator { Q_OBJECT - public: NameValidator(QObject *parent=nullptr); QValidator::State validate(QString &input, int &pos) const override; }; +class DoubleValidator : public QDoubleValidator { + Q_OBJECT +public: + DoubleValidator(QObject *parent = nullptr); +}; + namespace utils { QPixmap icon(const QString &id); void setTheme(int theme);