mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-13 16:18:42 +00:00
Add Strava activity download feature
This commit is contained in:
@@ -57,7 +57,8 @@
|
||||
#include "MetricAggregator.h"
|
||||
#include "SplitActivityWizard.h"
|
||||
#include "BatchExportDialog.h"
|
||||
#include "StravaDialog.h"
|
||||
#include "StravaUploadDialog.h"
|
||||
#include "StravaDownloadDialog.h"
|
||||
#include "RideWithGPSDialog.h"
|
||||
#include "TtbDialog.h"
|
||||
#include "TwitterDialog.h"
|
||||
@@ -853,6 +854,7 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
stravaAction = new QAction(tr("Upload to Strava..."), this);
|
||||
connect(stravaAction, SIGNAL(triggered(bool)), this, SLOT(uploadStrava()));
|
||||
rideMenu->addAction(stravaAction);
|
||||
rideMenu->addAction(tr("Download from Strava..."), this, SLOT(downloadStrava()));
|
||||
|
||||
rideWithGPSAction = new QAction(tr("Upload to RideWithGPS..."), this);
|
||||
connect(rideWithGPSAction, SIGNAL(triggered(bool)), this, SLOT(uploadRideWithGPSAction()));
|
||||
@@ -2143,11 +2145,18 @@ MainWindow::uploadStrava()
|
||||
RideItem *item = dynamic_cast<RideItem*>(_item);
|
||||
|
||||
if (item) { // menu is disabled anyway, but belt and braces
|
||||
StravaDialog d(this, item);
|
||||
StravaUploadDialog d(this, item);
|
||||
d.exec();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::downloadStrava()
|
||||
{
|
||||
StravaDownloadDialog d(this);
|
||||
d.exec();
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
* RideWithGPS.com
|
||||
*--------------------------------------------------------------------*/
|
||||
|
||||
@@ -284,6 +284,7 @@ class MainWindow : public QMainWindow
|
||||
void exportBatch();
|
||||
void exportMetrics();
|
||||
void uploadStrava();
|
||||
void downloadStrava();
|
||||
void uploadRideWithGPSAction();
|
||||
void uploadTtb();
|
||||
void downloadErgDB();
|
||||
|
||||
347
src/StravaDownloadDialog.cpp
Normal file
347
src/StravaDownloadDialog.cpp
Normal file
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Damien.Grauser (damien.grauser@pev-geneve.ch)
|
||||
*
|
||||
* 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 "StravaDownloadDialog.h"
|
||||
#include "Settings.h"
|
||||
#include <QHttp>
|
||||
#include <QUrl>
|
||||
#include <QScriptEngine>
|
||||
#include "TimeUtils.h"
|
||||
#include "Units.h"
|
||||
|
||||
// acccess to metrics
|
||||
#include "MetricAggregator.h"
|
||||
#include "RideMetric.h"
|
||||
#include "DBAccess.h"
|
||||
#include "RideImportWizard.h"
|
||||
#include "TcxRideFile.h"
|
||||
|
||||
|
||||
// Download a Strava activity using the Strava API V1
|
||||
// http://www.strava.com/api/v1/streams/9999
|
||||
// which returns a json string with time-series of speed, position, heartrate, etc.
|
||||
//
|
||||
// Be aware that these APIs are being deprecated.
|
||||
// The new API coming in early 2013.
|
||||
//
|
||||
// TODO work with the v3
|
||||
// http://strava.github.com/api/v3/activities/streams/
|
||||
|
||||
StravaDownloadDialog::StravaDownloadDialog(MainWindow *mainWindow) :
|
||||
mainWindow(mainWindow)
|
||||
{
|
||||
STRAVA_URL_V1 = "http://www.strava.com/api/v1/";
|
||||
STRAVA_URL_V2 = "http://www.strava.com/api/v2/";
|
||||
STRAVA_URL_V3 = "http://www.strava.com/api/v3/";
|
||||
|
||||
setWindowTitle("Strava download");
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
||||
|
||||
QGroupBox *groupBox = new QGroupBox(tr("Choose rideid to download: "));
|
||||
|
||||
QHBoxLayout *hbox = new QHBoxLayout();
|
||||
activityIdEdit = new QLineEdit();
|
||||
hbox->addWidget(activityIdEdit);
|
||||
|
||||
groupBox->setLayout(hbox);
|
||||
mainLayout->addWidget(groupBox);
|
||||
|
||||
// show progress
|
||||
QVBoxLayout *progressLayout = new QVBoxLayout;
|
||||
progressBar = new QProgressBar(this);
|
||||
progressLabel = new QLabel("", this);
|
||||
|
||||
progressLayout->addWidget(progressBar);
|
||||
progressLayout->addWidget(progressLabel);
|
||||
|
||||
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||
|
||||
downloadButton = new QPushButton(tr("&Download Ride"), this);
|
||||
buttonLayout->addWidget(downloadButton);
|
||||
|
||||
cancelButton = new QPushButton(tr("&Cancel"), this);
|
||||
buttonLayout->addStretch();
|
||||
buttonLayout->addWidget(cancelButton);
|
||||
|
||||
mainLayout->addLayout(progressLayout);
|
||||
mainLayout->addLayout(buttonLayout);
|
||||
|
||||
connect(downloadButton, SIGNAL(clicked()), this, SLOT(downloadRide()));
|
||||
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
|
||||
}
|
||||
|
||||
void
|
||||
StravaDownloadDialog::downloadRide()
|
||||
{
|
||||
activityId = activityIdEdit->text();
|
||||
|
||||
fileNames = new QStringList();
|
||||
|
||||
progressBar->setValue(5);
|
||||
count = 1;
|
||||
requestRideDetail();
|
||||
//requestListRides();
|
||||
}
|
||||
|
||||
void
|
||||
StravaDownloadDialog::requestRideDetail()
|
||||
{
|
||||
show();
|
||||
|
||||
tmp = new QTemporaryFile(mainWindow->home.absoluteFilePath(".download."+activityId+".XXXXXX.strava"));
|
||||
//QString tmpl = mainWindow->home.absoluteFilePath(".download.XXXXXX."+activityId+".strava"); //
|
||||
//tmp.setFileTemplate(tmpl);
|
||||
tmp->setAutoRemove(true);
|
||||
|
||||
if (!tmp->open()) {
|
||||
err = "Failed to create temporary file "
|
||||
+ tmp->fileName() + ": " + tmp->error();
|
||||
|
||||
return;
|
||||
}
|
||||
tmp->resize(0);
|
||||
|
||||
progressLabel->setText(tr("Get activity %1 details").arg(activityId));
|
||||
|
||||
QEventLoop eventLoop;
|
||||
QNetworkAccessManager networkMgr;
|
||||
|
||||
connect(&networkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestRideDetailFinished(QNetworkReply*)));
|
||||
connect(&networkMgr, SIGNAL(finished(QNetworkReply *)), &eventLoop, SLOT(quit()));
|
||||
|
||||
QUrl url = QUrl(STRAVA_URL_V1 + "rides/"+activityId);
|
||||
|
||||
QNetworkRequest request = QNetworkRequest(url);
|
||||
|
||||
networkMgr.get(request);
|
||||
eventLoop.exec();
|
||||
progressBar->setValue(progressBar->value()+5/count);
|
||||
}
|
||||
|
||||
void
|
||||
StravaDownloadDialog::requestRideDetailFinished(QNetworkReply *reply)
|
||||
{
|
||||
progressBar->setValue(15);
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
qDebug() << "Error from ride details " << reply->error();
|
||||
else {
|
||||
QString response = reply->readLine();
|
||||
|
||||
tmp->write(response.toAscii());
|
||||
progressBar->setValue(progressBar->value()+10/count);
|
||||
|
||||
requestDownloadRide();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StravaDownloadDialog::requestDownloadRide()
|
||||
{
|
||||
show();
|
||||
|
||||
progressLabel->setText(tr("Download activity %1").arg(activityId));
|
||||
|
||||
QEventLoop eventLoop;
|
||||
QNetworkAccessManager networkMgr;
|
||||
|
||||
connect(&networkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestDownloadRideFinished(QNetworkReply*)));
|
||||
connect(&networkMgr, SIGNAL(finished(QNetworkReply *)), &eventLoop, SLOT(quit()));
|
||||
|
||||
QUrl url = QUrl(STRAVA_URL_V1 + "streams/"+activityId);
|
||||
|
||||
QNetworkRequest request = QNetworkRequest(url);
|
||||
|
||||
networkMgr.get(request);
|
||||
eventLoop.exec();
|
||||
progressBar->setValue(progressBar->value()+20/count);
|
||||
}
|
||||
|
||||
void
|
||||
StravaDownloadDialog::requestDownloadRideFinished(QNetworkReply *reply)
|
||||
{
|
||||
progressBar->setValue(60);
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
qDebug() << "Error from upload " <<reply->error();
|
||||
else {
|
||||
QString response = reply->readLine();
|
||||
|
||||
progressBar->setValue(70);
|
||||
tmp->seek(tmp->size()-2);
|
||||
tmp->write(",\"streams\":");
|
||||
tmp->write(response.toAscii());
|
||||
tmp->write("},\"api_version\":\"1\"}");
|
||||
tmp->close();
|
||||
progressBar->setValue(progressBar->value()+60/count);
|
||||
|
||||
fileNames->append(tmp->fileName());
|
||||
|
||||
if (fileNames->count() == count) {
|
||||
close();
|
||||
RideImportWizard *import = new RideImportWizard(*fileNames, mainWindow->home, mainWindow);
|
||||
import->process();
|
||||
progressBar->setValue(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StravaDownloadDialog::okClicked()
|
||||
{
|
||||
dialog->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
StravaDownloadDialog::cancelClicked()
|
||||
{
|
||||
dialog->reject();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StravaDownloadDialog::requestLogin()
|
||||
{
|
||||
progressLabel->setText(tr("Login..."));
|
||||
progressBar->setValue(5);
|
||||
|
||||
QString username = appsettings->cvalue(mainWindow->cyclist, GC_STRUSER).toString();
|
||||
QString password = appsettings->cvalue(mainWindow->cyclist, GC_STRPASS).toString();
|
||||
|
||||
QNetworkAccessManager networkMgr;
|
||||
QEventLoop eventLoop;
|
||||
connect(&networkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestLoginFinished(QNetworkReply*)));
|
||||
connect(&networkMgr, SIGNAL(finished(QNetworkReply *)), &eventLoop, SLOT(quit()));
|
||||
|
||||
QByteArray data;
|
||||
/*data += "{\"email\": \"" + username + "\",";
|
||||
data += "\"password\": \"" + password + "\",";
|
||||
data += "\"agreed_to_terms\": \"true\"}";*/
|
||||
|
||||
QUrl params;
|
||||
|
||||
params.addQueryItem("email", username);
|
||||
params.addQueryItem("password",password);
|
||||
params.addQueryItem("agreed_to_terms", "true");
|
||||
data = params.encodedQuery();
|
||||
|
||||
QUrl url = QUrl( STRAVA_URL_V2_SSL + "/authentication/login");
|
||||
QNetworkRequest request = QNetworkRequest(url);
|
||||
//request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
|
||||
|
||||
networkMgr.post( request, data);
|
||||
eventLoop.exec();
|
||||
}
|
||||
|
||||
void
|
||||
StravaDownloadDialog::requestLoginFinished(QNetworkReply *reply)
|
||||
{
|
||||
loggedIn = false;
|
||||
|
||||
|
||||
if (reply->error() == QNetworkReply::NoError)
|
||||
{
|
||||
QString response = reply->readLine();
|
||||
|
||||
if(response.contains("token"))
|
||||
{
|
||||
QScriptValue sc;
|
||||
QScriptEngine se;
|
||||
|
||||
sc = se.evaluate("("+response+")");
|
||||
token = sc.property("token").toString();
|
||||
athleteId = sc.property("athlete").property("id").toString();
|
||||
|
||||
loggedIn = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
token = "";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
token = "";
|
||||
|
||||
#ifdef Q_OS_MACX
|
||||
#define GC_PREF tr("Golden Cheetah->Preferences")
|
||||
#else
|
||||
#define GC_PREF tr("Tools->Options")
|
||||
#endif
|
||||
QString advise = QString(tr("Please make sure to fill the Strava login info found under\n %1.")).arg(GC_PREF);
|
||||
QMessageBox err(QMessageBox::Critical, tr("Strava login Error"), advise);
|
||||
err.exec();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StravaDownloadDialog::requestListRides()
|
||||
{
|
||||
QString athleteId = "775290"; //Rica 131476
|
||||
|
||||
progressBar->setValue(0);
|
||||
progressLabel->setText(tr("Download athlete"));
|
||||
|
||||
QEventLoop eventLoop;
|
||||
QNetworkAccessManager networkMgr;
|
||||
|
||||
connect(&networkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestListRidesFinished(QNetworkReply*)));
|
||||
connect(&networkMgr, SIGNAL(finished(QNetworkReply *)), &eventLoop, SLOT(quit()));
|
||||
|
||||
QUrl url = QUrl(STRAVA_URL_V1 + "rides?athleteId="+athleteId+"&offset=147");//+"&offset=0"
|
||||
|
||||
QNetworkRequest request = QNetworkRequest(url);
|
||||
|
||||
networkMgr.get(request);
|
||||
eventLoop.exec();
|
||||
progressBar->setValue(5);
|
||||
}
|
||||
|
||||
void
|
||||
StravaDownloadDialog::requestListRidesFinished(QNetworkReply *reply)
|
||||
{
|
||||
progressBar->setValue(10);
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
qDebug() << "Error from upload " <<reply->error();
|
||||
else {
|
||||
QString response = reply->readLine();
|
||||
|
||||
QScriptValue sc;
|
||||
QScriptEngine se;
|
||||
|
||||
sc = se.evaluate("("+response+")");
|
||||
count = sc.property("rides").property("length").toInteger();
|
||||
|
||||
//count = 10;
|
||||
for(int i = 0; i < count; i++) {
|
||||
activityId = sc.property("rides").property(i).property("id").toString();
|
||||
|
||||
requestRideDetail();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
91
src/StravaDownloadDialog.h
Normal file
91
src/StravaDownloadDialog.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Damien.Grauser (damien.grauser@pev-geneve.ch)
|
||||
*
|
||||
* 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 STRAVADOWNLOADDIALOG_H
|
||||
#define STRAVADOWNLOADDIALOG_H
|
||||
#include "GoldenCheetah.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QtGui>
|
||||
#include "MainWindow.h"
|
||||
#include "RideItem.h"
|
||||
|
||||
#ifdef GC_HAVE_LIBOAUTH
|
||||
extern "C" {
|
||||
#include <oauth.h>
|
||||
}
|
||||
#endif
|
||||
|
||||
class StravaDownloadDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
G_OBJECT
|
||||
|
||||
public:
|
||||
StravaDownloadDialog(MainWindow *mainWindow);
|
||||
|
||||
private slots:
|
||||
|
||||
void requestLogin();
|
||||
void requestLoginFinished(QNetworkReply *reply);
|
||||
|
||||
void downloadRide();
|
||||
|
||||
void requestRideDetail();
|
||||
void requestRideDetailFinished(QNetworkReply *reply);
|
||||
|
||||
void requestDownloadRide();
|
||||
void requestDownloadRideFinished(QNetworkReply *reply);
|
||||
|
||||
void requestListRides();
|
||||
void requestListRidesFinished(QNetworkReply *reply);
|
||||
|
||||
void okClicked();
|
||||
void cancelClicked();
|
||||
|
||||
private:
|
||||
QDialog *dialog;
|
||||
|
||||
QLineEdit *activityIdEdit;
|
||||
|
||||
QPushButton *downloadButton;
|
||||
QPushButton *cancelButton;
|
||||
MainWindow *mainWindow;
|
||||
|
||||
QProgressBar *progressBar;
|
||||
QLabel *progressLabel;
|
||||
|
||||
QTemporaryFile *tmp;
|
||||
QStringList *fileNames;
|
||||
RideFile *rideFile;
|
||||
|
||||
int count;
|
||||
|
||||
QString athleteId;
|
||||
QString token;
|
||||
QString activityId;
|
||||
|
||||
QString err;
|
||||
QString STRAVA_URL_V1,
|
||||
STRAVA_URL_V2, STRAVA_URL_V2_SSL,
|
||||
STRAVA_URL_V3;
|
||||
|
||||
bool loggedIn;
|
||||
};
|
||||
|
||||
#endif // STRAVADOWNLOADDIALOG_H
|
||||
108
src/StravaParser.cpp
Normal file
108
src/StravaParser.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Damien.Grauser (damien.grauser@pev-geneve.ch)
|
||||
*
|
||||
* 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 <QScriptEngine>
|
||||
|
||||
#include "StravaParser.h"
|
||||
#include "TimeUtils.h"
|
||||
#include "Units.h"
|
||||
|
||||
StravaParser::StravaParser (RideFile* rideFile, QFile* file)
|
||||
: rideFile(rideFile), file(file)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
StravaParser::parse()
|
||||
{
|
||||
if (!file->open(QIODevice::ReadOnly)) {
|
||||
delete rideFile;
|
||||
return;
|
||||
}
|
||||
|
||||
QScriptValue sc;
|
||||
QScriptEngine se;
|
||||
|
||||
QByteArray content = file->readAll();
|
||||
|
||||
sc = se.evaluate("("+content+")");
|
||||
|
||||
if (sc.isError()) {
|
||||
delete rideFile;
|
||||
return;
|
||||
}
|
||||
|
||||
QScriptValue ride = sc.property("ride");
|
||||
|
||||
if (!ride.isNull()) {
|
||||
rideFile->setRecIntSecs(1.0);
|
||||
rideFile->setDeviceType("Strava activity");
|
||||
rideFile->setFileFormat("Strava activity streams (strava)");
|
||||
|
||||
QDateTime datetime = QDateTime::fromString(ride.property("startDateLocal").toString(), Qt::ISODate);
|
||||
rideFile->setStartTime(datetime);
|
||||
|
||||
rideFile->setTag("Notes", ride.property("location").toString());
|
||||
|
||||
QScriptValue streams = ride.property("streams");
|
||||
|
||||
int length = streams.property("time").property("length").toInteger();
|
||||
|
||||
bool hasHeartrate = (streams.property("heartrate").property("length").toInteger()>0);
|
||||
bool hasVelocity = (streams.property("velocity_smooth").property("length").toInteger()>0);
|
||||
bool hasDistance = (streams.property("distance").property("length").toInteger()>0);
|
||||
bool hasCadence = (streams.property("cadence").property("length").toInteger()>0);
|
||||
bool hasAltitude = (streams.property("altitude").property("length").toInteger()>0);
|
||||
bool hasLatLng = (streams.property("latlng").property("length").toInteger()>0);
|
||||
bool hasWatts = (streams.property("watts").property("length").toInteger()>0);
|
||||
bool hasTemp = (streams.property("temp").property("length").toInteger()>0);
|
||||
|
||||
for(int i = 0; i < length; i++) {
|
||||
RideFilePoint point;
|
||||
|
||||
point.secs = streams.property("time").property(i).toNumber();
|
||||
if (hasDistance)
|
||||
point.km = streams.property("distance").property(i).toNumber()/1000.0;
|
||||
if (hasVelocity)
|
||||
point.kph = streams.property("velocity_smooth").property(i).toNumber()*3.6;
|
||||
if (hasHeartrate)
|
||||
point.hr = streams.property("heartrate").property(i).toNumber();
|
||||
if (hasCadence)
|
||||
point.cad = streams.property("cadence").property(i).toNumber();
|
||||
if (hasAltitude)
|
||||
point.alt = streams.property("altitude").property(i).toNumber();
|
||||
if (hasLatLng) {
|
||||
point.lat = streams.property("latlng").property(i).property(0).toNumber();
|
||||
point.lon = streams.property("latlng").property(i).property(1).toNumber();
|
||||
}
|
||||
if (hasWatts)
|
||||
point.watts = streams.property("watts").property(i).toNumber();
|
||||
if (hasTemp)
|
||||
point.temp = streams.property("temp").property(i).toNumber();
|
||||
|
||||
rideFile->appendPoint(point.secs, point.cad, point.hr, point.km,
|
||||
point.kph, point.nm, point.watts, point.alt,
|
||||
point.lon, point.lat, point.headwind,
|
||||
point.slope, point.temp, point.lrbalance, point.interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
41
src/StravaParser.h
Normal file
41
src/StravaParser.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Damien.Grauser (damien.grauser@pev-geneve.ch)
|
||||
*
|
||||
* 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 _StravaParser_h
|
||||
#define _StravaParser_h
|
||||
|
||||
#include "RideFile.h"
|
||||
#include <QString>
|
||||
#include <QDateTime>
|
||||
#include <QXmlDefaultHandler>
|
||||
|
||||
class StravaParser : public QXmlDefaultHandler
|
||||
{
|
||||
public:
|
||||
StravaParser(RideFile* rideFile, QFile* file);
|
||||
|
||||
void parse();
|
||||
|
||||
private:
|
||||
RideFile* rideFile;
|
||||
QFile* file;
|
||||
|
||||
};
|
||||
|
||||
#endif // _StravaParser_h
|
||||
|
||||
37
src/StravaRideFile.cpp
Normal file
37
src/StravaRideFile.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Damien.Grauser (damien.grauser@pev-geneve.ch)
|
||||
*
|
||||
* 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 "StravaRideFile.h"
|
||||
#include "StravaParser.h"
|
||||
|
||||
static int stravaFileReaderRegistered =
|
||||
RideFileFactory::instance().registerReader(
|
||||
"strava", "Strava activity streams", new StravaFileReader());
|
||||
|
||||
RideFile *StravaFileReader::openRideFile(QFile &file, QStringList &errors, QList<RideFile*>*) const
|
||||
{
|
||||
(void) errors;
|
||||
RideFile *rideFile = new RideFile();
|
||||
rideFile->setDeviceType("Strava activity");
|
||||
rideFile->setFileFormat("Strava activity streams (strava)");
|
||||
|
||||
StravaParser parser(rideFile, &file);
|
||||
parser.parse();
|
||||
|
||||
return rideFile;
|
||||
}
|
||||
30
src/StravaRideFile.h
Normal file
30
src/StravaRideFile.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Damien.Grauser (damien.grauser@pev-geneve.ch)
|
||||
*
|
||||
* 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 _StravaRideFile_h
|
||||
#define _StravaRideFile_h
|
||||
|
||||
#include "RideFile.h"
|
||||
|
||||
struct StravaFileReader : public RideFileReader {
|
||||
virtual RideFile *openRideFile(QFile &file, QStringList &errors, QList<RideFile*>* = 0) const;
|
||||
bool hasWrite() const { return false; }
|
||||
};
|
||||
|
||||
#endif // _StravaRideFile_h
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Justin F. Knotzke (jknotzke@shampoo.ca),
|
||||
* Damien.Grauser (damien.grauser@pev-geneve.ch)
|
||||
* Copyright (c) 2011-2013 Justin F. Knotzke (jknotzke@shampoo.ca),
|
||||
* Damien.Grauser (damien.grauser@pev-geneve.ch)
|
||||
*
|
||||
* 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
|
||||
@@ -17,7 +17,7 @@
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "StravaDialog.h"
|
||||
#include "StravaUploadDialog.h"
|
||||
#include "Settings.h"
|
||||
#include <QHttp>
|
||||
#include <QUrl>
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "DBAccess.h"
|
||||
#include "TcxRideFile.h"
|
||||
|
||||
StravaDialog::StravaDialog(MainWindow *mainWindow, RideItem *item) :
|
||||
StravaUploadDialog::StravaUploadDialog(MainWindow *mainWindow, RideItem *item) :
|
||||
mainWindow(mainWindow)
|
||||
{
|
||||
STRAVA_URL1 = "http://www.strava.com/api/v1/";
|
||||
@@ -112,7 +112,7 @@ StravaDialog::StravaDialog(MainWindow *mainWindow, RideItem *item) :
|
||||
|
||||
|
||||
void
|
||||
StravaDialog::uploadToStrava()
|
||||
StravaUploadDialog::uploadToStrava()
|
||||
{
|
||||
show();
|
||||
overwrite = true;
|
||||
@@ -173,7 +173,7 @@ StravaDialog::uploadToStrava()
|
||||
}
|
||||
|
||||
void
|
||||
StravaDialog::getActivityFromStrava()
|
||||
StravaUploadDialog::getActivityFromStrava()
|
||||
{
|
||||
if (token.length()==0)
|
||||
requestLogin();
|
||||
@@ -196,14 +196,14 @@ StravaDialog::getActivityFromStrava()
|
||||
}
|
||||
|
||||
void
|
||||
StravaDialog::okClicked()
|
||||
StravaUploadDialog::okClicked()
|
||||
{
|
||||
dialog->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
StravaDialog::cancelClicked()
|
||||
StravaUploadDialog::cancelClicked()
|
||||
{
|
||||
dialog->reject();
|
||||
return;
|
||||
@@ -211,7 +211,7 @@ StravaDialog::cancelClicked()
|
||||
|
||||
|
||||
void
|
||||
StravaDialog::requestLogin()
|
||||
StravaUploadDialog::requestLogin()
|
||||
{
|
||||
progressLabel->setText(tr("Login..."));
|
||||
progressBar->setValue(5);
|
||||
@@ -247,7 +247,7 @@ StravaDialog::requestLogin()
|
||||
}
|
||||
|
||||
void
|
||||
StravaDialog::requestLoginFinished(QNetworkReply *reply)
|
||||
StravaUploadDialog::requestLoginFinished(QNetworkReply *reply)
|
||||
{
|
||||
loggedIn = false;
|
||||
|
||||
@@ -294,7 +294,7 @@ StravaDialog::requestLoginFinished(QNetworkReply *reply)
|
||||
// https://strava.pbworks.com/w/page/39241255/v2%20upload%20create
|
||||
|
||||
void
|
||||
StravaDialog::requestUpload()
|
||||
StravaUploadDialog::requestUpload()
|
||||
{
|
||||
progressLabel->setText(tr("Upload ride..."));
|
||||
progressBar->setValue(10);
|
||||
@@ -393,7 +393,7 @@ StravaDialog::requestUpload()
|
||||
}
|
||||
|
||||
void
|
||||
StravaDialog::requestUploadFinished(QNetworkReply *reply)
|
||||
StravaUploadDialog::requestUploadFinished(QNetworkReply *reply)
|
||||
{
|
||||
progressBar->setValue(90);
|
||||
progressLabel->setText(tr("Upload finished."));
|
||||
@@ -425,7 +425,7 @@ StravaDialog::requestUploadFinished(QNetworkReply *reply)
|
||||
}
|
||||
|
||||
void
|
||||
StravaDialog::requestVerifyUpload()
|
||||
StravaUploadDialog::requestVerifyUpload()
|
||||
{
|
||||
progressBar->setValue(0);
|
||||
progressLabel->setText(tr("Ride processing..."));
|
||||
@@ -447,7 +447,7 @@ StravaDialog::requestVerifyUpload()
|
||||
}
|
||||
|
||||
void
|
||||
StravaDialog::requestVerifyUploadFinished(QNetworkReply *reply)
|
||||
StravaUploadDialog::requestVerifyUploadFinished(QNetworkReply *reply)
|
||||
{
|
||||
uploadSuccessful = false;
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
@@ -496,7 +496,7 @@ StravaDialog::requestVerifyUploadFinished(QNetworkReply *reply)
|
||||
}
|
||||
|
||||
void
|
||||
StravaDialog::requestSearchRide()
|
||||
StravaUploadDialog::requestSearchRide()
|
||||
{
|
||||
progressBar->setValue(0);
|
||||
progressLabel->setText(tr("Searching corresponding Ride"));
|
||||
@@ -519,7 +519,7 @@ StravaDialog::requestSearchRide()
|
||||
}
|
||||
|
||||
void
|
||||
StravaDialog::requestSearchRideFinished(QNetworkReply *reply)
|
||||
StravaUploadDialog::requestSearchRideFinished(QNetworkReply *reply)
|
||||
{
|
||||
uploadSuccessful = false;
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Damien.Grauser (damien.grauser@pev-geneve.ch)
|
||||
* Copyright (c) 2011-2013 Damien.Grauser (damien.grauser@pev-geneve.ch)
|
||||
*
|
||||
* 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
|
||||
@@ -16,8 +16,8 @@
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef STRAVADIALOG_H
|
||||
#define STRAVADIALOG_H
|
||||
#ifndef STRAVAUPLOADDIALOG_H
|
||||
#define STRAVAUPLOADDIALOG_H
|
||||
#include "GoldenCheetah.h"
|
||||
|
||||
#include <QObject>
|
||||
@@ -31,13 +31,13 @@ extern "C" {
|
||||
}
|
||||
#endif
|
||||
|
||||
class StravaDialog : public QDialog
|
||||
class StravaUploadDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
G_OBJECT
|
||||
|
||||
public:
|
||||
StravaDialog(MainWindow *mainWindow, RideItem *item);
|
||||
StravaUploadDialog(MainWindow *mainWindow, RideItem *item);
|
||||
|
||||
signals:
|
||||
|
||||
@@ -96,4 +96,4 @@ private:
|
||||
bool overwrite, loggedIn, uploadSuccessful;
|
||||
};
|
||||
|
||||
#endif // STRAVADIALOG_H
|
||||
#endif // STRAVAUPLOADDIALOG_H
|
||||
10
src/src.pro
10
src/src.pro
@@ -372,7 +372,10 @@ HEADERS += \
|
||||
SmfRideFile.h \
|
||||
SrdRideFile.h \
|
||||
SrmRideFile.h \
|
||||
StravaDialog.h \
|
||||
StravaDownloadDialog.h \
|
||||
StravaParser.h \
|
||||
StravaRideFile.h \
|
||||
StravaUploadDialog.h \
|
||||
StressCalculator.h \
|
||||
SummaryMetrics.h \
|
||||
SummaryWindow.h \
|
||||
@@ -558,7 +561,10 @@ SOURCES += \
|
||||
SmfRideFile.cpp \
|
||||
SrdRideFile.cpp \
|
||||
SrmRideFile.cpp \
|
||||
StravaDialog.cpp \
|
||||
StravaDownloadDialog.cpp \
|
||||
StravaParser.cpp \
|
||||
StravaRideFile.cpp \
|
||||
StravaUploadDialog.cpp \
|
||||
StressCalculator.cpp \
|
||||
SummaryMetrics.cpp \
|
||||
SummaryWindow.cpp \
|
||||
|
||||
Reference in New Issue
Block a user