diff --git a/saori.pro b/saori.pro index 225a8de..7be987b 100644 --- a/saori.pro +++ b/saori.pro @@ -33,7 +33,8 @@ saoricache.cpp \ saoriviewentry.cpp \ saoriconfiguredialog.cpp \ - saoritootwidget.cpp + saoritootwidget.cpp \ + saoridownloader.cpp HEADERS += \ saoriwindow.h \ @@ -46,7 +47,8 @@ saoricache.h \ saoriviewentry.h \ saoriconfiguredialog.h \ - saoritootwidget.h + saoritootwidget.h \ + saoridownloader.h FORMS += \ saoriwindow.ui \ diff --git a/saoricache.cpp b/saoricache.cpp index 96b3420..ffe0095 100644 --- a/saoricache.cpp +++ b/saoricache.cpp @@ -51,6 +51,20 @@ SaoriCache::SaoriCache(QObject *parent) : QObject(parent) { migration(); + m_thread = new QThread; + m_downloader = new SaoriDownloader; + m_downloader->moveToThread(m_thread); + connect(this,&SaoriCache::initDownloader,m_downloader,&SaoriDownloader::initialize,Qt::QueuedConnection); + connect(this,&SaoriCache::get,m_downloader,&SaoriDownloader::get,Qt::QueuedConnection); + connect(m_downloader,&SaoriDownloader::downloaded,this,&SaoriCache::downloadFinished,Qt::QueuedConnection); + connect(m_downloader,&SaoriDownloader::error,this,&SaoriCache::networkError,Qt::QueuedConnection); + m_thread->start(); + emit initDownloader(); +} + +SaoriCache::~SaoriCache() +{ + m_thread->exit(); } void SaoriCache::removeFileCache(const QUrl url) @@ -90,37 +104,7 @@ m_nowloading.append(url); QNetworkRequest request; request.setUrl(url); - auto *reply = SaoriApplication::saori()->manager->get(request); - connect(reply,&QNetworkReply::finished,this,[=](){ - if (reply->error() == QNetworkReply::NoError) { - QFile localfile(urlToFilename(url)); - if (localfile.exists()) localfile.remove(); - localfile.open(QIODevice::WriteOnly); - localfile.write(reply->readAll()); - // TODO 100MBのファイルに100MBのメモリを使うのは如何なものか。 - qint64 size = localfile.size(); - localfile.close(); - QSqlQuery query(*SaoriApplication::saori()->database()); - query.prepare("INSERT INTO file_cache(url,filename,size,timestamp) values(?,?,?,?);"); - query.addBindValue(url.toString()); - query.addBindValue(urlToFilename(url)); - query.addBindValue(size); - query.addBindValue(QDateTime::currentSecsSinceEpoch()); - query.exec(); - emit downloaded(url); - } else { - QSqlQuery query(*SaoriApplication::saori()->database()); - query.prepare("INSERT INTO file_cache(url,filename,size,timestamp) values(?,?,?,?);"); - query.addBindValue(url.toString()); - query.addBindValue(":/icons/ionicons-md/md-alert.svg"); - query.addBindValue("-1"); - query.addBindValue(QDateTime::currentSecsSinceEpoch()); - query.exec(); - emit downloaded(url); - } - m_nowloading.removeAll(url); - reply->deleteLater(); - }); + emit get(request); } bool SaoriCache::isCached(const QUrl url) @@ -143,3 +127,36 @@ d.mkpath(SaoriApplication::saori()->cacheDirectory().absolutePath() + "/" + dir); return QString(SaoriApplication::saori()->cacheDirectory().absolutePath() + "/" + dir + "/" + file); } + +void SaoriCache::downloadFinished(QNetworkRequest req, QByteArray data) +{ + QFile localfile(urlToFilename(req.url())); + if (localfile.exists()) localfile.remove(); + localfile.open(QIODevice::WriteOnly); + localfile.write(data); + // TODO 100MBのファイルに100MBのメモリを使うのは如何なものか。 + qint64 size = localfile.size(); + localfile.close(); + QSqlQuery query(*SaoriApplication::saori()->database()); + query.prepare("INSERT INTO file_cache(url,filename,size,timestamp) values(?,?,?,?);"); + query.addBindValue(req.url().toString()); + query.addBindValue(urlToFilename(req.url())); + query.addBindValue(size); + query.addBindValue(QDateTime::currentSecsSinceEpoch()); + query.exec(); + emit downloaded(req.url()); + m_nowloading.removeAll(req.url()); +} + +void SaoriCache::networkError(QNetworkRequest req, QNetworkReply::NetworkError error) +{ + if (error == QNetworkReply::NoError) return; + QSqlQuery query(*SaoriApplication::saori()->database()); + query.prepare("INSERT INTO file_cache(url,filename,size,timestamp) values(?,?,?,?);"); + query.addBindValue(req.url().toString()); + query.addBindValue(":/icons/ionicons-md/md-alert.svg"); + query.addBindValue("-1"); + query.addBindValue(QDateTime::currentSecsSinceEpoch()); + query.exec(); + emit downloaded(req.url()); +} diff --git a/saoricache.h b/saoricache.h index 834e139..4928c1e 100644 --- a/saoricache.h +++ b/saoricache.h @@ -30,18 +30,23 @@ #include #include #include +#include +#include "saoridownloader.h" class SaoriCache : public QObject { Q_OBJECT public: explicit SaoriCache(QObject *parent = nullptr); + ~SaoriCache(); void removeFileCache(const QUrl url); void reloadFileCache(const QUrl url); const QString fileCache(const QUrl url); protected: static QList m_nowloading; + SaoriDownloader *m_downloader; + QThread *m_thread; protected: bool migration(); @@ -50,8 +55,14 @@ static const QString urlToFilename(QUrl url); const QString localfileName(const QUrl url); +protected slots: + void downloadFinished(QNetworkRequest req,QByteArray data); + void networkError(QNetworkRequest req,QNetworkReply::NetworkError error); + signals: void downloaded(const QUrl); + void initDownloader(); + void get(QNetworkRequest); public slots: }; diff --git a/saoridownloader.cpp b/saoridownloader.cpp new file mode 100644 index 0000000..9212d6f --- /dev/null +++ b/saoridownloader.cpp @@ -0,0 +1,49 @@ +/*** + +The MIT License + +Copyright (c) 2018 Teppei Tamra (TAM) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +***/ + +#include +#include "saoridownloader.h" + +SaoriDownloader::SaoriDownloader(QObject *parent) : QObject(parent) +{ + +} + +void SaoriDownloader::initialize() +{ + m_manager = new QNetworkAccessManager(this); +} + +void SaoriDownloader::get(QNetworkRequest req) +{ + auto reply = m_manager->get(req); + connect(reply,&QNetworkReply::finished,[=](){ + emit error(req,reply->error()); + if (reply->error() == QNetworkReply::NoError) { + emit downloaded(req,reply->readAll()); + } + }); +} diff --git a/saoridownloader.h b/saoridownloader.h new file mode 100644 index 0000000..d09b878 --- /dev/null +++ b/saoridownloader.h @@ -0,0 +1,53 @@ +/*** + +The MIT License + +Copyright (c) 2018 Teppei Tamra (TAM) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +***/ + +#ifndef SAORIDOWNLOADER_H +#define SAORIDOWNLOADER_H + +#include +#include +#include +#include + +class SaoriDownloader : public QObject +{ + Q_OBJECT +public: + explicit SaoriDownloader(QObject *parent = nullptr); + +protected: + QNetworkAccessManager *m_manager; + +signals: + void downloaded(QNetworkRequest,QByteArray); + void error(QNetworkRequest,QNetworkReply::NetworkError); + +public slots: + void initialize(); + void get(QNetworkRequest req); +}; + +#endif // SAORIDOWNLOADER_H