Convert most of the old code for FacebookPlugin to the new System

It should still not work correctly - but the plugin should be almost
ready - I'll do some papercuts on the next few commits.

Signed-off-by: Tomaz Canabrava <tomaz.canabrava@intel.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Tomaz Canabrava 2015-11-08 10:33:29 -02:00 committed by Dirk Hohndel
parent 440423ff64
commit 70e6840d51
5 changed files with 495 additions and 1 deletions

View file

@ -1,4 +1,5 @@
set(FACEBOOK_PLUGIN_SRCS facebook_integration.cpp)
set(FACEBOOK_PLUGIN_SRCS facebook_integration.cpp facebookconnectwidget.cpp)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_library(facebook_integration SHARED ${FACEBOOK_PLUGIN_SRCS})

View file

@ -0,0 +1,328 @@
#include "facebookconnectwidget.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QNetworkCookieJar>
#include <QUrlQuery>
#include <QEventLoop>
#include <QHttpMultiPart>
#include <QSettings>
#include <QFile>
#include <QBuffer>
#include <QDebug>
#include <QMessageBox>
#include <QInputDialog>
#include <QWebView>
#include "mainwindow.h"
#include "profile-widget/profilewidget2.h"
#include "pref.h"
#include "helpers.h"
#include "ui_socialnetworksdialog.h"
#include "ui_facebookconnectwidget.h"
#if SAVE_FB_CREDENTIALS
#define GET_TXT(name, field) \
v = s.value(QString(name)); \
if (v.isValid()) \
prefs.field = strdup(v.toString().toUtf8().constData()); \
else \
prefs.field = default_prefs.field
#endif
FacebookManager *FacebookManager::instance()
{
static FacebookManager *self = new FacebookManager();
return self;
}
FacebookManager::FacebookManager(QObject *parent) : QObject(parent)
{
sync();
}
QUrl FacebookManager::connectUrl() {
return QUrl("https://www.facebook.com/dialog/oauth?"
"client_id=427722490709000"
"&redirect_uri=http://www.facebook.com/connect/login_success.html"
"&response_type=token,granted_scopes"
"&display=popup"
"&scope=publish_actions,user_photos"
);
}
bool FacebookManager::loggedIn() {
return prefs.facebook.access_token != NULL;
}
void FacebookManager::sync()
{
#if SAVE_FB_CREDENTIALS
QSettings s;
s.beginGroup("WebApps");
s.beginGroup("Facebook");
QVariant v;
GET_TXT("ConnectToken", facebook.access_token);
GET_TXT("UserId", facebook.user_id);
GET_TXT("AlbumId", facebook.album_id);
#endif
}
void FacebookManager::tryLogin(const QUrl& loginResponse)
{
QString result = loginResponse.toString();
if (!result.contains("access_token"))
return;
if (result.contains("denied_scopes=publish_actions") || result.contains("denied_scopes=user_photos")) {
qDebug() << "user did not allow us access" << result;
return;
}
int from = result.indexOf("access_token=") + strlen("access_token=");
int to = result.indexOf("&expires_in");
QString securityToken = result.mid(from, to-from);
#if SAVE_FB_CREDENTIALS
QSettings settings;
settings.beginGroup("WebApps");
settings.beginGroup("Facebook");
settings.setValue("ConnectToken", securityToken);
sync();
#else
prefs.facebook.access_token = copy_string(securityToken.toUtf8().data());
#endif
requestUserId();
sync();
emit justLoggedIn(true);
}
void FacebookManager::logout()
{
#if SAVE_FB_CREDENTIALS
QSettings settings;
settings.beginGroup("WebApps");
settings.beginGroup("Facebook");
settings.remove("ConnectToken");
settings.remove("UserId");
settings.remove("AlbumId");
sync();
#else
free(prefs.facebook.access_token);
free(prefs.facebook.album_id);
free(prefs.facebook.user_id);
prefs.facebook.access_token = NULL;
prefs.facebook.album_id = NULL;
prefs.facebook.user_id = NULL;
#endif
emit justLoggedOut(true);
}
void FacebookManager::requestAlbumId()
{
QUrl albumListUrl("https://graph.facebook.com/me/albums?access_token=" + QString(prefs.facebook.access_token));
QNetworkAccessManager *manager = new QNetworkAccessManager();
QNetworkReply *reply = manager->get(QNetworkRequest(albumListUrl));
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
#if SAVE_FB_CREDENTIALS
QSettings s;
s.beginGroup("WebApps");
s.beginGroup("Facebook");
#endif
QJsonDocument albumsDoc = QJsonDocument::fromJson(reply->readAll());
QJsonArray albumObj = albumsDoc.object().value("data").toArray();
foreach(const QJsonValue &v, albumObj){
QJsonObject obj = v.toObject();
if (obj.value("name").toString() == albumName) {
#if SAVE_FB_CREDENTIALS
s.setValue("AlbumId", obj.value("id").toString());
#else
prefs.facebook.album_id = copy_string(obj.value("id").toString().toUtf8().data());
#endif
return;
}
}
QUrlQuery params;
params.addQueryItem("name", albumName );
params.addQueryItem("description", "Subsurface Album");
params.addQueryItem("privacy", "{'value': 'SELF'}");
QNetworkRequest request(albumListUrl);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");
reply = manager->post(request, params.query().toLocal8Bit());
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
albumsDoc = QJsonDocument::fromJson(reply->readAll());
QJsonObject album = albumsDoc.object();
if (album.contains("id")) {
#if SAVE_FB_CREDENTIALS
s.setValue("AlbumId", album.value("id").toString());
#else
prefs.facebook.album_id = copy_string(album.value("id").toString().toUtf8().data());
#endif
sync();
return;
}
}
void FacebookManager::requestUserId()
{
QUrl userIdRequest("https://graph.facebook.com/me?fields=id&access_token=" + QString(prefs.facebook.access_token));
QNetworkAccessManager *getUserID = new QNetworkAccessManager();
QNetworkReply *reply = getUserID->get(QNetworkRequest(userIdRequest));
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll());
QJsonObject obj = jsonDoc.object();
if (obj.keys().contains("id")){
#if SAVE_FB_CREDENTIALS
QSettings s;
s.beginGroup("WebApps");
s.beginGroup("Facebook");
s.setValue("UserId", obj.value("id").toVariant());
#else
prefs.facebook.user_id = copy_string(obj.value("id").toString().toUtf8().data());
#endif
return;
}
}
void FacebookManager::setDesiredAlbumName(const QString& a)
{
albumName = a;
}
/* to be changed to export the currently selected dive as shown on the profile.
* Much much easier, and its also good to people do not select all the dives
* and send erroniously *all* of them to facebook. */
void FacebookManager::sendDive()
{
SocialNetworkDialog dialog(qApp->activeWindow());
if (dialog.exec() != QDialog::Accepted)
return;
setDesiredAlbumName(dialog.album());
requestAlbumId();
ProfileWidget2 *profile = MainWindow::instance()->graphics();
profile->setToolTipVisibile(false);
QPixmap pix = QPixmap::grabWidget(profile);
profile->setToolTipVisibile(true);
QByteArray bytes;
QBuffer buffer(&bytes);
buffer.open(QIODevice::WriteOnly);
pix.save(&buffer, "PNG");
QUrl url("https://graph.facebook.com/v2.2/" + QString(prefs.facebook.album_id) + "/photos?" +
"&access_token=" + QString(prefs.facebook.access_token) +
"&source=image" +
"&message=" + dialog.text().replace("&quot;", "%22"));
QNetworkAccessManager *am = new QNetworkAccessManager(this);
QNetworkRequest request(url);
QString bound="margin";
//according to rfc 1867 we need to put this string here:
QByteArray data(QString("--" + bound + "\r\n").toLocal8Bit());
data.append("Content-Disposition: form-data; name=\"action\"\r\n\r\n");
data.append("https://graph.facebook.com/v2.2/\r\n");
data.append("--" + bound + "\r\n"); //according to rfc 1867
data.append("Content-Disposition: form-data; name=\"uploaded\"; filename=\"" + QString::number(qrand()) + ".png\"\r\n"); //name of the input is "uploaded" in my form, next one is a file name.
data.append("Content-Type: image/jpeg\r\n\r\n"); //data type
data.append(bytes); //let's read the file
data.append("\r\n");
data.append("--" + bound + "--\r\n"); //closing boundary according to rfc 1867
request.setRawHeader(QString("Content-Type").toLocal8Bit(),QString("multipart/form-data; boundary=" + bound).toLocal8Bit());
request.setRawHeader(QString("Content-Length").toLocal8Bit(), QString::number(data.length()).toLocal8Bit());
QNetworkReply *reply = am->post(request,data);
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
QByteArray response = reply->readAll();
QJsonDocument jsonDoc = QJsonDocument::fromJson(response);
QJsonObject obj = jsonDoc.object();
if (obj.keys().contains("id")){
QMessageBox::information(qApp->activeWindow(),
tr("Photo upload sucessfull"),
tr("Your dive profile was updated to Facebook."),
QMessageBox::Ok);
} else {
QMessageBox::information(qApp->activeWindow(),
tr("Photo upload failed"),
tr("Your dive profile was not updated to Facebook, \n "
"please send the following to the developer. \n"
+ response),
QMessageBox::Ok);
}
}
FacebookConnectWidget::FacebookConnectWidget(QWidget *parent) : QDialog(parent), ui(new Ui::FacebookConnectWidget) {
FacebookManager *fb = FacebookManager::instance();
facebookWebView = new QWebView(this);
ui->fbWebviewContainer->layout()->addWidget(facebookWebView);
if (fb->loggedIn()) {
facebookLoggedIn();
} else {
facebookDisconnect();
}
connect(facebookWebView, &QWebView::urlChanged, fb, &FacebookManager::tryLogin);
connect(fb, &FacebookManager::justLoggedIn, this, &FacebookConnectWidget::facebookLoggedIn);
}
void FacebookConnectWidget::facebookLoggedIn()
{
ui->fbWebviewContainer->hide();
ui->fbWebviewContainer->setEnabled(false);
ui->FBLabel->setText(tr("To disconnect Subsurface from your Facebook account, use the button below"));
}
void FacebookConnectWidget::facebookDisconnect()
{
// remove the connect/disconnect button
// and instead add the login view
ui->fbWebviewContainer->show();
ui->fbWebviewContainer->setEnabled(true);
ui->FBLabel->setText(tr("To connect to Facebook, please log in. This enables Subsurface to publish dives to your timeline"));
if (facebookWebView) {
facebookWebView->page()->networkAccessManager()->setCookieJar(new QNetworkCookieJar());
facebookWebView->setUrl(FacebookManager::instance()->connectUrl());
}
}
SocialNetworkDialog::SocialNetworkDialog(QWidget* parent, Qt::WindowFlags f): QDialog(parent, f)
{
}
QString SocialNetworkDialog::name() const
{
return _name;
}
QString SocialNetworkDialog::album() const
{
return _album;
}
QString SocialNetworkDialog::text() const
{
return _text;
}

View file

@ -0,0 +1,61 @@
#ifndef FACEBOOKCONNECTWIDGET_H
#define FACEBOOKCONNECTWIDGET_H
#include <QDialog>
class QWebView;
namespace Ui {
class FacebookConnectWidget;
}
class FacebookManager : public QObject
{
Q_OBJECT
public:
static FacebookManager *instance();
void requestAlbumId();
void requestUserId();
void sync();
QUrl connectUrl();
bool loggedIn();
signals:
void justLoggedIn(bool triggererd);
void justLoggedOut(bool triggered);
public slots:
void tryLogin(const QUrl& loginResponse);
void logout();
void setDesiredAlbumName(const QString& albumName);
void sendDive();
private:
explicit FacebookManager(QObject *parent = 0);
QString albumName;
};
class FacebookConnectWidget : public QDialog {
Q_OBJECT
public:
explicit FacebookConnectWidget(QWidget* parent = 0);
void facebookLoggedIn();
void facebookDisconnect();
private:
Ui::FacebookConnectWidget *ui;
QWebView *facebookWebView;
};
class SocialNetworkDialog : public QDialog {
Q_OBJECT
public:
explicit SocialNetworkDialog(QWidget* parent = 0, Qt::WindowFlags f = 0);
QString album() const;
QString name() const;
QString text() const;
private:
QString _album;
QString _name;
QString _text;
};
#endif

View file

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FacebookConnectWidget</class>
<widget class="QDialog" name="FacebookConnectWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>835</width>
<height>698</height>
</rect>
</property>
<property name="windowTitle">
<string>Preferences</string>
</property>
<property name="windowIcon">
<iconset>
<normalon>:/subsurface-icon</normalon>
</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<layout class="QHBoxLayout" name="mainHorizontalLayout">
<item>
<widget class="QStackedWidget" name="stackedWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="facebook_page">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="fbLayout" stretch="0">
<property name="spacing">
<number>5</number>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="QLabel" name="FBLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Connect to facebook text placeholder</string>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="fbWebviewContainer" native="true">
<layout class="QVBoxLayout" name="verticalLayout_10"/>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,184 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SocialnetworksDialog</class>
<widget class="QDialog" name="SocialnetworksDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>475</width>
<height>416</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>290</x>
<y>380</y>
<width>166</width>
<height>22</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>15</y>
<width>451</width>
<height>361</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout" rowstretch="0,1,0,0,0,0,0,0,0,0,0">
<property name="leftMargin">
<number>1</number>
</property>
<property name="topMargin">
<number>1</number>
</property>
<property name="rightMargin">
<number>1</number>
</property>
<property name="bottomMargin">
<number>1</number>
</property>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>The text to the right will be posted as the description with your profile picture to Facebook. The album name is required (the profile picture will be posted to that album).</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Album</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLineEdit" name="album">
<property name="toolTip">
<string>The profile picture will be posted in this album (required)</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Include</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="date">
<property name="text">
<string>Date and time</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="duration">
<property name="text">
<string>Duration</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QCheckBox" name="Location">
<property name="text">
<string>Location</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QCheckBox" name="Divemaster">
<property name="text">
<string>Divemaster</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QCheckBox" name="Buddy">
<property name="text">
<string>Buddy</string>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QCheckBox" name="Notes">
<property name="text">
<string>Notes</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Facebook post preview</string>
</property>
</widget>
</item>
<item row="2" column="1" rowspan="9">
<widget class="QPlainTextEdit" name="text"/>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SocialnetworksDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SocialnetworksDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>