mirror of
https://github.com/dragonpilot/dragonpilot.git
synced 2026-06-20 21:42:05 +08:00
cabana: add support for multiple columns charts (#27000)
This commit is contained in:
@@ -22,9 +22,19 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) {
|
||||
// toolbar
|
||||
QToolBar *toolbar = new QToolBar(tr("Charts"), this);
|
||||
toolbar->setIconSize({16, 16});
|
||||
title_label = new QLabel();
|
||||
title_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
toolbar->addWidget(title_label);
|
||||
|
||||
toolbar->addWidget(title_label = new QLabel());
|
||||
title_label->setContentsMargins(0 ,0, 12, 0);
|
||||
columns_cb = new QComboBox(this);
|
||||
columns_cb->addItems({"1", "2", "3", "4"});
|
||||
columns_cb->setCurrentIndex(std::clamp(settings.chart_column_count - 1, 0, 3));
|
||||
toolbar->addWidget(new QLabel(tr("Columns:")));
|
||||
toolbar->addWidget(columns_cb);
|
||||
|
||||
QLabel *stretch_label = new QLabel(this);
|
||||
stretch_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
toolbar->addWidget(stretch_label);
|
||||
|
||||
show_all_values_btn = toolbar->addAction("");
|
||||
toolbar->addWidget(range_label = new QLabel());
|
||||
reset_zoom_btn = toolbar->addAction(bootstrapPixmap("arrow-counterclockwise"), "");
|
||||
@@ -36,8 +46,11 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) {
|
||||
|
||||
// charts
|
||||
QWidget *charts_container = new QWidget(this);
|
||||
charts_layout = new QVBoxLayout(charts_container);
|
||||
charts_layout->addStretch();
|
||||
QVBoxLayout *charts_main_layout = new QVBoxLayout(charts_container);
|
||||
charts_main_layout->setContentsMargins(0, 0, 0, 0);
|
||||
charts_layout = new QGridLayout(charts_container);
|
||||
charts_main_layout->addLayout(charts_layout);
|
||||
charts_main_layout->addStretch(0);
|
||||
|
||||
QScrollArea *charts_scroll = new QScrollArea(this);
|
||||
charts_scroll->setWidgetResizable(true);
|
||||
@@ -53,6 +66,7 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) {
|
||||
align_charts_timer = new QTimer(this);
|
||||
align_charts_timer->setSingleShot(true);
|
||||
align_charts_timer->callOnTimeout(this, &ChartsWidget::alignCharts);
|
||||
column_count = settings.chart_column_count;
|
||||
|
||||
QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &ChartsWidget::removeAll);
|
||||
QObject::connect(can, &CANMessages::eventsMerged, this, &ChartsWidget::eventsMerged);
|
||||
@@ -60,6 +74,8 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) {
|
||||
QObject::connect(show_all_values_btn, &QAction::triggered, this, &ChartsWidget::showAllData);
|
||||
QObject::connect(remove_all_btn, &QAction::triggered, this, &ChartsWidget::removeAll);
|
||||
QObject::connect(reset_zoom_btn, &QAction::triggered, this, &ChartsWidget::zoomReset);
|
||||
QObject::connect(columns_cb, SIGNAL(activated(int)), SLOT(setColumnCount(int)));
|
||||
QObject::connect(&settings, &Settings::changed, this, &ChartsWidget::settingChanged);
|
||||
QObject::connect(dock_btn, &QAction::triggered, [this]() {
|
||||
emit dock(!docking);
|
||||
docking = !docking;
|
||||
@@ -144,6 +160,14 @@ void ChartsWidget::updateToolBar() {
|
||||
dock_btn->setToolTip(docking ? tr("Undock charts") : tr("Dock charts"));
|
||||
}
|
||||
|
||||
void ChartsWidget::settingChanged() {
|
||||
for (auto c : charts) {
|
||||
c->setFixedHeight(settings.chart_height);
|
||||
columns_cb->setCurrentIndex(std::clamp(settings.chart_column_count - 1, 0, columns_cb->count() - 1));
|
||||
setColumnCount(settings.chart_column_count);
|
||||
}
|
||||
}
|
||||
|
||||
ChartView *ChartsWidget::findChart(const QString &id, const Signal *sig) {
|
||||
for (auto c : charts)
|
||||
if (c->hasSeries(id, sig)) return c;
|
||||
@@ -157,6 +181,9 @@ void ChartsWidget::showChart(const QString &id, const Signal *sig, bool show, bo
|
||||
chart = merge && charts.size() > 0 ? charts.back() : nullptr;
|
||||
if (!chart) {
|
||||
chart = new ChartView(this);
|
||||
chart->setFixedHeight(settings.chart_height);
|
||||
chart->setMinimumWidth(CHART_MIN_WIDTH);
|
||||
chart->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
||||
chart->chart()->setTheme(use_dark_theme ? QChart::QChart::ChartThemeDark : QChart::ChartThemeLight);
|
||||
chart->setEventsRange(display_range);
|
||||
auto range = is_zoomed ? zoomed_range : display_range;
|
||||
@@ -167,8 +194,8 @@ void ChartsWidget::showChart(const QString &id, const Signal *sig, bool show, bo
|
||||
QObject::connect(chart, &ChartView::seriesRemoved, this, &ChartsWidget::seriesChanged);
|
||||
QObject::connect(chart, &ChartView::seriesAdded, this, &ChartsWidget::seriesChanged);
|
||||
QObject::connect(chart, &ChartView::axisYUpdated, [this]() { align_charts_timer->start(100); });
|
||||
charts_layout->insertWidget(0, chart);
|
||||
charts.push_back(chart);
|
||||
updateLayout();
|
||||
}
|
||||
chart->addSeries(id, sig);
|
||||
} else if (!show && chart) {
|
||||
@@ -178,6 +205,29 @@ void ChartsWidget::showChart(const QString &id, const Signal *sig, bool show, bo
|
||||
setUpdatesEnabled(true);
|
||||
}
|
||||
|
||||
void ChartsWidget::setColumnCount(int n) {
|
||||
n = std::clamp(n + 1, 1, columns_cb->count());
|
||||
if (column_count != n) {
|
||||
column_count = n;
|
||||
updateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
void ChartsWidget::updateLayout() {
|
||||
int n = column_count;
|
||||
for (; n >= 1; --n) {
|
||||
if ((n * (CHART_MIN_WIDTH + charts_layout->spacing())) < rect().width()) break;
|
||||
}
|
||||
for (int i = 0; i < charts.size(); ++i) {
|
||||
charts_layout->addWidget(charts[i], i / n, i % n);
|
||||
}
|
||||
}
|
||||
|
||||
void ChartsWidget::resizeEvent(QResizeEvent *event) {
|
||||
QWidget::resizeEvent(event);
|
||||
updateLayout();
|
||||
}
|
||||
|
||||
void ChartsWidget::removeChart(ChartView *chart) {
|
||||
charts.removeOne(chart);
|
||||
chart->deleteLater();
|
||||
@@ -244,13 +294,11 @@ ChartView::ChartView(QWidget *parent) : QChartView(nullptr, parent) {
|
||||
setChart(chart);
|
||||
setRenderHint(QPainter::Antialiasing);
|
||||
setRubberBand(QChartView::HorizontalRubberBand);
|
||||
updateFromSettings();
|
||||
|
||||
QObject::connect(dbc(), &DBCManager::signalRemoved, this, &ChartView::signalRemoved);
|
||||
QObject::connect(dbc(), &DBCManager::signalUpdated, this, &ChartView::signalUpdated);
|
||||
QObject::connect(dbc(), &DBCManager::msgRemoved, this, &ChartView::msgRemoved);
|
||||
QObject::connect(dbc(), &DBCManager::msgUpdated, this, &ChartView::msgUpdated);
|
||||
QObject::connect(&settings, &Settings::changed, this, &ChartView::updateFromSettings);
|
||||
QObject::connect(remove_btn, &QToolButton::clicked, this, &ChartView::remove);
|
||||
QObject::connect(manage_btn, &QToolButton::clicked, this, &ChartView::manageSeries);
|
||||
}
|
||||
@@ -386,10 +434,6 @@ void ChartView::updateTitle() {
|
||||
}
|
||||
}
|
||||
|
||||
void ChartView::updateFromSettings() {
|
||||
setFixedHeight(settings.chart_height);
|
||||
}
|
||||
|
||||
void ChartView::setEventsRange(const std::pair<double, double> &range) {
|
||||
if (range != events_range) {
|
||||
events_range = range;
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
#include <QComboBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QDragEnterEvent>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QListWidget>
|
||||
#include <QGraphicsProxyWidget>
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
#include <QtCharts/QChartView>
|
||||
#include <QtCharts/QLineSeries>
|
||||
#include <QtCharts/QValueAxis>
|
||||
@@ -68,7 +68,6 @@ private:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
void updateAxisY();
|
||||
void updateTitle();
|
||||
void updateFromSettings();
|
||||
void drawForeground(QPainter *painter, const QRectF &rect) override;
|
||||
void applyNiceNumbers(qreal min, qreal max);
|
||||
qreal niceNumber(qreal x, bool ceiling);
|
||||
@@ -92,12 +91,16 @@ public:
|
||||
void showChart(const QString &id, const Signal *sig, bool show, bool merge);
|
||||
inline bool hasSignal(const QString &id, const Signal *sig) { return findChart(id, sig) != nullptr; }
|
||||
|
||||
public slots:
|
||||
void setColumnCount(int n);
|
||||
|
||||
signals:
|
||||
void dock(bool floating);
|
||||
void rangeChanged(double min, double max, bool is_zommed);
|
||||
void seriesChanged();
|
||||
|
||||
private:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
void alignCharts();
|
||||
void removeChart(ChartView *chart);
|
||||
void eventsMerged();
|
||||
@@ -108,6 +111,8 @@ private:
|
||||
void updateToolBar();
|
||||
void removeAll();
|
||||
void showAllData();
|
||||
void updateLayout();
|
||||
void settingChanged();
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
ChartView *findChart(const QString &id, const Signal *sig);
|
||||
|
||||
@@ -119,7 +124,7 @@ private:
|
||||
QAction *reset_zoom_btn;
|
||||
QAction *remove_all_btn;
|
||||
QTimer *align_charts_timer;
|
||||
QVBoxLayout *charts_layout;
|
||||
QGridLayout *charts_layout;
|
||||
QList<ChartView *> charts;
|
||||
uint32_t max_chart_range = 0;
|
||||
bool is_zoomed = false;
|
||||
@@ -127,6 +132,9 @@ private:
|
||||
std::pair<double, double> display_range;
|
||||
std::pair<double, double> zoomed_range;
|
||||
bool use_dark_theme = false;
|
||||
QComboBox *columns_cb;
|
||||
int column_count = 1;
|
||||
const int CHART_MIN_WIDTH = 300;
|
||||
};
|
||||
|
||||
class SeriesSelector : public QDialog {
|
||||
|
||||
@@ -18,6 +18,7 @@ void Settings::save() {
|
||||
s.setValue("cached_segment", cached_segment_limit);
|
||||
s.setValue("chart_height", chart_height);
|
||||
s.setValue("max_chart_x_range", max_chart_x_range);
|
||||
s.setValue("chart_column_count", chart_column_count);
|
||||
s.setValue("last_dir", last_dir);
|
||||
s.setValue("window_state", window_state);
|
||||
s.setValue("geometry", geometry);
|
||||
@@ -30,6 +31,7 @@ void Settings::load() {
|
||||
cached_segment_limit = s.value("cached_segment", 3).toInt();
|
||||
chart_height = s.value("chart_height", 200).toInt();
|
||||
max_chart_x_range = s.value("max_chart_x_range", 3 * 60).toInt();
|
||||
chart_column_count = s.value("chart_column_count", 1).toInt();
|
||||
last_dir = s.value("last_dir", QDir::homePath()).toString();
|
||||
window_state = s.value("window_state").toByteArray();
|
||||
geometry = s.value("geometry").toByteArray();
|
||||
|
||||
@@ -16,6 +16,7 @@ public:
|
||||
int fps = 10;
|
||||
int cached_segment_limit = 3;
|
||||
int chart_height = 200;
|
||||
int chart_column_count = 1;
|
||||
int max_chart_x_range = 3 * 60; // 3 minutes
|
||||
QString last_dir;
|
||||
QByteArray geometry;
|
||||
|
||||
Reference in New Issue
Block a user