mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-06-28 01:52:06 +08:00
cabana: support undo/redo zoom (#27799)
* support updo/redo zoom * cleanup eventsMerged * init axis_x when create chart * update tool bar after create chart * align charts after updatelayout old-commit-hash: c5f5a3b5f2063be36497c81526c3a4c42d84beb7
This commit is contained in:
@@ -57,10 +57,16 @@ ChartsWidget::ChartsWidget(QWidget *parent) : align_timer(this), QFrame(parent)
|
||||
range_slider->setPageStep(60); // 1 min
|
||||
range_slider_action = toolbar->addWidget(range_slider);
|
||||
|
||||
undo_zoom_action = toolbar->addAction(utils::icon("arrow-counterclockwise"), tr("Previous zoom"));
|
||||
qobject_cast<QToolButton*>(toolbar->widgetForAction(undo_zoom_action))->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
|
||||
reset_zoom_action = toolbar->addAction(utils::icon("zoom-out"), tr("Reset Zoom"));
|
||||
// zoom controls
|
||||
zoom_undo_stack = new QUndoStack(this);
|
||||
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);
|
||||
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);
|
||||
|
||||
remove_all_btn = toolbar->addAction(utils::icon("x"), tr("Remove all charts"));
|
||||
@@ -99,7 +105,6 @@ ChartsWidget::ChartsWidget(QWidget *parent) : align_timer(this), QFrame(parent)
|
||||
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(undo_zoom_action, &QAction::triggered, this, &ChartsWidget::zoomUndo);
|
||||
QObject::connect(reset_zoom_action, &QAction::triggered, this, &ChartsWidget::zoomReset);
|
||||
QObject::connect(&settings, &Settings::changed, this, &ChartsWidget::settingChanged);
|
||||
QObject::connect(dock_btn, &QAction::triggered, [this]() {
|
||||
@@ -115,14 +120,9 @@ ChartsWidget::ChartsWidget(QWidget *parent) : align_timer(this), QFrame(parent)
|
||||
}
|
||||
|
||||
void ChartsWidget::eventsMerged() {
|
||||
{
|
||||
QFutureSynchronizer<void> future_synchronizer;
|
||||
for (auto c : charts) {
|
||||
future_synchronizer.addFuture(QtConcurrent::run(c, &ChartView::updateSeries, nullptr));
|
||||
}
|
||||
}
|
||||
if (can->isPaused()) {
|
||||
updateState();
|
||||
QFutureSynchronizer<void> future_synchronizer;
|
||||
for (auto c : charts) {
|
||||
future_synchronizer.addFuture(QtConcurrent::run(c, &ChartView::updateSeries, nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,25 +135,12 @@ void ChartsWidget::setZoom(double min, double max) {
|
||||
}
|
||||
|
||||
void ChartsWidget::zoomIn(double min, double max) {
|
||||
// Save previous zoom on undo stack
|
||||
if (is_zoomed) {
|
||||
zoom_stack.push({zoomed_range.first, zoomed_range.second});
|
||||
}
|
||||
setZoom(min, max);
|
||||
zoom_undo_stack->push(new ZoomCommand(this, {min, max}));
|
||||
}
|
||||
|
||||
void ChartsWidget::zoomReset() {
|
||||
setZoom(display_range.first, display_range.second);
|
||||
zoom_stack.clear();
|
||||
}
|
||||
|
||||
void ChartsWidget::zoomUndo() {
|
||||
if (!zoom_stack.isEmpty()) {
|
||||
auto r = zoom_stack.pop();
|
||||
setZoom(r.first, r.second);
|
||||
} else {
|
||||
zoomReset();
|
||||
}
|
||||
zoom_undo_stack->clear();
|
||||
}
|
||||
|
||||
void ChartsWidget::showValueTip(double sec) {
|
||||
@@ -199,12 +186,13 @@ void ChartsWidget::setMaxChartRange(int value) {
|
||||
void ChartsWidget::updateToolBar() {
|
||||
title_label->setText(tr("Charts: %1").arg(charts.size()));
|
||||
columns_action->setText(tr("Column: %1").arg(column_count));
|
||||
range_lb->setText(QString("Range: %1 ").arg(utils::formatSeconds(max_chart_range)));
|
||||
range_lb->setText(utils::formatSeconds(max_chart_range));
|
||||
range_lb_action->setVisible(!is_zoomed);
|
||||
range_slider_action->setVisible(!is_zoomed);
|
||||
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("Zoomin: %1-%2").arg(zoomed_range.first, 0, 'f', 1).arg(zoomed_range.second, 0, 'f', 1) : "");
|
||||
reset_zoom_action->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->setToolTip(docking ? tr("Undock charts") : tr("Dock charts"));
|
||||
@@ -225,20 +213,21 @@ ChartView *ChartsWidget::findChart(const MessageId &id, const cabana::Signal *si
|
||||
}
|
||||
|
||||
ChartView *ChartsWidget::createChart() {
|
||||
auto chart = new ChartView(this);
|
||||
auto chart = new ChartView(is_zoomed ? zoomed_range : display_range, this);
|
||||
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, this, &ChartsWidget::zoomUndo);
|
||||
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_back(chart);
|
||||
updateLayout();
|
||||
updateToolBar();
|
||||
return chart;
|
||||
}
|
||||
|
||||
@@ -247,11 +236,9 @@ void ChartsWidget::showChart(const MessageId &id, const cabana::Signal *sig, boo
|
||||
if (show && !chart) {
|
||||
chart = merge && charts.size() > 0 ? charts.back() : createChart();
|
||||
chart->addSeries(id, sig);
|
||||
updateState();
|
||||
} else if (!show && chart) {
|
||||
chart->removeIf([&](auto &s) { return s.msg_id == id && s.sig == sig; });
|
||||
}
|
||||
updateToolBar();
|
||||
}
|
||||
|
||||
void ChartsWidget::setColumnCount(int n) {
|
||||
@@ -305,8 +292,8 @@ void ChartsWidget::removeChart(ChartView *chart) {
|
||||
charts.removeOne(chart);
|
||||
chart->deleteLater();
|
||||
updateToolBar();
|
||||
alignCharts();
|
||||
updateLayout();
|
||||
alignCharts();
|
||||
emit seriesChanged();
|
||||
}
|
||||
|
||||
@@ -366,7 +353,7 @@ bool ChartsWidget::event(QEvent *event) {
|
||||
}
|
||||
|
||||
if (back_button) {
|
||||
zoomUndo();
|
||||
emit undo_zoom_action->triggered();
|
||||
return true;
|
||||
}
|
||||
return QFrame::event(event);
|
||||
@@ -374,7 +361,7 @@ bool ChartsWidget::event(QEvent *event) {
|
||||
|
||||
// ChartView
|
||||
|
||||
ChartView::ChartView(QWidget *parent) : tip_label(this), QChartView(nullptr, parent) {
|
||||
ChartView::ChartView(const std::pair<double, double> &x_range, QWidget *parent) : tip_label(this), QChartView(nullptr, parent) {
|
||||
series_type = (SeriesType)settings.chart_series_type;
|
||||
QChart *chart = new QChart();
|
||||
chart->setBackgroundVisible(false);
|
||||
@@ -386,6 +373,7 @@ ChartView::ChartView(QWidget *parent) : tip_label(this), QChartView(nullptr, par
|
||||
chart->legend()->setShowToolTips(true);
|
||||
chart->setMargins({0, 0, 0, 0});
|
||||
|
||||
axis_x->setRange(x_range.first, x_range.second);
|
||||
setChart(chart);
|
||||
|
||||
createToolButtons();
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
#include <QListWidget>
|
||||
#include <QGraphicsPixmapItem>
|
||||
#include <QGraphicsProxyWidget>
|
||||
#include <QStack>
|
||||
#include <QTimer>
|
||||
#include <QUndoCommand>
|
||||
#include <QUndoStack>
|
||||
#include <QtCharts/QChartView>
|
||||
#include <QtCharts/QLegendMarker>
|
||||
#include <QtCharts/QLineSeries>
|
||||
@@ -36,7 +37,7 @@ class ChartView : public QChartView {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ChartView(QWidget *parent = nullptr);
|
||||
ChartView(const std::pair<double, double> &x_range, QWidget *parent = nullptr);
|
||||
void addSeries(const MessageId &msg_id, const cabana::Signal *sig);
|
||||
bool hasSeries(const MessageId &msg_id, const cabana::Signal *sig) const;
|
||||
void updateSeries(const cabana::Signal *sig = nullptr);
|
||||
@@ -129,6 +130,7 @@ public:
|
||||
public slots:
|
||||
void setColumnCount(int n);
|
||||
void removeAll();
|
||||
void setZoom(double min, double max);
|
||||
|
||||
signals:
|
||||
void dock(bool floating);
|
||||
@@ -146,8 +148,6 @@ private:
|
||||
void updateState();
|
||||
void zoomIn(double min, double max);
|
||||
void zoomReset();
|
||||
void zoomUndo();
|
||||
void setZoom(double min, double max);
|
||||
void updateToolBar();
|
||||
void setMaxChartRange(int value);
|
||||
void updateLayout();
|
||||
@@ -163,8 +163,12 @@ private:
|
||||
QAction *range_slider_action;
|
||||
bool docking = true;
|
||||
QAction *dock_btn;
|
||||
|
||||
QAction *undo_zoom_action;
|
||||
QAction *redo_zoom_action;
|
||||
QAction *reset_zoom_action;
|
||||
QUndoStack *zoom_undo_stack;
|
||||
|
||||
QAction *remove_all_btn;
|
||||
QGridLayout *charts_layout;
|
||||
QList<ChartView *> charts;
|
||||
@@ -174,11 +178,23 @@ private:
|
||||
bool is_zoomed = false;
|
||||
std::pair<double, double> display_range;
|
||||
std::pair<double, double> zoomed_range;
|
||||
QStack<QPair<double, double>> zoom_stack;
|
||||
QAction *columns_action;
|
||||
int column_count = 1;
|
||||
int current_column_count = 0;
|
||||
QTimer align_timer;
|
||||
friend class ZoomCommand;
|
||||
};
|
||||
|
||||
class ZoomCommand : public QUndoCommand {
|
||||
public:
|
||||
ZoomCommand(ChartsWidget *charts, std::pair<double, double> range) : charts(charts), range(range), QUndoCommand() {
|
||||
prev_range = charts->is_zoomed ? charts->zoomed_range : charts->display_range;
|
||||
setText(QObject::tr("Zoom to %1-%2").arg(range.first, 0, 'f', 1).arg(range.second, 0, 'f', 1));
|
||||
}
|
||||
void undo() override { charts->setZoom(prev_range.first, prev_range.second); }
|
||||
void redo() override { charts->setZoom(range.first, range.second); }
|
||||
ChartsWidget *charts;
|
||||
std::pair<double, double> prev_range, range;
|
||||
};
|
||||
|
||||
class SeriesSelector : public QDialog {
|
||||
|
||||
Reference in New Issue
Block a user