mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-13 16:18:42 +00:00
Calendar Cloud Services Configuration
.. configuring calendar access was lost when refactoring the cloud account config. .. we use the cloud service framework for the config steps (Oauth/user+pass etc). .. existing code for interacting with the service in CalendarDownload.cpp and CalDAV.cpp is left untouched for now since it isn't used in many places.
This commit is contained in:
@@ -110,14 +110,12 @@ AddClass::AddClass(AddCloudWizard *parent) : QWizardPage(parent), wizard(parent)
|
||||
mapper->setMapping(p, CloudService::Measures);
|
||||
layout->addWidget(p);
|
||||
|
||||
#if 0 // DEPRECATING (?)
|
||||
// Activities
|
||||
p = new QCommandLinkButton(tr("Calendar"), tr("Sync planned workouts to WebDAV and CalDAV calendars."));
|
||||
// Calendar
|
||||
p = new QCommandLinkButton(tr("Calendar"), tr("Sync planned workouts to WebDAV and CalDAV calendars like Google Calendar."));
|
||||
p->setStyleSheet(QString("font-size: %1px;").arg(font.pointSizeF() * dpiXFactor));
|
||||
connect(p, SIGNAL(clicked()), mapper, SLOT(map()));
|
||||
mapper->setMapping(p, CloudService::Calendar);
|
||||
layout->addWidget(p);
|
||||
#endif
|
||||
|
||||
setFinalPage(false);
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ class AddAuth : public QWizardPage
|
||||
public slots:
|
||||
void initializePage();
|
||||
bool validatePage();
|
||||
int nextId() const { return wizard->cloudService->type() & CloudService::Measures ? 90 : (hasAthlete ? 25 : 30); }
|
||||
int nextId() const { return wizard->cloudService->type() & (CloudService::Measures|CloudService::Calendar) ? 90 : (hasAthlete ? 25 : 30); }
|
||||
void updateServiceSettings();
|
||||
void doAuth();
|
||||
|
||||
|
||||
@@ -58,13 +58,13 @@ class CalDAV : public QObject
|
||||
Q_OBJECT
|
||||
G_OBJECT
|
||||
|
||||
public:
|
||||
enum action { Options, PropFind, Put, Get, Events, Report, None };
|
||||
typedef enum action ActionType;
|
||||
|
||||
enum type { Standard, Google };
|
||||
enum type { Standard, Google, Webcal };
|
||||
typedef enum type CalDAVType;
|
||||
|
||||
public:
|
||||
CalDAV(Context *context);
|
||||
|
||||
public slots:
|
||||
|
||||
83
src/Cloud/CalDAVCloud.cpp
Normal file
83
src/Cloud/CalDAVCloud.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Mark Liversedge (liversedge@gmail.com)
|
||||
* 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 "CalDAVCloud.h"
|
||||
#include "Athlete.h"
|
||||
#include "Settings.h"
|
||||
#include "mvjson.h"
|
||||
#include <QByteArray>
|
||||
#include <QHttpMultiPart>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
|
||||
|
||||
#ifndef CALDAV_DEBUG
|
||||
#define CALDAV_DEBUG false
|
||||
#endif
|
||||
#ifdef Q_CC_MSVC
|
||||
#define printd(fmt, ...) do { \
|
||||
if (CALDAV_DEBUG) { \
|
||||
printf("[%s:%d %s] " fmt , __FILE__, __LINE__, \
|
||||
__FUNCTION__, __VA_ARGS__); \
|
||||
fflush(stdout); \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
#define printd(fmt, args...) \
|
||||
do { \
|
||||
if (CALDAV_DEBUG) { \
|
||||
printf("[%s:%d %s] " fmt , __FILE__, __LINE__, \
|
||||
__FUNCTION__, ##args); \
|
||||
fflush(stdout); \
|
||||
} \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
CalDAVCloud::CalDAVCloud(Context *context, CalDAV::type variant) : CloudService(context), context(context), variant(variant) {
|
||||
|
||||
// config
|
||||
if (variant == CalDAV::Google) {
|
||||
settings.insert(OAuthToken, GC_GOOGLE_CALENDAR_REFRESH_TOKEN);
|
||||
} else if (variant == CalDAV::Webcal) {
|
||||
settings.insert(URL, GC_WEBCAL_URL);
|
||||
} else {
|
||||
settings.insert(URL, GC_DVURL);
|
||||
settings.insert(Username, GC_DVUSER);
|
||||
settings.insert(Password, GC_DVPASS);
|
||||
}
|
||||
}
|
||||
|
||||
CalDAVCloud::~CalDAVCloud() {}
|
||||
|
||||
QImage CalDAVCloud::logo() const
|
||||
{
|
||||
return QImage(":images/services/google.png");
|
||||
}
|
||||
|
||||
static bool addCalDAVCloud() {
|
||||
CloudServiceFactory::instance().addService(new CalDAVCloud(NULL, CalDAV::Google));
|
||||
CloudServiceFactory::instance().addService(new CalDAVCloud(NULL, CalDAV::Standard));
|
||||
CloudServiceFactory::instance().addService(new CalDAVCloud(NULL, CalDAV::Webcal));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool add = addCalDAVCloud();
|
||||
|
||||
91
src/Cloud/CalDAVCloud.h
Normal file
91
src/Cloud/CalDAVCloud.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Mark Liversedge (liversedge@gmail.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
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Calendars are still downloaded and managed using the old code
|
||||
// See CalDAV.cpp and CalendarDownload.cpp
|
||||
//
|
||||
// This is a stub service to use the configuration framework provided
|
||||
// by the CloudService API to make it seamless for users
|
||||
//
|
||||
// As part of v4 planning development we may revisit this and refactor
|
||||
// this class to support open/read/write etc
|
||||
//
|
||||
|
||||
#ifndef GC_CalDAVCloud_h
|
||||
#define GC_CalDAVCloud_h
|
||||
|
||||
#include "CloudService.h"
|
||||
#include "CalDAV.h"
|
||||
|
||||
class QNetworkReply;
|
||||
class QNetworkAccessManager;
|
||||
|
||||
class CalDAVCloud : public CloudService {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
int type() const { return CloudService::Calendar; }
|
||||
int capabilities() const { return OAuth; }
|
||||
|
||||
QString id() const {
|
||||
switch(variant) {
|
||||
case CalDAV::Google: return "Google Calendar";
|
||||
case CalDAV::Webcal: return "Web Calendar";
|
||||
default:
|
||||
case CalDAV::Standard: return "CalDAV Calendar";
|
||||
}
|
||||
}
|
||||
|
||||
QString uiName() const {
|
||||
switch(variant) {
|
||||
case CalDAV::Google: return "Google Calendar";
|
||||
case CalDAV::Webcal: return "Web Calendar";
|
||||
default:
|
||||
case CalDAV::Standard: return "CalDAV Calendar";
|
||||
}
|
||||
}
|
||||
|
||||
QString description() const {
|
||||
switch(variant) {
|
||||
case CalDAV::Google: return tr("Google Calendar using CalDAV protocol and authenticate using Google Account");
|
||||
case CalDAV::Webcal: return tr("Web Calendar using iCal format as a web resource");
|
||||
default:
|
||||
case CalDAV::Standard: return tr("Generic CalDAV Calendar such as Apple iCloud calendar");
|
||||
}
|
||||
}
|
||||
|
||||
QImage logo() const;
|
||||
|
||||
// we can be instantiated as a generic calDAV service or a Google
|
||||
// CalDAV service. We don't have separate implementations, so at startup
|
||||
// we register one of each with the cloud service factory
|
||||
CalDAVCloud(Context *context, CalDAV::type variant);
|
||||
CloudService *clone(Context *context) { return new CalDAVCloud(context, variant); }
|
||||
~CalDAVCloud();
|
||||
|
||||
private:
|
||||
Context *context;
|
||||
CalDAV::type variant;
|
||||
|
||||
};
|
||||
#endif
|
||||
@@ -46,6 +46,7 @@ OAuthDialog::OAuthDialog(Context *context, OAuthSite site, CloudService *service
|
||||
if (service->id() == "Strava") site = this->site = STRAVA;
|
||||
if (service->id() == "Dropbox") site = this->site = DROPBOX;
|
||||
if (service->id() == "Cycling Analytics") site = this->site = CYCLING_ANALYTICS;
|
||||
if (service->id() == "Google Calendar") site = this->site = GOOGLE_CALENDAR;
|
||||
if (service->id() == "Google Drive") site = this->site = GOOGLE_DRIVE;
|
||||
if (service->id() == "University of Kent") site = this->site = KENTUNI;
|
||||
if (service->id() == "Today's Plan") site = this->site = TODAYSPLAN;
|
||||
@@ -129,6 +130,14 @@ OAuthDialog::OAuthDialog(Context *context, OAuthSite site, CloudService *service
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
|
||||
} else if (site == GOOGLE_CALENDAR) {
|
||||
// OAUTH 2.0 - Google flow for installed applications
|
||||
urlstr = QString("https://accounts.google.com/o/oauth2/auth?");
|
||||
urlstr.append("scope=https://www.googleapis.com/auth/calendar&");
|
||||
urlstr.append("redirect_uri=urn:ietf:wg:oauth:2.0:oob&");
|
||||
urlstr.append("response_type=code&");
|
||||
urlstr.append("client_id=").append(GC_GOOGLE_CALENDAR_CLIENT_ID);
|
||||
|
||||
} else if (site == GOOGLE_DRIVE) {
|
||||
|
||||
const QString scope = service->getSetting(GC_GOOGLE_DRIVE_AUTH_SCOPE, "drive.appdata").toString();
|
||||
@@ -194,7 +203,7 @@ OAuthDialog::OAuthDialog(Context *context, OAuthSite site, CloudService *service
|
||||
//
|
||||
// STEP 1: LOGIN AND AUTHORISE THE APPLICATION
|
||||
//
|
||||
if (site == DROPBOX || site == STRAVA || site == CYCLING_ANALYTICS || site == POLAR || site == SPORTTRACKS || site == GOOGLE_DRIVE || site == KENTUNI || site == TODAYSPLAN || site == WITHINGS) {
|
||||
if (site == DROPBOX || site == STRAVA || site == CYCLING_ANALYTICS || site == POLAR || site == SPORTTRACKS || site == GOOGLE_CALENDAR || site == GOOGLE_DRIVE || site == KENTUNI || site == TODAYSPLAN || site == WITHINGS) {
|
||||
|
||||
url = QUrl(urlstr);
|
||||
view->setUrl(url);
|
||||
@@ -363,7 +372,7 @@ void
|
||||
OAuthDialog::loadFinished(bool ok)
|
||||
{
|
||||
|
||||
if (site == GOOGLE_DRIVE || site == KENTUNI) {
|
||||
if (site == GOOGLE_CALENDAR || site == GOOGLE_DRIVE || site == KENTUNI) {
|
||||
|
||||
if (ok && url.toString().startsWith("https://accounts.google.com/o/oauth2/auth")) {
|
||||
|
||||
@@ -380,9 +389,15 @@ OAuthDialog::loadFinished(bool ok)
|
||||
QUrl params;
|
||||
#endif
|
||||
QString urlstr = "https://www.googleapis.com/oauth2/v3/token?";
|
||||
params.addQueryItem("client_id", GC_GOOGLE_DRIVE_CLIENT_ID);
|
||||
if (site == GOOGLE_CALENDAR) {
|
||||
params.addQueryItem("client_id", GC_GOOGLE_CALENDAR_CLIENT_ID);
|
||||
} else if (site == GOOGLE_DRIVE || site == KENTUNI) {
|
||||
params.addQueryItem("client_id", GC_GOOGLE_DRIVE_CLIENT_ID);
|
||||
}
|
||||
|
||||
if (site == GOOGLE_DRIVE || site == KENTUNI) {
|
||||
if (site == GOOGLE_CALENDAR) {
|
||||
params.addQueryItem("client_secret", GC_GOOGLE_CALENDAR_CLIENT_SECRET);
|
||||
} else if (site == GOOGLE_DRIVE || site == KENTUNI) {
|
||||
params.addQueryItem("client_secret", GC_GOOGLE_DRIVE_CLIENT_SECRET);
|
||||
}
|
||||
|
||||
@@ -481,7 +496,7 @@ OAuthDialog::networkRequestFinished(QNetworkReply *reply)
|
||||
|
||||
// if we failed to extract then we have a big problem
|
||||
// google uses a refresh token so trap for them only
|
||||
if (((site == GOOGLE_DRIVE || site == KENTUNI) && refresh_token == "") || access_token == "") {
|
||||
if (((site == GOOGLE_CALENDAR || site == GOOGLE_DRIVE || site == KENTUNI) && refresh_token == "") || access_token == "") {
|
||||
|
||||
// Something failed.
|
||||
// Only Google uses both refresh and access tokens.
|
||||
@@ -561,6 +576,16 @@ OAuthDialog::networkRequestFinished(QNetworkReply *reply)
|
||||
QMessageBox information(QMessageBox::Information, tr("Information"), info);
|
||||
information.exec();
|
||||
|
||||
} else if (site == GOOGLE_CALENDAR) {
|
||||
// remove the Google Page first
|
||||
url = QUrl("http://www.goldencheetah.org");
|
||||
view->setUrl(url);
|
||||
appsettings->setCValue(context->athlete->cyclist, GC_GOOGLE_CALENDAR_REFRESH_TOKEN, refresh_token);
|
||||
QString info = QString(tr("Google Calendar authorization was successful."));
|
||||
QMessageBox information(QMessageBox::Information,
|
||||
tr("Information"), info);
|
||||
information.exec();
|
||||
|
||||
} else if (site == KENTUNI) {
|
||||
|
||||
service->setSetting(GC_UOK_GOOGLE_DRIVE_REFRESH_TOKEN, refresh_token);
|
||||
|
||||
@@ -64,6 +64,7 @@ public:
|
||||
STRAVA,
|
||||
DROPBOX,
|
||||
CYCLING_ANALYTICS,
|
||||
GOOGLE_CALENDAR,
|
||||
GOOGLE_DRIVE,
|
||||
SPORTTRACKS,
|
||||
TODAYSPLAN,
|
||||
|
||||
@@ -49,7 +49,7 @@ ConfigDialog::ConfigDialog(QDir _home, Context *context) :
|
||||
QToolBar *head = addToolBar(tr("Options"));
|
||||
head->setMovable(false); // oops!
|
||||
|
||||
setMinimumSize(700 *dpiXFactor,650 *dpiYFactor); //changed for hidpi sizing
|
||||
setMinimumSize(800 *dpiXFactor,650 *dpiYFactor); //changed for hidpi sizing
|
||||
#endif
|
||||
|
||||
// center
|
||||
|
||||
20
src/src.pro
20
src/src.pro
@@ -720,11 +720,11 @@ HEADERS += Charts/Aerolab.h Charts/AerolabWindow.h Charts/AllPlot.h Charts/AllPl
|
||||
}
|
||||
|
||||
# cloud services
|
||||
HEADERS += Cloud/BodyMeasuresDownload.h Cloud/CalendarDownload.h Cloud/CloudService.h Cloud/LocalFileStore.h \
|
||||
Cloud/OAuthDialog.h Cloud/OAuthManager.h Cloud/TodaysPlanBodyMeasures.h Cloud/WithingsDownload.h \
|
||||
Cloud/Strava.h Cloud/CyclingAnalytics.h Cloud/RideWithGPS.h Cloud/TrainingsTageBuch.h \
|
||||
Cloud/Selfloops.h Cloud/Velohero.h Cloud/SportsPlusHealth.h Cloud/AddCloudWizard.h \
|
||||
Cloud/Withings.h Cloud/HrvMeasuresDownload.h Cloud/Xert.h
|
||||
HEADERS += Cloud/BodyMeasuresDownload.h Cloud/CalDAVCloud.h Cloud/CalendarDownload.h Cloud/CloudService.h \
|
||||
Cloud/LocalFileStore.h Cloud/OAuthDialog.h Cloud/OAuthManager.h Cloud/TodaysPlanBodyMeasures.h \
|
||||
Cloud/WithingsDownload.h Cloud/Strava.h Cloud/CyclingAnalytics.h Cloud/RideWithGPS.h \
|
||||
Cloud/TrainingsTageBuch.h Cloud/Selfloops.h Cloud/Velohero.h Cloud/SportsPlusHealth.h \
|
||||
Cloud/AddCloudWizard.h Cloud/Withings.h Cloud/HrvMeasuresDownload.h Cloud/Xert.h
|
||||
|
||||
# core data
|
||||
HEADERS += Core/Athlete.h Core/Context.h Core/DataFilter.h Core/FreeSearch.h Core/GcCalendarModel.h Core/GcUpgrade.h \
|
||||
@@ -813,11 +813,11 @@ SOURCES += Charts/Aerolab.cpp Charts/AerolabWindow.cpp Charts/AllPlot.cpp Charts
|
||||
}
|
||||
|
||||
## Cloud Services / Web resources
|
||||
SOURCES += Cloud/BodyMeasuresDownload.cpp Cloud/CalendarDownload.cpp Cloud/CloudService.cpp Cloud/LocalFileStore.cpp \
|
||||
Cloud/OAuthDialog.cpp Cloud/OAuthManager.cpp Cloud/TodaysPlanBodyMeasures.cpp Cloud/WithingsDownload.cpp \
|
||||
Cloud/Strava.cpp Cloud/CyclingAnalytics.cpp Cloud/RideWithGPS.cpp Cloud/TrainingsTageBuch.cpp \
|
||||
Cloud/Selfloops.cpp Cloud/Velohero.cpp Cloud/SportsPlusHealth.cpp Cloud/AddCloudWizard.cpp \
|
||||
Cloud/Withings.cpp Cloud/HrvMeasuresDownload.cpp Cloud/Xert.cpp
|
||||
SOURCES += Cloud/BodyMeasuresDownload.cpp Cloud/CalDAVCloud.cpp Cloud/CalendarDownload.cpp Cloud/CloudService.cpp \
|
||||
Cloud/LocalFileStore.cpp Cloud/OAuthDialog.cpp Cloud/OAuthManager.cpp Cloud/TodaysPlanBodyMeasures.cpp \
|
||||
Cloud/WithingsDownload.cpp Cloud/Strava.cpp Cloud/CyclingAnalytics.cpp Cloud/RideWithGPS.cpp \
|
||||
Cloud/TrainingsTageBuch.cpp Cloud/Selfloops.cpp Cloud/Velohero.cpp Cloud/SportsPlusHealth.cpp \
|
||||
Cloud/AddCloudWizard.cpp Cloud/Withings.cpp Cloud/HrvMeasuresDownload.cpp Cloud/Xert.cpp
|
||||
|
||||
## Core Data Structures
|
||||
SOURCES += Core/Athlete.cpp Core/Context.cpp Core/DataFilter.cpp Core/FreeSearch.cpp Core/GcUpgrade.cpp Core/IdleTimer.cpp \
|
||||
|
||||
Reference in New Issue
Block a user