mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-13 16:18:42 +00:00
Manual patch entry by Eric Murray. Users can now enter in a manual entry based on distance or time.
This commit is contained in:
356
src/ManualRideDialog.cpp
Normal file
356
src/ManualRideDialog.cpp
Normal file
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* $Id:$
|
||||
*
|
||||
* Copyright (c) 2009 Eric Murray (ericm@lne.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 "ManualRideDialog.h"
|
||||
#include "MainWindow.h"
|
||||
#include "Settings.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <QtGui>
|
||||
#include <math.h>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
|
||||
ManualRideDialog::ManualRideDialog(MainWindow *mainWindow,
|
||||
const QDir &home, bool useMetric) :
|
||||
mainWindow(mainWindow), home(home)
|
||||
{
|
||||
useMetricUnits = useMetric;
|
||||
int row;
|
||||
|
||||
|
||||
mainWindow->getBSFactors(timeBS,distanceBS);
|
||||
|
||||
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setWindowTitle(tr("Manually Enter Ride Data"));
|
||||
|
||||
// ride date
|
||||
QLabel *manualDateLabel = new QLabel(tr("Ride date: "), this);
|
||||
dateTimeEdit = new QDateTimeEdit( QDateTime::currentDateTime(), this );
|
||||
// Wed 6/24/09 6:55 AM
|
||||
dateTimeEdit->setDisplayFormat(tr("ddd MMM d, yyyy h:mm AP"));
|
||||
|
||||
// ride length
|
||||
QLabel *manualLengthLabel = new QLabel(tr("Ride length: "), this);
|
||||
QHBoxLayout *manualLengthLayout = new QHBoxLayout;
|
||||
hrslbl = new QLabel(tr("hours"),this);
|
||||
hrslbl->setFrameStyle(QFrame::Panel | QFrame::Sunken);
|
||||
hrsentry = new QLineEdit(this);
|
||||
hrsentry->setInputMask("00");
|
||||
manualLengthLayout->addWidget(hrslbl);
|
||||
manualLengthLayout->addWidget(hrsentry);
|
||||
|
||||
minslbl = new QLabel(tr("mins"),this);
|
||||
minslbl->setFrameStyle(QFrame::Panel | QFrame::Sunken);
|
||||
minsentry = new QLineEdit(this);
|
||||
minsentry->setInputMask("00");
|
||||
manualLengthLayout->addWidget(minslbl);
|
||||
manualLengthLayout->addWidget(minsentry);
|
||||
|
||||
secslbl = new QLabel(tr("secs"),this);
|
||||
secslbl->setFrameStyle(QFrame::Panel | QFrame::Sunken);
|
||||
secsentry = new QLineEdit(this);
|
||||
secsentry->setInputMask("00");
|
||||
manualLengthLayout->addWidget(secslbl);
|
||||
manualLengthLayout->addWidget(secsentry);
|
||||
|
||||
// ride distance
|
||||
QString *DistanceString = new QString(tr("Distance "));
|
||||
if (useMetricUnits)
|
||||
DistanceString->append("(" + tr("km") + "):");
|
||||
else
|
||||
DistanceString->append("(" + tr("miles") + "):");
|
||||
|
||||
QLabel *DistanceLabel = new QLabel(*DistanceString, this);
|
||||
distanceentry = new QLineEdit(this);
|
||||
distanceentry->setInputMask("009.00");
|
||||
|
||||
// AvgHR
|
||||
QLabel *HRLabel = new QLabel(tr("Average HR: "), this);
|
||||
HRentry = new QLineEdit(this);
|
||||
HRentry->setInputMask("099");
|
||||
|
||||
// how to estimate BikeScore:
|
||||
QLabel *BSEstLabel;
|
||||
QSettings settings(GC_SETTINGS_CO, GC_SETTINGS_APP);
|
||||
QVariant BSmode = settings.value(GC_BIKESCOREMODE);
|
||||
|
||||
|
||||
estBSbyTimeButton = NULL;
|
||||
estBSbyDistButton = NULL;
|
||||
if (timeBS || distanceBS) {
|
||||
BSEstLabel = new QLabel(tr("Estimate BikeScore by: "));
|
||||
if (timeBS) {
|
||||
estBSbyTimeButton = new QRadioButton(tr("Time"));
|
||||
// default to time based unless no timeBS factor
|
||||
if (BSmode.toString() != "distance")
|
||||
estBSbyTimeButton->setDown(true);
|
||||
}
|
||||
if (distanceBS) {
|
||||
estBSbyDistButton = new QRadioButton(tr("Distance"));
|
||||
if (BSmode.toString() == "distance" || ! timeBS)
|
||||
estBSbyDistButton->setDown(true);
|
||||
}
|
||||
}
|
||||
|
||||
// BikeScore
|
||||
QLabel *ManualBSLabel = new QLabel(tr("BikeScore: "), this);
|
||||
BSentry = new QLineEdit(this);
|
||||
BSentry->setInputMask("009");
|
||||
|
||||
// buttons
|
||||
enterButton = new QPushButton(tr("&OK"), this);
|
||||
cancelButton = new QPushButton(tr("&Cancel"), this);
|
||||
|
||||
// Set up the layout:
|
||||
QGridLayout *glayout = new QGridLayout(this);
|
||||
row = 0;
|
||||
glayout->addWidget(manualDateLabel, row, 0);
|
||||
glayout->addWidget(dateTimeEdit, row, 1, 1, -1);
|
||||
row++;
|
||||
|
||||
glayout->addWidget(manualLengthLabel, row, 0);
|
||||
glayout->addLayout(manualLengthLayout,row,1,1,-1);
|
||||
row++;
|
||||
|
||||
glayout->addWidget(DistanceLabel,row,0);
|
||||
glayout->addWidget(distanceentry,row,1,1,-1);
|
||||
row++;
|
||||
|
||||
glayout->addWidget(HRLabel,row,0);
|
||||
glayout->addWidget(HRentry,row,1,1,-1);
|
||||
row++;
|
||||
|
||||
if (timeBS || distanceBS) {
|
||||
glayout->addWidget(BSEstLabel,row,0);
|
||||
if (estBSbyTimeButton)
|
||||
glayout->addWidget(estBSbyTimeButton,row,1,1,-1);
|
||||
if (estBSbyDistButton)
|
||||
glayout->addWidget(estBSbyDistButton,row,2,1,-1);
|
||||
row++;
|
||||
}
|
||||
|
||||
glayout->addWidget(ManualBSLabel,row,0);
|
||||
glayout->addWidget(BSentry,row,1,1,-1);
|
||||
row++;
|
||||
|
||||
glayout->addWidget(enterButton,row,1);
|
||||
glayout->addWidget(cancelButton,row,2);
|
||||
|
||||
this->resize(QSize(400,275));
|
||||
|
||||
connect(enterButton, SIGNAL(clicked()), this, SLOT(enterClicked()));
|
||||
connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancelClicked()));
|
||||
connect(hrsentry, SIGNAL(editingFinished()), this, SLOT(setBsEst()));
|
||||
//connect(secsentry, SIGNAL(editingFinished()), this, SLOT(setBsEst()));
|
||||
connect(minsentry, SIGNAL(editingFinished()), this, SLOT(setBsEst()));
|
||||
connect(distanceentry, SIGNAL(editingFinished()), this, SLOT(setBsEst()));
|
||||
if (estBSbyTimeButton)
|
||||
connect(estBSbyTimeButton,SIGNAL(clicked()),this, SLOT(bsEstChanged()));
|
||||
if (estBSbyDistButton)
|
||||
connect(estBSbyDistButton,SIGNAL(clicked()),this, SLOT(bsEstChanged()));
|
||||
}
|
||||
|
||||
void
|
||||
ManualRideDialog::estBSFromDistance()
|
||||
{
|
||||
// calculate distance-based BS estimate
|
||||
double bs = 0;
|
||||
bs = distanceentry->text().toFloat() * distanceBS;
|
||||
QString text = QString("%1").arg((int)bs);
|
||||
// cast to int so QLineEdit doesn't interpret "51.3" as "513"
|
||||
BSentry->clear();
|
||||
BSentry->insert(text);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ManualRideDialog::estBSFromTime()
|
||||
{
|
||||
// calculate time-based BS estimate
|
||||
double bs = 0;
|
||||
bs = ((hrsentry->text().toInt() ) +
|
||||
(minsentry->text().toInt() / 60) +
|
||||
(secsentry->text().toInt()/ 3600)) * timeBS;
|
||||
QString text = QString("%1").arg((int)bs);
|
||||
BSentry->clear();
|
||||
BSentry->insert(text);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ManualRideDialog::bsEstChanged()
|
||||
{
|
||||
if (estBSbyDistButton->isChecked()) {
|
||||
estBSFromDistance();
|
||||
}
|
||||
else {
|
||||
estBSFromTime();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ManualRideDialog::setBsEst()
|
||||
{
|
||||
if (estBSbyDistButton->isChecked()) {
|
||||
estBSFromDistance();
|
||||
}
|
||||
else {
|
||||
estBSFromTime();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ManualRideDialog::cancelClicked()
|
||||
{
|
||||
reject();
|
||||
}
|
||||
|
||||
void
|
||||
ManualRideDialog::enterClicked()
|
||||
{
|
||||
// write data to manual entry file
|
||||
|
||||
if (filename == "") {
|
||||
char tmp[32];
|
||||
|
||||
// use user's time for file:
|
||||
QDateTime lt = dateTimeEdit->dateTime().toLocalTime();
|
||||
|
||||
sprintf(tmp, "%04d_%02d_%02d_%02d_%02d_%02d.man",
|
||||
lt.date().year(), lt.date().month(),
|
||||
lt.date().day(), lt.time().hour(),
|
||||
lt.time().minute(),
|
||||
lt.time().second());
|
||||
|
||||
filename = tmp;
|
||||
filepath = home.absolutePath() + "/" + filename;
|
||||
FILE *out = fopen(filepath.toAscii().constData(), "r");
|
||||
if (out) {
|
||||
fclose(out);
|
||||
if (QMessageBox::warning(
|
||||
this,
|
||||
tr("Ride Already Downloaded"),
|
||||
tr("This ride appears to have already ")
|
||||
+ tr("been downloaded. Do you want to ")
|
||||
+ tr("download it again and overwrite ")
|
||||
+ tr("the previous download?"),
|
||||
tr("&Overwrite"), tr("&Cancel"),
|
||||
QString(), 1, 1) == 1) {
|
||||
reject();
|
||||
return ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString tmpname;
|
||||
{
|
||||
// QTemporaryFile doesn't actually close the file on .close(); it
|
||||
// closes the file when in its destructor. On Windows, we can't
|
||||
// rename an open file. So let tmp go out of scope before calling
|
||||
// rename.
|
||||
|
||||
QString tmpl = home.absoluteFilePath(".ptdl.XXXXXX");
|
||||
QTemporaryFile tmp(tmpl);
|
||||
tmp.setAutoRemove(false);
|
||||
if (!tmp.open()) {
|
||||
QMessageBox::critical(this, tr("Error"),
|
||||
tr("Failed to create temporary file ")
|
||||
+ tmpl + ": " + tmp.error());
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
QTextStream out(&tmp);
|
||||
|
||||
tmpname = tmp.fileName(); // after close(), tmp.fileName() is ""
|
||||
|
||||
/*
|
||||
* File format:
|
||||
* "manual"
|
||||
* "minutes,mph,watts,miles,hr,bikescore" # header (metric or imperial)
|
||||
* minutes,mph,watts,miles,hr,bikeScore # data
|
||||
*/
|
||||
|
||||
out << "manual\n";
|
||||
if (useMetricUnits)
|
||||
out << "minutes,kmh,watts,km,hr,bikescore\n";
|
||||
else
|
||||
out << "minutes,mph,watts,miles,hr,bikescore\n";
|
||||
|
||||
// data
|
||||
double secs = (hrsentry->text().toInt() * 3600) +
|
||||
(minsentry->text().toInt() * 60) +
|
||||
(secsentry->text().toInt());
|
||||
out << secs/60.0;
|
||||
out << ",";
|
||||
out << distanceentry->text().toFloat() / (secs / 3600.0);
|
||||
out << ",";
|
||||
out << 0.0; // watts
|
||||
out << ",";
|
||||
out << distanceentry->text().toFloat();
|
||||
out << ",";
|
||||
out << HRentry->text().toInt();
|
||||
out << ",";
|
||||
out << BSentry->text().toInt();
|
||||
out << "\n";
|
||||
|
||||
|
||||
tmp.close();
|
||||
|
||||
// QTemporaryFile initially has permissions set to 0600.
|
||||
// Make it readable by everyone.
|
||||
tmp.setPermissions(tmp.permissions()
|
||||
| QFile::ReadOwner | QFile::ReadUser
|
||||
| QFile::ReadGroup | QFile::ReadOther);
|
||||
}
|
||||
|
||||
#ifdef __WIN32__
|
||||
// Windows ::rename won't overwrite an existing file.
|
||||
if (QFile::exists(filepath)) {
|
||||
QFile old(filepath);
|
||||
if (!old.remove()) {
|
||||
QMessageBox::critical(this, tr("Error"),
|
||||
tr("Failed to remove existing file ")
|
||||
+ filepath + ": " + old.error());
|
||||
QFile::remove(tmpname);
|
||||
reject();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Use ::rename() instead of QFile::rename() to get forced overwrite.
|
||||
if (rename(QFile::encodeName(tmpname), QFile::encodeName(filepath)) < 0) {
|
||||
QMessageBox::critical(this, tr("Error"),
|
||||
tr("Failed to rename ") + tmpname + tr(" to ")
|
||||
+ filepath + ": " + strerror(errno));
|
||||
QFile::remove(tmpname);
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
|
||||
mainWindow->addRide(filename);
|
||||
accept();
|
||||
}
|
||||
|
||||
|
||||
67
src/ManualRideDialog.h
Normal file
67
src/ManualRideDialog.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Eric Murray (ericm@lne.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_ManualRideDialog_h
|
||||
#define _GC_ManualRideDialog_h 1
|
||||
|
||||
#include <QtGui>
|
||||
#include <qdatetimeedit.h>
|
||||
#include "PowerTap.h"
|
||||
|
||||
class MainWindow;
|
||||
|
||||
class ManualRideDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ManualRideDialog(MainWindow *mainWindow, const QDir &home,
|
||||
bool useMetric);
|
||||
|
||||
private slots:
|
||||
void enterClicked();
|
||||
void cancelClicked();
|
||||
void bsEstChanged();
|
||||
void setBsEst();
|
||||
|
||||
private:
|
||||
|
||||
void estBSFromDistance();
|
||||
void estBSFromTime();
|
||||
|
||||
bool useMetricUnits;
|
||||
float timeBS, distanceBS;
|
||||
MainWindow *mainWindow;
|
||||
QDir home;
|
||||
QPushButton *enterButton, *cancelButton;
|
||||
QLabel *label;
|
||||
|
||||
QLabel *hrslbl, *minslbl, *secslbl;
|
||||
QLineEdit *hrsentry, *minsentry, *secsentry;
|
||||
QLabel * distancelbl;
|
||||
QLineEdit *distanceentry;
|
||||
QLineEdit *HRentry, *BSentry;
|
||||
QDateTimeEdit *dateTimeEdit;
|
||||
QRadioButton *estBSbyTimeButton, *estBSbyDistButton;
|
||||
|
||||
QVector<unsigned char> records;
|
||||
QString filename, filepath;
|
||||
};
|
||||
|
||||
#endif // _GC_ManualRideDialog_h
|
||||
|
||||
139
src/ManualRideFile.cpp
Normal file
139
src/ManualRideFile.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Eric Murray (ericm@lne.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 "ManualRideFile.h"
|
||||
#include <QRegExp>
|
||||
#include <QTextStream>
|
||||
#include <algorithm> // for std::sort
|
||||
#include <assert.h>
|
||||
#include "math.h"
|
||||
|
||||
#define MILES_TO_KM 1.609344
|
||||
#define FEET_TO_METERS 0.3048
|
||||
|
||||
static int manualFileReaderRegistered =
|
||||
RideFileFactory::instance().registerReader("man", new ManualFileReader());
|
||||
|
||||
RideFile *ManualFileReader::openRideFile(QFile &file, QStringList &errors) const
|
||||
{
|
||||
QRegExp metricUnits("(km|kph|km/h)", Qt::CaseInsensitive);
|
||||
QRegExp englishUnits("(miles|mph|mp/h)", Qt::CaseInsensitive);
|
||||
bool metric;
|
||||
|
||||
int unitsHeader = 2;
|
||||
|
||||
/*
|
||||
* File format:
|
||||
* "manual"
|
||||
* "minutes,mph,watts,miles,hr,bikescore" # header (metric or imperial)
|
||||
* minutes,mph,watts,miles,hr,bikeScore # data
|
||||
*/
|
||||
QRegExp manualCSV("manual", Qt::CaseInsensitive);
|
||||
bool manual = false;
|
||||
|
||||
double rideSec;
|
||||
|
||||
if (!file.open(QFile::ReadOnly)) {
|
||||
errors << ("Could not open ride file: \""
|
||||
+ file.fileName() + "\"");
|
||||
return NULL;
|
||||
}
|
||||
int lineno = 1;
|
||||
QTextStream is(&file);
|
||||
RideFile *rideFile = new RideFile();
|
||||
while (!is.atEnd()) {
|
||||
// the readLine() method doesn't handle old Macintosh CR line endings
|
||||
// this workaround will load the the entire file if it has CR endings
|
||||
// then split and loop through each line
|
||||
// otherwise, there will be nothing to split and it will read each line as expected.
|
||||
QString linesIn = is.readLine();
|
||||
QStringList lines = linesIn.split('\r');
|
||||
// workaround for empty lines
|
||||
if(lines.isEmpty()) {
|
||||
lineno++;
|
||||
continue;
|
||||
}
|
||||
for (int li = 0; li < lines.size(); ++li) {
|
||||
QString line = lines[li];
|
||||
|
||||
if (lineno == 1) {
|
||||
if (manualCSV.indexIn(line) != -1) {
|
||||
manual = true;
|
||||
rideFile->setDeviceType("Manual CSV");
|
||||
++lineno;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (lineno == unitsHeader) {
|
||||
if (metricUnits.indexIn(line) != -1)
|
||||
metric = true;
|
||||
else if (englishUnits.indexIn(line) != -1)
|
||||
metric = false;
|
||||
else {
|
||||
errors << ("Can't find units in first line: \"" + line + "\"");
|
||||
delete rideFile;
|
||||
file.close();
|
||||
return NULL;
|
||||
}
|
||||
++lineno;
|
||||
continue;
|
||||
}
|
||||
// minutes,kph,watts,km,hr,bikeScore
|
||||
else if (lineno > unitsHeader) {
|
||||
double minutes,kph,watts,km,hr,bs;
|
||||
double cad, nm;
|
||||
int interval;
|
||||
minutes = line.section(',', 0, 0).toDouble();
|
||||
kph = line.section(',', 1, 1).toDouble();
|
||||
watts = line.section(',', 2, 2).toDouble();
|
||||
km = line.section(',', 3, 3).toDouble();
|
||||
hr = line.section(',', 4, 4).toDouble();
|
||||
bs = line.section(',', 5, 5).toDouble();
|
||||
if (!metric) {
|
||||
km *= MILES_TO_KM;
|
||||
kph *= MILES_TO_KM;
|
||||
}
|
||||
cad = nm = 0.0;
|
||||
interval = 0;
|
||||
|
||||
rideFile->appendPoint(minutes * 60.0, cad, hr, km,
|
||||
kph, nm, watts, interval, bs);
|
||||
|
||||
rideSec = minutes * 60.0;
|
||||
}
|
||||
++lineno;
|
||||
}
|
||||
}
|
||||
// fix recording interval at ride length:
|
||||
rideFile->setRecIntSecs(rideSec);
|
||||
|
||||
QRegExp rideTime("^.*/(\\d\\d\\d\\d)_(\\d\\d)_(\\d\\d)_"
|
||||
"(\\d\\d)_(\\d\\d)_(\\d\\d)\\.csv$");
|
||||
if (rideTime.indexIn(file.fileName()) >= 0) {
|
||||
QDateTime datetime(QDate(rideTime.cap(1).toInt(),
|
||||
rideTime.cap(2).toInt(),
|
||||
rideTime.cap(3).toInt()),
|
||||
QTime(rideTime.cap(4).toInt(),
|
||||
rideTime.cap(5).toInt(),
|
||||
rideTime.cap(6).toInt()));
|
||||
rideFile->setStartTime(datetime);
|
||||
}
|
||||
file.close();
|
||||
return rideFile;
|
||||
}
|
||||
|
||||
29
src/ManualRideFile.h
Normal file
29
src/ManualRideFile.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Eric Murray (ericm@lne.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 _ManualRideFile_h
|
||||
#define _ManualRideFile_h
|
||||
|
||||
#include "RideFile.h"
|
||||
|
||||
struct ManualFileReader : public RideFileReader {
|
||||
virtual RideFile *openRideFile(QFile &file, QStringList &errors) const;
|
||||
};
|
||||
|
||||
#endif // _ManualRideFile_h
|
||||
|
||||
Reference in New Issue
Block a user