Cache images and correctly save relative image paths

This commit is contained in:
Tobias Fella 2020-04-25 22:16:19 +02:00
parent 3977aa7e41
commit 7328745bef
9 changed files with 72 additions and 25 deletions

View File

@ -72,3 +72,8 @@ void EntryListModel::fetch()
{ {
Fetcher::instance().fetch(QUrl(m_feed)); Fetcher::instance().fetch(QUrl(m_feed));
} }
QString EntryListModel::image(QString url)
{
return Fetcher::instance().image(url);
}

View File

@ -42,6 +42,7 @@ public:
QHash<int, QByteArray> roleNames() const override; QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE void fetch(); Q_INVOKABLE void fetch();
Q_INVOKABLE QString image(QString url);
QString feed() const; QString feed() const;
void setFeed(QString feed); void setFeed(QString feed);

View File

@ -20,7 +20,6 @@
#include <QDebug> #include <QDebug>
#include <QModelIndex> #include <QModelIndex>
#include <QSqlError>
#include <QSqlRecord> #include <QSqlRecord>
#include <QUrl> #include <QUrl>
@ -35,6 +34,10 @@ FeedListModel::FeedListModel(QObject *parent)
setSort(0, Qt::AscendingOrder); setSort(0, Qt::AscendingOrder);
setEditStrategy(OnFieldChange); setEditStrategy(OnFieldChange);
select(); select();
connect(&Fetcher::instance(), &Fetcher::updated, this, [this]() {
select();
});
} }
QHash<int, QByteArray> FeedListModel::roleNames() const QHash<int, QByteArray> FeedListModel::roleNames() const
@ -62,11 +65,6 @@ void FeedListModel::addFeed(QString url)
insertRecord(-1, rec); insertRecord(-1, rec);
connect(&Fetcher::instance(), &Fetcher::updated, this, [this]() {
select();
disconnect(&Fetcher::instance(), &Fetcher::updated, nullptr, nullptr);
});
Fetcher::instance().fetch(QUrl(url)); Fetcher::instance().fetch(QUrl(url));
} }
@ -102,3 +100,8 @@ void FeedListModel::removeFeed(int index)
Database::instance().execute(query); Database::instance().execute(query);
select(); select();
} }
QString FeedListModel::image(QString url)
{
return Fetcher::instance().image(url);
}

View File

@ -43,6 +43,7 @@ public:
Q_INVOKABLE void addFeed(QString url); Q_INVOKABLE void addFeed(QString url);
Q_INVOKABLE void removeFeed(int index); Q_INVOKABLE void removeFeed(int index);
Q_INVOKABLE QString image(QString url);
private: private:
bool feedExists(QString url); bool feedExists(QString url);

View File

@ -20,6 +20,9 @@
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkReply> #include <QNetworkReply>
#include <QFile>
#include <QStandardPaths>
#include <QFileInfo>
#include <Syndication/Syndication> #include <Syndication/Syndication>
@ -28,17 +31,17 @@
Fetcher::Fetcher() Fetcher::Fetcher()
{ {
manager = new QNetworkAccessManager(this);
manager->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
manager->setStrictTransportSecurityEnabled(true);
manager->enableStrictTransportSecurityStore(true);
} }
void Fetcher::fetch(QUrl url) void Fetcher::fetch(QUrl url)
{ {
qDebug() << "Starting to fetch" << url.toString(); qDebug() << "Starting to fetch" << url.toString();
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
manager->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
manager->setStrictTransportSecurityEnabled(true);
manager->enableStrictTransportSecurityStore(true);
QNetworkRequest request = QNetworkRequest(QUrl(url)); QNetworkRequest request(url);
QNetworkReply *reply = manager->get(request); QNetworkReply *reply = manager->get(request);
connect(reply, &QNetworkReply::finished, this, [this, url, reply]() { connect(reply, &QNetworkReply::finished, this, [this, url, reply]() {
QByteArray data = reply->readAll(); QByteArray data = reply->readAll();
@ -53,7 +56,11 @@ void Fetcher::fetch(QUrl url)
query.prepare(QStringLiteral("UPDATE Feeds SET name=:name, image=:image WHERE url=:url;")); query.prepare(QStringLiteral("UPDATE Feeds SET name=:name, image=:image WHERE url=:url;"));
query.bindValue(QStringLiteral(":name"), feed->title()); query.bindValue(QStringLiteral(":name"), feed->title());
query.bindValue(QStringLiteral(":url"), url.toString()); query.bindValue(QStringLiteral(":url"), url.toString());
query.bindValue(QStringLiteral(":image"), feed->image()->url()); if(feed->image()->url().startsWith(QStringLiteral("/"))) {
QString absolute = url.adjusted(QUrl::RemovePath).toString() + feed->image()->url();
query.bindValue(QStringLiteral(":image"), absolute);
} else
query.bindValue(QStringLiteral(":image"), feed->image()->url());
Database::instance().execute(query); Database::instance().execute(query);
qDebug() << "Updated feed title:" << feed->title(); qDebug() << "Updated feed title:" << feed->title();
@ -91,3 +98,27 @@ void Fetcher::fetch(QUrl url)
delete reply; delete reply;
}); });
} }
QString Fetcher::image(QString url)
{
QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/") + QString::fromStdString(QCryptographicHash::hash(url.toUtf8(), QCryptographicHash::Md5).toHex().toStdString());
if(QFileInfo(path).exists()) {
return path;
}
QNetworkRequest request((QUrl(url)));
QNetworkReply *reply = manager->get(request);
connect(reply, &QNetworkReply::finished, this, [this, url, reply, path]() {
QByteArray data = reply->readAll();
QFile file(path);
file.open(QIODevice::WriteOnly);
file.write(data);
file.close();
emit updated();
delete reply;
});
return QStringLiteral("");
}

View File

@ -22,6 +22,7 @@
#include <QObject> #include <QObject>
#include <QUrl> #include <QUrl>
#include <QNetworkAccessManager>
class Fetcher : public QObject class Fetcher : public QObject
{ {
@ -33,11 +34,14 @@ public:
return _instance; return _instance;
} }
void fetch(QUrl); void fetch(QUrl);
QString image(QString);
private: private:
Fetcher(); Fetcher();
Fetcher(const Fetcher &); Fetcher(const Fetcher &);
QNetworkAccessManager *manager;
Q_SIGNALS: Q_SIGNALS:
void updated(); void updated();
}; };

View File

@ -35,8 +35,8 @@
#include "alligatorsettings.h" #include "alligatorsettings.h"
#include "database.h" #include "database.h"
#include "entryListModel.h" #include "entryListModel.h"
#include "feed.h"
#include "feedListModel.h" #include "feedListModel.h"
#include "fetcher.h"
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
Q_DECL_EXPORT Q_DECL_EXPORT

View File

@ -29,9 +29,11 @@ import org.kde.alligator 1.0
Kirigami.ScrollablePage { Kirigami.ScrollablePage {
id: page id: page
property var data property var name
property var url
property var image
property var all: page.data.url === "all" property var all: page.feedData.url === "all"
contextualActions: [ contextualActions: [
Kirigami.Action { Kirigami.Action {
@ -59,21 +61,21 @@ Kirigami.ScrollablePage {
visible: count !== 0 visible: count !== 0
model: EntryListModel { model: EntryListModel {
id: entryListModel id: entryListModel
feed: page.data.url feed: page.url
} }
header: RowLayout { header: RowLayout {
width: parent.width width: parent.width
height: page.height * 0.2 height: root.height * 0.2
visible: !all visible: !all
Image { Kirigami.Icon {
source: page.data.image source: entryListModel.image(page.image)
fillMode: Image.PreserveAspectFit width: height
sourceSize.width: 0 height: parent.height
sourceSize.height: parent.height Component.onCompleted: console.log("Height: " + page.height)
} }
Kirigami.Heading { Kirigami.Heading {
text: page.data.name text: page.name
} }
} }

View File

@ -101,7 +101,7 @@ Kirigami.ScrollablePage {
Item { Item {
Kirigami.Icon { Kirigami.Icon {
id: icon id: icon
source: model.image source: feedListModel.image(model.image)
width: height width: height
height: parent.height height: parent.height
} }
@ -128,7 +128,7 @@ Kirigami.ScrollablePage {
onClicked: { onClicked: {
lastFeed = model.url lastFeed = model.url
pageStack.push("qrc:/EntryListPage.qml", {"data": model}) pageStack.push("qrc:/EntryListPage.qml", {"name": name, "url": url, "image": image})
} }
} }
} }