cabana: switch theme on the fly (#27855)

* switch theme on the fly

* better chart theme

* Darcula like dark theme

* add TODO

* use theme aware toolbutton in ChartView

* add margin to text title

* lighter activity colors

* fix historylog header

* replace hardcoded color

* improve chart tooltip color

* use macro

* space

* remove function toolbutton

* fix remove all btn

* remove menu arrow

* improve chart::removeIf

* cleanup charts
pull/27868/head
Dean Lee 2 years ago committed by GitHub
parent 2b32b07bbb
commit fc90814199
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 109
      tools/cabana/chartswidget.cc
  2. 14
      tools/cabana/chartswidget.h
  3. 6
      tools/cabana/detailwidget.cc
  4. 1
      tools/cabana/historylog.cc
  5. 1
      tools/cabana/mainwin.cc
  6. 25
      tools/cabana/settings.cc
  7. 3
      tools/cabana/settings.h
  8. 6
      tools/cabana/signalview.cc
  9. 73
      tools/cabana/util.cc
  10. 26
      tools/cabana/util.h
  11. 11
      tools/cabana/videowidget.cc

@ -37,8 +37,10 @@ ChartsWidget::ChartsWidget(QWidget *parent) : align_timer(this), auto_scroll_tim
int icon_size = style()->pixelMetric(QStyle::PM_SmallIconSize);
toolbar->setIconSize({icon_size, icon_size});
QAction *new_plot_btn = toolbar->addAction(utils::icon("file-plus"), tr("New Chart"));
QAction *new_tab_btn = toolbar->addAction(utils::icon("window-stack"), tr("New Tab"));
auto new_plot_btn = new ToolButton("file-plus", tr("New Chart"));
auto new_tab_btn = new ToolButton("window-stack", tr("New Tab"));
toolbar->addWidget(new_plot_btn);
toolbar->addWidget(new_tab_btn);
toolbar->addWidget(title_label = new QLabel());
title_label->setContentsMargins(0, 0, style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing), 0);
@ -65,18 +67,15 @@ ChartsWidget::ChartsWidget(QWidget *parent) : align_timer(this), auto_scroll_tim
// zoom controls
zoom_undo_stack = new QUndoStack(this);
undo_zoom_action = zoom_undo_stack->createUndoAction(this);
toolbar->addAction(undo_zoom_action = zoom_undo_stack->createUndoAction(this));
undo_zoom_action->setIcon(utils::icon("arrow-counterclockwise"));
toolbar->addAction(undo_zoom_action);
redo_zoom_action = zoom_undo_stack->createRedoAction(this);
toolbar->addAction(redo_zoom_action = zoom_undo_stack->createRedoAction(this));
redo_zoom_action->setIcon(utils::icon("arrow-clockwise"));
toolbar->addAction(redo_zoom_action);
reset_zoom_action = toolbar->addAction(utils::icon("zoom-out"), "");
reset_zoom_action->setToolTip(tr("Reset zoom"));
qobject_cast<QToolButton*>(toolbar->widgetForAction(reset_zoom_action))->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
reset_zoom_action = toolbar->addWidget(reset_zoom_btn = new ToolButton("zoom-out", tr("Reset Zoom")));
reset_zoom_btn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
remove_all_btn = toolbar->addAction(utils::icon("x"), tr("Remove all charts"));
dock_btn = toolbar->addAction("");
toolbar->addWidget(remove_all_btn = new ToolButton("x", tr("Remove all charts")));
toolbar->addWidget(dock_btn = new ToolButton(""));
main_layout->addWidget(toolbar);
// tabbar
@ -101,6 +100,7 @@ ChartsWidget::ChartsWidget(QWidget *parent) : align_timer(this), auto_scroll_tim
main_layout->addWidget(charts_scroll);
// init settings
current_theme = settings.theme;
column_count = std::clamp(settings.chart_column_count, 1, MAX_COLUMN_COUNT);
max_chart_range = std::clamp(settings.chart_range, 1, settings.max_cached_minutes * 60);
display_range = {0, max_chart_range};
@ -114,16 +114,16 @@ ChartsWidget::ChartsWidget(QWidget *parent) : align_timer(this), auto_scroll_tim
QObject::connect(can, &AbstractStream::eventsMerged, this, &ChartsWidget::eventsMerged);
QObject::connect(can, &AbstractStream::updated, this, &ChartsWidget::updateState);
QObject::connect(range_slider, &QSlider::valueChanged, this, &ChartsWidget::setMaxChartRange);
QObject::connect(new_plot_btn, &QAction::triggered, this, &ChartsWidget::newChart);
QObject::connect(remove_all_btn, &QAction::triggered, this, &ChartsWidget::removeAll);
QObject::connect(reset_zoom_action, &QAction::triggered, this, &ChartsWidget::zoomReset);
QObject::connect(new_plot_btn, &QToolButton::clicked, this, &ChartsWidget::newChart);
QObject::connect(remove_all_btn, &QToolButton::clicked, this, &ChartsWidget::removeAll);
QObject::connect(reset_zoom_btn, &QToolButton::clicked, this, &ChartsWidget::zoomReset);
QObject::connect(&settings, &Settings::changed, this, &ChartsWidget::settingChanged);
QObject::connect(new_tab_btn, &QAction::triggered, this, &ChartsWidget::newTab);
QObject::connect(new_tab_btn, &QToolButton::clicked, this, &ChartsWidget::newTab);
QObject::connect(tabbar, &QTabBar::tabCloseRequested, this, &ChartsWidget::removeTab);
QObject::connect(tabbar, &QTabBar::currentChanged, [this](int index) {
if (index != -1) updateLayout(true);
});
QObject::connect(dock_btn, &QAction::triggered, [this]() {
QObject::connect(dock_btn, &QToolButton::clicked, [this]() {
emit dock(!docking);
docking = !docking;
updateToolBar();
@ -170,10 +170,6 @@ void ChartsWidget::setZoom(double min, double max) {
emit rangeChanged(min, max, is_zoomed);
}
void ChartsWidget::zoomIn(double min, double max) {
zoom_undo_stack->push(new ZoomCommand(this, {min, max}));
}
void ChartsWidget::zoomReset() {
setZoom(display_range.first, display_range.second);
zoom_undo_stack->clear();
@ -228,17 +224,26 @@ void ChartsWidget::updateToolBar() {
undo_zoom_action->setVisible(is_zoomed);
redo_zoom_action->setVisible(is_zoomed);
reset_zoom_action->setVisible(is_zoomed);
reset_zoom_action->setText(is_zoomed ? tr("%1-%2").arg(zoomed_range.first, 0, 'f', 1).arg(zoomed_range.second, 0, 'f', 1) : "");
reset_zoom_btn->setText(is_zoomed ? tr("%1-%2").arg(zoomed_range.first, 0, 'f', 1).arg(zoomed_range.second, 0, 'f', 1) : "");
remove_all_btn->setEnabled(!charts.isEmpty());
dock_btn->setIcon(utils::icon(docking ? "arrow-up-right-square" : "arrow-down-left-square"));
dock_btn->setIcon(docking ? "arrow-up-right-square" : "arrow-down-left-square");
dock_btn->setToolTip(docking ? tr("Undock charts") : tr("Dock charts"));
}
void ChartsWidget::settingChanged() {
if (std::exchange(current_theme, settings.theme) != current_theme) {
undo_zoom_action->setIcon(utils::icon("arrow-counterclockwise"));
redo_zoom_action->setIcon(utils::icon("arrow-clockwise"));
auto theme = settings.theme == DARK_THEME ? QChart::QChart::ChartThemeDark : QChart::ChartThemeLight;
for (auto c : charts) {
c->setTheme(theme);
}
}
range_slider->setRange(1, settings.max_cached_minutes * 60);
for (auto c : charts) {
c->setFixedHeight(settings.chart_height);
c->setSeriesType((SeriesType)settings.chart_series_type);
c->resetChartCache();
}
}
@ -253,14 +258,7 @@ ChartView *ChartsWidget::createChart() {
chart->setFixedHeight(settings.chart_height);
chart->setMinimumWidth(CHART_MIN_WIDTH);
chart->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
chart->chart()->setTheme(settings.theme == 2 ? QChart::QChart::ChartThemeDark : QChart::ChartThemeLight);
QObject::connect(chart, &ChartView::remove, [=]() { removeChart(chart); });
QObject::connect(chart, &ChartView::zoomIn, this, &ChartsWidget::zoomIn);
QObject::connect(chart, &ChartView::zoomUndo, undo_zoom_action, &QAction::trigger);
QObject::connect(chart, &ChartView::seriesRemoved, this, &ChartsWidget::seriesChanged);
QObject::connect(chart, &ChartView::seriesAdded, this, &ChartsWidget::seriesChanged);
QObject::connect(chart, &ChartView::axisYLabelWidthChanged, &align_timer, qOverload<>(&QTimer::start));
QObject::connect(chart, &ChartView::hovered, this, &ChartsWidget::showValueTip);
charts.push_front(chart);
currentCharts().push_front(chart);
updateLayout(true);
@ -408,7 +406,7 @@ void ChartsWidget::alignCharts() {
bool ChartsWidget::eventFilter(QObject *obj, QEvent *event) {
if (obj != this && event->type() == QEvent::Close) {
emit dock_btn->triggered();
emit dock_btn->clicked();
return true;
}
return false;
@ -439,7 +437,7 @@ bool ChartsWidget::event(QEvent *event) {
}
if (back_button) {
emit undo_zoom_action->triggered();
zoom_undo_stack->undo();
return true;
}
return QFrame::event(event);
@ -466,6 +464,7 @@ ChartView::ChartView(const std::pair<double, double> &x_range, ChartsWidget *par
// TODO: enable zoomIn/seekTo in live streaming mode.
setRubberBand(can->liveStreaming() ? QChartView::NoRubberBand : QChartView::HorizontalRubberBand);
setMouseTracking(true);
setTheme(settings.theme == DARK_THEME ? QChart::QChart::ChartThemeDark : QChart::ChartThemeLight);
QObject::connect(axis_y, &QValueAxis::rangeChanged, [this]() { resetChartCache(); });
QObject::connect(axis_y, &QAbstractAxis::titleTextChanged, [this]() { resetChartCache(); });
@ -480,7 +479,7 @@ void ChartView::createToolButtons() {
move_icon = new QGraphicsPixmapItem(utils::icon("grip-horizontal"), chart());
move_icon->setToolTip(tr("Drag and drop to move chart"));
QToolButton *remove_btn = toolButton("x", tr("Remove Chart"));
QToolButton *remove_btn = new ToolButton("x", tr("Remove Chart"));
close_btn_proxy = new QGraphicsProxyWidget(chart());
close_btn_proxy->setWidget(remove_btn);
close_btn_proxy->setZValue(chart()->zValue() + 11);
@ -500,19 +499,34 @@ void ChartView::createToolButtons() {
menu->addSeparator();
menu->addAction(tr("Manage series"), this, &ChartView::manageSeries);
QToolButton *manage_btn = toolButton("list", "");
QToolButton *manage_btn = new ToolButton("list", "");
manage_btn->setMenu(menu);
manage_btn->setPopupMode(QToolButton::InstantPopup);
manage_btn->setStyleSheet("QToolButton::menu-indicator { image: none; }");
manage_btn_proxy = new QGraphicsProxyWidget(chart());
manage_btn_proxy->setWidget(manage_btn);
manage_btn_proxy->setZValue(chart()->zValue() + 11);
QObject::connect(remove_btn, &QToolButton::clicked, this, &ChartView::remove);
QObject::connect(remove_btn, &QToolButton::clicked, [this]() { charts_widget->removeChart(this); });
QObject::connect(change_series_group, &QActionGroup::triggered, [this](QAction *action) {
setSeriesType((SeriesType)action->data().toInt());
});
}
void ChartView::setTheme(QChart::ChartTheme theme) {
chart()->setTheme(theme);
if (theme == QChart::ChartThemeDark) {
axis_x->setTitleBrush(palette().color(QPalette::Text));
axis_x->setLabelsBrush(palette().color(QPalette::Text));
axis_y->setTitleBrush(palette().color(QPalette::Text));
axis_y->setLabelsBrush(palette().color(QPalette::Text));
chart()->legend()->setLabelColor(palette().color(QPalette::Text));
}
for (auto &s : sigs) {
s.series->setColor(getColor(s.sig));
}
}
void ChartView::addSeries(const MessageId &msg_id, const cabana::Signal *sig) {
if (hasSeries(msg_id, sig)) return;
@ -521,7 +535,7 @@ void ChartView::addSeries(const MessageId &msg_id, const cabana::Signal *sig) {
updateTitle();
updateSeries(sig);
updateSeriesPoints();
emit seriesAdded(msg_id, sig);
emit charts_widget->seriesChanged();
}
bool ChartView::hasSeries(const MessageId &msg_id, const cabana::Signal *sig) const {
@ -534,17 +548,15 @@ void ChartView::removeIf(std::function<bool(const SigItem &s)> predicate) {
if (predicate(*it)) {
chart()->removeSeries(it->series);
it->series->deleteLater();
auto msg_id = it->msg_id;
auto sig = it->sig;
it = sigs.erase(it);
emit seriesRemoved(msg_id, sig);
} else {
++it;
}
}
if (sigs.empty()) {
emit remove();
charts_widget->removeChart(this);
} else if (sigs.size() != prev_size) {
emit charts_widget->seriesChanged();
updateAxisY();
resetChartCache();
}
@ -781,7 +793,7 @@ qreal ChartView::niceNumber(qreal x, bool ceiling) {
void ChartView::leaveEvent(QEvent *event) {
if (tip_label.isVisible()) {
emit hovered(-1);
charts_widget->showValueTip(-1);
}
QChartView::leaveEvent(event);
}
@ -863,13 +875,13 @@ void ChartView::mouseReleaseEvent(QMouseEvent *event) {
// no rubber dragged, seek to mouse position
can->seekTo(min);
} else if (rubber->width() > 10) {
emit zoomIn(min, max);
charts_widget->zoom_undo_stack->push(new ZoomCommand(charts_widget, {min, max}));
} else {
viewport()->update();
}
event->accept();
} else if (!can->liveStreaming() && event->button() == Qt::RightButton) {
emit zoomUndo();
charts_widget->zoom_undo_stack->undo();
event->accept();
} else {
QGraphicsView::mouseReleaseEvent(event);
@ -898,9 +910,9 @@ void ChartView::mouseMoveEvent(QMouseEvent *ev) {
if (!is_zooming && plot_area.contains(ev->pos())) {
const double sec = chart()->mapToValue(ev->pos()).x();
emit hovered(sec);
charts_widget->showValueTip(sec);
} else if (tip_label.isVisible()) {
emit hovered(-1);
charts_widget->showValueTip(-1);
}
QChartView::mouseMoveEvent(ev);
@ -979,7 +991,7 @@ void ChartView::dropEvent(QDropEvent *event) {
updateTitle();
source_chart->sigs.clear();
emit source_chart->remove();
charts_widget->removeChart(source_chart);
event->acceptProposedAction();
}
can_drop = false;
@ -1244,7 +1256,12 @@ QList<SeriesSelector::ListItem *> SeriesSelector::seletedItems() {
ValueTipLabel::ValueTipLabel(QWidget *parent) : QLabel(parent, Qt::ToolTip | Qt::FramelessWindowHint) {
setForegroundRole(QPalette::ToolTipText);
setBackgroundRole(QPalette::ToolTipBase);
setPalette(QToolTip::palette());
auto palette = QToolTip::palette();
if (settings.theme != DARK_THEME) {
palette.setColor(QPalette::ToolTipBase, QApplication::palette().color(QPalette::Base));
palette.setColor(QPalette::ToolTipText, QRgb(0x404044)); // same color as chart label brush
}
setPalette(palette);
ensurePolished();
setMargin(1 + style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, nullptr, this));
setAttribute(Qt::WA_ShowWithoutActivating);

@ -63,13 +63,7 @@ public:
};
signals:
void seriesRemoved(const MessageId &id, const cabana::Signal *sig);
void seriesAdded(const MessageId &id, const cabana::Signal *sig);
void zoomIn(double min, double max);
void zoomUndo();
void remove();
void axisYLabelWidthChanged(int w);
void hovered(double sec);
private slots:
void signalUpdated(const cabana::Signal *sig);
@ -94,6 +88,7 @@ private:
void updateAxisY();
void updateTitle();
void resetChartCache();
void setTheme(QChart::ChartTheme theme);
void paintEvent(QPaintEvent *event) override;
void drawForeground(QPainter *painter, const QRectF &rect) override;
void drawBackground(QPainter *painter, const QRectF &rect) override;
@ -167,7 +162,6 @@ private:
void removeChart(ChartView *chart);
void eventsMerged();
void updateState();
void zoomIn(double min, double max);
void zoomReset();
void startAutoScroll();
void stopAutoScroll();
@ -189,14 +183,15 @@ private:
QAction *range_lb_action;
QAction *range_slider_action;
bool docking = true;
QAction *dock_btn;
ToolButton *dock_btn;
QAction *undo_zoom_action;
QAction *redo_zoom_action;
QAction *reset_zoom_action;
ToolButton *reset_zoom_btn;
QUndoStack *zoom_undo_stack;
QAction *remove_all_btn;
ToolButton *remove_all_btn;
QList<ChartView *> charts;
std::unordered_map<int, QList<ChartView *>> tab_charts;
QTabBar *tabbar;
@ -212,6 +207,7 @@ private:
int auto_scroll_count = 0;
QTimer auto_scroll_timer;
QTimer align_timer;
int current_theme = 0;
friend class ZoomCommand;
friend class ChartView;
friend class ChartsContainer;

@ -22,7 +22,7 @@ DetailWidget::DetailWidget(ChartsWidget *charts, QWidget *parent) : charts(chart
// message title
QHBoxLayout *title_layout = new QHBoxLayout();
title_layout->setContentsMargins(0, 6, 0, 0);
title_layout->setContentsMargins(3, 6, 3, 0);
time_label = new QLabel(this);
time_label->setToolTip(tr("Current time"));
time_label->setStyleSheet("QLabel{font-weight:bold;}");
@ -32,9 +32,9 @@ DetailWidget::DetailWidget(ChartsWidget *charts, QWidget *parent) : charts(chart
name_label->setAlignment(Qt::AlignCenter);
name_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
title_layout->addWidget(name_label);
auto edit_btn = toolButton("pencil", tr("Edit Message"));
auto edit_btn = new ToolButton("pencil", tr("Edit Message"));
title_layout->addWidget(edit_btn);
remove_btn = toolButton("x-lg", tr("Remove Message"));
remove_btn = new ToolButton("x-lg", tr("Remove Message"));
title_layout->addWidget(remove_btn);
main_layout->addLayout(title_layout);

@ -186,6 +186,7 @@ void HeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalI
painter->fillRect(rect, bg_role.value<QBrush>());
}
QString text = model()->headerData(logicalIndex, Qt::Horizontal, Qt::DisplayRole).toString();
painter->setPen(palette().color(settings.theme == DARK_THEME ? QPalette::BrightText : QPalette::Text));
painter->drawText(rect.adjusted(5, 3, -5, -3), defaultAlignment(), text.replace(QChar('_'), ' '));
}

@ -541,7 +541,6 @@ void MainWindow::updateDownloadProgress(uint64_t cur, uint64_t total, bool succe
void MainWindow::updateStatus() {
status_label->setText(tr("Cached Minutes:%1 FPS:%2").arg(settings.max_cached_minutes).arg(settings.fps));
utils::setTheme(settings.theme);
}
void MainWindow::dockCharts(bool dock) {

@ -1,11 +1,13 @@
#include "tools/cabana/settings.h"
#include <QAbstractButton>
#include <QDialogButtonBox>
#include <QDir>
#include <QFormLayout>
#include <QSettings>
// Settings
#include "tools/cabana/util.h"
Settings settings;
Settings::Settings() {
@ -85,21 +87,32 @@ SettingsDlg::SettingsDlg(QWidget *parent) : QDialog(parent) {
chart_height->setValue(settings.chart_height);
form_layout->addRow(tr("Chart Height"), chart_height);
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply);
form_layout->addRow(buttonBox);
setFixedWidth(360);
connect(buttonBox, &QDialogButtonBox::accepted, this, &SettingsDlg::save);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(buttonBox, &QDialogButtonBox::clicked, [=](QAbstractButton *button) {
auto role = buttonBox->buttonRole(button);
if (role == QDialogButtonBox::AcceptRole) {
save();
accept();
} else if (role == QDialogButtonBox::ApplyRole) {
save();
} else if (role == QDialogButtonBox::RejectRole) {
reject();
}
});
}
void SettingsDlg::save() {
settings.fps = fps->value();
settings.theme = theme->currentIndex();
if (std::exchange(settings.theme, theme->currentIndex()) != settings.theme) {
// set theme before emit changed
utils::setTheme(settings.theme);
}
settings.max_cached_minutes = cached_minutes->value();
settings.chart_series_type = chart_series_type->currentIndex();
settings.chart_height = chart_height->value();
settings.save();
accept();
emit settings.changed();
}

@ -5,6 +5,9 @@
#include <QDialog>
#include <QSpinBox>
#define LIGHT_THEME 1
#define DARK_THEME 2
class Settings : public QObject {
Q_OBJECT

@ -525,7 +525,7 @@ SignalView::SignalView(ChartsWidget *charts, QWidget *parent) : charts(charts),
sparkline_range_slider->setValue(settings.sparkline_range);
sparkline_range_slider->setToolTip(tr("Sparkline time range"));
auto collapse_btn = toolButton("dash-square", tr("Collapse All"));
auto collapse_btn = new ToolButton("dash-square", tr("Collapse All"));
collapse_btn->setIconSize({12, 12});
hl->addWidget(collapse_btn);
@ -582,8 +582,8 @@ void SignalView::rowsChanged() {
h->setContentsMargins(0, v_margin, -h_margin, v_margin);
h->setSpacing(style()->pixelMetric(QStyle::PM_ToolBarItemSpacing));
auto remove_btn = toolButton("x", tr("Remove signal"));
auto plot_btn = toolButton("graph-up", "");
auto remove_btn = new ToolButton("x", tr("Remove signal"));
auto plot_btn = new ToolButton("graph-up", "");
plot_btn->setCheckable(true);
h->addWidget(plot_btn);
h->addWidget(remove_btn);

@ -8,9 +8,8 @@
#include <limits>
#include "selfdrive/ui/qt/util.h"
#include "tools/cabana/settings.h"
static QColor blend(QColor a, QColor b) {
static inline QColor blend(const QColor &a, const QColor &b) {
return QColor((a.red() + b.red()) / 2, (a.green() + b.green()) / 2, (a.blue() + b.blue()) / 2, (a.alpha() + b.alpha()) / 2);
}
@ -22,6 +21,11 @@ void ChangeTracker::compute(const QByteArray &dat, double ts, uint32_t freq) {
std::fill(colors.begin(), colors.end(), QColor(0, 0, 0, 0));
std::fill(last_change_t.begin(), last_change_t.end(), ts);
} else {
int factor = settings.theme == DARK_THEME ? 135 : 0;
QColor cyan = QColor(0, 187, 255, start_alpha).lighter(factor);
QColor red = QColor(255, 0, 0, start_alpha).lighter(factor);
QColor greyish_blue = QColor(102, 86, 169, start_alpha / 2).lighter(factor);
for (int i = 0; i < dat.size(); ++i) {
const uint8_t last = prev_dat[i];
const uint8_t cur = dat[i];
@ -30,14 +34,10 @@ void ChangeTracker::compute(const QByteArray &dat, double ts, uint32_t freq) {
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
}
colors[i] = (cur > last) ? cyan : red;
} else {
// Periodic changes
colors[i] = blend(colors[i], QColor(102, 86, 169, start_alpha / 2)); // Greyish/Blue
colors[i] = blend(colors[i], greyish_blue);
}
// Track bit level changes
@ -146,7 +146,7 @@ QValidator::State NameValidator::validate(QString &input, int &pos) const {
namespace utils {
QPixmap icon(const QString &id) {
bool dark_theme = settings.theme == 2;
bool dark_theme = settings.theme == DARK_THEME;
QPixmap pm;
QString key = "bootstrap_" % id % (dark_theme ? "1" : "0");
if (!QPixmapCache::find(key, &pm)) {
@ -154,7 +154,7 @@ QPixmap icon(const QString &id) {
if (dark_theme) {
QPainter p(&pm);
p.setCompositionMode(QPainter::CompositionMode_SourceIn);
p.fillRect(pm.rect(), Qt::white);
p.fillRect(pm.rect(), QColor("#bbbbbb"));
}
QPixmapCache::insert(key, pm);
}
@ -168,42 +168,39 @@ void setTheme(int theme) {
static int prev_theme = 0;
if (theme != prev_theme) {
prev_theme = theme;
if (theme == 2) {
// modify palette to dark
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, QColor(53, 53, 53));
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, QColor(25, 25, 25));
darkPalette.setColor(QPalette::AlternateBase, QColor(53, 53, 53));
darkPalette.setColor(QPalette::ToolTipBase, Qt::white);
darkPalette.setColor(QPalette::ToolTipText, QColor(41, 41, 41));
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, QColor(53, 53, 53));
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::BrightText, Qt::red);
darkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
darkPalette.setColor(QPalette::HighlightedText, Qt::black);
qApp->setPalette(darkPalette);
QPalette new_palette;
if (theme == DARK_THEME) {
// "Darcula" like dark theme
new_palette.setColor(QPalette::Window, QColor("#353535"));
new_palette.setColor(QPalette::WindowText, QColor("#bbbbbb"));
new_palette.setColor(QPalette::Base, QColor("#3c3f41"));
new_palette.setColor(QPalette::AlternateBase, QColor("#3c3f41"));
new_palette.setColor(QPalette::ToolTipBase, QColor("#3c3f41"));
new_palette.setColor(QPalette::ToolTipText, QColor("#bbb"));
new_palette.setColor(QPalette::Text, QColor("#bbbbbb"));
new_palette.setColor(QPalette::Button, QColor("#3c3f41"));
new_palette.setColor(QPalette::ButtonText, QColor("#bbbbbb"));
new_palette.setColor(QPalette::Highlight, QColor("#2f65ca"));
new_palette.setColor(QPalette::HighlightedText, QColor("#bbbbbb"));
new_palette.setColor(QPalette::BrightText, QColor("#f0f0f0"));
new_palette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor("#777777"));
new_palette.setColor(QPalette::Disabled, QPalette::WindowText, QColor("#777777"));
new_palette.setColor(QPalette::Disabled, QPalette::Text, QColor("#777777"));;
new_palette.setColor(QPalette::Light, QColor("#3c3f41"));
new_palette.setColor(QPalette::Dark, QColor("#353535"));
} else {
qApp->setPalette(style->standardPalette());
new_palette = style->standardPalette();
}
qApp->setPalette(new_palette);
style->polish(qApp);
for (auto w : QApplication::allWidgets()) {
w->setPalette(new_palette);
}
}
}
} // namespace utils
QToolButton *toolButton(const QString &icon, const QString &tooltip) {
auto btn = new QToolButton();
btn->setIcon(utils::icon(icon));
btn->setToolTip(tooltip);
btn->setAutoRaise(true);
const int metric = qApp->style()->pixelMetric(QStyle::PM_SmallIconSize);
btn->setIconSize({metric, metric});
return btn;
};
QString toHex(uint8_t byte) {
static std::array<QString, 256> hex = []() {
std::array<QString, 256> ret;

@ -3,6 +3,7 @@
#include <array>
#include <cmath>
#include <QApplication>
#include <QByteArray>
#include <QDateTime>
#include <QColor>
@ -14,6 +15,7 @@
#include <QVector>
#include "tools/cabana/dbc/dbc.h"
#include "tools/cabana/settings.h"
class ChangeTracker {
public:
@ -104,5 +106,27 @@ inline QString formatSeconds(int seconds) {
}
}
QToolButton *toolButton(const QString &icon, const QString &tooltip);
class ToolButton : public QToolButton {
Q_OBJECT
public:
ToolButton(const QString &icon, const QString &tooltip = {}, QWidget *parent = nullptr) : QToolButton(parent) {
setIcon(icon);
setToolTip(tooltip);
setAutoRaise(true);
const int metric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
setIconSize({metric, metric});
theme = settings.theme;
connect(&settings, &Settings::changed, this, &ToolButton::updateIcon);
}
void setIcon(const QString &icon) {
icon_str = icon;
QToolButton::setIcon(utils::icon(icon_str));
}
private:
void updateIcon() { if (std::exchange(theme, settings.theme) != theme) setIcon(icon_str); }
QString icon_str;
int theme;
};
int num_decimals(double num);

@ -63,6 +63,7 @@ VideoWidget::VideoWidget(QWidget *parent) : QFrame(parent) {
QObject::connect(play_btn, &QPushButton::clicked, []() { can->pause(!can->isPaused()); });
QObject::connect(can, &AbstractStream::paused, this, &VideoWidget::updatePlayBtnState);
QObject::connect(can, &AbstractStream::resume, this, &VideoWidget::updatePlayBtnState);
QObject::connect(&settings, &Settings::changed, this, &VideoWidget::updatePlayBtnState);
updatePlayBtnState();
setWhatsThis(tr(R"(
@ -303,7 +304,7 @@ void InfoLabel::showAlert(const AlertInfo &alert) {
void InfoLabel::paintEvent(QPaintEvent *event) {
QPainter p(this);
p.setPen(QPen(Qt::white, 2));
p.setPen(QPen(palette().color(QPalette::BrightText), 2));
if (!pixmap.isNull()) {
p.drawPixmap(0, 0, pixmap);
p.drawRect(rect());
@ -322,9 +323,11 @@ void InfoLabel::paintEvent(QPaintEvent *event) {
text += "\n" + alert_info.text2;
}
QFont font;
font.setPixelSize(!pixmap.isNull() ? 11 : QFont().pixelSize());
p.setFont(font);
if (!pixmap.isNull()) {
QFont font;
font.setPixelSize(11);
p.setFont(font);
}
QRect text_rect = rect().adjusted(2, 2, -2, -2);
QRect r = p.fontMetrics().boundingRect(text_rect, Qt::AlignTop | Qt::AlignHCenter | Qt::TextWordWrap, text);
p.fillRect(text_rect.left(), r.top(), text_rect.width(), r.height(), color);

Loading…
Cancel
Save