mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-04-06 14:34:01 +08:00
cabana: replace Qt types with stdlib (#37519)
* cabana: replace Qt types with stdlib * lil more * cleanup sconscript
This commit is contained in:
@@ -13,7 +13,6 @@ if arch == "Darwin":
|
||||
has_qt = False
|
||||
else:
|
||||
has_qt = shutil.which('qmake') is not None
|
||||
|
||||
if not has_qt:
|
||||
Return()
|
||||
|
||||
@@ -21,7 +20,7 @@ SConscript(['#tools/replay/SConscript'])
|
||||
Import('replay_lib')
|
||||
|
||||
qt_env = env.Clone()
|
||||
qt_modules = ["Widgets", "Gui", "Core", "Network", "Concurrent", "DBus", "Xml"]
|
||||
qt_modules = ["Widgets", "Gui", "Core", "Concurrent", "Xml"]
|
||||
|
||||
qt_libs = []
|
||||
if arch == "Darwin":
|
||||
@@ -51,7 +50,7 @@ else:
|
||||
qt_env['QT3DIR'] = qt_env['QTDIR']
|
||||
qt_env.Tool('qt3')
|
||||
|
||||
qt_env['CPPPATH'] += qt_dirs + ["#third_party/qrcode"]
|
||||
qt_env['CPPPATH'] += qt_dirs
|
||||
qt_flags = [
|
||||
"-D_REENTRANT",
|
||||
"-DQT_NO_DEBUG",
|
||||
|
||||
@@ -258,7 +258,7 @@ void BinaryViewModel::refresh() {
|
||||
int pos = sig->is_little_endian ? flipBitPos(sig->start_bit + j) : flipBitPos(sig->start_bit) + j;
|
||||
int idx = column_count * (pos / 8) + pos % 8;
|
||||
if (idx >= items.size()) {
|
||||
qWarning() << "signal " << sig->name << "out of bounds.start_bit:" << sig->start_bit << "size:" << sig->size;
|
||||
qWarning() << "signal " << sig->name.c_str() << "out of bounds.start_bit:" << sig->start_bit << "size:" << sig->size;
|
||||
break;
|
||||
}
|
||||
if (j == 0) sig->is_little_endian ? items[idx].is_lsb = true : items[idx].is_msb = true;
|
||||
|
||||
@@ -46,13 +46,13 @@ int main(int argc, char *argv[]) {
|
||||
stream = new DeviceStream(&app, cmd_parser.value("zmq"));
|
||||
} else if (cmd_parser.isSet("panda") || cmd_parser.isSet("panda-serial")) {
|
||||
try {
|
||||
stream = new PandaStream(&app, {.serial = cmd_parser.value("panda-serial")});
|
||||
stream = new PandaStream(&app, {.serial = cmd_parser.value("panda-serial").toStdString()});
|
||||
} catch (std::exception &e) {
|
||||
qWarning() << e.what();
|
||||
return 0;
|
||||
}
|
||||
} else if (SocketCanStream::available() && cmd_parser.isSet("socketcan")) {
|
||||
stream = new SocketCanStream(&app, {.device = cmd_parser.value("socketcan")});
|
||||
stream = new SocketCanStream(&app, {.device = cmd_parser.value("socketcan").toStdString()});
|
||||
} else {
|
||||
uint32_t replay_flags = REPLAY_FLAG_NONE;
|
||||
if (cmd_parser.isSet("ecam")) replay_flags |= REPLAY_FLAG_ECAM;
|
||||
@@ -70,7 +70,7 @@ int main(int argc, char *argv[]) {
|
||||
if (!route.isEmpty()) {
|
||||
auto replay_stream = std::make_unique<ReplayStream>(&app);
|
||||
bool auto_source = cmd_parser.isSet("auto");
|
||||
if (!replay_stream->loadRoute(route, cmd_parser.value("data_dir"), replay_flags, auto_source)) {
|
||||
if (!replay_stream->loadRoute(route.toStdString(), cmd_parser.value("data_dir").toStdString(), replay_flags, auto_source)) {
|
||||
return 0;
|
||||
}
|
||||
stream = replay_stream.release();
|
||||
|
||||
@@ -237,8 +237,8 @@ void ChartView::updateTitle() {
|
||||
for (auto &s : sigs) {
|
||||
auto decoration = s.series->isVisible() ? "none" : "line-through";
|
||||
s.series->setName(QString("<span style=\"text-decoration:%1; color:%2\"><b>%3</b> <font color=\"%4\">%5 %6</font></span>")
|
||||
.arg(decoration, titleColorCss, s.sig->name,
|
||||
msgColorCss, msgName(s.msg_id), s.msg_id.toString()));
|
||||
.arg(decoration, titleColorCss, QString::fromStdString(s.sig->name),
|
||||
msgColorCss, QString::fromStdString(msgName(s.msg_id)), QString::fromStdString(s.msg_id.toString())));
|
||||
}
|
||||
split_chart_act->setEnabled(sigs.size() > 1);
|
||||
resetChartCache();
|
||||
@@ -339,13 +339,13 @@ void ChartView::updateAxisY() {
|
||||
|
||||
double min = std::numeric_limits<double>::max();
|
||||
double max = std::numeric_limits<double>::lowest();
|
||||
QString unit = sigs[0].sig->unit;
|
||||
QString unit = QString::fromStdString(sigs[0].sig->unit);
|
||||
|
||||
for (auto &s : sigs) {
|
||||
if (!s.series->isVisible()) continue;
|
||||
|
||||
// Only show unit when all signals have the same unit
|
||||
if (unit != s.sig->unit) {
|
||||
if (unit != QString::fromStdString(s.sig->unit)) {
|
||||
unit.clear();
|
||||
}
|
||||
|
||||
@@ -573,11 +573,11 @@ void ChartView::showTip(double sec) {
|
||||
// use reverse iterator to find last item <= sec.
|
||||
auto it = std::lower_bound(s.vals.crbegin(), s.vals.crend(), sec, [](auto &p, double v) { return p.x() > v; });
|
||||
if (it != s.vals.crend() && it->x() >= axis_x->min()) {
|
||||
value = s.sig->formatValue(it->y(), false);
|
||||
value = QString::fromStdString(s.sig->formatValue(it->y(), false));
|
||||
s.track_pt = *it;
|
||||
x = std::max(x, chart()->mapToPosition(*it).x());
|
||||
}
|
||||
QString name = sigs.size() > 1 ? s.sig->name + ": " : "";
|
||||
QString name = sigs.size() > 1 ? QString::fromStdString(s.sig->name) + ": " : "";
|
||||
QString min = s.min == std::numeric_limits<double>::max() ? "--" : QString::number(s.min);
|
||||
QString max = s.max == std::numeric_limits<double>::lowest() ? "--" : QString::number(s.max);
|
||||
text_list << QString("<span style=\"color:%1;\">■ </span>%2<b>%3</b> (%4, %5)")
|
||||
@@ -766,7 +766,7 @@ void ChartView::drawSignalValue(QPainter *painter) {
|
||||
for (auto &s : sigs) {
|
||||
auto it = std::lower_bound(s.vals.crbegin(), s.vals.crend(), cur_sec,
|
||||
[](auto &p, double x) { return p.x() > x + EPSILON; });
|
||||
QString value = (it != s.vals.crend() && it->x() >= axis_x->min()) ? s.sig->formatValue(it->y()) : "--";
|
||||
QString value = (it != s.vals.crend() && it->x() >= axis_x->min()) ? QString::fromStdString(s.sig->formatValue(it->y())) : "--";
|
||||
QRectF marker_rect = legend_markers[i++]->sceneBoundingRect();
|
||||
QRectF value_rect(marker_rect.bottomLeft() - QPoint(0, 1), marker_rect.size());
|
||||
QString elided_val = painter->fontMetrics().elidedText(value, Qt::ElideRight, value_rect.width());
|
||||
|
||||
@@ -327,7 +327,7 @@ QStringList ChartsWidget::serializeChartIds() const {
|
||||
for (auto c : charts) {
|
||||
QStringList ids;
|
||||
for (const auto& s : c->sigs)
|
||||
ids += QString("%1|%2").arg(s.msg_id.toString(), s.sig->name);
|
||||
ids += QString("%1|%2").arg(QString::fromStdString(s.msg_id.toString()), QString::fromStdString(s.sig->name));
|
||||
chart_ids += ids.join(',');
|
||||
}
|
||||
std::reverse(chart_ids.begin(), chart_ids.end());
|
||||
@@ -340,9 +340,9 @@ void ChartsWidget::restoreChartsFromIds(const QStringList& chart_ids) {
|
||||
for (const auto& part : chart_id.split(',')) {
|
||||
const auto sig_parts = part.split('|');
|
||||
if (sig_parts.size() != 2) continue;
|
||||
MessageId msg_id = MessageId::fromString(sig_parts[0]);
|
||||
MessageId msg_id = MessageId::fromString(sig_parts[0].toStdString());
|
||||
if (auto* msg = dbc()->msg(msg_id))
|
||||
if (auto* sig = msg->sig(sig_parts[1]))
|
||||
if (auto* sig = msg->sig(sig_parts[1].toStdString()))
|
||||
showChart(msg_id, sig, true, index++ > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ SignalSelector::SignalSelector(QString title, QWidget *parent) : QDialog(parent)
|
||||
|
||||
for (const auto &[id, _] : can->lastMessages()) {
|
||||
if (auto m = dbc()->msg(id)) {
|
||||
msgs_combo->addItem(QString("%1 (%2)").arg(m->name).arg(id.toString()), QVariant::fromValue(id));
|
||||
msgs_combo->addItem(QString("%1 (%2)").arg(QString::fromStdString(m->name)).arg(QString::fromStdString(id.toString())), QVariant::fromValue(id));
|
||||
}
|
||||
}
|
||||
msgs_combo->model()->sort(0);
|
||||
@@ -92,8 +92,8 @@ void SignalSelector::updateAvailableList(int index) {
|
||||
}
|
||||
|
||||
void SignalSelector::addItemToList(QListWidget *parent, const MessageId id, const cabana::Signal *sig, bool show_msg_name) {
|
||||
QString text = QString("<span style=\"color:%0;\">■ </span> %1").arg(sig->color.name(), sig->name);
|
||||
if (show_msg_name) text += QString(" <font color=\"gray\">%0 %1</font>").arg(msgName(id), id.toString());
|
||||
QString text = QString("<span style=\"color:%0;\">■ </span> %1").arg(sig->color.name(), QString::fromStdString(sig->name));
|
||||
if (show_msg_name) text += QString(" <font color=\"gray\">%0 %1</font>").arg(QString::fromStdString(msgName(id)), QString::fromStdString(id.toString()));
|
||||
|
||||
QLabel *label = new QLabel(text);
|
||||
label->setContentsMargins(5, 0, 5, 0);
|
||||
|
||||
@@ -4,22 +4,22 @@
|
||||
|
||||
// EditMsgCommand
|
||||
|
||||
EditMsgCommand::EditMsgCommand(const MessageId &id, const QString &name, int size,
|
||||
const QString &node, const QString &comment, QUndoCommand *parent)
|
||||
EditMsgCommand::EditMsgCommand(const MessageId &id, const std::string &name, int size,
|
||||
const std::string &node, const std::string &comment, QUndoCommand *parent)
|
||||
: id(id), new_name(name), new_size(size), new_node(node), new_comment(comment), QUndoCommand(parent) {
|
||||
if (auto msg = dbc()->msg(id)) {
|
||||
old_name = msg->name;
|
||||
old_size = msg->size;
|
||||
old_node = msg->transmitter;
|
||||
old_comment = msg->comment;
|
||||
setText(QObject::tr("edit message %1:%2").arg(name).arg(id.address));
|
||||
setText(QObject::tr("edit message %1:%2").arg(QString::fromStdString(name)).arg(id.address));
|
||||
} else {
|
||||
setText(QObject::tr("new message %1:%2").arg(name).arg(id.address));
|
||||
setText(QObject::tr("new message %1:%2").arg(QString::fromStdString(name)).arg(id.address));
|
||||
}
|
||||
}
|
||||
|
||||
void EditMsgCommand::undo() {
|
||||
if (old_name.isEmpty())
|
||||
if (old_name.empty())
|
||||
dbc()->removeMsg(id);
|
||||
else
|
||||
dbc()->updateMsg(id, old_name, old_size, old_node, old_comment);
|
||||
@@ -34,12 +34,12 @@ void EditMsgCommand::redo() {
|
||||
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(message.name).arg(id.address));
|
||||
setText(QObject::tr("remove message %1:%2").arg(QString::fromStdString(message.name)).arg(id.address));
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveMsgCommand::undo() {
|
||||
if (!message.name.isEmpty()) {
|
||||
if (!message.name.empty()) {
|
||||
dbc()->updateMsg(id, message.name, message.size, message.transmitter, message.comment);
|
||||
for (auto s : message.getSignals())
|
||||
dbc()->addSignal(id, *s);
|
||||
@@ -47,7 +47,7 @@ void RemoveMsgCommand::undo() {
|
||||
}
|
||||
|
||||
void RemoveMsgCommand::redo() {
|
||||
if (!message.name.isEmpty())
|
||||
if (!message.name.empty())
|
||||
dbc()->removeMsg(id);
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ void RemoveMsgCommand::redo() {
|
||||
|
||||
AddSigCommand::AddSigCommand(const MessageId &id, const cabana::Signal &sig, QUndoCommand *parent)
|
||||
: id(id), signal(sig), QUndoCommand(parent) {
|
||||
setText(QObject::tr("add signal %1 to %2:%3").arg(sig.name).arg(msgName(id)).arg(id.address));
|
||||
setText(QObject::tr("add signal %1 to %2:%3").arg(QString::fromStdString(sig.name)).arg(QString::fromStdString(msgName(id))).arg(id.address));
|
||||
}
|
||||
|
||||
void AddSigCommand::undo() {
|
||||
@@ -85,7 +85,7 @@ RemoveSigCommand::RemoveSigCommand(const MessageId &id, const cabana::Signal *si
|
||||
}
|
||||
}
|
||||
}
|
||||
setText(QObject::tr("remove signal %1 from %2:%3").arg(sig->name).arg(msgName(id)).arg(id.address));
|
||||
setText(QObject::tr("remove signal %1 from %2:%3").arg(QString::fromStdString(sig->name)).arg(QString::fromStdString(msgName(id))).arg(id.address));
|
||||
}
|
||||
|
||||
void RemoveSigCommand::undo() { for (const auto &s : sigs) dbc()->addSignal(id, s); }
|
||||
@@ -108,7 +108,7 @@ EditSignalCommand::EditSignalCommand(const MessageId &id, const cabana::Signal *
|
||||
}
|
||||
}
|
||||
}
|
||||
setText(QObject::tr("edit signal %1 in %2:%3").arg(sig->name).arg(msgName(id)).arg(id.address));
|
||||
setText(QObject::tr("edit signal %1 in %2:%3").arg(QString::fromStdString(sig->name)).arg(QString::fromStdString(msgName(id))).arg(id.address));
|
||||
}
|
||||
|
||||
void EditSignalCommand::undo() { for (const auto &s : sigs) dbc()->updateSignal(id, s.second.name, s.first); }
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <QUndoCommand>
|
||||
#include <QUndoStack>
|
||||
@@ -10,14 +12,14 @@
|
||||
|
||||
class EditMsgCommand : public QUndoCommand {
|
||||
public:
|
||||
EditMsgCommand(const MessageId &id, const QString &name, int size, const QString &node,
|
||||
const QString &comment, QUndoCommand *parent = nullptr);
|
||||
EditMsgCommand(const MessageId &id, const std::string &name, int size, const std::string &node,
|
||||
const std::string &comment, QUndoCommand *parent = nullptr);
|
||||
void undo() override;
|
||||
void redo() override;
|
||||
|
||||
private:
|
||||
const MessageId id;
|
||||
QString old_name, new_name, old_comment, new_comment, old_node, new_node;
|
||||
std::string old_name, new_name, old_comment, new_comment, old_node, new_node;
|
||||
int old_size = 0, new_size = 0;
|
||||
};
|
||||
|
||||
@@ -52,7 +54,7 @@ public:
|
||||
|
||||
private:
|
||||
const MessageId id;
|
||||
QList<cabana::Signal> sigs;
|
||||
std::vector<cabana::Signal> sigs;
|
||||
};
|
||||
|
||||
class EditSignalCommand : public QUndoCommand {
|
||||
@@ -63,7 +65,7 @@ public:
|
||||
|
||||
private:
|
||||
const MessageId id;
|
||||
QList<std::pair<cabana::Signal, cabana::Signal>> sigs; // QList<{old_sig, new_sig}>
|
||||
std::vector<std::pair<cabana::Signal, cabana::Signal>> sigs; // {old_sig, new_sig}
|
||||
};
|
||||
|
||||
namespace UndoStack {
|
||||
|
||||
@@ -4,10 +4,6 @@
|
||||
|
||||
#include "tools/cabana/utils/util.h"
|
||||
|
||||
uint qHash(const MessageId &item) {
|
||||
return qHash(item.source) ^ qHash(item.address);
|
||||
}
|
||||
|
||||
// cabana::Msg
|
||||
|
||||
cabana::Msg::~Msg() {
|
||||
@@ -22,7 +18,7 @@ cabana::Signal *cabana::Msg::addSignal(const cabana::Signal &sig) {
|
||||
return s;
|
||||
}
|
||||
|
||||
cabana::Signal *cabana::Msg::updateSignal(const QString &sig_name, const cabana::Signal &new_sig) {
|
||||
cabana::Signal *cabana::Msg::updateSignal(const std::string &sig_name, const cabana::Signal &new_sig) {
|
||||
auto s = sig(sig_name);
|
||||
if (s) {
|
||||
*s = new_sig;
|
||||
@@ -31,7 +27,7 @@ cabana::Signal *cabana::Msg::updateSignal(const QString &sig_name, const cabana:
|
||||
return s;
|
||||
}
|
||||
|
||||
void cabana::Msg::removeSignal(const QString &sig_name) {
|
||||
void cabana::Msg::removeSignal(const std::string &sig_name) {
|
||||
auto it = std::find_if(sigs.begin(), sigs.end(), [&](auto &s) { return s->name == sig_name; });
|
||||
if (it != sigs.end()) {
|
||||
delete *it;
|
||||
@@ -57,7 +53,7 @@ cabana::Msg &cabana::Msg::operator=(const cabana::Msg &other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
cabana::Signal *cabana::Msg::sig(const QString &sig_name) const {
|
||||
cabana::Signal *cabana::Msg::sig(const std::string &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;
|
||||
}
|
||||
@@ -69,17 +65,17 @@ int cabana::Msg::indexOf(const cabana::Signal *sig) const {
|
||||
return -1;
|
||||
}
|
||||
|
||||
QString cabana::Msg::newSignalName() {
|
||||
QString new_name;
|
||||
std::string cabana::Msg::newSignalName() {
|
||||
std::string new_name;
|
||||
for (int i = 1; /**/; ++i) {
|
||||
new_name = QString("NEW_SIGNAL_%1").arg(i);
|
||||
new_name = "NEW_SIGNAL_" + std::to_string(i);
|
||||
if (sig(new_name) == nullptr) break;
|
||||
}
|
||||
return new_name;
|
||||
}
|
||||
|
||||
void cabana::Msg::update() {
|
||||
if (transmitter.isEmpty()) {
|
||||
if (transmitter.empty()) {
|
||||
transmitter = DEFAULT_NODE_NAME;
|
||||
}
|
||||
mask.assign(size, 0x00);
|
||||
@@ -129,13 +125,13 @@ void cabana::Msg::update() {
|
||||
|
||||
void cabana::Signal::update() {
|
||||
updateMsbLsb(*this);
|
||||
if (receiver_name.isEmpty()) {
|
||||
if (receiver_name.empty()) {
|
||||
receiver_name = DEFAULT_NODE_NAME;
|
||||
}
|
||||
|
||||
float h = 19 * (float)lsb / 64.0;
|
||||
h = fmod(h, 1.0);
|
||||
size_t hash = qHash(name);
|
||||
size_t hash = std::hash<std::string>{}(name);
|
||||
float s = 0.25 + 0.25 * (float)(hash & 0xff) / 255.0;
|
||||
float v = 0.75 + 0.25 * (float)((hash >> 8) & 0xff) / 255.0;
|
||||
|
||||
@@ -143,7 +139,7 @@ void cabana::Signal::update() {
|
||||
precision = std::max(num_decimals(factor), num_decimals(offset));
|
||||
}
|
||||
|
||||
QString cabana::Signal::formatValue(double value, bool with_unit) const {
|
||||
std::string cabana::Signal::formatValue(double value, bool with_unit) const {
|
||||
// Show enum string
|
||||
int64_t raw_value = round((value - offset) / factor);
|
||||
for (const auto &[val, desc] : val_desc) {
|
||||
@@ -152,8 +148,10 @@ QString cabana::Signal::formatValue(double value, bool with_unit) const {
|
||||
}
|
||||
}
|
||||
|
||||
QString val_str = QString::number(value, 'f', precision);
|
||||
if (with_unit && !unit.isEmpty()) {
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "%.*f", precision, value);
|
||||
std::string val_str(buf);
|
||||
if (with_unit && !unit.empty()) {
|
||||
val_str += " " + unit;
|
||||
}
|
||||
return val_str;
|
||||
|
||||
@@ -1,29 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <QColor>
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
|
||||
const QString UNTITLED = "untitled";
|
||||
const QString DEFAULT_NODE_NAME = "XXX";
|
||||
const std::string UNTITLED = "untitled";
|
||||
const std::string DEFAULT_NODE_NAME = "XXX";
|
||||
constexpr int CAN_MAX_DATA_BYTES = 64;
|
||||
|
||||
struct MessageId {
|
||||
uint8_t source = 0;
|
||||
uint32_t address = 0;
|
||||
|
||||
QString toString() const {
|
||||
return QString("%1:%2").arg(source).arg(QString::number(address, 16).toUpper());
|
||||
std::string toString() const {
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "%u:%X", source, address);
|
||||
return buf;
|
||||
}
|
||||
|
||||
inline static MessageId fromString(const QString &str) {
|
||||
auto parts = str.split(':');
|
||||
if (parts.size() != 2) return {};
|
||||
return MessageId{.source = uint8_t(parts[0].toUInt()), .address = parts[1].toUInt(nullptr, 16)};
|
||||
inline static MessageId fromString(const std::string &str) {
|
||||
auto pos = str.find(':');
|
||||
if (pos == std::string::npos) return {};
|
||||
return MessageId{.source = uint8_t(std::stoul(str.substr(0, pos))),
|
||||
.address = uint32_t(std::stoul(str.substr(pos + 1), nullptr, 16))};
|
||||
}
|
||||
|
||||
bool operator==(const MessageId &other) const {
|
||||
@@ -43,15 +49,17 @@ struct MessageId {
|
||||
}
|
||||
};
|
||||
|
||||
uint qHash(const MessageId &item);
|
||||
Q_DECLARE_METATYPE(MessageId);
|
||||
|
||||
template <>
|
||||
struct std::hash<MessageId> {
|
||||
std::size_t operator()(const MessageId &k) const noexcept { return qHash(k); }
|
||||
std::size_t operator()(const MessageId &k) const noexcept {
|
||||
return std::hash<uint8_t>{}(k.source) ^ (std::hash<uint32_t>{}(k.address) << 1);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<std::pair<double, QString>> ValueDescription;
|
||||
typedef std::vector<std::pair<double, std::string>> ValueDescription;
|
||||
Q_DECLARE_METATYPE(ValueDescription);
|
||||
|
||||
namespace cabana {
|
||||
|
||||
@@ -61,7 +69,7 @@ public:
|
||||
Signal(const Signal &other) = default;
|
||||
void update();
|
||||
bool getValue(const uint8_t *data, size_t data_size, double *val) const;
|
||||
QString formatValue(double value, bool with_unit = true) const;
|
||||
std::string formatValue(double value, bool with_unit = true) const;
|
||||
bool operator==(const cabana::Signal &other) const;
|
||||
inline bool operator!=(const cabana::Signal &other) const { return !(*this == other); }
|
||||
|
||||
@@ -72,16 +80,16 @@ public:
|
||||
};
|
||||
|
||||
Type type = Type::Normal;
|
||||
QString name;
|
||||
std::string name;
|
||||
int start_bit, msb, lsb, size;
|
||||
double factor = 1.0;
|
||||
double offset = 0;
|
||||
bool is_signed;
|
||||
bool is_little_endian;
|
||||
double min, max;
|
||||
QString unit;
|
||||
QString comment;
|
||||
QString receiver_name;
|
||||
std::string unit;
|
||||
std::string comment;
|
||||
std::string receiver_name;
|
||||
ValueDescription val_desc;
|
||||
int precision = 0;
|
||||
QColor color;
|
||||
@@ -97,20 +105,20 @@ public:
|
||||
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);
|
||||
cabana::Signal *updateSignal(const std::string &sig_name, const cabana::Signal &sig);
|
||||
void removeSignal(const std::string &sig_name);
|
||||
Msg &operator=(const Msg &other);
|
||||
int indexOf(const cabana::Signal *sig) const;
|
||||
cabana::Signal *sig(const QString &sig_name) const;
|
||||
QString newSignalName();
|
||||
cabana::Signal *sig(const std::string &sig_name) const;
|
||||
std::string newSignalName();
|
||||
void update();
|
||||
inline const std::vector<cabana::Signal *> &getSignals() const { return sigs; }
|
||||
|
||||
uint32_t address;
|
||||
QString name;
|
||||
std::string name;
|
||||
uint32_t size;
|
||||
QString comment;
|
||||
QString transmitter;
|
||||
std::string comment;
|
||||
std::string transmitter;
|
||||
std::vector<cabana::Signal *> sigs;
|
||||
|
||||
std::vector<uint8_t> mask;
|
||||
@@ -123,4 +131,8 @@ public:
|
||||
double get_raw_value(const uint8_t *data, size_t data_size, const cabana::Signal &sig);
|
||||
void updateMsbLsb(cabana::Signal &s);
|
||||
inline int flipBitPos(int start_bit) { return 8 * (start_bit / 8) + 7 - start_bit % 8; }
|
||||
inline QString doubleToString(double value) { return QString::number(value, 'g', std::numeric_limits<double>::digits10); }
|
||||
inline std::string doubleToString(double value) {
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "%.*g", std::numeric_limits<double>::digits10, value);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
|
||||
DBCFile::DBCFile(const QString &dbc_file_name) {
|
||||
QFile file(dbc_file_name);
|
||||
DBCFile::DBCFile(const std::string &dbc_file_name) {
|
||||
QFile file(QString::fromStdString(dbc_file_name));
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
name_ = QFileInfo(dbc_file_name).baseName();
|
||||
name_ = QFileInfo(QString::fromStdString(dbc_file_name)).baseName().toStdString();
|
||||
filename = dbc_file_name;
|
||||
parse(file.readAll());
|
||||
} else {
|
||||
@@ -15,34 +16,35 @@ DBCFile::DBCFile(const QString &dbc_file_name) {
|
||||
}
|
||||
}
|
||||
|
||||
DBCFile::DBCFile(const QString &name, const QString &content) : name_(name), filename("") {
|
||||
parse(content);
|
||||
DBCFile::DBCFile(const std::string &name, const std::string &content) : name_(name), filename("") {
|
||||
parse(QString::fromStdString(content));
|
||||
}
|
||||
|
||||
bool DBCFile::save() {
|
||||
assert(!filename.isEmpty());
|
||||
assert(!filename.empty());
|
||||
return writeContents(filename);
|
||||
}
|
||||
|
||||
bool DBCFile::saveAs(const QString &new_filename) {
|
||||
bool DBCFile::saveAs(const std::string &new_filename) {
|
||||
filename = new_filename;
|
||||
return save();
|
||||
}
|
||||
|
||||
bool DBCFile::writeContents(const QString &fn) {
|
||||
QFile file(fn);
|
||||
bool DBCFile::writeContents(const std::string &fn) {
|
||||
QFile file(QString::fromStdString(fn));
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
return file.write(generateDBC().toUtf8()) >= 0;
|
||||
std::string content = generateDBC();
|
||||
return file.write(content.c_str(), content.size()) >= 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DBCFile::updateMsg(const MessageId &id, const QString &name, uint32_t size, const QString &node, const QString &comment) {
|
||||
void DBCFile::updateMsg(const MessageId &id, const std::string &name, uint32_t size, const std::string &node, const std::string &comment) {
|
||||
auto &m = msgs[id.address];
|
||||
m.address = id.address;
|
||||
m.name = name;
|
||||
m.size = size;
|
||||
m.transmitter = node.isEmpty() ? DEFAULT_NODE_NAME : node;
|
||||
m.transmitter = node.empty() ? DEFAULT_NODE_NAME : node;
|
||||
m.comment = comment;
|
||||
}
|
||||
|
||||
@@ -51,12 +53,12 @@ cabana::Msg *DBCFile::msg(uint32_t address) {
|
||||
return it != msgs.end() ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
cabana::Msg *DBCFile::msg(const QString &name) {
|
||||
cabana::Msg *DBCFile::msg(const std::string &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;
|
||||
}
|
||||
|
||||
cabana::Signal *DBCFile::signal(uint32_t address, const QString &name) {
|
||||
cabana::Signal *DBCFile::signal(uint32_t address, const std::string &name) {
|
||||
auto m = msg(address);
|
||||
return m ? (cabana::Signal *)m->sig(name) : nullptr;
|
||||
}
|
||||
@@ -93,13 +95,13 @@ void DBCFile::parse(const QString &content) {
|
||||
seen = false;
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
throw std::runtime_error(QString("[%1:%2]%3: %4").arg(filename).arg(line_num).arg(e.what()).arg(line).toStdString());
|
||||
throw std::runtime_error(QString("[%1:%2]%3: %4").arg(QString::fromStdString(filename)).arg(line_num).arg(e.what()).arg(line).toStdString());
|
||||
}
|
||||
|
||||
if (seen) {
|
||||
seen_first = true;
|
||||
} else if (!seen_first) {
|
||||
header += raw_line + "\n";
|
||||
header += raw_line.toStdString() + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,9 +124,9 @@ cabana::Msg *DBCFile::parseBO(const QString &line) {
|
||||
// Create a new message object
|
||||
cabana::Msg *msg = &msgs[address];
|
||||
msg->address = address;
|
||||
msg->name = match.captured("name");
|
||||
msg->name = match.captured("name").toStdString();
|
||||
msg->size = match.captured("size").toULong();
|
||||
msg->transmitter = match.captured("transmitter").trimmed();
|
||||
msg->transmitter = match.captured("transmitter").trimmed().toStdString();
|
||||
return msg;
|
||||
}
|
||||
|
||||
@@ -141,7 +143,7 @@ void DBCFile::parseCM_BO(const QString &line, const QString &content, const QStr
|
||||
throw std::runtime_error("Invalid message comment format");
|
||||
|
||||
if (auto m = (cabana::Msg *)msg(match.captured("address").toUInt()))
|
||||
m->comment = match.captured("comment").trimmed().replace("\\\"", "\"");
|
||||
m->comment = match.captured("comment").trimmed().replace("\\\"", "\"").toStdString();
|
||||
}
|
||||
|
||||
void DBCFile::parseSG(const QString &line, cabana::Msg *current_msg, int &multiplexor_cnt) {
|
||||
@@ -160,7 +162,7 @@ void DBCFile::parseSG(const QString &line, cabana::Msg *current_msg, int &multip
|
||||
if (!match.hasMatch())
|
||||
throw std::runtime_error("Invalid SG_ line format");
|
||||
|
||||
QString name = match.captured(1);
|
||||
std::string name = match.captured(1).toStdString();
|
||||
if (current_msg->sig(name) != nullptr)
|
||||
throw std::runtime_error("Duplicate signal name");
|
||||
|
||||
@@ -188,8 +190,8 @@ void DBCFile::parseSG(const QString &line, cabana::Msg *current_msg, int &multip
|
||||
s.offset = match.captured(offset + 7).toDouble();
|
||||
s.min = match.captured(8 + offset).toDouble();
|
||||
s.max = match.captured(9 + offset).toDouble();
|
||||
s.unit = match.captured(10 + offset);
|
||||
s.receiver_name = match.captured(11 + offset).trimmed();
|
||||
s.unit = match.captured(10 + offset).toStdString();
|
||||
s.receiver_name = match.captured(11 + offset).trimmed().toStdString();
|
||||
current_msg->sigs.push_back(new cabana::Signal(s));
|
||||
}
|
||||
|
||||
@@ -205,8 +207,8 @@ void DBCFile::parseCM_SG(const QString &line, const QString &content, const QStr
|
||||
if (!match.hasMatch())
|
||||
throw std::runtime_error("Invalid CM_ SG_ line format");
|
||||
|
||||
if (auto s = signal(match.captured(1).toUInt(), match.captured(2))) {
|
||||
s->comment = match.captured(3).trimmed().replace("\\\"", "\"");
|
||||
if (auto s = signal(match.captured(1).toUInt(), match.captured(2).toStdString())) {
|
||||
s->comment = match.captured(3).trimmed().replace("\\\"", "\"").toStdString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,55 +219,60 @@ void DBCFile::parseVAL(const QString &line) {
|
||||
if (!match.hasMatch())
|
||||
throw std::runtime_error("invalid VAL_ line format");
|
||||
|
||||
if (auto s = signal(match.captured(1).toUInt(), match.captured(2))) {
|
||||
if (auto s = signal(match.captured(1).toUInt(), match.captured(2).toStdString())) {
|
||||
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});
|
||||
s->val_desc.push_back({val.toDouble(), desc.toStdString()});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString DBCFile::generateDBC() {
|
||||
QString dbc_string, comment, val_desc;
|
||||
std::string DBCFile::generateDBC() {
|
||||
std::string dbc_string, comment, val_desc;
|
||||
for (const auto &[address, m] : msgs) {
|
||||
const QString transmitter = m.transmitter.isEmpty() ? DEFAULT_NODE_NAME : m.transmitter;
|
||||
dbc_string += QString("BO_ %1 %2: %3 %4\n").arg(address).arg(m.name).arg(m.size).arg(transmitter);
|
||||
if (!m.comment.isEmpty()) {
|
||||
comment += QString("CM_ BO_ %1 \"%2\";\n").arg(address).arg(QString(m.comment).replace("\"", "\\\""));
|
||||
const std::string &transmitter = m.transmitter.empty() ? DEFAULT_NODE_NAME : m.transmitter;
|
||||
dbc_string += "BO_ " + std::to_string(address) + " " + m.name + ": " + std::to_string(m.size) + " " + transmitter + "\n";
|
||||
if (!m.comment.empty()) {
|
||||
std::string escaped_comment = m.comment;
|
||||
// Replace " with \"
|
||||
for (size_t pos = 0; (pos = escaped_comment.find('"', pos)) != std::string::npos; pos += 2)
|
||||
escaped_comment.replace(pos, 1, "\\\"");
|
||||
comment += "CM_ BO_ " + std::to_string(address) + " \"" + escaped_comment + "\";\n";
|
||||
}
|
||||
for (auto sig : m.getSignals()) {
|
||||
QString multiplexer_indicator;
|
||||
std::string multiplexer_indicator;
|
||||
if (sig->type == cabana::Signal::Type::Multiplexor) {
|
||||
multiplexer_indicator = "M ";
|
||||
} else if (sig->type == cabana::Signal::Type::Multiplexed) {
|
||||
multiplexer_indicator = QString("m%1 ").arg(sig->multiplex_value);
|
||||
multiplexer_indicator = "m" + std::to_string(sig->multiplex_value) + " ";
|
||||
}
|
||||
dbc_string += QString(" SG_ %1 %2: %3|%4@%5%6 (%7,%8) [%9|%10] \"%11\" %12\n")
|
||||
.arg(sig->name)
|
||||
.arg(multiplexer_indicator)
|
||||
.arg(sig->start_bit)
|
||||
.arg(sig->size)
|
||||
.arg(sig->is_little_endian ? '1' : '0')
|
||||
.arg(sig->is_signed ? '-' : '+')
|
||||
.arg(doubleToString(sig->factor))
|
||||
.arg(doubleToString(sig->offset))
|
||||
.arg(doubleToString(sig->min))
|
||||
.arg(doubleToString(sig->max))
|
||||
.arg(sig->unit)
|
||||
.arg(sig->receiver_name.isEmpty() ? DEFAULT_NODE_NAME : sig->receiver_name);
|
||||
if (!sig->comment.isEmpty()) {
|
||||
comment += QString("CM_ SG_ %1 %2 \"%3\";\n").arg(address).arg(sig->name).arg(QString(sig->comment).replace("\"", "\\\""));
|
||||
const std::string &recv = sig->receiver_name.empty() ? DEFAULT_NODE_NAME : sig->receiver_name;
|
||||
dbc_string += " SG_ " + sig->name + " " + multiplexer_indicator + ": " +
|
||||
std::to_string(sig->start_bit) + "|" + std::to_string(sig->size) + "@" +
|
||||
std::string(1, sig->is_little_endian ? '1' : '0') +
|
||||
std::string(1, sig->is_signed ? '-' : '+') +
|
||||
" (" + doubleToString(sig->factor) + "," + doubleToString(sig->offset) + ")" +
|
||||
" [" + doubleToString(sig->min) + "|" + doubleToString(sig->max) + "]" +
|
||||
" \"" + sig->unit + "\" " + recv + "\n";
|
||||
if (!sig->comment.empty()) {
|
||||
std::string escaped_comment = sig->comment;
|
||||
for (size_t pos = 0; (pos = escaped_comment.find('"', pos)) != std::string::npos; pos += 2)
|
||||
escaped_comment.replace(pos, 1, "\\\"");
|
||||
comment += "CM_ SG_ " + std::to_string(address) + " " + sig->name + " \"" + escaped_comment + "\";\n";
|
||||
}
|
||||
if (!sig->val_desc.empty()) {
|
||||
QStringList text;
|
||||
std::string text;
|
||||
for (auto &[val, desc] : sig->val_desc) {
|
||||
text << QString("%1 \"%2\"").arg(val).arg(desc);
|
||||
if (!text.empty()) text += " ";
|
||||
char val_buf[64];
|
||||
snprintf(val_buf, sizeof(val_buf), "%g", val);
|
||||
text += std::string(val_buf) + " \"" + desc + "\"";
|
||||
}
|
||||
val_desc += QString("VAL_ %1 %2 %3;\n").arg(address).arg(sig->name).arg(text.join(" "));
|
||||
val_desc += "VAL_ " + std::to_string(address) + " " + sig->name + " " + text + ";\n";
|
||||
}
|
||||
}
|
||||
dbc_string += "\n";
|
||||
|
||||
@@ -1,34 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <QTextStream>
|
||||
|
||||
#include "tools/cabana/dbc/dbc.h"
|
||||
|
||||
class DBCFile {
|
||||
public:
|
||||
DBCFile(const QString &dbc_file_name);
|
||||
DBCFile(const QString &name, const QString &content);
|
||||
DBCFile(const std::string &dbc_file_name);
|
||||
DBCFile(const std::string &name, const std::string &content);
|
||||
~DBCFile() {}
|
||||
|
||||
bool save();
|
||||
bool saveAs(const QString &new_filename);
|
||||
bool writeContents(const QString &fn);
|
||||
QString generateDBC();
|
||||
bool saveAs(const std::string &new_filename);
|
||||
bool writeContents(const std::string &fn);
|
||||
std::string generateDBC();
|
||||
|
||||
void updateMsg(const MessageId &id, const QString &name, uint32_t size, const QString &node, const QString &comment);
|
||||
void updateMsg(const MessageId &id, const std::string &name, uint32_t size, const std::string &node, const std::string &comment);
|
||||
inline void removeMsg(const MessageId &id) { msgs.erase(id.address); }
|
||||
|
||||
inline const std::map<uint32_t, cabana::Msg> &getMessages() const { return msgs; }
|
||||
cabana::Msg *msg(uint32_t address);
|
||||
cabana::Msg *msg(const QString &name);
|
||||
cabana::Msg *msg(const std::string &name);
|
||||
inline cabana::Msg *msg(const MessageId &id) { return msg(id.address); }
|
||||
cabana::Signal *signal(uint32_t address, const QString &name);
|
||||
cabana::Signal *signal(uint32_t address, const std::string &name);
|
||||
|
||||
inline QString name() const { return name_.isEmpty() ? "untitled" : name_; }
|
||||
inline bool isEmpty() const { return msgs.empty() && name_.isEmpty(); }
|
||||
inline std::string name() const { return name_.empty() ? "untitled" : name_; }
|
||||
inline bool isEmpty() const { return msgs.empty() && name_.empty(); }
|
||||
|
||||
QString filename;
|
||||
std::string filename;
|
||||
|
||||
private:
|
||||
void parse(const QString &content);
|
||||
@@ -38,7 +39,7 @@ private:
|
||||
void parseCM_SG(const QString &line, const QString &content, const QString &raw_line, const QTextStream &stream);
|
||||
void parseVAL(const QString &line);
|
||||
|
||||
QString header;
|
||||
std::string header;
|
||||
std::map<uint32_t, cabana::Msg> msgs;
|
||||
QString name_;
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#include "tools/cabana/dbc/dbcmanager.h"
|
||||
|
||||
#include <QSet>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <set>
|
||||
|
||||
bool DBCManager::open(const SourceSet &sources, const QString &dbc_file_name, QString *error) {
|
||||
bool DBCManager::open(const SourceSet &sources, const std::string &dbc_file_name, QString *error) {
|
||||
try {
|
||||
auto it = std::find_if(dbc_files.begin(), dbc_files.end(),
|
||||
[&](auto &f) { return f.second && f.second->filename == dbc_file_name; });
|
||||
@@ -21,7 +20,7 @@ bool DBCManager::open(const SourceSet &sources, const QString &dbc_file_name, QS
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DBCManager::open(const SourceSet &sources, const QString &name, const QString &content, QString *error) {
|
||||
bool DBCManager::open(const SourceSet &sources, const std::string &name, const std::string &content, QString *error) {
|
||||
try {
|
||||
auto file = std::make_shared<DBCFile>(name, content);
|
||||
for (auto s : sources) {
|
||||
@@ -64,7 +63,7 @@ void DBCManager::addSignal(const MessageId &id, const cabana::Signal &sig) {
|
||||
}
|
||||
}
|
||||
|
||||
void DBCManager::updateSignal(const MessageId &id, const QString &sig_name, const cabana::Signal &sig) {
|
||||
void DBCManager::updateSignal(const MessageId &id, const std::string &sig_name, const cabana::Signal &sig) {
|
||||
if (auto m = msg(id)) {
|
||||
if (auto s = m->updateSignal(sig_name, sig)) {
|
||||
emit signalUpdated(s);
|
||||
@@ -73,7 +72,7 @@ void DBCManager::updateSignal(const MessageId &id, const QString &sig_name, cons
|
||||
}
|
||||
}
|
||||
|
||||
void DBCManager::removeSignal(const MessageId &id, const QString &sig_name) {
|
||||
void DBCManager::removeSignal(const MessageId &id, const std::string &sig_name) {
|
||||
if (auto m = msg(id)) {
|
||||
if (auto s = m->sig(sig_name)) {
|
||||
emit signalRemoved(s);
|
||||
@@ -83,7 +82,7 @@ void DBCManager::removeSignal(const MessageId &id, const QString &sig_name) {
|
||||
}
|
||||
}
|
||||
|
||||
void DBCManager::updateMsg(const MessageId &id, const QString &name, uint32_t size, const QString &node, const QString &comment) {
|
||||
void DBCManager::updateMsg(const MessageId &id, const std::string &name, uint32_t size, const std::string &node, const std::string &comment) {
|
||||
auto dbc_file = findDBCFile(id);
|
||||
assert(dbc_file); // This should be impossible
|
||||
dbc_file->updateMsg(id, name, size, node, comment);
|
||||
@@ -98,11 +97,13 @@ void DBCManager::removeMsg(const MessageId &id) {
|
||||
emit maskUpdated();
|
||||
}
|
||||
|
||||
QString DBCManager::newMsgName(const MessageId &id) {
|
||||
return QString("NEW_MSG_") + QString::number(id.address, 16).toUpper();
|
||||
std::string DBCManager::newMsgName(const MessageId &id) {
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "NEW_MSG_%X", id.address);
|
||||
return buf;
|
||||
}
|
||||
|
||||
QString DBCManager::newSignalName(const MessageId &id) {
|
||||
std::string DBCManager::newSignalName(const MessageId &id) {
|
||||
auto m = msg(id);
|
||||
return m ? m->newSignalName() : "";
|
||||
}
|
||||
@@ -118,14 +119,14 @@ cabana::Msg *DBCManager::msg(const MessageId &id) {
|
||||
return dbc_file ? dbc_file->msg(id) : nullptr;
|
||||
}
|
||||
|
||||
cabana::Msg *DBCManager::msg(uint8_t source, const QString &name) {
|
||||
cabana::Msg *DBCManager::msg(uint8_t source, const std::string &name) {
|
||||
auto dbc_file = findDBCFile(source);
|
||||
return dbc_file ? dbc_file->msg(name) : nullptr;
|
||||
}
|
||||
|
||||
QStringList DBCManager::signalNames() {
|
||||
std::vector<std::string> DBCManager::signalNames() {
|
||||
// Used for autocompletion
|
||||
QSet<QString> names;
|
||||
std::set<std::string> names;
|
||||
for (auto &f : allDBCFiles()) {
|
||||
for (auto &[_, m] : f->getMessages()) {
|
||||
for (auto sig : m.getSignals()) {
|
||||
@@ -133,8 +134,8 @@ QStringList DBCManager::signalNames() {
|
||||
}
|
||||
}
|
||||
}
|
||||
QStringList ret = names.values();
|
||||
ret.sort();
|
||||
std::vector<std::string> ret(names.begin(), names.end());
|
||||
std::sort(ret.begin(), ret.end());
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -165,11 +166,13 @@ const SourceSet DBCManager::sources(const DBCFile *dbc_file) const {
|
||||
return sources;
|
||||
}
|
||||
|
||||
QString toString(const SourceSet &ss) {
|
||||
return std::accumulate(ss.cbegin(), ss.cend(), QString(), [](QString str, int source) {
|
||||
if (!str.isEmpty()) str += ", ";
|
||||
return str + (source == -1 ? QStringLiteral("all") : QString::number(source));
|
||||
});
|
||||
std::string toString(const SourceSet &ss) {
|
||||
std::string result;
|
||||
for (int source : ss) {
|
||||
if (!result.empty()) result += ", ";
|
||||
result += (source == -1) ? "all" : std::to_string(source);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DBCManager *dbc() {
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "tools/cabana/dbc/dbcfile.h"
|
||||
|
||||
@@ -18,27 +20,27 @@ class DBCManager : public QObject {
|
||||
public:
|
||||
DBCManager(QObject *parent) : QObject(parent) {}
|
||||
~DBCManager() {}
|
||||
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);
|
||||
bool open(const SourceSet &sources, const std::string &dbc_file_name, QString *error = nullptr);
|
||||
bool open(const SourceSet &sources, const std::string &name, const std::string &content, QString *error = nullptr);
|
||||
void close(const SourceSet &sources);
|
||||
void close(DBCFile *dbc_file);
|
||||
void closeAll();
|
||||
|
||||
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);
|
||||
void updateSignal(const MessageId &id, const std::string &sig_name, const cabana::Signal &sig);
|
||||
void removeSignal(const MessageId &id, const std::string &sig_name);
|
||||
|
||||
void updateMsg(const MessageId &id, const QString &name, uint32_t size, const QString &node, const QString &comment);
|
||||
void updateMsg(const MessageId &id, const std::string &name, uint32_t size, const std::string &node, const std::string &comment);
|
||||
void removeMsg(const MessageId &id);
|
||||
|
||||
QString newMsgName(const MessageId &id);
|
||||
QString newSignalName(const MessageId &id);
|
||||
std::string newMsgName(const MessageId &id);
|
||||
std::string newSignalName(const MessageId &id);
|
||||
|
||||
const std::map<uint32_t, cabana::Msg> &getMessages(uint8_t source);
|
||||
cabana::Msg *msg(const MessageId &id);
|
||||
cabana::Msg* msg(uint8_t source, const QString &name);
|
||||
cabana::Msg* msg(uint8_t source, const std::string &name);
|
||||
|
||||
QStringList signalNames();
|
||||
std::vector<std::string> signalNames();
|
||||
inline int dbcCount() { return allDBCFiles().size(); }
|
||||
int nonEmptyDBCCount();
|
||||
|
||||
@@ -62,8 +64,8 @@ private:
|
||||
|
||||
DBCManager *dbc();
|
||||
|
||||
QString toString(const SourceSet &ss);
|
||||
inline QString msgName(const MessageId &id) {
|
||||
std::string toString(const SourceSet &ss);
|
||||
inline std::string msgName(const MessageId &id) {
|
||||
auto msg = dbc()->msg(id);
|
||||
return msg ? msg->name : UNTITLED;
|
||||
}
|
||||
|
||||
@@ -124,9 +124,9 @@ int DetailWidget::findOrAddTab(const MessageId& message_id) {
|
||||
if (tabbar->tabData(index).value<MessageId>() == message_id) break;
|
||||
}
|
||||
if (index == -1) {
|
||||
index = tabbar->addTab(message_id.toString());
|
||||
index = tabbar->addTab(QString::fromStdString(message_id.toString()));
|
||||
tabbar->setTabData(index, QVariant::fromValue(message_id));
|
||||
tabbar->setTabToolTip(index, msgName(message_id));
|
||||
tabbar->setTabToolTip(index, QString::fromStdString(msgName(message_id)));
|
||||
}
|
||||
return index;
|
||||
}
|
||||
@@ -151,21 +151,21 @@ std::pair<QString, QStringList> DetailWidget::serializeMessageIds() const {
|
||||
QStringList msgs;
|
||||
for (int i = 0; i < tabbar->count(); ++i) {
|
||||
MessageId id = tabbar->tabData(i).value<MessageId>();
|
||||
msgs.append(id.toString());
|
||||
msgs.append(QString::fromStdString(id.toString()));
|
||||
}
|
||||
return std::make_pair(msg_id.toString(), msgs);
|
||||
return std::make_pair(QString::fromStdString(msg_id.toString()), msgs);
|
||||
}
|
||||
|
||||
void DetailWidget::restoreTabs(const QString active_msg_id, const QStringList& msg_ids) {
|
||||
tabbar->blockSignals(true);
|
||||
for (const auto& str_id : msg_ids) {
|
||||
MessageId id = MessageId::fromString(str_id);
|
||||
MessageId id = MessageId::fromString(str_id.toStdString());
|
||||
if (dbc()->msg(id) != nullptr)
|
||||
findOrAddTab(id);
|
||||
}
|
||||
tabbar->blockSignals(false);
|
||||
|
||||
auto active_id = MessageId::fromString(active_msg_id);
|
||||
auto active_id = MessageId::fromString(active_msg_id.toStdString());
|
||||
if (dbc()->msg(active_id) != nullptr)
|
||||
setMessage(active_id);
|
||||
}
|
||||
@@ -180,10 +180,10 @@ void DetailWidget::refresh() {
|
||||
warnings.push_back(tr("Message size (%1) is incorrect.").arg(msg->size));
|
||||
}
|
||||
for (auto s : binary_view->getOverlappingSignals()) {
|
||||
warnings.push_back(tr("%1 has overlapping bits.").arg(s->name));
|
||||
warnings.push_back(tr("%1 has overlapping bits.").arg(QString::fromStdString(s->name)));
|
||||
}
|
||||
}
|
||||
QString msg_name = msg ? QString("%1 (%2)").arg(msg->name, msg->transmitter) : msgName(msg_id);
|
||||
QString msg_name = msg ? QString("%1 (%2)").arg(QString::fromStdString(msg->name), QString::fromStdString(msg->transmitter)) : QString::fromStdString(msgName(msg_id));
|
||||
name_label->setText(msg_name);
|
||||
name_label->setToolTip(msg_name);
|
||||
action_remove_msg->setEnabled(msg != nullptr);
|
||||
@@ -208,10 +208,10 @@ void DetailWidget::updateState(const std::set<MessageId> *msgs) {
|
||||
void DetailWidget::editMsg() {
|
||||
auto msg = dbc()->msg(msg_id);
|
||||
int size = msg ? msg->size : can->lastMessage(msg_id).dat.size();
|
||||
EditMessageDialog dlg(msg_id, msgName(msg_id), size, this);
|
||||
EditMessageDialog dlg(msg_id, QString::fromStdString(msgName(msg_id)), size, this);
|
||||
if (dlg.exec()) {
|
||||
UndoStack::push(new EditMsgCommand(msg_id, dlg.name_edit->text().trimmed(), dlg.size_spin->value(),
|
||||
dlg.node->text().trimmed(), dlg.comment_edit->toPlainText().trimmed()));
|
||||
UndoStack::push(new EditMsgCommand(msg_id, dlg.name_edit->text().trimmed().toStdString(), dlg.size_spin->value(),
|
||||
dlg.node->text().trimmed().toStdString(), dlg.comment_edit->toPlainText().trimmed().toStdString()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ void DetailWidget::removeMsg() {
|
||||
|
||||
EditMessageDialog::EditMessageDialog(const MessageId &msg_id, const QString &title, int size, QWidget *parent)
|
||||
: original_name(title), msg_id(msg_id), QDialog(parent) {
|
||||
setWindowTitle(tr("Edit message: %1").arg(msg_id.toString()));
|
||||
setWindowTitle(tr("Edit message: %1").arg(QString::fromStdString(msg_id.toString())));
|
||||
QFormLayout *form_layout = new QFormLayout(this);
|
||||
|
||||
form_layout->addRow("", error_label = new QLabel);
|
||||
@@ -241,8 +241,8 @@ EditMessageDialog::EditMessageDialog(const MessageId &msg_id, const QString &tit
|
||||
form_layout->addRow(btn_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel));
|
||||
|
||||
if (auto msg = dbc()->msg(msg_id)) {
|
||||
node->setText(msg->transmitter);
|
||||
comment_edit->setText(msg->comment);
|
||||
node->setText(QString::fromStdString(msg->transmitter));
|
||||
comment_edit->setText(QString::fromStdString(msg->comment));
|
||||
}
|
||||
validateName(name_edit->text());
|
||||
setFixedWidth(parent->width() * 0.9);
|
||||
@@ -252,10 +252,10 @@ EditMessageDialog::EditMessageDialog(const MessageId &msg_id, const QString &tit
|
||||
}
|
||||
|
||||
void EditMessageDialog::validateName(const QString &text) {
|
||||
bool valid = text.compare(UNTITLED, Qt::CaseInsensitive) != 0;
|
||||
bool valid = text.compare(QString::fromStdString(UNTITLED), Qt::CaseInsensitive) != 0;
|
||||
error_label->setVisible(false);
|
||||
if (!text.isEmpty() && valid && text != original_name) {
|
||||
valid = dbc()->msg(msg_id.source, text) == nullptr;
|
||||
valid = dbc()->msg(msg_id.source, text.toStdString()) == nullptr;
|
||||
if (!valid) {
|
||||
error_label->setText(tr("Name already exists"));
|
||||
error_label->setVisible(true);
|
||||
|
||||
@@ -14,7 +14,7 @@ QVariant HistoryLogModel::data(const QModelIndex &index, int role) const {
|
||||
const int col = index.column();
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (col == 0) return QString::number(can->toSeconds(m.mono_time), 'f', 3);
|
||||
if (!isHexMode()) return sigs[col - 1]->formatValue(m.sig_values[col - 1], false);
|
||||
if (!isHexMode()) return QString::fromStdString(sigs[col - 1]->formatValue(m.sig_values[col - 1], false));
|
||||
} else if (role == Qt::TextAlignmentRole) {
|
||||
return (uint32_t)(Qt::AlignRight | Qt::AlignVCenter);
|
||||
}
|
||||
@@ -49,8 +49,8 @@ QVariant HistoryLogModel::headerData(int section, Qt::Orientation orientation, i
|
||||
if (section == 0) return "Time";
|
||||
if (isHexMode()) return "Data";
|
||||
|
||||
QString name = sigs[section - 1]->name;
|
||||
QString unit = sigs[section - 1]->unit;
|
||||
QString name = QString::fromStdString(sigs[section - 1]->name);
|
||||
QString unit = QString::fromStdString(sigs[section - 1]->unit);
|
||||
return unit.isEmpty() ? name : QString("%1 (%2)").arg(name, unit);
|
||||
} else if (role == Qt::BackgroundRole && section > 0 && !isHexMode()) {
|
||||
// Alpha-blend the signal color with the background to ensure contrast
|
||||
@@ -216,7 +216,7 @@ LogsWidget::LogsWidget(QWidget *parent) : QFrame(parent) {
|
||||
void LogsWidget::modelReset() {
|
||||
signals_cb->clear();
|
||||
for (auto s : model->sigs) {
|
||||
signals_cb->addItem(s->name);
|
||||
signals_cb->addItem(QString::fromStdString(s->name));
|
||||
}
|
||||
export_btn->setEnabled(false);
|
||||
value_edit->clear();
|
||||
@@ -238,8 +238,8 @@ void LogsWidget::filterChanged() {
|
||||
}
|
||||
|
||||
void LogsWidget::exportToCSV() {
|
||||
QString dir = QString("%1/%2_%3.csv").arg(settings.last_dir).arg(can->routeName()).arg(msgName(model->msg_id));
|
||||
QString fn = QFileDialog::getSaveFileName(this, QString("Export %1 to CSV file").arg(msgName(model->msg_id)),
|
||||
QString dir = QString("%1/%2_%3.csv").arg(settings.last_dir).arg(QString::fromStdString(can->routeName())).arg(QString::fromStdString(msgName(model->msg_id)));
|
||||
QString fn = QFileDialog::getSaveFileName(this, QString("Export %1 to CSV file").arg(QString::fromStdString(msgName(model->msg_id))),
|
||||
dir, tr("csv (*.csv)"));
|
||||
if (!fn.isEmpty()) {
|
||||
model->isHexMode() ? utils::exportToCSV(fn, model->msg_id)
|
||||
|
||||
@@ -234,7 +234,7 @@ void MainWindow::DBCFileChanged() {
|
||||
|
||||
QStringList title;
|
||||
for (auto f : dbc()->allDBCFiles()) {
|
||||
title.push_back(tr("(%1) %2").arg(toString(dbc()->sources(f)), f->name()));
|
||||
title.push_back(tr("(%1) %2").arg(QString::fromStdString(toString(dbc()->sources(f))), QString::fromStdString(f->name())));
|
||||
}
|
||||
setWindowFilePath(title.join(" | "));
|
||||
|
||||
@@ -259,7 +259,7 @@ void MainWindow::closeStream() {
|
||||
}
|
||||
|
||||
void MainWindow::exportToCSV() {
|
||||
QString dir = QString("%1/%2.csv").arg(settings.last_dir).arg(can->routeName());
|
||||
QString dir = QString("%1/%2.csv").arg(settings.last_dir).arg(QString::fromStdString(can->routeName()));
|
||||
QString fn = QFileDialog::getSaveFileName(this, "Export stream to CSV file", dir, tr("csv (*.csv)"));
|
||||
if (!fn.isEmpty()) {
|
||||
utils::exportToCSV(fn);
|
||||
@@ -268,7 +268,7 @@ void MainWindow::exportToCSV() {
|
||||
|
||||
void MainWindow::newFile(SourceSet s) {
|
||||
closeFile(s);
|
||||
dbc()->open(s, "", "");
|
||||
dbc()->open(s, std::string(""), std::string(""));
|
||||
}
|
||||
|
||||
void MainWindow::openFile(SourceSet s) {
|
||||
@@ -284,7 +284,7 @@ void MainWindow::loadFile(const QString &fn, SourceSet s) {
|
||||
closeFile(s);
|
||||
|
||||
QString error;
|
||||
if (dbc()->open(s, fn, &error)) {
|
||||
if (dbc()->open(s, fn.toStdString(), &error)) {
|
||||
updateRecentFiles(fn);
|
||||
statusBar()->showMessage(tr("DBC File %1 loaded").arg(fn), 2000);
|
||||
} else {
|
||||
@@ -304,7 +304,7 @@ void MainWindow::loadFromClipboard(SourceSet s, bool close_all) {
|
||||
|
||||
QString dbc_str = QGuiApplication::clipboard()->text();
|
||||
QString error;
|
||||
bool ret = dbc()->open(s, "", dbc_str, &error);
|
||||
bool ret = dbc()->open(s, std::string(""), dbc_str.toStdString(), &error);
|
||||
if (ret && dbc()->nonEmptyDBCCount() > 0) {
|
||||
QMessageBox::information(this, tr("Load From Clipboard"), tr("DBC Successfully Loaded!"));
|
||||
} else {
|
||||
@@ -333,7 +333,7 @@ void MainWindow::startStream(AbstractStream *stream, QString dbc_file) {
|
||||
can->start();
|
||||
|
||||
loadFile(dbc_file);
|
||||
statusBar()->showMessage(tr("Stream [%1] started").arg(can->routeName()), 2000);
|
||||
statusBar()->showMessage(tr("Stream [%1] started").arg(QString::fromStdString(can->routeName())), 2000);
|
||||
|
||||
bool has_stream = dynamic_cast<DummyStream *>(can) == nullptr;
|
||||
close_stream_act->setEnabled(has_stream);
|
||||
@@ -341,7 +341,7 @@ void MainWindow::startStream(AbstractStream *stream, QString dbc_file) {
|
||||
tools_menu->setEnabled(has_stream);
|
||||
createDockWidgets();
|
||||
|
||||
video_dock->setWindowTitle(can->routeName());
|
||||
video_dock->setWindowTitle(QString::fromStdString(can->routeName()));
|
||||
if (can->liveStreaming() || video_splitter->sizes()[0] == 0) {
|
||||
// display video at minimum size.
|
||||
video_splitter->setSizes({1, 1});
|
||||
@@ -368,9 +368,9 @@ void MainWindow::startStream(AbstractStream *stream, QString dbc_file) {
|
||||
}
|
||||
|
||||
void MainWindow::eventsMerged() {
|
||||
if (!can->liveStreaming() && std::exchange(car_fingerprint, can->carFingerprint()) != car_fingerprint) {
|
||||
if (!can->liveStreaming() && std::exchange(car_fingerprint, QString::fromStdString(can->carFingerprint())) != car_fingerprint) {
|
||||
video_dock->setWindowTitle(tr("ROUTE: %1 FINGERPRINT: %2")
|
||||
.arg(can->routeName())
|
||||
.arg(QString::fromStdString(can->routeName()))
|
||||
.arg(car_fingerprint.isEmpty() ? tr("Unknown Car") : car_fingerprint));
|
||||
// Don't overwrite already loaded DBC
|
||||
if (!dbc()->nonEmptyDBCCount() && fingerprint_to_dbc.object().contains(car_fingerprint)) {
|
||||
@@ -416,7 +416,7 @@ void MainWindow::closeFile(DBCFile *dbc_file) {
|
||||
|
||||
void MainWindow::saveFile(DBCFile *dbc_file) {
|
||||
assert(dbc_file != nullptr);
|
||||
if (!dbc_file->filename.isEmpty()) {
|
||||
if (!dbc_file->filename.empty()) {
|
||||
dbc_file->save();
|
||||
UndoStack::instance()->setClean();
|
||||
statusBar()->showMessage(tr("File saved"), 2000);
|
||||
@@ -426,10 +426,10 @@ void MainWindow::saveFile(DBCFile *dbc_file) {
|
||||
}
|
||||
|
||||
void MainWindow::saveFileAs(DBCFile *dbc_file) {
|
||||
QString title = tr("Save File (bus: %1)").arg(toString(dbc()->sources(dbc_file)));
|
||||
QString title = tr("Save File (bus: %1)").arg(QString::fromStdString(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);
|
||||
dbc_file->saveAs(fn.toStdString());
|
||||
UndoStack::instance()->setClean();
|
||||
statusBar()->showMessage(tr("File saved as %1").arg(fn), 2000);
|
||||
updateRecentFiles(fn);
|
||||
@@ -446,7 +446,7 @@ void MainWindow::saveToClipboard() {
|
||||
|
||||
void MainWindow::saveFileToClipboard(DBCFile *dbc_file) {
|
||||
assert(dbc_file != nullptr);
|
||||
QGuiApplication::clipboard()->setText(dbc_file->generateDBC());
|
||||
QGuiApplication::clipboard()->setText(QString::fromStdString(dbc_file->generateDBC()));
|
||||
QMessageBox::information(this, tr("Copy To Clipboard"), tr("DBC Successfully copied!"));
|
||||
}
|
||||
|
||||
@@ -467,14 +467,14 @@ void MainWindow::updateLoadSaveMenus() {
|
||||
auto dbc_file = dbc()->findDBCFile(source);
|
||||
if (dbc_file) {
|
||||
bus_menu->addSeparator();
|
||||
bus_menu->addAction(dbc_file->name() + " (" + toString(dbc()->sources(dbc_file)) + ")")->setEnabled(false);
|
||||
bus_menu->addAction(QString::fromStdString(dbc_file->name()) + " (" + QString::fromStdString(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); });
|
||||
}
|
||||
bus_menu->setTitle(tr("Bus %1 (%2)").arg(source).arg(dbc_file ? dbc_file->name() : "No DBCs loaded"));
|
||||
bus_menu->setTitle(tr("Bus %1 (%2)").arg(source).arg(dbc_file ? QString::fromStdString(dbc_file->name()) : "No DBCs loaded"));
|
||||
|
||||
manage_dbcs_menu->addMenu(bus_menu);
|
||||
}
|
||||
@@ -627,7 +627,7 @@ void MainWindow::saveSessionState() {
|
||||
settings.active_charts.clear();
|
||||
|
||||
for (auto &f : dbc()->allDBCFiles())
|
||||
if (!f->isEmpty()) { settings.recent_dbc_file = f->filename; break; }
|
||||
if (!f->isEmpty()) { settings.recent_dbc_file = QString::fromStdString(f->filename); break; }
|
||||
|
||||
if (auto *detail = center_widget->getDetailWidget()) {
|
||||
auto [active_id, ids] = detail->serializeMessageIds();
|
||||
@@ -643,7 +643,7 @@ void MainWindow::restoreSessionState() {
|
||||
|
||||
QString dbc_file;
|
||||
for (auto& f : dbc()->allDBCFiles())
|
||||
if (!f->isEmpty()) { dbc_file = f->filename; break; }
|
||||
if (!f->isEmpty()) { dbc_file = QString::fromStdString(f->filename); break; }
|
||||
if (dbc_file != settings.recent_dbc_file) return;
|
||||
|
||||
if (!settings.selected_msg_ids.isEmpty())
|
||||
|
||||
@@ -205,7 +205,7 @@ QVariant MessageListModel::data(const QModelIndex &index, int role) const {
|
||||
} else if (role == Qt::ToolTipRole && index.column() == Column::NAME) {
|
||||
auto msg = dbc()->msg(item.id);
|
||||
auto tooltip = item.name;
|
||||
if (msg && !msg->comment.isEmpty()) tooltip += "<br /><span style=\"color:gray;\">" + msg->comment + "</span>";
|
||||
if (msg && !msg->comment.empty()) tooltip += "<br /><span style=\"color:gray;\">" + QString::fromStdString(msg->comment) + "</span>";
|
||||
return tooltip;
|
||||
}
|
||||
return {};
|
||||
@@ -277,7 +277,7 @@ bool MessageListModel::match(const MessageListModel::Item &item) {
|
||||
if (!match) {
|
||||
const auto m = dbc()->msg(item.id);
|
||||
match = m && std::any_of(m->sigs.cbegin(), m->sigs.cend(),
|
||||
[&txt](const auto &s) { return s->name.contains(txt, Qt::CaseInsensitive); });
|
||||
[&txt](const auto &s) { return QString::fromStdString(s->name).contains(txt, Qt::CaseInsensitive); });
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -323,8 +323,8 @@ bool MessageListModel::filterAndSort() {
|
||||
if (show_inactive_messages || can->isMessageActive(id)) {
|
||||
auto msg = dbc()->msg(id);
|
||||
Item item = {.id = id,
|
||||
.name = msg ? msg->name : UNTITLED,
|
||||
.node = msg ? msg->transmitter : QString()};
|
||||
.name = msg ? QString::fromStdString(msg->name) : QString::fromStdString(UNTITLED),
|
||||
.node = msg ? QString::fromStdString(msg->transmitter) : QString()};
|
||||
if (match(item))
|
||||
items.emplace_back(item);
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ SignalModel::SignalModel(QObject *parent) : root(new Item), QAbstractItemModel(p
|
||||
}
|
||||
|
||||
void SignalModel::insertItem(SignalModel::Item *root_item, int pos, const cabana::Signal *sig) {
|
||||
Item *parent_item = new Item{.type = Item::Sig, .parent = root_item, .sig = sig, .title = sig->name};
|
||||
root_item->children.insert(pos, parent_item);
|
||||
Item *parent_item = new Item{.type = Item::Sig, .parent = root_item, .sig = sig, .title = QString::fromStdString(sig->name)};
|
||||
root_item->children.insert(root_item->children.begin() + pos, parent_item);
|
||||
QString titles[]{"Name", "Size", "Receiver Nodes", "Little Endian", "Signed", "Offset", "Factor", "Type",
|
||||
"Multiplex Value", "Extra Info", "Unit", "Comment", "Minimum Value", "Maximum Value", "Value Table"};
|
||||
for (int i = 0; i < std::size(titles); ++i) {
|
||||
@@ -63,7 +63,7 @@ void SignalModel::refresh() {
|
||||
root.reset(new SignalModel::Item);
|
||||
if (auto msg = dbc()->msg(msg_id)) {
|
||||
for (auto s : msg->getSignals()) {
|
||||
if (filter_str.isEmpty() || s->name.contains(filter_str, Qt::CaseInsensitive)) {
|
||||
if (filter_str.isEmpty() || QString::fromStdString(s->name).contains(filter_str, Qt::CaseInsensitive)) {
|
||||
insertItem(root.get(), root->children.size(), s);
|
||||
}
|
||||
}
|
||||
@@ -124,25 +124,25 @@ QVariant SignalModel::data(const QModelIndex &index, int role) const {
|
||||
const Item *item = getItem(index);
|
||||
if (role == Qt::DisplayRole || role == Qt::EditRole) {
|
||||
if (index.column() == 0) {
|
||||
return item->type == Item::Sig ? item->sig->name : item->title;
|
||||
return item->type == Item::Sig ? QString::fromStdString(item->sig->name) : item->title;
|
||||
} else {
|
||||
switch (item->type) {
|
||||
case Item::Sig: return item->sig_val;
|
||||
case Item::Name: return item->sig->name;
|
||||
case Item::Name: return QString::fromStdString(item->sig->name);
|
||||
case Item::Size: return item->sig->size;
|
||||
case Item::Node: return item->sig->receiver_name;
|
||||
case Item::Node: return QString::fromStdString(item->sig->receiver_name);
|
||||
case Item::SignalType: return signalTypeToString(item->sig->type);
|
||||
case Item::MultiplexValue: return item->sig->multiplex_value;
|
||||
case Item::Offset: return doubleToString(item->sig->offset);
|
||||
case Item::Factor: return doubleToString(item->sig->factor);
|
||||
case Item::Unit: return item->sig->unit;
|
||||
case Item::Comment: return item->sig->comment;
|
||||
case Item::Min: return doubleToString(item->sig->min);
|
||||
case Item::Max: return doubleToString(item->sig->max);
|
||||
case Item::Offset: return QString::fromStdString(doubleToString(item->sig->offset));
|
||||
case Item::Factor: return QString::fromStdString(doubleToString(item->sig->factor));
|
||||
case Item::Unit: return QString::fromStdString(item->sig->unit);
|
||||
case Item::Comment: return QString::fromStdString(item->sig->comment);
|
||||
case Item::Min: return QString::fromStdString(doubleToString(item->sig->min));
|
||||
case Item::Max: return QString::fromStdString(doubleToString(item->sig->max));
|
||||
case Item::Desc: {
|
||||
QStringList val_desc;
|
||||
for (auto &[val, desc] : item->sig->val_desc) {
|
||||
val_desc << QString("%1 \"%2\"").arg(val).arg(desc);
|
||||
val_desc << QString("%1 \"%2\"").arg(val).arg(QString::fromStdString(desc));
|
||||
}
|
||||
return val_desc.join(" ");
|
||||
}
|
||||
@@ -165,17 +165,17 @@ bool SignalModel::setData(const QModelIndex &index, const QVariant &value, int r
|
||||
Item *item = getItem(index);
|
||||
cabana::Signal s = *item->sig;
|
||||
switch (item->type) {
|
||||
case Item::Name: s.name = value.toString(); break;
|
||||
case Item::Name: s.name = value.toString().toStdString(); break;
|
||||
case Item::Size: s.size = value.toInt(); break;
|
||||
case Item::Node: s.receiver_name = value.toString().trimmed(); break;
|
||||
case Item::Node: s.receiver_name = value.toString().trimmed().toStdString(); break;
|
||||
case Item::SignalType: s.type = (cabana::Signal::Type)value.toInt(); break;
|
||||
case Item::MultiplexValue: s.multiplex_value = value.toInt(); break;
|
||||
case Item::Endian: s.is_little_endian = value.toBool(); break;
|
||||
case Item::Signed: s.is_signed = value.toBool(); break;
|
||||
case Item::Offset: s.offset = value.toDouble(); break;
|
||||
case Item::Factor: s.factor = value.toDouble(); break;
|
||||
case Item::Unit: s.unit = value.toString(); break;
|
||||
case Item::Comment: s.comment = value.toString(); break;
|
||||
case Item::Unit: s.unit = value.toString().toStdString(); break;
|
||||
case Item::Comment: s.comment = value.toString().toStdString(); break;
|
||||
case Item::Min: s.min = value.toDouble(); break;
|
||||
case Item::Max: s.max = value.toDouble(); break;
|
||||
case Item::Desc: s.val_desc = value.value<ValueDescription>(); break;
|
||||
@@ -189,7 +189,7 @@ bool SignalModel::setData(const QModelIndex &index, const QVariant &value, int r
|
||||
bool SignalModel::saveSignal(const cabana::Signal *origin_s, cabana::Signal &s) {
|
||||
auto msg = dbc()->msg(msg_id);
|
||||
if (s.name != origin_s->name && msg->sig(s.name) != nullptr) {
|
||||
QString text = tr("There is already a signal with the same name '%1'").arg(s.name);
|
||||
QString text = tr("There is already a signal with the same name '%1'").arg(QString::fromStdString(s.name));
|
||||
QMessageBox::warning(nullptr, tr("Failed to save signal"), text);
|
||||
return false;
|
||||
}
|
||||
@@ -214,7 +214,7 @@ void SignalModel::handleSignalAdded(MessageId id, const cabana::Signal *sig) {
|
||||
beginInsertRows({}, i, i);
|
||||
insertItem(root.get(), i, sig);
|
||||
endInsertRows();
|
||||
} else if (sig->name.contains(filter_str, Qt::CaseInsensitive)) {
|
||||
} else if (QString::fromStdString(sig->name).contains(filter_str, Qt::CaseInsensitive)) {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
@@ -229,7 +229,9 @@ void SignalModel::handleSignalUpdated(const cabana::Signal *sig) {
|
||||
int to = dbc()->msg(msg_id)->indexOf(sig);
|
||||
if (to != row) {
|
||||
beginMoveRows({}, row, row, {}, to > row ? to + 1 : to);
|
||||
root->children.move(row, to);
|
||||
auto item = root->children[row];
|
||||
root->children.erase(root->children.begin() + row);
|
||||
root->children.insert(root->children.begin() + to, item);
|
||||
endMoveRows();
|
||||
}
|
||||
}
|
||||
@@ -239,7 +241,8 @@ void SignalModel::handleSignalUpdated(const cabana::Signal *sig) {
|
||||
void SignalModel::handleSignalRemoved(const cabana::Signal *sig) {
|
||||
if (int row = signalRow(sig); row != -1) {
|
||||
beginRemoveRows({}, row, row);
|
||||
delete root->children.takeAt(row);
|
||||
delete root->children[row];
|
||||
root->children.erase(root->children.begin() + row);
|
||||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
@@ -373,7 +376,10 @@ QWidget *SignalItemDelegate::createEditor(QWidget *parent, const QStyleOptionVie
|
||||
else e->setValidator(double_validator);
|
||||
|
||||
if (item->type == SignalModel::Item::Name) {
|
||||
QCompleter *completer = new QCompleter(dbc()->signalNames(), e);
|
||||
auto names = dbc()->signalNames();
|
||||
QStringList qnames;
|
||||
for (const auto &n : names) qnames.push_back(QString::fromStdString(n));
|
||||
QCompleter *completer = new QCompleter(qnames, e);
|
||||
completer->setCaseSensitivity(Qt::CaseInsensitive);
|
||||
completer->setFilterMode(Qt::MatchContains);
|
||||
e->setCompleter(completer);
|
||||
@@ -395,7 +401,7 @@ QWidget *SignalItemDelegate::createEditor(QWidget *parent, const QStyleOptionVie
|
||||
return c;
|
||||
} else if (item->type == SignalModel::Item::Desc) {
|
||||
ValueDescriptionDlg dlg(item->sig->val_desc, parent);
|
||||
dlg.setWindowTitle(item->sig->name);
|
||||
dlg.setWindowTitle(QString::fromStdString(item->sig->name));
|
||||
if (dlg.exec()) {
|
||||
((QAbstractItemModel *)index.model())->setData(index, QVariant::fromValue(dlg.val_desc));
|
||||
}
|
||||
@@ -621,7 +627,7 @@ void SignalView::updateState(const std::set<MessageId> *msgs) {
|
||||
for (auto item : model->root->children) {
|
||||
double value = 0;
|
||||
if (item->sig->getValue(last_msg.dat.data(), last_msg.dat.size(), &value)) {
|
||||
item->sig_val = item->sig->formatValue(value);
|
||||
item->sig_val = QString::fromStdString(item->sig->formatValue(value));
|
||||
max_value_width = std::max(max_value_width, fontMetrics().horizontalAdvance(item->sig_val));
|
||||
}
|
||||
}
|
||||
@@ -677,7 +683,7 @@ ValueDescriptionDlg::ValueDescriptionDlg(const ValueDescription &descriptions, Q
|
||||
int row = 0;
|
||||
for (auto &[val, desc] : descriptions) {
|
||||
table->setItem(row, 0, new QTableWidgetItem(QString::number(val)));
|
||||
table->setItem(row, 1, new QTableWidgetItem(desc));
|
||||
table->setItem(row, 1, new QTableWidgetItem(QString::fromStdString(desc)));
|
||||
++row;
|
||||
}
|
||||
|
||||
@@ -706,7 +712,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.toDouble(), desc});
|
||||
val_desc.push_back({val.toDouble(), desc.toStdString()});
|
||||
}
|
||||
}
|
||||
QDialog::accept();
|
||||
|
||||
@@ -20,12 +20,15 @@ class SignalModel : public QAbstractItemModel {
|
||||
public:
|
||||
struct Item {
|
||||
enum Type {Root, Sig, Name, Size, Node, Endian, Signed, Offset, Factor, SignalType, MultiplexValue, ExtraInfo, Unit, Comment, Min, Max, Desc };
|
||||
~Item() { qDeleteAll(children); }
|
||||
inline int row() { return parent->children.indexOf(this); }
|
||||
~Item() { for (auto c : children) delete c; }
|
||||
inline int row() {
|
||||
auto it = std::find(parent->children.begin(), parent->children.end(), this);
|
||||
return it != parent->children.end() ? std::distance(parent->children.begin(), it) : -1;
|
||||
}
|
||||
|
||||
Type type = Type::Root;
|
||||
Item *parent = nullptr;
|
||||
QList<Item *> children;
|
||||
std::vector<Item *> children;
|
||||
|
||||
const cabana::Signal *sig = nullptr;
|
||||
QString title;
|
||||
|
||||
@@ -65,8 +65,8 @@ public:
|
||||
virtual void start() = 0;
|
||||
virtual bool liveStreaming() const { return true; }
|
||||
virtual void seekTo(double ts) {}
|
||||
virtual QString routeName() const = 0;
|
||||
virtual QString carFingerprint() const { return ""; }
|
||||
virtual std::string routeName() const = 0;
|
||||
virtual std::string carFingerprint() const { return ""; }
|
||||
virtual QDateTime beginDateTime() const { return {}; }
|
||||
virtual uint64_t beginMonoTime() const { return 0; }
|
||||
virtual double minSeconds() const { return 0; }
|
||||
@@ -149,7 +149,7 @@ class DummyStream : public AbstractStream {
|
||||
Q_OBJECT
|
||||
public:
|
||||
DummyStream(QObject *parent) : AbstractStream(parent) {}
|
||||
QString routeName() const override { return tr("No Stream"); }
|
||||
std::string routeName() const override { return "No Stream"; }
|
||||
void start() override {}
|
||||
};
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ class DeviceStream : public LiveStream {
|
||||
public:
|
||||
DeviceStream(QObject *parent, QString address = {});
|
||||
~DeviceStream();
|
||||
inline QString routeName() const override {
|
||||
return QString("Live Streaming From %1").arg(zmq_address.isEmpty() ? "127.0.0.1" : zmq_address);
|
||||
inline std::string routeName() const override {
|
||||
return "Live Streaming From " + (zmq_address.isEmpty() ? std::string("127.0.0.1") : zmq_address.toStdString());
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@@ -16,8 +16,8 @@ PandaStream::PandaStream(QObject *parent, PandaStreamConfig config_) : config(co
|
||||
|
||||
bool PandaStream::connect() {
|
||||
try {
|
||||
qDebug() << "Connecting to panda " << config.serial;
|
||||
panda.reset(new Panda(config.serial.toStdString()));
|
||||
qDebug() << "Connecting to panda " << config.serial.c_str();
|
||||
panda.reset(new Panda(config.serial));
|
||||
config.bus_config.resize(3);
|
||||
qDebug() << "Connected";
|
||||
} catch (const std::exception& e) {
|
||||
@@ -81,7 +81,7 @@ void PandaStream::streamThread() {
|
||||
OpenPandaWidget::OpenPandaWidget(QWidget *parent) : AbstractOpenStreamWidget(parent) {
|
||||
form_layout = new QFormLayout(this);
|
||||
if (can && dynamic_cast<PandaStream *>(can) != nullptr) {
|
||||
form_layout->addWidget(new QLabel(tr("Already connected to %1.").arg(can->routeName())));
|
||||
form_layout->addWidget(new QLabel(tr("Already connected to %1.").arg(QString::fromStdString(can->routeName()))));
|
||||
form_layout->addWidget(new QLabel("Close the current connection via [File menu -> Close Stream] before connecting to another Panda."));
|
||||
QTimer::singleShot(0, [this]() { emit enableOpenButton(false); });
|
||||
return;
|
||||
@@ -129,7 +129,7 @@ void OpenPandaWidget::buildConfigForm() {
|
||||
}
|
||||
|
||||
if (has_panda) {
|
||||
config.serial = serial;
|
||||
config.serial = serial.toStdString();
|
||||
config.bus_config.resize(3);
|
||||
for (int i = 0; i < config.bus_config.size(); i++) {
|
||||
QHBoxLayout *bus_layout = new QHBoxLayout;
|
||||
|
||||
@@ -19,7 +19,7 @@ struct BusConfig {
|
||||
};
|
||||
|
||||
struct PandaStreamConfig {
|
||||
QString serial = "";
|
||||
std::string serial = "";
|
||||
std::vector<BusConfig> bus_config;
|
||||
};
|
||||
|
||||
@@ -28,8 +28,8 @@ class PandaStream : public LiveStream {
|
||||
public:
|
||||
PandaStream(QObject *parent, PandaStreamConfig config_ = {});
|
||||
~PandaStream() { stop(); }
|
||||
inline QString routeName() const override {
|
||||
return QString("Panda: %1").arg(config.serial);
|
||||
inline std::string routeName() const override {
|
||||
return "Panda: " + config.serial;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@@ -46,9 +46,9 @@ void ReplayStream::mergeSegments() {
|
||||
}
|
||||
}
|
||||
|
||||
bool ReplayStream::loadRoute(const QString &route, const QString &data_dir, uint32_t replay_flags, bool auto_source) {
|
||||
replay.reset(new Replay(route.toStdString(), {"can", "roadEncodeIdx", "driverEncodeIdx", "wideRoadEncodeIdx", "carParams"},
|
||||
{}, nullptr, replay_flags, data_dir.toStdString(), auto_source));
|
||||
bool ReplayStream::loadRoute(const std::string &route, const std::string &data_dir, uint32_t replay_flags, bool auto_source) {
|
||||
replay.reset(new Replay(route, {"can", "roadEncodeIdx", "driverEncodeIdx", "wideRoadEncodeIdx", "carParams"},
|
||||
{}, nullptr, replay_flags, data_dir, auto_source));
|
||||
replay->setSegmentCacheLimit(settings.max_cached_minutes);
|
||||
replay->installEventFilter([this](const Event *event) { return eventFilter(event); });
|
||||
|
||||
@@ -72,17 +72,17 @@ bool ReplayStream::loadRoute(const QString &route, const QString &data_dir, uint
|
||||
"This will grant access to routes from your comma account.";
|
||||
} else {
|
||||
message = tr("Access Denied. You do not have permission to access route:\n\n%1\n\n"
|
||||
"This is likely a private route.").arg(route);
|
||||
"This is likely a private route.").arg(QString::fromStdString(route));
|
||||
}
|
||||
QMessageBox::warning(nullptr, tr("Access Denied"), message);
|
||||
} else if (replay->lastRouteError() == RouteLoadError::NetworkError) {
|
||||
QMessageBox::warning(nullptr, tr("Network Error"),
|
||||
tr("Unable to load the route:\n\n %1.\n\nPlease check your network connection and try again.").arg(route));
|
||||
tr("Unable to load the route:\n\n %1.\n\nPlease check your network connection and try again.").arg(QString::fromStdString(route)));
|
||||
} else if (replay->lastRouteError() == RouteLoadError::FileNotFound) {
|
||||
QMessageBox::warning(nullptr, tr("Route Not Found"),
|
||||
tr("The specified route could not be found:\n\n %1.\n\nPlease check the route name and try again.").arg(route));
|
||||
tr("The specified route could not be found:\n\n %1.\n\nPlease check the route name and try again.").arg(QString::fromStdString(route)));
|
||||
} else {
|
||||
QMessageBox::warning(nullptr, tr("Route Load Failed"), tr("Failed to load route: '%1'").arg(route));
|
||||
QMessageBox::warning(nullptr, tr("Route Load Failed"), tr("Failed to load route: '%1'").arg(QString::fromStdString(route)));
|
||||
}
|
||||
}
|
||||
return success;
|
||||
@@ -168,7 +168,7 @@ AbstractStream *OpenReplayWidget::open() {
|
||||
if (cameras[2]->isChecked()) flags |= REPLAY_FLAG_ECAM;
|
||||
if (flags == REPLAY_FLAG_NONE && !cameras[0]->isChecked()) flags = REPLAY_FLAG_NO_VIPC;
|
||||
|
||||
if (replay_stream->loadRoute(route, data_dir, flags)) {
|
||||
if (replay_stream->loadRoute(route.toStdString(), data_dir.toStdString(), flags)) {
|
||||
return replay_stream.release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@ class ReplayStream : public AbstractStream {
|
||||
public:
|
||||
ReplayStream(QObject *parent);
|
||||
void start() override { replay->start(); }
|
||||
bool loadRoute(const QString &route, const QString &data_dir, uint32_t replay_flags = REPLAY_FLAG_NONE, bool auto_source = false);
|
||||
bool loadRoute(const std::string &route, const std::string &data_dir, uint32_t replay_flags = REPLAY_FLAG_NONE, bool auto_source = false);
|
||||
bool eventFilter(const Event *event);
|
||||
void seekTo(double ts) override { replay->seekTo(std::max(double(0), ts), false); }
|
||||
bool liveStreaming() const override { return false; }
|
||||
inline QString routeName() const override { return QString::fromStdString(replay->route().name()); }
|
||||
inline QString carFingerprint() const override { return replay->carFingerprint().c_str(); }
|
||||
inline std::string routeName() const override { return replay->route().name(); }
|
||||
inline std::string carFingerprint() const override { return replay->carFingerprint(); }
|
||||
double minSeconds() const override { return replay->minSeconds(); }
|
||||
double maxSeconds() const { return replay->maxSeconds(); }
|
||||
inline QDateTime beginDateTime() const { return QDateTime::fromSecsSinceEpoch(replay->routeDateTime()); }
|
||||
|
||||
@@ -12,7 +12,7 @@ SocketCanStream::SocketCanStream(QObject *parent, SocketCanStreamConfig config_)
|
||||
throw std::runtime_error("SocketCAN plugin not available");
|
||||
}
|
||||
|
||||
qDebug() << "Connecting to SocketCAN device" << config.device;
|
||||
qDebug() << "Connecting to SocketCAN device" << config.device.c_str();
|
||||
if (!connect()) {
|
||||
throw std::runtime_error("Failed to connect to SocketCAN device");
|
||||
}
|
||||
@@ -26,7 +26,7 @@ bool SocketCanStream::connect() {
|
||||
// Connecting might generate some warnings about missing socketcan/libsocketcan libraries
|
||||
// These are expected and can be ignored, we don't need the advanced features of libsocketcan
|
||||
QString errorString;
|
||||
device.reset(QCanBus::instance()->createDevice("socketcan", config.device, &errorString));
|
||||
device.reset(QCanBus::instance()->createDevice("socketcan", QString::fromStdString(config.device), &errorString));
|
||||
device->setConfigurationParameter(QCanBusDevice::CanFdKey, true);
|
||||
|
||||
if (!device) {
|
||||
@@ -87,7 +87,7 @@ OpenSocketCanWidget::OpenSocketCanWidget(QWidget *parent) : AbstractOpenStreamWi
|
||||
main_layout->addStretch(1);
|
||||
|
||||
QObject::connect(refresh, &QPushButton::clicked, this, &OpenSocketCanWidget::refreshDevices);
|
||||
QObject::connect(device_edit, &QComboBox::currentTextChanged, this, [=]{ config.device = device_edit->currentText(); });
|
||||
QObject::connect(device_edit, &QComboBox::currentTextChanged, this, [=]{ config.device = device_edit->currentText().toStdString(); });
|
||||
|
||||
// Populate devices
|
||||
refreshDevices();
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "tools/cabana/streams/livestream.h"
|
||||
|
||||
struct SocketCanStreamConfig {
|
||||
QString device = ""; // TODO: support multiple devices/buses at once
|
||||
std::string device = ""; // TODO: support multiple devices/buses at once
|
||||
};
|
||||
|
||||
class SocketCanStream : public LiveStream {
|
||||
@@ -20,8 +20,8 @@ public:
|
||||
~SocketCanStream() { stop(); }
|
||||
static bool available();
|
||||
|
||||
inline QString routeName() const override {
|
||||
return QString("Live Streaming From Socket CAN %1").arg(config.device);
|
||||
inline std::string routeName() const override {
|
||||
return "Live Streaming From Socket CAN " + config.device;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
const std::string TEST_RLOG_URL = "https://commadataci.blob.core.windows.net/openpilotci/0c94aa1e1296d7c6/2021-05-05--19-48-37/0/rlog.bz2";
|
||||
|
||||
TEST_CASE("DBCFile::generateDBC") {
|
||||
QString fn = QString("%1/%2.dbc").arg(OPENDBC_FILE_PATH, "tesla_can");
|
||||
std::string fn = std::string(OPENDBC_FILE_PATH) + "/tesla_can.dbc";
|
||||
DBCFile dbc_origin(fn);
|
||||
DBCFile dbc_from_generated("", dbc_origin.generateDBC());
|
||||
|
||||
@@ -30,7 +30,7 @@ TEST_CASE("DBCFile::generateDBC") {
|
||||
|
||||
TEST_CASE("DBCFile::generateDBC - comment order") {
|
||||
// Ensure that message comments are followed by signal comments and in the correct order
|
||||
auto content = R"(BO_ 160 message_1: 8 EON
|
||||
std::string content = R"(BO_ 160 message_1: 8 EON
|
||||
SG_ signal_1 : 0|12@1+ (1,0) [0|4095] "unit" XXX
|
||||
|
||||
BO_ 162 message_2: 8 EON
|
||||
@@ -46,7 +46,7 @@ CM_ SG_ 162 signal_2 "signal comment";
|
||||
}
|
||||
|
||||
TEST_CASE("DBCFile::generateDBC -- preserve original header") {
|
||||
QString content = R"(VERSION "1.0"
|
||||
std::string content = R"(VERSION "1.0"
|
||||
|
||||
NS_ :
|
||||
CM_
|
||||
@@ -66,7 +66,7 @@ CM_ SG_ 160 signal_1 "signal comment";
|
||||
}
|
||||
|
||||
TEST_CASE("DBCFile::generateDBC - escaped quotes") {
|
||||
QString content = R"(BO_ 160 message_1: 8 EON
|
||||
std::string content = R"(BO_ 160 message_1: 8 EON
|
||||
SG_ signal_1 : 0|12@1+ (1,0) [0|4095] "unit" XXX
|
||||
|
||||
CM_ BO_ 160 "message comment with \"escaped quotes\"";
|
||||
@@ -77,7 +77,7 @@ CM_ SG_ 160 signal_1 "signal comment with \"escaped quotes\"";
|
||||
}
|
||||
|
||||
TEST_CASE("parse_dbc") {
|
||||
QString content = R"(
|
||||
std::string content = R"(
|
||||
BO_ 160 message_1: 8 EON
|
||||
SG_ signal_1 : 0|12@1+ (1,0) [0|4095] "unit" XXX
|
||||
SG_ signal_2 : 12|1@1+ (1.0,0.0) [0.0|1] "" XXX
|
||||
@@ -119,9 +119,9 @@ CM_ SG_ 162 signal_1 "signal comment with \"escaped quotes\"";
|
||||
REQUIRE(sig_1->comment == "signal comment");
|
||||
REQUIRE(sig_1->receiver_name == "XXX");
|
||||
REQUIRE(sig_1->val_desc.size() == 3);
|
||||
REQUIRE(sig_1->val_desc[0] == std::pair<double, QString>{0, "disabled"});
|
||||
REQUIRE(sig_1->val_desc[1] == std::pair<double, QString>{1.2, "initializing"});
|
||||
REQUIRE(sig_1->val_desc[2] == std::pair<double, QString>{2, "fault"});
|
||||
REQUIRE(sig_1->val_desc[0] == std::pair<double, std::string>{0, "disabled"});
|
||||
REQUIRE(sig_1->val_desc[1] == std::pair<double, std::string>{1.2, "initializing"});
|
||||
REQUIRE(sig_1->val_desc[2] == std::pair<double, std::string>{2, "fault"});
|
||||
|
||||
auto &sig_2 = msg->sigs[1];
|
||||
REQUIRE(sig_2->comment == "multiple line comment \n1\n2");
|
||||
@@ -147,7 +147,7 @@ TEST_CASE("parse_opendbc") {
|
||||
QStringList errors;
|
||||
for (auto fn : dir.entryList({"*.dbc"}, QDir::Files, QDir::Name)) {
|
||||
try {
|
||||
auto dbc = DBCFile(dir.filePath(fn));
|
||||
auto dbc = DBCFile(dir.filePath(fn).toStdString());
|
||||
} catch (std::exception &e) {
|
||||
errors.push_back(e.what());
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ QVariant FindSignalModel::data(const QModelIndex &index, int role) const {
|
||||
if (role == Qt::DisplayRole) {
|
||||
const auto &s = filtered_signals[index.row()];
|
||||
switch (index.column()) {
|
||||
case 0: return s.id.toString();
|
||||
case 0: return QString::fromStdString(s.id.toString());
|
||||
case 1: return QString("%1, %2").arg(s.sig.start_bit).arg(s.sig.size);
|
||||
case 2: return s.values.join(" ");
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::Wi
|
||||
msg_cb = new QComboBox(this);
|
||||
// TODO: update when src_bus_combo changes
|
||||
for (auto &[address, msg] : dbc()->getMessages(-1)) {
|
||||
msg_cb->addItem(msg.name, address);
|
||||
msg_cb->addItem(QString::fromStdString(msg.name), address);
|
||||
}
|
||||
msg_cb->model()->sort(0);
|
||||
msg_cb->setCurrentIndex(0);
|
||||
|
||||
@@ -26,7 +26,7 @@ void exportSignalsToCSV(const QString &file_name, const MessageId &msg_id) {
|
||||
QTextStream stream(&file);
|
||||
stream << "time,addr,bus";
|
||||
for (auto s : msg->sigs)
|
||||
stream << "," << s->name;
|
||||
stream << "," << s->name.c_str();
|
||||
stream << "\n";
|
||||
|
||||
for (auto e : can->events(msg_id)) {
|
||||
|
||||
@@ -278,7 +278,7 @@ QString signalToolTip(const cabana::Signal *sig) {
|
||||
Start Bit: %2 Size: %3<br />
|
||||
MSB: %4 LSB: %5<br />
|
||||
Little Endian: %6 Signed: %7</span>
|
||||
)").arg(sig->name).arg(sig->start_bit).arg(sig->size).arg(sig->msb).arg(sig->lsb)
|
||||
)").arg(QString::fromStdString(sig->name)).arg(sig->start_bit).arg(sig->size).arg(sig->msb).arg(sig->lsb)
|
||||
.arg(sig->is_little_endian ? "Y" : "N").arg(sig->is_signed ? "Y" : "N");
|
||||
}
|
||||
|
||||
|
||||
@@ -384,9 +384,9 @@ QPixmap StreamCameraView::generateThumbnail(QPixmap thumb, double seconds) {
|
||||
|
||||
void StreamCameraView::drawScrubThumbnail(QPainter &p) {
|
||||
p.fillRect(rect(), Qt::black);
|
||||
auto it = big_thumbnails.lowerBound(can->toMonoTime(thumbnail_dispaly_time));
|
||||
auto it = big_thumbnails.lower_bound(can->toMonoTime(thumbnail_dispaly_time));
|
||||
if (it != big_thumbnails.end()) {
|
||||
QPixmap scaled_thumb = it.value().scaled(rect().size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
QPixmap scaled_thumb = it->second.scaled(rect().size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
QRect thumb_rect(rect().center() - scaled_thumb.rect().center(), scaled_thumb.size());
|
||||
p.drawPixmap(thumb_rect.topLeft(), scaled_thumb);
|
||||
drawTime(p, thumb_rect, thumbnail_dispaly_time);
|
||||
@@ -394,9 +394,9 @@ void StreamCameraView::drawScrubThumbnail(QPainter &p) {
|
||||
}
|
||||
|
||||
void StreamCameraView::drawThumbnail(QPainter &p) {
|
||||
auto it = thumbnails.lowerBound(can->toMonoTime(thumbnail_dispaly_time));
|
||||
auto it = thumbnails.lower_bound(can->toMonoTime(thumbnail_dispaly_time));
|
||||
if (it != thumbnails.end()) {
|
||||
const QPixmap &thumb = it.value();
|
||||
const QPixmap &thumb = it->second;
|
||||
auto [min_sec, max_sec] = can->timeRange().value_or(std::make_pair(can->minSeconds(), can->maxSeconds()));
|
||||
int pos = (thumbnail_dispaly_time - min_sec) * width() / (max_sec - min_sec);
|
||||
int x = std::clamp(pos - thumb.width() / 2, THUMBNAIL_MARGIN, width() - thumb.width() - THUMBNAIL_MARGIN + 1);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
@@ -47,8 +48,8 @@ private:
|
||||
void drawTime(QPainter &p, const QRect &rect, double seconds);
|
||||
|
||||
QPropertyAnimation *fade_animation;
|
||||
QMap<uint64_t, QPixmap> big_thumbnails;
|
||||
QMap<uint64_t, QPixmap> thumbnails;
|
||||
std::map<uint64_t, QPixmap> big_thumbnails;
|
||||
std::map<uint64_t, QPixmap> thumbnails;
|
||||
double thumbnail_dispaly_time = -1;
|
||||
friend class VideoWidget;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user