mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-06-28 01:52:06 +08:00
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 old-commit-hash: fc90814199d10b4419574f0e5a01102ec55c9cdb
This commit is contained in:
@@ -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);
|
||||
|
||||
+35
-38
@@ -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;
|
||||
|
||||
+25
-1
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user