Skip to content

Commit

Permalink
Initial QT based URL fetch
Browse files Browse the repository at this point in the history
Signed-off-by: Scott Wilson <[email protected]>
  • Loading branch information
muellmusik committed Aug 7, 2013
1 parent 334a580 commit 4d352de
Show file tree
Hide file tree
Showing 6 changed files with 309 additions and 0 deletions.
62 changes: 62 additions & 0 deletions HelpSource/Classes/Download.schelp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
TITLE:: Download
summary:: Fetch a file from a remote URL
categories:: Files
related:: Classes/File

DESCRIPTION::
Download allows you to download a file from a specified URL


CLASSMETHODS::
private:: qtClass

METHOD:: new
Create and start a new Download.

ARGUMENT:: requestedURL
A link::Classes/String:: containing the URL of the file to download.

ARGUMENT:: localPath
A link::Classes/String:: containing the local path at which to save the downloaded file.

ARGUMENT:: finishedFunc
A link::Classes/Function:: to evaluate when the download is complete.

ARGUMENT:: errorFunc
A link::Classes/Function:: to evaluate if the download fails due to an error.

ARGUMENT:: progressFunc
A link::Classes/Function:: to process the download's progress. This Function will be passed two arguments, the bytes received, and the total bytes.

returns:: A new Download.

METHOD:: cancelAll
Cancel all active Downloads.


INSTANCEMETHODS::
private:: doProgress, doError, doFinished, doOnShutDown, cleanup, startDownload, init

METHOD:: cancel
Cancel the download.

METHOD:: errorFunc
Get or set the error link::Classes/Function::.

METHOD:: finishedFunc
Get or set the download finished link::Classes/Function::.

METHOD:: progressFunc
Get or set the download progress link::Classes/Function::.



EXAMPLES::

code::
Download("http://art-on-wires.org/wp-content/uploads/2011/03/nick_collins.png", "/tmp/nick.png", {\huzzah.postln;}, {\error.postln}, {|rec, tot| [rec, tot].postln}); // beautify your tmp directory

d = Download("http://scottwilson.ca/files/flame.mp3", "/tmp/flame.mp3", {\huzzah.postln;}, {\error.postln}, {|rec, tot| [rec, tot].postln});
d.cancel; // cancel this

::
2 changes: 2 additions & 0 deletions QtCollider/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ set( QT_COLLIDER_HDRS
${QT_COLLIDER_DIR}/QcApplication.h
${QT_COLLIDER_DIR}/QObjectProxy.h
${QT_COLLIDER_DIR}/QWidgetProxy.h
${QT_COLLIDER_DIR}/QtDownload.h
${QT_COLLIDER_DIR}/widgets/BasicWidgets.h
${QT_COLLIDER_DIR}/widgets/QcButton.h
${QT_COLLIDER_DIR}/widgets/QcCheckBox.h
Expand Down Expand Up @@ -73,6 +74,7 @@ set( QT_COLLIDER_SRCS
${QT_COLLIDER_DIR}/QObjectProxy.cpp
${QT_COLLIDER_DIR}/QWidgetProxy.cpp
${QT_COLLIDER_DIR}/QcObjectFactory.cpp
${QT_COLLIDER_DIR}/QtDownload.cpp
${QT_COLLIDER_DIR}/hacks/hacks_x11.cpp
${QT_COLLIDER_DIR}/primitives/primitives.cpp
${QT_COLLIDER_DIR}/primitives/prim_QObject.cpp
Expand Down
109 changes: 109 additions & 0 deletions QtCollider/QtDownload.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* QtDownload.cpp
*
*
* Copyright 2013 Scott Wilson.
*
* This file is part of SuperCollider.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/

#include "Common.h"
#include "QtDownload.h"
#include "QcWidgetFactory.h"

#include <QCoreApplication>
#include <QUrl>
#include <QNetworkRequest>
#include <QFile>
#include <QDebug>

QC_DECLARE_QOBJECT_FACTORY(QtDownload);

QtDownload::QtDownload() : QObject(0), started(false) {
}

QtDownload::~QtDownload() {
}


void QtDownload::setSource(const QString &t) {
m_target = t;
}

void QtDownload::setDestination(const QString &l) {
m_local = l;
}

void QtDownload::downloadFinished() {
if (m_reply->error() == QNetworkReply::NoError) { // only write if no error
QFile localFile(this->m_local);
if (!localFile.open(QIODevice::WriteOnly))
return;
const QByteArray sdata = m_reply->readAll();
localFile.write(sdata);
qDebug() << sdata;
localFile.close();

// call action
Q_EMIT( doFinished() );
}

m_reply->deleteLater();
m_manager->deleteLater();
}

void QtDownload::download() {
if(!started) {
started = true;
m_manager = new QNetworkAccessManager(this);
QUrl url = QUrl::fromEncoded(this->m_target.toLocal8Bit());
QNetworkRequest request;
request.setUrl(url);
m_reply = m_manager->get(request);
QObject::connect(m_reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(downloadProgress(qint64,qint64)));
QObject::connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(replyError(QNetworkReply::NetworkError)));
bool fin = QObject::connect(m_reply, SIGNAL(finished()),this, SLOT(downloadFinished()));
if (!fin) {
printf("Download could not connect\n");
}
}
}

void QtDownload::cancel() {
if(m_reply) {
m_reply->disconnect();
m_reply->abort();
}
}

void QtDownload::replyError(QNetworkReply::NetworkError errorCode)
{
printf(m_reply->errorString().toStdString().c_str());
printf("\n");

// call action
Q_EMIT( doError() );
}

void QtDownload::downloadProgress(qint64 received, qint64 total) {

qDebug() << received << total;

// call action
Q_EMIT( doProgress(static_cast<int>(received), static_cast<int>(total)) );

}
62 changes: 62 additions & 0 deletions QtCollider/QtDownload.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* QtDownload.h
*
*
* Copyright 2013 Scott Wilson.
*
* This file is part of SuperCollider.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*/

#include <QObject>
#include <QString>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>


class QtDownload : public QObject {
Q_OBJECT
Q_PROPERTY( QString source READ source WRITE setSource );
Q_PROPERTY( QString destination READ destination WRITE setDestination );

public:
explicit QtDownload();
~QtDownload();

void setSource(const QString& t);
void setDestination(const QString& l);
QString source() { return m_target; }
QString destination() {return m_local; }
Q_INVOKABLE void cancel();
Q_INVOKABLE void download();

Q_SIGNALS:
void doFinished();
void doError();
void doProgress(int, int);

private:
QNetworkAccessManager *m_manager;
QString m_target;
QString m_local;
QNetworkReply* m_reply;
bool started;

public Q_SLOTS:
void downloadFinished();
void downloadProgress(qint64 recieved, qint64 total);
void replyError(QNetworkReply::NetworkError errorCode);
};
1 change: 1 addition & 0 deletions QtCollider/factories.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ void loadFactories () {
QC_ADD_FACTORY( QcVBoxLayout );
QC_ADD_FACTORY( QcGridLayout );
QC_ADD_FACTORY( QcStackLayout );
QC_ADD_FACTORY( QtDownload );
}

} // namespace QtCollider
73 changes: 73 additions & 0 deletions SCClassLibrary/QtCollider/Download.sc
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
Download : QObject {
classvar requests;
var <>finishedFunc, <>errorFunc, <>progressFunc;
var error = false, started = false;

*new {|requestedURL, localPath, finishedFunc, errorFunc, progressFunc|
^super.new.init(requestedURL, localPath, finishedFunc, errorFunc, progressFunc);
}

*qtClass { ^'QtDownload' }

init {|requestedURL, localPath, argfinFunc, argerrFunc, argprogFunc|
localPath = localPath ?? { Platform.defaultTempDir +/+ "download" };
finishedFunc = argfinFunc;
errorFunc = argerrFunc;
progressFunc = argprogFunc;
if(requests.isNil, { requests = Set.new; });
requests.add(this);
this.startDownload(requestedURL, localPath);
}

cancel {
"Download of % cancelled\n".postf(this.getProperty(\source));
this.invokeMethod(\cancel);
this.cleanup;
}

*cancelAll { requests.do({|dl| dl.cancel }); }

// private

doOnShutDown { this.cancel }

startDownload { |requestedURL, localPath|
if(started.not, {
started = true;
ShutDown.add(this);
this.setProperty(\source, requestedURL);
this.setProperty(\destination, localPath);
this.connectMethod('doFinished()', 'doFinished');
this.connectMethod('doError()', 'doError');
this.connectMethod('doProgress(int, int)', 'doProgress');
this.invokeMethod(\download);
});
}

doFinished {
"Download of % finished\n".postf(this.getProperty(\source));
this.cleanup;
if(error.not, {
finishedFunc.value;
});
}

cleanup {
requests.remove(this);
heap.remove(this);
ShutDown.remove(this);
}

doError {
error = true;
this.cleanup;
errorFunc.value;
}

doProgress {|bytesReceived, bytesTotal|
if(error.not, {
progressFunc.value(bytesReceived, bytesTotal);
});
}

}

0 comments on commit 4d352de

Please sign in to comment.