Support for OAuth for the Twitter feature. Metric adjectives by Robert Carlsen.

This commit is contained in:
Justin Knotzke
2010-08-08 15:55:57 -04:00
parent f6eb97ec0f
commit 899e6eb362
10 changed files with 208 additions and 68 deletions

View File

@@ -44,14 +44,14 @@ ConfigDialog::ConfigDialog(QDir _home, Zones *_zones, MainWindow *mainWindow) :
configPage = new ConfigurationPage(mainWindow);
devicePage = new DevicePage(this);
twitterPage = new TwitterPage(this);
pagesWidget = new QStackedWidget;
pagesWidget->addWidget(configPage);
pagesWidget->addWidget(cyclistPage);
pagesWidget->addWidget(devicePage);
#ifdef GC_HAVE_LIBOAUTH
twitterPage = new TwitterPage(this);
pagesWidget->addWidget(twitterPage);
#endif
closeButton = new QPushButton(tr("Close"));
saveButton = new QPushButton(tr("Save"));
@@ -117,11 +117,13 @@ void ConfigDialog::createIcons()
realtimeButton->setTextAlignment(Qt::AlignHCenter);
realtimeButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
#ifdef GC_HAVE_LIBOAUTH
QListWidgetItem *twitterButton = new QListWidgetItem(contentsWidget);
twitterButton->setIcon(QIcon(":images/twitter.png"));
twitterButton->setText(tr("Twitter"));
twitterButton->setTextAlignment(Qt::AlignHCenter);
twitterButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
#endif
connect(contentsWidget,
SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
@@ -169,11 +171,6 @@ void ConfigDialog::save_Clicked()
settings->setValue(GC_LTS_DAYS, cyclistPage->perfManLTSavg->text());
settings->setValue(GC_SB_TODAY, (int) cyclistPage->showSBToday->isChecked());
//Save Twitter - Info PASSWORD IS IN CLEAR
settings->setValue(GC_TWITTER_USERNAME, twitterPage->accountName->text());
settings->setValue(GC_TWITTER_PASSWORD, twitterPage->passwordEdit->text());
// set default stress names if not set:
settings->setValue(GC_STS_NAME, settings->value(GC_STS_NAME,tr("Short Term Stress")));
settings->setValue(GC_STS_ACRONYM, settings->value(GC_STS_ACRONYM,tr("STS")));
@@ -188,6 +185,10 @@ void ConfigDialog::save_Clicked()
// save interval metrics and ride data pages
configPage->saveClicked();
#ifdef GC_HAVE_LIBOAUTH
//Call Twitter Save Dialog to get Access Token
twitterPage->saveClicked();
#endif
// Save the device configuration...
DeviceConfigurations all;
all.writeConfig(devicePage->deviceListModel->Configuration);

View File

@@ -950,10 +950,6 @@ MainWindow::showTreeContextMenuPopup(const QPoint &pos)
QAction *actSplitRide = new QAction(tr("Split Ride"), treeWidget);
connect(actSplitRide, SIGNAL(triggered(void)), this, SLOT(splitRide()));
QAction *actTweetRide = new QAction(tr("Tweet Ride"), treeWidget);
connect(actTweetRide, SIGNAL(triggered(void)), this, SLOT(tweetRide()));
if (rideItem->isDirty() == true) {
menu.addAction(actSaveRide);
menu.addAction(revertRide);
@@ -963,7 +959,12 @@ MainWindow::showTreeContextMenuPopup(const QPoint &pos)
menu.addAction(actBestInt);
menu.addAction(actPowerPeaks);
menu.addAction(actSplitRide);
menu.addAction(actTweetRide);
#ifdef GC_HAVE_LIBOAUTH
QAction *actTweetRide = new QAction(tr("Tweet Ride"), treeWidget);
connect(actTweetRide, SIGNAL(triggered(void)), this, SLOT(tweetRide()));
menu.addAction(actTweetRide);
#endif
menu.exec(treeWidget->mapToGlobal( pos ));
}
@@ -1482,6 +1483,7 @@ MainWindow::manualProcess(QString name)
}
}
#ifdef GC_HAVE_LIBOAUTH
void
MainWindow::tweetRide()
{
@@ -1496,4 +1498,5 @@ MainWindow::tweetRide()
twitterDialog->setWindowModality(Qt::ApplicationModal);
twitterDialog->exec();
}
#endif

View File

@@ -163,7 +163,9 @@ class MainWindow : public QMainWindow
void frontInterval();
void backInterval();
void intervalEdited(QTreeWidgetItem *, int);
#ifdef GC_HAVE_LIBOAUTH
void tweetRide();
#endif
protected:

View File

@@ -10,6 +10,8 @@
#include "ColorButton.h"
#include "SpecialFields.h"
#include <QDebug>
ConfigurationPage::ConfigurationPage(MainWindow *main) : main(main)
{
QTabWidget *tabs = new QTabWidget(this);
@@ -1819,29 +1821,94 @@ CPPage::zonesChanged()
}
}
}
#ifdef GC_HAVE_LIBOAUTH
//
// Twitter Config page
//
TwitterPage::TwitterPage(QWidget *parent) : QWidget(parent)
{
boost::shared_ptr<QSettings> settings = GetApplicationSettings();
settings = GetApplicationSettings();
QTabWidget *tabs = new QTabWidget(this);
QWidget *twitter = new QWidget(this);
tabs->addTab(twitter, tr("Twitter Config"));
QHBoxLayout *twitterlayout = new QHBoxLayout(twitter);
authorizeButton = new QPushButton(tr("Authorize"));
accountLabel = new QLabel(tr("Twitter User Name"),this);
accountName = new QLineEdit(tr(""), this);
QTextEdit *twitterInstructionsEdit = new QTextEdit(this);
twitterInstructionsEdit->setReadOnly(true);
twitterInstructionsEdit->setEnabled(false);
twitterInstructionsEdit->setPlainText(tr("Click the Authorize button. Your default browser will open to Twitter. "
"Once you have authorized Golden Cheetah access your Twitter account, "
"Copy/Paste PIN number from Twitter into PIN field. Click Save"));
twitterPinLabel = new QLabel(tr("Enter PIN: "),this);
twitterPIN = new QLineEdit(tr(""), this);
passwordLabel = new QLabel(tr("Password"),this);
passwordEdit = new QLineEdit(tr(""), this);
passwordEdit->setEchoMode(QLineEdit::Password);
twitterlayout->addWidget(accountLabel);
twitterlayout->addWidget(accountName);
twitterlayout->addWidget(passwordLabel);
twitterlayout->addWidget(passwordEdit);
accountName->setText(settings->value(GC_TWITTER_USERNAME).toString());
passwordEdit->setText(settings->value(GC_TWITTER_PASSWORD).toString());
twitterlayout->addWidget(twitterInstructionsEdit);
twitterlayout->addWidget(authorizeButton);
twitterlayout->addWidget(twitterPinLabel);
twitterlayout->addWidget(twitterPIN);
connect(authorizeButton, SIGNAL(clicked()), this, SLOT(authorizeClicked()));
}
void TwitterPage::authorizeClicked()
{
int rc;
char **rv = NULL;
QString token;
QString url = QString();
t_key = NULL;
t_secret = NULL;
const char *request_token_uri = "http://api.twitter.com/oauth/request_token";
char *req_url = NULL;
char *postarg = NULL;
char *reply = NULL;
req_url = oauth_sign_url2(request_token_uri, NULL, OA_HMAC, NULL, GC_TWITTER_CONSUMER_KEY, GC_TWITTER_CONSUMER_SECRET, NULL, NULL);
reply = oauth_http_get(req_url,postarg);
rc = oauth_split_url_parameters(reply, &rv);
qsort(rv, rc, sizeof(char *), oauth_cmpstringp);
token = QString(rv[1]);
t_key =strdup(&(rv[1][12]));
t_secret =strdup(&(rv[2][19]));
url = QString("http://api.twitter.com/oauth/authorize?");
url.append(token);
QDesktopServices::openUrl(QUrl(url));
if(rv) free(rv);
}
void TwitterPage::saveClicked()
{
char *reply;
char *req_url;
char **rv = NULL;
char *postarg = NULL;
QString url = QString("http://api.twitter.com/oauth/access_token?a=b&oauth_verifier=");
QString strPin = twitterPIN->text();
if(strPin.size() == 0)
return;
url.append(strPin);
req_url = oauth_sign_url2(url.toLatin1(), NULL, OA_HMAC, NULL, GC_TWITTER_CONSUMER_KEY, GC_TWITTER_CONSUMER_SECRET, t_key, t_secret);
reply = oauth_http_get(req_url,postarg);
int rc = oauth_split_url_parameters(reply, &rv);
if(rc ==4)
{
qsort(rv, rc, sizeof(char *), oauth_cmpstringp);
const char *oauth_token = strdup(&(rv[0][12]));
const char *oauth_secret = strdup(&(rv[1][19]));
//Save Twitter oauth_token and oauth_secret;
settings->setValue(GC_TWITTER_TOKEN, oauth_token);
settings->setValue(GC_TWITTER_SECRET, oauth_secret);
}
}
#endif

View File

@@ -23,6 +23,10 @@
#include "RideMetadata.h"
#include "DataProcessor.h"
extern "C" {
#include <oauth.h>
}
class QGroupBox;
class QHBoxLayout;
class QVBoxLayout;
@@ -402,16 +406,17 @@ class TwitterPage : public QWidget
public:
TwitterPage(QWidget *parent = 0);
void saveClicked();
// Children talk to each other
SchemePage *schemePage;
CPPage *cpPage;
QLineEdit *accountName;
QLineEdit *passwordEdit;
QLineEdit *twitterPIN;
void saveClicked();
public slots:
#ifdef GC_HAVE_LIBOAUTH
void authorizeClicked();
#endif
protected:
@@ -422,8 +427,12 @@ class TwitterPage : public QWidget
// local versions for modification
private:
QLabel *accountLabel;
QLabel *passwordLabel;
QLabel *twitterPinLabel;
QPushButton *authorizeButton;
char *t_key;
char *t_secret;
boost::shared_ptr<QSettings> settings;
};
#endif

View File

@@ -61,8 +61,6 @@
#define GC_WORKOUTDIR "workoutDir"
#define GC_TRAIN_SPLITTER_SIZES "trainwindow/splitterSizes"
#define GC_LTM_SPLITTER_SIZES "ltmwindow/splitterSizes"
#define GC_TWITTER_USERNAME "TwitterUser"
#define GC_TWITTER_PASSWORD "TwitterPass"
// device Configurations NAME/SPEC/TYPE/DEFI/DEFR all get a number appended
// to them to specify which configured device i.e. devices1 ... devicesn where
@@ -82,6 +80,12 @@
#define GC_DPFS_VARIANCE "dataprocess/fixspikes/variance"
#define GC_DPTA "dataprocess/torqueadjust/adjustment"
//Twitter oauth keys
#define GC_TWITTER_CONSUMER_KEY "qbbmhDt8bG8ZBcT3r9nYw" //< consumer key
#define GC_TWITTER_CONSUMER_SECRET "IWXu2G6mQC5xvhM8V0ohA0mPTUOqAFutiuKIva3LQg"
#define GC_TWITTER_TOKEN "twitter_token"
#define GC_TWITTER_SECRET "twitter_secret"
#include <QSettings>
#include <boost/shared_ptr.hpp>

View File

@@ -1,3 +1,21 @@
/*
* Copyright (c) 2009 Justin F. Knotzke (jknotzke@shampoo.ca)
*
* 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 "TwitterDialog.h"
#include "Settings.h"
#include <QHttp>
@@ -19,7 +37,7 @@ TwitterDialog::TwitterDialog(MainWindow *mainWindow, RideItem *item) :
timeRidingChk = new QCheckBox(tr("Time Riding"));
totalDistanceChk = new QCheckBox(tr("Total Distance"));
elevationGainChk = new QCheckBox(tr("Elevation Gain"));
totalWorkChk = new QCheckBox(tr("Total Work (kj)"));
totalWorkChk = new QCheckBox(tr("Total Work (kJ)"));
averageSpeedChk = new QCheckBox(tr("Average Speed"));
averagePowerChk = new QCheckBox(tr("Average Power"));
averageHRMChk = new QCheckBox(tr("Average Heart Rate"));
@@ -78,26 +96,26 @@ TwitterDialog::TwitterDialog(MainWindow *mainWindow, RideItem *item) :
void
TwitterDialog::tweetCurrentRide()
{
setEnabled(false);
QString twitterMsg = getTwitterMessage();
QString post = "/statuses/update.xml?status=";
QString strUrl = QUrl::toPercentEncoding(twitterMsg + " #goldencheetah");
qDebug() << post << strUrl;
QHttp *twitter_http_updater = new QHttp();
twitter_http_updater->setHost("www.twitter.com");
twitter_http_updater->setUser(settings->value(GC_TWITTER_USERNAME).toString(), settings->value(GC_TWITTER_PASSWORD).toString());
twitter_http_updater->post(post+strUrl, QByteArray());
connect(twitter_http_updater, SIGNAL(done(bool)), this, SLOT(updateTwitterStatusFinish(bool)));
}
void TwitterDialog::updateTwitterStatusFinish(bool error)
{
if(error == true)
QMessageBox::warning(this, tr("Tweeted Ride"), tr("Tweet Not Sent"));
else
QMessageBox::information(this, tr("Tweeted Ride"), tr("Tweet Sent"));
QString strToken = settings->value(GC_TWITTER_TOKEN).toString();
QString strSecret = settings->value(GC_TWITTER_SECRET).toString();
QString s_token = QString(strToken);
QString s_secret = QString(strSecret);
char *postarg = NULL;
QString qurl = "http://api.twitter.com/1/statuses/update.json?status=";
QString twitterMsg = getTwitterMessage();
const QString strUrl = QUrl::toPercentEncoding(twitterMsg + " #goldencheetah");
qurl.append(strUrl);
const char *req_url = oauth_sign_url2(qurl.toLatin1(), &postarg, OA_HMAC, NULL, GC_TWITTER_CONSUMER_KEY, GC_TWITTER_CONSUMER_SECRET, s_token.toLatin1(), s_secret.toLatin1());
oauth_http_post(req_url,postarg);
if(postarg) free(postarg);
accept();
}
QString TwitterDialog::getTwitterMessage()
@@ -127,9 +145,7 @@ QString TwitterDialog::getTwitterMessage()
if(totalDistanceChk->isChecked())
{
m = ride->metrics.value("total_distance");
tmp = round(m->value(useMetricUnits));
QString msg = QString("Total Distance: %1 " + (useMetricUnits ? tr("KM") : tr("Miles"))).arg(tmp);
qDebug() << msg;
QString msg = QString("Total Distance: %1" + (useMetricUnits ? tr("km") : tr("mi"))).arg(m->value(useMetricUnits),1,'f',1);
twitterMsg.append(msg + " ");
}
@@ -137,7 +153,7 @@ QString TwitterDialog::getTwitterMessage()
{
m = ride->metrics.value("elevation_gain");
tmp = round(m->value(useMetricUnits));
QString msg = QString("Elevation Gained: %1"+ (useMetricUnits ? tr("Meters") : tr("Feet"))).arg(tmp);
QString msg = QString("Elevation Gained: %1"+ (useMetricUnits ? tr("m") : tr("ft"))).arg(tmp);
twitterMsg.append(msg + " ");
}
@@ -145,15 +161,14 @@ QString TwitterDialog::getTwitterMessage()
{
m = ride->metrics.value("total_work");
tmp = round(m->value(true));
QString msg = QString("Total Work (kj): %1").arg(tmp);
QString msg = QString("Total Work: %1"+ tr("kJ")).arg(tmp);
twitterMsg.append(msg + " ");
}
if(averageSpeedChk->isChecked())
{
m = ride->metrics.value("average_speed");
tmp = round(m->value(useMetricUnits));
QString msg = QString("Average Speed: %1"+ (useMetricUnits ? tr("KM/H") : tr("MPH"))).arg(tmp);
QString msg = QString("Average Speed: %1"+ (useMetricUnits ? tr("km/h") : tr("mph"))).arg(m->value(useMetricUnits),1,'f',1);
twitterMsg.append(msg + " ");
}
@@ -161,7 +176,7 @@ QString TwitterDialog::getTwitterMessage()
{
m = ride->metrics.value("average_power");
tmp = round(m->value(true));
QString msg = QString("Average Power: %1 watts").arg(tmp);
QString msg = QString("Average Power: %1 "+ tr("watts")).arg(tmp);
twitterMsg.append(msg + " ");
}
@@ -169,7 +184,7 @@ QString TwitterDialog::getTwitterMessage()
{
m = ride->metrics.value("average_hr");
tmp = round(m->value(true));
QString msg = QString("Average Heart Rate: %1").arg(tmp);
QString msg = QString("Average Heart Rate: %1"+ tr("bpm")).arg(tmp);
twitterMsg.append(msg + " ");
}
@@ -177,7 +192,7 @@ QString TwitterDialog::getTwitterMessage()
{
m = ride->metrics.value("average_cad");
tmp = round(m->value(true));
QString msg = QString("Average Cadence: %1").arg(tmp);
QString msg = QString("Average Cadence: %1"+ tr("rpm")).arg(tmp);
twitterMsg.append(msg + " ");
}
@@ -185,7 +200,7 @@ QString TwitterDialog::getTwitterMessage()
{
m = ride->metrics.value("max_power");
tmp = round(m->value(true));
QString msg = QString("Max Power: %1 watts").arg(tmp);
QString msg = QString("Max Power: %1 "+ tr("watts")).arg(tmp);
twitterMsg.append(msg + " ");
}
@@ -193,7 +208,7 @@ QString TwitterDialog::getTwitterMessage()
{
m = ride->metrics.value("max_heartrate");
tmp = round(m->value(true));
QString msg = QString("Max Heart Rate: %1").arg(tmp);
QString msg = QString("Max Heart Rate: %1"+ tr("bpm")).arg(tmp);
twitterMsg.append(msg + " ");
}

View File

@@ -1,3 +1,21 @@
/*
* Copyright (c) 2009 Justin F. Knotzke (jknotzke@shampoo.ca)
*
* 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 TWITTERDIALOG_H
#define TWITTERDIALOG_H
@@ -5,6 +23,9 @@
#include <QtGui>
#include "MainWindow.h"
#include "RideItem.h"
extern "C" {
#include <oauth.h>
}
class TwitterDialog : public QDialog
{
@@ -15,7 +36,6 @@ public:
signals:
private slots:
void updateTwitterStatusFinish(bool error);
void onCheck(int state);
void tweetMsgChange(QString);
void tweetCurrentRide();

View File

@@ -6,6 +6,16 @@ BOOST_INSTALL = /usr/local/boost
SRMIO_INSTALL = /usr/local/srmio
D2XX_INCLUDE = /usr/local/include/D2XX
# If you want Twitter support you must install liboauth
# http://liboauth.sourceforge.net/
# Set the path to where liboauth.a was installed
# By default it will have been installed like this:
#
#LIBOAUTH_INSTALL = /usr/local
#LIBCRYPTO_INSTALL = -lcrypto
#LIBCURL_INSTALL=-lcurl
#LIBZ_INSTALL=-lz
# If you want 3D plotting, you need to install qwtplot3d
#
# http://qwtplot3d.sourceforge.net/

View File

@@ -11,6 +11,17 @@ QT += xml sql network webkit
LIBS += ../qwt/lib/libqwt.a
LIBS += -lm
!isEmpty( LIBOAUTH_INSTALL ) {
INCLUDEPATH += $${LIBOAUTH_INSTALL}/include
LIBS += $${LIBCRYPTO_INSTALL}
LIBS += $${LIBOAUTH_INSTALL}/lib/liboauth.a
LIBS += $${LIBZ_INSTALL}
LIBS += $${LIBCURL_INSTALL}
DEFINES += GC_HAVE_LIBOAUTH
SOURCES += TwitterDialog.cpp
HEADERS += TwitterDialog.h
}
!isEmpty( D2XX_INCLUDE ) {
INCLUDEPATH += $${D2XX_INCLUDE}
HEADERS += D2XX.h
@@ -171,7 +182,6 @@ HEADERS += \
TrainTabs.h \
TrainTool.h \
TrainWindow.h \
TwitterDialog.h \
Units.h \
ViewSelection.h \
WeeklySummaryWindow.h \
@@ -281,7 +291,6 @@ SOURCES += \
TrainTabs.cpp \
TrainTool.cpp \
TrainWindow.cpp \
TwitterDialog.cpp \
ViewSelection.cpp \
WeeklySummaryWindow.cpp \
WkoRideFile.cpp \