abstract "Histogram Analysis" tab into its own class

This commit is contained in:
Sean Rhea
2009-10-03 19:16:27 -04:00
parent de96ee2f16
commit 5b8837a423
5 changed files with 345 additions and 253 deletions

264
src/HistogramWindow.cpp Normal file
View File

@@ -0,0 +1,264 @@
/*
* Copyright (c) 2009 Sean C. Rhea (srhea@srhea.net)
*
* 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
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "HistogramWindow.h"
#include "PowerHist.h"
#include "RideFile.h"
#include "RideItem.h"
#include <QtGui>
HistogramWindow::HistogramWindow(QWidget *parent) : QWidget(parent)
{
QVBoxLayout *vlayout = new QVBoxLayout;
QHBoxLayout *binWidthLayout = new QHBoxLayout;
QLabel *binWidthLabel = new QLabel(tr("Bin width"), this);
binWidthLineEdit = new QLineEdit(this);
binWidthLineEdit->setFixedWidth(30);
binWidthLayout->addWidget(binWidthLabel);
binWidthLayout->addWidget(binWidthLineEdit);
binWidthSlider = new QSlider(Qt::Horizontal);
binWidthSlider->setTickPosition(QSlider::TicksBelow);
binWidthSlider->setTickInterval(1);
binWidthSlider->setMinimum(1);
binWidthSlider->setMaximum(100);
binWidthLayout->addWidget(binWidthSlider);
lnYHistCheckBox = new QCheckBox;
lnYHistCheckBox->setText("Log y");
binWidthLayout->addWidget(lnYHistCheckBox);
withZerosCheckBox = new QCheckBox;
withZerosCheckBox->setText("With zeros");
binWidthLayout->addWidget(withZerosCheckBox);
histParameterCombo = new QComboBox();
binWidthLayout->addWidget(histParameterCombo);
powerHist = new PowerHist();
setHistTextValidator();
lnYHistCheckBox->setChecked(powerHist->islnY());
withZerosCheckBox->setChecked(powerHist->withZeros());
binWidthSlider->setValue(powerHist->binWidth());
setHistBinWidthText();
vlayout->addWidget(powerHist);
vlayout->addLayout(binWidthLayout);
setLayout(vlayout);
connect(binWidthSlider, SIGNAL(valueChanged(int)),
this, SLOT(setBinWidthFromSlider()));
connect(binWidthLineEdit, SIGNAL(editingFinished()),
this, SLOT(setBinWidthFromLineEdit()));
connect(lnYHistCheckBox, SIGNAL(stateChanged(int)),
this, SLOT(setlnYHistFromCheckBox()));
connect(withZerosCheckBox, SIGNAL(stateChanged(int)),
this, SLOT(setWithZerosFromCheckBox()));
connect(histParameterCombo, SIGNAL(currentIndexChanged(int)),
this, SLOT(setHistSelection(int)));
}
void
HistogramWindow::setData(RideItem *ride)
{
// set the histogram data
powerHist->setData(ride);
// make sure the histogram has a legal selection
powerHist->fixSelection();
// update the options in the histogram combobox
setHistWidgets(ride);
}
void
HistogramWindow::zonesChanged()
{
powerHist->refreshZoneLabels();
powerHist->replot();
}
void
HistogramWindow::setBinWidthFromSlider()
{
if (powerHist->binWidth() != binWidthSlider->value()) {
powerHist->setBinWidth(binWidthSlider->value());
setHistBinWidthText();
}
}
void
HistogramWindow::setlnYHistFromCheckBox()
{
if (powerHist->islnY() != lnYHistCheckBox->isChecked())
powerHist->setlnY(! powerHist->islnY());
}
void
HistogramWindow::setWithZerosFromCheckBox()
{
if (powerHist->withZeros() != withZerosCheckBox->isChecked()) {
powerHist->setWithZeros(withZerosCheckBox->isChecked());
}
}
void
HistogramWindow::setHistBinWidthText()
{
binWidthLineEdit->setText(QString("%1").arg(powerHist->getBinWidthRealUnits(), 0, 'g', 3));
}
void
HistogramWindow::setHistTextValidator()
{
double delta = powerHist->getDelta();
int digits = powerHist->getDigits();
binWidthLineEdit->setValidator(
(digits == 0) ?
(QValidator *) (
new QIntValidator(binWidthSlider->minimum() * delta,
binWidthSlider->maximum() * delta,
binWidthLineEdit
)
) :
(QValidator *) (
new QDoubleValidator(binWidthSlider->minimum() * delta,
binWidthSlider->maximum() * delta,
digits,
binWidthLineEdit
)
)
);
}
void
HistogramWindow::setHistSelection(int id)
{
if (id == histWattsShadedID)
powerHist->setSelection(PowerHist::wattsShaded);
else if (id == histWattsUnshadedID)
powerHist->setSelection(PowerHist::wattsUnshaded);
else if (id == histNmID)
powerHist->setSelection(PowerHist::nm);
else if (id == histHrID)
powerHist->setSelection(PowerHist::hr);
else if (id == histKphID)
powerHist->setSelection(PowerHist::kph);
else if (id == histCadID)
powerHist->setSelection(PowerHist::cad);
else
fprintf(stderr, "Illegal id encountered: %d", id);
setHistBinWidthText();
setHistTextValidator();
}
void
HistogramWindow::setBinWidthFromLineEdit()
{
double value = binWidthLineEdit->text().toDouble();
if (value != powerHist->binWidth()) {
binWidthSlider->setValue(powerHist->setBinWidthRealUnits(value));
setHistBinWidthText();
}
}
void
HistogramWindow::setHistWidgets(RideItem *rideItem)
{
int count = 0;
assert(rideItem);
RideFile *ride = rideItem->ride;
// prevent selection from changing during reconstruction of options
disconnect(histParameterCombo, SIGNAL(currentIndexChanged(int)),
this, SLOT(setHistSelection(int)));
if (ride) {
// we want to retain the present selection
PowerHist::Selection s = powerHist->selection();
histParameterCombo->clear();
histWattsShadedID =
histWattsUnshadedID =
histNmID =
histHrID =
histKphID =
histCadID =
-1;
if (ride->areDataPresent()->watts) {
histWattsShadedID = count ++;
histParameterCombo->addItem(tr("Watts(shaded)"));
histWattsUnshadedID = count ++;
histParameterCombo->addItem(tr("Watts(unshaded)"));
}
if (ride->areDataPresent()->nm) {
histNmID = count ++;
histParameterCombo->addItem(tr("Torque"));
}
if (ride->areDataPresent()->hr) {
histHrID = count ++;
histParameterCombo->addItem(tr("Heartrate"));
}
if (ride->areDataPresent()->kph) {
histKphID = count ++;
histParameterCombo->addItem(tr("Speed"));
}
if (ride->areDataPresent()->cad) {
histCadID = count ++;
histParameterCombo->addItem(tr("Cadence"));
}
if (count > 0) {
histParameterCombo->setEnabled(true);
binWidthLineEdit->setEnabled(true);
binWidthSlider->setEnabled(true);
withZerosCheckBox->setEnabled(true);
lnYHistCheckBox->setEnabled(true);
// set widget to proper value
if ((s == PowerHist::wattsShaded) && (histWattsShadedID >= 0))
histParameterCombo->setCurrentIndex(histWattsShadedID);
else if ((s == PowerHist::wattsUnshaded) && (histWattsUnshadedID >= 0))
histParameterCombo->setCurrentIndex(histWattsUnshadedID);
else if ((s == PowerHist::nm) && (histNmID >= 0))
histParameterCombo->setCurrentIndex(histNmID);
else if ((s == PowerHist::hr) && (histHrID >= 0))
histParameterCombo->setCurrentIndex(histHrID);
else if ((s == PowerHist::kph) && (histKphID >= 0))
histParameterCombo->setCurrentIndex(histKphID);
else if ((s == PowerHist::cad) && (histCadID >= 0))
histParameterCombo->setCurrentIndex(histCadID);
else
histParameterCombo->setCurrentIndex(0);
// reconnect widget
connect(histParameterCombo, SIGNAL(currentIndexChanged(int)),
this, SLOT(setHistSelection(int)));
return;
}
}
histParameterCombo->addItem(tr("no data"));
histParameterCombo->setEnabled(false);
binWidthLineEdit->setEnabled(false);
binWidthSlider->setEnabled(false);
withZerosCheckBox->setEnabled(false);
lnYHistCheckBox->setEnabled(false);
}

72
src/HistogramWindow.h Normal file
View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2009 Sean C. Rhea (srhea@srhea.net)
*
* 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
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _GC_HistogramWindow_h
#define _GC_HistogramWindow_h 1
#include <QWidget>
class PowerHist;
class QCheckBox;
class QComboBox;
class QLineEdit;
class QSlider;
class RideItem;
class HistogramWindow : public QWidget
{
Q_OBJECT
public:
HistogramWindow(QWidget *parent);
void setData(RideItem *ride);
void zonesChanged();
protected slots:
void setHistWidgets(RideItem *rideItem);
void setBinWidthFromSlider();
void setBinWidthFromLineEdit();
void setlnYHistFromCheckBox();
void setWithZerosFromCheckBox();
void setHistSelection(int id);
protected:
void setHistTextValidator();
void setHistBinWidthText();
PowerHist *powerHist;
QSlider *binWidthSlider;
QLineEdit *binWidthLineEdit;
QCheckBox *lnYHistCheckBox;
QCheckBox *withZerosCheckBox;
QComboBox *histParameterCombo;
int histWattsShadedID;
int histWattsUnshadedID;
int histNmID;
int histHrID;
int histKphID;
int histCadID;
int histAltID;
};
#endif // _GC_HistogramWindow_h

View File

@@ -25,7 +25,7 @@
#include "PfPvPlot.h"
#include "DownloadRideDialog.h"
#include "ManualRideDialog.h"
#include "PowerHist.h"
#include "HistogramWindow.h"
#include "RideItem.h"
#include "RideFile.h"
#include "RideImportWizard.h"
@@ -233,43 +233,8 @@ MainWindow::MainWindow(const QDir &home) :
//////////////////////// Power Histogram Tab ////////////////////////
window = new QWidget;
vlayout = new QVBoxLayout;
QHBoxLayout *binWidthLayout = new QHBoxLayout;
QLabel *binWidthLabel = new QLabel(tr("Bin width"), window);
binWidthLineEdit = new QLineEdit(window);
binWidthLineEdit->setFixedWidth(30);
binWidthLayout->addWidget(binWidthLabel);
binWidthLayout->addWidget(binWidthLineEdit);
binWidthSlider = new QSlider(Qt::Horizontal);
binWidthSlider->setTickPosition(QSlider::TicksBelow);
binWidthSlider->setTickInterval(1);
binWidthSlider->setMinimum(1);
binWidthSlider->setMaximum(100);
binWidthLayout->addWidget(binWidthSlider);
lnYHistCheckBox = new QCheckBox;
lnYHistCheckBox->setText("Log y");
binWidthLayout->addWidget(lnYHistCheckBox);
withZerosCheckBox = new QCheckBox;
withZerosCheckBox->setText("With zeros");
binWidthLayout->addWidget(withZerosCheckBox);
histParameterCombo = new QComboBox();
binWidthLayout->addWidget(histParameterCombo);
powerHist = new PowerHist();
setHistTextValidator();
lnYHistCheckBox->setChecked(powerHist->islnY());
withZerosCheckBox->setChecked(powerHist->withZeros());
binWidthSlider->setValue(powerHist->binWidth());
setHistBinWidthText();
vlayout->addWidget(powerHist);
vlayout->addLayout(binWidthLayout);
window->setLayout(vlayout);
tabWidget->addTab(window, "Histogram Analysis");
histogramWindow = new HistogramWindow(this);
tabWidget->addTab(histogramWindow, "Histogram Analysis");
//////////////////////// Pedal Force/Velocity Plot ////////////////////////
@@ -430,16 +395,6 @@ MainWindow::MainWindow(const QDir &home) :
this, SLOT(splitterMoved()));
connect(cpintSetCPButton, SIGNAL(clicked()),
this, SLOT(cpintSetCPButtonClicked()));
connect(binWidthSlider, SIGNAL(valueChanged(int)),
this, SLOT(setBinWidthFromSlider()));
connect(binWidthLineEdit, SIGNAL(editingFinished()),
this, SLOT(setBinWidthFromLineEdit()));
connect(lnYHistCheckBox, SIGNAL(stateChanged(int)),
this, SLOT(setlnYHistFromCheckBox()));
connect(withZerosCheckBox, SIGNAL(stateChanged(int)),
this, SLOT(setWithZerosFromCheckBox()));
connect(histParameterCombo, SIGNAL(currentIndexChanged(int)),
this, SLOT(setHistSelection(int)));
connect(shadeZonesPfPvCheckBox, SIGNAL(stateChanged(int)),
this, SLOT(setShadeZonesPfPvFromCheckBox()));
connect(qaCPValue, SIGNAL(editingFinished()),
@@ -795,14 +750,7 @@ MainWindow::rideSelected()
if (ride) {
allPlotWindow->setData(ride);
// set the histogram data
powerHist->setData(ride);
// make sure the histogram has a legal selection
powerHist->fixSelection();
// update the options in the histogram combobox
setHistWidgets(ride);
histogramWindow->setData(ride);
pfPvPlot->setData(ride);
// update the QLabel widget with the CP value set in PfPvPlot::setData()
qaCPValue->setText(QString("%1").arg(pfPvPlot->getCP()));
@@ -1298,8 +1246,7 @@ MainWindow::showOptions()
allPlotWindow->zonesChanged();
// histogram
powerHist->refreshZoneLabels();
powerHist->replot();
histogramWindow->zonesChanged();
// force-versus-pedal velocity plot
pfPvPlot->refreshZoneItems();
@@ -1394,82 +1341,6 @@ MainWindow::cpintSetCPButtonClicked()
}
void
MainWindow::setBinWidthFromSlider()
{
if (powerHist->binWidth() != binWidthSlider->value()) {
powerHist->setBinWidth(binWidthSlider->value());
setHistBinWidthText();
}
}
void
MainWindow::setlnYHistFromCheckBox()
{
if (powerHist->islnY() != lnYHistCheckBox->isChecked())
powerHist->setlnY(! powerHist->islnY());
}
void
MainWindow::setWithZerosFromCheckBox()
{
if (powerHist->withZeros() != withZerosCheckBox->isChecked()) {
powerHist->setWithZeros(withZerosCheckBox->isChecked());
}
}
void
MainWindow::setHistBinWidthText()
{
binWidthLineEdit->setText(QString("%1").arg(powerHist->getBinWidthRealUnits(), 0, 'g', 3));
}
void
MainWindow::setHistTextValidator()
{
double delta = powerHist->getDelta();
int digits = powerHist->getDigits();
binWidthLineEdit->setValidator(
(digits == 0) ?
(QValidator *) (
new QIntValidator(binWidthSlider->minimum() * delta,
binWidthSlider->maximum() * delta,
binWidthLineEdit
)
) :
(QValidator *) (
new QDoubleValidator(binWidthSlider->minimum() * delta,
binWidthSlider->maximum() * delta,
digits,
binWidthLineEdit
)
)
);
}
void
MainWindow::setHistSelection(int id)
{
if (id == histWattsShadedID)
powerHist->setSelection(PowerHist::wattsShaded);
else if (id == histWattsUnshadedID)
powerHist->setSelection(PowerHist::wattsUnshaded);
else if (id == histNmID)
powerHist->setSelection(PowerHist::nm);
else if (id == histHrID)
powerHist->setSelection(PowerHist::hr);
else if (id == histKphID)
powerHist->setSelection(PowerHist::kph);
else if (id == histCadID)
powerHist->setSelection(PowerHist::cad);
else
fprintf(stderr, "Illegal id encountered: %d", id);
setHistBinWidthText();
setHistTextValidator();
}
void
MainWindow::setShadeZonesPfPvFromCheckBox()
{
@@ -1478,16 +1349,6 @@ MainWindow::setShadeZonesPfPvFromCheckBox()
}
}
void
MainWindow::setBinWidthFromLineEdit()
{
double value = binWidthLineEdit->text().toDouble();
if (value != powerHist->binWidth()) {
binWidthSlider->setValue(powerHist->setBinWidthRealUnits(value));
setHistBinWidthText();
}
}
void
MainWindow::setQaCPFromLineEdit()
{
@@ -1654,92 +1515,6 @@ MainWindow::deleteRide()
removeCurrentRide();
}
void MainWindow::setHistWidgets(RideItem *rideItem)
{
int count = 0;
assert(rideItem);
RideFile *ride = rideItem->ride;
// prevent selection from changing during reconstruction of options
disconnect(histParameterCombo, SIGNAL(currentIndexChanged(int)),
this, SLOT(setHistSelection(int)));
if (ride) {
// we want to retain the present selection
PowerHist::Selection s = powerHist->selection();
histParameterCombo->clear();
histWattsShadedID =
histWattsUnshadedID =
histNmID =
histHrID =
histKphID =
histCadID =
-1;
if (ride->areDataPresent()->watts) {
histWattsShadedID = count ++;
histParameterCombo->addItem(tr("Watts(shaded)"));
histWattsUnshadedID = count ++;
histParameterCombo->addItem(tr("Watts(unshaded)"));
}
if (ride->areDataPresent()->nm) {
histNmID = count ++;
histParameterCombo->addItem(tr("Torque"));
}
if (ride->areDataPresent()->hr) {
histHrID = count ++;
histParameterCombo->addItem(tr("Heartrate"));
}
if (ride->areDataPresent()->kph) {
histKphID = count ++;
histParameterCombo->addItem(tr("Speed"));
}
if (ride->areDataPresent()->cad) {
histCadID = count ++;
histParameterCombo->addItem(tr("Cadence"));
}
if (count > 0) {
histParameterCombo->setEnabled(true);
binWidthLineEdit->setEnabled(true);
binWidthSlider->setEnabled(true);
withZerosCheckBox->setEnabled(true);
lnYHistCheckBox->setEnabled(true);
// set widget to proper value
if ((s == PowerHist::wattsShaded) && (histWattsShadedID >= 0))
histParameterCombo->setCurrentIndex(histWattsShadedID);
else if ((s == PowerHist::wattsUnshaded) && (histWattsUnshadedID >= 0))
histParameterCombo->setCurrentIndex(histWattsUnshadedID);
else if ((s == PowerHist::nm) && (histNmID >= 0))
histParameterCombo->setCurrentIndex(histNmID);
else if ((s == PowerHist::hr) && (histHrID >= 0))
histParameterCombo->setCurrentIndex(histHrID);
else if ((s == PowerHist::kph) && (histKphID >= 0))
histParameterCombo->setCurrentIndex(histKphID);
else if ((s == PowerHist::cad) && (histCadID >= 0))
histParameterCombo->setCurrentIndex(histCadID);
else
histParameterCombo->setCurrentIndex(0);
// reconnect widget
connect(histParameterCombo, SIGNAL(currentIndexChanged(int)),
this, SLOT(setHistSelection(int)));
return;
}
}
histParameterCombo->addItem(tr("no data"));
histParameterCombo->setEnabled(false);
binWidthLineEdit->setEnabled(false);
binWidthSlider->setEnabled(false);
withZerosCheckBox->setEnabled(false);
lnYHistCheckBox->setEnabled(false);
}
/*
* This slot gets called when the user picks a new date, using the mouse,
* in the calendar. We have to adjust TreeView to match.

View File

@@ -28,8 +28,8 @@
class AllPlotWindow;
class CpintPlot;
class HistogramWindow;
class PfPvPlot;
class PowerHist;
class QwtPlotPanner;
class QwtPlotPicker;
class QwtPlotZoomer;
@@ -70,13 +70,7 @@ class MainWindow : public QMainWindow
void findBestIntervals();
void splitRide();
void deleteRide();
void setHistWidgets(RideItem *rideItem);
void cpintSetCPButtonClicked();
void setBinWidthFromSlider();
void setBinWidthFromLineEdit();
void setlnYHistFromCheckBox();
void setWithZerosFromCheckBox();
void setHistSelection(int id);
void setQaCPFromLineEdit();
void setQaCADFromLineEdit();
void setQaCLFromLineEdit();
@@ -99,8 +93,6 @@ class MainWindow : public QMainWindow
private:
bool parseRideFileName(const QString &name, QString *notesFileName, QDateTime *dt);
void setHistBinWidthText();
void setHistTextValidator();
boost::shared_ptr<QSettings> settings;
@@ -111,20 +103,15 @@ class MainWindow : public QMainWindow
QTextEdit *rideSummary;
QTextEdit *weeklySummary;
AllPlotWindow *allPlotWindow;
HistogramWindow *histogramWindow;
CpintPlot *cpintPlot;
QLineEdit *cpintTimeValue;
QLineEdit *cpintTodayValue;
QLineEdit *cpintAllValue;
QPushButton *cpintSetCPButton;
QwtPlotPicker *picker;
QSlider *binWidthSlider;
QLineEdit *binWidthLineEdit;
QCheckBox *lnYHistCheckBox;
QCheckBox *withZerosCheckBox;
QComboBox *histParameterCombo;
QCheckBox *shadeZonesPfPvCheckBox;
QTreeWidgetItem *allRides;
PowerHist *powerHist;
QwtPlot *weeklyPlot;
QwtPlotCurve *weeklyDistCurve;
QwtPlotCurve *weeklyDurationCurve;
@@ -150,14 +137,6 @@ class MainWindow : public QMainWindow
RideItem *ride; // the currently selected ride
int histWattsShadedID;
int histWattsUnshadedID;
int histNmID;
int histHrID;
int histKphID;
int histCadID;
int histAltID;
bool useMetricUnits; // whether metric units are used (or imperial)
float timebsfactor;

View File

@@ -57,6 +57,7 @@ HEADERS += \
PfPvPlot.h \
PolarRideFile.h \
PowerHist.h \
HistogramWindow.h \
RawRideFile.h \
RideFile.h \
RideItem.h \
@@ -105,6 +106,7 @@ SOURCES += \
PfPvPlot.cpp \
PolarRideFile.cpp \
PowerHist.cpp \
HistogramWindow.cpp \
RawRideFile.cpp \
RideFile.cpp \
RideItem.cpp \