From acd5c3f863ab10bce4a14f1f7509973ce6d2958a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michal=20Mal=C3=BD?= Date: Tue, 18 Feb 2014 23:37:09 +0100 Subject: [PATCH] - Continue the redesign towards the new relative coordinates system - Draw scales on graphs - Create a fresh pixmap separately at the beginning of the rendering process --- gui/graphview.cpp | 17 ++- signalcontroller.cpp | 39 +++++++ signalcontroller.h | 55 +++------- signaldrawer.cpp | 250 +++++++++++++++++++++++++++++++++---------- signaldrawer.h | 26 ++++- 5 files changed, 279 insertions(+), 108 deletions(-) diff --git a/gui/graphview.cpp b/gui/graphview.cpp index 0d2128e..91d5cd3 100644 --- a/gui/graphview.cpp +++ b/gui/graphview.cpp @@ -35,9 +35,11 @@ GraphView::GraphView(std::shared_ptr controller, QWidget* pare m_graphCrosshairXPix(-1), m_graphCrosshairYPix(-1) { - setDefaultZoom(); setMouseTracking(true); setCursor(Qt::BlankCursor); + setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding)); + setMinimumWidth(SignalDrawer::SCALE_MARGIN_VALUE); + setMinimumHeight(SignalDrawer::SCALE_MARGIN_TIME); connect(&m_ctxMenu, SIGNAL(deletePeak(QPoint)), this, SLOT(onCtxMenuDeletePeak(QPoint))); connect(&m_ctxMenu, SIGNAL(zoomOut()), this, SLOT(onCtxMenuZoomOut())); @@ -133,11 +135,6 @@ void GraphView::mousePressEvent(QMouseEvent* ev) } break; case GraphView::MouseMode::ZOOM: - if (m_zoomRectLastXPix < m_zoomRectStartXPix) - std::swap(m_zoomRectLastXPix, m_zoomRectStartXPix); - if (m_zoomRectLastYPix > m_zoomRectStartYPix) - std::swap(m_zoomRectLastYPix, m_zoomRectStartYPix); - zoom(m_zoomRectStartXPix, m_zoomRectStartYPix, m_zoomRectLastXPix, m_zoomRectLastYPix); m_mouseMode = GraphView::MouseMode::CROSSHAIR; break; @@ -148,7 +145,9 @@ void GraphView::mousePressEvent(QMouseEvent* ev) PeakDrawData pdData = m_controller->integratePeak(xPixToRel(m_integrateStartXPix), yPixToRel(m_integrateStartYPix), xPixToRel(m_integrateStopXPix), yPixToRel(m_integrateStopYPix)); eraseIntegrationBaseline(true); - update(renderPeak(pdData)); + QRect rect = renderPeak(pdData, m_background); + copyPixmapRegion(rect, m_background, m_pixmap); + update(rect); m_integrateStartXPix = -1; m_mouseMode = GraphView::MouseMode::CROSSHAIR; break; @@ -468,8 +467,8 @@ void GraphView::zoom(const int fromXPix, const int fromYPix, const int toXPix, c void GraphView::onCtxMenuDeletePeak(const QPoint pixPos) { const PeakDrawData pdData = m_controller->deletePeak(xPixToRel(pixPos.x())); - QRegion reg = erasePeak(pdData); - refresh(reg); + QRect rect = erasePeak(pdData); + refresh(rect); } void GraphView::onCtxMenuZoomOut() diff --git a/signalcontroller.cpp b/signalcontroller.cpp index 520bc8c..d073d11 100644 --- a/signalcontroller.cpp +++ b/signalcontroller.cpp @@ -129,6 +129,45 @@ std::vector SignalController::getPeaksDrawData(const double fromX, return peaks; } +RulerDrawData SignalController::getRulerDrawData(const double from, const double to, Axis axis) +{ + double diffAbs, diffRel; + double fromAbs, toAbs; + double step, relStep; + double firstTickAbs, firstTickRel; + + diffRel = to - from; + + switch (axis) { + case Axis::TIME: + fromAbs = m_signal->timeAt(relToIdx(from)); + toAbs = m_signal->timeAt(relToIdx(to)); + break; + case Axis::VALUE: + fromAbs = relToValue(from); + toAbs = relToValue(to); + break; + } + + if (axis == Axis::VALUE) + qDebug() << " ---- VALUE SCALE ----"; + + /* Calculate step */ + diffAbs = toAbs - fromAbs; + step = 1 / pow(10, floor(log10(1 / (diffAbs))) + 1); // Magic - you want to love it but you better not touch! + relStep = (diffRel * step) / (diffAbs); + if (axis == Axis::VALUE) + qDebug() << __QFUNC__ << "Step" << step << "RelStep" << relStep << "relDiff" << diffRel; + + /* Calculate position of the first major tick */ + firstTickAbs = ceil(fromAbs / step) * step; + firstTickRel = (diffRel / diffAbs) * (firstTickAbs - fromAbs) + from; + if (axis == Axis::VALUE) + qDebug() << __QFUNC__ << "First tick Abs:" << firstTickAbs << "Rel:" << firstTickRel; + + return RulerDrawData(firstTickAbs, firstTickRel, step, relStep); +} + Signal::TimeValuePair SignalController::getXYValues(const double x) { size_t idx = relToIdx(x); diff --git a/signalcontroller.h b/signalcontroller.h index 3e53a3d..ee84f09 100644 --- a/signalcontroller.h +++ b/signalcontroller.h @@ -30,6 +30,8 @@ #include #include +#include + struct GraphDrawData { GraphDrawData() : ddata(nullptr), ddataLen(0) {} @@ -56,25 +58,31 @@ struct PeakDrawData { const double auc, time; }; +struct RulerDrawData { + RulerDrawData() : firstTickAbs(0), firstTickRel(0), step(0), relStep(0) {} + RulerDrawData(const double fta, const double ftr, const double s, const double rs) : firstTickAbs(fta), firstTickRel(ftr), step(s), relStep(rs) + {} + + const double firstTickAbs; + const double firstTickRel; + const double step; + const double relStep; +}; + class SignalController : public QObject { Q_OBJECT public: + enum class Axis { TIME, VALUE }; + explicit SignalController(std::shared_ptr signal, QObject* parent = nullptr); ~SignalController(); - /*double currentYMax() const { return m_yMax; } - double currentYMin() const { return m_yMin; } - double currentStartX() const; - double currentStartY() const; - double currentStopX() const; - double currentStopY() const; - void draw();*/ - SignalDataTableModel* dataTableModel() { return m_dtblModel; } + SignalDataTableModel* dataTableModel() { return m_dtblModel; } PeakDrawData deletePeak(const double x); - //double* generateDrawData(size_t from, size_t to); Signal::TimeValuePair getXYValues(const double x); std::shared_ptr getGraphDrawData(const double fromX, const double toX); std::vector getPeaksDrawData(const double fromX, const double fromY, const double toX, const double toY); + RulerDrawData getRulerDrawData(const double from, const double to, SignalController::Axis axis); double fromXAbs() const { return m_signal->timeAt(0); } double toXAbs() const { return m_signal->timeAt(m_signal->count()-1); } double fromYAbs() const { return m_signal->valueAt(0); } @@ -88,53 +96,24 @@ public: static const double RELATIVE_MIN; private: - //GraphViewContextMenu m_ctxMenu; - //int m_ctxMenuX; - //int m_ctxMenuY; SignalDataTableModel* m_dtblModel; - //uint m_fromIdx; - //uint m_toIdx; IntegrationTableModel* m_integTblModel; std::shared_ptr m_integrator; std::shared_ptr m_signal; - //int m_viewHeight; - //int m_viewWidth; - //double m_yMax; - //double m_yMin; double idxToRel(const size_t idx); double valueToRel(const double value); size_t relToIdx(const double rel); double relToValue(const double rel); - //void drawAllPeaks(); - //void drawFullGraph(); - //void drawGraph(); void drawIntegratedPeak(const std::shared_ptr peak); PeakDrawData genPeakDrawData(const std::shared_ptr peak); - //bool updateConstraints(const int fromX, const int fromY, const int toX, const int to); - //double yValToCoord(double y); static const QString ME_SENDER_STR; public slots: - /*void onCtxMenuUnzoom(); - void onCtxMenuDeletePeak(); - void onViewCrosshairErased(); - void onViewCrosshairMoved(const int x, const int y); - void onViewIntegrated(const int fromX, const int fromY, const int toX, const int toY); - void onViewRedrawNeeded(); - void onViewResized(const int w, const int h); - void onViewShowContextMenu(const int x, const int y, const QPoint& globalPos); - bool onViewZoomed(const int fromX, const int fromY, const int toX, const int toY); - bool onViewZoomedByValues(const double fromX, const double fromY, const double toX, const double toY);*/ signals: - //void viewCtxMenuClosed(); - //void viewDrawGraph(double* data, size_t len, double min, double max); - //void viewDrawIntegration(int startX, double startY, int stopX, double stopY, int peakStartX, double peakStartY, const QString& time, const QString& area); - //void viewUpdateCurrentValues(double x, double y); - //void viewRemoveCurrentValues(); void fillDataList(); }; diff --git a/signaldrawer.cpp b/signaldrawer.cpp index b246a4d..09559b5 100644 --- a/signaldrawer.cpp +++ b/signaldrawer.cpp @@ -4,6 +4,8 @@ #include const QString SignalDrawer::ME_SENDER_STR("SignalDrawer"); +const int SignalDrawer::SCALE_MARGIN_TIME(16); +const int SignalDrawer::SCALE_MARGIN_VALUE(48); SignalDrawer::SignalDrawer(std::shared_ptr controller) : m_controller(controller), @@ -21,67 +23,191 @@ Constraints SignalDrawer::currentConstraints() bool SignalDrawer::draw(const double fromX, const double fromY, const double toX, const double toY) { + QPixmap* fresh; bool ret; setNewRelativeConstraints(fromX, fromY, toX, toY); - ret = drawGraph(fromX, fromY, toX, toY); + fresh = createFreshPixmap(); + if (fresh == nullptr) + return false; + ret = drawGraph(fresh); if (!ret) { Logger::log(Logger::Level::WARNING, ME_SENDER_STR, __QFUNC__ + " cannot draw graph"); restoreRelativeConstraints(); + delete fresh; return ret; } - ret = drawPeaks(fromX, fromY, toX, toY); + ret = renderScale(SignalController::Axis::VALUE, fresh); + ret = renderScale(SignalController::Axis::TIME, fresh); + ret = drawPeaks(fresh); if (!ret) { Logger::log(Logger::Level::WARNING, ME_SENDER_STR, __QFUNC__ + " cannot draw integrated peaks"); restoreRelativeConstraints(); + delete fresh; return ret; } + renderFresh(fresh); - return ret; + return true; } bool SignalDrawer::setDimensions(const int width, const int height) { - if (width < 0 || height < 0) { + if (width < SCALE_MARGIN_VALUE || height < SCALE_MARGIN_TIME) { Logger::log(Logger::Level::WARNING, ME_SENDER_STR, __QFUNC__ + " invalid dimensions (" + QString::number(width) + ", " + QString::number(height) + ")"); return false; } - m_width = width; m_height = height; + m_width = width; + m_gWidth = width - SCALE_MARGIN_VALUE; + m_gHeight = height - SCALE_MARGIN_TIME; + + qDebug() << __QFUNC__ << width << height << m_width << m_height; return draw(); } /** Protected methods **/ -bool SignalDrawer::drawGraph(const double fromX, const double fromY, const double toX, const double toY) +void SignalDrawer::copyPixmapRegion(const QRect& rect, QPixmap* const source, QPixmap* const target) { - std::shared_ptr gdData = m_controller->getGraphDrawData(fromX, toX); + QPainter p(target); + + p.drawPixmap(rect, *source, rect); +} + +bool SignalDrawer::drawGraph(QPixmap* const target) +{ + std::shared_ptr gdData = m_controller->getGraphDrawData(m_relXMin, m_relXMax); if (gdData->ddataLen == 0) return false; m_gdData = gdData; - return renderGraph(fromY, toY); + return renderGraph(target); } -bool SignalDrawer::drawPeaks(const double fromX, const double fromY, const double toX, const double toY) +bool SignalDrawer::drawPeaks(QPixmap* const target) { - std::vector pdData = m_controller->getPeaksDrawData(fromX, fromY, toX, toY); + std::vector pdData = m_controller->getPeaksDrawData(m_relXMin, m_relYMin, m_relXMax, m_relYMax); if (pdData.size() < 1) return true; for (const PeakDrawData& pd : pdData) { - QRegion reg = renderPeak(pd); + QRegion reg = renderPeak(pd, target); if (reg.isEmpty()) return false; } return true; } -QRegion SignalDrawer::erasePeak(const PeakDrawData& pd) +bool SignalDrawer::renderScale(const SignalController::Axis axis, QPixmap* const target) +{ + QPainter p; + int absVal; + double relMin, relMax; + std::function tickDrawFunc; + std::function textDrawFunc; + + if (target == nullptr) { + Logger::log(Logger::Level::WARNING, ME_SENDER_STR, __QFUNC__ + " null pointer to pixmap"); + return false; + } + + p.begin(target); + switch (axis) { + case SignalController::Axis::TIME: + relMin = m_relXMin; relMax = m_relXMax; + tickDrawFunc = std::bind(&SignalDrawer::renderTimeScaleTick, this, &p, std::placeholders::_1, std::placeholders::_2); + textDrawFunc = std::bind(&SignalDrawer::renderTimeScaleText, this, &p, std::placeholders::_1, std::placeholders::_2); + p.drawLine(SCALE_MARGIN_VALUE, m_gHeight + 1, m_gWidth + SCALE_MARGIN_VALUE, m_gHeight + 1); + break; + case SignalController::Axis::VALUE: + relMin = m_relYMin; relMax = m_relYMax; + tickDrawFunc = std::bind(&SignalDrawer::renderValueScaleTick, this, &p, std::placeholders::_1, std::placeholders::_2); + textDrawFunc = std::bind(&SignalDrawer::renderValueScaleText, this, &p, std::placeholders::_1, std::placeholders::_2); + p.drawLine(SCALE_MARGIN_VALUE - 1, 0, SCALE_MARGIN_VALUE - 1, m_gHeight); + break; + } + + RulerDrawData rd = m_controller->getRulerDrawData(relMin, relMax, axis); + + if (axis == SignalController::Axis::VALUE) + qDebug() << __QFUNC__ << "step" << rd.step << "relStep" << rd.relStep; + + /* Draw subticks before the first tick */ + { + int ctr = 10; + for (double subRel = rd.firstTickRel; subRel >= relMin; subRel -= rd.relStep / 10) + tickDrawFunc(subRel, (--ctr == 5) ? TickType::TICK : TickType::SUBTICK); + } + /* Draw ticks */ + absVal = rd.firstTickAbs; + for (double rel = rd.firstTickRel; rel <= relMax; rel += rd.relStep) { + tickDrawFunc(rel, TickType::TICK); + textDrawFunc(rel, absVal); + absVal += rd.step; + + /* Draw subticks ticks */ + double subRel = rel; + for (uint i = 1; i < 10; i++) { + subRel += rd.relStep / 10; + tickDrawFunc(subRel, (i == 5) ? TickType::TICK : TickType::SUBTICK); + } + + } + p.end(); + + return true; +} + +void SignalDrawer::renderTimeScaleText(QPainter*const p, const double rel, const double value) +{ + const int xPix = relToXPix(rel); + + p->drawText(xPix + 2, m_gHeight + 15, m_locale.toString(value, 'f', 3)); +} + +void SignalDrawer::renderValueScaleText(QPainter*const p, const double rel, const double value) +{ + const int yPix = relToYPix(rel); + + p->drawText(1, yPix + 5, m_locale.toString(value, 'f', 2)); +} + +void SignalDrawer::renderTimeScaleTick(QPainter*const p, const double rel, const TickType tt) +{ + const int xPix = relToXPix(rel); + + switch (tt) { + case TickType::TICK: + p->drawLine(xPix, m_gHeight + 2, xPix, m_gHeight + 6); + break; + case TickType::SUBTICK: + p->drawLine(xPix, m_gHeight + 2, xPix , m_gHeight + 4); + break; + } +} + +void SignalDrawer::renderValueScaleTick(QPainter*const p, const double rel, const TickType tt) +{ + const int yPix = relToYPix(rel); + + qDebug() << __QFUNC__ << "yPix" << yPix << "rel" << rel; + + switch (tt) { + case TickType::TICK: + p->drawLine(SCALE_MARGIN_VALUE - 6, yPix, SCALE_MARGIN_VALUE - 1, yPix); + break; + case TickType::SUBTICK: + p->drawLine(SCALE_MARGIN_VALUE - 4, yPix, SCALE_MARGIN_VALUE - 1, yPix); + break; + } +} + +QRect SignalDrawer::erasePeak(const PeakDrawData& pd) { QPainter p; QFont font("arial", 10); @@ -95,15 +221,15 @@ QRegion SignalDrawer::erasePeak(const PeakDrawData& pd) if (m_background == nullptr) { Logger::log(Logger::Level::WARNING, ME_SENDER_STR, __QFUNC__ + " null pointer to pixmap"); - return QRegion(); + return QRect(); } /* No peak */ if (pd.auc == 0) - return QRegion(); + return QRect(); - fromXPix = relToXPix(pd.fromX); fromYPix = relToYPix(pd.fromY); - toXPix = relToXPix(pd.toX); toYPix = relToYPix(pd.toY); - peakX = relToXPix(pd.peakX); peakY = relToYPix(pd.peakY); + fromXPix = relToXPix(pd.fromX) + SCALE_MARGIN_VALUE; fromYPix = relToYPix(pd.fromY); + toXPix = relToXPix(pd.toX) + SCALE_MARGIN_VALUE; toYPix = relToYPix(pd.toY); + peakX = relToXPix(pd.peakX) + SCALE_MARGIN_VALUE; peakY = relToYPix(pd.peakY); aucText = m_locale.toString(pd.auc, 'f', 4); timeText = m_locale.toString(pd.time, 'f', 4); tTextWidth = fm.width(timeText); @@ -122,17 +248,16 @@ QRegion SignalDrawer::erasePeak(const PeakDrawData& pd) else endXPix = toXPix; - return QRegion(beginXPix, 0, endXPix - beginXPix, m_height); + return QRect(beginXPix, 0, endXPix - beginXPix, m_height); } -bool SignalDrawer::renderGraph(const double fromY, const double toY) +bool SignalDrawer::renderGraph(QPixmap* const target) { - QPixmap* pixmap; QPainter p; double xStep, yStep; - int fromXPix = 0, fromYPix; + int fromXPix = SCALE_MARGIN_VALUE, fromYPix; - if (m_width < 1 || m_height < 1) { + if (m_width < SCALE_MARGIN_VALUE || m_height < SCALE_MARGIN_VALUE) { Logger::log(Logger::Level::WARNING, ME_SENDER_STR, __QFUNC__ + " invalid dimensions (" + QString::number(m_width) + ", " + QString::number(m_height) + ")"); return false; } @@ -141,19 +266,18 @@ bool SignalDrawer::renderGraph(const double fromY, const double toY) return false; } - pixmap = new QPixmap(m_width, m_height); - p.begin(pixmap); + p.begin(target); p.fillRect(0, 0, m_width, m_height, Qt::white); p.setPen(QColor(Qt::blue)); - xStep = static_cast(m_width) / m_gdData->ddataLen; - yStep = static_cast(m_height) / (toY - fromY); + xStep = static_cast(m_gWidth) / m_gdData->ddataLen; + yStep = static_cast(m_gHeight) / (m_relYMax - m_relYMin); Logger::log(Logger::Level::DEBUG, ME_SENDER_STR, __QFUNC__ + " yStep: " + QString::number(yStep) - + " fY " + QString::number(fromY) + " tY " + QString::number(toY)); - fromYPix = m_height - yStep * (m_gdData->ddata[0] - fromY); + + " fY " + QString::number(m_relYMin) + " tY " + QString::number(m_relYMax)); + fromYPix = m_gHeight - yStep * (m_gdData->ddata[0] - m_relYMin); for (size_t i = 1; i < m_gdData->ddataLen; i++) { - int toXPix = xStep * i; - int toYPix = m_height - yStep * (m_gdData->ddata[i] - fromY); + int toXPix = xStep * i + SCALE_MARGIN_VALUE; + int toYPix = m_gHeight - yStep * (m_gdData->ddata[i] - m_relYMin); p.drawLine(fromXPix, fromYPix, toXPix, toYPix); fromXPix = toXPix; fromYPix = toYPix; @@ -161,17 +285,22 @@ bool SignalDrawer::renderGraph(const double fromY, const double toY) p.end(); + + return true; +} + +void SignalDrawer::renderFresh(QPixmap* const fresh) +{ if (m_pixmap) delete m_pixmap; - m_pixmap = pixmap; + m_pixmap = fresh; if (m_background) delete m_background; m_background = new QPixmap(*m_pixmap); - - return true; } -QRegion SignalDrawer::renderPeak(const PeakDrawData& pd) + +QRect SignalDrawer::renderPeak(const PeakDrawData& pd, QPixmap* const target) { QPainter p; QFont font("arial", 10); @@ -183,21 +312,21 @@ QRegion SignalDrawer::renderPeak(const PeakDrawData& pd) int peakX, peakY; int beginXPix, endXPix; - if (m_background == nullptr) { + if (target == nullptr) { Logger::log(Logger::Level::WARNING, ME_SENDER_STR, __QFUNC__ + " null pointer to pixmap"); - return QRegion(); + return QRect(); } /* No peak */ if (pd.auc == 0) - return QRegion(); + return QRect(); fromXPix = relToXPix(pd.fromX); fromYPix = relToYPix(pd.fromY); toXPix = relToXPix(pd.toX); toYPix = relToYPix(pd.toY); peakX = relToXPix(pd.peakX); peakY = relToYPix(pd.peakY); aucText = m_locale.toString(pd.auc, 'f', 4); - timeText = m_locale.toString(pd.time, 'f', 4); + timeText = QString("A:") + m_locale.toString(pd.time, 'f', 4); - p.begin(m_background); + p.begin(target); p.setPen(Qt::red); p.drawLine(fromXPix, fromYPix, toXPix, toYPix); @@ -228,33 +357,31 @@ QRegion SignalDrawer::renderPeak(const PeakDrawData& pd) else endXPix = toXPix; - /* Copy peak to foreground pixmap */ - p.begin(m_pixmap); - p.drawPixmap(beginXPix, 0, *m_background, beginXPix, 0, endXPix - beginXPix, m_height); - p.end(); - - return QRegion(beginXPix, 0, endXPix - beginXPix, m_height); + return QRect(beginXPix, 0, endXPix - beginXPix, m_height); } /** Private functions **/ int SignalDrawer::relToXPix(const double rel) { - const int ret = m_width / (m_relXMax - m_relXMin) * (rel - m_relXMin); + const int ret = m_gWidth / (m_relXMax - m_relXMin) * (rel - m_relXMin) + SCALE_MARGIN_VALUE; //qDebug() << __QFUNC__ << ret; return ret; } int SignalDrawer::relToYPix(const double rel) { - const int ret = m_height - (m_height / (m_relYMax - m_relYMin) * (rel - m_relYMin)); + const int ret = m_gHeight - (m_gHeight / (m_relYMax - m_relYMin) * (rel - m_relYMin)); //qDebug() << __QFUNC__ << ret; return ret; } double SignalDrawer::xPixToRel(const int pix) { - const double ret = (pix * (m_relXMax - m_relXMin) / m_width) + m_relXMin; + double ret; + if (pix < SCALE_MARGIN_VALUE) + return 0.0; + ret = ((pix - SCALE_MARGIN_VALUE) * (m_relXMax - m_relXMin) / m_gWidth) + m_relXMin; //qDebug() << __QFUNC__ << ret; return ret; } @@ -262,10 +389,10 @@ double SignalDrawer::xPixToRel(const int pix) double SignalDrawer::yPixToRel(const int pix) { const double range = m_relYMax - m_relYMin; - const int invPix = m_height - pix; - const double ret = (range / m_height * invPix) + m_relYMin; - //qDebug() << __QFUNC__ << ret; - return ret; + const int invPix = m_gHeight - pix; + if (invPix < 0) + return 0; + return (range / m_gHeight * invPix) + m_relYMin; } /** Private methods **/ @@ -285,10 +412,21 @@ void SignalDrawer::setNewRelativeConstraints(const double fromX, const double fr m_oldRelYMin = m_relYMin; m_oldRelYMax = m_relYMax; - m_relXMin = fromX; - m_relXMax = toX; - m_relYMin = fromY; - m_relYMax = toY; + if (fromX < toX) { + m_relXMin = fromX; + m_relXMax = toX; + } else { + m_relXMin = toX; + m_relXMax = fromX; + } + + if (fromY < toY) { + m_relYMin = fromY; + m_relYMax = toY; + } else { + m_relYMin = toY; + m_relYMax = fromY; + } } SignalDrawer::~SignalDrawer() diff --git a/signaldrawer.h b/signaldrawer.h index 95e97ad..dd5ba6a 100644 --- a/signaldrawer.h +++ b/signaldrawer.h @@ -24,15 +24,18 @@ public: int dheight() const { return m_height; } bool draw(const double fromX = SignalController::RELATIVE_MIN, const double fromY = SignalController::RELATIVE_MIN, const double toX = SignalController::RELATIVE_MAX, const double toY = SignalController::RELATIVE_MAX); - bool drawGraph(const double fromX, const double fromY, const double toX, const double toY); - bool drawPeaks(const double fromX, const double fromY, const double toX, const double toY); - QRegion erasePeak(const PeakDrawData& pd); + bool drawGraph(QPixmap* const target); + bool drawPeaks(QPixmap* const target); + QRect erasePeak(const PeakDrawData& pd); int dwidth() const { return m_width; } - bool renderGraph(const double fromY, const double toY); - QRegion renderPeak(const PeakDrawData& pd); + bool renderGraph(QPixmap* const fresh); + QRect renderPeak(const PeakDrawData& pd, QPixmap* const target); + bool renderScale(const SignalController::Axis axis, QPixmap* const target); bool setDimensions(const int width, const int height); protected: + enum class TickType { TICK, SUBTICK }; + std::shared_ptr m_controller; QLocale m_locale; QPixmap* m_background; @@ -44,14 +47,27 @@ protected: double m_relYMin; std::shared_ptr m_gdData; + void copyPixmapRegion(const QRect& region, QPixmap* const source, QPixmap* const target); + QPixmap* createFreshPixmap() { return new QPixmap(m_width, m_height); } + void renderFresh(QPixmap* const fresh); + void renderTimeScaleText(QPainter*const p, const double rel, const double value); + void renderValueScaleText(QPainter*const p, const double rel, const double value); + void renderTimeScaleTick(QPainter*const p, const double rel, const TickType tt); + void renderValueScaleTick(QPainter*const p, const double rel, const TickType tt); + int relToXPix(const double rel); int relToYPix(const double rel); double xPixToRel(const int pix); double yPixToRel(const int pix); + static const int SCALE_MARGIN_TIME; + static const int SCALE_MARGIN_VALUE; + private: int m_height; int m_width; + int m_gHeight; + int m_gWidth; double m_oldRelXMax; double m_oldRelXMin; -- 2.43.5