diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index df6bf0c8b7..7fae43ceb9 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -385,19 +385,18 @@ ChartView::ChartView(QWidget *parent) : tip_label(this), QChartView(nullptr, par chart->legend()->setShowToolTips(true); chart->setMargins({0, 0, 0, 0}); - background = new QGraphicsRectItem(chart); - background->setBrush(QApplication::palette().color(QPalette::Base)); - background->setPen(Qt::NoPen); - background->setZValue(chart->zValue() - 1); - setChart(chart); createToolButtons(); - setRenderHint(QPainter::Antialiasing); // TODO: enable zoomIn/seekTo in live streaming mode. setRubberBand(can->liveStreaming() ? QChartView::NoRubberBand : QChartView::HorizontalRubberBand); setMouseTracking(true); + QObject::connect(axis_x, &QValueAxis::rangeChanged, [this]() { resetChartCache(); }); + QObject::connect(axis_y, &QValueAxis::rangeChanged, [this]() { resetChartCache(); }); + QObject::connect(axis_y, &QAbstractAxis::titleTextChanged, [this]() { resetChartCache(); }); + QObject::connect(chart, &QChart::plotAreaChanged, [this]() { resetChartCache(); }); + QObject::connect(dbc(), &DBCManager::signalRemoved, this, &ChartView::signalRemoved); QObject::connect(dbc(), &DBCManager::signalUpdated, this, &ChartView::signalUpdated); QObject::connect(dbc(), &DBCManager::msgRemoved, this, &ChartView::msgRemoved); @@ -474,6 +473,7 @@ void ChartView::removeIf(std::function predicate) { emit remove(); } else if (sigs.size() != prev_size) { updateAxisY(); + resetChartCache(); } } @@ -515,15 +515,14 @@ void ChartView::resizeEvent(QResizeEvent *event) { manage_btn_proxy->setPos(x, top); chart()->legend()->setGeometry({move_icon->sceneBoundingRect().topRight(), manage_btn_proxy->sceneBoundingRect().bottomLeft()}); if (align_to > 0) { - updatePlotArea(align_to); + updatePlotArea(align_to, true); } QChartView::resizeEvent(event); } -void ChartView::updatePlotArea(int left_pos) { - if (align_to != left_pos || rect() != background->rect()) { +void ChartView::updatePlotArea(int left_pos, bool force) { + if (align_to != left_pos || force) { align_to = left_pos; - background->setRect(rect()); qreal left, top, right, bottom; chart()->layout()->getContentsMargins(&left, &top, &right, &bottom); @@ -532,9 +531,6 @@ void ChartView::updatePlotArea(int left_pos) { int adjust_top = chart()->legend()->geometry().height() + style()->pixelMetric(QStyle::PM_LayoutTopMargin); chart()->setPlotArea(rect().adjusted(align_to + left, adjust_top + top, -x_label_size.width() / 2 - right, -x_label_size.height() - bottom)); chart()->layout()->invalidate(); - if (can->isPaused()) { - update(); - } } } @@ -546,6 +542,7 @@ void ChartView::updateTitle() { auto decoration = s.series->isVisible() ? "none" : "line-through"; s.series->setName(QString("%2 %3 %4").arg(decoration, s.sig->name, msgName(s.msg_id), s.msg_id.toString())); } + resetChartCache(); } void ChartView::updatePlot(double cur, double min, double max) { @@ -555,7 +552,7 @@ void ChartView::updatePlot(double cur, double min, double max) { updateAxisY(); updateSeriesPoints(); } - scene()->update(); + viewport()->update(); } void ChartView::updateSeriesPoints() { @@ -617,6 +614,7 @@ void ChartView::updateSeries(const cabana::Signal *sig) { } } updateAxisY(); + resetChartCache(); } // auto zoom on yaxis @@ -752,7 +750,7 @@ void ChartView::mouseReleaseEvent(QMouseEvent *event) { } else if (rubber->width() > 10) { emit zoomIn(min_rounded, max_rounded); } else { - scene()->update(); + viewport()->update(); } event->accept(); } else if (!can->liveStreaming() && event->button() == Qt::RightButton) { @@ -798,7 +796,7 @@ void ChartView::mouseMoveEvent(QMouseEvent *ev) { if (rubber_rect != rubber->geometry()) { rubber->setGeometry(rubber_rect); } - scene()->update(); + viewport()->update(); } } @@ -822,13 +820,13 @@ void ChartView::showTip(double sec) { QPointF tooltip_pt(x, chart()->plotArea().top()); int plot_right = mapToGlobal(chart()->plotArea().topRight().toPoint()).x(); tip_label.showText(mapToGlobal(tooltip_pt.toPoint()), "

" + text_list.join("
") + "

", plot_right); - scene()->update(); + viewport()->update(); } void ChartView::hideTip() { clearTrackPoints(); tip_label.hide(); - scene()->update(); + viewport()->update(); } void ChartView::dragMoveEvent(QDragMoveEvent *event) { @@ -858,6 +856,34 @@ void ChartView::dropEvent(QDropEvent *event) { } } +void ChartView::resetChartCache() { + chart_pixmap = QPixmap(); + viewport()->update(); +} + +void ChartView::paintEvent(QPaintEvent *event) { + if (!can->liveStreaming()) { + if (chart_pixmap.isNull()) { + const qreal dpr = viewport()->devicePixelRatioF(); + chart_pixmap = QPixmap(viewport()->size() * dpr); + chart_pixmap.setDevicePixelRatio(dpr); + chart_pixmap.fill(palette().color(QPalette::Base)); + QPainter p(&chart_pixmap); + p.setRenderHints(QPainter::Antialiasing); + scene()->setSceneRect(viewport()->rect()); + scene()->render(&p); + } + + QPainter painter(viewport()); + painter.setRenderHints(QPainter::Antialiasing); + painter.drawPixmap(QPoint(), chart_pixmap); + QRectF exposed_rect = mapToScene(event->region().boundingRect()).boundingRect(); + drawForeground(&painter, exposed_rect); + } else { + QChartView::paintEvent(event); + } +} + void ChartView::drawForeground(QPainter *painter, const QRectF &rect) { // draw time line qreal x = chart()->mapToPosition(QPointF{cur_sec, 0}).x(); diff --git a/tools/cabana/chartswidget.h b/tools/cabana/chartswidget.h index 98ceb02674..f4cc681ff0 100644 --- a/tools/cabana/chartswidget.h +++ b/tools/cabana/chartswidget.h @@ -42,7 +42,7 @@ public: void updateSeries(const cabana::Signal *sig = nullptr); void updatePlot(double cur, double min, double max); void setSeriesType(SeriesType type); - void updatePlotArea(int left); + void updatePlotArea(int left, bool force = false); void showTip(double sec); void hideTip(); @@ -88,6 +88,8 @@ private: QSize sizeHint() const override { return {CHART_MIN_WIDTH, settings.chart_height}; } void updateAxisY(); void updateTitle(); + void resetChartCache(); + void paintEvent(QPaintEvent *event) override; void drawForeground(QPainter *painter, const QRectF &rect) override; std::tuple getNiceAxisNumbers(qreal min, qreal max, int tick_count); qreal niceNumber(qreal x, bool ceiling); @@ -103,7 +105,6 @@ private: QGraphicsPixmapItem *move_icon; QGraphicsProxyWidget *close_btn_proxy; QGraphicsProxyWidget *manage_btn_proxy; - QGraphicsRectItem *background; ValueTipLabel tip_label; QList sigs; double cur_sec = 0; @@ -111,6 +112,7 @@ private: SeriesType series_type = SeriesType::Line; bool is_scrubbing = false; bool resume_after_scrub = false; + QPixmap chart_pixmap; friend class ChartsWidget; };