mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-06-27 17:42:04 +08:00
cabana: refactor message id from QString to struct (#27352)
* cabana: refactor message id from QString to struct * fix tabbar * fix findsimilarbits * optimize hash function * cleanup sorting * use in updateLastMsgsTo old-commit-hash: 5078c918056c189a3ec84bc63231fbae75c57eda
This commit is contained in:
@@ -94,7 +94,7 @@ void BinaryView::addShortcuts() {
|
||||
QObject::connect(shortcut_plot_c, &QShortcut::activated, shortcut_plot, &QShortcut::activated);
|
||||
QObject::connect(shortcut_plot, &QShortcut::activated, [=]{
|
||||
if (hovered_sig != nullptr) {
|
||||
emit showChart(model->msg_id, hovered_sig, true, false);
|
||||
emit showChart(*model->msg_id, hovered_sig, true, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -189,14 +189,14 @@ void BinaryView::leaveEvent(QEvent *event) {
|
||||
QTableView::leaveEvent(event);
|
||||
}
|
||||
|
||||
void BinaryView::setMessage(const QString &message_id) {
|
||||
void BinaryView::setMessage(const MessageId &message_id) {
|
||||
model->msg_id = message_id;
|
||||
verticalScrollBar()->setValue(0);
|
||||
refresh();
|
||||
}
|
||||
|
||||
void BinaryView::refresh() {
|
||||
if (model->msg_id.isEmpty()) return;
|
||||
if (!model->msg_id) return;
|
||||
|
||||
clearSelection();
|
||||
anchor_index = QModelIndex();
|
||||
@@ -231,7 +231,7 @@ std::tuple<int, int, bool> BinaryView::getSelection(QModelIndex index) {
|
||||
void BinaryViewModel::refresh() {
|
||||
beginResetModel();
|
||||
items.clear();
|
||||
if ((dbc_msg = dbc()->msg(msg_id))) {
|
||||
if ((dbc_msg = dbc()->msg(*msg_id))) {
|
||||
row_count = dbc_msg->size;
|
||||
items.resize(row_count * column_count);
|
||||
for (auto sig : dbc_msg->getSignals()) {
|
||||
@@ -250,7 +250,7 @@ void BinaryViewModel::refresh() {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
row_count = can->lastMessage(msg_id).dat.size();
|
||||
row_count = can->lastMessage(*msg_id).dat.size();
|
||||
items.resize(row_count * column_count);
|
||||
}
|
||||
endResetModel();
|
||||
@@ -259,7 +259,7 @@ void BinaryViewModel::refresh() {
|
||||
|
||||
void BinaryViewModel::updateState() {
|
||||
auto prev_items = items;
|
||||
const auto &last_msg = can->lastMessage(msg_id);
|
||||
const auto &last_msg = can->lastMessage(*msg_id);
|
||||
const auto &binary = last_msg.dat;
|
||||
|
||||
// data size may changed.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QList>
|
||||
#include <QSet>
|
||||
@@ -46,7 +48,7 @@ public:
|
||||
};
|
||||
std::vector<Item> items;
|
||||
|
||||
QString msg_id;
|
||||
std::optional<MessageId> msg_id;
|
||||
const DBCMsg *dbc_msg = nullptr;
|
||||
int row_count = 0;
|
||||
const int column_count = 9;
|
||||
@@ -57,7 +59,7 @@ class BinaryView : public QTableView {
|
||||
|
||||
public:
|
||||
BinaryView(QWidget *parent = nullptr);
|
||||
void setMessage(const QString &message_id);
|
||||
void setMessage(const MessageId &message_id);
|
||||
void highlight(const Signal *sig);
|
||||
QSet<const Signal*> getOverlappingSignals() const;
|
||||
inline void updateState() { model->updateState(); }
|
||||
@@ -70,7 +72,7 @@ signals:
|
||||
void resizeSignal(const Signal *sig, int from, int size);
|
||||
void removeSignal(const Signal *sig);
|
||||
void editSignal(const Signal *origin_s, Signal &s);
|
||||
void showChart(const QString &name, const Signal *sig, bool show, bool merge);
|
||||
void showChart(const MessageId &id, const Signal *sig, bool show, bool merge);
|
||||
|
||||
private:
|
||||
void addShortcuts();
|
||||
|
||||
@@ -181,7 +181,7 @@ void ChartsWidget::settingChanged() {
|
||||
}
|
||||
}
|
||||
|
||||
ChartView *ChartsWidget::findChart(const QString &id, const Signal *sig) {
|
||||
ChartView *ChartsWidget::findChart(const MessageId &id, const Signal *sig) {
|
||||
for (auto c : charts)
|
||||
if (c->hasSeries(id, sig)) return c;
|
||||
return nullptr;
|
||||
@@ -204,7 +204,7 @@ ChartView *ChartsWidget::createChart() {
|
||||
return chart;
|
||||
}
|
||||
|
||||
void ChartsWidget::showChart(const QString &id, const Signal *sig, bool show, bool merge) {
|
||||
void ChartsWidget::showChart(const MessageId &id, const Signal *sig, bool show, bool merge) {
|
||||
setUpdatesEnabled(false);
|
||||
ChartView *chart = findChart(id, sig);
|
||||
if (show && !chart) {
|
||||
@@ -363,19 +363,18 @@ ChartView::ChartView(QWidget *parent) : QChartView(nullptr, parent) {
|
||||
QObject::connect(remove_btn, &QToolButton::clicked, this, &ChartView::remove);
|
||||
}
|
||||
|
||||
void ChartView::addSeries(const QString &msg_id, const Signal *sig) {
|
||||
void ChartView::addSeries(const MessageId &msg_id, const Signal *sig) {
|
||||
if (hasSeries(msg_id, sig)) return;
|
||||
|
||||
QXYSeries *series = createSeries(series_type, getColor(sig));
|
||||
auto [source, address] = DBCManager::parseId(msg_id);
|
||||
sigs.push_back({.msg_id = msg_id, .address = address, .source = source, .sig = sig, .series = series});
|
||||
sigs.push_back({.msg_id = msg_id, .sig = sig, .series = series});
|
||||
updateTitle();
|
||||
updateSeries(sig);
|
||||
updateSeriesPoints();
|
||||
emit seriesAdded(msg_id, sig);
|
||||
}
|
||||
|
||||
bool ChartView::hasSeries(const QString &msg_id, const Signal *sig) const {
|
||||
bool ChartView::hasSeries(const MessageId &msg_id, const Signal *sig) const {
|
||||
return std::any_of(sigs.begin(), sigs.end(), [&](auto &s) { return s.msg_id == msg_id && s.sig == sig; });
|
||||
}
|
||||
|
||||
@@ -409,7 +408,7 @@ void ChartView::signalUpdated(const Signal *sig) {
|
||||
}
|
||||
|
||||
void ChartView::msgUpdated(uint32_t address) {
|
||||
if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.address == address; }))
|
||||
if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.msg_id.address == address; }))
|
||||
updateTitle();
|
||||
}
|
||||
|
||||
@@ -455,7 +454,7 @@ void ChartView::updateTitle() {
|
||||
}
|
||||
for (auto &s : sigs) {
|
||||
auto decoration = s.series->isVisible() ? "none" : "line-through";
|
||||
s.series->setName(QString("<span style=\"text-decoration:%1\"><b>%2</b> <font color=\"gray\">%3 %4</font></span>").arg(decoration, s.sig->name.c_str(), msgName(s.msg_id), s.msg_id));
|
||||
s.series->setName(QString("<span style=\"text-decoration:%1\"><b>%2</b> <font color=\"gray\">%3 %4</font></span>").arg(decoration, s.sig->name.c_str(), msgName(s.msg_id), s.msg_id.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,7 +516,7 @@ void ChartView::updateSeries(const Signal *sig, const std::vector<Event *> *even
|
||||
for (auto it = chunk.first; it != chunk.second; ++it) {
|
||||
if ((*it)->which == cereal::Event::Which::CAN) {
|
||||
for (const auto &c : (*it)->event.getCan()) {
|
||||
if (s.address == c.getAddress() && s.source == c.getSrc()) {
|
||||
if (s.msg_id.address == c.getAddress() && s.msg_id.source == c.getSrc()) {
|
||||
auto dat = c.getDat();
|
||||
double value = get_raw_value((uint8_t *)dat.begin(), dat.size(), *s.sig);
|
||||
double ts = ((*it)->mono_time / (double)1e9) - route_start_time; // seconds
|
||||
@@ -847,7 +846,7 @@ SeriesSelector::SeriesSelector(QString title, QWidget *parent) : QDialog(parent)
|
||||
|
||||
for (auto it = can->can_msgs.cbegin(); it != can->can_msgs.cend(); ++it) {
|
||||
if (auto m = dbc()->msg(it.key())) {
|
||||
msgs_combo->addItem(QString("%1 (%2)").arg(m->name).arg(it.key()), it.key());
|
||||
msgs_combo->addItem(QString("%1 (%2)").arg(m->name).arg(it.key().toString()), QVariant::fromValue(it.key()));
|
||||
}
|
||||
}
|
||||
msgs_combo->model()->sort(0);
|
||||
@@ -872,7 +871,7 @@ void SeriesSelector::add(QListWidgetItem *item) {
|
||||
|
||||
void SeriesSelector::remove(QListWidgetItem *item) {
|
||||
auto it = (ListItem *)item;
|
||||
if (it->msg_id == msgs_combo->currentData().toString()) {
|
||||
if (it->msg_id == msgs_combo->currentData().value<MessageId>()) {
|
||||
addItemToList(available_list, it->msg_id, it->sig);
|
||||
}
|
||||
delete item;
|
||||
@@ -881,7 +880,7 @@ void SeriesSelector::remove(QListWidgetItem *item) {
|
||||
void SeriesSelector::updateAvailableList(int index) {
|
||||
if (index == -1) return;
|
||||
available_list->clear();
|
||||
QString msg_id = msgs_combo->itemData(index).toString();
|
||||
MessageId msg_id = msgs_combo->itemData(index).value<MessageId>();
|
||||
auto selected_items = seletedItems();
|
||||
for (auto &[name, s] : dbc()->msg(msg_id)->sigs) {
|
||||
bool is_selected = std::any_of(selected_items.begin(), selected_items.end(), [=, sig=&s](auto it) { return it->msg_id == msg_id && it->sig == sig; });
|
||||
@@ -891,9 +890,9 @@ void SeriesSelector::updateAvailableList(int index) {
|
||||
}
|
||||
}
|
||||
|
||||
void SeriesSelector::addItemToList(QListWidget *parent, const QString id, const Signal *sig, bool show_msg_name) {
|
||||
void SeriesSelector::addItemToList(QListWidget *parent, const MessageId id, const Signal *sig, bool show_msg_name) {
|
||||
QString text = QString("<span style=\"color:%0;\">■ </span> %1").arg(getColor(sig).name(), sig->name.c_str());
|
||||
if (show_msg_name) text += QString(" <font color=\"gray\">%0 %1</font>").arg(msgName(id), id);
|
||||
if (show_msg_name) text += QString(" <font color=\"gray\">%0 %1</font>").arg(msgName(id), id.toString());
|
||||
|
||||
QLabel *label = new QLabel(text);
|
||||
label->setContentsMargins(5, 0, 5, 0);
|
||||
|
||||
+13
-15
@@ -25,17 +25,15 @@ class ChartView : public QChartView {
|
||||
|
||||
public:
|
||||
ChartView(QWidget *parent = nullptr);
|
||||
void addSeries(const QString &msg_id, const Signal *sig);
|
||||
bool hasSeries(const QString &msg_id, const Signal *sig) const;
|
||||
void addSeries(const MessageId &msg_id, const Signal *sig);
|
||||
bool hasSeries(const MessageId &msg_id, const Signal *sig) const;
|
||||
void updateSeries(const Signal *sig = nullptr, const std::vector<Event*> *events = nullptr, bool clear = true);
|
||||
void updatePlot(double cur, double min, double max);
|
||||
void setSeriesType(QAbstractSeries::SeriesType type);
|
||||
void updatePlotArea(int left);
|
||||
|
||||
struct SigItem {
|
||||
QString msg_id;
|
||||
uint8_t source = 0;
|
||||
uint32_t address = 0;
|
||||
MessageId msg_id;
|
||||
const Signal *sig = nullptr;
|
||||
QXYSeries *series = nullptr;
|
||||
QVector<QPointF> vals;
|
||||
@@ -43,8 +41,8 @@ public:
|
||||
};
|
||||
|
||||
signals:
|
||||
void seriesRemoved(const QString &id, const Signal *sig);
|
||||
void seriesAdded(const QString &id, const Signal *sig);
|
||||
void seriesRemoved(const MessageId &id, const Signal *sig);
|
||||
void seriesAdded(const MessageId &id, const Signal *sig);
|
||||
void zoomIn(double min, double max);
|
||||
void zoomReset();
|
||||
void remove();
|
||||
@@ -55,7 +53,7 @@ private slots:
|
||||
void signalUpdated(const Signal *sig);
|
||||
void manageSeries();
|
||||
void handleMarkerClicked();
|
||||
void msgRemoved(uint32_t address) { removeIf([=](auto &s) { return s.address == address; }); }
|
||||
void msgRemoved(uint32_t address) { removeIf([=](auto &s) { return s.msg_id.address == address; }); }
|
||||
void signalRemoved(const Signal *sig) { removeIf([=](auto &s) { return s.sig == sig; }); }
|
||||
|
||||
private:
|
||||
@@ -99,8 +97,8 @@ class ChartsWidget : public QWidget {
|
||||
|
||||
public:
|
||||
ChartsWidget(QWidget *parent = nullptr);
|
||||
void showChart(const QString &id, const Signal *sig, bool show, bool merge);
|
||||
inline bool hasSignal(const QString &id, const Signal *sig) { return findChart(id, sig) != nullptr; }
|
||||
void showChart(const MessageId &id, const Signal *sig, bool show, bool merge);
|
||||
inline bool hasSignal(const MessageId &id, const Signal *sig) { return findChart(id, sig) != nullptr; }
|
||||
|
||||
public slots:
|
||||
void setColumnCount(int n);
|
||||
@@ -126,7 +124,7 @@ private:
|
||||
void updateLayout();
|
||||
void settingChanged();
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
ChartView *findChart(const QString &id, const Signal *sig);
|
||||
ChartView *findChart(const MessageId &id, const Signal *sig);
|
||||
|
||||
QLabel *title_label;
|
||||
QLabel *range_lb;
|
||||
@@ -152,18 +150,18 @@ private:
|
||||
class SeriesSelector : public QDialog {
|
||||
public:
|
||||
struct ListItem : public QListWidgetItem {
|
||||
ListItem(const QString &msg_id, const Signal *sig, QListWidget *parent) : msg_id(msg_id), sig(sig), QListWidgetItem(parent) {}
|
||||
QString msg_id;
|
||||
ListItem(const MessageId &msg_id, const Signal *sig, QListWidget *parent) : msg_id(msg_id), sig(sig), QListWidgetItem(parent) {}
|
||||
MessageId msg_id;
|
||||
const Signal *sig;
|
||||
};
|
||||
|
||||
SeriesSelector(QString title, QWidget *parent);
|
||||
QList<ListItem *> seletedItems();
|
||||
inline void addSelected(const QString &id, const Signal *sig) { addItemToList(selected_list, id, sig, true); }
|
||||
inline void addSelected(const MessageId &id, const Signal *sig) { addItemToList(selected_list, id, sig, true); }
|
||||
|
||||
private:
|
||||
void updateAvailableList(int index);
|
||||
void addItemToList(QListWidget *parent, const QString id, const Signal *sig, bool show_msg_name = false);
|
||||
void addItemToList(QListWidget *parent, const MessageId id, const Signal *sig, bool show_msg_name = false);
|
||||
void add(QListWidgetItem *item);
|
||||
void remove(QListWidgetItem *item);
|
||||
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
|
||||
// EditMsgCommand
|
||||
|
||||
EditMsgCommand::EditMsgCommand(const QString &id, const QString &title, int size, QUndoCommand *parent)
|
||||
EditMsgCommand::EditMsgCommand(const MessageId &id, const QString &title, int size, QUndoCommand *parent)
|
||||
: id(id), new_title(title), new_size(size), QUndoCommand(parent) {
|
||||
if (auto msg = dbc()->msg(id)) {
|
||||
old_title = msg->name;
|
||||
old_size = msg->size;
|
||||
}
|
||||
setText(QObject::tr("Edit message %1:%2").arg(DBCManager::parseId(id).second).arg(title));
|
||||
setText(QObject::tr("Edit message %1:%2").arg(id.address).arg(title));
|
||||
}
|
||||
|
||||
void EditMsgCommand::undo() {
|
||||
@@ -26,10 +26,10 @@ void EditMsgCommand::redo() {
|
||||
|
||||
// RemoveMsgCommand
|
||||
|
||||
RemoveMsgCommand::RemoveMsgCommand(const QString &id, QUndoCommand *parent) : id(id), QUndoCommand(parent) {
|
||||
RemoveMsgCommand::RemoveMsgCommand(const MessageId &id, QUndoCommand *parent) : id(id), QUndoCommand(parent) {
|
||||
if (auto msg = dbc()->msg(id)) {
|
||||
message = *msg;
|
||||
setText(QObject::tr("Remove message %1:%2").arg(DBCManager::parseId(id).second).arg(message.name));
|
||||
setText(QObject::tr("Remove message %1:%2").arg(id.address).arg(message.name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,9 +48,9 @@ void RemoveMsgCommand::redo() {
|
||||
|
||||
// AddSigCommand
|
||||
|
||||
AddSigCommand::AddSigCommand(const QString &id, const Signal &sig, QUndoCommand *parent)
|
||||
AddSigCommand::AddSigCommand(const MessageId &id, const Signal &sig, QUndoCommand *parent)
|
||||
: id(id), signal(sig), QUndoCommand(parent) {
|
||||
setText(QObject::tr("Add signal %1 to %2").arg(sig.name.c_str()).arg(DBCManager::parseId(id).second));
|
||||
setText(QObject::tr("Add signal %1 to %2").arg(sig.name.c_str()).arg(id.address));
|
||||
}
|
||||
|
||||
void AddSigCommand::undo() { dbc()->removeSignal(id, signal.name.c_str()); }
|
||||
@@ -58,9 +58,9 @@ void AddSigCommand::redo() { dbc()->addSignal(id, signal); }
|
||||
|
||||
// RemoveSigCommand
|
||||
|
||||
RemoveSigCommand::RemoveSigCommand(const QString &id, const Signal *sig, QUndoCommand *parent)
|
||||
RemoveSigCommand::RemoveSigCommand(const MessageId &id, const Signal *sig, QUndoCommand *parent)
|
||||
: id(id), signal(*sig), QUndoCommand(parent) {
|
||||
setText(QObject::tr("Remove signal %1 from %2").arg(signal.name.c_str()).arg(DBCManager::parseId(id).second));
|
||||
setText(QObject::tr("Remove signal %1 from %2").arg(signal.name.c_str()).arg(id.address));
|
||||
}
|
||||
|
||||
void RemoveSigCommand::undo() { dbc()->addSignal(id, signal); }
|
||||
@@ -68,7 +68,7 @@ void RemoveSigCommand::redo() { dbc()->removeSignal(id, signal.name.c_str()); }
|
||||
|
||||
// EditSignalCommand
|
||||
|
||||
EditSignalCommand::EditSignalCommand(const QString &id, const Signal *sig, const Signal &new_sig, QUndoCommand *parent)
|
||||
EditSignalCommand::EditSignalCommand(const MessageId &id, const Signal *sig, const Signal &new_sig, QUndoCommand *parent)
|
||||
: id(id), old_signal(*sig), new_signal(new_sig), QUndoCommand(parent) {
|
||||
setText(QObject::tr("Edit signal %1").arg(old_signal.name.c_str()));
|
||||
}
|
||||
|
||||
+10
-10
@@ -7,57 +7,57 @@
|
||||
|
||||
class EditMsgCommand : public QUndoCommand {
|
||||
public:
|
||||
EditMsgCommand(const QString &id, const QString &title, int size, QUndoCommand *parent = nullptr);
|
||||
EditMsgCommand(const MessageId &id, const QString &title, int size, QUndoCommand *parent = nullptr);
|
||||
void undo() override;
|
||||
void redo() override;
|
||||
|
||||
private:
|
||||
const QString id;
|
||||
const MessageId id;
|
||||
QString old_title, new_title;
|
||||
int old_size = 0, new_size = 0;
|
||||
};
|
||||
|
||||
class RemoveMsgCommand : public QUndoCommand {
|
||||
public:
|
||||
RemoveMsgCommand(const QString &id, QUndoCommand *parent = nullptr);
|
||||
RemoveMsgCommand(const MessageId &id, QUndoCommand *parent = nullptr);
|
||||
void undo() override;
|
||||
void redo() override;
|
||||
|
||||
private:
|
||||
const QString id;
|
||||
const MessageId id;
|
||||
DBCMsg message;
|
||||
};
|
||||
|
||||
class AddSigCommand : public QUndoCommand {
|
||||
public:
|
||||
AddSigCommand(const QString &id, const Signal &sig, QUndoCommand *parent = nullptr);
|
||||
AddSigCommand(const MessageId &id, const Signal &sig, QUndoCommand *parent = nullptr);
|
||||
void undo() override;
|
||||
void redo() override;
|
||||
|
||||
private:
|
||||
const QString id;
|
||||
const MessageId id;
|
||||
Signal signal = {};
|
||||
};
|
||||
|
||||
class RemoveSigCommand : public QUndoCommand {
|
||||
public:
|
||||
RemoveSigCommand(const QString &id, const Signal *sig, QUndoCommand *parent = nullptr);
|
||||
RemoveSigCommand(const MessageId &id, const Signal *sig, QUndoCommand *parent = nullptr);
|
||||
void undo() override;
|
||||
void redo() override;
|
||||
|
||||
private:
|
||||
const QString id;
|
||||
const MessageId id;
|
||||
Signal signal = {};
|
||||
};
|
||||
|
||||
class EditSignalCommand : public QUndoCommand {
|
||||
public:
|
||||
EditSignalCommand(const QString &id, const Signal *sig, const Signal &new_sig, QUndoCommand *parent = nullptr);
|
||||
EditSignalCommand(const MessageId &id, const Signal *sig, const Signal &new_sig, QUndoCommand *parent = nullptr);
|
||||
void undo() override;
|
||||
void redo() override;
|
||||
|
||||
private:
|
||||
const QString id;
|
||||
const MessageId id;
|
||||
Signal old_signal = {};
|
||||
Signal new_signal = {};
|
||||
};
|
||||
|
||||
+15
-19
@@ -4,6 +4,10 @@
|
||||
#include <sstream>
|
||||
#include <QVector>
|
||||
|
||||
uint qHash(const MessageId &item) {
|
||||
return qHash(item.source) ^ qHash(item.address);
|
||||
}
|
||||
|
||||
DBCManager::DBCManager(QObject *parent) : QObject(parent) {}
|
||||
|
||||
DBCManager::~DBCManager() {}
|
||||
@@ -56,29 +60,27 @@ QString DBCManager::generateDBC() {
|
||||
return dbc_string;
|
||||
}
|
||||
|
||||
void DBCManager::updateMsg(const QString &id, const QString &name, uint32_t size) {
|
||||
auto [_, address] = parseId(id);
|
||||
auto &m = msgs[address];
|
||||
void DBCManager::updateMsg(const MessageId &id, const QString &name, uint32_t size) {
|
||||
auto &m = msgs[id.address];
|
||||
m.name = name;
|
||||
m.size = size;
|
||||
emit msgUpdated(address);
|
||||
emit msgUpdated(id.address);
|
||||
}
|
||||
|
||||
void DBCManager::removeMsg(const QString &id) {
|
||||
uint32_t address = parseId(id).second;
|
||||
msgs.erase(address);
|
||||
emit msgRemoved(address);
|
||||
void DBCManager::removeMsg(const MessageId &id) {
|
||||
msgs.erase(id.address);
|
||||
emit msgRemoved(id.address);
|
||||
}
|
||||
|
||||
void DBCManager::addSignal(const QString &id, const Signal &sig) {
|
||||
if (auto m = const_cast<DBCMsg *>(msg(id))) {
|
||||
void DBCManager::addSignal(const MessageId &id, const Signal &sig) {
|
||||
if (auto m = const_cast<DBCMsg *>(msg(id.address))) {
|
||||
auto &s = m->sigs[sig.name.c_str()];
|
||||
s = sig;
|
||||
emit signalAdded(parseId(id).second, &s);
|
||||
emit signalAdded(id.address, &s);
|
||||
}
|
||||
}
|
||||
|
||||
void DBCManager::updateSignal(const QString &id, const QString &sig_name, const Signal &sig) {
|
||||
void DBCManager::updateSignal(const MessageId &id, const QString &sig_name, const Signal &sig) {
|
||||
if (auto m = const_cast<DBCMsg *>(msg(id))) {
|
||||
// change key name
|
||||
QString new_name = QString::fromStdString(sig.name);
|
||||
@@ -91,7 +93,7 @@ void DBCManager::updateSignal(const QString &id, const QString &sig_name, const
|
||||
}
|
||||
}
|
||||
|
||||
void DBCManager::removeSignal(const QString &id, const QString &sig_name) {
|
||||
void DBCManager::removeSignal(const MessageId &id, const QString &sig_name) {
|
||||
if (auto m = const_cast<DBCMsg *>(msg(id))) {
|
||||
auto it = m->sigs.find(sig_name);
|
||||
if (it != m->sigs.end()) {
|
||||
@@ -101,12 +103,6 @@ void DBCManager::removeSignal(const QString &id, const QString &sig_name) {
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<uint8_t, uint32_t> DBCManager::parseId(const QString &id) {
|
||||
const auto list = id.split(':');
|
||||
if (list.size() != 2) return {0, 0};
|
||||
return {list[0].toInt(), list[1].toUInt(nullptr, 16)};
|
||||
}
|
||||
|
||||
DBCManager *dbc() {
|
||||
static DBCManager dbc_manager(nullptr);
|
||||
return &dbc_manager;
|
||||
|
||||
@@ -5,6 +5,35 @@
|
||||
#include <QString>
|
||||
#include "opendbc/can/common_dbc.h"
|
||||
|
||||
struct MessageId {
|
||||
uint8_t source;
|
||||
uint32_t address;
|
||||
|
||||
QString toString() const {
|
||||
return QString("%1:%2").arg(source).arg(address, 1, 16);
|
||||
}
|
||||
|
||||
bool operator==(const MessageId &other) const {
|
||||
return source == other.source && address == other.address;
|
||||
}
|
||||
|
||||
bool operator!=(const MessageId &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool operator<(const MessageId &other) const {
|
||||
return std::pair{source, address} < std::pair{other.source, other.address};
|
||||
}
|
||||
|
||||
bool operator>(const MessageId &other) const {
|
||||
return std::pair{source, address} > std::pair{other.source, other.address};
|
||||
}
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(MessageId);
|
||||
|
||||
uint qHash(const MessageId &item);
|
||||
|
||||
struct DBCMsg {
|
||||
QString name;
|
||||
uint32_t size;
|
||||
@@ -24,17 +53,16 @@ public:
|
||||
void open(const QString &dbc_file_name);
|
||||
bool open(const QString &name, const QString &content, QString *error = nullptr);
|
||||
QString generateDBC();
|
||||
void addSignal(const QString &id, const Signal &sig);
|
||||
void updateSignal(const QString &id, const QString &sig_name, const Signal &sig);
|
||||
void removeSignal(const QString &id, const QString &sig_name);
|
||||
void addSignal(const MessageId &id, const Signal &sig);
|
||||
void updateSignal(const MessageId &id, const QString &sig_name, const Signal &sig);
|
||||
void removeSignal(const MessageId &id, const QString &sig_name);
|
||||
|
||||
static std::pair<uint8_t, uint32_t> parseId(const QString &id);
|
||||
inline static std::vector<std::string> allDBCNames() { return get_dbc_names(); }
|
||||
inline QString name() const { return dbc ? dbc->name.c_str() : ""; }
|
||||
void updateMsg(const QString &id, const QString &name, uint32_t size);
|
||||
void removeMsg(const QString &id);
|
||||
void updateMsg(const MessageId &id, const QString &name, uint32_t size);
|
||||
void removeMsg(const MessageId &id);
|
||||
inline const std::map<uint32_t, DBCMsg> &messages() const { return msgs; }
|
||||
inline const DBCMsg *msg(const QString &id) const { return msg(parseId(id).second); }
|
||||
inline const DBCMsg *msg(const MessageId &id) const { return msg(id.address); }
|
||||
inline const DBCMsg *msg(uint32_t address) const {
|
||||
auto it = msgs.find(address);
|
||||
return it != msgs.end() ? &it->second : nullptr;
|
||||
@@ -65,7 +93,7 @@ int bigEndianBitIndex(int index);
|
||||
void updateSigSizeParamsFromRange(Signal &s, int start_bit, int size);
|
||||
std::pair<int, int> getSignalRange(const Signal *s);
|
||||
DBCManager *dbc();
|
||||
inline QString msgName(const QString &id) {
|
||||
inline QString msgName(const MessageId &id) {
|
||||
auto msg = dbc()->msg(id);
|
||||
return msg ? msg->name : UNTITLED;
|
||||
}
|
||||
|
||||
@@ -85,11 +85,15 @@ DetailWidget::DetailWidget(ChartsWidget *charts, QWidget *parent) : charts(chart
|
||||
QObject::connect(UndoStack::instance(), &QUndoStack::indexChanged, this, &DetailWidget::refresh);
|
||||
QObject::connect(tabbar, &QTabBar::customContextMenuRequested, this, &DetailWidget::showTabBarContextMenu);
|
||||
QObject::connect(tabbar, &QTabBar::currentChanged, [this](int index) {
|
||||
if (index != -1 && tabbar->tabText(index) != msg_id) {
|
||||
setMessage(tabbar->tabText(index));
|
||||
if (index != -1) {
|
||||
setMessage(tabbar_ids[index]);
|
||||
}
|
||||
});
|
||||
QObject::connect(tabbar, &QTabBar::tabCloseRequested, tabbar, &QTabBar::removeTab);
|
||||
QObject::connect(tabbar, &QTabBar::tabCloseRequested, [this](int index) {
|
||||
tabbar_ids.removeAt(index);
|
||||
tabbar->removeTab(index);
|
||||
assert(tabbar_ids.size() == tabbar->count());
|
||||
});
|
||||
QObject::connect(charts, &ChartsWidget::seriesChanged, signal_view, &SignalView::updateChartState);
|
||||
}
|
||||
|
||||
@@ -108,29 +112,32 @@ void DetailWidget::showTabBarContextMenu(const QPoint &pt) {
|
||||
}
|
||||
|
||||
void DetailWidget::removeAll() {
|
||||
msg_id = "";
|
||||
msg_id = std::nullopt;
|
||||
tabbar->blockSignals(true);
|
||||
while (tabbar->count() > 0) {
|
||||
tabbar->removeTab(0);
|
||||
}
|
||||
tabbar_ids.clear();
|
||||
tabbar->blockSignals(false);
|
||||
stacked_layout->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
void DetailWidget::setMessage(const QString &message_id) {
|
||||
void DetailWidget::setMessage(const MessageId &message_id) {
|
||||
msg_id = message_id;
|
||||
int index = tabbar->count() - 1;
|
||||
for (/**/; index >= 0 && tabbar->tabText(index) != msg_id; --index) { /**/ }
|
||||
int index = tabbar_ids.indexOf(*msg_id);
|
||||
|
||||
if (index == -1) {
|
||||
index = tabbar->addTab(message_id);
|
||||
tabbar_ids.append(*msg_id);
|
||||
index = tabbar->addTab(message_id.toString());
|
||||
tabbar->setTabToolTip(index, msgName(message_id));
|
||||
}
|
||||
assert(tabbar->count() == tabbar_ids.size());
|
||||
|
||||
setUpdatesEnabled(false);
|
||||
|
||||
signal_view->setMessage(msg_id);
|
||||
binary_view->setMessage(msg_id);
|
||||
history_log->setMessage(msg_id);
|
||||
signal_view->setMessage(*msg_id);
|
||||
binary_view->setMessage(*msg_id);
|
||||
history_log->setMessage(*msg_id);
|
||||
|
||||
stacked_layout->setCurrentIndex(1);
|
||||
tabbar->setCurrentIndex(index);
|
||||
@@ -141,12 +148,12 @@ void DetailWidget::setMessage(const QString &message_id) {
|
||||
}
|
||||
|
||||
void DetailWidget::refresh() {
|
||||
if (msg_id.isEmpty()) return;
|
||||
if (!msg_id) return;
|
||||
|
||||
QStringList warnings;
|
||||
const DBCMsg *msg = dbc()->msg(msg_id);
|
||||
const DBCMsg *msg = dbc()->msg(*msg_id);
|
||||
if (msg) {
|
||||
if (msg->size != can->lastMessage(msg_id).dat.size()) {
|
||||
if (msg->size != can->lastMessage(*msg_id).dat.size()) {
|
||||
warnings.push_back(tr("Message size (%1) is incorrect.").arg(msg->size));
|
||||
}
|
||||
for (auto s : binary_view->getOverlappingSignals()) {
|
||||
@@ -156,7 +163,7 @@ void DetailWidget::refresh() {
|
||||
warnings.push_back(tr("Drag-Select in binary view to create new signal."));
|
||||
}
|
||||
remove_msg_act->setEnabled(msg != nullptr);
|
||||
name_label->setText(msgName(msg_id));
|
||||
name_label->setText(msgName(*msg_id));
|
||||
|
||||
if (!warnings.isEmpty()) {
|
||||
warning_label->setText(warnings.join('\n'));
|
||||
@@ -165,9 +172,9 @@ void DetailWidget::refresh() {
|
||||
warning_widget->setVisible(!warnings.isEmpty());
|
||||
}
|
||||
|
||||
void DetailWidget::updateState(const QHash<QString, CanData> *msgs) {
|
||||
void DetailWidget::updateState(const QHash<MessageId, CanData> *msgs) {
|
||||
time_label->setText(QString::number(can->currentSec(), 'f', 3));
|
||||
if (msg_id.isEmpty() || (msgs && !msgs->contains(msg_id)))
|
||||
if (!msg_id || (msgs && !msgs->contains(*msg_id)))
|
||||
return;
|
||||
|
||||
if (tab_widget->currentIndex() == 0)
|
||||
@@ -177,24 +184,24 @@ void DetailWidget::updateState(const QHash<QString, CanData> *msgs) {
|
||||
}
|
||||
|
||||
void DetailWidget::editMsg() {
|
||||
QString id = msg_id;
|
||||
MessageId id = *msg_id;
|
||||
auto msg = dbc()->msg(id);
|
||||
int size = msg ? msg->size : can->lastMessage(id).dat.size();
|
||||
EditMessageDialog dlg(id, msgName(id), size, this);
|
||||
if (dlg.exec()) {
|
||||
UndoStack::push(new EditMsgCommand(msg_id, dlg.name_edit->text(), dlg.size_spin->value()));
|
||||
UndoStack::push(new EditMsgCommand(*msg_id, dlg.name_edit->text(), dlg.size_spin->value()));
|
||||
}
|
||||
}
|
||||
|
||||
void DetailWidget::removeMsg() {
|
||||
UndoStack::push(new RemoveMsgCommand(msg_id));
|
||||
UndoStack::push(new RemoveMsgCommand(*msg_id));
|
||||
}
|
||||
|
||||
// EditMessageDialog
|
||||
|
||||
EditMessageDialog::EditMessageDialog(const QString &msg_id, const QString &title, int size, QWidget *parent)
|
||||
EditMessageDialog::EditMessageDialog(const MessageId &msg_id, const QString &title, int size, QWidget *parent)
|
||||
: original_name(title), QDialog(parent) {
|
||||
setWindowTitle(tr("Edit message: %1").arg(msg_id));
|
||||
setWindowTitle(tr("Edit message: %1").arg(msg_id.toString()));
|
||||
QFormLayout *form_layout = new QFormLayout(this);
|
||||
|
||||
form_layout->addRow("", error_label = new QLabel);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
class EditMessageDialog : public QDialog {
|
||||
public:
|
||||
EditMessageDialog(const QString &msg_id, const QString &title, int size, QWidget *parent);
|
||||
EditMessageDialog(const MessageId &msg_id, const QString &title, int size, QWidget *parent);
|
||||
void validateName(const QString &text);
|
||||
|
||||
QString original_name;
|
||||
@@ -34,7 +34,7 @@ class DetailWidget : public QWidget {
|
||||
|
||||
public:
|
||||
DetailWidget(ChartsWidget *charts, QWidget *parent);
|
||||
void setMessage(const QString &message_id);
|
||||
void setMessage(const MessageId &message_id);
|
||||
void refresh();
|
||||
void removeAll();
|
||||
QSize minimumSizeHint() const override { return binary_view->minimumSizeHint(); }
|
||||
@@ -43,13 +43,14 @@ private:
|
||||
void showTabBarContextMenu(const QPoint &pt);
|
||||
void editMsg();
|
||||
void removeMsg();
|
||||
void updateState(const QHash<QString, CanData> * msgs = nullptr);
|
||||
void updateState(const QHash<MessageId, CanData> * msgs = nullptr);
|
||||
|
||||
QString msg_id;
|
||||
std::optional<MessageId> msg_id;
|
||||
QLabel *time_label, *warning_icon, *warning_label;
|
||||
ElidedLabel *name_label;
|
||||
QWidget *warning_widget;
|
||||
QTabBar *tabbar;
|
||||
QList<MessageId> tabbar_ids;
|
||||
QTabWidget *tab_widget;
|
||||
QAction *remove_msg_act;
|
||||
LogsWidget *history_log;
|
||||
|
||||
@@ -22,14 +22,14 @@ QVariant HistoryLogModel::data(const QModelIndex &index, int role) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
void HistoryLogModel::setMessage(const QString &message_id) {
|
||||
void HistoryLogModel::setMessage(const MessageId &message_id) {
|
||||
msg_id = message_id;
|
||||
}
|
||||
|
||||
void HistoryLogModel::refresh() {
|
||||
beginResetModel();
|
||||
sigs.clear();
|
||||
if (auto dbc_msg = dbc()->msg(msg_id)) {
|
||||
if (auto dbc_msg = dbc()->msg(*msg_id)) {
|
||||
sigs = dbc_msg->getSignals();
|
||||
}
|
||||
last_fetch_time = 0;
|
||||
@@ -78,8 +78,8 @@ void HistoryLogModel::setFilter(int sig_idx, const QString &value, std::function
|
||||
}
|
||||
|
||||
void HistoryLogModel::updateState() {
|
||||
if (!msg_id.isEmpty()) {
|
||||
uint64_t current_time = (can->lastMessage(msg_id).ts + can->routeStartTime()) * 1e9 + 1;
|
||||
if (msg_id) {
|
||||
uint64_t current_time = (can->lastMessage(*msg_id).ts + can->routeStartTime()) * 1e9 + 1;
|
||||
auto new_msgs = dynamic_mode ? fetchData(current_time, last_fetch_time) : fetchData(0);
|
||||
if (!new_msgs.empty()) {
|
||||
beginInsertRows({}, 0, new_msgs.size() - 1);
|
||||
@@ -106,12 +106,11 @@ void HistoryLogModel::fetchMore(const QModelIndex &parent) {
|
||||
template <class InputIt>
|
||||
std::deque<HistoryLogModel::Message> HistoryLogModel::fetchData(InputIt first, InputIt last, uint64_t min_time) {
|
||||
std::deque<HistoryLogModel::Message> msgs;
|
||||
const auto [src, address] = DBCManager::parseId(msg_id);
|
||||
QVector<double> values(sigs.size());
|
||||
for (auto it = first; it != last && (*it)->mono_time > min_time; ++it) {
|
||||
if ((*it)->which == cereal::Event::Which::CAN) {
|
||||
for (const auto &c : (*it)->event.getCan()) {
|
||||
if (address == c.getAddress() && src == c.getSrc()) {
|
||||
if (msg_id->address == c.getAddress() && msg_id->source == c.getSrc()) {
|
||||
const auto dat = c.getDat();
|
||||
for (int i = 0; i < sigs.size(); ++i) {
|
||||
values[i] = get_raw_value((uint8_t *)dat.begin(), dat.size(), *(sigs[i]));
|
||||
@@ -136,7 +135,7 @@ template std::deque<HistoryLogModel::Message> HistoryLogModel::fetchData<>(std::
|
||||
|
||||
std::deque<HistoryLogModel::Message> HistoryLogModel::fetchData(uint64_t from_time, uint64_t min_time) {
|
||||
auto events = can->events();
|
||||
const auto freq = can->lastMessage(msg_id).freq;
|
||||
const auto freq = can->lastMessage(*msg_id).freq;
|
||||
const bool update_colors = !display_signals_mode || sigs.empty();
|
||||
|
||||
if (dynamic_mode) {
|
||||
@@ -241,13 +240,13 @@ LogsWidget::LogsWidget(QWidget *parent) : QWidget(parent) {
|
||||
QObject::connect(can, &AbstractStream::eventsMerged, model, &HistoryLogModel::segmentsMerged);
|
||||
}
|
||||
|
||||
void LogsWidget::setMessage(const QString &message_id) {
|
||||
void LogsWidget::setMessage(const MessageId &message_id) {
|
||||
model->setMessage(message_id);
|
||||
refresh();
|
||||
}
|
||||
|
||||
void LogsWidget::refresh() {
|
||||
if (model->msg_id.isEmpty()) return;
|
||||
if (!model->msg_id) return;
|
||||
|
||||
model->setFilter(0, "", nullptr);
|
||||
model->refresh();
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <optional>
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QHeaderView>
|
||||
@@ -22,7 +24,7 @@ class HistoryLogModel : public QAbstractTableModel {
|
||||
|
||||
public:
|
||||
HistoryLogModel(QObject *parent) : QAbstractTableModel(parent) {}
|
||||
void setMessage(const QString &message_id);
|
||||
void setMessage(const MessageId &message_id);
|
||||
void updateState();
|
||||
void setFilter(int sig_idx, const QString &value, std::function<bool(double, double)> cmp);
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
@@ -52,7 +54,7 @@ public:
|
||||
std::deque<HistoryLogModel::Message> fetchData(InputIt first, InputIt last, uint64_t min_time);
|
||||
std::deque<Message> fetchData(uint64_t from_time, uint64_t min_time = 0);
|
||||
|
||||
QString msg_id;
|
||||
std::optional<MessageId> msg_id;
|
||||
ChangeTracker hex_colors;
|
||||
bool has_more_data = true;
|
||||
const int batch_size = 50;
|
||||
@@ -71,7 +73,7 @@ class LogsWidget : public QWidget {
|
||||
|
||||
public:
|
||||
LogsWidget(QWidget *parent);
|
||||
void setMessage(const QString &message_id);
|
||||
void setMessage(const MessageId &message_id);
|
||||
void updateState() {if (dynamic_mode->isChecked()) model->updateState(); }
|
||||
void showEvent(QShowEvent *event) override { if (dynamic_mode->isChecked()) model->refresh(); }
|
||||
|
||||
|
||||
@@ -46,12 +46,12 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) {
|
||||
QObject::connect(dbc(), &DBCManager::DBCFileChanged, model, &MessageListModel::sortMessages);
|
||||
QObject::connect(dbc(), &DBCManager::msgUpdated, model, &MessageListModel::sortMessages);
|
||||
QObject::connect(dbc(), &DBCManager::msgRemoved, model, &MessageListModel::sortMessages);
|
||||
QObject::connect(model, &MessageListModel::modelReset, [this]() { selectMessage(current_msg_id); });
|
||||
QObject::connect(model, &MessageListModel::modelReset, [this]() { selectMessage(*current_msg_id); });
|
||||
QObject::connect(table_widget->selectionModel(), &QItemSelectionModel::currentChanged, [=](const QModelIndex ¤t, const QModelIndex &previous) {
|
||||
if (current.isValid() && current.row() < model->msgs.size()) {
|
||||
if (model->msgs[current.row()] != current_msg_id) {
|
||||
if (model->msgs[current.row()] != *current_msg_id) {
|
||||
current_msg_id = model->msgs[current.row()];
|
||||
emit msgSelectionChanged(current_msg_id);
|
||||
emit msgSelectionChanged(*current_msg_id);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -67,7 +67,7 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) {
|
||||
updateSuppressedButtons();
|
||||
}
|
||||
|
||||
void MessagesWidget::selectMessage(const QString &msg_id) {
|
||||
void MessagesWidget::selectMessage(const MessageId &msg_id) {
|
||||
if (int row = model->msgs.indexOf(msg_id); row != -1) {
|
||||
table_widget->selectionModel()->setCurrentIndex(model->index(row, 0), QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect);
|
||||
}
|
||||
@@ -86,7 +86,7 @@ void MessagesWidget::updateSuppressedButtons() {
|
||||
void MessagesWidget::reset() {
|
||||
model->reset();
|
||||
filter->clear();
|
||||
current_msg_id = "";
|
||||
current_msg_id = std::nullopt;
|
||||
updateSuppressedButtons();
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ QVariant MessageListModel::data(const QModelIndex &index, int role) const {
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (index.column()) {
|
||||
case 0: return msgName(id);
|
||||
case 1: return id;
|
||||
case 1: return id.toString(); // TODO: put source and address in separate columns
|
||||
case 2: return can_data.freq;
|
||||
case 3: return can_data.count;
|
||||
case 4: return toHex(can_data.dat);
|
||||
@@ -128,9 +128,9 @@ QVariant MessageListModel::data(const QModelIndex &index, int role) const {
|
||||
}
|
||||
|
||||
void MessageListModel::setFilterString(const QString &string) {
|
||||
auto contains = [](const QString &id, const QString &txt) {
|
||||
auto contains = [](const MessageId &id, const QString &txt) {
|
||||
auto cs = Qt::CaseInsensitive;
|
||||
if (id.contains(txt, cs) || msgName(id).contains(txt, cs)) return true;
|
||||
if (id.toString().contains(txt, cs) || msgName(id).contains(txt, cs)) return true;
|
||||
// Search by signal name
|
||||
if (const auto msg = dbc()->msg(id)) {
|
||||
for (auto &signal : msg->getSignals()) {
|
||||
@@ -160,9 +160,7 @@ void MessageListModel::sortMessages() {
|
||||
});
|
||||
} else if (sort_column == 1) {
|
||||
std::sort(msgs.begin(), msgs.end(), [this](auto &l, auto &r) {
|
||||
auto ll = DBCManager::parseId(l);
|
||||
auto rr = DBCManager::parseId(r);
|
||||
return sort_order == Qt::AscendingOrder ? ll < rr : ll > rr;
|
||||
return sort_order == Qt::AscendingOrder ? l < r : l > r;
|
||||
});
|
||||
} else if (sort_column == 2) {
|
||||
std::sort(msgs.begin(), msgs.end(), [this](auto &l, auto &r) {
|
||||
@@ -180,7 +178,7 @@ void MessageListModel::sortMessages() {
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void MessageListModel::msgsReceived(const QHash<QString, CanData> *new_msgs) {
|
||||
void MessageListModel::msgsReceived(const QHash<MessageId, CanData> *new_msgs) {
|
||||
int prev_row_count = msgs.size();
|
||||
if (filter_str.isEmpty() && msgs.size() != can->can_msgs.size()) {
|
||||
msgs = can->can_msgs.keys();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QHeaderView>
|
||||
#include <QLineEdit>
|
||||
@@ -20,13 +22,13 @@ public:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override { return msgs.size(); }
|
||||
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
|
||||
void setFilterString(const QString &string);
|
||||
void msgsReceived(const QHash<QString, CanData> *new_msgs = nullptr);
|
||||
void msgsReceived(const QHash<MessageId, CanData> *new_msgs = nullptr);
|
||||
void sortMessages();
|
||||
void suppress();
|
||||
void clearSuppress();
|
||||
void reset();
|
||||
QStringList msgs;
|
||||
QSet<std::pair<QString, int>> suppressed_bytes;
|
||||
QList<MessageId> msgs;
|
||||
QSet<std::pair<MessageId, int>> suppressed_bytes;
|
||||
|
||||
private:
|
||||
QString filter_str;
|
||||
@@ -39,18 +41,18 @@ class MessagesWidget : public QWidget {
|
||||
|
||||
public:
|
||||
MessagesWidget(QWidget *parent);
|
||||
void selectMessage(const QString &message_id);
|
||||
void selectMessage(const MessageId &message_id);
|
||||
QByteArray saveHeaderState() const { return table_widget->horizontalHeader()->saveState(); }
|
||||
bool restoreHeaderState(const QByteArray &state) const { return table_widget->horizontalHeader()->restoreState(state); }
|
||||
void updateSuppressedButtons();
|
||||
void reset();
|
||||
|
||||
signals:
|
||||
void msgSelectionChanged(const QString &message_id);
|
||||
void msgSelectionChanged(const MessageId &message_id);
|
||||
|
||||
protected:
|
||||
QTableView *table_widget;
|
||||
QString current_msg_id;
|
||||
std::optional<MessageId> current_msg_id;
|
||||
QLineEdit *filter;
|
||||
MessageListModel *model;
|
||||
QPushButton *suppress_add;
|
||||
|
||||
@@ -31,7 +31,7 @@ void SignalModel::insertItem(SignalModel::Item *parent_item, int pos, const Sign
|
||||
}
|
||||
}
|
||||
|
||||
void SignalModel::setMessage(const QString &id) {
|
||||
void SignalModel::setMessage(const MessageId &id) {
|
||||
msg_id = id;
|
||||
filter_str = "";
|
||||
refresh();
|
||||
@@ -56,7 +56,7 @@ void SignalModel::refresh() {
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void SignalModel::updateState(const QHash<QString, CanData> *msgs) {
|
||||
void SignalModel::updateState(const QHash<MessageId, CanData> *msgs) {
|
||||
if (!msgs || (msgs->contains(msg_id))) {
|
||||
auto &dat = can->lastMessage(msg_id).dat;
|
||||
int row = 0;
|
||||
@@ -230,13 +230,13 @@ void SignalModel::removeSignal(const Signal *sig) {
|
||||
}
|
||||
|
||||
void SignalModel::handleMsgChanged(uint32_t address) {
|
||||
if (address == DBCManager::parseId(msg_id).second) {
|
||||
if (address == msg_id.address) {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void SignalModel::handleSignalAdded(uint32_t address, const Signal *sig) {
|
||||
if (address == DBCManager::parseId(msg_id).second) {
|
||||
if (address == msg_id.address) {
|
||||
int i = 0;
|
||||
for (; i < root->children.size(); ++i) {
|
||||
if (sig->start_bit < root->children[i]->sig->start_bit) break;
|
||||
@@ -367,7 +367,7 @@ SignalView::SignalView(ChartsWidget *charts, QWidget *parent) : charts(charts),
|
||||
QObject::connect(dbc(), &DBCManager::signalAdded, [this](uint32_t address, const Signal *sig) { expandSignal(sig); });
|
||||
}
|
||||
|
||||
void SignalView::setMessage(const QString &id) {
|
||||
void SignalView::setMessage(const MessageId &id) {
|
||||
msg_id = id;
|
||||
filter_edit->clear();
|
||||
model->setMessage(id);
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
QModelIndex parent(const QModelIndex &index) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
void setMessage(const QString &id);
|
||||
void setMessage(const MessageId &id);
|
||||
void setFilter(const QString &txt);
|
||||
void addSignal(int start_bit, int size, bool little_endian);
|
||||
bool saveSignal(const Signal *origin_s, Signal &s);
|
||||
@@ -54,9 +54,9 @@ private:
|
||||
void handleSignalRemoved(const Signal *sig);
|
||||
void handleMsgChanged(uint32_t address);
|
||||
void refresh();
|
||||
void updateState(const QHash<QString, CanData> *msgs);
|
||||
void updateState(const QHash<MessageId, CanData> *msgs);
|
||||
|
||||
QString msg_id;
|
||||
MessageId msg_id;
|
||||
QString filter_str;
|
||||
std::unique_ptr<Item> root;
|
||||
friend class SignalView;
|
||||
@@ -76,7 +76,7 @@ class SignalView : public QWidget {
|
||||
|
||||
public:
|
||||
SignalView(ChartsWidget *charts, QWidget *parent);
|
||||
void setMessage(const QString &id);
|
||||
void setMessage(const MessageId &id);
|
||||
void signalHovered(const Signal *sig);
|
||||
void updateChartState();
|
||||
void expandSignal(const Signal *sig);
|
||||
@@ -85,13 +85,13 @@ public:
|
||||
|
||||
signals:
|
||||
void highlight(const Signal *sig);
|
||||
void showChart(const QString &name, const Signal *sig, bool show, bool merge);
|
||||
void showChart(const MessageId &id, const Signal *sig, bool show, bool merge);
|
||||
|
||||
private:
|
||||
void rowsChanged();
|
||||
void leaveEvent(QEvent *event);
|
||||
|
||||
QString msg_id;
|
||||
MessageId msg_id;
|
||||
QTreeView *tree;
|
||||
QLineEdit *filter_edit;
|
||||
ChartsWidget *charts;
|
||||
|
||||
@@ -4,12 +4,12 @@ AbstractStream *can = nullptr;
|
||||
|
||||
AbstractStream::AbstractStream(QObject *parent, bool is_live_streaming) : is_live_streaming(is_live_streaming), QObject(parent) {
|
||||
can = this;
|
||||
new_msgs = std::make_unique<QHash<QString, CanData>>();
|
||||
new_msgs = std::make_unique<QHash<MessageId, CanData>>();
|
||||
QObject::connect(this, &AbstractStream::received, this, &AbstractStream::process, Qt::QueuedConnection);
|
||||
QObject::connect(this, &AbstractStream::seekedTo, this, &AbstractStream::updateLastMsgsTo);
|
||||
}
|
||||
|
||||
void AbstractStream::process(QHash<QString, CanData> *messages) {
|
||||
void AbstractStream::process(QHash<MessageId, CanData> *messages) {
|
||||
for (auto it = messages->begin(); it != messages->end(); ++it) {
|
||||
can_msgs[it.key()] = it.value();
|
||||
}
|
||||
@@ -25,7 +25,7 @@ bool AbstractStream::updateEvent(const Event *event) {
|
||||
if (event->which == cereal::Event::Which::CAN) {
|
||||
double current_sec = event->mono_time / 1e9 - routeStartTime();
|
||||
for (const auto &c : event->event.getCan()) {
|
||||
QString id = QString("%1:%2").arg(c.getSrc()).arg(c.getAddress(), 1, 16);
|
||||
MessageId id = {.source = c.getSrc(), .address = c.getAddress()};
|
||||
CanData &data = (*new_msgs)[id];
|
||||
data.ts = current_sec;
|
||||
data.dat = QByteArray((char *)c.getDat().begin(), c.getDat().size());
|
||||
@@ -44,21 +44,21 @@ bool AbstractStream::updateEvent(const Event *event) {
|
||||
prev_update_ts = ts;
|
||||
// use pointer to avoid data copy in queued connection.
|
||||
emit received(new_msgs.release());
|
||||
new_msgs.reset(new QHash<QString, CanData>);
|
||||
new_msgs.reset(new QHash<MessageId, CanData>);
|
||||
new_msgs->reserve(100);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const CanData &AbstractStream::lastMessage(const QString &id) {
|
||||
const CanData &AbstractStream::lastMessage(const MessageId &id) {
|
||||
static CanData empty_data;
|
||||
auto it = can_msgs.find(id);
|
||||
return it != can_msgs.end() ? it.value() : empty_data;
|
||||
}
|
||||
|
||||
void AbstractStream::updateLastMsgsTo(double sec) {
|
||||
QHash<std::pair<uint8_t, uint32_t>, CanData> last_msgs; // Much faster than QHash<String, CanData>
|
||||
QHash<MessageId, CanData> last_msgs;
|
||||
last_msgs.reserve(can_msgs.size());
|
||||
double route_start_time = routeStartTime();
|
||||
uint64_t last_ts = (sec + route_start_time) * 1e9;
|
||||
@@ -66,7 +66,7 @@ void AbstractStream::updateLastMsgsTo(double sec) {
|
||||
for (auto it = last; it != events()->rend(); ++it) {
|
||||
if ((*it)->which == cereal::Event::Which::CAN) {
|
||||
for (const auto &c : (*it)->event.getCan()) {
|
||||
auto &m = last_msgs[{c.getSrc(), c.getAddress()}];
|
||||
auto &m = last_msgs[{.source = c.getSrc(), .address = c.getAddress()}];
|
||||
if (++m.count == 1) {
|
||||
m.ts = ((*it)->mono_time / 1e9) - route_start_time;
|
||||
m.dat = QByteArray((char *)c.getDat().begin(), c.getDat().size());
|
||||
@@ -87,9 +87,8 @@ void AbstractStream::updateLastMsgsTo(double sec) {
|
||||
counters.clear();
|
||||
can_msgs.clear();
|
||||
for (auto it = last_msgs.cbegin(); it != last_msgs.cend(); ++it) {
|
||||
QString msg_id = QString("%1:%2").arg(it.key().first).arg(it.key().second, 1, 16);
|
||||
can_msgs[msg_id] = it.value();
|
||||
counters[msg_id] = it.value().count;
|
||||
can_msgs[it.key()] = it.value();
|
||||
counters[it.key()] = it.value().count;
|
||||
}
|
||||
emit updated();
|
||||
emit msgsReceived(&can_msgs);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <QColor>
|
||||
#include <QHash>
|
||||
|
||||
#include "tools/cabana/dbcmanager.h"
|
||||
#include "tools/cabana/settings.h"
|
||||
#include "tools/cabana/util.h"
|
||||
#include "tools/replay/replay.h"
|
||||
@@ -33,7 +34,7 @@ public:
|
||||
virtual double routeStartTime() const { return 0; }
|
||||
virtual double currentSec() const = 0;
|
||||
virtual QDateTime currentDateTime() const { return {}; }
|
||||
virtual const CanData &lastMessage(const QString &id);
|
||||
virtual const CanData &lastMessage(const MessageId &id);
|
||||
virtual VisionStreamType visionStreamType() const { return VISION_STREAM_ROAD; }
|
||||
virtual const Route *route() const { return nullptr; }
|
||||
virtual const std::vector<Event *> *events() const = 0;
|
||||
@@ -49,22 +50,22 @@ signals:
|
||||
void streamStarted();
|
||||
void eventsMerged();
|
||||
void updated();
|
||||
void msgsReceived(const QHash<QString, CanData> *);
|
||||
void received(QHash<QString, CanData> *);
|
||||
void msgsReceived(const QHash<MessageId, CanData> *);
|
||||
void received(QHash<MessageId, CanData> *);
|
||||
|
||||
public:
|
||||
QHash<QString, CanData> can_msgs;
|
||||
QHash<MessageId, CanData> can_msgs;
|
||||
|
||||
protected:
|
||||
void process(QHash<QString, CanData> *);
|
||||
void process(QHash<MessageId, CanData> *);
|
||||
bool updateEvent(const Event *event);
|
||||
void updateLastMsgsTo(double sec);
|
||||
|
||||
bool is_live_streaming = false;
|
||||
std::atomic<bool> processing = false;
|
||||
QHash<QString, uint32_t> counters;
|
||||
std::unique_ptr<QHash<QString, CanData>> new_msgs;
|
||||
QHash<QString, ChangeTracker> change_trackers;
|
||||
QHash<MessageId, uint32_t> counters;
|
||||
std::unique_ptr<QHash<MessageId, CanData>> new_msgs;
|
||||
QHash<MessageId, ChangeTracker> change_trackers;
|
||||
};
|
||||
|
||||
// A global pointer referring to the unique AbstractStream object
|
||||
|
||||
@@ -20,10 +20,10 @@ FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::Wi
|
||||
bus_combo = new QComboBox(this);
|
||||
QSet<uint8_t> bus_set;
|
||||
for (auto it = can->can_msgs.begin(); it != can->can_msgs.end(); ++it) {
|
||||
bus_set << DBCManager::parseId(it.key()).first;
|
||||
bus_set << it.key().source;
|
||||
}
|
||||
for (uint8_t bus : bus_set) {
|
||||
bus_combo->addItem(QString::number(bus));
|
||||
bus_combo->addItem(QString::number(bus), bus);
|
||||
}
|
||||
bus_combo->model()->sort(0);
|
||||
bus_combo->setCurrentIndex(0);
|
||||
@@ -69,9 +69,11 @@ FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::Wi
|
||||
|
||||
setMinimumSize({700, 500});
|
||||
QObject::connect(search_btn, &QPushButton::clicked, this, &FindSimilarBitsDlg::find);
|
||||
|
||||
QObject::connect(table, &QTableWidget::doubleClicked, [this](const QModelIndex &index) {
|
||||
if (index.isValid()) {
|
||||
emit openMessage(bus_combo->currentText() + ":" + table->item(index.row(), 0)->text());
|
||||
MessageId msg_id = {.source = (uint8_t)bus_combo->currentData().toUInt(), .address = table->item(index.row(), 0)->text().toUInt(0, 16)};
|
||||
emit openMessage(msg_id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <QSpinBox>
|
||||
#include <QTableWidget>
|
||||
|
||||
#include "tools/cabana/dbcmanager.h"
|
||||
|
||||
class FindSimilarBitsDlg : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
@@ -13,7 +15,7 @@ public:
|
||||
FindSimilarBitsDlg(QWidget *parent);
|
||||
|
||||
signals:
|
||||
void openMessage(const QString &msg_id);
|
||||
void openMessage(const MessageId &msg_id);
|
||||
|
||||
private:
|
||||
struct mismatched_struct {
|
||||
|
||||
Reference in New Issue
Block a user