diff --git a/src/Aerolab.cpp b/src/Aerolab.cpp index 2d5a03701..2879f6b0c 100644 --- a/src/Aerolab.cpp +++ b/src/Aerolab.cpp @@ -17,6 +17,7 @@ */ #include "Aerolab.h" +#include "AerolabWindow.h" #include "MainWindow.h" #include "RideFile.h" #include "RideItem.h" @@ -42,11 +43,193 @@ max(double a, double b) { if (a > b) return a; else return b; } static inline double min(double a, double b) { if (a < b) return a; else return b; } -Aerolab::Aerolab(QWidget *parent): + +/*---------------------------------------------------------------------- + * Interval plotting + *--------------------------------------------------------------------*/ + +class IntervalAerolabData : public QwtData +{ + public: + Aerolab *aerolab; + MainWindow *mainWindow; + IntervalAerolabData + ( + Aerolab *aerolab, + MainWindow *mainWindow + ) : aerolab( aerolab ), mainWindow( mainWindow ) { } + + double x( size_t ) const; + double y( size_t ) const; + size_t size() const; + virtual QwtData *copy() const; + + void init(); + + IntervalItem *intervalNum( int ) const; + + int intervalCount() const; +}; + +/* + * HELPER FUNCTIONS: + * intervalNum - returns a pointer to the nth selected interval + * intervalCount - returns the number of highlighted intervals + */ +// ------------------------------------------------------------------------------------------------------------ +// note this is operating on the children of allIntervals and not the +// intervalWidget (QTreeWidget) -- this is why we do not use the +// selectedItems() member. N starts a one not zero. +// ------------------------------------------------------------------------------------------------------------ +IntervalItem *IntervalAerolabData::intervalNum +( + int number +) const +{ + int highlighted = 0; + const QTreeWidgetItem *allIntervals = mainWindow->allIntervalItems(); + for ( int ii = 0; ii < allIntervals->childCount(); ii++) + + { + IntervalItem *current = (IntervalItem *) allIntervals->child( ii ); + + if ( current == NULL) + { + return NULL; + } + if ( current->isSelected() == true ) + { + ++highlighted; + } + if ( highlighted == number ) + { + return current; + } + } + + return NULL; +} + +// ------------------------------------------------------------------------------------------------------------ +// how many intervals selected? +// ------------------------------------------------------------------------------------------------------------ +int IntervalAerolabData::intervalCount() const +{ + int highlighted = 0; + + if ( mainWindow->allIntervalItems() != NULL ) + { + const QTreeWidgetItem *allIntervals = mainWindow->allIntervalItems(); + for ( int ii = 0; ii < allIntervals->childCount(); ii++) + { + IntervalItem *current = (IntervalItem *) allIntervals->child( ii ); + if ( current != NULL ) + { + if ( current->isSelected() == true ) + { + ++highlighted; + } + } + } + } + return highlighted; +} +/* + * INTERVAL HIGHLIGHTING CURVE + * IntervalAerolabData - implements the qwtdata interface where + * x,y return point co-ordinates and + * size returns the number of points + */ +// The interval curve data is derived from the intervals that have +// been selected in the MainWindow leftlayout for each selected +// interval we return 4 data points; bottomleft, topleft, topright +// and bottom right. +// +// the points correspond to: +// bottom left = interval start, 0 watts +// top left = interval start, maxwatts +// top right = interval stop, maxwatts +// bottom right = interval stop, 0 watts +// +double IntervalAerolabData::x +( + size_t number +) const +{ + // for each interval there are four points, which interval is this for? + // interval numbers start at 1 not ZERO in the utility functions + + double result = 0; + + int interval_no = number ? 1 + number / 4 : 1; + // get the interval + IntervalItem *current = intervalNum( interval_no ); + + if ( current != NULL ) + { + double multiplier = aerolab->useMetricUnits ? 1 : MILES_PER_KM; + // which point are we returning? +//qDebug() << "number = " << number << endl; + switch ( number % 4 ) + { + case 0 : result = aerolab->bydist ? multiplier * current->startKM : current->start/60; // bottom left + break; + case 1 : result = aerolab->bydist ? multiplier * current->startKM : current->start/60; // top left + break; + case 2 : result = aerolab->bydist ? multiplier * current->stopKM : current->stop/60; // bottom right + break; + case 3 : result = aerolab->bydist ? multiplier * current->stopKM : current->stop/60; // top right + break; + } + } + return result; +} +double IntervalAerolabData::y +( + size_t number +) const +{ + // which point are we returning? + double result = 0; + switch ( number % 4 ) + { + case 0 : result = -5000; // bottom left + break; + case 1 : result = 5000; // top left - set to out of bound value + break; + case 2 : result = 5000; // top right - set to out of bound value + break; + case 3 : result = -5000; // bottom right + break; + } + return result; +} + +size_t IntervalAerolabData::size() const +{ + return intervalCount() * 4; +} + +QwtData *IntervalAerolabData::copy() const +{ + return new IntervalAerolabData( aerolab, mainWindow ); +} + + +//********************************************** +//** END IntervalAerolabData ** +//********************************************** + + +Aerolab::Aerolab( + AerolabWindow *parent, + MainWindow *mainWindow +): QwtPlot(parent), + parent(parent), unit(0), rideItem(NULL), - smooth(1), bydist(false) { + smooth(1), bydist(true), autoEoffset(true) { crr = 0.005; cda = 0.500; @@ -68,9 +251,19 @@ Aerolab::Aerolab(QWidget *parent): setAxisScale(xBottom, 0, 60); veCurve = new QwtPlotCurve(tr("V-Elevation")); - altCurve = new QwtPlotCurve(tr("Elevation")); + // get rid of nasty blank space on right of the plot + veCurve->setYAxis( yLeft ); + altCurve->setYAxis( yLeft ); + + intervalHighlighterCurve = new QwtPlotCurve(); + intervalHighlighterCurve->setBaseline(-5000); + intervalHighlighterCurve->setYAxis( yLeft ); + intervalHighlighterCurve->setData( IntervalAerolabData( this, mainWindow ) ); + intervalHighlighterCurve->attach( this ); + this->legend()->remove( intervalHighlighterCurve ); // don't show in legend + grid = new QwtPlotGrid(); grid->enableX(false); grid->attach(this); @@ -78,6 +271,7 @@ Aerolab::Aerolab(QWidget *parent): configChanged(); } + void Aerolab::configChanged() { @@ -92,6 +286,16 @@ Aerolab::configChanged() QPen gridPen(GColor(CPLOTGRID)); gridPen.setStyle(Qt::DotLine); grid->setPen(gridPen); + + QPen ihlPen = QPen( GColor( CINTERVALHIGHLIGHTER ) ); + ihlPen.setWidth(1); + intervalHighlighterCurve->setPen( ihlPen ); + + QColor ihlbrush = QColor(GColor(CINTERVALHIGHLIGHTER)); + ihlbrush.setAlpha(40); + intervalHighlighterCurve->setBrush(ihlbrush); // fill below the line + + this->legend()->remove( intervalHighlighterCurve ); // don't show in legend } void @@ -157,7 +361,7 @@ Aerolab::setData(RideItem *_rideItem, bool new_zoom) { if ( arrayLength == 0 ) e = eoffset; - timeArray[arrayLength] = p1->secs; + timeArray[arrayLength] = p1->secs / 60.0; if ( have_recorded_alt_curve ) altArray[arrayLength] = (useMetricUnits ? p1->alt @@ -172,8 +376,13 @@ Aerolab::setData(RideItem *_rideItem, bool new_zoom) { } double f = 0.0; double a = 0.0; - d += v * dt; - distanceArray[arrayLength] = d/1000; + + // Use km data insteed of formula for file with a stop (gap). + //d += v * dt; + //distanceArray[arrayLength] = d/1000; + + distanceArray[arrayLength] = p1->km; + if( v > small_number ) { @@ -200,8 +409,8 @@ Aerolab::setData(RideItem *_rideItem, bool new_zoom) { veCurve->setVisible(false); altCurve->setVisible(false); } - recalc(new_zoom); + adjustEoffset(); } else { setTitle("no data"); @@ -222,6 +431,26 @@ Aerolab::setAxisTitle(int axis, QString label) QwtPlot::setAxisTitle(axis, title); } +void +Aerolab::adjustEoffset() { + + if (autoEoffset && !altArray.empty()) { + double idx = axisScaleDiv( QwtPlot::xBottom )->lowerBound(); + parent->eoffsetSlider->setEnabled(false); + + if (bydist) { + int v = 100*(altArray.at(rideItem->ride()->distanceIndex(idx))-veArray.at(rideItem->ride()->distanceIndex(idx))); + parent->eoffsetSlider->setValue(intEoffset()+v); + } + else { + int v = 100*(altArray.at(rideItem->ride()->timeIndex(60*idx))-veArray.at(rideItem->ride()->timeIndex(60*idx))); + parent->eoffsetSlider->setValue(intEoffset()+v); + } + } else + parent->eoffsetSlider->setEnabled(true); +} + + struct DataPoint { double time, hr, watts, speed, cad, alt; DataPoint(double t, double h, double w, double s, double c, double a) : @@ -248,8 +477,7 @@ Aerolab::recalc( bool new_zoom ) { return; } - - QVector &xaxis = distanceArray; + QVector &xaxis = (bydist?distanceArray:timeArray); int startingIndex = 0; int totalPoints = arrayLength - startingIndex; @@ -264,9 +492,12 @@ Aerolab::recalc( bool new_zoom ) { } if( new_zoom ) - setAxisScale(xBottom, 0.0, totalRideDistance); + setAxisScale(xBottom, 0.0, (bydist?totalRideDistance:rideTimeSecs)); - setYMax(); + + + setYMax(new_zoom ); + refreshIntervalMarkers(); replot(); } @@ -274,19 +505,75 @@ Aerolab::recalc( bool new_zoom ) { void -Aerolab::setYMax() { +Aerolab::setYMax(bool new_zoom) +{ + if (veCurve->isVisible()) + { - if (veCurve->isVisible()) { - setAxisTitle(yLeft, "Elevation"); + if ( useMetricUnits ) + + { + + setAxisTitle( yLeft, "Elevation (m)" ); + + } + + else + + { + + setAxisTitle( yLeft, "Elevation (')" ); + + } + + double minY = 0.0; + double maxY = 0.0; + + //************ + + //if (veCurve->isVisible()) { + // setAxisTitle(yLeft, tr("Elevation")); if ( !altArray.empty() ) { - setAxisScale(yLeft, - min( veCurve->minYValue(), altCurve->minYValue() ) - 10, - 10.0 + max( veCurve->maxYValue(), altCurve->maxYValue() ) ); + // setAxisScale(yLeft, + // min( veCurve->minYValue(), altCurve->minYValue() ) - 10, + // 10.0 + max( veCurve->maxYValue(), altCurve->maxYValue() ) ); + + minY = min( veCurve->minYValue(), altCurve->minYValue() ) - 10; + maxY = 10.0 + max( veCurve->maxYValue(), altCurve->maxYValue() ); + } else { - setAxisScale(yLeft, - veCurve->minYValue() , - 1.05 * veCurve->maxYValue() ); + //setAxisScale(yLeft, + // veCurve->minYValue() , + // 1.05 * veCurve->maxYValue() ); + + if ( new_zoom ) + + { + + minY = veCurve->minYValue(); + + maxY = veCurve->maxYValue(); + + } + + else + + { + + minY = parent->getCanvasTop(); + + maxY = parent->getCanvasBottom(); + + } + + //adjust eooffset + // TODO + + + } + + setAxisScale( yLeft, minY, maxY ); setAxisLabelRotation(yLeft,270); setAxisLabelAlignment(yLeft,Qt::AlignVCenter); } @@ -305,12 +592,18 @@ Aerolab::setXTitle() { setAxisTitle(xBottom, tr("Time (minutes)")); } +void +Aerolab::setAutoEoffset(int value) +{ + autoEoffset = value; + adjustEoffset(); +} void -Aerolab::setByDistance() { - bydist = true; +Aerolab::setByDistance(int value) { + bydist = value; setXTitle(); - recalc(false); + recalc(true); } @@ -401,3 +694,72 @@ Aerolab::setIntEoffset( eoffset = (double) value / 100.0; recalc(false); } + + + + + + + + + + +void Aerolab::pointHover (QwtPlotCurve *curve, int index) +{ + if ( index >= 0 && curve != intervalHighlighterCurve ) + { + double x_value = curve->x( index ); + double y_value = curve->y( index ); + // output the tooltip + + QString text = QString( "%1 %2 %3 %4 %5" ) + . arg( this->axisTitle( curve->xAxis() ).text() ) + . arg( x_value, 0, 'f', 3 ) + . arg( "\n" ) + . arg( this->axisTitle( curve->yAxis() ).text() ) + . arg( y_value, 0, 'f', 3 ); + + // set that text up + tooltip->setText( text ); + } + else + { + // no point + tooltip->setText( "" ); + } +} + +void Aerolab::refreshIntervalMarkers() +{ + foreach( QwtPlotMarker *mrk, d_mrk ) + { + mrk->detach(); + delete mrk; + } + 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()) { + // skip WKO autogenerated peak intervals + if (wkoAuto.exactMatch(interval.name)) + continue; + QwtPlotMarker *mrk = new QwtPlotMarker; + d_mrk.append(mrk); + mrk->attach(this); + mrk->setLineStyle(QwtPlotMarker::VLine); + mrk->setLabelAlignment(Qt::AlignRight | Qt::AlignTop); + mrk->setLinePen(QPen(GColor(CPLOTMARKER), 0, Qt::DashDotLine)); + QwtText text(interval.name); + text.setFont(QFont("Helvetica", 10, QFont::Bold)); + text.setColor(GColor(CPLOTMARKER)); + if (!bydist) + mrk->setValue(interval.start / 60.0, 0.0); + else + mrk->setValue((useMetricUnits ? 1 : MILES_PER_KM) * + rideItem->ride()->timeToDistance(interval.start), 0.0); + mrk->setLabel(text); + } + } +} diff --git a/src/Aerolab.h b/src/Aerolab.h index ef3573748..afada30da 100644 --- a/src/Aerolab.h +++ b/src/Aerolab.h @@ -23,6 +23,7 @@ #include #include #include +#include "LTMWindow.h" // for tooltip/canvaspicker // forward references class RideItem; @@ -32,6 +33,10 @@ class QwtPlotGrid; class QwtPlotMarker; class AerolabWindow; class MainWindow; +class IntervalAerolabData; +class LTMToolTip; +class LTMCanvasPicker; + class Aerolab : public QwtPlot { @@ -40,27 +45,47 @@ class Aerolab : public QwtPlot { public: - Aerolab(QWidget *parent); + Aerolab( AerolabWindow *, MainWindow * ); bool byDistance() const { return bydist; } bool useMetricUnits; // whether metric units are used (or imperial) void setData(RideItem *_rideItem, bool new_zoom); void setAxisTitle(int axis, QString label); + void refreshIntervalMarkers(); + + private: + AerolabWindow *parent; + + LTMToolTip *tooltip; + LTMCanvasPicker *_canvasPicker; // allow point selection/hover + + void adjustEoffset(); + public slots: - void setByDistance(); + + void setAutoEoffset(int value); + void setByDistance(int value); void configChanged(); + void pointHover( QwtPlotCurve *, int ); + signals: protected: friend class ::AerolabWindow; + friend class ::IntervalAerolabData; + + QVariant unit; QwtPlotGrid *grid; + QVector d_mrk; // One curve to plot in the Course Profile: QwtPlotCurve *veCurve; // virtual elevation curve QwtPlotCurve *altCurve; // recorded elevation curve, if available + QwtPlotCurve *intervalHighlighterCurve; // highlight selected intervals on the Plot + RideItem *rideItem; QVector hrArray; @@ -76,6 +101,7 @@ class Aerolab : public QwtPlot { int smooth; bool bydist; + bool autoEoffset; int arrayLength; int iCrr; int iCda; @@ -89,7 +115,7 @@ class Aerolab : public QwtPlot { double slope(double, double, double, double, double, double, double); void recalc(bool); - void setYMax(); + void setYMax(bool); void setXTitle(); void setIntCrr(int); void setIntCda(int); @@ -97,18 +123,20 @@ class Aerolab : public QwtPlot { void setIntEta(int); void setIntEoffset(int); void setIntTotalMass(int); - double getCrr() const { return (double)crr; }; - double getCda() const { return (double)cda; }; - double getTotalMass() const { return (double)totalMass; }; - double getRho() const { return (double)rho; }; - double getEta() const { return (double)eta; }; - double getEoffset() const { return (double)eoffset; }; - int intCrr() const { return (int)( crr * 1000000 ); }; - int intCda() const { return (int)( cda * 100000); }; - int intTotalMass() const { return (int)( totalMass * 100); }; - int intRho() const { return (int)( rho * 10000); }; - int intEta() const { return (int)( eta * 10000); }; - int intEoffset() const { return (int)( eoffset * 100); }; + double getCrr() const { return (double)crr; } + double getCda() const { return (double)cda; } + double getTotalMass() const { return (double)totalMass; } + double getRho() const { return (double)rho; } + double getEta() const { return (double)eta; } + double getEoffset() const { return (double)eoffset; } + int intCrr() const { return (int)( crr * 1000000 ); } + int intCda() const { return (int)( cda * 10000); } + int intTotalMass() const { return (int)( totalMass * 100); } + int intRho() const { return (int)( rho * 10000); } + int intEta() const { return (int)( eta * 10000); } + int intEoffset() const { return (int)( eoffset * 100); } + + }; #endif // _GC_Aerolab_h diff --git a/src/AerolabWindow.cpp b/src/AerolabWindow.cpp index c1b3bcf2e..c25d05ecc 100644 --- a/src/AerolabWindow.cpp +++ b/src/AerolabWindow.cpp @@ -35,7 +35,7 @@ AerolabWindow::AerolabWindow(MainWindow *mainWindow) : QHBoxLayout *cLayout = new QHBoxLayout; // Plot: - aerolab = new Aerolab(this); + aerolab = new Aerolab(this, mainWindow); // Left controls layout: QVBoxLayout *leftControls = new QVBoxLayout; @@ -65,11 +65,14 @@ AerolabWindow::AerolabWindow(MainWindow *mainWindow) : QHBoxLayout *cdaLayout = new QHBoxLayout; QLabel *cdaLabel = new QLabel(tr("CdA"), this); cdaLabel->setFixedWidth(labelWidth1); - cdaQLCDNumber = new QLCDNumber(7); + cdaLineEdit = new QLineEdit(); + cdaLineEdit->setFixedWidth(50); + cdaLineEdit->setText(QString("%1").arg(aerolab->getCda()) ); + /*cdaQLCDNumber = new QLCDNumber(7); cdaQLCDNumber->setMode(QLCDNumber::Dec); cdaQLCDNumber->setSmallDecimalPoint(false); cdaQLCDNumber->setSegmentStyle(QLCDNumber::Flat); - cdaQLCDNumber->display(QString("%1").arg(aerolab->getCda()) ); + cdaQLCDNumber->display(QString("%1").arg(aerolab->getCda()) );*/ cdaSlider = new QSlider(Qt::Horizontal); cdaSlider->setTickPosition(QSlider::TicksBelow); cdaSlider->setTickInterval(100); @@ -77,7 +80,8 @@ AerolabWindow::AerolabWindow(MainWindow *mainWindow) : cdaSlider->setMaximum(6000); cdaSlider->setValue(aerolab->intCda()); cdaLayout->addWidget( cdaLabel ); - cdaLayout->addWidget( cdaQLCDNumber ); + //cdaLayout->addWidget( cdaQLCDNumber ); + cdaLayout->addWidget( cdaLineEdit ); cdaLayout->addWidget( cdaSlider ); // Eta: @@ -159,16 +163,28 @@ AerolabWindow::AerolabWindow(MainWindow *mainWindow) : eoffsetSlider->setTickPosition(QSlider::TicksBelow); eoffsetSlider->setTickInterval(1000); eoffsetSlider->setMinimum(-30000); - eoffsetSlider->setMaximum(30000); + eoffsetSlider->setMaximum(100000); eoffsetSlider->setValue(aerolab->intEoffset()); eoffsetLayout->addWidget( eoffsetLabel ); eoffsetLayout->addWidget( eoffsetQLCDNumber ); eoffsetLayout->addWidget( eoffsetSlider ); + QCheckBox *eoffsetAuto = new QCheckBox(tr("eoffset auto"), this); + eoffsetAuto->setCheckState(Qt::Checked); + eoffsetLayout->addWidget(eoffsetAuto); + + QHBoxLayout *smoothLayout = new QHBoxLayout; + QComboBox *comboDistance = new QComboBox(); + comboDistance->addItem(tr("X Axis Shows Time")); + comboDistance->addItem(tr("X Axis Shows Distance")); + comboDistance->setCurrentIndex(1); + smoothLayout->addWidget(comboDistance); + // Add to leftControls: rightControls->addLayout( mLayout ); rightControls->addLayout( rhoLayout ); rightControls->addLayout( eoffsetLayout ); + rightControls->addLayout( smoothLayout ); // Assemble controls layout: @@ -182,27 +198,68 @@ AerolabWindow::AerolabWindow(MainWindow *mainWindow) : | QwtPicker::CornerToCorner); allZoomer->setTrackerMode(QwtPicker::AlwaysOff); allZoomer->setEnabled(true); + allZoomer->setMousePattern( QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier ); + allZoomer->setMousePattern( QwtEventPattern::MouseSelect3, Qt::RightButton ); // SIGNALs to SLOTs: //connect(mainWindow, SIGNAL(rideSelected()), this, SLOT(rideSelected())); connect(this, SIGNAL(rideItemChanged(RideItem*)), this, SLOT(rideSelected())); connect(crrSlider, SIGNAL(valueChanged(int)),this, SLOT(setCrrFromSlider())); connect(cdaSlider, SIGNAL(valueChanged(int)), this, SLOT(setCdaFromSlider())); + connect(cdaLineEdit, SIGNAL(textChanged(const QString)), this, SLOT(setCdaFromText(const QString))); connect(mSlider, SIGNAL(valueChanged(int)),this, SLOT(setTotalMassFromSlider())); connect(rhoSlider, SIGNAL(valueChanged(int)), this, SLOT(setRhoFromSlider())); connect(etaSlider, SIGNAL(valueChanged(int)), this, SLOT(setEtaFromSlider())); connect(eoffsetSlider, SIGNAL(valueChanged(int)), this, SLOT(setEoffsetFromSlider())); + connect(eoffsetAuto, SIGNAL(stateChanged(int)), this, SLOT(setAutoEoffset(int))); + connect(comboDistance, SIGNAL(currentIndexChanged(int)), this, SLOT(setByDistance(int))); connect(mainWindow, SIGNAL(configChanged()), aerolab, SLOT(configChanged())); connect(mainWindow, SIGNAL(configChanged()), this, SLOT(configChanged())); + connect(mainWindow, SIGNAL( intervalSelected() ), this, SLOT(intervalSelected())); + connect(allZoomer, SIGNAL( zoomed(const QwtDoubleRect) ), this, SLOT(zoomChanged())); + // Build the tab layout: vLayout->addWidget(aerolab); vLayout->addLayout(cLayout); setLayout(vLayout); + + // tooltip on hover over point + //************************************ + aerolab->tooltip = new LTMToolTip( QwtPlot::xBottom, + QwtPlot::yLeft, + QwtPicker::PointSelection, + QwtPicker::VLineRubberBand, + QwtPicker::AlwaysOn, + aerolab->canvas(), + "" + ); + aerolab->tooltip->setSelectionFlags( QwtPicker::PointSelection | QwtPicker::RectSelection | QwtPicker::DragSelection); + aerolab->tooltip->setRubberBand( QwtPicker::VLineRubberBand ); + aerolab->tooltip->setMousePattern( QwtEventPattern::MouseSelect1, Qt::LeftButton, Qt::ShiftModifier ); + aerolab->tooltip->setTrackerPen( QColor( Qt::black ) ); + QColor inv( Qt::white ); + inv.setAlpha( 0 ); + aerolab->tooltip->setRubberBandPen( inv ); + aerolab->tooltip->setEnabled( true ); + aerolab->_canvasPicker = new LTMCanvasPicker( aerolab ); + + connect( aerolab->_canvasPicker, SIGNAL( pointHover( QwtPlotCurve*, int ) ), + aerolab, SLOT ( pointHover( QwtPlotCurve*, int ) ) ); + + configChanged(); // pickup colors etc } +void +AerolabWindow::zoomChanged() +{ + RideItem *ride = myRideItem; + aerolab->setData(ride, false); +} + + void AerolabWindow::configChanged() { @@ -219,7 +276,10 @@ AerolabWindow::rideSelected() { if (!ride) return; + + aerolab->setData(ride, true); + allZoomer->setZoomBase(); } @@ -234,6 +294,18 @@ AerolabWindow::setCrrFromSlider() { } } +void +AerolabWindow::setCdaFromText(const QString text) { + int value = 10000 * text.toDouble(); + if (aerolab->intCda() != value) { + aerolab->setIntCda(value); + //cdaQLCDNumber->display(QString("%1").arg(aerolab->getCda())); + cdaSlider->setValue(aerolab->intCda()); + RideItem *ride = myRideItem; + aerolab->setData(ride, false); + } +} + void AerolabWindow::setCdaFromSlider() { @@ -289,6 +361,23 @@ AerolabWindow::setEoffsetFromSlider() { } } +void +AerolabWindow::setAutoEoffset(int value) +{ + aerolab->setAutoEoffset(value); +} + +void +AerolabWindow::setByDistance(int value) +{ + aerolab->setByDistance(value); + // refresh + RideItem *ride = myRideItem; + aerolab->setData(ride, false); +} + + + void AerolabWindow::zoomInterval(IntervalItem *which) { @@ -304,5 +393,30 @@ AerolabWindow::zoomInterval(IntervalItem *which) { rect.setTop(aerolab->veCurve->maxYValue()*1.1); rect.setBottom(aerolab->veCurve->minYValue()-10); allZoomer->zoom(rect); + + aerolab->recalc(false); } +void AerolabWindow::intervalSelected() +{ + RideItem *ride = myRideItem; + if ( !ride ) + { + return; + } + + // set the elevation data + aerolab->setData( ride, true ); +} + +double AerolabWindow::getCanvasTop() const +{ + const QwtDoubleRect &canvasRect = allZoomer->zoomRect(); + return canvasRect.top(); +} + +double AerolabWindow::getCanvasBottom() const +{ + const QwtDoubleRect &canvasRect = allZoomer->zoomRect(); + return canvasRect.bottom(); +} diff --git a/src/AerolabWindow.h b/src/AerolabWindow.h index 08e032a69..bb859a64c 100644 --- a/src/AerolabWindow.h +++ b/src/AerolabWindow.h @@ -41,18 +41,25 @@ class AerolabWindow : public GcWindow { AerolabWindow(MainWindow *mainWindow); void setData(RideItem *ride); void zoomInterval(IntervalItem *); // zoom into a specified interval + double getCanvasTop() const; + double getCanvasBottom() const; + QSlider *eoffsetSlider; public slots: void setCrrFromSlider(); void setCdaFromSlider(); + void setCdaFromText(const QString text); void setTotalMassFromSlider(); void setRhoFromSlider(); void setEtaFromSlider(); void setEoffsetFromSlider(); + void setAutoEoffset(int value); + void setByDistance(int value); void rideSelected(); + void zoomChanged(); void configChanged(); - + void intervalSelected(); protected slots: @@ -77,7 +84,7 @@ class AerolabWindow : public GcWindow { QSlider *etaSlider; QLineEdit *etaLineEdit; QLCDNumber *etaQLCDNumber; - QSlider *eoffsetSlider; + QLineEdit *eoffsetLineEdit; QLCDNumber *eoffsetQLCDNumber;