openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

97 lines
3.4 KiB

#include "tools/cabana/historylog.h"
#include <QFontDatabase>
// HistoryLogModel
inline const Signal &get_signal(const DBCMsg *m, int index) {
return std::next(m->sigs.begin(), index)->second;
}
QVariant HistoryLogModel::data(const QModelIndex &index, int role) const {
bool has_signal = dbc_msg && !dbc_msg->sigs.empty();
if (role == Qt::DisplayRole) {
const auto &m = messages[index.row()];
if (index.column() == 0) {
return QString::number(m.ts, 'f', 2);
}
return has_signal ? QString::number(get_raw_value((uint8_t *)m.dat.begin(), m.dat.size(), get_signal(dbc_msg, index.column() - 1)))
: toHex(m.dat);
} else if (role == Qt::FontRole && index.column() == 1 && !has_signal) {
return QFontDatabase::systemFont(QFontDatabase::FixedFont);
}
return {};
}
void HistoryLogModel::setMessage(const QString &message_id) {
beginResetModel();
msg_id = message_id;
dbc_msg = dbc()->msg(message_id);
column_count = (dbc_msg && !dbc_msg->sigs.empty() ? dbc_msg->sigs.size() : 1) + 1;
row_count = 0;
endResetModel();
updateState();
}
QVariant HistoryLogModel::headerData(int section, Qt::Orientation orientation, int role) const {
if (orientation == Qt::Horizontal) {
bool has_signal = dbc_msg && !dbc_msg->sigs.empty();
if (role == Qt::DisplayRole || role == Qt::ToolTipRole) {
if (section == 0) {
return "Time";
}
return has_signal ? QString::fromStdString(get_signal(dbc_msg, section - 1).name).replace('_', ' ') : "Data";
} else if (role == Qt::BackgroundRole && section > 0 && has_signal) {
return QBrush(QColor(getColor(section - 1)));
}
}
return {};
}
void HistoryLogModel::updateState() {
if (msg_id.isEmpty()) return;
int prev_row_count = row_count;
messages = can->messages(msg_id);
row_count = messages.size();
int delta = row_count - prev_row_count;
if (delta > 0) {
beginInsertRows({}, prev_row_count, row_count - 1);
endInsertRows();
} else if (delta < 0) {
beginRemoveRows({}, row_count, prev_row_count - 1);
endRemoveRows();
}
if (row_count > 0) {
emit dataChanged(index(0, 0), index(row_count - 1, column_count - 1), {Qt::DisplayRole});
}
}
// HeaderView
QSize HeaderView::sectionSizeFromContents(int logicalIndex) const {
const QString text = model()->headerData(logicalIndex, this->orientation(), Qt::DisplayRole).toString();
const QRect rect = fontMetrics().boundingRect(QRect(0, 0, sectionSize(logicalIndex), 1000), defaultAlignment(), text);
return rect.size() + QSize{10, 5};
}
// HistoryLog
HistoryLog::HistoryLog(QWidget *parent) : QTableView(parent) {
model = new HistoryLogModel(this);
setModel(model);
setHorizontalHeader(new HeaderView(Qt::Horizontal, this));
horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | (Qt::Alignment)Qt::TextWordWrap);
horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
verticalHeader()->setVisible(false);
setFrameShape(QFrame::NoFrame);
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
setStyleSheet("QTableView::item { border:0px; padding-left:5px; padding-right:5px; }");
}
int HistoryLog::sizeHintForColumn(int column) const {
// sizeHintForColumn is only called for column 0 (ResizeToContents)
return itemDelegate()->sizeHint(viewOptions(), model->index(0, 0)).width() + 1; // +1 for grid
}