settings and render for setUseColorsByCanId

This commit is contained in:
Daniele Baggio
2026-03-18 10:31:22 +01:00
parent ad65cf78a8
commit fb6881eeaa
7 changed files with 124 additions and 18 deletions
+38 -17
View File
@@ -3,6 +3,8 @@
#include <QFile>
#include <QApplication>
#include <QPalette>
#include <QColor>
#include <QBrush>
#include <QDateTime>
#include <QSettings>
#include "utility.h"
@@ -76,6 +78,7 @@ CANFrameModel::CANFrameModel(QObject *parent)
overwriteDups = false;
filtersPersistDuringClear = false;
useHexMode = true;
useColorsByCanId = false;
timeStyle = TS_MICROS;
timeOffset = 0;
needFilterRefresh = false;
@@ -101,6 +104,16 @@ void CANFrameModel::setHexMode(bool mode)
}
}
void CANFrameModel::setUseColorsByCanId(bool mode)
{
if (useColorsByCanId != mode)
{
this->beginResetModel();
useColorsByCanId = mode;
this->endResetModel();
}
}
void CANFrameModel::setTimeStyle(TimeStyle newStyle)
{
if (timeStyle != newStyle)
@@ -401,7 +414,6 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const
{
QString tempString;
CANFrame thisFrame;
static bool rowFlip = false;
QVariant ts;
if (!index.isValid())
@@ -425,9 +437,31 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const
return msg->bgColor;
}
}
rowFlip = (index.row() % 2);
if (rowFlip) return QApplication::palette().color(QPalette::Base);
else return QApplication::palette().color(QPalette::AlternateBase);
if (useColorsByCanId)
{
QString frameStr = Utility::formatCANID(thisFrame.frameId(), thisFrame.hasExtendedFrameFormat());
// Color rows by the value in the "category" column
return QBrush(Utility::colorForString(frameStr));
}
return (index.row() % 2) ?
QApplication::palette().color(QPalette::Base) :
QApplication::palette().color(QPalette::AlternateBase);
}
if (role == Qt::ForegroundRole)
{
if (dbcHandler != nullptr && interpretFrames && !ignoreDBCColors)
{
DBC_MESSAGE *msg = dbcHandler->findMessage(thisFrame);
if (msg != nullptr)
{
return msg->fgColor;
}
}
return QApplication::palette().color(QPalette::WindowText);
}
if (role == Qt::TextAlignmentRole)
@@ -448,19 +482,6 @@ QVariant CANFrameModel::data(const QModelIndex &index, int role) const
}
}
if (role == Qt::ForegroundRole)
{
if (dbcHandler != nullptr && interpretFrames && !ignoreDBCColors)
{
DBC_MESSAGE *msg = dbcHandler->findMessage(thisFrame);
if (msg != nullptr)
{
return msg->fgColor;
}
}
return QApplication::palette().color(QPalette::WindowText);
}
if (role == Qt::DisplayRole) {
switch (Column(index.column()))
{
+2
View File
@@ -47,6 +47,7 @@ public:
bool getInterpretMode();
void setOverwriteMode(bool);
void setHexMode(bool);
void setUseColorsByCanId(bool);
void setClearMode(bool mode);
void setTimeStyle(TimeStyle newStyle);
void setIgnoreDBCColors(bool mode);
@@ -94,6 +95,7 @@ private:
QString timeFormat;
TimeStyle timeStyle;
bool useHexMode;
bool useColorsByCanId;
bool needFilterRefresh;
bool ignoreDBCColors;
int64_t timeOffset;
+3
View File
@@ -90,7 +90,9 @@ MainSettingsDialog::MainSettingsDialog(QWidget *parent) :
ui->cbUseFiltered->setChecked(settings.value("Main/UseFiltered", false).toBool());
ui->cbUseOpenGL->setChecked(settings.value("Main/UseOpenGL", false).toBool());
ui->cbFilterLabeling->setChecked(settings.value("Main/FilterLabeling", true).toBool());
ui->cbFilterLabeling->setChecked(settings.value("Main/FilterLabeling", true).toBool());
ui->cbIgnoreDBCColors->setChecked(settings.value("Main/IgnoreDBCColors", false).toBool());
ui->cbColorsByCanId->setChecked(settings.value("Main/ColorsByCanId", false).toBool());
int maxFramesDefault;
if (QSysInfo::WordSize > 32)
@@ -208,6 +210,7 @@ void MainSettingsDialog::updateSettings()
settings.setValue("Main/MaximumFrames", ui->spinMaximumFrames->value());
settings.setValue("Main/BytesPerLine", ui->spinBytesPerLine->value());
settings.setValue("Main/FontFixedWidth", ui->cbFontFixedWidth->isChecked());
settings.setValue("Main/ColorsByCanId", ui->cbColorsByCanId->isChecked());
settings.sync();
emit updatedSettings();
+4 -1
View File
@@ -36,7 +36,7 @@ MainWindow::MainWindow(QWidget *parent) :
#endif
useHex = true;
useColorsByCanId = false;
selfRef = this;
this->setWindowTitle("Savvy CAN V" + QString::number(VERSION) + " [Built " + QString(__DATE__) +"]");
@@ -415,6 +415,9 @@ void MainWindow::readUpdateableSettings()
model->setHexMode(useHex);
Utility::decimalMode = !useHex;
useColorsByCanId = settings.value("Main/ColorsByCanId", false).toBool();
model->setUseColorsByCanId(useColorsByCanId);
bool tempBool;
TimeStyle ts = TS_MICROS;
tempBool = settings.value("Main/TimeSeconds", false).toBool();
+1
View File
@@ -160,6 +160,7 @@ private:
int rxFrames;
bool inhibitFilterUpdate;
bool useHex;
bool useColorsByCanId;
bool allowCapture;
bool ignoreDBCColors;
bool CSVAbsTime;
+7
View File
@@ -97,6 +97,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbColorsByCanId">
<property name="text">
<string>Color rows by CAN ID</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbUseOpenGL">
<property name="text">
+69
View File
@@ -10,6 +10,8 @@
#include <QRect>
#include <QComboBox>
#include <QStandardItemModel>
#include <QColor>
#include <QString>
//#include <QDesktopWidget>
enum TimeStyle
@@ -20,6 +22,44 @@ enum TimeStyle
TS_CLOCK
};
// 32 dark, saturated colors — all designed for readability on white backgrounds.
// Minimum contrast ratio ≥ 4.5:1 against white (WCAG AA).
static constexpr std::array<QRgb, 32> kRowPalette = {{
0xFFC62828, // 0 Red 800
0xFFE53935, // 1 Red 600
0xFFD84315, // 2 Deep Orange 800
0xFFEF6C00, // 3 Orange 800
0xFFF9A825, // 4 Amber 800
0xFF558B2F, // 5 Green 800
0xFF2E7D32, // 6 Green 900
0xFF00695C, // 7 Teal 800
0xFF00838F, // 8 Cyan 800
0xFF0277BD, // 9 Blue 800
0xFF1565C0, // 10 Blue 900
0xFF283593, // 11 Indigo 900
0xFF4527A0, // 12 Deep Purple 800
0xFF6A1B9A, // 13 Purple 900
0xFF880E4F, // 14 Pink 900
0xFFAD1457, // 15 Pink 800
0xFF37474F, // 16 Blue Grey 800
0xFF4E342E, // 17 Brown 800
0xFF827717, // 18 Lime 900
0xFF1B5E20, // 19 Green 900 alt
0xFF006064, // 20 Cyan 900
0xFF01579B, // 21 Light Blue 900
0xFF0D47A1, // 22 Blue 900 alt
0xFF311B92, // 23 Deep Purple 900
0xFF4A148C, // 24 Purple 900 alt
0xFFB71C1C, // 25 Red 900
0xFFBF360C, // 26 Deep Orange 900
0xFFE65100, // 27 Orange 900
0xFF33691E, // 28 Light Green 900
0xFF004D40, // 29 Teal 900
0xFF263238, // 30 Blue Grey 900
0xFF5D4037, // 31 Brown 700
}};
class Utility
{
public:
@@ -344,6 +384,35 @@ public:
return result;
}
// FNV-1a 32-bit hash — fast, good distribution, no dependencies.
static quint32 hashString(const QString &s)
{
quint32 hash = 2166136261u;
for (const QChar ch : s) {
hash ^= static_cast<quint32>(ch.unicode());
hash *= 16777619u;
}
return hash;
}
// Returns a background QColor deterministically chosen from the palette.
// The same string always maps to the same color.
static QColor colorForString(const QString &s)
{
const quint32 idx = hashString(s) % static_cast<quint32>(kRowPalette.size());
// Use a light tint (alpha ~18%) as the row background so text stays readable.
QColor base(kRowPalette[idx]);
base.setAlpha(46); // ~18% — comfortable on white, still clearly tinted
return base;
}
// Opaque variant — useful for badges, tags, or legend swatches.
static QColor solidColorForString(const QString &s)
{
const quint32 idx = hashString(s) % static_cast<quint32>(kRowPalette.size());
return QColor(kRowPalette[idx]);
}
};
#endif // UTILITY_H