Browse Source

v2 changes

gwillz 5 years ago
commit
cb9cc450ef
21 changed files with 1246 additions and 0 deletions
  1. 222 0
      .gitignore
  2. 37 0
      FBSlideshow.pro
  3. 36 0
      PKGBUILD
  4. 9 0
      PhotoBunny.desktop
  5. BIN
      black.png
  6. 14 0
      common.h
  7. 153 0
      dialogs.cpp
  8. 72 0
      dialogs.h
  9. 246 0
      fbApi.cpp
  10. 76 0
      fbApi.h
  11. BIN
      homepage.png
  12. BIN
      homepage.psd
  13. 90 0
      install.nsi
  14. 60 0
      main.cpp
  15. 1 0
      res.rc
  16. 7 0
      resources.qrc
  17. BIN
      silhouette-bunny.ico
  18. BIN
      silhouette-bunny.png
  19. 154 0
      slidewindow.cpp
  20. 48 0
      slidewindow.h
  21. 21 0
      version.h

+ 222 - 0
.gitignore

@@ -0,0 +1,222 @@
+#################
+## Eclipse
+#################
+
+*.pydevproject
+.project
+.metadata
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.classpath
+.settings/
+.loadpath
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# CDT-specific
+.cproject
+
+# PDT-specific
+.buildpath
+
+
+#################
+## Visual Studio
+#################
+
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.sln.docstates
+
+# Build results
+
+[Dd]ebug/
+[Rr]elease/
+x64/
+build/
+[Bb]in/
+[Oo]bj/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+*_i.c
+*_p.c
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.log
+*.scc
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+*.ncrunch*
+.*crunch*.local.xml
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.Publish.xml
+*.pubxml
+
+# NuGet Packages Directory
+## TODO: If you have NuGet Package Restore enabled, uncomment the next line
+#packages/
+
+# Windows Azure Build Output
+csx
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Others
+sql/
+*.Cache
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.[Pp]ublish.xml
+*.pfx
+*.publishsettings
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file to a newer
+# Visual Studio version. Backup files are not needed, because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+App_Data/*.mdf
+App_Data/*.ldf
+
+#############
+## Windows detritus
+#############
+
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Mac crap
+.DS_Store
+
+
+#############
+## Python
+#############
+
+*.py[co]
+
+# Packages
+*.egg
+*.egg-info
+dist/
+build/
+eggs/
+parts/
+var/
+sdist/
+develop-eggs/
+.installed.cfg
+
+# Installer logs
+pip-log.txt
+
+# Unit test / coverage reports
+.coverage
+.tox
+
+#Translations
+*.mo
+
+#Mr Developer
+.mr.developer.cfg
+*.pub
+*.xls
+*.pdf
+
+*master*
+src/
+pkg/

+ 37 - 0
FBSlideshow.pro

@@ -0,0 +1,37 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2014-02-28T13:55:57
+#
+#-------------------------------------------------
+
+QT      += core gui network webkit
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets webkitwidgets
+
+TARGET = photobunny
+TEMPLATE = app
+
+SOURCES += main.cpp\
+           slidewindow.cpp \
+           fbApi.cpp \
+           dialogs.cpp
+
+HEADERS  += slidewindow.h \
+            fbApi.h \
+            dialogs.h \
+    common.h
+
+RESOURCES += \
+            resources.qrc
+
+#platform specific stuff
+linux-g++* {
+    LIBS += /usr/lib/libqjson.so
+}
+
+win32 {
+    RC_FILE = res.rc
+    HEADERS += version.h
+    LIBS += D:/Documents/Programs/FBSlideshow/qjson/qjson.lib
+    INCLUDEPATH += D:/Documents/Programs/FBSlideshow/qjson/
+}

+ 36 - 0
PKGBUILD

@@ -0,0 +1,36 @@
+# Maintainer: Gwilyn Saunders <gwillz@internode.on.net>
+pkgname="photobunny"
+pkgver=0.2
+pkgrel=1
+pkgdesc="A slideshow that scrolls through facebook albums."
+arch=(x86_64)
+url="http://gitlab.gwillz.com:8888/gwillz/fbslideshow/"
+license=('GPLv3')
+provides=('photobunny')
+conflicts=('photobunny')
+depends=('qjson' 'qt4' 'openssl' 'libjpeg')
+makedepends=('qjson' 'qt4')
+checkdepends=()
+optdepends=()
+source=()
+noextract=()
+md5sums=() #generate with 'makepkg -g'
+
+build() {
+    cd $srcdir/
+    cp ../*{.h,.cpp,.pro,.qrc,.png} ./
+    qmake-qt4
+    make -j 4
+}
+
+package() {
+    cd $pkgdir/
+    #make DESTDIR=$pkgdir install
+    mkdir -p usr/bin
+    mkdir -p usr/share/pixmaps
+    mkdir -p usr/share/applications
+    
+    cp $srcdir/photobunny usr/bin
+    cp $srcdir/silhouette-bunny.png usr/share/pixmaps/photobunny.png
+    cp $srcdir/../PhotoBunny.desktop usr/share/applications/PhotoBunny.desktop
+}

+ 9 - 0
PhotoBunny.desktop

@@ -0,0 +1,9 @@
+[Desktop Entry]
+Name=PhotoBunny
+Comment=Facebook Album Slideshow
+Exec=cd ~/.local/ && photobunny
+Icon=photobunny.png
+Terminal=false
+Type=Application
+Encoding=UTF-8
+Categories=Internet;Application;

BIN
black.png


+ 14 - 0
common.h

@@ -0,0 +1,14 @@
+
+//qsettings
+#define company_str "GwillzCorp"
+#define app_str "fbslideshow"
+
+//facebook application id
+#define APP_ID = "1402768076653253" //photoBunny
+
+//fbApi urls
+#define fbUrl "https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&response_type=token&redirect_uri=https://www.facebook.com/connect/login_success.html&scope=user_photos,friends_photos"
+#define getAlbums "https://graph.facebook.com/me/albums?fields=name,id&limit=150&access_token=ACCESS_TOKEN"
+//#define getAlbumPics "https://graph.facebook.com/fql?q=SELECT+src_big+FROM+photo+WHERE+ALBUM_IDS&access_token=ACCESS_TOKEN"
+#define getAlbumPics "https://graph.facebook.com/fql?q=SELECT+src_big,+images.source+FROM+photo+WHERE+ALBUM_IDS&access_token=ACCESS_TOKEN"
+

+ 153 - 0
dialogs.cpp

@@ -0,0 +1,153 @@
+/* 
+ * Project PhotoBunny
+ * 2014 Gwilyn Saunders
+ */
+
+#include <QtGui>
+#include "dialogs.h"
+
+LoginDialog::LoginDialog(QWidget *parent) 
+        : QDialog(parent) {
+    
+    //housekeeping
+    setWindowTitle("Login to Facebook | PhotoBunny");
+    setFixedWidth(300);
+    setFixedHeight(180);
+    QFormLayout *layout = new QFormLayout(this);
+    setLayout(layout);
+    
+    //create form elements
+    userEdit = new QLineEdit(this);
+    passEdit = new QLineEdit(this);
+    timeEdit = new QSpinBox(this);
+    hdEdit = new QCheckBox(this);
+    cacheEdit = new QCheckBox(this);
+    QLabel *accessButton = new QLabel(this);
+    
+    passEdit->setEchoMode(QLineEdit::Password);
+    timeEdit->setMaximum(300);
+    timeEdit->setMinimum(1);
+    
+    //load settings
+    st = new QSettings(company_str, app_str);
+    userEdit->setText(st->value("user").toString());
+    passEdit->setText(st->value("pass").toString());
+    timeEdit->setValue(st->value("timeout").toLongLong()/1000);
+    hdEdit->setChecked(st->value("hd").toBool());
+    cacheEdit->setChecked(st->value("cache").toBool());
+    
+    //load FB api
+    FbApi *fb = new FbApi();
+    fb->id = "1402768076653253";
+    accessButton->setText(tr("<a href='%1'>Grant Access</a>").arg(fb->getLoginUrl().toString()));
+    accessButton->setOpenExternalLinks(true);
+    accessButton->setAlignment(Qt::AlignRight);
+    
+    //create buttons
+    QPushButton *okButton = new QPushButton("Login", this);
+    QPushButton *exitButton = new QPushButton("Cancel", this);
+    okButton->setMaximumWidth(70);
+    exitButton->setMaximumWidth(70);
+    
+    //add buttons
+    QHBoxLayout *buttons = new QHBoxLayout(this);
+    buttons->addStretch();
+    buttons->addWidget(okButton);
+    buttons->addWidget(exitButton);
+    
+    //mix form
+    layout->addRow("Username:", userEdit);
+    layout->addRow("Password:", passEdit);
+    layout->addRow("Timeout:", timeEdit);
+    layout->addRow("High Res:", hdEdit);
+    layout->addRow("Caching:", cacheEdit);
+    layout->addWidget(accessButton);
+    layout->addRow(buttons);
+    
+    connect(okButton, SIGNAL(clicked()), this, SLOT(okClicked()));
+    connect(exitButton, SIGNAL(clicked()), this, SLOT(reject()));
+}
+
+void LoginDialog::okClicked() {
+    st->setValue("user", userEdit->text());
+    st->setValue("pass", passEdit->text());
+    st->setValue("timeout", timeEdit->value()*1000);
+    st->setValue("hd", hdEdit->isChecked());
+    st->setValue("cache", cacheEdit->isChecked());
+    st->sync();
+    
+    accept();
+}
+
+AlbumDialog::AlbumDialog(QWidget *parent) 
+        : QDialog(parent) {
+    
+    //housekeeping
+    setFixedHeight(500);
+    setFixedWidth(350);
+    setWindowTitle("Select an Album | PhotoBunny");
+    QVBoxLayout *layout = new QVBoxLayout(this);
+    setLayout(layout);
+    
+    st = new QSettings(company_str, app_str);
+    
+    fb = new FbApi(this);
+    fb->id = "1402768076653253";
+    fb->saveCredentials(st->value("user").toString(), st->value("pass").toString());
+    fb->authenticate();
+    
+    connect(fb, SIGNAL(loginResult(bool)), this, SLOT(loggedIn()));
+    connect(fb, SIGNAL(albumsLoaded()), this, SLOT(loadAlbums()));
+    
+    
+    list = new QListWidget(this);
+    QPushButton *okButton = new QPushButton("Select", this);
+    okButton->setMaximumWidth(70);
+    QPushButton *cancelButton = new QPushButton("Cancel", this);
+    cancelButton->setMaximumWidth(70);
+    
+    QHBoxLayout *buttons = new QHBoxLayout(this);
+    buttons->addStretch();
+    buttons->addWidget(okButton);
+    buttons->addWidget(cancelButton);
+    
+    layout->addWidget(list);
+    layout->addLayout(buttons);
+    
+    connect(okButton, SIGNAL(clicked()), this, SLOT(okClicked()));
+    connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
+    //connect(list, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(okClicked()));
+}
+
+void AlbumDialog::okClicked() {
+    qDebug() << "registering albums";
+    
+    QStringList checked;
+    for (int i=0; i<list->count(); i++) {
+        QListWidgetItem *item = list->item(i);
+        
+        if (item->checkState() == Qt::Checked) {
+            checked.append(item->data(Qt::UserRole).toString());
+            qDebug() << "id: " << item->data(Qt::UserRole).toString();
+        }
+    }
+    
+    st->setValue("albums", checked);
+    st->sync();
+    
+    accept();
+}
+
+void AlbumDialog::loggedIn() {
+    fb->getAlbumsId();
+}
+
+void AlbumDialog::loadAlbums() {
+    foreach (QVariantMap album, fb->albumList) {
+        QListWidgetItem *item = new QListWidgetItem(album.value("name").toString());
+        item->setData(Qt::UserRole, album.value("id").toString());
+        item->setCheckState(Qt::Unchecked);
+        list->addItem(item);
+    }
+}
+

+ 72 - 0
dialogs.h

@@ -0,0 +1,72 @@
+/* 
+ * Project PhotoBunny
+ * 2014 Gwilyn Saunders
+ */
+
+#ifndef LOGINDIALOG_H
+#define LOGINDIALOG_H
+
+#include <QDialog>
+#include <QSettings>
+#include "fbApi.h"
+#include "common.h"
+class QLineEdit;
+class QSpinBox;
+class QCheckBox;
+
+class LoginDialog 
+        : public QDialog {
+    Q_OBJECT
+    
+    QSettings *st;
+    
+    QLineEdit *userEdit;
+    QLineEdit *passEdit;
+    QSpinBox *timeEdit;
+    QCheckBox *hdEdit;
+    QCheckBox *cacheEdit;
+    
+    public:
+        explicit LoginDialog(QWidget *parent = 0);
+        
+    signals:
+        
+    public slots:
+        void okClicked();
+};
+#endif // LOGINDIALOG_H
+
+
+#ifndef ALBUMDIALOG_H
+#define ALBUMDIALOG_H
+
+#include <QDialog>
+#include "fbApi.h"
+#include "common.h"
+class QListWidget;
+
+class AlbumDialog 
+        : public QDialog {
+    Q_OBJECT
+    
+    QSettings *st;
+    
+    QListWidget *list;
+    FbApi *fb;
+    QString aid;
+    
+    public:
+        explicit AlbumDialog(QWidget *parent = 0);
+        
+    signals:
+        
+    public slots:
+        void okClicked();
+        
+        void loadAlbums();
+        void loggedIn();
+};
+
+#endif // ALBUMDIALOG_H
+
+

+ 246 - 0
fbApi.cpp

@@ -0,0 +1,246 @@
+/* 
+ * From: https://github.com/netogallo/FrameBook/
+ * heavily modified for Project PhotoBunny
+ * 
+ * 2014 Gwilyn Saunders
+ */
+
+#include "fbApi.h"
+#include <QString>
+#include <QUrl>
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QObject>
+#include <QVariantMap>
+#include <stdio.h>
+#include <QDebug>
+#include <QDir>
+#include <QFile>
+#include <QWebPage>
+#include <QWebFrame>
+#include <QWebElement>
+
+#include <QDesktopServices>
+#include <QSettings>
+
+FbApi::FbApi(QObject * parent) 
+        : QObject(parent) {
+    
+    //housekeeping
+    net = new QNetworkAccessManager(this);
+    page = new QWebPage(this);
+
+    //defaults
+    id = "";
+    token = "";
+    imgCount = 0;
+    tmpPath = QDir::tempPath().append("/%1").arg(app_str);
+    
+    if (!QDir().exists(tmpPath)) {
+        QDir().mkdir(tmpPath);
+    }
+    
+    //get settings
+    syncSettings();
+    
+    //events
+    connect(page, SIGNAL(loadFinished(bool)), this, SLOT(doAuthentication(bool)));
+}
+
+void FbApi::syncSettings() {
+    st = new QSettings(company_str, app_str);
+    picList = new QStringList(st->value("images").toStringList());
+    aid = st->value("albums").toStringList();
+    user = new QString(st->value("user").toString());
+    pass = new QString(st->value("pass").toString());
+    highRes = st->value("hd").toBool();
+    caching = st->value("cache").toBool();
+}
+
+void FbApi::authenticate() {
+    qDebug() << "authenticating";
+    
+    page->mainFrame()->load(QUrl(getLoginUrl()));
+}
+
+void FbApi::doAuthentication(bool stat) {
+    if (stat) {
+        qDebug() << page->mainFrame()->url().toString();
+        
+        QUrl url = QUrl(page->mainFrame()->url().toString().replace("#access_token", "?access_token"));
+        
+        if (url.hasQueryItem("access_token")){
+            qDebug() << "success";
+            //qDebug() << url.queryItemValue("access_token");
+            
+            token = url.queryItemValue("access_token");
+            //getPicsId();
+            
+            emit loginResult(true);
+        }
+        else if (url.hasQueryItem("login_attempt")) {
+            qDebug() << "Wrong user/password";
+            
+            emit loginResult(false);
+        }
+        
+        else {
+            qDebug() << "sending credentials";
+            //qDebug() << url.toString();
+            
+            page->mainFrame()->findFirstElement("input#email").setAttribute("value", *user);
+            page->mainFrame()->findFirstElement("input#pass").setAttribute("value", *pass);
+            page->mainFrame()->evaluateJavaScript("document.getElementById(\"login_form\").submit()");
+        }
+    }
+}
+
+QUrl FbApi::getLoginUrl() {
+    QString *url = new QString(fbUrl);
+    return QUrl(url->replace("YOUR_APP_ID", id, Qt::CaseSensitive));
+}
+
+void FbApi::getPicsId() {
+    qDebug() << "fetching picture ids";
+    qDebug() << "Album: " << aid;
+    
+    QString url = QString(getAlbumPics);
+    url.replace("ACCESS_TOKEN", token, Qt::CaseSensitive);
+    
+    QString albumString = QString("album_object_id=\"%1\"").arg(aid.takeFirst());
+    
+    foreach (QString a, aid) {
+        albumString += QString("or album_object_id=\"%1\"").arg(a);
+    }
+    
+    url.replace("ALBUM_IDS", albumString, Qt::CaseSensitive);
+    resp = net->get(QNetworkRequest(QUrl(url)));
+    connect(resp, SIGNAL(finished()), this, SLOT(loadPicList()));
+}
+
+void FbApi::saveCredentials(QString myUser, QString myPass) {
+    qDebug() << "registering login details";
+    
+    user = new QString(myUser);
+    pass = new QString(myPass);
+    
+    st->setValue("user", *user);
+    st->setValue("pass", *pass);
+}
+
+void FbApi::loadPicList() {
+    qDebug() << "processing response";
+    
+    bool ok;
+    
+    QVariant result = parser.parse(resp->readAll(), &ok);
+    qDebug() << resp->url();
+    resp->close();
+    
+    if (ok) {
+        qDebug() << "loading photos";
+        
+        delete picList;
+        picList = new QStringList();
+        
+        foreach (QVariant pic, result.toMap()["data"].toList()) {
+            if (highRes) {
+                picList->append(pic.toMap()["images"].toList()[0].toMap()["source"].toString());
+            } else {
+                picList->append(pic.toMap()["src_big"].toString());
+            }
+        }
+        
+        qDebug() << picList->count() << "photo(s)";
+        
+        st->setValue("images", *picList);
+        
+        emit picsLoaded();
+    }
+}
+
+void FbApi::getAlbumsId() {
+    qDebug() << "fetching album ids";
+    
+    QString url = QString(getAlbums);
+    url.replace("ACCESS_TOKEN", token, Qt::CaseSensitive);
+    
+    resp = net->get(QNetworkRequest(QUrl(url)));
+    connect(resp, SIGNAL(finished()), this, SLOT(loadAlbumList()));
+}
+
+void FbApi::loadAlbumList() {
+    qDebug() << "processing response";
+    
+    bool ok;
+    
+    QVariant result = parser.parse(resp->readAll(), &ok);
+    resp->close();
+    //delete resp;
+
+    if (ok) {
+        albumList.clear();
+        qDebug() << "loading albums";
+        
+        foreach (QVariant album, result.toMap()["data"].toList()) {
+            albumList.append(album.toMap());
+        }
+        
+        qDebug() << albumList.count() << "album(s)";
+        
+        emit albumsLoaded();
+    }
+}
+
+bool FbApi::nextPicture() {
+    if (picList->size() > 0) {
+        
+        if (imgCount >= picList->size()) {
+            imgCount = 0; //loop
+        }
+        
+        QString picUrl = picList->at(imgCount);
+        QString path = QString(tmpPath).append("/%1").arg(picUrl.split("/").last());
+        
+        if (caching) {
+            if (!QFile::exists(path)) {
+                //load if not already cached
+                picResp = net->get(QNetworkRequest(QUrl(picUrl)));
+                connect(picResp, SIGNAL(finished()), this, SLOT(setPicture()));
+            }
+            else {
+                emit picLoaded(path);
+                qDebug() << imgCount << ": CACHED :" << path;
+                imgCount++;
+            }
+        } 
+        else {
+            //remove previous image
+            QFile::remove(path);
+            picResp = net->get(QNetworkRequest(QUrl(picUrl)));
+            connect(picResp, SIGNAL(finished()), this, SLOT(setPicture()));
+        }
+        
+        return true;
+    }
+    return false;
+}
+
+void FbApi::setPicture() {
+    if (picResp->error() == QNetworkReply::NoError && picResp->size() > 1) {
+        
+        QString picUrl = picList->at(imgCount);
+        QString path = QString(tmpPath).append("/%1").arg(picUrl.split("/").last());
+        
+        //write picResp to file
+        pic = new QFile(path);
+        pic->open(QIODevice::WriteOnly);
+        pic->write(picResp->readAll());
+        pic->close();
+        
+        emit picLoaded(path);
+        qDebug() << imgCount << ":" << path;
+        
+        imgCount++;
+    }
+}

+ 76 - 0
fbApi.h

@@ -0,0 +1,76 @@
+/* 
+ * From: https://github.com/netogallo/FrameBook/
+ * heavily modified for Project PhotoBunny
+ * 
+ * 2014 Gwilyn Saunders
+ */
+
+#ifndef FBAPI_H
+#define FBAPI_H
+
+#include <QString>
+#include <QSettings>
+#include <QUrl>
+#include <QNetworkRequest>
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QFile>
+#include <qjson/parser.h>
+#include <QWebPage>
+#include "common.h"
+
+class FbApi 
+        : public QObject{
+    Q_OBJECT
+    
+    public:
+        FbApi(QObject *parent = 0);
+        
+        QSettings *st;
+        
+        QUrl getLoginUrl();
+        QString token;
+        
+        bool highRes;
+        bool caching;
+        QString id;
+        QStringList *picList;
+        void getPicsId();
+        
+        QStringList aid;
+        QList<QVariantMap> albumList;
+        void getAlbumsId();
+        
+        bool nextPicture();
+        void authenticate();
+        QString *user;
+        QString *pass;
+        void saveCredentials(QString myUser, QString myPass);
+        void syncSettings();
+        
+    private:
+        int imgCount;
+        QString tmpPath;
+        
+        QNetworkAccessManager *net;
+        QNetworkReply *resp;
+        QNetworkReply *picResp;
+        QJson::Parser parser;
+        QFile *pic;
+        QWebPage *page;
+
+    signals:
+        void picsLoaded();
+        void picLoaded(QString pic);
+        void loginResult(bool res);
+        void albumsLoaded();
+
+    public slots:
+        void loadPicList();
+        void loadAlbumList();
+        void setPicture();
+        void doAuthentication(bool stat);
+};
+
+
+#endif // FBAPI_H

BIN
homepage.png


BIN
homepage.psd


+ 90 - 0
install.nsi

@@ -0,0 +1,90 @@
+#setup vars
+Name "PhotoBunny"
+OutFile "setup.exe"
+InstallDir "$PROGRAMFILES\PhotoBunny"
+RequestExecutionLevel highest
+
+#version stuff
+VIAddVersionKey "ProductName" "PhotoBunny"
+VIAddVersionKey "CompanyName" "GwillzCorp"
+VIAddVersionKey "LegalTrademarks" "Licensed under GPL 3.0"
+VIAddVersionKey "LegalCopyright" "© Gwilyn Saunders"
+VIAddVersionKey "FileDescription" "Setup installer for PhotoBunny"
+VIAddVersionKey "FileVersion" "1.0"
+VIAddVersionKey "ProductVersion" "1.0.0.1"
+VIProductVersion "1.0.0.1"
+
+LicenseData "installer\GPL3.txt"
+DirText "Select somewhere to install and junk"
+
+#imports
+!include "LogicLib.nsh"
+
+#layout
+Page license
+Page directory
+Page instfiles
+UninstPage uninstConfirm
+UninstPage instfiles
+
+#default section
+Section "Common Files (Required)"
+    SectionIn RO
+	SetOutPath $INSTDIR
+	
+	#copy files
+	File "build\release\photobunny.exe"
+	File "installer\QtCore4.dll"
+	File "installer\QtGui4.dll"
+	File "installer\QtNetwork4.dll"
+	File "installer\QtWebKit4.dll"
+	File "installer\qjson.dll"
+	File "installer\libeay32.dll"
+	File "installer\ssleay32.dll"
+	File "installer\vcredist_sp1_x86.exe"
+	File "installer\GPL3.txt"
+	CreateDirectory "$INSTDIR\imageformats"
+	SetOutPath "$INSTDIR\imageformats"
+	File "installer\qjpeg4.dll"
+	
+	#Check for 32bit VC2010 on a 32bit system
+	ReadRegDWORD $0 HKLM "SOFTWARE\Microsoft\VisualStudio\10.0\VC\VCRedist\x86" "Installed"
+	${If} $0 == ""
+		#then check on a 64bit system
+		ReadRegDWORD $1 HKLM "SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\VC\VCRedist\x86" "Installed"
+		${If} $1 == ""
+			ExecWait "$INSTDIR\vcredist_sp1_x86.exe"
+		${EndIf}
+	${EndIf}
+	
+	#create uninstaller
+	WriteUninstaller "$INSTDIR\uninstall.exe"
+	#create shortcuts
+	CreateDirectory "$SMPROGRAMS\PhotoBunny"
+	CreateShortCut "$SMPROGRAMS\PhotoBunny\PhotoBunny.lnk" "$INSTDIR\photobunny.exe"
+	CreateShortCut "$SMPROGRAMS\PhotoBunny\Licence.lnk" "$INSTDIR\GPL3.txt"
+	CreateShortCut "$SMPROGRAMS\PhotoBunny\Uninstall.lnk" "$INSTDIR\uninstall.exe"
+SectionEnd
+
+#uninstall section
+Section "Uninstall"
+	#remove program files
+	Delete "$INSTDIR\photobunny.exe"
+	Delete "$INSTDIR\QtCore4.dll"
+	Delete "$INSTDIR\QtGui4.dll"
+	Delete "$INSTDIR\QtNetwork4.dll"
+	Delete "$INSTDIR\QtWebKit4.dll"
+	Delete "$INSTDIR\qjson.dll"
+	Delete "$INSTDIR\libeay32.dll"
+	Delete "$INSTDIR\ssleay32.dll"
+	Delete "$INSTDIR\GPL3.txt"
+	Delete "$INSTDIR\uninstall.exe"
+	Delete "$INSTDIR\imageformats\qjpeg4.dll"
+	
+	#remove shortcut files
+	Delete "$SMPROGRAMS\PhotoBunny\PhotoBunny.lnk"
+	Delete "$SMPROGRAMS\PhotoBunny\Licence.lnk"
+	Delete "$SMPROGRAMS\PhotoBunny\Uninstall.lnk"
+	RMDir "$SMPROGRAMS\PhotoBunny"
+	
+SectionEnd

+ 60 - 0
main.cpp

@@ -0,0 +1,60 @@
+/* 
+ * Project PhotoBunny
+ * 2014 Gwilyn Saunders
+ */
+
+#include "slidewindow.h"
+#include <QApplication>
+#include <QtCore>
+
+void customMessageHandler(QtMsgType type, const char *msg) {
+    //Q_UNUSED(context);
+    
+    
+    QString dt = QDateTime::currentDateTime().toString("mm:ss");
+    QString txt = QString("[%1] ").arg(dt);
+    
+    switch (type) {
+        case QtDebugMsg:
+            txt += QString("{Debug} \t\t %1").arg(msg);
+            break;
+        case QtWarningMsg:
+            txt += QString("{Warning} \t %1").arg(msg);
+            break;
+        case QtCriticalMsg:
+            txt += QString("{Critical} \t %1").arg(msg);
+            break;
+        case QtFatalMsg:
+            txt += QString("{Fatal} \t\t %1").arg(msg);
+            abort();
+            break;
+    }
+    
+    QFile outFile(QDir::rootPath() + "/log.txt");
+    outFile.open(QIODevice::WriteOnly | QIODevice::Append);
+    
+    QTextStream textStream(&outFile);
+    textStream << txt << "\r\n";
+    outFile.close();
+}
+
+int main(int argc, char *argv[]) {
+    
+    //refresh log
+    QString dt = QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm");
+    QFile outFile(QDir::rootPath() + "/log.txt");
+    outFile.open(QIODevice::WriteOnly);
+    QTextStream textStream(&outFile);
+    textStream << "FB Slideshow started on " << dt << "\r\n";
+    textStream << "------------------------------------\r\n";
+    outFile.close();
+    
+    //replace qDebug handler
+//    qInstallMsgHandler(customMessageHandler);
+    
+    QApplication a(argc, argv);
+    SlideWindow w;
+    w.show();
+    
+    return a.exec();
+}

+ 1 - 0
res.rc

@@ -0,0 +1 @@
+IDI_ICON1               ICON    DISCARDABLE     "silhouette-bunny.ico"

+ 7 - 0
resources.qrc

@@ -0,0 +1,7 @@
+<RCC>
+    <qresource prefix="/img">
+        <file>black.png</file>
+        <file>homepage.png</file>
+        <file alias="icon.png">silhouette-bunny.png</file>
+    </qresource>
+</RCC>

BIN
silhouette-bunny.ico


BIN
silhouette-bunny.png


+ 154 - 0
slidewindow.cpp

@@ -0,0 +1,154 @@
+/* 
+ * Project PhotoBunny
+ * 2014 Gwilyn Saunders
+ */
+
+#include "slidewindow.h"
+#include <QtGui>
+#include <QDesktopWidget>
+
+SlideWindow::SlideWindow(QWidget *parent)
+        : QMainWindow(parent) {
+    
+    //load settings
+    st = new QSettings(company_str, app_str);
+    timeout = st->value("timeout").toInt();
+    
+    setupUi();
+    setupLogin();
+}
+
+void SlideWindow::setupUi() {
+    //housekeeping
+    setWindowTitle("PhotoBunny");
+    setWindowIcon(QIcon(":/img/icon.png"));
+    
+    QDesktopWidget *desktop = new QDesktopWidget();
+    setFixedWidth(desktop->width());
+    setFixedHeight(desktop->height());
+    
+    setWindowState(Qt::WindowFullScreen);
+    setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
+    setPalette(QPalette(QColor().black()));
+    
+    //set default pixmap
+    QPixmap pix(":/img/homepage.png");
+    pix = pix.scaledToHeight(this->height(),Qt::SmoothTransformation);
+    int tl = (pix.width() - this->width()) / 2;
+    pix = pix.copy(tl, 0, this->width(), this->height());
+    
+    //set label widget
+    img = new QLabel(this);
+    img->setPixmap(pix);
+    img->setMaximumHeight(this->height());
+    img->setMaximumWidth(this->width());
+    img->setAlignment(Qt::AlignCenter | Qt::AlignHCenter);
+    setCentralWidget(img);
+    
+    //set keyboard shortcuts
+    QAction *escAction = new QAction(this);
+    QAction *aboutAction = new QAction(this);
+    QAction *pauseAction = new QAction(this);
+    QAction *blankAction = new QAction(this);
+    escAction->setShortcut(Qt::Key_Escape);
+    aboutAction->setShortcut(Qt::Key_F1);
+    pauseAction->setShortcut(Qt::Key_Space);
+    blankAction->setShortcut(Qt::Key_Return);
+    
+    addAction(escAction);
+    addAction(aboutAction);
+    addAction(pauseAction);
+    addAction(blankAction);
+    
+    //events
+    connect(escAction, SIGNAL(triggered()), qApp, SLOT(quit()));
+    connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));
+    connect(pauseAction, SIGNAL(triggered()), this, SLOT(pause()));
+    connect(blankAction, SIGNAL(triggered()), this, SLOT(blank()));
+}
+
+void SlideWindow::setupLogin() {
+    
+    //open login dialog
+    loginDiag = new LoginDialog(this);
+    loginDiag->show();
+    
+    connect(loginDiag, SIGNAL(accepted()), this, SLOT(setupAlbums()));
+    connect(loginDiag, SIGNAL(rejected()), qApp, SLOT(quit()));
+}
+
+void SlideWindow::setupAlbums() {
+    albumDiag = new AlbumDialog(this);
+    albumDiag->show();
+    connect(albumDiag, SIGNAL(accepted()), this, SLOT(setupFB()));
+    connect(albumDiag, SIGNAL(rejected()), qApp, SLOT(quit()));
+}
+
+void SlideWindow::setupFB() {
+    //fb stuff
+    qApp->setOverrideCursor(Qt::BlankCursor);
+    
+    timer = new QTimer();
+    fb = new FbApi(this);
+    fb->id = "1402768076653253"; //TODO: change to #define
+    
+    fb->syncSettings();
+    fb->saveCredentials(st->value("user").toString(), st->value("pass").toString());
+    fb->authenticate();
+    
+    qDebug() << "-- slideshow started with a" << timeout << "ms timeout --";
+    if (fb->caching) {
+        qDebug() << "-- caching enabled --";
+    }
+    
+    connect(timer, SIGNAL(timeout()), this, SLOT(photoChange()));
+    connect(fb, SIGNAL(picsLoaded()), this, SLOT(photoChange()));
+    connect(fb, SIGNAL(picLoaded(QString)), this, SLOT(setImage(QString)));
+    connect(fb, SIGNAL(loginResult(bool)), this, SLOT(loggedIn()));
+}
+
+void SlideWindow::about() {
+    QMessageBox::about(this, 
+                       "PhotoBunny", 
+                       "A fullscreen app that displays a slideshow of photos from selected facebook albums. \n"
+                       "Made for Lincoln College, North Adelaide SA, Australia \n"
+                       "www.lincoln.edu.au \n"
+                       "Licenced under GPL 3 \n"
+                       "(c) Gwilyn Saunders 2014");
+    
+}
+
+void SlideWindow::pause() {
+    if (timer->isActive()) {
+        qDebug() << "paused";
+        timer->stop();
+    } else {
+        qDebug() << "unpaused";
+        photoChange();
+    }
+}
+
+void SlideWindow::blank() {
+    pause();
+    img->setPixmap(QPixmap(":/img/black.png"));
+}
+
+void SlideWindow::photoChange() {
+    timer->stop();
+    if (fb->nextPicture()) {
+        timer->start(timeout);
+    }
+    //TODO: else, report empty album?
+}
+
+void SlideWindow::setImage(QString path) {
+    QPixmap pix(path);
+    pix = pix.scaled(this->width(), this->height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
+    
+    img->setPixmap(pix);
+}
+
+void SlideWindow::loggedIn() {
+    fb->getPicsId();
+}
+

+ 48 - 0
slidewindow.h

@@ -0,0 +1,48 @@
+/* 
+ * Project PhotoBunny
+ * 2014 Gwilyn Saunders
+ */
+
+#ifndef SLIDEWINDOW_H
+#define SLIDEWINDOW_H
+
+#include <QMainWindow>
+#include <QPixmap>
+#include <QLabel>
+#include <QTimer>
+#include <QSettings>
+#include "common.h"
+#include "fbApi.h"
+#include "dialogs.h"
+
+class SlideWindow 
+        : public QMainWindow {
+    Q_OBJECT
+    
+    int timeout;
+    
+    QLabel *img;
+    QTimer *timer;
+    FbApi *fb;
+    LoginDialog *loginDiag;
+    AlbumDialog *albumDiag;
+    QSettings *st;
+    
+    public:
+        SlideWindow(QWidget *parent = 0);
+        
+    public slots:
+        void photoChange();
+        void setImage(QString path);
+        void loggedIn();
+        void pause();
+        void blank();
+        void about();
+        void setupUi();
+        void setupLogin();
+        void setupAlbums();
+        void setupFB();
+};
+
+#endif // SLIDEWINDOW_H
+

+ 21 - 0
version.h

@@ -0,0 +1,21 @@
+#ifndef VERSION_H
+#define VERSION_H
+
+#define VER_FILEVERSION             1,0,0,1
+#define VER_FILEVERSION_STR         "1.0.0.1\0"
+
+#define VER_PRODUCTVERSION          1,0,0,1
+#define VER_PRODUCTVERSION_STR      "1.0\0"
+
+#define VER_COMPANYNAME_STR         "GwillzCorp"
+#define VER_FILEDESCRIPTION_STR     "PhotoBunny"
+#define VER_INTERNALNAME_STR        "photobunny"
+#define VER_LEGALCOPYRIGHT_STR      "Copyright (c) 2014 Gwilyn Saunders"
+#define VER_LEGALTRADEMARKS1_STR    "Licensed under GPL 3.0"
+#define VER_LEGALTRADEMARKS2_STR    "All Rights Reserved"
+#define VER_ORIGINALFILENAME_STR    "photobunny.exe"
+#define VER_PRODUCTNAME_STR         "PhotoBunny"
+
+#define VER_COMPANYDOMAIN_STR       "gwillz.com"
+
+#endif // VERSION_H