mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-13 08:08:42 +00:00
TCX importing and Pedal Force vs. Pedal Velocity Chart from
J.T. Conklin (jtc@acorntoolworks.com).
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
#include "ChooseCyclistDialog.h"
|
||||
#include "ConfigDialog.h"
|
||||
#include "CpintPlot.h"
|
||||
#include "PfPvPlot.h"
|
||||
#include "DownloadRideDialog.h"
|
||||
#include "PowerHist.h"
|
||||
#include "RideItem.h"
|
||||
@@ -49,7 +50,7 @@
|
||||
#define MILES_PER_KM 0.62137119
|
||||
|
||||
static char *rideFileRegExp = ("^(\\d\\d\\d\\d)_(\\d\\d)_(\\d\\d)"
|
||||
"_(\\d\\d)_(\\d\\d)_(\\d\\d)\\.(raw|srm|csv)$");
|
||||
"_(\\d\\d)_(\\d\\d)_(\\d\\d)\\.(raw|srm|csv|tcx)$");
|
||||
|
||||
QString
|
||||
MainWindow::notesFileName(QString rideFileName) {
|
||||
@@ -281,6 +282,33 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
|
||||
tabWidget->addTab(window, "Power Histogram");
|
||||
|
||||
//////////////////////// Pedal Force/Velocity Plot ////////////////////////
|
||||
|
||||
window = new QWidget;
|
||||
vlayout = new QVBoxLayout;
|
||||
QHBoxLayout *qaLayout = new QHBoxLayout;
|
||||
|
||||
pfPvPlot = new PfPvPlot();
|
||||
QLabel *qaCPLabel = new QLabel(tr("CP:"), window);
|
||||
qaCPValue = new QLineEdit(QString("%1").arg(pfPvPlot->getCP()));
|
||||
QLabel *qaCadLabel = new QLabel(tr("Cadence:"), window);
|
||||
qaCadValue = new QLineEdit(QString("%1").arg(pfPvPlot->getCAD()));
|
||||
QLabel *qaClLabel = new QLabel(tr("Crank Length:"), window);
|
||||
qaClValue = new QLineEdit(QString("%1").arg(pfPvPlot->getCL()));
|
||||
qaLayout->addWidget(qaCPLabel);
|
||||
qaLayout->addWidget(qaCPValue);
|
||||
qaLayout->addWidget(qaCadLabel);
|
||||
qaLayout->addWidget(qaCadValue);
|
||||
qaLayout->addWidget(qaClLabel);
|
||||
qaLayout->addWidget(qaClValue);
|
||||
|
||||
vlayout->addWidget(pfPvPlot);
|
||||
vlayout->addLayout(qaLayout);
|
||||
window->setLayout(vlayout);
|
||||
window->show();
|
||||
|
||||
tabWidget->addTab(window, tr("PF/PV Plot"));
|
||||
|
||||
//////////////////////// Ride Notes ////////////////////////
|
||||
|
||||
rideNotes = new QTextEdit;
|
||||
@@ -316,6 +344,12 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
this, SLOT(setBinWidthFromSlider()));
|
||||
connect(binWidthLineEdit, SIGNAL(returnPressed()),
|
||||
this, SLOT(setBinWidthFromLineEdit()));
|
||||
connect(qaCPValue, SIGNAL(returnPressed()),
|
||||
this, SLOT(setQaCPFromLineEdit()));
|
||||
connect(qaCadValue, SIGNAL(returnPressed()),
|
||||
this, SLOT(setQaCADFromLineEdit()));
|
||||
connect(qaClValue, SIGNAL(returnPressed()),
|
||||
this, SLOT(setQaCLFromLineEdit()));
|
||||
connect(tabWidget, SIGNAL(currentChanged(int)),
|
||||
this, SLOT(tabChanged(int)));
|
||||
connect(rideNotes, SIGNAL(textChanged()),
|
||||
@@ -340,6 +374,8 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
SLOT(importSRM()), tr("Ctrl+I"));
|
||||
rideMenu->addAction(tr("&Import from CSV..."), this,
|
||||
SLOT (importCSV()), tr ("Ctrl+S"));
|
||||
rideMenu->addAction(tr("&Import from TCX..."), this,
|
||||
SLOT (importTCX()));
|
||||
rideMenu->addAction(tr("Find &best intervals..."), this,
|
||||
SLOT(findBestIntervals()), tr ("Ctrl+B"));
|
||||
QMenu *optionsMenu = menuBar()->addMenu(tr("&Options"));
|
||||
@@ -595,6 +631,54 @@ MainWindow::importSRM()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::importTCX()
|
||||
{
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(
|
||||
this, tr("Import SRM"), QDir::homePath(),
|
||||
tr("TCX Format (*.tcx)"));
|
||||
QStringListIterator i(fileNames);
|
||||
while (i.hasNext()) {
|
||||
QString fileName = i.next();
|
||||
QFile file(fileName);
|
||||
QStringList errors;
|
||||
RideFile *ride =
|
||||
RideFileFactory::instance().openRideFile(file, errors);
|
||||
if (!ride || !errors.empty()) {
|
||||
QString all = (ride
|
||||
? tr("Non-fatal problem(s) opening %1:")
|
||||
: tr("Fatal problem(s) opening %1:")).arg(fileName);
|
||||
QStringListIterator i(errors);
|
||||
while (i.hasNext())
|
||||
all += "\n" + i.next();
|
||||
if (ride)
|
||||
QMessageBox::warning(this, tr("Open Warning"), all);
|
||||
else {
|
||||
QMessageBox::critical(this, tr("Open Error"), all);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QChar zero = QLatin1Char('0');
|
||||
QString name = QString("%1_%2_%3_%4_%5_%6.tcx")
|
||||
.arg(ride->startTime().date().year(), 4, 10, zero)
|
||||
.arg(ride->startTime().date().month(), 2, 10, zero)
|
||||
.arg(ride->startTime().date().day(), 2, 10, zero)
|
||||
.arg(ride->startTime().time().hour(), 2, 10, zero)
|
||||
.arg(ride->startTime().time().minute(), 2, 10, zero)
|
||||
.arg(ride->startTime().time().second(), 2, 10, zero);
|
||||
|
||||
if (!file.copy(home.absolutePath() + "/" + name)) {
|
||||
QMessageBox::critical(this, tr("Copy Error"),
|
||||
tr("Couldn't copy %1").arg(fileName));
|
||||
return;
|
||||
}
|
||||
|
||||
delete ride;
|
||||
addRide(name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::findBestIntervals()
|
||||
{
|
||||
@@ -617,6 +701,8 @@ MainWindow::rideSelected()
|
||||
cpintPlot->calculate(ride->fileName, ride->dateTime);
|
||||
if (ride->ride)
|
||||
powerHist->setData(ride->ride);
|
||||
if (ride->ride)
|
||||
pfPvPlot->setData(ride->ride);
|
||||
|
||||
QDate wstart = ride->dateTime.date();
|
||||
wstart = wstart.addDays(Qt::Monday - wstart.dayOfWeek());
|
||||
@@ -875,6 +961,27 @@ MainWindow::setBinWidthFromLineEdit()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::setQaCPFromLineEdit()
|
||||
{
|
||||
int value = qaCPValue->text().toInt();
|
||||
pfPvPlot->setCP(value);
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::setQaCADFromLineEdit()
|
||||
{
|
||||
int value = qaCadValue->text().toInt();
|
||||
pfPvPlot->setCAD(value);
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::setQaCLFromLineEdit()
|
||||
{
|
||||
double value = qaClValue->text().toDouble();
|
||||
pfPvPlot->setCL(value);
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::tabChanged(int index)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
class AllPlot;
|
||||
class CpintPlot;
|
||||
class PfPvPlot;
|
||||
class PowerHist;
|
||||
class QwtPlotPanner;
|
||||
class QwtPlotPicker;
|
||||
@@ -56,11 +57,15 @@ class MainWindow : public QMainWindow
|
||||
void exportCSV();
|
||||
void importCSV();
|
||||
void importSRM();
|
||||
void importTCX();
|
||||
void findBestIntervals();
|
||||
void setSmoothingFromSlider();
|
||||
void setSmoothingFromLineEdit();
|
||||
void setBinWidthFromSlider();
|
||||
void setBinWidthFromLineEdit();
|
||||
void setQaCPFromLineEdit();
|
||||
void setQaCADFromLineEdit();
|
||||
void setQaCLFromLineEdit();
|
||||
void tabChanged(int index);
|
||||
void pickerMoved(const QPoint &);
|
||||
void aboutDialog();
|
||||
@@ -97,6 +102,12 @@ class MainWindow : public QMainWindow
|
||||
PowerHist *powerHist;
|
||||
Zones *zones;
|
||||
|
||||
// pedal force/pedal velocity scatter plot widgets
|
||||
PfPvPlot *pfPvPlot;
|
||||
QLineEdit *qaCPValue;
|
||||
QLineEdit *qaCadValue;
|
||||
QLineEdit *qaClValue;
|
||||
|
||||
QTextEdit *rideNotes;
|
||||
QString currentNotesFile;
|
||||
bool currentNotesChanged;
|
||||
|
||||
165
src/gui/PfPvPlot.cpp
Normal file
165
src/gui/PfPvPlot.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Sean C. Rhea (srhea@srhea.net),
|
||||
* J.T Conklin (jtc@acorntoolworks.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
|
||||
* 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 "PfPvPlot.h"
|
||||
#include "RideFile.h"
|
||||
#include "Settings.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <qwt_data.h>
|
||||
#include <qwt_legend.h>
|
||||
#include <qwt_plot_curve.h>
|
||||
#include <qwt_plot_marker.h>
|
||||
#include <set>
|
||||
|
||||
#define PI 3.14159
|
||||
|
||||
PfPvPlot::PfPvPlot()
|
||||
: cp_ (300),
|
||||
cad_ (85),
|
||||
cl_ (0.175)
|
||||
{
|
||||
setCanvasBackground(Qt::white);
|
||||
|
||||
setAxisTitle(yLeft, "Average Effective Pedal Force (N)");
|
||||
setAxisScale(yLeft, 0, 600);
|
||||
setAxisTitle(xBottom, "Circumferential Pedal Velocity (m/s)");
|
||||
setAxisScale(xBottom, 0, 3);
|
||||
|
||||
mX = new QwtPlotMarker();
|
||||
mX->setLineStyle(QwtPlotMarker::VLine);
|
||||
mX->attach(this);
|
||||
|
||||
mY = new QwtPlotMarker();
|
||||
mY->setLineStyle(QwtPlotMarker::HLine);
|
||||
mY->attach(this);
|
||||
|
||||
cpCurve = new QwtPlotCurve();
|
||||
cpCurve->setRenderHint(QwtPlotItem::RenderAntialiased);
|
||||
cpCurve->attach(this);
|
||||
|
||||
curve = new QwtPlotCurve();
|
||||
curve->setPen(QPen(Qt::red));
|
||||
curve->setStyle(QwtPlotCurve::Dots);
|
||||
curve->attach(this);
|
||||
|
||||
recalc();
|
||||
}
|
||||
|
||||
void
|
||||
PfPvPlot::setData(RideFile *ride)
|
||||
{
|
||||
setTitle(ride->startTime().toString(GC_DATETIME_FORMAT));
|
||||
|
||||
// due to the discrete power and cadence values returned by the
|
||||
// power meter, there will very likely be many duplicate values.
|
||||
// Rather than pass them all to the curve, use a set to strip
|
||||
// out duplicates.
|
||||
std::set<std::pair<double, double> > dataSet;
|
||||
QListIterator<RideFilePoint*> i(ride->dataPoints());
|
||||
while (i.hasNext()) {
|
||||
const RideFilePoint *p1 = i.next();
|
||||
|
||||
if (p1->watts != 0 && p1->cad != 0) {
|
||||
double aepf = (p1->watts * 60.0) / (p1->cad * cl_ * 2.0 * PI);
|
||||
double cpv = (p1->cad * cl_ * 2.0 * PI) / 60.0;
|
||||
|
||||
dataSet.insert(std::make_pair<double, double>(aepf, cpv));
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we have the set of points, transform them into the
|
||||
// QwtArrays needed to set the curve's data.
|
||||
QwtArray<double> aepfArray;
|
||||
QwtArray<double> cpvArray;
|
||||
std::set<std::pair<double, double> >::const_iterator j(dataSet.begin());
|
||||
while (j != dataSet.end()) {
|
||||
const std::pair<double, double>& dataPoint = *j;
|
||||
|
||||
aepfArray.push_back(dataPoint.first);
|
||||
cpvArray.push_back(dataPoint.second);
|
||||
|
||||
++j;
|
||||
}
|
||||
|
||||
curve->setData(cpvArray, aepfArray);
|
||||
replot();
|
||||
}
|
||||
|
||||
void
|
||||
PfPvPlot::recalc()
|
||||
{
|
||||
double cpv = (cad_ * cl_ * 2.0 * PI) / 60.0;
|
||||
mX->setXValue(cpv);
|
||||
|
||||
double aepf = (cp_ * 60.0) / (cad_ * cl_ * 2.0 * PI);
|
||||
mY->setYValue(aepf);
|
||||
|
||||
QwtArray<double> aepfArray;
|
||||
QwtArray<double> cpvArray;
|
||||
for (double cpv = 0.1; cpv <= 3.0; cpv += 0.05) {
|
||||
double aepf = cp_ / cpv;
|
||||
|
||||
aepfArray.push_back(aepf);
|
||||
cpvArray.push_back(cpv);
|
||||
}
|
||||
|
||||
cpCurve->setData(cpvArray, aepfArray);
|
||||
|
||||
replot();
|
||||
}
|
||||
|
||||
int
|
||||
PfPvPlot::getCP()
|
||||
{
|
||||
return cp_;
|
||||
}
|
||||
|
||||
void
|
||||
PfPvPlot::setCP(int cp)
|
||||
{
|
||||
cp_ = cp;
|
||||
recalc();
|
||||
}
|
||||
|
||||
int
|
||||
PfPvPlot::getCAD()
|
||||
{
|
||||
return cad_;
|
||||
}
|
||||
|
||||
void
|
||||
PfPvPlot::setCAD(int cadence)
|
||||
{
|
||||
cad_ = cadence;
|
||||
recalc();
|
||||
}
|
||||
|
||||
double
|
||||
PfPvPlot::getCL()
|
||||
{
|
||||
return cl_;
|
||||
}
|
||||
|
||||
void
|
||||
PfPvPlot::setCL(double cranklen)
|
||||
{
|
||||
cl_ = cranklen;
|
||||
recalc();
|
||||
}
|
||||
62
src/gui/PfPvPlot.h
Normal file
62
src/gui/PfPvPlot.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Sean C. Rhea (srhea@srhea.net),
|
||||
* J.T Conklin (jtc@acorntoolworks.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
|
||||
* 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_QaPlot_h
|
||||
#define _GC_QaPlot_h 1
|
||||
|
||||
#include <qwt_plot.h>
|
||||
|
||||
// forward references
|
||||
class RideFile;
|
||||
class QwtPlotCurve;
|
||||
class QwtPlotMarker;
|
||||
|
||||
class PfPvPlot : public QwtPlot
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
PfPvPlot();
|
||||
void setData(RideFile *ride);
|
||||
|
||||
int getCP();
|
||||
void setCP(int cp);
|
||||
int getCAD();
|
||||
void setCAD(int cadence);
|
||||
double getCL();
|
||||
void setCL(double cranklen);
|
||||
|
||||
public slots:
|
||||
|
||||
protected:
|
||||
void recalc();
|
||||
|
||||
QwtPlotCurve *curve;
|
||||
QwtPlotCurve *cpCurve;
|
||||
QwtPlotMarker *mX;
|
||||
QwtPlotMarker *mY;
|
||||
|
||||
int cp_;
|
||||
int cad_;
|
||||
double cl_;
|
||||
};
|
||||
|
||||
#endif // _GC_QaPlot_h
|
||||
|
||||
114
src/gui/TcxParser.cpp
Normal file
114
src/gui/TcxParser.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Sean C. Rhea (srhea@srhea.net),
|
||||
* J.T Conklin (jtc@acorntoolworks.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
|
||||
* 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 <QString>
|
||||
#include "TcxParser.h"
|
||||
|
||||
TcxParser::TcxParser (RideFile* rideFile)
|
||||
: rideFile_(rideFile)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
TcxParser::startElement( const QString&, const QString&,
|
||||
const QString& qName,
|
||||
const QXmlAttributes& qAttributes)
|
||||
{
|
||||
buf_.clear();
|
||||
|
||||
if (qName == "Activity") {
|
||||
lap_ = 0;
|
||||
} else if (qName == "Lap") {
|
||||
// Use the time of the first lap as the time of the activity.
|
||||
if (lap_ == 0) {
|
||||
start_time_ = QDateTime::fromString(qAttributes.value("StartTime"),
|
||||
Qt::ISODate);
|
||||
rideFile_->setStartTime(start_time_);
|
||||
|
||||
last_km_ = 0.0;
|
||||
last_time_ = start_time_;
|
||||
}
|
||||
|
||||
++lap_;
|
||||
} else if (qName == "Trackpoint") {
|
||||
watts_ = 0.0;
|
||||
cad_ = 0.0;
|
||||
hr_ = 0.0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool
|
||||
TcxParser::endElement( const QString&, const QString&, const QString& qName)
|
||||
{
|
||||
if (qName == "Time") {
|
||||
time_ = QDateTime::fromString(buf_, Qt::ISODate);
|
||||
}
|
||||
if (qName == "DistanceMeters") {
|
||||
km_ = buf_.toDouble() / 1000;
|
||||
} else if (qName == "Watts") {
|
||||
watts_ = buf_.toDouble();
|
||||
} else if (qName == "Value") {
|
||||
hr_ = buf_.toDouble();
|
||||
} else if (qName == "Cadence") {
|
||||
cad_ = buf_.toDouble();
|
||||
} else if (qName == "Trackpoint") {
|
||||
// compute the elapsed time and distance traveled since the
|
||||
// last recorded trackpoint
|
||||
double delta_d = km_ - last_km_;
|
||||
double delta_t = last_time_.secsTo(time_);
|
||||
|
||||
// compute speed for this trackpoint by dividing the distance
|
||||
// traveled by the elapsed time. The elapsed time will be 0.0
|
||||
// for the first trackpoint -- so set speed to 0.0 instead of
|
||||
// dividing by zero.
|
||||
double kph = ((delta_t != 0.0) ? ((delta_d / delta_t) * 3600.0) : 0.0);
|
||||
|
||||
// Don't know what to do about torque
|
||||
double nm = 0.0;
|
||||
|
||||
// Time from beginning of activity
|
||||
double secs = start_time_.secsTo(time_);
|
||||
|
||||
// Work around bug in 705 firmware where cadence and
|
||||
// power values repeat when stopped.
|
||||
if (delta_d == 0.0) {
|
||||
watts_ = 0.0;
|
||||
cad_ = 0.0;
|
||||
}
|
||||
|
||||
// Record trackpoint
|
||||
rideFile_->appendPoint(secs, cad_, hr_, km_,
|
||||
kph, nm, watts_, lap_);
|
||||
|
||||
last_km_ = km_;
|
||||
last_time_ = time_;
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool
|
||||
TcxParser::characters( const QString& str )
|
||||
{
|
||||
buf_ += str;
|
||||
return TRUE;
|
||||
}
|
||||
58
src/gui/TcxParser.h
Normal file
58
src/gui/TcxParser.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Sean C. Rhea (srhea@srhea.net),
|
||||
* J.T Conklin (jtc@acorntoolworks.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
|
||||
* 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 _TcxParser_h
|
||||
#define _TcxParser_h
|
||||
|
||||
#include "RideFile.h"
|
||||
#include <QString>
|
||||
#include <QDateTime>
|
||||
#include <QXmlDefaultHandler>
|
||||
|
||||
class TcxParser : public QXmlDefaultHandler
|
||||
{
|
||||
public:
|
||||
TcxParser(RideFile* rideFile);
|
||||
|
||||
bool startElement( const QString&, const QString&, const QString&,
|
||||
const QXmlAttributes& );
|
||||
bool endElement( const QString&, const QString&, const QString& );
|
||||
|
||||
bool characters( const QString& );
|
||||
|
||||
private:
|
||||
|
||||
RideFile* rideFile_;
|
||||
|
||||
QString buf_;
|
||||
|
||||
QDateTime start_time_;
|
||||
QDateTime last_time_;
|
||||
QDateTime time_;
|
||||
double last_km_;
|
||||
double km_;
|
||||
|
||||
int lap_;
|
||||
double watts_;
|
||||
double cad_;
|
||||
double hr_;
|
||||
};
|
||||
|
||||
#endif // _TcxParser_h
|
||||
|
||||
40
src/gui/TcxRideFile.cpp
Normal file
40
src/gui/TcxRideFile.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Sean C. Rhea (srhea@srhea.net),
|
||||
* J.T Conklin (jtc@acorntoolworks.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
|
||||
* 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 "TcxRideFile.h"
|
||||
#include "TcxParser.h"
|
||||
|
||||
static int tcxFileReaderRegistered =
|
||||
RideFileFactory::instance().registerReader("tcx", new TcxFileReader());
|
||||
|
||||
RideFile *TcxFileReader::openRideFile(QFile &file, QStringList &errors) const
|
||||
{
|
||||
(void) errors;
|
||||
RideFile *rideFile = new RideFile();
|
||||
rideFile->setRecIntSecs(1.0);
|
||||
|
||||
TcxParser handler(rideFile);
|
||||
|
||||
QXmlInputSource source (&file);
|
||||
QXmlSimpleReader reader;
|
||||
reader.setContentHandler (&handler);
|
||||
reader.parse (source);
|
||||
|
||||
return rideFile;
|
||||
}
|
||||
30
src/gui/TcxRideFile.h
Normal file
30
src/gui/TcxRideFile.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Sean C. Rhea (srhea@srhea.net),
|
||||
* J.T Conklin (jtc@acorntoolworks.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
|
||||
* 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 _TcxRideFile_h
|
||||
#define _TcxRideFile_h
|
||||
|
||||
#include "RideFile.h"
|
||||
|
||||
struct TcxFileReader : public RideFileReader {
|
||||
virtual RideFile *openRideFile(QFile &file, QStringList &errors) const;
|
||||
};
|
||||
|
||||
#endif // _TcxRideFile_h
|
||||
|
||||
@@ -51,7 +51,7 @@ cpi_files_to_update(const char *dir)
|
||||
cpi_file_info *head = NULL, *tail = NULL;
|
||||
|
||||
if (regcomp(®, "^([0-9][0-9][0-9][0-9])_([0-9][0-9])_([0-9][0-9])"
|
||||
"_([0-9][0-9])_([0-9][0-9])_([0-9][0-9])\\.(raw|srm|csv)$",
|
||||
"_([0-9][0-9])_([0-9][0-9])_([0-9][0-9])\\.(raw|srm|csv|tcx)$",
|
||||
REG_EXTENDED))
|
||||
assert(0);
|
||||
|
||||
|
||||
@@ -37,11 +37,14 @@ HEADERS += \
|
||||
RideItem.h \
|
||||
RideMetric.h \
|
||||
SrmRideFile.h \
|
||||
TcxParser.h \
|
||||
TcxRideFile.h \
|
||||
TimeUtils.h \
|
||||
Zones.h \
|
||||
Pages.h \
|
||||
ConfigDialog.h \
|
||||
cpint.h
|
||||
cpint.h \
|
||||
PfPvPlot.h
|
||||
|
||||
SOURCES += \
|
||||
AllPlot.cpp \
|
||||
@@ -62,12 +65,14 @@ SOURCES += \
|
||||
RideItem.cpp \
|
||||
RideMetric.cpp \
|
||||
SrmRideFile.cpp \
|
||||
TimeUtils.cpp \
|
||||
TcxParser.cpp \
|
||||
TcxRideFile.cpp \
|
||||
TimeUtils.cpp \
|
||||
Zones.cpp \
|
||||
Pages.cpp \
|
||||
ConfigDialog.cpp \
|
||||
cpint.cpp \
|
||||
\
|
||||
PfPvPlot.cpp \
|
||||
main.cpp
|
||||
|
||||
RESOURCES = application.qrc
|
||||
|
||||
Reference in New Issue
Block a user