From 1615d6074b20845d2f829ca52f5c1c71bd5e6482 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michal=20Mal=C3=BD?= Date: Tue, 19 Nov 2013 15:01:26 +0100 Subject: [PATCH] Move drawing logic to GraphView and update only the part of screen that needs to be repainted. --- datamanager.cpp | 20 +- gui/graphview.cpp | 532 ++++++++++++++++++++++++++++++++++++++++++- gui/graphview.h | 61 ++++- gui/mainwindow.cpp | 6 +- gui/signalview.cpp | 470 +------------------------------------- gui/signalview.h | 65 +----- gui/signalview.ui | 41 ++-- mathhelpers.h | 7 + metatypes.h | 2 + signalcontroller.cpp | 3 +- signalcontroller.h | 2 +- 11 files changed, 632 insertions(+), 577 deletions(-) diff --git a/datamanager.cpp b/datamanager.cpp index ba8dffa..3f6fdff 100644 --- a/datamanager.cpp +++ b/datamanager.cpp @@ -262,16 +262,16 @@ void DataManager::showOneSignal(std::shared_ptr ctrl) swp->setTypeText(ctrl->signal()->resourceToString()); swp->setXUnits(ctrl->signal()->xunitToString()); swp->setYUnits(ctrl->signal()->yunitToString()); - connect(swp, SIGNAL(crosshairErased()), ctrl.get(), SLOT(onViewCrosshairErased())); - connect(swp, SIGNAL(crosshairMoved(int,int)), ctrl.get(), SLOT(onViewCrosshairMoved(int,int))); - connect(swp, SIGNAL(integrated(int,int,int,int)), ctrl.get(), SLOT(onViewIntegrated(int,int,int,int))); - connect(swp, SIGNAL(redrawNeeded()), ctrl.get(), SLOT(onViewRedrawNeeded())); - connect(swp, SIGNAL(resized(int,int)), ctrl.get(), SLOT(onViewResized(int,int))); - connect(swp, SIGNAL(showContextMenu(int,int,QPoint)), ctrl.get(), SLOT(onViewShowContextMenu(int,int,QPoint))); - connect(swp, SIGNAL(zoomed(int,int,int,int)), ctrl.get(), SLOT(onViewZoomed(int,int,int,int))); - connect(ctrl.get(), SIGNAL(guiDrawGraph(double*,size_t,double,double)), swp, SLOT(onUpdateGraph(double*,size_t,double,double))); - connect(ctrl.get(), SIGNAL(viewCtxMenuClosed()), swp, SLOT(onCtxMenuClosed())); - connect(ctrl.get(), SIGNAL(viewDrawIntegration(int,double,int,double,int,double,QString,QString,bool)), swp, + connect(swp->m_graphView, SIGNAL(crosshairErased()), ctrl.get(), SLOT(onViewCrosshairErased())); + connect(swp->m_graphView, SIGNAL(crosshairMoved(int,int)), ctrl.get(), SLOT(onViewCrosshairMoved(int,int))); + connect(swp->m_graphView, SIGNAL(integrated(int,int,int,int)), ctrl.get(), SLOT(onViewIntegrated(int,int,int,int))); + connect(swp->m_graphView, SIGNAL(redrawNeeded()), ctrl.get(), SLOT(onViewRedrawNeeded())); + connect(swp->m_graphView, SIGNAL(resized(int,int)), ctrl.get(), SLOT(onViewResized(int,int))); + connect(swp->m_graphView, SIGNAL(showContextMenuReq(int,int,QPoint)), ctrl.get(), SLOT(onViewShowContextMenu(int,int,QPoint))); + connect(swp->m_graphView, SIGNAL(zoomed(int,int,int,int)), ctrl.get(), SLOT(onViewZoomed(int,int,int,int))); + connect(ctrl.get(), SIGNAL(viewDrawGraph(double*,size_t,double,double)), swp->m_graphView, SLOT(onUpdateGraph(double*,size_t,double,double))); + connect(ctrl.get(), SIGNAL(viewCtxMenuClosed()), swp->m_graphView, SLOT(onCtxMenuClosed())); + connect(ctrl.get(), SIGNAL(viewDrawIntegration(int,double,int,double,int,double,QString,QString,bool)), swp->m_graphView, SLOT(onDrawIntegration(int,double,int,double,int,double,QString,QString,bool))); connect(ctrl.get(), SIGNAL(viewUpdateCurrentValues(double,double)), swp, SLOT(onUpdateCurrentValues(double,double))); connect(ctrl.get(), SIGNAL(viewRemoveCurrentValues()), swp, SLOT(onRemoveCurrentValues())); diff --git a/gui/graphview.cpp b/gui/graphview.cpp index d6da6d0..602aa86 100644 --- a/gui/graphview.cpp +++ b/gui/graphview.cpp @@ -21,18 +21,25 @@ */ #include "gui/graphview.h" +#include -GraphView::GraphView(QWidget *parent) : - QLabel(parent) +#include + +GraphView::GraphView(QWidget* parent) : + QWidget(parent), + m_ctxMenuOpen(false), + m_backbuffer(nullptr), + m_plainGraph(nullptr), + m_mouseMode(GraphView::MouseMode::CROSSHAIR), + m_drawData(nullptr), + m_graphCrosshairX(-1), + m_graphCrosshairY(-1) { setMouseTracking(true); setCursor(Qt::BlankCursor); } -void GraphView::leaveEvent(QEvent *) -{ - emit mouseCursorLeft(); -} +/* Public functions */ void GraphView::mouseDoubleClickEvent(QMouseEvent* ev) { @@ -47,18 +54,525 @@ void GraphView::mouseDoubleClickEvent(QMouseEvent* ev) } } +void GraphView::leaveEvent(QEvent *) +{ + switch (m_mouseMode) { + case MouseMode::CROSSHAIR: + this->eraseCrosshair(true); + break; + case MouseMode::INTEGRATE: + this->eraseIntegrationBaseline(true); + break; + case MouseMode::ZOOM: + this->eraseZoomRect(true); + break; + } + + emit mouseCursorLeft(); +} + void GraphView::mouseMoveEvent(QMouseEvent* ev) { - emit mouseMoved(ev->x(), ev->y()); + switch (m_mouseMode) { + case GraphView::MouseMode::CROSSHAIR: + this->drawCrosshair(ev->x(), ev->y()); + break; + case GraphView::MouseMode::ZOOM: + this->drawZoomRect(ev->x(), ev->y()); + break; + case GraphView::MouseMode::INTEGRATE: + this->drawIntegrationBaseline(ev->x(), ev->y()); + break; + } + + emit crosshairMoved(ev->x(), ev->y()); } void GraphView::mousePressEvent(QMouseEvent* ev) { - emit mouseButtonTriggered(ev->x(), ev->y(), ev->button(), ev->type(), ev->globalPos()); + if (m_ctxMenuOpen) + return; + + switch (ev->button()) { + case Qt::LeftButton: + switch (m_mouseMode) { + case GraphView::MouseMode::CROSSHAIR: + if (m_graphCtrlMode == GraphControlModes::ZOOM) { + m_zoomRectStartX = ev->x(); + m_zoomRectStartY = ev->y(); + m_zoomRectLastX = ev->x(); + m_zoomRectLastY = ev->y(); + this->eraseCrosshair(true); + m_mouseMode = GraphView::MouseMode::ZOOM; + } else if (m_graphCtrlMode == GraphControlModes::INTEGRATE) { + m_integrateStartX = ev->x(); + m_integrateStartY = ev->y(); + m_integrateStopX = ev->x(); + m_integrateStopY = ev->y(); + this->eraseCrosshair(true); + m_graphCrosshairX = -1; + m_mouseMode = GraphView::MouseMode::INTEGRATE; + } + break; + case GraphView::MouseMode::ZOOM: + if (m_zoomRectLastX < m_zoomRectStartX) + std::swap(m_zoomRectLastX, m_zoomRectStartX); + if (m_zoomRectLastY < m_zoomRectStartY) + std::swap(m_zoomRectLastY, m_zoomRectStartY); + emit zoomed(m_zoomRectStartX, m_zoomRectStartY, m_zoomRectLastX, m_zoomRectLastY); + m_mouseMode = GraphView::MouseMode::CROSSHAIR; + break; + case GraphView::MouseMode::INTEGRATE: + if (m_integrateStartX > m_integrateStopX) + std::swap(m_integrateStartX, m_integrateStopX); + emit integrated(m_integrateStartX, m_integrateStartY, m_integrateStopX, m_integrateStopY); + this->eraseIntegrationBaseline(true); + m_integrateStartX = -1; + m_mouseMode = GraphView::MouseMode::CROSSHAIR; + break; + } + break; + case Qt::RightButton: + switch (m_mouseMode) { + case GraphView::MouseMode::CROSSHAIR: + m_ctxMenuOpen = true; + this->eraseCrosshair(true); + emit showContextMenuReq(ev->x(), ev->y(), ev->globalPos()); + break; + case GraphView::MouseMode::ZOOM: + this->eraseZoomRect(true); + m_mouseMode = GraphView::MouseMode::CROSSHAIR; + break; + case GraphView::MouseMode::INTEGRATE: + this->eraseIntegrationBaseline(true); + m_mouseMode = GraphView::MouseMode::CROSSHAIR; + break; + default: + break; + } + break; + default: + break; + } +} + +void GraphView::paintEvent(QPaintEvent* ev) +{ + QPainter p(this); + if (m_backbuffer != nullptr) + p.drawPixmap(0, 0, width(), height(), *m_backbuffer); } void GraphView::resizeEvent(QResizeEvent* ev) { - if (ev->size().width() > 1 && ev->size().height() > 1) + if (ev->size().width() > 1 && ev->size().height() > 1) { + emit resized(ev->size().width(), ev->size().height()); emit redrawNeeded(); + } +} + +/* Private functions */ + +void GraphView::drawCrosshair(const int x, const int y) +{ + QPainter p; + int w, h; + + if (m_backbuffer == nullptr) { + qDebug() << "NPTR"; + return; + } + + w = this->width(); + h = this->height(); + + QRegion reg = eraseCrosshair(); + + p.begin(m_backbuffer); + p.setPen(Qt::black); + /* Draw new crosshair */ + p.drawLine(0, y, w, y); /* Horizontal */ + p.drawLine(x, 0, x, h); /* Vertical */ + p.end(); + + /* New lines */ + reg += QRect(0, y, w, 1); + reg += QRect(x, 0, 1, h); + + m_graphCrosshairX = x; + m_graphCrosshairY = y; + + update(reg); +} + +void GraphView::drawIntegratedPeak(const int fromX, const double fromY, const int toX, const double toY, const int peakX, const double peakY, + const QString& time, const QString& area, const bool valley) +{ + QPainter p; + QPainter pBB; + QRegion reg; + int w, h; + int startX, startY, stopX, stopY, peakStartX, peakStartY; + double yStep, xStep; + double dStartY, dStopY; + QFont font("arial", 10); + QFontMetrics fm(font); + int textWidth; + if (m_backbuffer == nullptr) + return; + + w = this->width(); + h = this->height(); + xStep = static_cast(w) / m_drawDataLen; + yStep = static_cast(h) / (m_drawDataMax - m_drawDataMin); + startX = floor(fromX * xStep + 0.5); + stopX = floor(toX * xStep + 0.5); + startY = floor((h - yStep * (fromY - m_drawDataMin)) + 0.5); + stopY = floor((h - yStep * (toY - m_drawDataMin)) + 0.5); + peakStartX = floor(peakX * xStep + 0.5); + peakStartY = floor(h - yStep * (peakY - m_drawDataMin) + 0.5); + + dStartY = h - yStep * (fromY - m_drawDataMin); + dStopY = h - yStep * (toY - m_drawDataMin); + + /*qDebug("Drawing peak"); + qDebug() << "RSX" << fromX << "RSY" << fromY << "REX" << toX << "REY" << toY; + qDebug() << "X step" << xStep << "Y step" << yStep; + qDebug() << "SX" << startX << "SY" << startY << "EX" << stopX << "EY" << stopY << "w/h" << w << h; + qDebug() << "DSY" << dStartY << "DEY" << dStopY << "Slope I" << (toY-fromY)/(toX-fromX) << "Slope D" << (dStopY-dStartY)/(toX-fromX); + qDebug("---");*/ + + p.begin(m_plainGraph); + p.setPen(Qt::red); + p.drawLine(startX, startY, stopX, stopY); + + /* Draw AREA and TIME caption */ + p.setFont(font); + p.setPen(Qt::black); + textWidth = fm.width(time); + if (peakStartY - textWidth < 2) + peakStartY += textWidth - peakStartY + 2; + p.save(); + p.translate(peakStartX, peakStartY); + p.rotate(-90); + p.drawText(0, 0, time); + p.rotate(+90); + p.restore(); + p.drawText(peakStartX + 5, peakStartY, area); + p.end(); + + /* Copy updated plainGraph to backbuffer */ + pBB.begin(m_backbuffer); + pBB.drawPixmap(QRect(0, 0, w, h), *m_plainGraph); // Can be optimized! + //pBB.drawPixmap(startX, 0, *m_plainGraph, startX, 0, w - startX, h); + pBB.end(); + + //reg = QRect(startX, 0, w - startX, h); + update(); //Again - can be optimized! +} + +void GraphView::drawIntegrationBaseline(const int x, const int y) +{ + QPainter p; + QRegion reg; + int w = this->width(); + int h = this->height(); + int lstartX, lstartY, lstopX, lstopY; + if (m_backbuffer == nullptr) + return; + + reg = eraseIntegrationBaseline(); + + if (m_integrateStartX > m_integrateStopX) { + lstartX = (m_integrateStopX > 1) ? m_integrateStopX - 1 : 0; + lstopX = (m_integrateStartX < w-1) ? m_integrateStartX + 1 : w-1; + } else { + lstartX = (m_integrateStartX > 1) ? m_integrateStartX -1 : 0; + lstopX = (m_integrateStopX < w-1) ? m_integrateStopX + 1 : w-1; + } + if (m_integrateStartY > m_integrateStopY) { + lstartY = (m_integrateStopY > 1) ? m_integrateStopY - 1 : 0; + lstopY = (m_integrateStartY < h-1) ? m_integrateStartY + 1 : h-1; + } else { + lstartY = (m_integrateStartY > 1) ? m_integrateStartY - 1 : 0; + lstopY = (m_integrateStopY < h-1) ? m_integrateStopY + 1 : h-1; + } + + p.begin(m_backbuffer); + /* Draw new line */ + p.setPen(Qt::black); + p.drawLine(m_integrateStartX, m_integrateStartY, x, y); + p.end(); + + reg += QRect(lstartX, lstartY, lstopX, lstopY); + + m_integrateStopX = x; + m_integrateStopY = y; + + update(reg); +} + + +void GraphView::drawGraph() +{ + int w = this->width(); + int h = this->height(); + uint lastColumn = 0; + double yAvg = 0; + double yStep; + QPainter p; + QPixmap* fresh; + + if (m_drawData == nullptr) + return; + if (w < 1 || h < 1) + return; + + fresh = new QPixmap(w, h); + qDebug() << "DGR" << w << h; + + p.begin(fresh); + p.fillRect(0, 0, w, h, Qt::white); + p.setPen(QColor(Qt::blue)); + + /* Scaling */ + yStep = static_cast(h) / fabs(m_drawDataMax - m_drawDataMin); + + /* Downscale to grid */ + if (w < m_drawDataLen) { + double columnsPerPixel = static_cast(m_drawDataLen) / w; + uint columnsPerLastPixel = 0; + int* block = new int[w]; + //qDebug() << "CPP" << columnsPerPixel << "yStep" << yStep << "Dims" << h << w << "Data" << w*columnsPerPixel << m_graphLen; + for (uint i = 0; i < m_drawDataLen; i++) { + uint column = i / columnsPerPixel; + if (column != lastColumn) { + yAvg /= columnsPerLastPixel; + block[lastColumn] = h - yStep * (yAvg -m_drawDataMin); + //qDebug() << "YAVG" << block[lastColumn] << "CPLP" << columnsPerLastPixel; + yAvg = 0; + columnsPerLastPixel= 0; + lastColumn = column; + } + yAvg += m_drawData[i]; + columnsPerLastPixel++; + } + /* Add the last column */ + yAvg /= columnsPerLastPixel; + block[w-1] = h - yStep * (yAvg - m_drawDataMin); + /* Draw the pixmap */ + for (int i = 1; i < w; i++) + p.drawLine(i-1, floor(block[i-1]+0.5), i, floor(block[i]+0.5)); + //qDebug() << "LAST YAVG" << block[m_graphLen-1] << "CPLP" << columnsPerLastPixel; + delete[] block; + } else { /* Upscale to grid */ + double pixelsPerValue = static_cast(w) / m_drawDataLen; + uint cPixX; + uint pPixX = 0; + uint cPixY; + uint pPixY = floor((h - yStep * (m_drawData[0] - m_drawDataMin)) + 0.5); + for (int i = 1; i < m_drawDataLen; i++) { + cPixX= floor(i * pixelsPerValue + 0.5); + cPixY = h - yStep * (m_drawData[i] - m_drawDataMin); + //qDebug() << "Upscale" << pPixX << pPixY << cPixX << cPixY; + p.drawLine(pPixX, pPixY, cPixX, cPixY); + pPixX = cPixX; + pPixY = cPixY; + } + } + + if (m_backbuffer != nullptr) + delete m_backbuffer; + m_backbuffer = fresh; + if (m_plainGraph != nullptr) + delete m_plainGraph; + m_plainGraph = new QPixmap(*m_backbuffer); +} + +void GraphView::drawZoomRect(const int x, const int y) +{ + QPainter p; + QRegion reg; + int lstartX, lstartY, lstopX, lstopY; + if (m_backbuffer == nullptr) + return; + + if (x < m_zoomRectStartX) { + lstartX = x; + lstopX = m_zoomRectStartX; + } else { + lstartX = m_zoomRectStartX; + lstopX = x; + } + if (y < m_zoomRectStartY) { + lstartY = y; + lstopY = m_zoomRectStartY; + } else { + lstartY = m_zoomRectStartY; + lstopY = y; + } + + reg = eraseZoomRect(); + + p.begin(m_backbuffer); + p.setPen(Qt::green); + // Top line + p.drawLine(lstartX, lstartY, lstopX, lstartY); + // Left line + p.drawLine(lstartX, lstartY, lstartX, lstopY); + // Right line + p.drawLine(lstopX, lstartY, lstopX, lstopY); + // Bottom line + p.drawLine(lstartX, lstopY, lstopX, lstopY); + p.end(); + + reg += QRect(lstartX-1, lstartY, lstopX - lstartX, 1); // Top line + reg += QRect(lstartX, lstartY, 1, lstopY - lstartY); //Left line + reg += QRect(lstopX, lstartY, 1, lstopY - lstartY + 1); //Right line; + reg += QRect(lstartX, lstopY, lstopX - lstartX, 1); // Bottom line + + m_zoomRectLastX = x; + m_zoomRectLastY = y; + + update(reg); +} + +QRegion GraphView::eraseCrosshair(bool apply) +{ + QPainter p; + int w, h; + if (m_backbuffer == nullptr) + return QRegion(); + + w = this->width(); + h = this->height(); + + if (m_graphCrosshairX != -1 || m_graphCrosshairY != -1) { + QRegion reg; + + p.begin(m_backbuffer); + p.drawPixmap(m_graphCrosshairX, 0, *m_plainGraph, m_graphCrosshairX, 0, 1, h); + p.drawPixmap(0, m_graphCrosshairY, *m_plainGraph, 0, m_graphCrosshairY, w, 1); + p.end(); + + reg = QRect(0, m_graphCrosshairY, w, 1); + reg += QRect(m_graphCrosshairX, 0, 1, h); + + if (apply) + update(reg); + + return reg; + } + + return QRegion(); +} + +QRegion GraphView::eraseIntegrationBaseline(bool apply) +{ + QPainter p; + QRegion reg; + int lstartX, lstartY, lstopX, lstopY; + int w, h; + + if (m_backbuffer == nullptr) + return QRegion(); + if (m_integrateStartX < 0) + return QRegion(); + + w = this->width(); + h = this->height(); + + p.begin(m_backbuffer); + if (m_integrateStartX > m_integrateStopX) { + lstartX = (m_integrateStopX > 1) ? m_integrateStopX - 1 : 0; + lstopX = (m_integrateStartX < w-1) ? m_integrateStartX + 1 : w-1; + } else { + lstartX = (m_integrateStartX > 1) ? m_integrateStartX -1 : 0; + lstopX = (m_integrateStopX < w-1) ? m_integrateStopX + 1 : w-1; + } + if (m_integrateStartY > m_integrateStopY) { + lstartY = (m_integrateStopY > 1) ? m_integrateStopY - 1 : 0; + lstopY = (m_integrateStartY < h-1) ? m_integrateStartY + 1 : h-1; + } else { + lstartY = (m_integrateStartY > 1) ? m_integrateStartY - 1 : 0; + lstopY = (m_integrateStopY < h-1) ? m_integrateStopY + 1 : h-1; + } + + p.drawPixmap(lstartX, lstartY, *m_plainGraph, lstartX, lstartY, lstopX - lstartX+1, lstopY - lstartY+1); //FIXME: +1 should not be needed! + p.end(); + + reg = QRect(lstartX, lstartY, lstopX - lstartX +1, lstopY - lstartY + 1); + + if (apply) + update(reg); + + return reg; +} + +QRegion GraphView::eraseZoomRect(bool apply) +{ + int lstartX, lstartY, lstopX, lstopY; + QPainter p; + QRegion reg; + if (m_backbuffer == nullptr) + return QRegion(); + + if (m_zoomRectLastX < m_zoomRectStartX) { + lstartX = m_zoomRectLastX; + lstopX = m_zoomRectStartX; + } else { + lstartX = m_zoomRectStartX; + lstopX = m_zoomRectLastX; + } + if (m_zoomRectLastY < m_zoomRectStartY) { + lstartY = m_zoomRectLastY; + lstopY = m_zoomRectStartY; + } else { + lstartY = m_zoomRectStartY; + lstopY = m_zoomRectLastY; + } + + /* Erase any existing lines */ + p.begin(m_backbuffer); + // TODO: It might not be necessary to erase all lines every time - OPTIMIZE THIS !!! + // Top line + p.drawPixmap(lstartX, lstartY, *m_plainGraph, lstartX, lstartY, lstopX - lstartX, 1); + // Left line + p.drawPixmap(lstartX, lstartY, *m_plainGraph, lstartX, lstartY, 1, lstopY - lstartY); + // Right line + p.drawPixmap(lstopX, lstartY, *m_plainGraph, lstopX, lstartY, 1, lstopY - lstartY + 1); + // Bottom line + p.drawPixmap(lstartX, lstopY, *m_plainGraph, lstartX, lstopY, lstopX - lstartX + 1, 1); + p.end(); + + reg = QRect(lstartX, lstartY, lstopX - lstartX, 1); // Top line + reg += QRect(lstartX, lstartY, 1, lstopY - lstartY); //Left line + reg += QRect(lstopX, lstartY, 1, lstopY - lstartY + 1); //Right line; + reg += QRect(lstartX, lstopY, lstopX - lstartX + 1, 1); // Bottom line + + if (apply) + update(reg); + + return reg; +} + +/* Public slots */ +void GraphView::onDrawIntegration(const int fromX, const double fromY, const int toX, const double toY, const int peakX, const double peakY, + const QString& time, const QString& area, const bool valley) +{ + this->drawIntegratedPeak(fromX, fromY, toX, toY, peakX, peakY, time, area, valley); +} + +void GraphView::onUpdateGraph(double* data, size_t len, double min, double max) +{ + if (m_drawData != nullptr) + delete[] m_drawData; + + m_drawData = data; + m_drawDataLen = len; + m_drawDataMax = max; + m_drawDataMin = min; + + this->drawGraph(); + this->update(); } diff --git a/gui/graphview.h b/gui/graphview.h index b3db5b4..d0c37a7 100644 --- a/gui/graphview.h +++ b/gui/graphview.h @@ -24,28 +24,81 @@ #define GRAPHVIEW_H #include -#include +#include +#include "mathhelpers.h" +#include "metatypes.h" -class GraphView : public QLabel +class GraphView : public QWidget { Q_OBJECT public: + enum class MouseMode { + CROSSHAIR, + ZOOM, + INTEGRATE + }; + explicit GraphView(QWidget* parent = nullptr); void leaveEvent(QEvent* ); void mouseDoubleClickEvent(QMouseEvent* ); void mouseMoveEvent(QMouseEvent* ev); void mousePressEvent(QMouseEvent* ev); + void paintEvent(QPaintEvent* ev); private: + void drawCrosshair(const int x, const int y); + void drawGraph(); + void drawIntegratedPeak(const int fromX, const double fromY, const int toX, const double toY, const int peakX, const double peakY, + const QString& time, const QString& area, const bool valley); + void drawIntegrationBaseline(const int x, const int y); + void drawZoomRect(const int x, const int y); + QRegion eraseCrosshair(bool apply = false); + QRegion eraseIntegrationBaseline(bool apply = false); + QRegion eraseZoomRect(bool apply = false); + void resizeEvent(QResizeEvent* ev); + bool m_ctxMenuOpen; + QPixmap* m_backbuffer; + QPixmap* m_plainGraph; + + MouseMode m_mouseMode; + GraphControlModes m_graphCtrlMode; + + double* m_drawData; + size_t m_drawDataLen; + double m_drawDataMax; + double m_drawDataMin; + /* Crosshair */ + int m_graphCrosshairX; + int m_graphCrosshairY; + /* Integration baseline */ + int m_integrateStartX; + int m_integrateStartY; + int m_integrateStopX; + int m_integrateStopY; + /* Zooming rectangle */ + int m_zoomRectStartX; + int m_zoomRectStartY; + int m_zoomRectLastX; + int m_zoomRectLastY; + public slots: + void onControlModeChanged(GraphControlModes mode) { m_graphCtrlMode = mode; } + void onCtxMenuClosed() { m_ctxMenuOpen = false; } + void onDrawIntegration(const int fromX, const double fromY, const int toX, const double toY, const int peakX, const double peakY, + const QString& time, const QString& area, const bool valley); + void onUpdateGraph(double* data, size_t len, double min, double max); signals: + void crosshairErased(); + void crosshairMoved(const int x, const int y); + void integrated(const int fromX, const int fromY, const int toX, const int toY); void mouseCursorLeft(); - void mouseMoved(const int x, const int y); - void mouseButtonTriggered(const int x, const int y, Qt::MouseButton button, QEvent::Type type, const QPoint& globalPos); void redrawNeeded(); + void resized(const int x, const int y); + void showContextMenuReq(const int x, const int y, const QPoint& globalPos); + void zoomed(const int fromX, const int fromY, const int toX, const int toY); }; #endif // GRAPHVIEW_H diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 9b7b717..59ee7cc 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -77,11 +77,11 @@ void MainWindow::connectActions() void MainWindow::onAddToDashboard(SignalView* sw) { if (ui->qpb_integrate->isChecked()) - sw->setControlMode(GraphControlModes::INTEGRATE); + sw->m_graphView->onControlModeChanged(GraphControlModes::INTEGRATE); else if(ui->qpb_zoom->isChecked()) - sw->setControlMode(GraphControlModes::ZOOM); + sw->m_graphView->onControlModeChanged(GraphControlModes::ZOOM); - connect(this, SIGNAL(controlModeChanged(GraphControlModes)), sw, SLOT(onControlModeChanged(GraphControlModes))); + connect(this, SIGNAL(controlModeChanged(GraphControlModes)), sw->m_graphView, SLOT(onControlModeChanged(GraphControlModes))); connect(sw, SIGNAL(fullSizeToggle()), this, SLOT(onSWFullSizeToggle())); m_dashboard->addWidget(sw); diff --git a/gui/signalview.cpp b/gui/signalview.cpp index 9f1f447..21ae43f 100644 --- a/gui/signalview.cpp +++ b/gui/signalview.cpp @@ -30,26 +30,15 @@ //#include -SignalView::SignalView(QWidget *parent) : +SignalView::SignalView(QWidget* parent) : QWidget(parent), - m_graph(nullptr), - m_graphPlain(nullptr), - m_graphData(nullptr), - m_ctxMenuOpen(false), - m_mouseMode(SignalView::MouseMode::CROSSHAIR), ui(new Ui::SignalView) { ui->setupUi(this); - m_graphPainter = new QPainter(); - m_graphCrosshairX = -1; - m_graphCrosshairY = -1; - m_integrateStartX = -1; + m_graphView = new GraphView(this); - connect(ui->qw_graphView, SIGNAL(mouseCursorLeft()), this, SLOT(onGraphViewMouseCursorLeft())); - connect(ui->qw_graphView, SIGNAL(mouseMoved(int,int)), this, SLOT(onGraphViewMouseMoved(int,int))); - connect(ui->qw_graphView, SIGNAL(mouseButtonTriggered(int,int,Qt::MouseButton,QEvent::Type,QPoint)), this, - SLOT(onMouseButtonTriggered(int,int,Qt::MouseButton,QEvent::Type,QPoint))); - connect(ui->qw_graphView, SIGNAL(redrawNeeded()), this, SLOT(onGraphRedrawNeeded())); + ui->qw_container->setLayout(new QVBoxLayout()); + ui->qw_container->layout()->addWidget(m_graphView); } /* Public functions */ @@ -64,11 +53,6 @@ void SignalView::mouseDoubleClickEvent(QMouseEvent* ev) } } -void SignalView::setControlMode(GraphControlModes mode) -{ - m_graphCtrlMode = mode; -} - void SignalView::setDataTableModel(SignalDataTableModel* model) { ui->qtblv_signalDataTable->setModel(model); @@ -94,262 +78,6 @@ void SignalView::setYUnits(const QString &text) ui->ql_yUnits->setText(text); } -/* Private functions */ - -void SignalView::drawCrosshair(const int x, const int y) -{ - int w, h; - if (m_graph == nullptr) - return; - w = ui->qw_graphView->width(); - h = ui->qw_graphView->height(); - - m_graphPainter->begin(m_graph); - m_graphPainter->setPen(Qt::black); - /* Draw new crosshair */ - m_graphPainter->drawLine(0, y, w, y); /* Horizontal */ - m_graphPainter->drawLine(x, 0, x, h); /* Vertical */ - m_graphPainter->end(); - - m_graphCrosshairX = x; - m_graphCrosshairY = y; - - ui->qw_graphView->setPixmap(*m_graph); - -} - -void SignalView::drawIntegrationBaseline(const int x, const int y) -{ - if (m_graph == nullptr) - return; - m_graphPainter->begin(m_graph); - /* Draw new line */ - m_graphPainter->setPen(Qt::black); - m_graphPainter->drawLine(m_integrateStartX, m_integrateStartY, x, y); - m_graphPainter->end(); - - m_integrateStopX = x; - m_integrateStopY = y; - - ui->qw_graphView->setPixmap(*m_graph); -} - -void SignalView::drawZoomRect(const int x, const int y) -{ - int startX, startY, stopX, stopY; - if (m_graph == nullptr) - return; - - if (x < m_zoomRectStartX) { - startX = x; - stopX = m_zoomRectStartX; - } else { - startX = m_zoomRectStartX; - stopX = x; - } - if (y < m_zoomRectStartY) { - startY = y; - stopY = m_zoomRectStartY; - } else { - startY = m_zoomRectStartY; - stopY = y; - } - - eraseZoomRect(); - - m_graphPainter->begin(m_graph); - m_graphPainter->setPen(Qt::green); - // Top line - m_graphPainter->drawLine(startX, startY, stopX, startY); - // Left line - m_graphPainter->drawLine(startX, startY, startX, stopY); - // Right line - m_graphPainter->drawLine(stopX, startY, stopX, stopY); - // Bottom line - m_graphPainter->drawLine(startX, stopY, stopX, stopY); - - m_zoomRectLastX = x; - m_zoomRectLastY = y; - - m_graphPainter->end(); - - ui->qw_graphView->setPixmap(*m_graph); -} - -void SignalView::eraseCrosshair(bool apply) -{ - int w, h; - if (m_graph == nullptr) - return; - w = ui->qw_graphView->width(); - h = ui->qw_graphView->height(); - - if (m_graphCrosshairX != -1 || m_graphCrosshairY != -1) { - m_graphPainter->begin(m_graph); - m_graphPainter->drawPixmap(m_graphCrosshairX, 0, *m_graphPlain, m_graphCrosshairX, 0, 1, h); - m_graphPainter->drawPixmap(0, m_graphCrosshairY, *m_graphPlain, 0, m_graphCrosshairY, w, 1); - m_graphPainter->end(); - if (apply) - ui->qw_graphView->setPixmap(*m_graph); - } -} - -void SignalView::eraseIntegrationBaseline(bool apply) -{ - int lstartX, lstartY, lstopX, lstopY; - int w, h; - - if (m_graph == nullptr) - return; - if (m_integrateStartX < 0) - return; - - w = ui->qw_graphView->width(); - h = ui->qw_graphView->height(); - - if (m_integrateStartX > m_integrateStopX) { - lstartX = (m_integrateStopX > 1) ? m_integrateStopX - 1 : 0; - lstopX = (m_integrateStartX < w-1) ? m_integrateStartX + 1 : w-1; - } else { - lstartX = (m_integrateStartX > 1) ? m_integrateStartX -1 : 0; - lstopX = (m_integrateStopX < w-1) ? m_integrateStopX + 1 : w-1; - } - if (m_integrateStartY > m_integrateStopY) { - lstartY = (m_integrateStopY > 1) ? m_integrateStopY - 1 : 0; - lstopY = (m_integrateStartY < h-1) ? m_integrateStartY + 1 : h-1; - } else { - lstartY = (m_integrateStartY > 1) ? m_integrateStartY - 1 : 0; - lstopY = (m_integrateStopY < h-1) ? m_integrateStopY + 1 : h-1; - } - - m_graphPainter->begin(m_graph); - m_graphPainter->drawPixmap(lstartX, lstartY, *m_graphPlain, lstartX, lstartY, lstopX - lstartX+1, lstopY - lstartY+1); //FIXME: +1 should not be needed! - m_graphPainter->end(); - - if (apply) - ui->qw_graphView->setPixmap(*m_graph); -} - -void SignalView::eraseZoomRect(bool apply) -{ - int lstartX, lstartY, lstopX, lstopY; - if (m_graph == nullptr) - return; - - if (m_zoomRectLastX < m_zoomRectStartX) { - lstartX = m_zoomRectLastX; - lstopX = m_zoomRectStartX; - } else { - lstartX = m_zoomRectStartX; - lstopX = m_zoomRectLastX; - } - if (m_zoomRectLastY < m_zoomRectStartY) { - lstartY = m_zoomRectLastY; - lstopY = m_zoomRectStartY; - } else { - lstartY = m_zoomRectStartY; - lstopY = m_zoomRectLastY; - } - - m_graphPainter->begin(m_graph); - /* Erase any existing lines */ - // TODO: It might not be necessary to erase all lines every time - OPTIMIZE THIS !!! - // Top line - m_graphPainter->drawPixmap(lstartX, lstartY, *m_graphPlain, lstartX, lstartY, lstopX - lstartX, 1); - // Left line - m_graphPainter->drawPixmap(lstartX, lstartY, *m_graphPlain, lstartX, lstartY, 1, lstopY - lstartY); - // Right line - m_graphPainter->drawPixmap(lstopX, lstartY, *m_graphPlain, lstopX, lstartY, 1, lstopY - lstartY + 1); - // Bottom line - m_graphPainter->drawPixmap(lstartX, lstopY, *m_graphPlain, lstartX, lstopY, lstopX - lstartX + 1, 1); - m_graphPainter->end(); - - if (apply) - ui->qw_graphView->setPixmap(*m_graph); -} - -void SignalView::redrawGraph() -{ - int w = ui->qw_graphView->width(); - int h = ui->qw_graphView->height(); - uint lastColumn = 0; - double yAvg = 0; - double yStep; - QPixmap* fresh = new QPixmap(w, h); - - if (m_graphData == nullptr) - return; - if (w < 1 || h < 1) - return; - - fresh->fill(Qt::white); - m_graphPainter->begin(fresh); - m_graphPainter->setPen(QColor(Qt::blue)); - - /* Scaling */ - yStep = static_cast(h) / fabs(m_graphMax - m_graphMin); - - /* Downscale to grid */ - if (w < m_graphLen) { - double columnsPerPixel = static_cast(m_graphLen) / w; - uint columnsPerLastPixel = 0; - int* block = new int[w]; - //qDebug() << "CPP" << columnsPerPixel << "yStep" << yStep << "Dims" << h << w << "Data" << w*columnsPerPixel << m_graphLen; - for (uint i = 0; i < m_graphLen; i++) { - uint column = i / columnsPerPixel; - if (column != lastColumn) { - yAvg /= columnsPerLastPixel; - block[lastColumn] = h - yStep * (yAvg -m_graphMin); - //qDebug() << "YAVG" << block[lastColumn] << "CPLP" << columnsPerLastPixel; - yAvg = 0; - columnsPerLastPixel= 0; - lastColumn = column; - } - yAvg += m_graphData[i]; - columnsPerLastPixel++; - } - /* Add the last column */ - yAvg /= columnsPerLastPixel; - block[w-1] = h - yStep * (yAvg - m_graphMin); - /* Draw the pixmap */ - for (int i = 1; i < w; i++) - m_graphPainter->drawLine(i-1, floor(block[i-1]+0.5), i, floor(block[i]+0.5)); - //qDebug() << "LAST YAVG" << block[m_graphLen-1] << "CPLP" << columnsPerLastPixel; - delete[] block; - } else { /* Upscale to grid */ - double pixelsPerValue = static_cast(w) / m_graphLen; - uint cPixX; - uint pPixX = 0; - uint cPixY; - uint pPixY = floor((h - yStep * (m_graphData[0] - m_graphMin)) + 0.5); - for (int i = 1; i < m_graphLen; i++) { - cPixX= floor(i * pixelsPerValue + 0.5); - cPixY = h - yStep * (m_graphData[i] - m_graphMin); - //qDebug() << "Upscale" << pPixX << pPixY << cPixX << cPixY; - m_graphPainter->drawLine(pPixX, pPixY, cPixX, cPixY); - pPixX = cPixX; - pPixY = cPixY; - } - } - - m_graphPainter->end(); - if (m_graphPlain != nullptr) - delete m_graphPlain; - m_graphPlain = new QPixmap(*fresh); - ui->qw_graphView->setPixmap(*fresh); - if (m_graph != nullptr) - delete m_graph; - m_graph = fresh; -} - -void SignalView::resizeEvent(QResizeEvent* ev) -{ - Q_UNUSED(ev); - - emit resized(ui->qw_graphView->width(), ui->qw_graphView->height()); - emit redrawNeeded(); -} - void SignalView::onUpdateCurrentValues(double x, double y) { QLocale l = QLocale::system(); @@ -363,197 +91,7 @@ void SignalView::onRemoveCurrentValues() ui->qle_yValue->setText("-"); } -/* Public slots */ -void SignalView::onControlModeChanged(GraphControlModes mode) -{ - m_graphCtrlMode = mode; -} - -void SignalView::onDrawIntegration(const int fromX, const double fromY, const int toX, const double toY, const int peakX, const double peakY, const QString& time, - const QString& area, const bool valley) -{ - int w, h; - int startX, startY, stopX, stopY, peakStartX, peakStartY; - double yStep, xStep; - double dStartY, dStopY; - QFont font("arial", 10); - QFontMetrics fm(font); - int textWidth; - if (m_graphPlain == nullptr) - return; - - w = ui->qw_graphView->width(); - h = ui->qw_graphView->height(); - xStep = static_cast(w) / m_graphLen; - yStep = static_cast(h) / (m_graphMax - m_graphMin); - startX = floor(fromX * xStep + 0.5); - stopX = floor(toX * xStep + 0.5); - startY = floor((h - yStep * (fromY - m_graphMin)) + 0.5); - stopY = floor((h - yStep * (toY - m_graphMin)) + 0.5); - peakStartX = floor(peakX * xStep + 0.5); - peakStartY = floor(h - yStep * (peakY - m_graphMin) + 0.5); - - dStartY = h - yStep * (fromY - m_graphMin); - dStopY = h - yStep * (toY - m_graphMin); - - /*qDebug("Drawing peak"); - qDebug() << "RSX" << fromX << "RSY" << fromY << "REX" << toX << "REY" << toY; - qDebug() << "X step" << xStep << "Y step" << yStep; - qDebug() << "SX" << startX << "SY" << startY << "EX" << stopX << "EY" << stopY << "w/h" << w << h; - qDebug() << "DSY" << dStartY << "DEY" << dStopY << "Slope I" << (toY-fromY)/(toX-fromX) << "Slope D" << (dStopY-dStartY)/(toX-fromX); - qDebug("---");*/ - - m_graphPainter->begin(m_graphPlain); - m_graphPainter->setPen(Qt::red); - m_graphPainter->drawLine(startX, startY, stopX, stopY); - - /* Draw AREA and TIME caption */ - m_graphPainter->setFont(font); - m_graphPainter->setPen(Qt::black); - textWidth = fm.width(time); - if (peakStartY - textWidth < 2) - peakStartY += textWidth - peakStartY + 2; - m_graphPainter->save(); - m_graphPainter->translate(peakStartX, peakStartY); - m_graphPainter->rotate(-90); - m_graphPainter->drawText(0, 0, time); - m_graphPainter->rotate(+90); - m_graphPainter->restore(); - m_graphPainter->drawText(peakStartX + 5, peakStartY, area); - - m_graphPainter->end(); - m_graphPainter->begin(m_graph); - m_graphPainter->drawPixmap(0, 0, *m_graphPlain, 0, 0, w, h); - m_graphPainter->end(); - ui->qw_graphView->setPixmap(*m_graph); -} - -void SignalView::onUpdateGraph(double* data, size_t len, double min, double max) -{ - if (m_graphData != nullptr) - delete[] m_graphData; - m_graphData = data; - m_graphLen = len; - m_graphMin = min; - m_graphMax = max; - - redrawGraph(); -} -/* ENDOF public slots */ - -/* Private slots*/ -void SignalView::onGraphViewMouseCursorLeft() -{ - if(m_graph == nullptr) - return; - - ui->qw_graphView->setPixmap(*m_graphPlain); - - emit crosshairErased(); -} - -void SignalView::onGraphRedrawNeeded() -{ - emit redrawNeeded(); -} - -void SignalView::onMouseButtonTriggered(const int x, const int y, Qt::MouseButton button, QEvent::Type type, const QPoint& globalPos) -{ - if (m_ctxMenuOpen) - return; - - switch (button) { - case Qt::LeftButton: - switch (m_mouseMode) { - case SignalView::MouseMode::CROSSHAIR: - if (m_graphCtrlMode == GraphControlModes::ZOOM) { - m_zoomRectStartX = x; - m_zoomRectStartY = y; - m_zoomRectLastX = x; - m_zoomRectLastY = y; - m_mouseMode = SignalView::MouseMode::ZOOM; - } else if (m_graphCtrlMode == GraphControlModes::INTEGRATE) { - m_integrateStartX = x; - m_integrateStartY = y; - m_integrateStopX = x; - m_integrateStopY = y; - eraseCrosshair(); - m_graphCrosshairX = -1; - m_mouseMode = SignalView::MouseMode::INTEGRATE; - } - break; - case SignalView::MouseMode::ZOOM: - if (m_zoomRectLastX < m_zoomRectStartX) - std::swap(m_zoomRectLastX, m_zoomRectStartX); - if (m_zoomRectLastY < m_zoomRectStartY) - std::swap(m_zoomRectLastY, m_zoomRectStartY); - emit zoomed(m_zoomRectStartX, m_zoomRectStartY, m_zoomRectLastX, m_zoomRectLastY); - m_mouseMode = SignalView::MouseMode::CROSSHAIR; - break; - case SignalView::MouseMode::INTEGRATE: - if (m_integrateStartX > m_integrateStopX) - std::swap(m_integrateStartX, m_integrateStopX); - emit integrated(m_integrateStartX, m_integrateStartY, m_integrateStopX, m_integrateStopY); - eraseIntegrationBaseline(true); - m_integrateStartX = -1; - m_mouseMode = SignalView::MouseMode::CROSSHAIR; - break; - } - break; - case Qt::RightButton: - switch (m_mouseMode) { - case SignalView::MouseMode::CROSSHAIR: - m_ctxMenuOpen = true; - emit showContextMenu(x, y, globalPos); - break; - case SignalView::MouseMode::ZOOM: - eraseZoomRect(true); - m_mouseMode = SignalView::MouseMode::CROSSHAIR; - break; - case SignalView::MouseMode::INTEGRATE: - eraseIntegrationBaseline(true); - m_mouseMode = SignalView::MouseMode::CROSSHAIR; - break; - default: - break; - } - break; - default: - break; - } -} - -void SignalView::onGraphViewMouseMoved(const int x, const int y) -{ - switch (m_mouseMode) { - case SignalView::MouseMode::CROSSHAIR: - eraseCrosshair(); - drawCrosshair(x, y); - break; - case SignalView::MouseMode::ZOOM: - eraseCrosshair(); - drawZoomRect(x, y); - break; - case SignalView::MouseMode::INTEGRATE: - eraseIntegrationBaseline(); - drawIntegrationBaseline(x, y); - break; - } - - emit crosshairMoved(x, y); -} - SignalView::~SignalView() { - if (m_graphPainter->isActive()) - m_graphPainter->end(); delete ui; - if (m_graph != nullptr) - delete m_graph; - if (m_graphPlain != nullptr) - delete m_graphPlain; - if (m_graphData != nullptr) - delete[] m_graphData; - - delete m_graphPainter; } diff --git a/gui/signalview.h b/gui/signalview.h index cd6507c..4989f1b 100644 --- a/gui/signalview.h +++ b/gui/signalview.h @@ -27,8 +27,8 @@ #include "integrationtablemodel.h" #include "signaldatatablemodel.h" #include +#include #include -#include "../metatypes.h" namespace Ui { class SignalView; @@ -37,86 +37,29 @@ namespace Ui { class SignalView : public QWidget { Q_OBJECT - public: - enum class MouseMode { - CROSSHAIR, - ZOOM, - INTEGRATE - }; - explicit SignalView(QWidget* parent = nullptr); ~SignalView(); void mouseDoubleClickEvent(QMouseEvent* ev); - void setControlMode(GraphControlModes mode); - void setDataTableModel (SignalDataTableModel* model); + void setDataTableModel(SignalDataTableModel* model); void setIntegrationTableModel(IntegrationTableModel* model); void setTypeText(const QString& text); void setXUnits(const QString& text); void setYUnits(const QString& text); -private: - void drawCrosshair(const int x, const int y); - void drawIntegrationBaseline(const int x, const int y); - void drawZoomRect(const int x, const int y); - void eraseCrosshair(bool apply = false); - void eraseIntegrationBaseline(bool apply = false); - void eraseZoomRect(bool apply = false); - void redrawGraph(); - void resizeEvent(QResizeEvent* ev); + GraphView* m_graphView; - QPainter* m_graphPainter; - /* Dataset to plot */ - QPixmap* m_graph; - QPixmap* m_graphPlain; - double* m_graphData; - double m_graphMin; - double m_graphMax; - size_t m_graphLen; - /* Crosshair */ - int m_graphCrosshairX; - int m_graphCrosshairY; - /* Integration baseline */ - int m_integrateStartX; - int m_integrateStartY; - int m_integrateStopX; - int m_integrateStopY; - /* Zooming rectangle */ - int m_zoomRectStartX; - int m_zoomRectStartY; - int m_zoomRectLastX; - int m_zoomRectLastY; - - bool m_ctxMenuOpen; - GraphControlModes m_graphCtrlMode; - MouseMode m_mouseMode; +private: Ui::SignalView* ui; public slots: - void onControlModeChanged(GraphControlModes mode); - void onCtxMenuClosed() { m_ctxMenuOpen = false; } - void onDrawIntegration(const int fromX, const double fromY, const int toX, const double toY, const int peakX, const double peakY, - const QString& time, const QString& area, const bool valley); - void onMouseButtonTriggered(const int x, const int y, Qt::MouseButton button, QEvent::Type type, const QPoint& globalPos); void onUpdateCurrentValues(double x, double y); void onRemoveCurrentValues(); - void onUpdateGraph(double* arr, size_t len, double min, double max); private slots: - void onGraphRedrawNeeded(); - void onGraphViewMouseCursorLeft(); - void onGraphViewMouseMoved(const int x, const int y); signals: - void crosshairErased(); - void crosshairMoved(const int x, const int y); void fullSizeToggle(); - void integrated(const int fromX, const int fromY, const int toX, const int toY); - void redrawNeeded(); - void resized(const int x, const int y); - void showContextMenu(const int x, const int y, const QPoint& globalPos); - void unzoomed(); - void zoomed(const int fromX, const int fromY, const int toX, const int toY); }; #endif // SIGNALVIEW_H diff --git a/gui/signalview.ui b/gui/signalview.ui index 03f18f1..e8faab7 100644 --- a/gui/signalview.ui +++ b/gui/signalview.ui @@ -67,24 +67,29 @@ - + - + 0 0 - - - 0 - 10 - - + + + + 120 + 60 + 160 + 80 + + + + - + - @@ -97,7 +102,7 @@ - + - @@ -110,21 +115,21 @@ - + Y: - + - - + @@ -137,7 +142,7 @@ - + X: @@ -172,14 +177,6 @@ - - - GraphView - QWidget -
gui/graphview.h
- 1 -
-
diff --git a/mathhelpers.h b/mathhelpers.h index f608875..9d03215 100644 --- a/mathhelpers.h +++ b/mathhelpers.h @@ -30,4 +30,11 @@ template T average(T* vals, size_t len) { return sum / len; } +template T clamp(T in, T min, T max) { + if (in < min) + return min; + if (in > max) + return max; +} + #endif // MATHHELPERS_H diff --git a/metatypes.h b/metatypes.h index 96323fe..133bc1c 100644 --- a/metatypes.h +++ b/metatypes.h @@ -23,6 +23,8 @@ #ifndef METATYPES_H #define METATYPES_H +#include + class SignalView; typedef std::shared_ptr SignalViewPtr; Q_DECLARE_METATYPE(SignalViewPtr); diff --git a/signalcontroller.cpp b/signalcontroller.cpp index ee722cc..44e62cb 100644 --- a/signalcontroller.cpp +++ b/signalcontroller.cpp @@ -94,7 +94,7 @@ void SignalController::drawGraph() for (uint idx = 0; idx < len; idx++) arr[idx] = m_signal->valueAt(idx + m_fromIdx); - emit guiDrawGraph(arr, len, m_yMin, m_yMax); + emit viewDrawGraph(arr, len, m_yMin, m_yMax); } void SignalController::drawIntegratedPeak(const std::shared_ptr peak) @@ -264,6 +264,7 @@ void SignalController::onViewRedrawNeeded() void SignalController::onViewResized(const int w, const int h) { + qDebug() << "Setting GW size" << w << h; m_viewHeight = h; m_viewWidth = w; } diff --git a/signalcontroller.h b/signalcontroller.h index a21d65c..44c59c0 100644 --- a/signalcontroller.h +++ b/signalcontroller.h @@ -79,11 +79,11 @@ public slots: signals: void viewCtxMenuClosed(); + void viewDrawGraph(double* data, size_t len, double min, double max); void viewDrawIntegration(const int fromX, const double fromY, const int toX, const double toY, const int peakX, const double peakY, const QString& peakTime, const QString& peakArea, const bool valley); void viewUpdateCurrentValues(double x, double y); void viewRemoveCurrentValues(); - void guiDrawGraph(double* data, size_t len, double min, double max); void fillDataList(); -- 2.43.5