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.

149 lines
4.5 KiB

#include "tools/cabana/util.h"
#include <QApplication>
#include <QFontDatabase>
#include <QPainter>
#include <QDebug>
#include <limits>
#include <cmath>
#include "selfdrive/ui/qt/util.h"
static QColor blend(QColor a, QColor b) {
return QColor((a.red() + b.red()) / 2, (a.green() + b.green()) / 2, (a.blue() + b.blue()) / 2, (a.alpha() + b.alpha()) / 2);
}
void ChangeTracker::compute(const QByteArray &dat, double ts, uint32_t freq) {
if (prev_dat.size() != dat.size()) {
colors.resize(dat.size());
last_change_t.resize(dat.size());
bit_change_counts.resize(dat.size());
std::fill(colors.begin(), colors.end(), QColor(0, 0, 0, 0));
std::fill(last_change_t.begin(), last_change_t.end(), ts);
} else {
for (int i = 0; i < dat.size(); ++i) {
const uint8_t last = prev_dat[i];
const uint8_t cur = dat[i];
if (last != cur) {
double delta_t = ts - last_change_t[i];
if (delta_t * freq > periodic_threshold) {
// Last change was while ago, choose color based on delta up or down
if (cur > last) {
colors[i] = QColor(0, 187, 255, start_alpha); // Cyan
} else {
colors[i] = QColor(255, 0, 0, start_alpha); // Red
}
} else {
// Periodic changes
colors[i] = blend(colors[i], QColor(102, 86, 169, start_alpha / 2)); // Greyish/Blue
}
// Track bit level changes
for (int bit = 0; bit < 8; bit++){
if ((cur ^ last) & (1 << bit)) {
bit_change_counts[i][bit] += 1;
}
}
last_change_t[i] = ts;
} else {
// Fade out
float alpha_delta = 1.0 / (freq + 1) / fade_time;
colors[i].setAlphaF(std::max(0.0, colors[i].alphaF() - alpha_delta));
}
}
}
prev_dat = dat;
}
void ChangeTracker::clear() {
prev_dat.clear();
last_change_t.clear();
bit_change_counts.clear();
colors.clear();
}
QList<QVariant> ChangeTracker::toVariantList(const QVector<QColor> &colors) {
QList<QVariant> ret;
ret.reserve(colors.size());
for (auto &c : colors) ret.append(c);
return ret;
}
// MessageBytesDelegate
MessageBytesDelegate::MessageBytesDelegate(QObject *parent) : QStyledItemDelegate(parent) {
fixed_font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
}
void MessageBytesDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {
QStyleOptionViewItemV4 opt = option;
initStyleOption(&opt, index);
auto byte_list = opt.text.split(" ");
if (byte_list.size() <= 1) {
QStyledItemDelegate::paint(painter, option, index);
return;
}
if ((option.state & QStyle::State_Selected) && (option.state & QStyle::State_Active)) {
painter->setPen(option.palette.color(QPalette::HighlightedText));
} else {
painter->setPen(option.palette.color(QPalette::Text));
}
painter->setFont(fixed_font);
QRect space = painter->boundingRect(opt.rect, opt.displayAlignment, " ");
QRect pos = painter->boundingRect(opt.rect, opt.displayAlignment, "00");
pos.moveLeft(pos.x() + space.width());
int m = space.width() / 2;
const QMargins margins(m, m, m, m);
QList<QVariant> colors = index.data(Qt::UserRole).toList();
int i = 0;
for (auto &byte : byte_list) {
if (i < colors.size()) {
painter->fillRect(pos.marginsAdded(margins), colors[i].value<QColor>());
}
painter->drawText(pos, opt.displayAlignment, byte);
pos.moveLeft(pos.right() + space.width());
i++;
}
}
QColor getColor(const Signal *sig) {
float h = 19 * (float)sig->lsb / 64.0;
h = fmod(h, 1.0);
size_t hash = qHash(QString::fromStdString(sig->name));
float s = 0.25 + 0.25 * (float)(hash & 0xff) / 255.0;
float v = 0.75 + 0.25 * (float)((hash >> 8) & 0xff) / 255.0;
return QColor::fromHsvF(h, s, v);
}
NameValidator::NameValidator(QObject *parent) : QRegExpValidator(QRegExp("^(\\w+)"), parent) { }
QValidator::State NameValidator::validate(QString &input, int &pos) const {
input.replace(' ', '_');
return QRegExpValidator::validate(input, pos);
}
namespace utils {
QPixmap icon(const QString &id) {
static bool dark_theme = QApplication::style()->standardPalette().color(QPalette::WindowText).value() >
QApplication::style()->standardPalette().color(QPalette::Background).value();
QPixmap pm = bootstrapPixmap(id);
if (dark_theme) {
QPainter p(&pm);
p.setCompositionMode(QPainter::CompositionMode_SourceIn);
p.fillRect(pm.rect(), Qt::lightGray);
}
return pm;
}
} // namespace utils