diff --git a/src/AllPlot.cpp b/src/AllPlot.cpp index 437e3fccc..7fe3dec8b 100644 --- a/src/AllPlot.cpp +++ b/src/AllPlot.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2006 Sean C. Rhea (srhea@srhea.net) + * Copyright (c) 2010 Mark Liversedge (liversedge@gmail.com) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -224,10 +225,234 @@ class TimeScaleDraw: public QwtScaleDraw }; - static inline double max(double a, double b) { if (a > b) return a; else return b; } +AllPlotObject::AllPlotObject(AllPlot *plot) : plot(plot) +{ + maxKM = maxSECS = 0; + + wattsCurve = new QwtPlotCurve(tr("Power")); + wattsCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + wattsCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 0)); + + npCurve = new QwtPlotCurve(tr("NP")); + npCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + npCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 0)); + + xpCurve = new QwtPlotCurve(tr("xPower")); + xpCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + xpCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 0)); + + apCurve = new QwtPlotCurve(tr("aPower")); + apCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + apCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 0)); + + hrCurve = new QwtPlotCurve(tr("Heart Rate")); + hrCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + hrCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); + + speedCurve = new QwtPlotCurve(tr("Speed")); + speedCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + speedCurve->setYAxis(QwtAxisId(QwtAxis::yRight, 0)); + + cadCurve = new QwtPlotCurve(tr("Cadence")); + cadCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + cadCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); + + altCurve = new QwtPlotCurve(tr("Altitude")); + altCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + // standard->altCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + altCurve->setYAxis(QwtAxisId(QwtAxis::yRight, 1)); + altCurve->setZ(-10); // always at the back. + + tempCurve = new QwtPlotCurve(tr("Temperature")); + tempCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + if (plot->context->athlete->useMetricUnits) + tempCurve->setYAxis(QwtAxisId(QwtAxis::yRight, 0)); + else + tempCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); // with cadence + + windCurve = new QwtPlotIntervalCurve(tr("Wind")); + windCurve->setYAxis(QwtAxisId(QwtAxis::yRight, 0)); + + torqueCurve = new QwtPlotCurve(tr("Torque")); + torqueCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + torqueCurve->setYAxis(QwtAxisId(QwtAxis::yRight, 0)); + + balanceLCurve = new QwtPlotCurve(tr("Left Balance")); + balanceLCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + balanceLCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); + + balanceRCurve = new QwtPlotCurve(tr("Right Balance")); + balanceRCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + balanceRCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); + + wCurve = new QwtPlotCurve(tr("W' Balance (j)")); + wCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + wCurve->setYAxis(QwtAxisId(QwtAxis::yRight, 2)); + + mCurve = new QwtPlotCurve(tr("Matches")); + mCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + mCurve->setStyle(QwtPlotCurve::Dots); + mCurve->setYAxis(QwtAxisId(QwtAxis::yRight, 2)); + + curveTitle.attach(plot); + curveTitle.setLabelAlignment(Qt::AlignRight); + + intervalHighlighterCurve = new QwtPlotCurve(); + intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 0)); + intervalHighlighterCurve->attach(plot); + + // setup that standard->grid + grid = new QwtPlotGrid(); + grid->enableX(true); + grid->enableY(true); + grid->attach(plot); + +} + +// we tend to only do this for the compare objects +void +AllPlotObject::setColor(QColor color) +{ + QList worklist; + worklist << mCurve << wCurve << wattsCurve << npCurve << xpCurve << speedCurve + << apCurve << cadCurve << tempCurve << hrCurve << torqueCurve << balanceLCurve + << balanceRCurve << altCurve; + + // work through getting progresively lighter + QPen pen; + pen.setWidth(1.0); + int alpha = 200; + bool antialias = appsettings->value(this, GC_ANTIALIAS, false).toBool(); + foreach(QwtPlotCurve *c, worklist) { + + pen.setColor(color); + color.setAlpha(alpha); + + c->setPen(pen); + if (antialias) c->setRenderHint(QwtPlotItem::RenderAntialiased); + + // lighten up for the next guy + color = color.darker(110); + alpha -= 10; + } + + // has to be different... + windCurve->setPen(pen); + if (antialias)windCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + + // and alt needs a feint brush + altCurve->setBrush(QBrush(altCurve->pen().color().lighter(150))); + +} + +// wipe those curves +AllPlotObject::~AllPlotObject() +{ + grid->detach(); delete grid; + mCurve->detach(); delete mCurve; + wCurve->detach(); delete wCurve; + wattsCurve->detach(); delete wattsCurve; + npCurve->detach(); delete npCurve; + xpCurve->detach(); delete xpCurve; + apCurve->detach(); delete apCurve; + hrCurve->detach(); delete hrCurve; + speedCurve->detach(); delete speedCurve; + cadCurve->detach(); delete cadCurve; + altCurve->detach(); delete altCurve; + tempCurve->detach(); delete tempCurve; + windCurve->detach(); delete windCurve; + torqueCurve->detach(); delete torqueCurve; + balanceLCurve->detach(); delete balanceLCurve; + balanceRCurve->detach(); delete balanceRCurve; +} + +void +AllPlotObject::setVisible(bool show) +{ + if (show == false) { + + grid->detach(); + mCurve->detach(); + wCurve->detach(); + wattsCurve->detach(); + npCurve->detach(); + xpCurve->detach(); + apCurve->detach(); + hrCurve->detach(); + speedCurve->detach(); + cadCurve->detach(); + altCurve->detach(); + tempCurve->detach(); + windCurve->detach(); + torqueCurve->detach(); + balanceLCurve->detach(); + balanceRCurve->detach(); + intervalHighlighterCurve->detach(); + + // marks, calibrations and reference lines + foreach(QwtPlotMarker *mrk, d_mrk) { + mrk->detach(); + } + foreach(QwtPlotCurve *referenceLine, referenceLines) { + referenceLine->detach(); + } + + } else { + + + altCurve->attach(plot); // always do first as it hasa brush + grid->attach(plot); + mCurve->attach(plot); + wCurve->attach(plot); + wattsCurve->attach(plot); + npCurve->attach(plot); + xpCurve->attach(plot); + apCurve->attach(plot); + hrCurve->attach(plot); + speedCurve->attach(plot); + cadCurve->attach(plot); + tempCurve->attach(plot); + windCurve->attach(plot); + torqueCurve->attach(plot); + balanceLCurve->attach(plot); + balanceRCurve->attach(plot); + + intervalHighlighterCurve->attach(plot); + + // marks, calibrations and reference lines + foreach(QwtPlotMarker *mrk, d_mrk) { + mrk->attach(plot); + } + foreach(QwtPlotCurve *referenceLine, referenceLines) { + referenceLine->attach(plot); + } + + } +} + +void +AllPlotObject::hideUnwanted() +{ + if (plot->showPowerState>1) wattsCurve->detach(); + if (!plot->showNP) npCurve->detach(); + if (!plot->showXP) xpCurve->detach(); + if (!plot->showAP) apCurve->detach(); + if (!plot->showW) wCurve->detach(); + if (!plot->showW) mCurve->detach(); + if (!plot->showHr) hrCurve->detach(); + if (!plot->showSpeed) speedCurve->detach(); + if (!plot->showCad) cadCurve->detach(); + if (!plot->showAlt) altCurve->detach(); + if (!plot->showTemp) tempCurve->detach(); + if (!plot->showWind) windCurve->detach(); + if (!plot->showTorque) torqueCurve->detach(); + if (!plot->showBalance) balanceLCurve->detach(); + if (!plot->showBalance) balanceRCurve->detach(); +} + AllPlot::AllPlot(AllPlotWindow *parent, Context *context, RideFile::SeriesType scope, RideFile::SeriesType secScope, bool wanttext): QwtPlot(parent), rideItem(NULL), @@ -251,12 +476,14 @@ AllPlot::AllPlot(AllPlotWindow *parent, Context *context, RideFile::SeriesType s parent(parent), wanttext(wanttext) { - referencePlot = NULL; if (appsettings->value(this, GC_SHADEZONES, true).toBool()==false) shade_zones = false; smooth = 1; + wantaxis = true; + setAutoDelete(false); // no - we are managing it via the AllPlotObjects now + referencePlot = NULL; // create a background object for shading bg = new AllPlotBackground(this); @@ -273,84 +500,9 @@ AllPlot::AllPlot(AllPlotWindow *parent, Context *context, RideFile::SeriesType s setXTitle(); - wattsCurve = new QwtPlotCurve(tr("Power")); - wattsCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); - wattsCurve->setYAxis(yLeft); + standard = new AllPlotObject(this); - npCurve = new QwtPlotCurve(tr("NP")); - npCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); - npCurve->setYAxis(yLeft); - - xpCurve = new QwtPlotCurve(tr("xPower")); - xpCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); - xpCurve->setYAxis(yLeft); - - apCurve = new QwtPlotCurve(tr("aPower")); - apCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); - apCurve->setYAxis(yLeft); - - hrCurve = new QwtPlotCurve(tr("Heart Rate")); - hrCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); - hrCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); - - speedCurve = new QwtPlotCurve(tr("Speed")); - speedCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); - speedCurve->setYAxis(yRight); - - cadCurve = new QwtPlotCurve(tr("Cadence")); - cadCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); - cadCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); - - altCurve = new QwtPlotCurve(tr("Altitude")); - altCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); - // altCurve->setRenderHint(QwtPlotItem::RenderAntialiased); - altCurve->setYAxis(QwtAxisId(QwtAxis::yRight, 1)); - - tempCurve = new QwtPlotCurve(tr("Temperature")); - tempCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); - if (context->athlete->useMetricUnits) - tempCurve->setYAxis(yRight); // with speed - else - tempCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); // with cadence - - windCurve = new QwtPlotIntervalCurve(tr("Wind")); - windCurve->setYAxis(yRight); - - torqueCurve = new QwtPlotCurve(tr("Torque")); - torqueCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); - torqueCurve->setYAxis(yRight); - - balanceLCurve = new QwtPlotCurve(tr("Left Balance")); - balanceLCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); - balanceLCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); - - balanceRCurve = new QwtPlotCurve(tr("Right Balance")); - balanceRCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); - balanceRCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); - - wCurve = new QwtPlotCurve(tr("W' Balance (j)")); - wCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); - wCurve->setYAxis(QwtAxisId(QwtAxis::yRight, 2)); - - mCurve = new QwtPlotCurve(tr("Matches")); - mCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); - mCurve->setStyle(QwtPlotCurve::Dots); - mCurve->setYAxis(QwtAxisId(QwtAxis::yRight, 2)); - - curveTitle.attach(this); - curveTitle.setLabelAlignment(Qt::AlignRight); - - intervalHighlighterCurve = new QwtPlotCurve(); - intervalHighlighterCurve->setYAxis(yLeft); - intervalHighlighterCurve->setSamples(new IntervalPlotData(this, context)); - intervalHighlighterCurve->attach(this); - //this->legend()->remove(intervalHighlighterCurve); // don't show in legend - - // setup that grid - grid = new QwtPlotGrid(); - grid->enableX(true); - grid->enableY(true); - grid->attach(this); + standard->intervalHighlighterCurve->setSamples(new IntervalPlotData(this, context)); setAxisMaxMinor(xBottom, 0); enableAxis(xBottom, true); @@ -365,163 +517,175 @@ AllPlot::AllPlot(AllPlotWindow *parent, Context *context, RideFile::SeriesType s configChanged(); // set colors } +AllPlot::~AllPlot() +{ + // wipe compare curves if there are any + foreach(QwtPlotCurve *compare, compares) { + compare->detach(); delete compare; + } + compares.clear(); + + // wipe the standard stuff + delete standard; +} + void AllPlot::configChanged() { double width = appsettings->value(this, GC_LINEWIDTH, 2.0).toDouble(); if (appsettings->value(this, GC_ANTIALIAS, false).toBool() == true) { - wattsCurve->setRenderHint(QwtPlotItem::RenderAntialiased); - npCurve->setRenderHint(QwtPlotItem::RenderAntialiased); - xpCurve->setRenderHint(QwtPlotItem::RenderAntialiased); - apCurve->setRenderHint(QwtPlotItem::RenderAntialiased); - wCurve->setRenderHint(QwtPlotItem::RenderAntialiased); - mCurve->setRenderHint(QwtPlotItem::RenderAntialiased); - hrCurve->setRenderHint(QwtPlotItem::RenderAntialiased); - speedCurve->setRenderHint(QwtPlotItem::RenderAntialiased); - cadCurve->setRenderHint(QwtPlotItem::RenderAntialiased); - altCurve->setRenderHint(QwtPlotItem::RenderAntialiased); - tempCurve->setRenderHint(QwtPlotItem::RenderAntialiased); - windCurve->setRenderHint(QwtPlotItem::RenderAntialiased); - torqueCurve->setRenderHint(QwtPlotItem::RenderAntialiased); - balanceLCurve->setRenderHint(QwtPlotItem::RenderAntialiased); - balanceRCurve->setRenderHint(QwtPlotItem::RenderAntialiased); - intervalHighlighterCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->wattsCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->npCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->xpCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->apCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->wCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->mCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->hrCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->speedCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->cadCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->altCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->tempCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->windCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->torqueCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->balanceLCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->balanceRCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->intervalHighlighterCurve->setRenderHint(QwtPlotItem::RenderAntialiased); } setCanvasBackground(GColor(CRIDEPLOTBACKGROUND)); QPen wattsPen = QPen(GColor(CPOWER)); wattsPen.setWidth(width); - wattsCurve->setPen(wattsPen); + standard->wattsCurve->setPen(wattsPen); QPen npPen = QPen(GColor(CNPOWER)); npPen.setWidth(width); - npCurve->setPen(npPen); + standard->npCurve->setPen(npPen); QPen xpPen = QPen(GColor(CXPOWER)); xpPen.setWidth(width); - xpCurve->setPen(xpPen); + standard->xpCurve->setPen(xpPen); QPen apPen = QPen(GColor(CAPOWER)); apPen.setWidth(width); - apCurve->setPen(apPen); + standard->apCurve->setPen(apPen); QPen hrPen = QPen(GColor(CHEARTRATE)); hrPen.setWidth(width); - hrCurve->setPen(hrPen); + standard->hrCurve->setPen(hrPen); QPen speedPen = QPen(GColor(CSPEED)); speedPen.setWidth(width); - speedCurve->setPen(speedPen); + standard->speedCurve->setPen(speedPen); QPen cadPen = QPen(GColor(CCADENCE)); cadPen.setWidth(width); - cadCurve->setPen(cadPen); + standard->cadCurve->setPen(cadPen); QPen altPen(GColor(CALTITUDE)); altPen.setWidth(width); - altCurve->setPen(altPen); + standard->altCurve->setPen(altPen); QColor brush_color = GColor(CALTITUDEBRUSH); brush_color.setAlpha(200); - altCurve->setBrush(brush_color); // fill below the line + standard->altCurve->setBrush(brush_color); // fill below the line QPen tempPen = QPen(GColor(CTEMP)); tempPen.setWidth(width); - tempCurve->setPen(tempPen); + standard->tempCurve->setPen(tempPen); if (smooth == 1) - tempCurve->setStyle(QwtPlotCurve::Dots); + standard->tempCurve->setStyle(QwtPlotCurve::Dots); else - tempCurve->setStyle(QwtPlotCurve::Lines); + standard->tempCurve->setStyle(QwtPlotCurve::Lines); //QPen windPen = QPen(GColor(CWINDSPEED)); //windPen.setWidth(width); - windCurve->setPen(QPen(Qt::NoPen)); + standard->windCurve->setPen(QPen(Qt::NoPen)); QColor wbrush_color = GColor(CWINDSPEED); wbrush_color.setAlpha(200); - windCurve->setBrush(wbrush_color); // fill below the line + standard->windCurve->setBrush(wbrush_color); // fill below the line QPen torquePen = QPen(GColor(CTORQUE)); torquePen.setWidth(width); - torqueCurve->setPen(torquePen); + standard->torqueCurve->setPen(torquePen); QPen balanceLPen = QPen(GColor(CBALANCERIGHT)); balanceLPen.setWidth(width); - balanceLCurve->setPen(balanceLPen); + standard->balanceLCurve->setPen(balanceLPen); QColor brbrush_color = GColor(CBALANCERIGHT); brbrush_color.setAlpha(200); - balanceLCurve->setBrush(brbrush_color); // fill below the line + standard->balanceLCurve->setBrush(brbrush_color); // fill below the line QPen balanceRPen = QPen(GColor(CBALANCELEFT)); balanceRPen.setWidth(width); - balanceRCurve->setPen(balanceRPen); + standard->balanceRCurve->setPen(balanceRPen); QColor blbrush_color = GColor(CBALANCELEFT); blbrush_color.setAlpha(200); - balanceRCurve->setBrush(blbrush_color); // fill below the line + standard->balanceRCurve->setBrush(blbrush_color); // fill below the line QPen wPen = QPen(GColor(CWBAL)); wPen.setWidth(2); // thicken - wCurve->setPen(wPen); + standard->wCurve->setPen(wPen); QwtSymbol *sym = new QwtSymbol; sym->setStyle(QwtSymbol::Rect); sym->setPen(QPen(QColor(255,127,0))); // orange like a match, will make configurable later sym->setSize(4); - mCurve->setSymbol(sym); + standard->mCurve->setSymbol(sym); QPen ihlPen = QPen(GColor(CINTERVALHIGHLIGHTER)); ihlPen.setWidth(width); - intervalHighlighterCurve->setPen(ihlPen); + standard->intervalHighlighterCurve->setPen(ihlPen); QColor ihlbrush = QColor(GColor(CINTERVALHIGHLIGHTER)); ihlbrush.setAlpha(128); - intervalHighlighterCurve->setBrush(ihlbrush); // fill below the line + standard->intervalHighlighterCurve->setBrush(ihlbrush); // fill below the line //this->legend()->remove(intervalHighlighterCurve); // don't show in legend QPen gridPen(GColor(CPLOTGRID)); gridPen.setStyle(Qt::DotLine); - grid->setPen(gridPen); + standard->grid->setPen(gridPen); // curve brushes if (parent->isPaintBrush()) { QColor p; - p = wattsCurve->pen().color(); + p = standard->wattsCurve->pen().color(); p.setAlpha(64); - wattsCurve->setBrush(QBrush(p)); + standard->wattsCurve->setBrush(QBrush(p)); - p = npCurve->pen().color(); + p = standard->npCurve->pen().color(); p.setAlpha(64); - npCurve->setBrush(QBrush(p)); + standard->npCurve->setBrush(QBrush(p)); - p = xpCurve->pen().color(); + p = standard->xpCurve->pen().color(); p.setAlpha(64); - xpCurve->setBrush(QBrush(p)); + standard->xpCurve->setBrush(QBrush(p)); - p = apCurve->pen().color(); + p = standard->apCurve->pen().color(); p.setAlpha(64); - apCurve->setBrush(QBrush(p)); + standard->apCurve->setBrush(QBrush(p)); - p = wCurve->pen().color(); + p = standard->wCurve->pen().color(); p.setAlpha(64); - wCurve->setBrush(QBrush(p)); + standard->wCurve->setBrush(QBrush(p)); - p = hrCurve->pen().color(); + p = standard->hrCurve->pen().color(); p.setAlpha(64); - hrCurve->setBrush(QBrush(p)); + standard->hrCurve->setBrush(QBrush(p)); - p = speedCurve->pen().color(); + p = standard->speedCurve->pen().color(); p.setAlpha(64); - speedCurve->setBrush(QBrush(p)); + standard->speedCurve->setBrush(QBrush(p)); - p = cadCurve->pen().color(); + p = standard->cadCurve->pen().color(); p.setAlpha(64); - cadCurve->setBrush(QBrush(p)); + standard->cadCurve->setBrush(QBrush(p)); - p = torqueCurve->pen().color(); + p = standard->torqueCurve->pen().color(); p.setAlpha(64); - torqueCurve->setBrush(QBrush(p)); + standard->torqueCurve->setBrush(QBrush(p)); - /*p = balanceLCurve->pen().color(); + /*p = standard->balanceLCurve->pen().color(); p.setAlpha(64); - balanceLCurve->setBrush(QBrush(p)); + standard->balanceLCurve->setBrush(QBrush(p)); - p = balanceRCurve->pen().color(); + p = standard->balanceRCurve->pen().color(); p.setAlpha(64); - balanceRCurve->setBrush(QBrush(p));*/ + standard->balanceRCurve->setBrush(QBrush(p));*/ } else { - wattsCurve->setBrush(Qt::NoBrush); - npCurve->setBrush(Qt::NoBrush); - xpCurve->setBrush(Qt::NoBrush); - apCurve->setBrush(Qt::NoBrush); - wCurve->setBrush(Qt::NoBrush); - hrCurve->setBrush(Qt::NoBrush); - speedCurve->setBrush(Qt::NoBrush); - cadCurve->setBrush(Qt::NoBrush); - torqueCurve->setBrush(Qt::NoBrush); - //balanceLCurve->setBrush(Qt::NoBrush); - //balanceRCurve->setBrush(Qt::NoBrush); + standard->wattsCurve->setBrush(Qt::NoBrush); + standard->npCurve->setBrush(Qt::NoBrush); + standard->xpCurve->setBrush(Qt::NoBrush); + standard->apCurve->setBrush(Qt::NoBrush); + standard->wCurve->setBrush(Qt::NoBrush); + standard->hrCurve->setBrush(Qt::NoBrush); + standard->speedCurve->setBrush(Qt::NoBrush); + standard->cadCurve->setBrush(Qt::NoBrush); + standard->torqueCurve->setBrush(Qt::NoBrush); + //standard->balanceLCurve->setBrush(Qt::NoBrush); + //standard->balanceRCurve->setBrush(Qt::NoBrush); } QPalette pal; @@ -583,6 +747,13 @@ AllPlot::configChanged() axisWidget(QwtAxisId(QwtAxis::yRight, 2))->setPalette(pal); } +void +AllPlot::setHighlightIntervals(bool state) +{ + if (state) standard->intervalHighlighterCurve->attach(this); + else standard->intervalHighlighterCurve->detach(); +} + struct DataPoint { double time, hr, watts, np, ap, xp, speed, cad, alt, temp, wind, torque, lrbalance; DataPoint(double t, double h, double w, double n, double l, double x, double s, double c, double a, double te, double wi, double tq, double lrb) : @@ -634,53 +805,54 @@ void AllPlot::refreshZoneLabels() void -AllPlot::recalc() +AllPlot::recalc(AllPlotObject *objects) { if (referencePlot !=NULL){ return; } - if (timeArray.empty()) + if (objects->timeArray.empty()) return; - int rideTimeSecs = (int) ceil(timeArray[arrayLength - 1]); + int rideTimeSecs = (int) ceil(objects->timeArray[objects->timeArray.count()-1]); if (rideTimeSecs > 7*24*60*60) { QwtArray data; QVector intData; - wCurve->setSamples(data,data); - mCurve->setSamples(data,data); - if (!npArray.empty()) - npCurve->setSamples(data, data); - if (!xpArray.empty()) - xpCurve->setSamples(data, data); - if (!apArray.empty()) - apCurve->setSamples(data, data); - if (!wattsArray.empty()) - wattsCurve->setSamples(data, data); - if (!hrArray.empty()) - hrCurve->setSamples(data, data); - if (!speedArray.empty()) - speedCurve->setSamples(data, data); - if (!cadArray.empty()) - cadCurve->setSamples(data, data); - if (!altArray.empty()) - altCurve->setSamples(data, data); - if (!tempArray.empty()) - tempCurve->setSamples(data, data); - if (!windArray.empty()) - windCurve->setSamples(new QwtIntervalSeriesData(intData)); - if (!torqueArray.empty()) - torqueCurve->setSamples(data, data); - if (!balanceArray.empty()) - balanceLCurve->setSamples(data, data); - if (!balanceArray.empty()) - balanceRCurve->setSamples(data, data); + objects->wCurve->setSamples(data,data); + objects->mCurve->setSamples(data,data); + if (!objects->npArray.empty()) + objects->npCurve->setSamples(data, data); + if (!objects->xpArray.empty()) + objects->xpCurve->setSamples(data, data); + if (!objects->apArray.empty()) + objects->apCurve->setSamples(data, data); + if (!objects->wattsArray.empty()) + objects->wattsCurve->setSamples(data, data); + if (!objects->hrArray.empty()) + objects->hrCurve->setSamples(data, data); + if (!objects->speedArray.empty()) + objects->speedCurve->setSamples(data, data); + if (!objects->cadArray.empty()) + objects->cadCurve->setSamples(data, data); + if (!objects->altArray.empty()) + objects->altCurve->setSamples(data, data); + if (!objects->tempArray.empty()) + objects->tempCurve->setSamples(data, data); + if (!objects->windArray.empty()) + objects->windCurve->setSamples(new QwtIntervalSeriesData(intData)); + if (!objects->torqueArray.empty()) + objects->torqueCurve->setSamples(data, data); + if (!objects->balanceArray.empty()) + objects->balanceLCurve->setSamples(data, data); + if (!objects->balanceArray.empty()) + objects->balanceRCurve->setSamples(data, data); return; } - // we should only smooth the curves if smoothed rate is greater than sample rate - if (smooth > rideItem->ride()->recIntSecs()) { + + // we should only smooth the curves if objects->smoothed rate is greater than sample rate + if (smooth > 0) { double totalWatts = 0.0; double totalNP = 0.0; @@ -698,92 +870,92 @@ AllPlot::recalc() QList list; - smoothWatts.resize(rideTimeSecs + 1); //(rideTimeSecs + 1); - smoothNP.resize(rideTimeSecs + 1); //(rideTimeSecs + 1); - smoothXP.resize(rideTimeSecs + 1); //(rideTimeSecs + 1); - smoothAP.resize(rideTimeSecs + 1); //(rideTimeSecs + 1); - smoothHr.resize(rideTimeSecs + 1); - smoothSpeed.resize(rideTimeSecs + 1); - smoothCad.resize(rideTimeSecs + 1); - smoothTime.resize(rideTimeSecs + 1); - smoothDistance.resize(rideTimeSecs + 1); - smoothAltitude.resize(rideTimeSecs + 1); - smoothTemp.resize(rideTimeSecs + 1); - smoothWind.resize(rideTimeSecs + 1); - smoothRelSpeed.resize(rideTimeSecs + 1); - smoothTorque.resize(rideTimeSecs + 1); - smoothBalanceL.resize(rideTimeSecs + 1); - smoothBalanceR.resize(rideTimeSecs + 1); + objects->smoothWatts.resize(rideTimeSecs + 1); //(rideTimeSecs + 1); + objects->smoothNP.resize(rideTimeSecs + 1); //(rideTimeSecs + 1); + objects->smoothXP.resize(rideTimeSecs + 1); //(rideTimeSecs + 1); + objects->smoothAP.resize(rideTimeSecs + 1); //(rideTimeSecs + 1); + objects->smoothHr.resize(rideTimeSecs + 1); + objects->smoothSpeed.resize(rideTimeSecs + 1); + objects->smoothCad.resize(rideTimeSecs + 1); + objects->smoothTime.resize(rideTimeSecs + 1); + objects->smoothDistance.resize(rideTimeSecs + 1); + objects->smoothAltitude.resize(rideTimeSecs + 1); + objects->smoothTemp.resize(rideTimeSecs + 1); + objects->smoothWind.resize(rideTimeSecs + 1); + objects->smoothRelSpeed.resize(rideTimeSecs + 1); + objects->smoothTorque.resize(rideTimeSecs + 1); + objects->smoothBalanceL.resize(rideTimeSecs + 1); + objects->smoothBalanceR.resize(rideTimeSecs + 1); for (int secs = 0; ((secs < smooth) && (secs < rideTimeSecs)); ++secs) { - smoothWatts[secs] = 0.0; - smoothNP[secs] = 0.0; - smoothXP[secs] = 0.0; - smoothAP[secs] = 0.0; - smoothHr[secs] = 0.0; - smoothSpeed[secs] = 0.0; - smoothCad[secs] = 0.0; - smoothTime[secs] = secs / 60.0; - smoothDistance[secs] = 0.0; - smoothAltitude[secs] = 0.0; - smoothTemp[secs] = 0.0; - smoothWind[secs] = 0.0; - smoothRelSpeed[secs] = QwtIntervalSample(); - smoothTorque[secs] = 0.0; - smoothBalanceL[secs] = 50; - smoothBalanceR[secs] = 50; + objects->smoothWatts[secs] = 0.0; + objects->smoothNP[secs] = 0.0; + objects->smoothXP[secs] = 0.0; + objects->smoothAP[secs] = 0.0; + objects->smoothHr[secs] = 0.0; + objects->smoothSpeed[secs] = 0.0; + objects->smoothCad[secs] = 0.0; + objects->smoothTime[secs] = secs / 60.0; + objects->smoothDistance[secs] = 0.0; + objects->smoothAltitude[secs] = 0.0; + objects->smoothTemp[secs] = 0.0; + objects->smoothWind[secs] = 0.0; + objects->smoothRelSpeed[secs] = QwtIntervalSample(); + objects->smoothTorque[secs] = 0.0; + objects->smoothBalanceL[secs] = 50; + objects->smoothBalanceR[secs] = 50; } int i = 0; for (int secs = smooth; secs <= rideTimeSecs; ++secs) { - while ((i < arrayLength) && (timeArray[i] <= secs)) { - DataPoint dp(timeArray[i], - (!hrArray.empty() ? hrArray[i] : 0), - (!wattsArray.empty() ? wattsArray[i] : 0), - (!npArray.empty() ? npArray[i] : 0), - (!apArray.empty() ? apArray[i] : 0), - (!xpArray.empty() ? xpArray[i] : 0), - (!speedArray.empty() ? speedArray[i] : 0), - (!cadArray.empty() ? cadArray[i] : 0), - (!altArray.empty() ? altArray[i] : 0), - (!tempArray.empty() ? tempArray[i] : 0), - (!windArray.empty() ? windArray[i] : 0), - (!torqueArray.empty() ? torqueArray[i] : 0), - (!balanceArray.empty() ? balanceArray[i] : 0)); - if (!wattsArray.empty()) - totalWatts += wattsArray[i]; - if (!npArray.empty()) - totalNP += npArray[i]; - if (!xpArray.empty()) - totalXP += xpArray[i]; - if (!apArray.empty()) - totalAP += apArray[i]; - if (!hrArray.empty()) - totalHr += hrArray[i]; - if (!speedArray.empty()) - totalSpeed += speedArray[i]; - if (!cadArray.empty()) - totalCad += cadArray[i]; - if (!altArray.empty()) - totalAlt += altArray[i]; - if (!tempArray.empty() ) { - if (tempArray[i] == RideFile::noTemp) { + while ((i < objects->timeArray.count()) && (objects->timeArray[i] <= secs)) { + DataPoint dp(objects->timeArray[i], + (!objects->hrArray.empty() ? objects->hrArray[i] : 0), + (!objects->wattsArray.empty() ? objects->wattsArray[i] : 0), + (!objects->npArray.empty() ? objects->npArray[i] : 0), + (!objects->apArray.empty() ? objects->apArray[i] : 0), + (!objects->xpArray.empty() ? objects->xpArray[i] : 0), + (!objects->speedArray.empty() ? objects->speedArray[i] : 0), + (!objects->cadArray.empty() ? objects->cadArray[i] : 0), + (!objects->altArray.empty() ? objects->altArray[i] : 0), + (!objects->tempArray.empty() ? objects->tempArray[i] : 0), + (!objects->windArray.empty() ? objects->windArray[i] : 0), + (!objects->torqueArray.empty() ? objects->torqueArray[i] : 0), + (!objects->balanceArray.empty() ? objects->balanceArray[i] : 0)); + if (!objects->wattsArray.empty()) + totalWatts += objects->wattsArray[i]; + if (!objects->npArray.empty()) + totalNP += objects->npArray[i]; + if (!objects->xpArray.empty()) + totalXP += objects->xpArray[i]; + if (!objects->apArray.empty()) + totalAP += objects->apArray[i]; + if (!objects->hrArray.empty()) + totalHr += objects->hrArray[i]; + if (!objects->speedArray.empty()) + totalSpeed += objects->speedArray[i]; + if (!objects->cadArray.empty()) + totalCad += objects->cadArray[i]; + if (!objects->altArray.empty()) + totalAlt += objects->altArray[i]; + if (!objects->tempArray.empty() ) { + if (objects->tempArray[i] == RideFile::noTemp) { dp.temp = (i>0 && !list.empty()?list.back().temp:0.0); totalTemp += dp.temp; } else { - totalTemp += tempArray[i]; + totalTemp += objects->tempArray[i]; } } - if (!windArray.empty()) - totalWind += windArray[i]; - if (!torqueArray.empty()) - totalTorque += torqueArray[i]; - if (!balanceArray.empty()) - totalBalance += (balanceArray[i]>0?balanceArray[i]:50); + if (!objects->windArray.empty()) + totalWind += objects->windArray[i]; + if (!objects->torqueArray.empty()) + totalTorque += objects->torqueArray[i]; + if (!objects->balanceArray.empty()) + totalBalance += (objects->balanceArray[i]>0?objects->balanceArray[i]:50); - totalDist = distanceArray[i]; + totalDist = objects->distanceArray[i]; list.append(dp); ++i; } @@ -806,190 +978,193 @@ AllPlot::recalc() // TODO: this is wrong. We should do a weighted average over the // seconds represented by each point... if (list.empty()) { - smoothWatts[secs] = 0.0; - smoothNP[secs] = 0.0; - smoothXP[secs] = 0.0; - smoothAP[secs] = 0.0; - smoothHr[secs] = 0.0; - smoothSpeed[secs] = 0.0; - smoothCad[secs] = 0.0; - smoothAltitude[secs] = smoothAltitude[secs - 1]; - smoothTemp[secs] = 0.0; - smoothWind[secs] = 0.0; - smoothRelSpeed[secs] = QwtIntervalSample(); - smoothTorque[secs] = 0.0; - smoothBalanceL[secs] = 50; - smoothBalanceR[secs] = 50; + objects->smoothWatts[secs] = 0.0; + objects->smoothNP[secs] = 0.0; + objects->smoothXP[secs] = 0.0; + objects->smoothAP[secs] = 0.0; + objects->smoothHr[secs] = 0.0; + objects->smoothSpeed[secs] = 0.0; + objects->smoothCad[secs] = 0.0; + objects->smoothAltitude[secs] = objects->smoothAltitude[secs - 1]; + objects->smoothTemp[secs] = 0.0; + objects->smoothWind[secs] = 0.0; + objects->smoothRelSpeed[secs] = QwtIntervalSample(); + objects->smoothTorque[secs] = 0.0; + objects->smoothBalanceL[secs] = 50; + objects->smoothBalanceR[secs] = 50; } else { - smoothWatts[secs] = totalWatts / list.size(); - smoothNP[secs] = totalNP / list.size(); - smoothXP[secs] = totalXP / list.size(); - smoothAP[secs] = totalAP / list.size(); - smoothHr[secs] = totalHr / list.size(); - smoothSpeed[secs] = totalSpeed / list.size(); - smoothCad[secs] = totalCad / list.size(); - smoothAltitude[secs] = totalAlt / list.size(); - smoothTemp[secs] = totalTemp / list.size(); - smoothWind[secs] = totalWind / list.size(); - smoothRelSpeed[secs] = QwtIntervalSample( bydist ? totalDist : secs / 60.0, QwtInterval(qMin(totalWind / list.size(), totalSpeed / list.size()), qMax(totalWind / list.size(), totalSpeed / list.size()) ) ); - smoothTorque[secs] = totalTorque / list.size(); + objects->smoothWatts[secs] = totalWatts / list.size(); + objects->smoothNP[secs] = totalNP / list.size(); + objects->smoothXP[secs] = totalXP / list.size(); + objects->smoothAP[secs] = totalAP / list.size(); + objects->smoothHr[secs] = totalHr / list.size(); + objects->smoothSpeed[secs] = totalSpeed / list.size(); + objects->smoothCad[secs] = totalCad / list.size(); + objects->smoothAltitude[secs] = totalAlt / list.size(); + objects->smoothTemp[secs] = totalTemp / list.size(); + objects->smoothWind[secs] = totalWind / list.size(); + objects->smoothRelSpeed[secs] = QwtIntervalSample( bydist ? totalDist : secs / 60.0, QwtInterval(qMin(totalWind / list.size(), totalSpeed / list.size()), qMax(totalWind / list.size(), totalSpeed / list.size()) ) ); + objects->smoothTorque[secs] = totalTorque / list.size(); double balance = totalBalance / list.size(); if (balance == 0) { - smoothBalanceL[secs] = 50; - smoothBalanceR[secs] = 50; + objects->smoothBalanceL[secs] = 50; + objects->smoothBalanceR[secs] = 50; } else if (balance >= 50) { - smoothBalanceL[secs] = balance; - smoothBalanceR[secs] = 50; + objects->smoothBalanceL[secs] = balance; + objects->smoothBalanceR[secs] = 50; } else { - smoothBalanceL[secs] = 50; - smoothBalanceR[secs] = balance; + objects->smoothBalanceL[secs] = 50; + objects->smoothBalanceR[secs] = balance; } } - smoothDistance[secs] = totalDist; - smoothTime[secs] = secs / 60.0; + objects->smoothDistance[secs] = totalDist; + objects->smoothTime[secs] = secs / 60.0; } } else { - // no smoothing .. just raw data - smoothWatts.resize(0); - smoothNP.resize(0); - smoothXP.resize(0); - smoothAP.resize(0); - smoothHr.resize(0); - smoothSpeed.resize(0); - smoothCad.resize(0); - smoothTime.resize(0); - smoothDistance.resize(0); - smoothAltitude.resize(0); - smoothTemp.resize(0); - smoothWind.resize(0); - smoothRelSpeed.resize(0); - smoothTorque.resize(0); - smoothBalanceL.resize(0); - smoothBalanceR.resize(0); + // no standard->smoothing .. just raw data + objects->smoothWatts.resize(0); + objects->smoothNP.resize(0); + objects->smoothXP.resize(0); + objects->smoothAP.resize(0); + objects->smoothHr.resize(0); + objects->smoothSpeed.resize(0); + objects->smoothCad.resize(0); + objects->smoothTime.resize(0); + objects->smoothDistance.resize(0); + objects->smoothAltitude.resize(0); + objects->smoothTemp.resize(0); + objects->smoothWind.resize(0); + objects->smoothRelSpeed.resize(0); + objects->smoothTorque.resize(0); + objects->smoothBalanceL.resize(0); + objects->smoothBalanceR.resize(0); foreach (RideFilePoint *dp, rideItem->ride()->dataPoints()) { - smoothWatts.append(dp->watts); - smoothNP.append(dp->np); - smoothXP.append(dp->xp); - smoothAP.append(dp->apower); - smoothHr.append(dp->hr); - smoothSpeed.append(context->athlete->useMetricUnits ? dp->kph : dp->kph * MILES_PER_KM); - smoothCad.append(dp->cad); - smoothTime.append(dp->secs/60); - smoothDistance.append(context->athlete->useMetricUnits ? dp->km : dp->km * MILES_PER_KM); - smoothAltitude.append(context->athlete->useMetricUnits ? dp->alt : dp->alt * FEET_PER_METER); - if (dp->temp == RideFile::noTemp && !smoothTemp.empty()) - dp->temp = smoothTemp.last(); - smoothTemp.append(context->athlete->useMetricUnits ? dp->temp : dp->temp * FAHRENHEIT_PER_CENTIGRADE + FAHRENHEIT_ADD_CENTIGRADE); - smoothWind.append(context->athlete->useMetricUnits ? dp->headwind : dp->headwind * MILES_PER_KM); - smoothTorque.append(dp->nm); + objects->smoothWatts.append(dp->watts); + objects->smoothNP.append(dp->np); + objects->smoothXP.append(dp->xp); + objects->smoothAP.append(dp->apower); + objects->smoothHr.append(dp->hr); + objects->smoothSpeed.append(context->athlete->useMetricUnits ? dp->kph : dp->kph * MILES_PER_KM); + objects->smoothCad.append(dp->cad); + objects->smoothTime.append(dp->secs/60); + objects->smoothDistance.append(context->athlete->useMetricUnits ? dp->km : dp->km * MILES_PER_KM); + objects->smoothAltitude.append(context->athlete->useMetricUnits ? dp->alt : dp->alt * FEET_PER_METER); + if (dp->temp == RideFile::noTemp && !objects->smoothTemp.empty()) + dp->temp = objects->smoothTemp.last(); + objects->smoothTemp.append(context->athlete->useMetricUnits ? dp->temp : dp->temp * FAHRENHEIT_PER_CENTIGRADE + FAHRENHEIT_ADD_CENTIGRADE); + objects->smoothWind.append(context->athlete->useMetricUnits ? dp->headwind : dp->headwind * MILES_PER_KM); + objects->smoothTorque.append(dp->nm); if (dp->lrbalance == 0) { - smoothBalanceL.append(50); - smoothBalanceR.append(50); + objects->smoothBalanceL.append(50); + objects->smoothBalanceR.append(50); } else if (dp->lrbalance >= 50) { - smoothBalanceL.append(dp->lrbalance); - smoothBalanceR.append(50); + objects->smoothBalanceL.append(dp->lrbalance); + objects->smoothBalanceR.append(50); } else { - smoothBalanceL.append(50); - smoothBalanceR.append(dp->lrbalance); + objects->smoothBalanceL.append(50); + objects->smoothBalanceR.append(dp->lrbalance); } double head = dp->headwind * (context->athlete->useMetricUnits ? 1.0f : MILES_PER_KM); double speed = dp->kph * (context->athlete->useMetricUnits ? 1.0f : MILES_PER_KM); - smoothRelSpeed.append(QwtIntervalSample( bydist ? smoothDistance.last() : smoothTime.last(), QwtInterval(qMin(head, speed) , qMax(head, speed) ) )); + objects->smoothRelSpeed.append(QwtIntervalSample( bydist ? objects->smoothDistance.last() : objects->smoothTime.last(), QwtInterval(qMin(head, speed) , qMax(head, speed) ) )); } } - QVector &xaxis = bydist ? smoothDistance : smoothTime; + QVector &xaxis = bydist ? objects->smoothDistance : objects->smoothTime; int startingIndex = qMin(smooth, xaxis.count()); int totalPoints = xaxis.count() - startingIndex; // set curves - we set the intervalHighlighter to whichver is available //W' curve set to whatever data we have - wCurve->setSamples(parent->wpData->xdata().data(), parent->wpData->ydata().data(), parent->wpData->xdata().count()); - mCurve->setSamples(parent->wpData->mxdata().data(), parent->wpData->mydata().data(), parent->wpData->mxdata().count()); + objects->wCurve->setSamples(parent->wpData->xdata().data(), parent->wpData->ydata().data(), parent->wpData->xdata().count()); + objects->mCurve->setSamples(parent->wpData->mxdata().data(), parent->wpData->mydata().data(), parent->wpData->mxdata().count()); - if (!wattsArray.empty()) { - wattsCurve->setSamples(xaxis.data() + startingIndex, smoothWatts.data() + startingIndex, totalPoints); - intervalHighlighterCurve->setYAxis(yLeft); + if (!objects->wattsArray.empty()) { + objects->wattsCurve->setSamples(xaxis.data() + startingIndex, objects->smoothWatts.data() + startingIndex, totalPoints); + standard->intervalHighlighterCurve->setYAxis(yLeft); } - if (!npArray.empty()) { - npCurve->setSamples(xaxis.data() + startingIndex, smoothNP.data() + startingIndex, totalPoints); - intervalHighlighterCurve->setYAxis(yLeft); + if (!objects->npArray.empty()) { + objects->npCurve->setSamples(xaxis.data() + startingIndex, objects->smoothNP.data() + startingIndex, totalPoints); + standard->intervalHighlighterCurve->setYAxis(yLeft); } - if (!xpArray.empty()) { - xpCurve->setSamples(xaxis.data() + startingIndex, smoothXP.data() + startingIndex, totalPoints); - intervalHighlighterCurve->setYAxis(yLeft); + if (!objects->xpArray.empty()) { + objects->xpCurve->setSamples(xaxis.data() + startingIndex, objects->smoothXP.data() + startingIndex, totalPoints); + standard->intervalHighlighterCurve->setYAxis(yLeft); } - if (!apArray.empty()) { - apCurve->setSamples(xaxis.data() + startingIndex, smoothAP.data() + startingIndex, totalPoints); - intervalHighlighterCurve->setYAxis(yLeft); + if (!objects->apArray.empty()) { + objects->apCurve->setSamples(xaxis.data() + startingIndex, objects->smoothAP.data() + startingIndex, totalPoints); + standard->intervalHighlighterCurve->setYAxis(yLeft); } - if (!hrArray.empty()) { - hrCurve->setSamples(xaxis.data() + startingIndex, smoothHr.data() + startingIndex, totalPoints); - intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); + if (!objects->hrArray.empty()) { + objects->hrCurve->setSamples(xaxis.data() + startingIndex, objects->smoothHr.data() + startingIndex, totalPoints); + standard->intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); } - if (!speedArray.empty()) { - speedCurve->setSamples(xaxis.data() + startingIndex, smoothSpeed.data() + startingIndex, totalPoints); - intervalHighlighterCurve->setYAxis(yRight); + if (!objects->speedArray.empty()) { + objects->speedCurve->setSamples(xaxis.data() + startingIndex, objects->smoothSpeed.data() + startingIndex, totalPoints); + standard->intervalHighlighterCurve->setYAxis(yRight); } - if (!cadArray.empty()) { - cadCurve->setSamples(xaxis.data() + startingIndex, smoothCad.data() + startingIndex, totalPoints); - intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); + if (!objects->cadArray.empty()) { + objects->cadCurve->setSamples(xaxis.data() + startingIndex, objects->smoothCad.data() + startingIndex, totalPoints); + standard->intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); } - if (!altArray.empty()) { - altCurve->setSamples(xaxis.data() + startingIndex, smoothAltitude.data() + startingIndex, totalPoints); - intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yRight, 1)); + if (!objects->altArray.empty()) { + objects->altCurve->setSamples(xaxis.data() + startingIndex, objects->smoothAltitude.data() + startingIndex, totalPoints); + standard->intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yRight, 1)); } - if (!tempArray.empty()) { - tempCurve->setSamples(xaxis.data() + startingIndex, smoothTemp.data() + startingIndex, totalPoints); + if (!objects->tempArray.empty()) { + objects->tempCurve->setSamples(xaxis.data() + startingIndex, objects->smoothTemp.data() + startingIndex, totalPoints); if (context->athlete->useMetricUnits) - intervalHighlighterCurve->setYAxis(yRight); + standard->intervalHighlighterCurve->setYAxis(yRight); else - intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); + standard->intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); } - if (!windArray.empty()) { - windCurve->setSamples(new QwtIntervalSeriesData(smoothRelSpeed)); - intervalHighlighterCurve->setYAxis(yRight); + if (!objects->windArray.empty()) { + objects->windCurve->setSamples(new QwtIntervalSeriesData(objects->smoothRelSpeed)); + standard->intervalHighlighterCurve->setYAxis(yRight); } - if (!torqueArray.empty()) { - torqueCurve->setSamples(xaxis.data() + startingIndex, smoothTorque.data() + startingIndex, totalPoints); - intervalHighlighterCurve->setYAxis(yRight); + if (!objects->torqueArray.empty()) { + objects->torqueCurve->setSamples(xaxis.data() + startingIndex, objects->smoothTorque.data() + startingIndex, totalPoints); + standard->intervalHighlighterCurve->setYAxis(yRight); } - if (!balanceArray.empty()) { - balanceLCurve->setSamples(xaxis.data() + startingIndex, smoothBalanceL.data() + startingIndex, totalPoints); - intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); - balanceRCurve->setSamples(xaxis.data() + startingIndex, smoothBalanceR.data() + startingIndex, totalPoints); - intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); + if (!objects->balanceArray.empty()) { + objects->balanceLCurve->setSamples(xaxis.data() + startingIndex, objects->smoothBalanceL.data() + startingIndex, totalPoints); + standard->intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); + objects->balanceRCurve->setSamples(xaxis.data() + startingIndex, objects->smoothBalanceR.data() + startingIndex, totalPoints); + standard->intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); } setYMax(); - refreshReferenceLines(); - refreshIntervalMarkers(); - refreshCalibrationMarkers(); - refreshZoneLabels(); + + if (!context->isCompareIntervals) { + refreshReferenceLines(); + refreshIntervalMarkers(); + refreshCalibrationMarkers(); + refreshZoneLabels(); + } replot(); } @@ -997,11 +1172,11 @@ AllPlot::recalc() void AllPlot::refreshIntervalMarkers() { - foreach(QwtPlotMarker *mrk, d_mrk) { + foreach(QwtPlotMarker *mrk, standard->d_mrk) { mrk->detach(); delete mrk; } - d_mrk.clear(); + standard->d_mrk.clear(); QRegExp wkoAuto("^(Peak *[0-9]*(s|min)|Entire workout|Find #[0-9]*) *\\([^)]*\\)$"); if (rideItem->ride()) { foreach(const RideFileInterval &interval, rideItem->ride()->intervals()) { @@ -1009,7 +1184,7 @@ AllPlot::refreshIntervalMarkers() if (wkoAuto.exactMatch(interval.name)) continue; QwtPlotMarker *mrk = new QwtPlotMarker; - d_mrk.append(mrk); + standard->d_mrk.append(mrk); mrk->attach(this); mrk->setLineStyle(QwtPlotMarker::VLine); mrk->setLabelAlignment(Qt::AlignRight | Qt::AlignTop); @@ -1038,16 +1213,16 @@ AllPlot::refreshIntervalMarkers() void AllPlot::refreshCalibrationMarkers() { - foreach(QwtPlotMarker *mrk, cal_mrk) { + foreach(QwtPlotMarker *mrk, standard->cal_mrk) { mrk->detach(); delete mrk; } - cal_mrk.clear(); + standard->cal_mrk.clear(); if (rideItem->ride()) { foreach(const RideFileCalibration &calibration, rideItem->ride()->calibrations()) { QwtPlotMarker *mrk = new QwtPlotMarker; - cal_mrk.append(mrk); + standard->cal_mrk.append(mrk); mrk->attach(this); mrk->setLineStyle(QwtPlotMarker::VLine); mrk->setLabelAlignment(Qt::AlignRight | Qt::AlignTop); @@ -1072,15 +1247,15 @@ AllPlot::refreshReferenceLines() if (scope != RideFile::none && scope != RideFile::watts && scope != RideFile::NP && scope != RideFile::aPower && scope != RideFile::xPower) return; - foreach(QwtPlotCurve *referenceLine, referenceLines) { + foreach(QwtPlotCurve *referenceLine, standard->referenceLines) { referenceLine->detach(); delete referenceLine; } - referenceLines.clear(); + standard->referenceLines.clear(); if (rideItem->ride()) { foreach(const RideFilePoint *referencePoint, rideItem->ride()->referencePoints()) { QwtPlotCurve *referenceLine = plotReferenceLine(referencePoint); - if (referenceLine) referenceLines.append(referenceLine); + if (referenceLine) standard->referenceLines.append(referenceLine); } } } @@ -1146,16 +1321,16 @@ void AllPlot::setYMax() { // set axis scales - if (wCurve->isVisible()) { + if (standard->wCurve->isVisible()) { setAxisTitle(QwtAxisId(QwtAxis::yRight, 2), tr("W' Balance (j)")); setAxisScale(QwtAxisId(QwtAxis::yRight, 2),parent->wpData->minY-1000,parent->wpData->maxY+1000); setAxisLabelAlignment(QwtAxisId(QwtAxis::yRight, 2),Qt::AlignVCenter); } - if (wattsCurve->isVisible()) { - double maxY = (referencePlot == NULL) ? (1.05 * wattsCurve->maxYValue()) : - (1.05 * referencePlot->wattsCurve->maxYValue()); + if (standard->wattsCurve->isVisible()) { + double maxY = (referencePlot == NULL) ? (1.05 * standard->wattsCurve->maxYValue()) : + (1.05 * referencePlot->standard->wattsCurve->maxYValue()); int axisHeight = qRound( plotLayout()->canvasRect().height() ); QFontMetrics labelWidthMetric = QFontMetrics( QwtPlot::axisFont(yLeft) ); @@ -1175,47 +1350,47 @@ AllPlot::setYMax() setAxisScaleDiv(QwtPlot::yLeft,QwtScaleDiv(0.0,maxY,xytick)); //setAxisLabelAlignment(yLeft,Qt::AlignVCenter); } - if (hrCurve->isVisible() || cadCurve->isVisible() || (!context->athlete->useMetricUnits && tempCurve->isVisible()) || balanceLCurve->isVisible()) { + if (standard->hrCurve->isVisible() || standard->cadCurve->isVisible() || (!context->athlete->useMetricUnits && standard->tempCurve->isVisible()) || standard->balanceLCurve->isVisible()) { double ymin = 0; double ymax = 0; QStringList labels; - if (hrCurve->isVisible()) { + if (standard->hrCurve->isVisible()) { labels << tr("BPM"); if (referencePlot == NULL) - ymax = hrCurve->maxYValue(); + ymax = standard->hrCurve->maxYValue(); else - ymax = referencePlot->hrCurve->maxYValue(); + ymax = referencePlot->standard->hrCurve->maxYValue(); } - if (cadCurve->isVisible()) { + if (standard->cadCurve->isVisible()) { labels << tr("RPM"); if (referencePlot == NULL) - ymax = qMax(ymax, cadCurve->maxYValue()); + ymax = qMax(ymax, standard->cadCurve->maxYValue()); else - ymax = qMax(ymax, referencePlot->cadCurve->maxYValue()); + ymax = qMax(ymax, referencePlot->standard->cadCurve->maxYValue()); } - if (tempCurve->isVisible() && !context->athlete->useMetricUnits) { + if (standard->tempCurve->isVisible() && !context->athlete->useMetricUnits) { labels << QString::fromUtf8("°F"); if (referencePlot == NULL) { - ymin = qMin(ymin, tempCurve->minYValue()); - ymax = qMax(ymax, tempCurve->maxYValue()); + ymin = qMin(ymin, standard->tempCurve->minYValue()); + ymax = qMax(ymax, standard->tempCurve->maxYValue()); } else { - ymin = qMin(ymin, referencePlot->tempCurve->minYValue()); - ymax = qMax(ymax, referencePlot->tempCurve->maxYValue()); + ymin = qMin(ymin, referencePlot->standard->tempCurve->minYValue()); + ymax = qMax(ymax, referencePlot->standard->tempCurve->maxYValue()); } } - if (balanceLCurve->isVisible()) { + if (standard->balanceLCurve->isVisible()) { labels << tr("% left"); if (referencePlot == NULL) - ymax = qMax(ymax, balanceLCurve->maxYValue()); + ymax = qMax(ymax, standard->balanceLCurve->maxYValue()); else - ymax = qMax(ymax, referencePlot->balanceLCurve->maxYValue()); + ymax = qMax(ymax, referencePlot->standard->balanceLCurve->maxYValue()); - balanceLCurve->setBaseline(50); - balanceRCurve->setBaseline(50); + standard->balanceLCurve->setBaseline(50); + standard->balanceRCurve->setBaseline(50); } int axisHeight = qRound( plotLayout()->canvasRect().height() ); @@ -1237,55 +1412,55 @@ AllPlot::setYMax() setAxisScaleDiv(QwtAxisId(QwtAxis::yLeft, 1),QwtScaleDiv(ymin, ymax, xytick)); //setAxisLabelAlignment(yLeft2,Qt::AlignVCenter); } - if (speedCurve->isVisible() || (context->athlete->useMetricUnits && tempCurve->isVisible()) || torqueCurve->isVisible()) { + if (standard->speedCurve->isVisible() || (context->athlete->useMetricUnits && standard->tempCurve->isVisible()) || standard->torqueCurve->isVisible()) { double ymin = 0; double ymax = 0; QStringList labels; - if (speedCurve->isVisible()) { + if (standard->speedCurve->isVisible()) { labels << (context->athlete->useMetricUnits ? tr("KPH") : tr("MPH")); if (referencePlot == NULL) - ymax = speedCurve->maxYValue(); + ymax = standard->speedCurve->maxYValue(); else - ymax = referencePlot->speedCurve->maxYValue(); + ymax = referencePlot->standard->speedCurve->maxYValue(); } - if (tempCurve->isVisible() && context->athlete->useMetricUnits) { + if (standard->tempCurve->isVisible() && context->athlete->useMetricUnits) { labels << QString::fromUtf8("°C"); if (referencePlot == NULL) { - ymin = qMin(ymin, tempCurve->minYValue()); - ymax = qMax(ymax, tempCurve->maxYValue()); + ymin = qMin(ymin, standard->tempCurve->minYValue()); + ymax = qMax(ymax, standard->tempCurve->maxYValue()); } else { - ymin = qMin(ymin, referencePlot->tempCurve->minYValue()); - ymax = qMax(ymax, referencePlot->tempCurve->maxYValue()); + ymin = qMin(ymin, referencePlot->standard->tempCurve->minYValue()); + ymax = qMax(ymax, referencePlot->standard->tempCurve->maxYValue()); } } - if (torqueCurve->isVisible()) { + if (standard->torqueCurve->isVisible()) { labels << (context->athlete->useMetricUnits ? tr("Nm") : tr("ftLb")); if (referencePlot == NULL) - ymax = qMax(ymax, torqueCurve->maxYValue()); + ymax = qMax(ymax, standard->torqueCurve->maxYValue()); else - ymax = qMax(ymax, referencePlot->torqueCurve->maxYValue()); + ymax = qMax(ymax, referencePlot->standard->torqueCurve->maxYValue()); } setAxisTitle(yRight, labels.join(" / ")); setAxisScale(yRight, ymin, 1.05 * ymax); //setAxisLabelAlignment(yRight,Qt::AlignVCenter); } - if (altCurve->isVisible()) { + if (standard->altCurve->isVisible()) { setAxisTitle(QwtAxisId(QwtAxis::yRight, 1), context->athlete->useMetricUnits ? tr("Meters") : tr("Feet")); double ymin,ymax; if (referencePlot == NULL) { - ymin = altCurve->minYValue(); - ymax = qMax(ymin + 100, 1.05 * altCurve->maxYValue()); + ymin = standard->altCurve->minYValue(); + ymax = qMax(ymin + 100, 1.05 * standard->altCurve->maxYValue()); } else { - ymin = referencePlot->altCurve->minYValue(); - ymax = qMax(ymin + 100, 1.05 * referencePlot->altCurve->maxYValue()); + ymin = referencePlot->standard->altCurve->minYValue(); + ymax = qMax(ymin + 100, 1.05 * referencePlot->standard->altCurve->maxYValue()); } ymin = (ymin < 0 ? -100 : 0) + ( qRound(ymin) / 100 ) * 100; @@ -1306,22 +1481,30 @@ AllPlot::setYMax() //setAxisScale(QwtAxisId(QwtAxis::yRight, 2), ymin, ymax); setAxisScaleDiv(QwtAxisId(QwtAxis::yRight, 1),QwtScaleDiv(ymin,ymax,xytick)); //setAxisLabelAlignment(QwtAxisId(QwtAxis::yRight, 2),Qt::AlignVCenter); - altCurve->setBaseline(ymin); + standard->altCurve->setBaseline(ymin); } - enableAxis(yLeft, wattsCurve->isVisible() || npCurve->isVisible() || xpCurve->isVisible() || apCurve->isVisible()); - enableAxis(QwtAxisId(QwtAxis::yLeft, 1).id, hrCurve->isVisible() || cadCurve->isVisible()); - enableAxis(yRight, speedCurve->isVisible()); - enableAxis(QwtAxisId(QwtAxis::yRight, 1).id, altCurve->isVisible()); - enableAxis(QwtAxisId(QwtAxis::yRight, 2).id, wCurve->isVisible()); + if (wantaxis) { - setAxisVisible(yLeft, wattsCurve->isVisible() || npCurve->isVisible() || xpCurve->isVisible() || apCurve->isVisible()); - setAxisVisible(QwtAxisId(QwtAxis::yLeft, 1), hrCurve->isVisible() || cadCurve->isVisible()); - setAxisVisible(yRight, speedCurve->isVisible()); - setAxisVisible(QwtAxisId(QwtAxis::yRight, 1), altCurve->isVisible()); - setAxisVisible(QwtAxisId(QwtAxis::yRight, 2), wCurve->isVisible()); - enableAxis(xBottom, true); - setAxisVisible(xBottom, true); + setAxisVisible(yLeft, standard->wattsCurve->isVisible() || standard->npCurve->isVisible() || standard->xpCurve->isVisible() || standard->apCurve->isVisible()); + setAxisVisible(QwtAxisId(QwtAxis::yLeft, 1), standard->hrCurve->isVisible() || standard->cadCurve->isVisible()); + setAxisVisible(yRight, standard->speedCurve->isVisible()); + setAxisVisible(QwtAxisId(QwtAxis::yRight, 1), standard->altCurve->isVisible()); + setAxisVisible(QwtAxisId(QwtAxis::yRight, 2), standard->wCurve->isVisible()); + setAxisVisible(xBottom, true); + + } else { + + setAxisVisible(yLeft, false); + setAxisVisible(QwtAxisId(QwtAxis::yLeft,1), false); + setAxisVisible(QwtAxisId(QwtAxis::yLeft,2), false); + setAxisVisible(yRight, false); + setAxisVisible(QwtAxisId(QwtPlot::yRight,1), false); + setAxisVisible(QwtAxisId(QwtAxis::yRight,2), false); + setAxisVisible(QwtAxisId(QwtAxis::yRight,3), false); + setAxisVisible(xBottom, false); + + } } void @@ -1346,46 +1529,46 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) referencePlot = plot; // You got to give me some data first! - if (!plot->distanceArray.count() || !plot->timeArray.count()) return; + if (!plot->standard->distanceArray.count() || !plot->standard->timeArray.count()) return; // reference the plot for data and state rideItem = plot->rideItem; bydist = plot->bydist; - arrayLength = stopidx-startidx; + //arrayLength = stopidx-startidx; if (bydist) { - startidx = plot->distanceIndex(plot->distanceArray[startidx]); - stopidx = plot->distanceIndex(plot->distanceArray[(stopidx>=plot->distanceArray.size()?plot->distanceArray.size()-1:stopidx)])-1; + startidx = plot->distanceIndex(plot->standard->distanceArray[startidx]); + stopidx = plot->distanceIndex(plot->standard->distanceArray[(stopidx>=plot->standard->distanceArray.size()?plot->standard->distanceArray.size()-1:stopidx)])-1; } else { - startidx = plot->timeIndex(plot->timeArray[startidx]/60); - stopidx = plot->timeIndex(plot->timeArray[(stopidx>=plot->timeArray.size()?plot->timeArray.size()-1:stopidx)]/60)-1; + startidx = plot->timeIndex(plot->standard->timeArray[startidx]/60); + stopidx = plot->timeIndex(plot->standard->timeArray[(stopidx>=plot->standard->timeArray.size()?plot->standard->timeArray.size()-1:stopidx)]/60)-1; } // center the curve title - curveTitle.setYValue(30); - curveTitle.setXValue(2); + standard->curveTitle.setYValue(30); + standard->curveTitle.setXValue(2); // make sure indexes are still valid if (startidx > stopidx || startidx < 0 || stopidx < 0) return; - double *smoothW = &plot->smoothWatts[startidx]; - double *smoothN = &plot->smoothNP[startidx]; - double *smoothX = &plot->smoothXP[startidx]; - double *smoothL = &plot->smoothAP[startidx]; - double *smoothT = &plot->smoothTime[startidx]; - double *smoothHR = &plot->smoothHr[startidx]; - double *smoothS = &plot->smoothSpeed[startidx]; - double *smoothC = &plot->smoothCad[startidx]; - double *smoothA = &plot->smoothAltitude[startidx]; - double *smoothD = &plot->smoothDistance[startidx]; - double *smoothTE = &plot->smoothTemp[startidx]; - //double *smoothWND = &plot->smoothWind[startidx]; - double *smoothNM = &plot->smoothTorque[startidx]; - double *smoothBALL = &plot->smoothBalanceL[startidx]; - double *smoothBALR = &plot->smoothBalanceR[startidx]; + double *smoothW = &plot->standard->smoothWatts[startidx]; + double *smoothN = &plot->standard->smoothNP[startidx]; + double *smoothX = &plot->standard->smoothXP[startidx]; + double *smoothL = &plot->standard->smoothAP[startidx]; + double *smoothT = &plot->standard->smoothTime[startidx]; + double *smoothHR = &plot->standard->smoothHr[startidx]; + double *smoothS = &plot->standard->smoothSpeed[startidx]; + double *smoothC = &plot->standard->smoothCad[startidx]; + double *smoothA = &plot->standard->smoothAltitude[startidx]; + double *smoothD = &plot->standard->smoothDistance[startidx]; + double *smoothTE = &plot->standard->smoothTemp[startidx]; + //double *standard->smoothWND = &plot->standard->smoothWind[startidx]; + double *smoothNM = &plot->standard->smoothTorque[startidx]; + double *smoothBALL = &plot->standard->smoothBalanceL[startidx]; + double *smoothBALR = &plot->standard->smoothBalanceR[startidx]; - QwtIntervalSample *smoothRS = &plot->smoothRelSpeed[startidx]; + QwtIntervalSample *smoothRS = &plot->standard->smoothRelSpeed[startidx]; double *xaxis = bydist ? smoothD : smoothT; @@ -1410,61 +1593,61 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) text.setFont(QFont("Helvetica", 10, QFont::Bold)); text.setColor(GColor(CWBAL)); - curveTitle.setLabel(text); + standard->curveTitle.setLabel(text); } else { - curveTitle.setLabel(QwtText("")); + standard->curveTitle.setLabel(QwtText("")); } - wCurve->detach(); - mCurve->detach(); - wattsCurve->detach(); - npCurve->detach(); - xpCurve->detach(); - apCurve->detach(); - hrCurve->detach(); - speedCurve->detach(); - cadCurve->detach(); - altCurve->detach(); - tempCurve->detach(); - windCurve->detach(); - torqueCurve->detach(); - balanceLCurve->detach(); - balanceRCurve->detach(); + standard->wCurve->detach(); + standard->mCurve->detach(); + standard->wattsCurve->detach(); + standard->npCurve->detach(); + standard->xpCurve->detach(); + standard->apCurve->detach(); + standard->hrCurve->detach(); + standard->speedCurve->detach(); + standard->cadCurve->detach(); + standard->altCurve->detach(); + standard->tempCurve->detach(); + standard->windCurve->detach(); + standard->torqueCurve->detach(); + standard->balanceLCurve->detach(); + standard->balanceRCurve->detach(); - wattsCurve->setVisible(rideItem->ride()->areDataPresent()->watts && showPowerState < 2); - npCurve->setVisible(rideItem->ride()->areDataPresent()->np && showNP); - xpCurve->setVisible(rideItem->ride()->areDataPresent()->xp && showXP); - apCurve->setVisible(rideItem->ride()->areDataPresent()->apower && showAP); - wCurve->setVisible(rideItem->ride()->areDataPresent()->watts && showPowerState<2 && showW); - mCurve->setVisible(rideItem->ride()->areDataPresent()->watts && showPowerState<2 && showW); - hrCurve->setVisible(rideItem->ride()->areDataPresent()->hr && showHr); - speedCurve->setVisible(rideItem->ride()->areDataPresent()->kph && showSpeed); - cadCurve->setVisible(rideItem->ride()->areDataPresent()->cad && showCad); - altCurve->setVisible(rideItem->ride()->areDataPresent()->alt && showAlt); - tempCurve->setVisible(rideItem->ride()->areDataPresent()->temp && showTemp); - windCurve->setVisible(rideItem->ride()->areDataPresent()->headwind && showWind); - torqueCurve->setVisible(rideItem->ride()->areDataPresent()->nm && showTorque); - balanceLCurve->setVisible(rideItem->ride()->areDataPresent()->lrbalance && showBalance); - balanceRCurve->setVisible(rideItem->ride()->areDataPresent()->lrbalance && showBalance); + standard->wattsCurve->setVisible(rideItem->ride()->areDataPresent()->watts && showPowerState < 2); + standard->npCurve->setVisible(rideItem->ride()->areDataPresent()->np && showNP); + standard->xpCurve->setVisible(rideItem->ride()->areDataPresent()->xp && showXP); + standard->apCurve->setVisible(rideItem->ride()->areDataPresent()->apower && showAP); + standard->wCurve->setVisible(rideItem->ride()->areDataPresent()->watts && showPowerState<2 && showW); + standard->mCurve->setVisible(rideItem->ride()->areDataPresent()->watts && showPowerState<2 && showW); + standard->hrCurve->setVisible(rideItem->ride()->areDataPresent()->hr && showHr); + standard->speedCurve->setVisible(rideItem->ride()->areDataPresent()->kph && showSpeed); + standard->cadCurve->setVisible(rideItem->ride()->areDataPresent()->cad && showCad); + standard->altCurve->setVisible(rideItem->ride()->areDataPresent()->alt && showAlt); + standard->tempCurve->setVisible(rideItem->ride()->areDataPresent()->temp && showTemp); + standard->windCurve->setVisible(rideItem->ride()->areDataPresent()->headwind && showWind); + standard->torqueCurve->setVisible(rideItem->ride()->areDataPresent()->nm && showTorque); + standard->balanceLCurve->setVisible(rideItem->ride()->areDataPresent()->lrbalance && showBalance); + standard->balanceRCurve->setVisible(rideItem->ride()->areDataPresent()->lrbalance && showBalance); - wCurve->setSamples(parent->wpData->xdata().data(),parent->wpData->ydata().data(),parent->wpData->xdata().count()); - mCurve->setSamples(parent->wpData->mxdata().data(),parent->wpData->mydata().data(),parent->wpData->mxdata().count()); - wattsCurve->setSamples(xaxis,smoothW,stopidx-startidx); - npCurve->setSamples(xaxis,smoothN,stopidx-startidx); - xpCurve->setSamples(xaxis,smoothX,stopidx-startidx); - apCurve->setSamples(xaxis,smoothL,stopidx-startidx); - hrCurve->setSamples(xaxis, smoothHR,stopidx-startidx); - speedCurve->setSamples(xaxis, smoothS, stopidx-startidx); - cadCurve->setSamples(xaxis, smoothC, stopidx-startidx); - altCurve->setSamples(xaxis, smoothA, stopidx-startidx); - tempCurve->setSamples(xaxis, smoothTE, stopidx-startidx); + standard->wCurve->setSamples(parent->wpData->xdata().data(),parent->wpData->ydata().data(),parent->wpData->xdata().count()); + standard->mCurve->setSamples(parent->wpData->mxdata().data(),parent->wpData->mydata().data(),parent->wpData->mxdata().count()); + standard->wattsCurve->setSamples(xaxis,smoothW,stopidx-startidx); + standard->npCurve->setSamples(xaxis,smoothN,stopidx-startidx); + standard->xpCurve->setSamples(xaxis,smoothX,stopidx-startidx); + standard->apCurve->setSamples(xaxis,smoothL,stopidx-startidx); + standard->hrCurve->setSamples(xaxis, smoothHR,stopidx-startidx); + standard->speedCurve->setSamples(xaxis, smoothS, stopidx-startidx); + standard->cadCurve->setSamples(xaxis, smoothC, stopidx-startidx); + standard->altCurve->setSamples(xaxis, smoothA, stopidx-startidx); + standard->tempCurve->setSamples(xaxis, smoothTE, stopidx-startidx); QVector tmpWND(stopidx-startidx); memcpy(tmpWND.data(), smoothRS, (stopidx-startidx) * sizeof(QwtIntervalSample)); - windCurve->setSamples(new QwtIntervalSeriesData(tmpWND)); - torqueCurve->setSamples(xaxis, smoothNM, stopidx-startidx); - balanceLCurve->setSamples(xaxis, smoothBALL, stopidx-startidx); - balanceRCurve->setSamples(xaxis, smoothBALR, stopidx-startidx); + standard->windCurve->setSamples(new QwtIntervalSeriesData(tmpWND)); + standard->torqueCurve->setSamples(xaxis, smoothNM, stopidx-startidx); + standard->balanceLCurve->setSamples(xaxis, smoothBALL, stopidx-startidx); + standard->balanceRCurve->setSamples(xaxis, smoothBALR, stopidx-startidx); /*QVector _time(stopidx-startidx); qMemCopy( _time.data(), xaxis, (stopidx-startidx) * sizeof( double ) ); @@ -1472,7 +1655,7 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) QVector tmpWND(stopidx-startidx); for (int i=0;i<_time.count();i++) { QwtIntervalSample inter = QwtIntervalSample(_time.at(i), 20,50); - tmpWND.append(inter); // plot->smoothRelSpeed.at(i) + tmpWND.append(inter); // plot->standard->smoothRelSpeed.at(i) }*/ QwtSymbol *sym = new QwtSymbol; @@ -1484,7 +1667,7 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) sym->setStyle(QwtSymbol::NoSymbol); sym->setSize(0); } - wCurve->setSymbol(sym); + standard->wCurve->setSymbol(sym); sym = new QwtSymbol; sym->setPen(QPen(GColor(CPLOTMARKER))); @@ -1495,7 +1678,7 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) sym->setStyle(QwtSymbol::NoSymbol); sym->setSize(0); } - wattsCurve->setSymbol(sym); + standard->wattsCurve->setSymbol(sym); sym = new QwtSymbol; sym->setPen(QPen(GColor(CPLOTMARKER))); @@ -1506,7 +1689,7 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) sym->setStyle(QwtSymbol::NoSymbol); sym->setSize(0); } - npCurve->setSymbol(sym); + standard->npCurve->setSymbol(sym); sym = new QwtSymbol; sym->setPen(QPen(GColor(CPLOTMARKER))); @@ -1517,7 +1700,7 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) sym->setStyle(QwtSymbol::NoSymbol); sym->setSize(0); } - xpCurve->setSymbol(sym); + standard->xpCurve->setSymbol(sym); sym = new QwtSymbol; sym->setPen(QPen(GColor(CPLOTMARKER))); @@ -1528,7 +1711,7 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) sym->setStyle(QwtSymbol::NoSymbol); sym->setSize(0); } - apCurve->setSymbol(sym); + standard->apCurve->setSymbol(sym); sym = new QwtSymbol; sym->setPen(QPen(GColor(CPLOTMARKER))); @@ -1539,7 +1722,7 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) sym->setStyle(QwtSymbol::NoSymbol); sym->setSize(0); } - hrCurve->setSymbol(sym); + standard->hrCurve->setSymbol(sym); sym = new QwtSymbol; sym->setPen(QPen(GColor(CPLOTMARKER))); @@ -1550,7 +1733,7 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) sym->setStyle(QwtSymbol::NoSymbol); sym->setSize(0); } - speedCurve->setSymbol(sym); + standard->speedCurve->setSymbol(sym); sym = new QwtSymbol; sym->setPen(QPen(GColor(CPLOTMARKER))); @@ -1561,7 +1744,7 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) sym->setStyle(QwtSymbol::NoSymbol); sym->setSize(0); } - cadCurve->setSymbol(sym); + standard->cadCurve->setSymbol(sym); sym = new QwtSymbol; sym->setPen(QPen(GColor(CPLOTMARKER))); @@ -1572,7 +1755,7 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) sym->setStyle(QwtSymbol::NoSymbol); sym->setSize(0); } - altCurve->setSymbol(sym); + standard->altCurve->setSymbol(sym); sym = new QwtSymbol; sym->setPen(QPen(GColor(CPLOTMARKER))); @@ -1583,7 +1766,7 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) sym->setStyle(QwtSymbol::NoSymbol); sym->setSize(0); } - tempCurve->setSymbol(sym); + standard->tempCurve->setSymbol(sym); sym = new QwtSymbol; sym->setPen(QPen(GColor(CPLOTMARKER))); @@ -1594,7 +1777,7 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) sym->setStyle(QwtSymbol::NoSymbol); sym->setSize(0); } - torqueCurve->setSymbol(sym); + standard->torqueCurve->setSymbol(sym); sym = new QwtSymbol; sym->setPen(QPen(GColor(CPLOTMARKER))); @@ -1605,7 +1788,7 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) sym->setStyle(QwtSymbol::NoSymbol); sym->setSize(0); } - balanceLCurve->setSymbol(sym); + standard->balanceLCurve->setSymbol(sym); sym = new QwtSymbol; sym->setPen(QPen(GColor(CPLOTMARKER))); @@ -1616,7 +1799,7 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) sym->setStyle(QwtSymbol::NoSymbol); sym->setSize(0); } - balanceRCurve->setSymbol(sym); + standard->balanceRCurve->setSymbol(sym); setYMax(); @@ -1624,58 +1807,58 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) enableAxis(xBottom, true); setAxisVisible(xBottom, true); - if (!plot->smoothAltitude.empty()) { - altCurve->attach(this); - intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yRight, 1)); + if (!plot->standard->smoothAltitude.empty()) { + standard->altCurve->attach(this); + standard->intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yRight, 1)); } if (parent->wpData->xdata().count()) { - wCurve->attach(this); - mCurve->attach(this); + standard->wCurve->attach(this); + standard->mCurve->attach(this); } - if (!plot->smoothWatts.empty()) { - wattsCurve->attach(this); - intervalHighlighterCurve->setYAxis(yLeft); + if (!plot->standard->smoothWatts.empty()) { + standard->wattsCurve->attach(this); + standard->intervalHighlighterCurve->setYAxis(yLeft); } - if (!plot->smoothNP.empty()) { - npCurve->attach(this); - intervalHighlighterCurve->setYAxis(yLeft); + if (!plot->standard->smoothNP.empty()) { + standard->npCurve->attach(this); + standard->intervalHighlighterCurve->setYAxis(yLeft); } - if (!plot->smoothXP.empty()) { - xpCurve->attach(this); - intervalHighlighterCurve->setYAxis(yLeft); + if (!plot->standard->smoothXP.empty()) { + standard->xpCurve->attach(this); + standard->intervalHighlighterCurve->setYAxis(yLeft); } - if (!plot->smoothAP.empty()) { - apCurve->attach(this); - intervalHighlighterCurve->setYAxis(yLeft); + if (!plot->standard->smoothAP.empty()) { + standard->apCurve->attach(this); + standard->intervalHighlighterCurve->setYAxis(yLeft); } - if (!plot->smoothHr.empty()) { - hrCurve->attach(this); - intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); + if (!plot->standard->smoothHr.empty()) { + standard->hrCurve->attach(this); + standard->intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); } - if (!plot->smoothSpeed.empty()) { - speedCurve->attach(this); - intervalHighlighterCurve->setYAxis(yRight); + if (!plot->standard->smoothSpeed.empty()) { + standard->speedCurve->attach(this); + standard->intervalHighlighterCurve->setYAxis(yRight); } - if (!plot->smoothCad.empty()) { - cadCurve->attach(this); - intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); + if (!plot->standard->smoothCad.empty()) { + standard->cadCurve->attach(this); + standard->intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); } - if (!plot->smoothTemp.empty()) { - tempCurve->attach(this); - intervalHighlighterCurve->setYAxis(yRight); + if (!plot->standard->smoothTemp.empty()) { + standard->tempCurve->attach(this); + standard->intervalHighlighterCurve->setYAxis(yRight); } - if (!plot->smoothWind.empty()) { - windCurve->attach(this); - intervalHighlighterCurve->setYAxis(yRight); + if (!plot->standard->smoothWind.empty()) { + standard->windCurve->attach(this); + standard->intervalHighlighterCurve->setYAxis(yRight); } - if (!plot->smoothTorque.empty()) { - torqueCurve->attach(this); - intervalHighlighterCurve->setYAxis(yRight); + if (!plot->standard->smoothTorque.empty()) { + standard->torqueCurve->attach(this); + standard->intervalHighlighterCurve->setYAxis(yRight); } - if (!plot->smoothBalanceL.empty()) { - balanceLCurve->attach(this); - balanceRCurve->attach(this); - intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); + if (!plot->standard->smoothBalanceL.empty()) { + standard->balanceLCurve->attach(this); + standard->balanceRCurve->attach(this); + standard->intervalHighlighterCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 1)); } @@ -1703,37 +1886,37 @@ AllPlot::setDataFromPlot(AllPlot *plot) bydist = plot->bydist; // remove all curves from the plot - wCurve->detach(); - mCurve->detach(); - wattsCurve->detach(); - npCurve->detach(); - xpCurve->detach(); - apCurve->detach(); - hrCurve->detach(); - speedCurve->detach(); - cadCurve->detach(); - altCurve->detach(); - tempCurve->detach(); - windCurve->detach(); - torqueCurve->detach(); - balanceLCurve->detach(); - balanceRCurve->detach(); + standard->wCurve->detach(); + standard->mCurve->detach(); + standard->wattsCurve->detach(); + standard->npCurve->detach(); + standard->xpCurve->detach(); + standard->apCurve->detach(); + standard->hrCurve->detach(); + standard->speedCurve->detach(); + standard->cadCurve->detach(); + standard->altCurve->detach(); + standard->tempCurve->detach(); + standard->windCurve->detach(); + standard->torqueCurve->detach(); + standard->balanceLCurve->detach(); + standard->balanceRCurve->detach(); - wCurve->setVisible(false); - mCurve->setVisible(false); - wattsCurve->setVisible(false); - npCurve->setVisible(false); - xpCurve->setVisible(false); - apCurve->setVisible(false); - hrCurve->setVisible(false); - speedCurve->setVisible(false); - cadCurve->setVisible(false); - altCurve->setVisible(false); - tempCurve->setVisible(false); - windCurve->setVisible(false); - torqueCurve->setVisible(false); - balanceLCurve->setVisible(false); - balanceRCurve->setVisible(false); + standard->wCurve->setVisible(false); + standard->mCurve->setVisible(false); + standard->wattsCurve->setVisible(false); + standard->npCurve->setVisible(false); + standard->xpCurve->setVisible(false); + standard->apCurve->setVisible(false); + standard->hrCurve->setVisible(false); + standard->speedCurve->setVisible(false); + standard->cadCurve->setVisible(false); + standard->altCurve->setVisible(false); + standard->tempCurve->setVisible(false); + standard->windCurve->setVisible(false); + standard->torqueCurve->setVisible(false); + standard->balanceLCurve->setVisible(false); + standard->balanceRCurve->setVisible(false); QwtPlotCurve *ourCurve = NULL, *thereCurve = NULL; QwtPlotCurve *ourCurve2 = NULL, *thereCurve2 = NULL; @@ -1745,27 +1928,27 @@ AllPlot::setDataFromPlot(AllPlot *plot) case RideFile::cad: { - ourCurve = cadCurve; - thereCurve = referencePlot->cadCurve; + ourCurve = standard->cadCurve; + thereCurve = referencePlot->standard->cadCurve; title = tr("Cadence"); } break; case RideFile::hr: { - ourCurve = hrCurve; - thereCurve = referencePlot->hrCurve; + ourCurve = standard->hrCurve; + thereCurve = referencePlot->standard->hrCurve; title = tr("Heartrate"); } break; case RideFile::kph: { - ourCurve = speedCurve; - thereCurve = referencePlot->speedCurve; + ourCurve = standard->speedCurve; + thereCurve = referencePlot->standard->speedCurve; if (secondaryScope == RideFile::headwind) { - ourICurve = windCurve; - thereICurve = referencePlot->windCurve; + ourICurve = standard->windCurve; + thereICurve = referencePlot->standard->windCurve; } title = tr("Speed"); } @@ -1773,84 +1956,84 @@ AllPlot::setDataFromPlot(AllPlot *plot) case RideFile::nm: { - ourCurve = torqueCurve; - thereCurve = referencePlot->torqueCurve; + ourCurve = standard->torqueCurve; + thereCurve = referencePlot->standard->torqueCurve; title = tr("Torque"); } break; case RideFile::watts: { - ourCurve = wattsCurve; - thereCurve = referencePlot->wattsCurve; + ourCurve = standard->wattsCurve; + thereCurve = referencePlot->standard->wattsCurve; title = tr("Power"); } break; case RideFile::wprime: { - ourCurve = wCurve; - ourCurve2 = mCurve; - thereCurve = referencePlot->wCurve; - thereCurve2 = referencePlot->mCurve; + ourCurve = standard->wCurve; + ourCurve2 = standard->mCurve; + thereCurve = referencePlot->standard->wCurve; + thereCurve2 = referencePlot->standard->mCurve; title = tr("W'bal"); } break; case RideFile::alt: { - ourCurve = altCurve; - thereCurve = referencePlot->altCurve; + ourCurve = standard->altCurve; + thereCurve = referencePlot->standard->altCurve; title = tr("Altitude"); } break; case RideFile::headwind: { - ourICurve = windCurve; - thereICurve = referencePlot->windCurve; + ourICurve = standard->windCurve; + thereICurve = referencePlot->standard->windCurve; title = tr("Headwind"); } break; case RideFile::temp: { - ourCurve = tempCurve; - thereCurve = referencePlot->tempCurve; + ourCurve = standard->tempCurve; + thereCurve = referencePlot->standard->tempCurve; title = tr("Temperature"); } break; case RideFile::NP: { - ourCurve = npCurve; - thereCurve = referencePlot->npCurve; + ourCurve = standard->npCurve; + thereCurve = referencePlot->standard->npCurve; title = tr("NP"); } break; case RideFile::xPower: { - ourCurve = xpCurve; - thereCurve = referencePlot->xpCurve; + ourCurve = standard->xpCurve; + thereCurve = referencePlot->standard->xpCurve; title = tr("xPower"); } break; case RideFile::lrbalance: { - ourCurve = balanceLCurve; - ourCurve2 = balanceRCurve; - thereCurve = referencePlot->balanceLCurve; - thereCurve2 = referencePlot->balanceRCurve; + ourCurve = standard->balanceLCurve; + ourCurve2 = standard->balanceRCurve; + thereCurve = referencePlot->standard->balanceLCurve; + thereCurve2 = referencePlot->standard->balanceRCurve; title = tr("L/R Balance"); } break; case RideFile::aPower: { - ourCurve = apCurve; - thereCurve = referencePlot->apCurve; + ourCurve = standard->apCurve; + thereCurve = referencePlot->standard->apCurve; title = tr("aPower"); } break; @@ -1877,7 +2060,7 @@ AllPlot::setDataFromPlot(AllPlot *plot) // lets clone the data QVector array; - for (int i=0; idata()->size(); i++) array << thereCurve->data()->sample(i); + for (size_t i=0; idata()->size(); i++) array << thereCurve->data()->sample(i); ourCurve->setSamples(array); ourCurve->setYAxis(yLeft); @@ -1905,7 +2088,7 @@ AllPlot::setDataFromPlot(AllPlot *plot) // lets clone the data QVector array; - for (int i=0; idata()->size(); i++) array << thereCurve2->data()->sample(i); + for (size_t i=0; idata()->size(); i++) array << thereCurve2->data()->sample(i); ourCurve2->setSamples(array); ourCurve2->setYAxis(yLeft); @@ -1933,7 +2116,7 @@ AllPlot::setDataFromPlot(AllPlot *plot) // lets clone the data QVector array; - for (int i=0; idata()->size(); i++) array << thereICurve->data()->sample(i); + for (size_t i=0; idata()->size(); i++) array << thereICurve->data()->sample(i); ourICurve->setSamples(array); ourICurve->setYAxis(yLeft); @@ -1947,6 +2130,7 @@ AllPlot::setDataFromPlot(AllPlot *plot) enableAxis(QwtPlot::xBottom, true); setAxisVisible(QwtPlot::xBottom, true); + setXTitle(); // y-axis yLeft setAxisVisible(yLeft, true); @@ -1980,8 +2164,8 @@ AllPlot::setDataFromPlot(AllPlot *plot) setAxisVisible(QwtAxisId(QwtAxis::yRight, 1), false); setAxisVisible(QwtAxisId(QwtAxis::yRight, 2), false); - // plot grid - grid->setVisible(referencePlot->grid->isVisible()); + // plot standard->grid + standard->grid->setVisible(referencePlot->standard->grid->isVisible()); // plot markers etc refreshIntervalMarkers(); @@ -1989,99 +2173,623 @@ AllPlot::setDataFromPlot(AllPlot *plot) refreshReferenceLines(); // always draw against yLeft in series mode - intervalHighlighterCurve->setYAxis(yLeft); + standard->intervalHighlighterCurve->setYAxis(yLeft); if (thereCurve) - intervalHighlighterCurve->setBaseline(thereCurve->minYValue()); + standard->intervalHighlighterCurve->setBaseline(thereCurve->minYValue()); else if (thereICurve) - intervalHighlighterCurve->setBaseline(thereICurve->boundingRect().top()); + standard->intervalHighlighterCurve->setBaseline(thereICurve->boundingRect().top()); #if 0 refreshZoneLabels(); #endif } } +void +AllPlot::setDataFromPlots(QList plots) +{ + // remove all curves from the plot + standard->wCurve->detach(); + standard->mCurve->detach(); + standard->wattsCurve->detach(); + standard->npCurve->detach(); + standard->xpCurve->detach(); + standard->apCurve->detach(); + standard->hrCurve->detach(); + standard->speedCurve->detach(); + standard->cadCurve->detach(); + standard->altCurve->detach(); + standard->tempCurve->detach(); + standard->windCurve->detach(); + standard->torqueCurve->detach(); + standard->balanceLCurve->detach(); + standard->balanceRCurve->detach(); + + standard->wCurve->setVisible(false); + standard->mCurve->setVisible(false); + standard->wattsCurve->setVisible(false); + standard->npCurve->setVisible(false); + standard->xpCurve->setVisible(false); + standard->apCurve->setVisible(false); + standard->hrCurve->setVisible(false); + standard->speedCurve->setVisible(false); + standard->cadCurve->setVisible(false); + standard->altCurve->setVisible(false); + standard->tempCurve->setVisible(false); + standard->windCurve->setVisible(false); + standard->torqueCurve->setVisible(false); + standard->balanceLCurve->setVisible(false); + standard->balanceRCurve->setVisible(false); + + // clear previous curves + foreach(QwtPlotCurve *prior, compares) { + prior->detach(); + delete prior; + } + compares.clear(); + + double MAXY = -100; + + // add all the curves + int index=0; + foreach (AllPlot *plot, plots) { + + if (context->compareIntervals[index].isChecked() == false) { + index++; + continue; // ignore if not shown + } + + referencePlot = plot; + + QwtPlotCurve *ourCurve = NULL, *thereCurve = NULL; + QwtPlotCurve *ourCurve2 = NULL, *thereCurve2 = NULL; + QwtPlotIntervalCurve *ourICurve = NULL, *thereICurve = NULL; + QString title; + + // which curve are we interested in ? + switch (scope) { + + case RideFile::cad: + { + ourCurve = new QwtPlotCurve(tr("Cadence")); + ourCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + thereCurve = referencePlot->standard->cadCurve; + title = tr("Cadence"); + } + break; + + case RideFile::hr: + { + ourCurve = new QwtPlotCurve(tr("Heart Rate")); + ourCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + thereCurve = referencePlot->standard->hrCurve; + title = tr("Heartrate"); + } + break; + + case RideFile::kph: + { + ourCurve = new QwtPlotCurve(tr("Speed")); + ourCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + thereCurve = referencePlot->standard->speedCurve; + if (secondaryScope == RideFile::headwind) { + ourICurve = standard->windCurve; + thereICurve = referencePlot->standard->windCurve; + } + title = tr("Speed"); + } + break; + + case RideFile::nm: + { + ourCurve = new QwtPlotCurve(tr("Torque")); + ourCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + thereCurve = referencePlot->standard->torqueCurve; + title = tr("Torque"); + } + break; + + case RideFile::watts: + { + ourCurve = new QwtPlotCurve(tr("Power")); + ourCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + thereCurve = referencePlot->standard->wattsCurve; + title = tr("Power"); + } + break; + + case RideFile::wprime: + { + ourCurve = new QwtPlotCurve(tr("W' Balance (j)")); + ourCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + ourCurve2 = new QwtPlotCurve(tr("Matches")); + ourCurve2->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + ourCurve2->setStyle(QwtPlotCurve::Dots); + ourCurve2->setYAxis(QwtAxisId(QwtAxis::yRight, 2)); + + thereCurve = referencePlot->standard->wCurve; + thereCurve2 = referencePlot->standard->mCurve; + title = tr("W'bal"); + } + break; + + case RideFile::alt: + { + ourCurve = new QwtPlotCurve(tr("Altitude")); + ourCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + ourCurve->setZ(-10); // always at the back. + thereCurve = referencePlot->standard->altCurve; + title = tr("Altitude"); + } + break; + + case RideFile::headwind: + { + ourICurve = new QwtPlotIntervalCurve(tr("Headwind")); + thereICurve = referencePlot->standard->windCurve; + title = tr("Headwind"); + } + break; + + case RideFile::temp: + { + ourCurve = new QwtPlotCurve(tr("Temperature")); + ourCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + thereCurve = referencePlot->standard->tempCurve; + title = tr("Temperature"); + } + break; + + case RideFile::NP: + { + ourCurve = new QwtPlotCurve(tr("NP")); + ourCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + thereCurve = referencePlot->standard->npCurve; + title = tr("NP"); + } + break; + + case RideFile::xPower: + { + ourCurve = new QwtPlotCurve(tr("xPower")); + ourCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + thereCurve = referencePlot->standard->xpCurve; + title = tr("xPower"); + } + break; + + case RideFile::lrbalance: + { + ourCurve = new QwtPlotCurve(tr("Left Balance")); + ourCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + ourCurve2 = new QwtPlotCurve(tr("Right Balance")); + ourCurve2->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + thereCurve = referencePlot->standard->balanceLCurve; + thereCurve2 = referencePlot->standard->balanceRCurve; + title = tr("L/R Balance"); + } + break; + + case RideFile::aPower: + { + ourCurve = new QwtPlotCurve(tr("aPower")); + ourCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + thereCurve = referencePlot->standard->apCurve; + title = tr("aPower"); + } + break; + + default: + case RideFile::interval: + case RideFile::slope: + case RideFile::vam: + case RideFile::wattsKg: + case RideFile::km: + case RideFile::lon: + case RideFile::lat: + case RideFile::none: + break; + } + + bool antialias = appsettings->value(this, GC_ANTIALIAS, false).toBool(); + + // lets clone ! + if ((ourCurve && thereCurve) || (ourICurve && thereICurve)) { + + if (ourCurve && thereCurve) { + + // remember for next time... + compares << ourCurve; + + // colours etc + if (antialias) ourCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + QPen pen = thereCurve->pen(); + pen.setColor(context->compareIntervals[index].color); + ourCurve->setPen(pen); + ourCurve->setVisible(true); + ourCurve->attach(this); + + // lets clone the data + QVector array; + for (size_t i=0; idata()->size(); i++) array << thereCurve->data()->sample(i); + + ourCurve->setSamples(array); + ourCurve->setYAxis(yLeft); + ourCurve->setBaseline(thereCurve->baseline()); + + if (ourCurve->maxYValue() > MAXY) MAXY = ourCurve->maxYValue(); + + // symbol when zoomed in super close + if (array.size() < 150) { + QwtSymbol *sym = new QwtSymbol; + sym->setPen(QPen(GColor(CPLOTMARKER))); + sym->setStyle(QwtSymbol::Ellipse); + sym->setSize(3); + ourCurve->setSymbol(sym); + } else { + QwtSymbol *sym = new QwtSymbol; + sym->setStyle(QwtSymbol::NoSymbol); + sym->setSize(0); + ourCurve->setSymbol(sym); + } + } + + if (ourCurve2 && thereCurve2) { + + // remember for next time... + compares << ourCurve2; + + ourCurve2->setVisible(true); + ourCurve2->attach(this); + if (antialias) ourCurve2->setRenderHint(QwtPlotItem::RenderAntialiased); + QPen pen = thereCurve2->pen(); + pen.setColor(context->compareIntervals[index].color); + ourCurve2->setPen(pen); + + // lets clone the data + QVector array; + for (size_t i=0; idata()->size(); i++) array << thereCurve2->data()->sample(i); + + ourCurve2->setSamples(array); + ourCurve2->setYAxis(yLeft); + ourCurve2->setBaseline(thereCurve2->baseline()); + + if (ourCurve2->maxYValue() > MAXY) MAXY = ourCurve2->maxYValue(); + + // symbol when zoomed in super close + if (array.size() < 150) { + QwtSymbol *sym = new QwtSymbol; + sym->setPen(QPen(GColor(CPLOTMARKER))); + sym->setStyle(QwtSymbol::Ellipse); + sym->setSize(3); + ourCurve2->setSymbol(sym); + } else { + QwtSymbol *sym = new QwtSymbol; + sym->setStyle(QwtSymbol::NoSymbol); + sym->setSize(0); + ourCurve2->setSymbol(sym); + } + } + + if (ourICurve && thereICurve) { + + ourICurve->setVisible(true); + ourICurve->attach(this); + QPen pen = thereICurve->pen(); + pen.setColor(context->compareIntervals[index].color); + ourICurve->setPen(pen); + if (antialias) ourICurve->setRenderHint(QwtPlotItem::RenderAntialiased); + + // lets clone the data + QVector array; + for (size_t i=0; idata()->size(); i++) array << thereICurve->data()->sample(i); + + ourICurve->setSamples(array); + ourICurve->setYAxis(yLeft); + + //XXXX ???? DUNNO ????? + //XXXX FIX LATER XXXX if (ourICurve->maxYValue() > MAXY) MAXY = ourICurve->maxYValue(); + } + + } + + // move on -- this is used to reference into the compareIntervals + // array to get the colors predominantly! + index++; + } + + // x-axis + enableAxis(QwtPlot::xBottom, true); + setAxisVisible(QwtPlot::xBottom, true); + setAxisVisible(yLeft, true); + + // prettify the chart at the end + QwtScaleDraw *sd = new QwtScaleDraw; + sd->setTickLength(QwtScaleDiv::MajorTick, 3); + sd->enableComponent(QwtScaleDraw::Ticks, false); + sd->enableComponent(QwtScaleDraw::Backbone, false); + setAxisScaleDraw(QwtPlot::yLeft, sd); + + // set the y-axis for largest value we saw +10% + setAxisScale(QwtPlot::yLeft, 0, MAXY * 1.10f); + + // hide other y axes + setAxisVisible(QwtAxisId(QwtAxis::yLeft, 1), false); + setAxisVisible(yRight, false); + setAxisVisible(QwtAxisId(QwtAxis::yRight, 1), false); + setAxisVisible(QwtAxisId(QwtAxis::yRight, 2), false); +#if 0 + + // plot standard->grid + standard->grid->setVisible(referencePlot->standard->grid->isVisible()); + + // plot markers etc + refreshIntervalMarkers(); + refreshCalibrationMarkers(); + refreshReferenceLines(); + + // always draw against yLeft in series mode + intervalHighlighterCurve->setYAxis(yLeft); + if (thereCurve) + intervalHighlighterCurve->setBaseline(thereCurve->minYValue()); + else if (thereICurve) + intervalHighlighterCurve->setBaseline(thereICurve->boundingRect().top()); +#if 0 + refreshZoneLabels(); +#endif +#endif +} + +// used to setup array of allplots where there is one for +// each interval in compare mode +void +AllPlot::setDataFromObject(AllPlotObject *object, AllPlot *reference) +{ + referencePlot = reference; + bydist = reference->bydist; + + // remove all curves from the plot + standard->wCurve->detach(); + standard->mCurve->detach(); + standard->wattsCurve->detach(); + standard->npCurve->detach(); + standard->xpCurve->detach(); + standard->apCurve->detach(); + standard->hrCurve->detach(); + standard->speedCurve->detach(); + standard->cadCurve->detach(); + standard->altCurve->detach(); + standard->tempCurve->detach(); + standard->windCurve->detach(); + standard->torqueCurve->detach(); + standard->balanceLCurve->detach(); + standard->balanceRCurve->detach(); + standard->intervalHighlighterCurve->detach(); + + standard->wCurve->setVisible(false); + standard->mCurve->setVisible(false); + standard->wattsCurve->setVisible(false); + standard->npCurve->setVisible(false); + standard->xpCurve->setVisible(false); + standard->apCurve->setVisible(false); + standard->hrCurve->setVisible(false); + standard->speedCurve->setVisible(false); + standard->cadCurve->setVisible(false); + standard->altCurve->setVisible(false); + standard->tempCurve->setVisible(false); + standard->windCurve->setVisible(false); + standard->torqueCurve->setVisible(false); + standard->balanceLCurve->setVisible(false); + standard->balanceRCurve->setVisible(false); + standard->intervalHighlighterCurve->setVisible(false); + + // NOW SET OUR CURVES USING THEIR DATA ... + QVector &xaxis = referencePlot->bydist ? object->smoothDistance : object->smoothTime; + int totalPoints = xaxis.count(); + + //W' curve set to whatever data we have + //object->wCurve->setSamples(parent->wpData->xdata().data(), parent->wpData->ydata().data(), parent->wpData->xdata().count()); + //object->mCurve->setSamples(parent->wpData->mxdata().data(), parent->wpData->mydata().data(), parent->wpData->mxdata().count()); + + if (!object->wattsArray.empty()) { + standard->wattsCurve->setSamples(xaxis.data(), object->smoothWatts.data(), totalPoints); + standard->wattsCurve->attach(this); + standard->wattsCurve->setVisible(true); + } + + if (!object->npArray.empty()) { + standard->npCurve->setSamples(xaxis.data(), object->smoothNP.data(), totalPoints); + standard->npCurve->attach(this); + standard->npCurve->setVisible(true); + } + + if (!object->xpArray.empty()) { + standard->xpCurve->setSamples(xaxis.data(), object->smoothXP.data(), totalPoints); + standard->xpCurve->attach(this); + standard->xpCurve->setVisible(true); + } + + if (!object->apArray.empty()) { + standard->apCurve->setSamples(xaxis.data(), object->smoothAP.data(), totalPoints); + standard->apCurve->attach(this); + standard->apCurve->setVisible(true); + } + + if (!object->hrArray.empty()) { + standard->hrCurve->setSamples(xaxis.data(), object->smoothHr.data(), totalPoints); + standard->hrCurve->attach(this); + standard->hrCurve->setVisible(true); + } + + if (!object->speedArray.empty()) { + standard->speedCurve->setSamples(xaxis.data(), object->smoothSpeed.data(), totalPoints); + standard->speedCurve->attach(this); + standard->speedCurve->setVisible(true); + } + + if (!object->cadArray.empty()) { + standard->cadCurve->setSamples(xaxis.data(), object->smoothCad.data(), totalPoints); + standard->cadCurve->attach(this); + standard->cadCurve->setVisible(true); + } + + if (!object->altArray.empty()) { + standard->altCurve->setSamples(xaxis.data(), object->smoothAltitude.data(), totalPoints); + standard->altCurve->attach(this); + standard->altCurve->setVisible(true); + } + + if (!object->tempArray.empty()) { + standard->tempCurve->setSamples(xaxis.data(), object->smoothTemp.data(), totalPoints); + standard->tempCurve->attach(this); + standard->tempCurve->setVisible(true); + } + + + if (!object->windArray.empty()) { + standard->windCurve->setSamples(new QwtIntervalSeriesData(object->smoothRelSpeed)); + standard->windCurve->attach(this); + standard->windCurve->setVisible(true); + } + + if (!object->torqueArray.empty()) { + standard->torqueCurve->setSamples(xaxis.data(), object->smoothTorque.data(), totalPoints); + standard->torqueCurve->attach(this); + standard->torqueCurve->setVisible(true); + } + + if (!object->balanceArray.empty()) { + standard->balanceLCurve->setSamples(xaxis.data(), object->smoothBalanceL.data(), totalPoints); + standard->balanceRCurve->setSamples(xaxis.data(), object->smoothBalanceR.data(), totalPoints); + standard->balanceLCurve->attach(this); + standard->balanceLCurve->setVisible(true); + standard->balanceRCurve->attach(this); + standard->balanceRCurve->setVisible(true); + } + + // to the max / min + standard->grid->detach(); + + // honour user preferences + standard->wCurve->setVisible(referencePlot->showPowerState < 2 && referencePlot->showW); + standard->mCurve->setVisible(referencePlot->showPowerState < 2 && referencePlot->showW); + standard->wattsCurve->setVisible(referencePlot->showPowerState < 2); + standard->npCurve->setVisible(referencePlot->showNP); + standard->xpCurve->setVisible(referencePlot->showXP); + standard->apCurve->setVisible(referencePlot->showAP); + standard->hrCurve->setVisible(referencePlot->showHr); + standard->speedCurve->setVisible(referencePlot->showSpeed); + standard->cadCurve->setVisible(referencePlot->showCad); + standard->altCurve->setVisible(referencePlot->showAlt); + standard->tempCurve->setVisible(referencePlot->showTemp); + standard->windCurve->setVisible(referencePlot->showWind); + standard->torqueCurve->setVisible(referencePlot->showWind); + standard->balanceLCurve->setVisible(referencePlot->showBalance); + standard->balanceRCurve->setVisible(referencePlot->showBalance); + + // set xaxis -- but not min/max as we get called during smoothing + // and massively quicker to reuse data and replot + setXTitle(); + enableAxis(xBottom, true); + setAxisVisible(xBottom, true); + + // set the y-axis scales now + referencePlot = NULL; + setYMax(); + + replot(); +} + void AllPlot::setDataFromRide(RideItem *_rideItem) { rideItem = _rideItem; if (_rideItem == NULL) return; - wattsArray.clear(); - curveTitle.setLabel(QwtText(QString(""), QwtText::PlainText)); // default to no title + // we don't have a reference plot + referencePlot = NULL; - RideFile *ride = rideItem->ride(); + // bsically clear out + standard->wattsArray.clear(); + standard->curveTitle.setLabel(QwtText(QString(""), QwtText::PlainText)); // default to no title + + setDataFromRideFile(rideItem->ride(), standard); +} + +void +AllPlot::setDataFromRideFile(RideFile *ride, AllPlotObject *here) +{ if (ride && ride->dataPoints().size()) { const RideFileDataPresent *dataPresent = ride->areDataPresent(); int npoints = ride->dataPoints().size(); - wattsArray.resize(dataPresent->watts ? npoints : 0); - npArray.resize(dataPresent->np ? npoints : 0); - xpArray.resize(dataPresent->xp ? npoints : 0); - apArray.resize(dataPresent->apower ? npoints : 0); - hrArray.resize(dataPresent->hr ? npoints : 0); - speedArray.resize(dataPresent->kph ? npoints : 0); - cadArray.resize(dataPresent->cad ? npoints : 0); - altArray.resize(dataPresent->alt ? npoints : 0); - tempArray.resize(dataPresent->temp ? npoints : 0); - windArray.resize(dataPresent->headwind ? npoints : 0); - torqueArray.resize(dataPresent->nm ? npoints : 0); - balanceArray.resize(dataPresent->lrbalance ? npoints : 0); - timeArray.resize(npoints); - distanceArray.resize(npoints); + here->wattsArray.resize(dataPresent->watts ? npoints : 0); + here->npArray.resize(dataPresent->np ? npoints : 0); + here->xpArray.resize(dataPresent->xp ? npoints : 0); + here->apArray.resize(dataPresent->apower ? npoints : 0); + here->hrArray.resize(dataPresent->hr ? npoints : 0); + here->speedArray.resize(dataPresent->kph ? npoints : 0); + here->cadArray.resize(dataPresent->cad ? npoints : 0); + here->altArray.resize(dataPresent->alt ? npoints : 0); + here->tempArray.resize(dataPresent->temp ? npoints : 0); + here->windArray.resize(dataPresent->headwind ? npoints : 0); + here->torqueArray.resize(dataPresent->nm ? npoints : 0); + here->balanceArray.resize(dataPresent->lrbalance ? npoints : 0); + here->timeArray.resize(npoints); + here->distanceArray.resize(npoints); // attach appropriate curves - wCurve->detach(); - mCurve->detach(); - wattsCurve->detach(); - npCurve->detach(); - xpCurve->detach(); - apCurve->detach(); - hrCurve->detach(); - speedCurve->detach(); - cadCurve->detach(); - altCurve->detach(); - tempCurve->detach(); - windCurve->detach(); - torqueCurve->detach(); - balanceLCurve->detach(); - balanceRCurve->detach(); + here->wCurve->detach(); + here->mCurve->detach(); + here->wattsCurve->detach(); + here->npCurve->detach(); + here->xpCurve->detach(); + here->apCurve->detach(); + here->hrCurve->detach(); + here->speedCurve->detach(); + here->cadCurve->detach(); + here->altCurve->detach(); + here->tempCurve->detach(); + here->windCurve->detach(); + here->torqueCurve->detach(); + here->balanceLCurve->detach(); + here->balanceRCurve->detach(); - if (!altArray.empty()) altCurve->attach(this); - if (!wattsArray.empty()) wattsCurve->attach(this); - if (!npArray.empty()) npCurve->attach(this); - if (!xpArray.empty()) xpCurve->attach(this); - if (!apArray.empty()) apCurve->attach(this); + if (!here->altArray.empty()) here->altCurve->attach(this); + if (!here->wattsArray.empty()) here->wattsCurve->attach(this); + if (!here->npArray.empty()) here->npCurve->attach(this); + if (!here->xpArray.empty()) here->xpCurve->attach(this); + if (!here->apArray.empty()) here->apCurve->attach(this); if (!parent->wpData->ydata().empty()) { - wCurve->attach(this); - mCurve->attach(this); + here->wCurve->attach(this); + here->mCurve->attach(this); } - if (!hrArray.empty()) hrCurve->attach(this); - if (!speedArray.empty()) speedCurve->attach(this); - if (!cadArray.empty()) cadCurve->attach(this); - if (!tempArray.empty()) tempCurve->attach(this); - if (!windArray.empty()) windCurve->attach(this); - if (!torqueArray.empty()) torqueCurve->attach(this); - if (!balanceArray.empty()) { - balanceLCurve->attach(this); - balanceRCurve->attach(this); + if (!here->hrArray.empty()) here->hrCurve->attach(this); + if (!here->speedArray.empty()) here->speedCurve->attach(this); + if (!here->cadArray.empty()) here->cadCurve->attach(this); + if (!here->tempArray.empty()) here->tempCurve->attach(this); + if (!here->windArray.empty()) here->windCurve->attach(this); + if (!here->torqueArray.empty()) here->torqueCurve->attach(this); + if (!here->balanceArray.empty()) { + here->balanceLCurve->attach(this); + here->balanceRCurve->attach(this); } - wCurve->setVisible(dataPresent->watts && showPowerState < 2 && showW); - mCurve->setVisible(dataPresent->watts && showPowerState < 2 && showW); - wattsCurve->setVisible(dataPresent->watts && showPowerState < 2); - npCurve->setVisible(dataPresent->np && showNP); - xpCurve->setVisible(dataPresent->xp && showXP); - apCurve->setVisible(dataPresent->apower && showAP); - hrCurve->setVisible(dataPresent->hr && showHr); - speedCurve->setVisible(dataPresent->kph && showSpeed); - cadCurve->setVisible(dataPresent->cad && showCad); - altCurve->setVisible(dataPresent->alt && showAlt); - tempCurve->setVisible(dataPresent->temp && showTemp); - windCurve->setVisible(dataPresent->headwind && showWind); - torqueCurve->setVisible(dataPresent->nm && showWind); - balanceLCurve->setVisible(dataPresent->lrbalance && showBalance); - balanceRCurve->setVisible(dataPresent->lrbalance && showBalance); + here->wCurve->setVisible(dataPresent->watts && showPowerState < 2 && showW); + here->mCurve->setVisible(dataPresent->watts && showPowerState < 2 && showW); + here->wattsCurve->setVisible(dataPresent->watts && showPowerState < 2); + here->npCurve->setVisible(dataPresent->np && showNP); + here->xpCurve->setVisible(dataPresent->xp && showXP); + here->apCurve->setVisible(dataPresent->apower && showAP); + here->hrCurve->setVisible(dataPresent->hr && showHr); + here->speedCurve->setVisible(dataPresent->kph && showSpeed); + here->cadCurve->setVisible(dataPresent->cad && showCad); + here->altCurve->setVisible(dataPresent->alt && showAlt); + here->tempCurve->setVisible(dataPresent->temp && showTemp); + here->windCurve->setVisible(dataPresent->headwind && showWind); + here->torqueCurve->setVisible(dataPresent->nm && showWind); + here->balanceLCurve->setVisible(dataPresent->lrbalance && showBalance); + here->balanceRCurve->setVisible(dataPresent->lrbalance && showBalance); - arrayLength = 0; + int arrayLength = 0; foreach (const RideFilePoint *point, ride->dataPoints()) { // we round the time to nearest 100th of a second @@ -2097,83 +2805,91 @@ AllPlot::setDataFromRide(RideItem *_rideItem) double secs = floor(point->secs); double msecs = round((point->secs - secs) * 100) * 10; - timeArray[arrayLength] = secs + msecs/1000; - if (!wattsArray.empty()) wattsArray[arrayLength] = max(0, point->watts); - if (!npArray.empty()) npArray[arrayLength] = max(0, point->np); - if (!xpArray.empty()) xpArray[arrayLength] = max(0, point->xp); - if (!apArray.empty()) apArray[arrayLength] = max(0, point->apower); + here->timeArray[arrayLength] = secs + msecs/1000; + if (!here->wattsArray.empty()) here->wattsArray[arrayLength] = max(0, point->watts); + if (!here->npArray.empty()) here->npArray[arrayLength] = max(0, point->np); + if (!here->xpArray.empty()) here->xpArray[arrayLength] = max(0, point->xp); + if (!here->apArray.empty()) here->apArray[arrayLength] = max(0, point->apower); - if (!hrArray.empty()) - hrArray[arrayLength] = max(0, point->hr); - if (!speedArray.empty()) - speedArray[arrayLength] = max(0, + if (!here->hrArray.empty()) + here->hrArray[arrayLength] = max(0, point->hr); + if (!here->speedArray.empty()) + here->speedArray[arrayLength] = max(0, (context->athlete->useMetricUnits ? point->kph : point->kph * MILES_PER_KM)); - if (!cadArray.empty()) - cadArray[arrayLength] = max(0, point->cad); - if (!altArray.empty()) - altArray[arrayLength] = (context->athlete->useMetricUnits + if (!here->cadArray.empty()) + here->cadArray[arrayLength] = max(0, point->cad); + if (!here->altArray.empty()) + here->altArray[arrayLength] = (context->athlete->useMetricUnits ? point->alt : point->alt * FEET_PER_METER); - if (!tempArray.empty()) - tempArray[arrayLength] = point->temp; + if (!here->tempArray.empty()) + here->tempArray[arrayLength] = point->temp; - if (!windArray.empty()) - windArray[arrayLength] = max(0, + if (!here->windArray.empty()) + here->windArray[arrayLength] = max(0, (context->athlete->useMetricUnits ? point->headwind : point->headwind * MILES_PER_KM)); - if (!balanceArray.empty()) - balanceArray[arrayLength] = point->lrbalance; + if (!here->balanceArray.empty()) + here->balanceArray[arrayLength] = point->lrbalance; - distanceArray[arrayLength] = max(0, + here->distanceArray[arrayLength] = max(0, (context->athlete->useMetricUnits ? point->km : point->km * MILES_PER_KM)); - if (!torqueArray.empty()) - torqueArray[arrayLength] = max(0, + if (!here->torqueArray.empty()) + here->torqueArray[arrayLength] = max(0, (context->athlete->useMetricUnits ? point->nm : point->nm * FEET_LB_PER_NM)); ++arrayLength; } - recalc(); + recalc(here); } else { //setTitle("no data"); - wCurve->detach(); - mCurve->detach(); - wattsCurve->detach(); - npCurve->detach(); - xpCurve->detach(); - apCurve->detach(); - hrCurve->detach(); - speedCurve->detach(); - cadCurve->detach(); - altCurve->detach(); - tempCurve->detach(); - windCurve->detach(); - torqueCurve->detach(); - balanceLCurve->detach(); - balanceRCurve->detach(); + here->wCurve->detach(); + here->mCurve->detach(); + here->wattsCurve->detach(); + here->npCurve->detach(); + here->xpCurve->detach(); + here->apCurve->detach(); + here->hrCurve->detach(); + here->speedCurve->detach(); + here->cadCurve->detach(); + here->altCurve->detach(); + here->tempCurve->detach(); + here->windCurve->detach(); + here->torqueCurve->detach(); + here->balanceLCurve->detach(); + here->balanceRCurve->detach(); - foreach(QwtPlotMarker *mrk, d_mrk) + foreach(QwtPlotMarker *mrk, here->d_mrk) delete mrk; - d_mrk.clear(); + here->d_mrk.clear(); - foreach(QwtPlotMarker *mrk, cal_mrk) + foreach(QwtPlotMarker *mrk, here->cal_mrk) delete mrk; - cal_mrk.clear(); + here->cal_mrk.clear(); - foreach(QwtPlotCurve *referenceLine, referenceLines) { + foreach(QwtPlotCurve *referenceLine, here->referenceLines) { referenceLine->detach(); delete referenceLine; } - referenceLines.clear(); + here->referenceLines.clear(); + } + + // record the max x value + if (here->timeArray.count() && here->distanceArray.count()) { + int maxSECS = here->timeArray[here->timeArray.count()-1]; + int maxKM = here->distanceArray[here->distanceArray.count()-1]; + if (maxKM > here->maxKM) here->maxKM = maxKM; + if (maxSECS > here->maxSECS) here->maxSECS = maxSECS; } } @@ -2183,7 +2899,7 @@ AllPlot::setShowPower(int id) if (showPowerState == id) return; showPowerState = id; - wattsCurve->setVisible(id < 2); + standard->wattsCurve->setVisible(id < 2); shade_zones = (id == 0); setYMax(); if (shade_zones) { @@ -2197,7 +2913,7 @@ void AllPlot::setShowNP(bool show) { showNP = show; - npCurve->setVisible(show); + standard->npCurve->setVisible(show); setYMax(); replot(); } @@ -2206,7 +2922,7 @@ void AllPlot::setShowXP(bool show) { showXP = show; - xpCurve->setVisible(show); + standard->xpCurve->setVisible(show); setYMax(); replot(); } @@ -2215,7 +2931,7 @@ void AllPlot::setShowAP(bool show) { showAP = show; - apCurve->setVisible(show); + standard->apCurve->setVisible(show); setYMax(); replot(); } @@ -2224,7 +2940,7 @@ void AllPlot::setShowHr(bool show) { showHr = show; - hrCurve->setVisible(show); + standard->hrCurve->setVisible(show); setYMax(); replot(); } @@ -2233,7 +2949,7 @@ void AllPlot::setShowSpeed(bool show) { showSpeed = show; - speedCurve->setVisible(show); + standard->speedCurve->setVisible(show); setYMax(); replot(); } @@ -2242,7 +2958,7 @@ void AllPlot::setShowCad(bool show) { showCad = show; - cadCurve->setVisible(show); + standard->cadCurve->setVisible(show); setYMax(); replot(); } @@ -2251,7 +2967,7 @@ void AllPlot::setShowAlt(bool show) { showAlt = show; - altCurve->setVisible(show); + standard->altCurve->setVisible(show); setYMax(); replot(); } @@ -2260,7 +2976,7 @@ void AllPlot::setShowTemp(bool show) { showTemp = show; - tempCurve->setVisible(show); + standard->tempCurve->setVisible(show); setYMax(); replot(); } @@ -2269,7 +2985,7 @@ void AllPlot::setShowWind(bool show) { showWind = show; - windCurve->setVisible(show); + standard->windCurve->setVisible(show); setYMax(); replot(); } @@ -2278,10 +2994,10 @@ void AllPlot::setShowW(bool show) { showW = show; - wCurve->setVisible(show); - mCurve->setVisible(show); + standard->wCurve->setVisible(show); + standard->mCurve->setVisible(show); if (!showW || parent->wpData->TAU <= 0) { - curveTitle.setLabel(QwtText("")); + standard->curveTitle.setLabel(QwtText("")); } setYMax(); replot(); @@ -2291,7 +3007,7 @@ void AllPlot::setShowTorque(bool show) { showTorque = show; - torqueCurve->setVisible(show); + standard->torqueCurve->setVisible(show); setYMax(); replot(); } @@ -2300,8 +3016,8 @@ void AllPlot::setShowBalance(bool show) { showBalance = show; - balanceLCurve->setVisible(show); - balanceRCurve->setVisible(show); + standard->balanceLCurve->setVisible(show); + standard->balanceRCurve->setVisible(show); setYMax(); replot(); } @@ -2309,7 +3025,7 @@ AllPlot::setShowBalance(bool show) void AllPlot::setShowGrid(bool show) { - grid->setVisible(show); + standard->grid->setVisible(show); replot(); } @@ -2319,66 +3035,66 @@ AllPlot::setPaintBrush(int state) if (state) { QColor p; - p = wCurve->pen().color(); + p = standard->wCurve->pen().color(); p.setAlpha(64); - wCurve->setBrush(QBrush(p)); + standard->wCurve->setBrush(QBrush(p)); - p = wattsCurve->pen().color(); + p = standard->wattsCurve->pen().color(); p.setAlpha(64); - wattsCurve->setBrush(QBrush(p)); + standard->wattsCurve->setBrush(QBrush(p)); - p = npCurve->pen().color(); + p = standard->npCurve->pen().color(); p.setAlpha(64); - npCurve->setBrush(QBrush(p)); + standard->npCurve->setBrush(QBrush(p)); - p = xpCurve->pen().color(); + p = standard->xpCurve->pen().color(); p.setAlpha(64); - xpCurve->setBrush(QBrush(p)); + standard->xpCurve->setBrush(QBrush(p)); - p = apCurve->pen().color(); + p = standard->apCurve->pen().color(); p.setAlpha(64); - apCurve->setBrush(QBrush(p)); + standard->apCurve->setBrush(QBrush(p)); - p = hrCurve->pen().color(); + p = standard->hrCurve->pen().color(); p.setAlpha(64); - hrCurve->setBrush(QBrush(p)); + standard->hrCurve->setBrush(QBrush(p)); - p = speedCurve->pen().color(); + p = standard->speedCurve->pen().color(); p.setAlpha(64); - speedCurve->setBrush(QBrush(p)); + standard->speedCurve->setBrush(QBrush(p)); - p = cadCurve->pen().color(); + p = standard->cadCurve->pen().color(); p.setAlpha(64); - cadCurve->setBrush(QBrush(p)); + standard->cadCurve->setBrush(QBrush(p)); - p = tempCurve->pen().color(); + p = standard->tempCurve->pen().color(); p.setAlpha(64); - tempCurve->setBrush(QBrush(p)); + standard->tempCurve->setBrush(QBrush(p)); - p = torqueCurve->pen().color(); + p = standard->torqueCurve->pen().color(); p.setAlpha(64); - torqueCurve->setBrush(QBrush(p)); + standard->torqueCurve->setBrush(QBrush(p)); - /*p = balanceLCurve->pen().color(); + /*p = standard->balanceLCurve->pen().color(); p.setAlpha(64); - balanceLCurve->setBrush(QBrush(p)); + standard->balanceLCurve->setBrush(QBrush(p)); - p = balanceRCurve->pen().color(); + p = standard->balanceRCurve->pen().color(); p.setAlpha(64); - balanceRCurve->setBrush(QBrush(p));*/ + standard->balanceRCurve->setBrush(QBrush(p));*/ } else { - wCurve->setBrush(Qt::NoBrush); - wattsCurve->setBrush(Qt::NoBrush); - npCurve->setBrush(Qt::NoBrush); - xpCurve->setBrush(Qt::NoBrush); - apCurve->setBrush(Qt::NoBrush); - hrCurve->setBrush(Qt::NoBrush); - speedCurve->setBrush(Qt::NoBrush); - cadCurve->setBrush(Qt::NoBrush); - tempCurve->setBrush(Qt::NoBrush); - torqueCurve->setBrush(Qt::NoBrush); - //balanceLCurve->setBrush(Qt::NoBrush); - //balanceRCurve->setBrush(Qt::NoBrush); + standard->wCurve->setBrush(Qt::NoBrush); + standard->wattsCurve->setBrush(Qt::NoBrush); + standard->npCurve->setBrush(Qt::NoBrush); + standard->xpCurve->setBrush(Qt::NoBrush); + standard->apCurve->setBrush(Qt::NoBrush); + standard->hrCurve->setBrush(Qt::NoBrush); + standard->speedCurve->setBrush(Qt::NoBrush); + standard->cadCurve->setBrush(Qt::NoBrush); + standard->tempCurve->setBrush(Qt::NoBrush); + standard->torqueCurve->setBrush(Qt::NoBrush); + //standard->balanceLCurve->setBrush(Qt::NoBrush); + //standard->balanceRCurve->setBrush(Qt::NoBrush); } replot(); } @@ -2387,7 +3103,7 @@ void AllPlot::setSmoothing(int value) { smooth = value; - recalc(); + recalc(standard); } void @@ -2395,7 +3111,7 @@ AllPlot::setByDistance(int id) { bydist = (id == 1); setXTitle(); - recalc(); + recalc(standard); } struct ComparePoints { @@ -2409,10 +3125,10 @@ AllPlot::timeIndex(double min) const { // return index offset for specified time QVector::const_iterator i = std::lower_bound( - smoothTime.begin(), smoothTime.end(), min, ComparePoints()); - if (i == smoothTime.end()) - return smoothTime.size(); - return i - smoothTime.begin(); + standard->smoothTime.begin(), standard->smoothTime.end(), min, ComparePoints()); + if (i == standard->smoothTime.end()) + return standard->smoothTime.size(); + return i - standard->smoothTime.begin(); } @@ -2422,10 +3138,10 @@ AllPlot::distanceIndex(double km) const { // return index offset for specified distance in km QVector::const_iterator i = std::lower_bound( - smoothDistance.begin(), smoothDistance.end(), km, ComparePoints()); - if (i == smoothDistance.end()) - return smoothDistance.size(); - return i - smoothDistance.begin(); + standard->smoothDistance.begin(), standard->smoothDistance.end(), km, ComparePoints()); + if (i == standard->smoothDistance.end()) + return standard->smoothDistance.size(); + return i - standard->smoothDistance.begin(); } /*---------------------------------------------------------------------- * Interval plotting @@ -2545,7 +3261,7 @@ QRectF IntervalPlotData::boundingRect() const void AllPlot::pointHover(QwtPlotCurve *curve, int index) { - if (index >= 0 && curve != intervalHighlighterCurve) { + if (index >= 0 && curve != standard->intervalHighlighterCurve) { double yvalue = curve->sample(index).y(); double xvalue = curve->sample(index).x(); @@ -2639,18 +3355,18 @@ AllPlot::plotTmpReference(int axis, int x, int y) RideFilePoint *referencePoint = new RideFilePoint(); referencePoint->watts = invTransform(axis, y); - foreach(QwtPlotCurve *curve, tmpReferenceLines) { + foreach(QwtPlotCurve *curve, standard->tmpReferenceLines) { if (curve) { curve->detach(); delete curve; } } - tmpReferenceLines.clear(); + standard->tmpReferenceLines.clear(); // only plot if they are relevant to the plot. QwtPlotCurve *referenceLine = parent->allPlot->plotReferenceLine(referencePoint); if (referenceLine) { - tmpReferenceLines.append(referenceLine); + standard->tmpReferenceLines.append(referenceLine); parent->allPlot->replot(); } @@ -2658,7 +3374,7 @@ AllPlot::plotTmpReference(int axis, int x, int y) foreach(AllPlot *plot, parent->seriesPlots) { QwtPlotCurve *referenceLine = plot->plotReferenceLine(referencePoint); if (referenceLine) { - tmpReferenceLines.append(referenceLine); + standard->tmpReferenceLines.append(referenceLine); plot->replot(); } } @@ -2667,7 +3383,7 @@ AllPlot::plotTmpReference(int axis, int x, int y) foreach(AllPlot *plot, parent->allPlots) { QwtPlotCurve *referenceLine = plot->plotReferenceLine(referencePoint); if (referenceLine) { - tmpReferenceLines.append(referenceLine); + standard->tmpReferenceLines.append(referenceLine); plot->replot(); } } @@ -2676,13 +3392,13 @@ AllPlot::plotTmpReference(int axis, int x, int y) } else { // wipe any we don't want - foreach(QwtPlotCurve *curve, tmpReferenceLines) { + foreach(QwtPlotCurve *curve, standard->tmpReferenceLines) { if (curve) { curve->detach(); delete curve; } } - tmpReferenceLines.clear(); + standard->tmpReferenceLines.clear(); parent->allPlot->replot(); foreach(AllPlot *plot, parent->seriesPlots) { plot->replot(); diff --git a/src/AllPlot.h b/src/AllPlot.h index a5725b58a..61a0f0b94 100644 --- a/src/AllPlot.h +++ b/src/AllPlot.h @@ -52,6 +52,95 @@ class Context; class LTMToolTip; class LTMCanvasPicker; +class AllPlot; +class AllPlotObject : public QObject +{ + Q_OBJECT; + + // one set for every ride being plotted, which + // as standard is just one, its only when we start + // compare mode that we get more... + + public: + + AllPlotObject(AllPlot*); // construct associate with a plot + ~AllPlotObject(); // delete and disassociate from a plot + + void setVisible(bool); // show or hide objects + void setColor(QColor color); // set ALL curves the same color + void hideUnwanted(); // hide curves we are not interested in + // using setVisible ... + + QwtPlotGrid *grid; + QVector d_mrk; + QVector cal_mrk; + QwtPlotMarker curveTitle; + QwtPlotMarker *allMarker1; + QwtPlotMarker *allMarker2; + // reference lines + QVector referenceLines; + QVector tmpReferenceLines; + + QwtPlotCurve *wattsCurve; + QwtPlotCurve *npCurve; + QwtPlotCurve *xpCurve; + QwtPlotCurve *apCurve; + QwtPlotCurve *hrCurve; + QwtPlotCurve *speedCurve; + QwtPlotCurve *cadCurve; + QwtPlotCurve *altCurve; + QwtPlotCurve *tempCurve; + QwtPlotIntervalCurve *windCurve; + QwtPlotCurve *torqueCurve; + QwtPlotCurve *balanceLCurve; + QwtPlotCurve *balanceRCurve; + QwtPlotCurve *wCurve; + QwtPlotCurve *mCurve; + + // source data + QVector hrArray; + QVector wattsArray; + QVector npArray; + QVector xpArray; + QVector apArray; + QVector speedArray; + QVector cadArray; + QVector timeArray; + QVector distanceArray; + QVector altArray; + QVector tempArray; + QVector windArray; + QVector torqueArray; + QVector balanceArray; + + // smoothed data + QVector smoothWatts; + QVector smoothNP; + QVector smoothAP; + QVector smoothXP; + QVector smoothHr; + QVector smoothSpeed; + QVector smoothCad; + QVector smoothTime; + QVector smoothDistance; + QVector smoothAltitude; + QVector smoothTemp; + QVector smoothWind; + QVector smoothTorque; + QVector smoothBalanceL; + QVector smoothBalanceR; + QVector smoothRelSpeed; + + // highlighting intervals + QwtPlotCurve *intervalHighlighterCurve; // highlight selected intervals on the Plot + + // the plot we work for + AllPlot *plot; + + // some handy stuff + double maxSECS, maxKM; +}; + class AllPlot : public QwtPlot { Q_OBJECT @@ -64,13 +153,18 @@ class AllPlot : public QwtPlot // wanttext is to say if plot markers should have text AllPlot(AllPlotWindow *parent, Context *context, RideFile::SeriesType series = RideFile::none, RideFile::SeriesType secSeries = RideFile::none, bool wanttext = true); + ~AllPlot(); bool eventFilter(QObject *object, QEvent *e); // set the curve data e.g. when a ride is selected void setDataFromRide(RideItem *_rideItem); + void setDataFromRideFile(RideFile *ride, AllPlotObject *object); // when plotting lots of rides on fullPlot void setDataFromPlot(AllPlot *plot, int startidx, int stopidx); void setDataFromPlot(AllPlot *plot); // used for single series plotting + void setDataFromPlots(QList); // user for single series comparing + void setDataFromObject(AllPlotObject *object, AllPlot *reference); // for allplot when one per ride in a stack + // reference is for settings et al // convert from time/distance to index in *smoothed* datapoints int timeIndex(double) const; @@ -86,9 +180,10 @@ class AllPlot : public QwtPlot void setAxisTitle(QwtAxisId axis, QString label); // refresh data / plot parameters - void recalc(); + void recalc(AllPlotObject *objects); void setYMax(); void setXTitle(); + void setHighlightIntervals(bool); void plotTmpReference(int axis, int x, int y); void confirmTmpReference(double value, int axis, bool allowDelete); @@ -114,6 +209,7 @@ class AllPlot : public QwtPlot void setShadeZones(bool x) { shade_zones=x; } void setSmoothing(int value); void setByDistance(int value); + void setWantAxis(bool x) { wantaxis = x;} void configChanged(); // for tooltip @@ -130,7 +226,6 @@ class AllPlot : public QwtPlot RideItem *rideItem; AllPlotBackground *bg; QSettings *settings; - bool wanttext; // controls bool shade_zones; @@ -149,68 +244,12 @@ class AllPlot : public QwtPlot bool showBalance; // plot objects - QwtPlotGrid *grid; - QVector d_mrk; - QVector cal_mrk; - QwtPlotMarker curveTitle; - QwtPlotMarker *allMarker1; - QwtPlotMarker *allMarker2; - QwtPlotCurve *wattsCurve; - QwtPlotCurve *npCurve; - QwtPlotCurve *xpCurve; - QwtPlotCurve *apCurve; - QwtPlotCurve *hrCurve; - QwtPlotCurve *speedCurve; - QwtPlotCurve *cadCurve; - QwtPlotCurve *altCurve; - QwtPlotCurve *tempCurve; - QwtPlotIntervalCurve *windCurve; - QwtPlotCurve *torqueCurve; - QwtPlotCurve *balanceLCurve; - QwtPlotCurve *balanceRCurve; - QwtPlotCurve *wCurve; - QwtPlotCurve *mCurve; - QwtPlotCurve *intervalHighlighterCurve; // highlight selected intervals on the Plot + AllPlotObject *standard; + QList compares; // when plotting single series in compare mode + QList zoneLabels; - QVector referenceLines; - QVector tmpReferenceLines; - - // source data - QVector hrArray; - QVector wattsArray; - QVector npArray; - QVector xpArray; - QVector apArray; - QVector speedArray; - QVector cadArray; - QVector timeArray; - QVector distanceArray; - QVector altArray; - QVector tempArray; - QVector windArray; - QVector torqueArray; - QVector balanceArray; - - // smoothed data - QVector smoothWatts; - QVector smoothNP; - QVector smoothAP; - QVector smoothXP; - QVector smoothHr; - QVector smoothSpeed; - QVector smoothCad; - QVector smoothTime; - QVector smoothDistance; - QVector smoothAltitude; - QVector smoothTemp; - QVector smoothWind; - QVector smoothTorque; - QVector smoothBalanceL; - QVector smoothBalanceR; - QVector smoothRelSpeed; // array / smooth state - int arrayLength; int smooth; bool bydist; @@ -218,11 +257,15 @@ class AllPlot : public QwtPlot RideFile::SeriesType scope; RideFile::SeriesType secondaryScope; - private: + protected: + friend class ::AllPlotObject; Context *context; + private: + AllPlot *referencePlot; AllPlotWindow *parent; + bool wanttext, wantaxis; LTMToolTip *tooltip; LTMCanvasPicker *_canvasPicker; // allow point selection/hover diff --git a/src/AllPlotWindow.cpp b/src/AllPlotWindow.cpp index 6ef1f2190..d98e2aef8 100644 --- a/src/AllPlotWindow.cpp +++ b/src/AllPlotWindow.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2009 Sean C. Rhea (srhea@srhea.net) + * Copyright (c) 2014 Mark Liversedge (liversedge@gmail.com) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -58,7 +59,7 @@ static const int stackZoomWidth[8] = { 5, 10, 15, 20, 30, 45, 60, 120 }; AllPlotWindow::AllPlotWindow(Context *context) : - GcChartWindow(context), current(NULL), context(context), active(false), stale(true), setupStack(false), setupSeriesStack(false) + GcChartWindow(context), current(NULL), context(context), active(false), stale(true), setupStack(false), setupSeriesStack(false), init(false) { QWidget *c = new QWidget; QVBoxLayout *clv = new QVBoxLayout(c); @@ -237,6 +238,10 @@ AllPlotWindow::AllPlotWindow(Context *context) : //allPlot->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); //allPlot->axisWidget(QwtPlot::yLeft)->installEventFilter(this); + allStack = new QStackedWidget(this); + allStack->addWidget(allPlot); + allStack->setCurrentIndex(0); + // sort out default values smoothSlider->setValue(allPlot->smooth); smoothLineEdit->setText(QString("%1").arg(allPlot->smooth)); @@ -292,13 +297,13 @@ AllPlotWindow::AllPlotWindow(Context *context) : allMarker1->setLineStyle(QwtPlotMarker::VLine); allMarker1->attach(allPlot); allMarker1->setLabelAlignment(Qt::AlignTop|Qt::AlignRight); - allPlot->allMarker1=allMarker1; + allPlot->standard->allMarker1=allMarker1; QwtPlotMarker* allMarker2 = new QwtPlotMarker(); allMarker2->setLineStyle(QwtPlotMarker::VLine); allMarker2->attach(allPlot); allMarker2->setLabelAlignment(Qt::AlignTop|Qt::AlignRight); - allPlot->allMarker2=allMarker2; + allPlot->standard->allMarker2=allMarker2; // // stack view @@ -340,6 +345,28 @@ AllPlotWindow::AllPlotWindow(Context *context) : seriesstackFrame->setContentsMargins(0,0,0,0); seriesstackFrame->setPalette(palette); + // + // Compare - AllPlots stack + // + comparePlotLayout = new QVBoxLayout(); + comparePlotLayout->setSpacing(0); + comparePlotLayout->setContentsMargins(0,0,0,0); + comparePlotWidget = new QWidget(); + comparePlotWidget->setAutoFillBackground(false); + comparePlotWidget->setLayout(comparePlotLayout); + comparePlotWidget->setPalette(palette); + + comparePlotFrame = new QScrollArea(); + comparePlotFrame->hide(); + comparePlotFrame->setAutoFillBackground(false); + comparePlotFrame->setWidgetResizable(true); + comparePlotFrame->setWidget(comparePlotWidget); + comparePlotFrame->setFrameStyle(QFrame::NoFrame); + comparePlotFrame->setContentsMargins(0,0,0,0); + comparePlotFrame->setPalette(palette); + + allStack->addWidget(comparePlotFrame); + // // allPlot view // @@ -389,25 +416,18 @@ AllPlotWindow::AllPlotWindow(Context *context) : #endif fullPlot = new AllPlot(this, context); - fullPlot->grid->enableY(false); + fullPlot->standard->grid->enableY(false); fullPlot->setFixedHeight(100); fullPlot->setCanvasBackground(GColor(CRIDEPLOTBACKGROUND)); + fullPlot->setHighlightIntervals(false); static_cast(fullPlot->canvas())->setBorderRadius(0); - fullPlot->enableAxis(QwtPlot::yLeft, false); - fullPlot->enableAxis(QwtAxisId(QwtAxis::yLeft,2).id, false); - fullPlot->enableAxis(QwtPlot::yRight, false); - fullPlot->enableAxis(QwtAxisId(QwtAxis::yRight,2).id, false); - fullPlot->enableAxis(QwtAxisId(QwtAxis::yRight,3).id, false); - fullPlot->enableAxis(QwtPlot::xBottom, false); - fullPlot->setAxisVisible(QwtPlot::xBottom, false); - //fullPlot->legend()->clear(); - //fullPlot->setTitle(""); + fullPlot->setWantAxis(false); fullPlot->setContentsMargins(0,0,0,0); // allPlotStack contains the allPlot and the stack by series // because both want the optional fullplot at the botton allPlotStack = new QStackedWidget(this); - allPlotStack->addWidget(allPlot); + allPlotStack->addWidget(allStack); allPlotStack->addWidget(seriesstackFrame); allPlotStack->setCurrentIndex(0); @@ -498,6 +518,10 @@ AllPlotWindow::AllPlotWindow(Context *context) : connect(context, SIGNAL(intervalSelected()), this, SLOT(intervalSelected())); connect(context, SIGNAL(rideDeleted(RideItem*)), this, SLOT(rideDeleted(RideItem*))); + // comparing things + connect(context, SIGNAL(compareIntervalsStateChanged(bool)), this, SLOT(compareChanged())); + connect(context, SIGNAL(compareIntervalsChanged()), this, SLOT(compareChanged())); + // set initial colors configChanged(); } @@ -526,10 +550,274 @@ AllPlotWindow::configChanged() stackFrame->widget()->setPalette(palette); fullPlot->setCanvasBackground(GColor(CRIDEPLOTBACKGROUND)); - // ok replot with the new config! - redrawFullPlot(); - redrawAllPlot(); - redrawStackPlot(); + // reset the charts etc + if (isCompare()) { + + compareChanged(); + + } else { + // ok replot with the new config! + redrawFullPlot(); + redrawAllPlot(); + redrawStackPlot(); + } +} + +void +AllPlotWindow::compareChanged() +{ +//XXXXX + + if (!amVisible()) { + stale = true; + return; + } + + // we get busy so lets turn off updates till we're done + setUpdatesEnabled(false); + + // clean up old + foreach(AllPlotObject *p, compareIntervalCurves) delete p; + compareIntervalCurves.clear(); + + // new ones .. + if (context->isCompareIntervals) { + + // + // SETUP FULLPLOT FOR COMPARE MODE + // + int maxKM=0, maxSECS=0; + + fullPlot->standard->setVisible(false); + foreach(CompareInterval ci, context->compareIntervals) { + + AllPlotObject *po = new AllPlotObject(fullPlot); + if (ci.isChecked()) fullPlot->setDataFromRideFile(ci.data, po); + + // what was the maximum x value? + if (po->maxKM > maxKM) maxKM = po->maxKM; + if (po->maxSECS > maxSECS) maxSECS = po->maxSECS; + + // prettify / hide unneccessary guff + po->setColor(ci.color); + po->hideUnwanted(); + + // remember + compareIntervalCurves << po; + } + + // what is the longest compareInterval? + if (fullPlot->bydist) fullPlot->setAxisScale(QwtPlot::xBottom, 0, maxKM); + else fullPlot->setAxisScale(QwtPlot::xBottom, 0, maxSECS/60); + + // now set it it in all the compare objects so they all get set + // to the same time / duration + foreach (AllPlotObject *po, compareIntervalCurves) { + po->maxKM = maxKM; + po->maxSECS = maxSECS; + } + + if (fullPlot->bydist == false) { + spanSlider->setMinimum(0); + spanSlider->setMaximum(maxSECS); + } else { + spanSlider->setMinimum(0); + spanSlider->setMaximum(maxKM * 1000); + } + spanSlider->setLowerValue(spanSlider->minimum()); + spanSlider->setUpperValue(spanSlider->maximum()); + + // redraw for red/no-red title + fullPlot->replot(); + + // + // SETUP ALLPLOT AS A STACK FOR EACH INTERVAL + // + allStack->setCurrentIndex(1); + + // first lets wipe the old ones + foreach (AllPlot *ap, allComparePlots) delete ap; + allComparePlots.clear(); + if (comparePlotLayout->count() == 1) { + comparePlotLayout->takeAt(0); // remove the stretch + } + + // now lets throw up one for each interval that + // is checked + int i=0; + foreach(CompareInterval ci, context->compareIntervals) { + + // create a new one using the interval data object and + // referencing fullPlot for the user prefs etc + AllPlot *ap = new AllPlot(this, context); + ap->bydist = fullPlot->bydist; + ap->setDataFromObject(compareIntervalCurves[i], allPlot); + + // simpler to keep the indexes aligned + if (!ci.isChecked()) ap->hide(); + + // tooltip on hover over point -- consider moving this to AllPlot (!) + ap->tooltip = new LTMToolTip(QwtPlot::xBottom, QwtPlot::yLeft, + QwtPicker::VLineRubberBand, + QwtPicker::AlwaysOn, + ap->canvas(), + ""); + ap->tooltip->setRubberBand(QwtPicker::VLineRubberBand); + ap->tooltip->setMousePattern(QwtEventPattern::MouseSelect1, Qt::LeftButton); + ap->tooltip->setTrackerPen(QColor(Qt::black)); + QColor inv(Qt::white); + inv.setAlpha(0); + ap->tooltip->setRubberBandPen(inv); + ap->tooltip->setEnabled(true); + + ap->_canvasPicker = new LTMCanvasPicker(ap); + connect(ap->_canvasPicker, SIGNAL(pointHover(QwtPlotCurve*, int)), ap, SLOT(pointHover(QwtPlotCurve*, int))); + + // format it for our purposes + if (fullPlot->bydist) ap->setAxisScale(QwtPlot::xBottom, 0, maxKM); + else ap->setAxisScale(QwtPlot::xBottom, 0, maxSECS/60.00f); + ap->setFixedHeight(100 + (stackWidth *3)); + + // add to layout + comparePlotLayout->addWidget(ap); + allComparePlots << ap; + + i++; + } + comparePlotLayout->addStretch(); + + // + // SETUP STACK SERIES + // + + // Wipe away whatever is there + foreach(AllPlot *plot, seriesPlots) delete plot; + seriesPlots.clear(); + // and the stretch + while (seriesstackPlotLayout->count()) { + delete seriesstackPlotLayout->takeAt(0); + } + + // work out what we want to see + QList wanted; + if (showPower->currentIndex()) wanted << RideFile::watts; + if (showHr->isChecked()) wanted << RideFile::hr; + if (showSpeed->isChecked()) wanted << RideFile::kph; + if (showCad->isChecked()) wanted << RideFile::cad; + if (showAlt->isChecked()) wanted << RideFile::alt; + if (showTemp->isChecked()) wanted << RideFile::temp; + if (showWind->isChecked()) wanted << RideFile::headwind; + if (showTorque->isChecked()) wanted << RideFile::nm; + if (showNP->isChecked()) wanted << RideFile::NP; + if (showXP->isChecked()) wanted << RideFile::xPower; + if (showAP->isChecked()) wanted << RideFile::aPower; + if (showW->isChecked()) wanted << RideFile::wprime; + if (showBalance->isChecked()) wanted << RideFile::lrbalance; + + // create blank and add to gui + QPalette palette; + palette.setBrush(QPalette::Background, Qt::NoBrush); + + foreach(RideFile::SeriesType x, wanted) { + + // create and setup with normal gui stuff + AllPlot *plot = new AllPlot(this, context, x, RideFile::none, false); + plot->setPalette(palette); + plot->setAutoFillBackground(false); + plot->setFixedHeight(120+(stackWidth*3)); + + // tooltip on hover over point -- consider moving this to AllPlot (!) + plot->tooltip = new LTMToolTip(QwtPlot::xBottom, QwtPlot::yLeft, + QwtPicker::VLineRubberBand, + QwtPicker::AlwaysOn, + plot->canvas(), + ""); + plot->tooltip->setRubberBand(QwtPicker::VLineRubberBand); + plot->tooltip->setMousePattern(QwtEventPattern::MouseSelect1, Qt::LeftButton); + plot->tooltip->setTrackerPen(QColor(Qt::black)); + QColor inv(Qt::white); + inv.setAlpha(0); + plot->tooltip->setRubberBandPen(inv); + plot->tooltip->setEnabled(true); + + plot->_canvasPicker = new LTMCanvasPicker(plot); + connect(plot->_canvasPicker, SIGNAL(pointHover(QwtPlotCurve*, int)), plot, SLOT(pointHover(QwtPlotCurve*, int))); + // No x axis titles + plot->bydist = fullPlot->bydist; + plot->setAxisVisible(QwtPlot::xBottom, true); + plot->enableAxis(QwtPlot::xBottom, true); + plot->setAxisTitle(QwtPlot::xBottom,NULL); + + // common y axis + QwtScaleDraw *sd = new QwtScaleDraw; + sd->setTickLength(QwtScaleDiv::MajorTick, 3); + sd->enableComponent(QwtScaleDraw::Ticks, false); + sd->enableComponent(QwtScaleDraw::Backbone, false); + plot->setAxisScaleDraw(QwtPlot::yLeft, sd); + + // y-axis title and colour + plot->setAxisTitle(QwtPlot::yLeft, RideFile::seriesName(x)); + QPalette pal; + pal.setColor(QPalette::WindowText, RideFile::colorFor(x)); + pal.setColor(QPalette::Text, RideFile::colorFor(x)); + plot->axisWidget(QwtPlot::yLeft)->setPalette(pal); + + // remember them + seriesstackPlotLayout->addWidget(plot); + seriesPlots << plot; + } + seriesstackPlotLayout->addStretch(); + + + // now lets get each of them loaded up with data and in the right format! + foreach(AllPlot *compare, seriesPlots) { + + // update the one already there + compare->standard->setVisible(false); + compare->setDataFromPlots(allComparePlots); + + // format it for our purposes + compare->bydist = fullPlot->bydist; + if (fullPlot->bydist) compare->setAxisScale(QwtPlot::xBottom, 0, maxKM); + else compare->setAxisScale(QwtPlot::xBottom, 0, maxSECS/60.00f); + compare->setXTitle(); + + compare->replot(); + } + + // now remove any series plots that are empty + for(int i=0; icompares.count() == 0) { + delete seriesPlots[i]; + seriesPlots.removeAt(i); + } else { + i++; + } + } + + // ok, we're done + + } else { + + // reset to normal view? + fullPlot->standard->setVisible(true); + + // back to allplot + allStack->setCurrentIndex(0); + + // reset by just calling ride selected + // and setting stale to true.. simpler this way + stale = true; + rideSelected(); + } + + // set the widgets straight + setAllPlotWidgets(NULL); + + // Now we're done lets paint + setUpdatesEnabled(true); + repaint(); + } void @@ -575,24 +863,17 @@ AllPlotWindow::redrawFullPlot() //We now use the window background color //fullPlot->setCanvasBackground(GColor(CPLOTTHUMBNAIL)); static_cast(fullPlot->canvas())->setBorderRadius(0); - fullPlot->grid->enableY(false); - fullPlot->enableAxis(QwtPlot::yLeft, false); - fullPlot->enableAxis(QwtAxisId(QwtAxis::yLeft,2).id, false); - fullPlot->enableAxis(QwtPlot::yRight, false); - fullPlot->enableAxis(QwtAxisId(QwtAxis::yRight,2).id, false); - fullPlot->enableAxis(QwtAxisId(QwtAxis::yRight,3).id, false); - fullPlot->enableAxis(QwtPlot::xBottom, false); - fullPlot->setAxisVisible(QwtPlot::xBottom, false); - //fullPlot->legend()->clear(); - //fullPlot->setTitle(""); + fullPlot->standard->grid->enableY(false); + // use the ride to decide if (fullPlot->bydist) fullPlot->setAxisScale(QwtPlot::xBottom, ride->ride()->dataPoints().first()->km * (context->athlete->useMetricUnits ? 1 : MILES_PER_KM), ride->ride()->dataPoints().last()->km * (context->athlete->useMetricUnits ? 1 : MILES_PER_KM)); else fullPlot->setAxisScale(QwtPlot::xBottom, ride->ride()->dataPoints().first()->secs/60, - ride->ride()->dataPoints().last()->secs/60); + ride->ride()->dataPoints().last()->secs/60); + fullPlot->replot(); } @@ -635,8 +916,30 @@ AllPlotWindow::redrawStackPlot() void AllPlotWindow::zoomChanged() { - redrawAllPlot(); - redrawStackPlot(); // series stacks! + if (isCompare()) { + + // zoom in all the compare plots + foreach (AllPlot *plot, allComparePlots) { + if (fullPlot->bydist) plot->setAxisScale(QwtPlot::xBottom, spanSlider->lowerValue()/1000.00f, spanSlider->upperValue()/1000.00f); + else plot->setAxisScale(QwtPlot::xBottom, spanSlider->lowerValue() / 60.00f, spanSlider->upperValue() / 60.00f); + + plot->replot(); + } + + // and the series plots + foreach (AllPlot *plot, seriesPlots) { + if (fullPlot->bydist) plot->setAxisScale(QwtPlot::xBottom, spanSlider->lowerValue()/1000.00f, spanSlider->upperValue()/1000.00f); + else plot->setAxisScale(QwtPlot::xBottom, spanSlider->lowerValue() / 60.00f, spanSlider->upperValue() / 60.00f); + + plot->replot(); + } + + + } else { + + redrawAllPlot(); + redrawStackPlot(); // series stacks! + } } void @@ -670,6 +973,12 @@ AllPlotWindow::moveRight() void AllPlotWindow::rideSelected() { + // compare mode ignores ride selection + if (init == true && context->isCompareIntervals) { + stale = true; + return; + } + RideItem *ride = myRideItem; if (ride == NULL) current = NULL; @@ -736,6 +1045,12 @@ AllPlotWindow::rideSelected() setupSeriesStackPlots(); stale = false; + + // we wanted a full setup to occur since + // we haven't seen an init take place + init = true; + if (context->isCompareIntervals) compareChanged(); + } void @@ -747,8 +1062,10 @@ AllPlotWindow::rideDeleted(RideItem *ride) // notify all the plots, because when zones are redrawn // they will try and reference AllPlot::rideItem - setAllPlotWidgets(NULL); - fullPlot->setDataFromRide(NULL); + if (!isCompare()) { + setAllPlotWidgets(NULL); + fullPlot->setDataFromRide(NULL); + } } } @@ -797,7 +1114,7 @@ AllPlotWindow::intervalsChanged() void AllPlotWindow::intervalSelected() { - if (!amVisible()) { + if (isCompare() || !amVisible()) { stale = true; return; } @@ -927,59 +1244,65 @@ AllPlotWindow::setAllPlotWidgets(RideItem *ride) // ride. It also hides/shows widgets depending // upon wether we are in 'normal' mode or // stacked plot mode - if (!ride) return; + if (!isCompare()) { - // checkboxes to show/hide specific data series... - const RideFileDataPresent *dataPresent = ride->ride()->areDataPresent(); - if (ride->ride() && ride->ride()->deviceType() != QString("Manual CSV")) { + // set for currently selected ride + if (!ride) return; - showPower->setEnabled(dataPresent->watts); - showHr->setEnabled(dataPresent->hr); - showSpeed->setEnabled(dataPresent->kph); - showCad->setEnabled(dataPresent->cad); - showAlt->setEnabled(dataPresent->alt); - showTemp->setEnabled(dataPresent->temp); - showWind->setEnabled(dataPresent->headwind); - showTorque->setEnabled(dataPresent->nm); - showBalance->setEnabled(dataPresent->lrbalance); - } else { - showPower->setEnabled(false); - showHr->setEnabled(false); - showSpeed->setEnabled(false); - showCad->setEnabled(false); - showAlt->setEnabled(false); - showTemp->setEnabled(false); - showWind->setEnabled(false); - showTorque->setEnabled(false); - showBalance->setEnabled(false); - } + // checkboxes to show/hide specific data series... + const RideFileDataPresent *dataPresent = ride->ride()->areDataPresent(); + if (ride->ride() && ride->ride()->deviceType() != QString("Manual CSV")) { - // turn on/off shading, if it's not available - bool shade; - if (dataPresent->watts) shade = (showPower->currentIndex() == 0); - else shade = false; - allPlot->setShadeZones(shade); - foreach (AllPlot *plot, allPlots) plot->setShadeZones(shade); - allPlot->setShowGrid(showGrid->checkState() == Qt::Checked); - foreach (AllPlot *plot, allPlots) plot->setShowGrid(showGrid->checkState() == Qt::Checked); + showPower->setEnabled(dataPresent->watts); + showHr->setEnabled(dataPresent->hr); + showSpeed->setEnabled(dataPresent->kph); + showCad->setEnabled(dataPresent->cad); + showAlt->setEnabled(dataPresent->alt); + showTemp->setEnabled(dataPresent->temp); + showWind->setEnabled(dataPresent->headwind); + showTorque->setEnabled(dataPresent->nm); + showBalance->setEnabled(dataPresent->lrbalance); + } else { + showPower->setEnabled(false); + showHr->setEnabled(false); + showSpeed->setEnabled(false); + showCad->setEnabled(false); + showAlt->setEnabled(false); + showTemp->setEnabled(false); + showWind->setEnabled(false); + showTorque->setEnabled(false); + showBalance->setEnabled(false); + } - // set the SpanSlider for the ride length, by default - // show the entire ride (the user can adjust later) - if (fullPlot->bydist == false) { - spanSlider->setMinimum(ride->ride()->dataPoints().first()->secs); - spanSlider->setMaximum(ride->ride()->dataPoints().last()->secs); - spanSlider->setLowerValue(spanSlider->minimum()); - spanSlider->setUpperValue(spanSlider->maximum()); - } else { - spanSlider->setMinimum(ride->ride()->dataPoints().first()->km * 1000); - spanSlider->setMaximum(ride->ride()->dataPoints().last()->km * 1000); - spanSlider->setLowerValue(spanSlider->minimum()); - spanSlider->setUpperValue(spanSlider->maximum()); + // turn on/off shading, if it's not available + bool shade; + if (dataPresent->watts) shade = (showPower->currentIndex() == 0); + else shade = false; + allPlot->setShadeZones(shade); + foreach (AllPlot *plot, allPlots) plot->setShadeZones(shade); + allPlot->setShowGrid(showGrid->checkState() == Qt::Checked); + foreach (AllPlot *plot, allPlots) plot->setShowGrid(showGrid->checkState() == Qt::Checked); + + // set the SpanSlider for the ride length, by default + // show the entire ride (the user can adjust later) + if (fullPlot->bydist == false) { + spanSlider->setMinimum(ride->ride()->dataPoints().first()->secs); + spanSlider->setMaximum(ride->ride()->dataPoints().last()->secs); + spanSlider->setLowerValue(spanSlider->minimum()); + spanSlider->setUpperValue(spanSlider->maximum()); + } else { + spanSlider->setMinimum(ride->ride()->dataPoints().first()->km * 1000); + spanSlider->setMaximum(ride->ride()->dataPoints().last()->km * 1000); + spanSlider->setLowerValue(spanSlider->minimum()); + spanSlider->setUpperValue(spanSlider->maximum()); + } } // now set the visible plots, depending upon whether // we are in stacked mode or not - if (showStack->isChecked() && !showBySeries->isChecked()) { + if (!isCompare() && showStack->isChecked() && !showBySeries->isChecked()) { + + // ALL PLOT STACK ORIGINAL AS CODED BY DAMIEN // hide normal view allPlotFrame->hide(); @@ -996,15 +1319,37 @@ AllPlotWindow::setAllPlotWidgets(RideItem *ride) } else { + // hide stack plots (segmented by time/distance) stackFrame->hide(); // show normal view allPlotFrame->show(); allPlot->show(); - if (showStack->isChecked() && showBySeries->isChecked()) allPlotStack->setCurrentIndex(1); - else allPlotStack->setCurrentIndex(0); + if (showStack->isChecked() && (isCompare() || showBySeries->isChecked())) { + // STACK SERIES LANES SHOWING + allPlotStack->setCurrentIndex(1); + + } else { + + // ALLPLOT + allPlotStack->setCurrentIndex(0); + + if (isCompare()) { + + // COMPARE ALL PLOTS + allStack->setCurrentIndex(1); // compare mode stack of all plots + + } else { + + // NORMAL SINGLE ALL PLOT + allStack->setCurrentIndex(0); // normal single allplot + } + + } + + // FIXUP FULL PLOT! if (showFull->isChecked()) { fullPlot->show(); controlsLayout->setRowStretch(0, 100); @@ -1026,6 +1371,9 @@ AllPlotWindow::setAllPlotWidgets(RideItem *ride) void AllPlotWindow::zoomOut() { + // we don't do that in compare mode + if (isCompare()) return; + // set them to maximums to avoid overlapping // when we set them below, daft but works spanSlider->setLowerValue(spanSlider->minimum()); @@ -1036,6 +1384,9 @@ AllPlotWindow::zoomOut() void AllPlotWindow::zoomInterval(IntervalItem *which) { + // we don't do that in compare mode + if (isCompare()) return; + // use the span slider to highlight // when we are in normal mode. @@ -1057,6 +1408,9 @@ AllPlotWindow::zoomInterval(IntervalItem *which) void AllPlotWindow::plotPickerSelected(const QPoint &pos) { + // we don't do selection in compare mode + if (isCompare()) return; + QwtPlotPicker* pick = qobject_cast(sender()); AllPlot* plot = qobject_cast(pick->plot()); double xValue = plot->invTransform(QwtPlot::xBottom, pos.x()); @@ -1067,6 +1421,9 @@ AllPlotWindow::plotPickerSelected(const QPoint &pos) void AllPlotWindow::plotPickerMoved(const QPoint &pos) { + // we don't do selection in compare mode + if (isCompare()) return; + QString name = QString("Selection #%1 ").arg(selection); // which picker and plot send this signal? @@ -1082,18 +1439,18 @@ AllPlotWindow::plotPickerMoved(const QPoint &pos) foreach (AllPlot *_plot, (showBySeries->isChecked() ? seriesPlots : allPlots)) { // mark the start of selection on every plot - _plot->allMarker1->setValue(plot->allMarker1->value()); + _plot->standard->allMarker1->setValue(plot->standard->allMarker1->value()); if (_plot->y()<=plot->y() && posY<_plot->y()){ - if (_plot->transform(QwtPlot::xBottom, _plot->allMarker2->xValue())>0) { + if (_plot->transform(QwtPlot::xBottom, _plot->standard->allMarker2->xValue())>0) { setEndSelection(_plot, 0, false, name); - _plot->allMarker2->setLabel(QString("")); + _plot->standard->allMarker2->setLabel(QString("")); } } else if (_plot->y()>=plot->y() && posY>_plot->y()+_plot->height()) { - if (_plot->transform(QwtPlot::xBottom, _plot->allMarker2->xValue())width()){ + if (_plot->transform(QwtPlot::xBottom, _plot->standard->allMarker2->xValue())width()){ setEndSelection(_plot, _plot->transform(QwtPlot::xBottom, plot->width()), false, name); } } @@ -1102,25 +1459,25 @@ AllPlotWindow::plotPickerMoved(const QPoint &pos) if (pos.x()<6) { posX = 6; } else if (!_plot->bydist && pos.x()>_plot->transform(QwtPlot::xBottom, - fullPlot->timeArray[fullPlot->timeArray.size()-1])) { - posX = _plot->transform(QwtPlot::xBottom, fullPlot->timeArray[fullPlot->timeArray.size()-1]); + fullPlot->standard->timeArray[fullPlot->standard->timeArray.size()-1])) { + posX = _plot->transform(QwtPlot::xBottom, fullPlot->standard->timeArray[fullPlot->standard->timeArray.size()-1]); } else if (plot->bydist && pos.x()>_plot->transform(QwtPlot::xBottom, - fullPlot->distanceArray[fullPlot->distanceArray.size()-1])) { + fullPlot->standard->distanceArray[fullPlot->standard->distanceArray.size()-1])) { posX = fullPlot->transform(QwtPlot::xBottom, - fullPlot->distanceArray[fullPlot->distanceArray.size()-1]); + fullPlot->standard->distanceArray[fullPlot->standard->distanceArray.size()-1]); } setEndSelection(_plot, _plot->invTransform(QwtPlot::xBottom, posX), true, name); if (plot->y()<_plot->y()) { - plot->allMarker1->setLabel(_plot->allMarker1->label()); - plot->allMarker2->setLabel(_plot->allMarker2->label()); + plot->standard->allMarker1->setLabel(_plot->standard->allMarker1->label()); + plot->standard->allMarker2->setLabel(_plot->standard->allMarker2->label()); } } else { - _plot->allMarker1->hide(); - _plot->allMarker2->hide(); + _plot->standard->allMarker1->hide(); + _plot->standard->allMarker2->hide(); } } @@ -1136,7 +1493,10 @@ AllPlotWindow::plotPickerMoved(const QPoint &pos) void AllPlotWindow::setStartSelection(AllPlot* plot, double xValue) { - QwtPlotMarker* allMarker1 = plot->allMarker1; + // we don't do selection in compare mode + if (isCompare()) return; + + QwtPlotMarker* allMarker1 = plot->standard->allMarker1; selection++; @@ -1149,10 +1509,13 @@ AllPlotWindow::setStartSelection(AllPlot* plot, double xValue) void AllPlotWindow::setEndSelection(AllPlot* plot, double xValue, bool newInterval, QString name) { + // we don't do selection in compare mode + if (isCompare()) return; + active = true; - QwtPlotMarker* allMarker1 = plot->allMarker1; - QwtPlotMarker* allMarker2 = plot->allMarker2; + QwtPlotMarker* allMarker1 = plot->standard->allMarker1; + QwtPlotMarker* allMarker2 = plot->standard->allMarker2; if (!allMarker2->isVisible() || allMarker2->xValue() != xValue) { allMarker2->setValue(xValue, plot->bydist ? 0 : 100); @@ -1278,29 +1641,35 @@ AllPlotWindow::setEndSelection(AllPlot* plot, double xValue, bool newInterval, Q void AllPlotWindow::clearSelection() { + // we don't do selection in compare mode + if (isCompare()) return; + selection = 0; - allPlot->allMarker1->setVisible(false); - allPlot->allMarker2->setVisible(false); + allPlot->standard->allMarker1->setVisible(false); + allPlot->standard->allMarker2->setVisible(false); foreach (AllPlot *plot, allPlots) { - plot->allMarker1->setVisible(false); - plot->allMarker2->setVisible(false); + plot->standard->allMarker1->setVisible(false); + plot->standard->allMarker2->setVisible(false); } } void AllPlotWindow::hideSelection() { + // we don't do selection in compare mode + if (isCompare()) return; + if (showStack->isChecked()) { foreach (AllPlot *plot, allPlots) { - plot->allMarker1->setVisible(false); - plot->allMarker2->setVisible(false); + plot->standard->allMarker1->setVisible(false); + plot->standard->allMarker2->setVisible(false); plot->replot(); } } else { fullPlot->replot(); - allPlot->allMarker1->setVisible(false); - allPlot->allMarker2->setVisible(false); + allPlot->standard->allMarker1->setVisible(false); + allPlot->standard->allMarker2->setVisible(false); allPlot->replot(); } } @@ -1310,7 +1679,11 @@ AllPlotWindow::setShowPower(int value) { showPower->setCurrentIndex(value); - //if (!current) return; + // compare mode selfcontained update + if (isCompare()) { + compareChanged(); + return; + } // we only show the power shading on the // allPlot / stack plots, not on the fullPlot @@ -1339,7 +1712,12 @@ AllPlotWindow::setShowHr(int value) { showHr->setChecked(value); - //if (!current) return; + // compare mode selfcontained update + if (isCompare()) { + compareChanged(); + return; + } + bool checked = ( ( value == Qt::Checked ) && showHr->isEnabled()) ? true : false; allPlot->setShowHr(checked); @@ -1354,7 +1732,12 @@ AllPlotWindow::setShowNP(int value) { showNP->setChecked(value); - //if (!current) return; + // compare mode selfcontained update + if (isCompare()) { + compareChanged(); + return; + } + bool checked = ( ( value == Qt::Checked ) && showNP->isEnabled()) ? true : false; // recalc only does it if it needs to @@ -1372,7 +1755,12 @@ AllPlotWindow::setShowXP(int value) { showXP->setChecked(value); - //if (!current) return; + // compare mode selfcontained update + if (isCompare()) { + compareChanged(); + return; + } + bool checked = ( ( value == Qt::Checked ) && showXP->isEnabled()) ? true : false; // recalc only does it if it needs to @@ -1390,7 +1778,12 @@ AllPlotWindow::setShowAP(int value) { showAP->setChecked(value); - //if (!current) return; + // compare mode selfcontained update + if (isCompare()) { + compareChanged(); + return; + } + bool checked = ( ( value == Qt::Checked ) && showAP->isEnabled()) ? true : false; // recalc only does it if it needs to @@ -1408,7 +1801,12 @@ AllPlotWindow::setShowSpeed(int value) { showSpeed->setChecked(value); - //if (!current) return; + // compare mode selfcontained update + if (isCompare()) { + compareChanged(); + return; + } + bool checked = ( ( value == Qt::Checked ) && showSpeed->isEnabled()) ? true : false; allPlot->setShowSpeed(checked); @@ -1423,7 +1821,12 @@ AllPlotWindow::setShowCad(int value) { showCad->setChecked(value); - //if (!current) return; + // compare mode selfcontained update + if (isCompare()) { + compareChanged(); + return; + } + bool checked = ( ( value == Qt::Checked ) && showCad->isEnabled()) ? true : false; allPlot->setShowCad(checked); @@ -1438,7 +1841,12 @@ AllPlotWindow::setShowAlt(int value) { showAlt->setChecked(value); - //if (!current) return; + // compare mode selfcontained update + if (isCompare()) { + compareChanged(); + return; + } + bool checked = ( ( value == Qt::Checked ) && showAlt->isEnabled()) ? true : false; allPlot->setShowAlt(checked); @@ -1453,7 +1861,12 @@ AllPlotWindow::setShowTemp(int value) { showTemp->setChecked(value); - //if (!current) return; + // compare mode selfcontained update + if (isCompare()) { + compareChanged(); + return; + } + bool checked = ( ( value == Qt::Checked ) && showTemp->isEnabled()) ? true : false; allPlot->setShowTemp(checked); @@ -1468,7 +1881,12 @@ AllPlotWindow::setShowWind(int value) { showWind->setChecked(value); - //if (!current) return; + // compare mode selfcontained update + if (isCompare()) { + compareChanged(); + return; + } + bool checked = (( value == Qt::Checked ) && showWind->isEnabled()) ? true : false; allPlot->setShowWind(checked); @@ -1484,7 +1902,12 @@ AllPlotWindow::setShowW(int value) { showW->setChecked(value); - //if (!current) return; + // compare mode selfcontained update + if (isCompare()) { + compareChanged(); + return; + } + bool checked = ( ( value == Qt::Checked ) && showW->isEnabled()) ? true : false; allPlot->setShowW(checked); @@ -1511,7 +1934,11 @@ AllPlotWindow::setShowTorque(int value) showTorque->setChecked(value); bool checked = ( ( value == Qt::Checked ) && showTorque->isEnabled()) ? true : false; - //if (!current) return; + // compare mode selfcontained update + if (isCompare()) { + compareChanged(); + return; + } allPlot->setShowTorque(checked); foreach (AllPlot *plot, allPlots) @@ -1525,6 +1952,12 @@ AllPlotWindow::setShowBalance(int value) { showBalance->setChecked(value); + // compare mode selfcontained update + if (isCompare()) { + compareChanged(); + return; + } + bool checked = ( ( value == Qt::Checked ) && showBalance->isEnabled()) ? true : false; allPlot->setShowBalance(checked); @@ -1560,13 +1993,19 @@ AllPlotWindow::setShowGrid(int value) { showGrid->setChecked(value); - //if (!current) return; + if (isCompare()) { - allPlot->setShowGrid(value); - foreach (AllPlot *plot, allPlots) - plot->setShowGrid(value); - // and the series stacks too - forceSetupSeriesStackPlots(); // scope changed so force redraw + // XXX + return; + + } else { + + allPlot->setShowGrid(value); + foreach (AllPlot *plot, allPlots) + plot->setShowGrid(value); + // and the series stacks too + forceSetupSeriesStackPlots(); // scope changed so force redraw + } } void @@ -1574,6 +2013,11 @@ AllPlotWindow::setPaintBrush(int value) { if (active == true) return; + if (isCompare()) { + // XXX + return; + } + active = true; paintBrush->setChecked(value); @@ -1596,6 +2040,14 @@ AllPlotWindow::setByDistance(int value) active = true; comboDistance->setCurrentIndex(value); + // compare mode is self contained + if (isCompare()) { + fullPlot->bydist = value; + compareChanged(); + active = false; + return; + } + fullPlot->setByDistance(value); allPlot->setByDistance(value); @@ -1620,10 +2072,37 @@ AllPlotWindow::setSmoothing(int value) // recalculate etc fullPlot->setSmoothing(value); - // redraw - redrawFullPlot(); - redrawAllPlot(); - redrawStackPlot(); + // Compare has LOTS of rides to smooth... + if (context->isCompareIntervals) { + + setUpdatesEnabled(false); + + // smooth each on full plots ... + foreach(AllPlotObject *po, compareIntervalCurves) { + fullPlot->recalc(po); + } + + // .. and all plots too! + int i=0; + foreach (AllPlot *plot, allComparePlots) { + plot->setDataFromObject(compareIntervalCurves[i], allPlot); + i++; + } + // and series plots.. + foreach (AllPlot *plot, seriesPlots) { + plot->setDataFromPlots(allComparePlots); + plot->replot(); // straight away this time + } + + setUpdatesEnabled(true); + + } else { + + // redraw + redrawFullPlot(); + redrawAllPlot(); + redrawStackPlot(); + } } void @@ -1699,6 +2178,8 @@ AllPlotWindow::setStackWidth(int width) resizeSeriesPlots(); // its only the size that needs to change // no need to replot + resizeComparePlots(); + // now lets do the plots... setupStack = false; // force resize setupStackPlots(); @@ -1707,16 +2188,27 @@ AllPlotWindow::setStackWidth(int width) void AllPlotWindow::showStackChanged(int value) { - if (!current) return; showStack->setCheckState((Qt::CheckState)value); rStack->setCheckState((Qt::CheckState)value); + if (isCompare()) { + setAllPlotWidgets(NULL); // no need to do anything fancy + return; + } + + if (!current) return; + // enables / disable as needed if (showStack->isChecked()) { showBySeries->setEnabled(true); rBySeries->setEnabled(true); + + // all plot... allPlotStack->setCurrentIndex(0); + if (isCompare()) allStack->setCurrentIndex(1); // compare mode stack of all plots + else allStack->setCurrentIndex(0); // normal single allplot + } else { showBySeries->setEnabled(false); rBySeries->setEnabled(false); @@ -1777,8 +2269,6 @@ AllPlotWindow::showBySeriesChanged(int value) showBySeries->setCheckState((Qt::CheckState)value); rBySeries->setCheckState((Qt::CheckState)value); - - // XXX ??? showStackChanged(showStack->checkState()); // force replot etc } @@ -1798,10 +2288,19 @@ AllPlotWindow::resizeSeriesPlots() seriesstackFrame->setUpdatesEnabled(true); } +void +AllPlotWindow::resizeComparePlots() +{ + comparePlotFrame->setUpdatesEnabled(false); + foreach (AllPlot *plot, allComparePlots) + plot->setFixedHeight(100 + (stackWidth *3)); + comparePlotFrame->setUpdatesEnabled(true); +} + void AllPlotWindow::setupSeriesStackPlots() { - if (!showStack->isChecked() || !showBySeries->isChecked() || setupSeriesStack) return; + if (!isCompare() && (!showStack->isChecked() || !showBySeries->isChecked() || setupSeriesStack)) return; QVBoxLayout *newLayout = new QVBoxLayout; @@ -1879,6 +2378,9 @@ AllPlotWindow::setupSeriesStackPlots() stackWidget->setLayout(newLayout); seriesstackFrame->setWidget(stackWidget); + // lets remember the layout + seriesstackPlotLayout = newLayout; + // ZZZZ zap old widgets - is NOT required // since setWidget above will destroy // the ScrollArea's children @@ -2039,13 +2541,13 @@ AllPlotWindow::addPickers(AllPlot *_allPlot) allMarker1->setLineStyle(QwtPlotMarker::VLine); allMarker1->attach(_allPlot); allMarker1->setLabelAlignment(Qt::AlignTop|Qt::AlignRight); - _allPlot->allMarker1 = allMarker1; + _allPlot->standard->allMarker1 = allMarker1; QwtPlotMarker* allMarker2 = new QwtPlotMarker(); allMarker2->setLineStyle(QwtPlotMarker::VLine); allMarker2->attach(_allPlot); allMarker2->setLabelAlignment(Qt::AlignTop|Qt::AlignRight); - _allPlot->allMarker2 = allMarker2; + _allPlot->standard->allMarker2 = allMarker2; // use the tooltip picker rather than a standard picker _allPlot->tooltip = new LTMToolTip(QwtPlot::xBottom, QwtPlot::yLeft, diff --git a/src/AllPlotWindow.h b/src/AllPlotWindow.h index ef5b04af6..5c444d6c9 100644 --- a/src/AllPlotWindow.h +++ b/src/AllPlotWindow.h @@ -27,6 +27,7 @@ #include class AllPlot; +class AllPlotObject; class Context; class QwtPlotPanner; class QwtPlotZoomer; @@ -78,6 +79,7 @@ class AllPlotWindow : public GcChartWindow AllPlotWindow(Context *context); void setData(RideItem *ride); + bool isCompare() const { return context->isCompareIntervals; } bool hasReveal() { return true; } // highlight a selection on the plots @@ -151,11 +153,15 @@ class AllPlotWindow : public GcChartWindow void zoomInterval(IntervalItem *); void stackZoomSliderChanged(); void resizeSeriesPlots(); + void resizeComparePlots(); void moveLeft(); void moveRight(); void showStackChanged(int state); void showBySeriesChanged(int state); + // compare mode started or items to compare changed + void compareChanged(); + protected: // whilst we refactor, lets make friend @@ -180,6 +186,14 @@ class AllPlotWindow : public GcChartWindow QwtPlotPanner *allPanner; QwtPlotZoomer *allZoomer; + QStackedWidget *allStack; // for normal allplot of stacked al plot in compare mode + + // compare mode all plot (is a stack view, not a single plot) + QScrollArea *comparePlotFrame; + QVBoxLayout *comparePlotLayout; + QWidget *comparePlotWidget; + QList allComparePlots; // allplot as a series of charts + // Stacked view QScrollArea *stackFrame; QVBoxLayout *stackPlotLayout; @@ -231,6 +245,9 @@ class AllPlotWindow : public GcChartWindow QCheckBox *rStack, *rBySeries, *rFull; QStackedWidget *allPlotStack; + // comparing + QList compareIntervalCurves; // one per compareInterval + // reset/redraw all the plots void setupStackPlots(); void forceSetupSeriesStackPlots(); @@ -248,6 +265,7 @@ class AllPlotWindow : public GcChartWindow bool stale; bool setupStack; // we optimise this out, its costly bool setupSeriesStack; // we optimise this out, its costly + bool init; // compare init one off setup private slots: diff --git a/src/ComparePane.cpp b/src/ComparePane.cpp index 5b95786fe..7d02a2b53 100644 --- a/src/ComparePane.cpp +++ b/src/ComparePane.cpp @@ -160,8 +160,8 @@ ComparePane::refreshTable() // metric summary QStringList always; always << "workout_time" << "total_distance"; - QString s = appsettings->value(this, GC_SETTINGS_SUMMARY_METRICS, GC_SETTINGS_SUMMARY_METRICS_DEFAULT).toString(); - if (s == "") s = GC_SETTINGS_SUMMARY_METRICS_DEFAULT; + QString s = appsettings->value(this, GC_SETTINGS_INTERVAL_METRICS, GC_SETTINGS_INTERVAL_METRICS_DEFAULT).toString(); + if (s == "") s = GC_SETTINGS_INTERVAL_METRICS_DEFAULT; QStringList metricColumns = always + s.split(","); // always showm metrics plus user defined summary metrics // called after config is updated typically @@ -210,7 +210,7 @@ ComparePane::refreshTable() QHash computed = RideMetric::computeMetrics(context, x.data, context->athlete->zones(), context->athlete->hrZones(), worklist); - for(int i = 0; i < worklist.count(); ++i) { + for(int i = 0; i < worklist.count(); i++) { if (worklist[i] != "") { RideMetricPtr m = computed.value(worklist[i]); if (m) metrics.setForSymbol(worklist[i], m->value(true)); @@ -253,21 +253,26 @@ ComparePane::refreshTable() table->setItem(counter, 4, t); // metrics - for(int i = 0; i < worklist.count(); ++i) { + for(int i = 0; i < worklist.count(); i++) { RideMetricPtr m = computed.value(worklist[i]); - // get value and convert if needed - double value = metrics.getForSymbol(worklist[i]) - * (context->athlete->useMetricUnits ? 1 : m->conversion()) - + (context->athlete->useMetricUnits ? 0 : m->conversionSum()); + QString strValue; - // use right precision - QString strValue = QString("%1").arg(value, 0, 'f', m->precision()); + if (m) { + // get value and convert if needed + double value = metrics.getForSymbol(worklist[i]) + * (context->athlete->useMetricUnits ? 1 : m->conversion()) + + (context->athlete->useMetricUnits ? 0 : m->conversionSum()); - // or maybe its a duration (worry about local lang or translated) - if (m->units(true) == "seconds" || m->units(true) == tr("seconds")) - strValue = time_to_string(value); + // use right precision + strValue = QString("%1").arg(value, 0, 'f', m->precision()); + + // or maybe its a duration (worry about local lang or translated) + if (m->units(true) == "seconds" || m->units(true) == tr("seconds")) + strValue = time_to_string(value); + + } // add to the table t = new CTableWidgetItem; @@ -401,7 +406,7 @@ ComparePane::refreshTable() table->setItem(counter, 4, t); // metrics - for(int i = 0; i < worklist.count(); ++i) { + for(int i = 0; i < worklist.count(); i++) { QString value = SummaryMetrics::getAggregated(x.sourceContext, worklist[i], x.metrics, QStringList(), false, context->athlete->useMetricUnits); diff --git a/src/Context.cpp b/src/Context.cpp index 6ab4965b8..6e33df1a0 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -33,3 +33,33 @@ Context::currentRide() { return athlete->currentRide(); } + +void +Context::notifyCompareIntervals(bool state) +{ + isCompareIntervals = state; + emit compareIntervalsStateChanged(state); +} + +void +Context::notifyCompareIntervalsChanged() +{ + if (isCompareIntervals) { + emit compareIntervalsChanged(); + } +} + +void +Context::notifyCompareDateRanges(bool state) +{ + isCompareDateRanges = state; + emit compareDateRangesStateChanged(state); +} + +void +Context::notifyCompareDateRangesChanged() +{ + if (isCompareDateRanges) { + emit compareDateRangesChanged(); + } +} diff --git a/src/Context.h b/src/Context.h index 9f9f8bb17..113e2f8e5 100644 --- a/src/Context.h +++ b/src/Context.h @@ -118,11 +118,11 @@ class Context : public QObject void notifyRideClean() { rideClean(ride); } void notifyRideDirty() { rideDirty(ride); } - void notifyCompareIntervals(bool state) { isCompareIntervals = state; emit compareIntervalsStateChanged(state); } - void notifyCompareIntervalsChanged() { emit compareIntervalsChanged(); } + void notifyCompareIntervals(bool state); + void notifyCompareIntervalsChanged(); - void notifyCompareDateRanges(bool state) { isCompareDateRanges = state; emit compareDateRangesStateChanged(state); } - void notifyCompareDateRangesChanged() { emit compareDateRangesChanged(); } + void notifyCompareDateRanges(bool state); + void notifyCompareDateRangesChanged(); signals: diff --git a/src/CpintPlot.cpp b/src/CpintPlot.cpp index b29085f55..14e6d86e1 100644 --- a/src/CpintPlot.cpp +++ b/src/CpintPlot.cpp @@ -902,7 +902,7 @@ CpintPlot::calculate(RideItem *rideItem) } void -CpintPlot::showGrid(int state) +CpintPlot::showGrid(int ) { //grid->setVisible(state == Qt::Checked); //replot(); @@ -1313,19 +1313,23 @@ CpintPlot::calculateForDateRanges(QList compareDateRanges) model = 0; // no model in compareDateRanges // prepare aggregates - for (int i = 0; i < compareDateRanges.size(); ++i) { - CompareDateRange range = compareDateRanges.at(i); + for (int j = 0; j < compareDateRanges.size(); ++j) { + + CompareDateRange range = compareDateRanges.at(j); + if (range.isChecked()) { RideFileCache bestsForRange(range.sourceContext, range.start, range.end, isFiltered, files, rangemode); bests.append(bestsForRange); if (bestsForRange.meanMaxArray(series).size()) { + int maxNonZero = 0; - for (int i = 0; i < bestsForRange.meanMaxArray(series).size(); ++i) { + int i=0; + for (; i < bestsForRange.meanMaxArray(series).size(); ++i) { if (bestsForRange.meanMaxArray(series)[i] > 0) maxNonZero = i; } - if (i>0) - shadeMode = 0; + if (i>0) shadeMode = 0; + plot_allCurve(this, maxNonZero, bestsForRange.meanMaxArray(series).constData() + 1, range.color, true); foreach(double v, bestsForRange.meanMaxArray(series)) { diff --git a/src/CriticalPowerWindow.cpp b/src/CriticalPowerWindow.cpp index 4c613dd04..59cb11105 100644 --- a/src/CriticalPowerWindow.cpp +++ b/src/CriticalPowerWindow.cpp @@ -1075,6 +1075,19 @@ void CriticalPowerWindow::shadeIntervalsChanged(int state) { cpintPlot->setShadeIntervals(state); + + // any existing interval curves need brush or no brush + foreach(QwtPlotCurve *p, intervalCurves) { + if (p) { + if (state) { + QColor curveColor = p->pen().color(); + curveColor.setAlpha(64); + QBrush brush(curveColor); + p->setBrush(brush); + } + else p->setBrush(Qt::NoBrush); + } + } if (rangemode) dateRangeChanged(DateRange()); else cpintPlot->calculate(currentRide); } diff --git a/src/IntervalTreeView.cpp b/src/IntervalTreeView.cpp index b54edb460..0caf5bfdc 100644 --- a/src/IntervalTreeView.cpp +++ b/src/IntervalTreeView.cpp @@ -35,8 +35,6 @@ IntervalTreeView::IntervalTreeView(Context *context) : context(context) void IntervalTreeView::dropEvent(QDropEvent* event) { -qDebug()<<"interval tree drop event!!"<mimeData()->urls(); - IntervalItem* item1 = (IntervalItem *)itemAt(event->pos()); QTreeWidget::dropEvent(event); IntervalItem* item2 = (IntervalItem *)itemAt(event->pos()); diff --git a/src/LTMPlot.cpp b/src/LTMPlot.cpp index bd646ae3e..b25d922f5 100644 --- a/src/LTMPlot.cpp +++ b/src/LTMPlot.cpp @@ -59,7 +59,6 @@ LTMPlot::LTMPlot(LTMWindow *parent, Context *context) : setAxesCount(QwtAxis::xBottom, 1); setAxesCount(QwtAxis::xTop, 0); - int n=0; for (int i=0; i<4; i++) { // lefts @@ -595,10 +594,6 @@ LTMPlot::setData(LTMSettings *set) // perform quadratic curve fit to data LTMTrend2 regress(xdata.data(), ydata.data(), count); - // override class variable as doing it temporarily for trend line only - double maxX = 0.5 + groupForDate(settings->end.date(), settings->groupBy) - - groupForDate(settings->start.date(), settings->groupBy); - QVector xtrend; QVector ytrend; diff --git a/src/LTMSidebar.cpp b/src/LTMSidebar.cpp index bbf882fa8..35f5cc34e 100644 --- a/src/LTMSidebar.cpp +++ b/src/LTMSidebar.cpp @@ -581,7 +581,6 @@ LTMSidebar::filterTreeWidgetSelectionChanged() QStringList errors, files; // results of all the selections bool first = true; - int index=0; foreach (QTreeWidgetItem *item, filterTree->selectedItems()) { diff --git a/src/LTMSidebar.h b/src/LTMSidebar.h index cd44fbd71..3024f0e93 100644 --- a/src/LTMSidebar.h +++ b/src/LTMSidebar.h @@ -122,7 +122,7 @@ class LTMSidebar : public QWidget GcSubSplitter *filterSplitter; // filter state - bool isautofilter, isqueryfilter; + bool isqueryfilter, isautofilter; QStringList autoFilterFiles, queryFilterFiles; }; diff --git a/src/LTMTrend2.h b/src/LTMTrend2.h index 8f19566f9..7c895a6a3 100644 --- a/src/LTMTrend2.h +++ b/src/LTMTrend2.h @@ -21,19 +21,14 @@ class LTMTrend2 { - /* calculated as points added then used to derive a b and c */ - int count; - double sx4, sx3, sx2, sx; // sum x^4, ^3, ^2 and just sum x - double sx2y, sxy, sy; // sum x^2 * y, sum x * y, and just sum y - public: double minx, miny, maxx, maxy; // constructor just initialises variables LTMTrend2(double *xdata, double *ydata, int count) - : sx4(0), sx3(0), sx2(0), sx(0), sx2y(0), sxy(0), sy(0), - minx(10000), miny(10000), maxx(-10000), maxy(-10000), count(count) + : minx(10000), miny(10000), maxx(-10000), maxy(-10000), count(count), + sx4(0), sx3(0), sx2(0), sx(0), sx2y(0), sxy(0), sy(0) { for (int i = 0; i < count; i++) { addPoint(xdata[i], ydata[i]); @@ -126,6 +121,11 @@ class LTMTrend2 } #endif + /* calculated as points added then used to derive a b and c */ + int count; + double sx4, sx3, sx2, sx; // sum x^4, ^3, ^2 and just sum x + double sx2y, sxy, sy; // sum x^2 * y, sum x * y, and just sum y + }; diff --git a/src/RideFile.cpp b/src/RideFile.cpp index 4b322aa1f..fd89470e4 100644 --- a/src/RideFile.cpp +++ b/src/RideFile.cpp @@ -94,10 +94,40 @@ RideFile::seriesName(SeriesType series) case RideFile::interval: return QString(tr("Interval")); case RideFile::vam: return QString(tr("VAM")); case RideFile::wattsKg: return QString(tr("Watts per Kilogram")); + case RideFile::wprime: return QString(tr("W' balance")); default: return QString(tr("Unknown")); } } +QColor +RideFile::colorFor(SeriesType series) +{ + switch (series) { + case RideFile::cad: return GColor(CCADENCE); + case RideFile::hr: return GColor(CHEARTRATE); + case RideFile::kph: return GColor(CSPEED); + case RideFile::nm: return GColor(CTORQUE); + case RideFile::watts: return GColor(CPOWER); + case RideFile::xPower: return GColor(CXPOWER); + case RideFile::aPower: return GColor(CAPOWER); + case RideFile::NP: return GColor(CNPOWER); + case RideFile::alt: return GColor(CALTITUDE); + case RideFile::headwind: return GColor(CWINDSPEED); + case RideFile::temp: return GColor(CTEMP); + case RideFile::lrbalance: return GColor(CBALANCELEFT); + case RideFile::interval: return GColor(CBALANCERIGHT); + case RideFile::wattsKg: return GColor(CPOWER); + case RideFile::wprime: return GColor(CWBAL); + case RideFile::secs: + case RideFile::km: + case RideFile::vam: + case RideFile::lon: + case RideFile::lat: + case RideFile::slope: + default: return GColor(CPLOTMARKER); + } +} + QString RideFile::unitName(SeriesType series, Context *context) { @@ -124,6 +154,7 @@ RideFile::unitName(SeriesType series, Context *context) case RideFile::interval: return QString(tr("Interval")); case RideFile::vam: return QString(tr("meters per hour")); case RideFile::wattsKg: return QString(useMetricUnits ? tr("watts/kg") : tr("watts/lb")); + case RideFile::wprime: return QString(useMetricUnits ? tr("joules") : tr("joules")); default: return QString(tr("Unknown")); } } @@ -570,6 +601,7 @@ RideFile::setDataPresent(SeriesType series, bool value) case temp : dataPresent.temp = value; break; case lrbalance : dataPresent.lrbalance = value; break; case interval : dataPresent.interval = value; break; + case wprime : dataPresent.wprime = value; break; default: case none : break; } @@ -717,6 +749,7 @@ RideFile::decimalsFor(SeriesType series) case vam : return 0; break; case wattsKg : return 2; break; case lrbalance : return 1; break; + case wprime : return 0; break; case none : break; } return 2; // default @@ -746,6 +779,7 @@ RideFile::maximumFor(SeriesType series) case vam : return 9999; break; case wattsKg : return 50; break; case lrbalance : return 100; break; + case wprime : return 99999; break; case none : break; } return 9999; // default @@ -775,6 +809,7 @@ RideFile::minimumFor(SeriesType series) case vam : return 0; break; case wattsKg : return 0; break; case lrbalance : return 0; break; + case wprime : return 0; break; case none : break; } return 0; // default diff --git a/src/RideFile.h b/src/RideFile.h index 5ce0986dd..038d725c1 100644 --- a/src/RideFile.h +++ b/src/RideFile.h @@ -58,14 +58,14 @@ struct RideFileDataPresent bool secs, cad, hr, km, kph, nm, watts, alt, lon, lat, headwind, slope, temp, lrbalance, interval; // derived - bool np,xp,apower; + bool np,xp,apower,wprime; // whether non-zero data of each field is present RideFileDataPresent(): secs(false), cad(false), hr(false), km(false), kph(false), nm(false), watts(false), alt(false), lon(false), lat(false), headwind(false), slope(false), temp(false), lrbalance(false), interval(false), - np(false), xp(false), apower(false) {} + np(false), xp(false), apower(false), wprime(false) {} }; struct RideFileInterval @@ -121,6 +121,7 @@ class RideFile : public QObject // QObject to emit signals static int decimalsFor(SeriesType series); static double maximumFor(SeriesType series); static double minimumFor(SeriesType series); + static QColor colorFor(SeriesType series); static bool parseRideFileName(const QString &name, QDateTime *dt); // Working with DATAPOINTS -- ***use command to modify*** diff --git a/src/RideFileCache.cpp b/src/RideFileCache.cpp index 65d6ae75e..1cb3bbedb 100644 --- a/src/RideFileCache.cpp +++ b/src/RideFileCache.cpp @@ -141,6 +141,7 @@ RideFileCache::decimalsFor(RideFile::SeriesType series) case RideFile::wattsKg : return 2; break; case RideFile::aPower : return 0; break; case RideFile::lrbalance : return 1; break; + case RideFile::wprime : return 0; break; case RideFile::none : break; } return 2; // default diff --git a/src/TabView.h b/src/TabView.h index 34665c85f..a8845b8dd 100644 --- a/src/TabView.h +++ b/src/TabView.h @@ -143,7 +143,7 @@ public: QSplitter(orientation, parent), orientation(orientation), name(name), tabView(parent), showForDrag(false) { setAcceptDrops(true); qRegisterMetaType("hpos"); - + toggle=NULL; } protected: @@ -153,6 +153,7 @@ protected: int handleWidth() { return 23; }; QPushButton *newtoggle() { + if (toggle) delete toggle; // we only need one! toggle = new QPushButton("OFF", this); toggle->setCheckable(true); toggle->setChecked(false); @@ -233,7 +234,6 @@ public slots: toggle->setStyleSheet(""); toggle->setText("OFF"); } - // we started compare mode emit compareChanged(toggle->isChecked()); }