1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
// SPDX-FileCopyrightText: 2020 Jonah BrĂ¼chert <jbb@kaidan.im>
// SPDX-FileCopyrightText: 2020 Rinigus <rinigus.git@gmail.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
#include "iconimageprovider.h"
#include <QBuffer>
#include <QByteArray>
#include <QImage>
#include <QPixmap>
#include <QQmlApplicationEngine>
#include <QString>
#include <QCoroFuture>
#include <QCoroSignal>
#include <QCoroTask>
#include "browsermanager.h"
IconImageProvider::IconImageProvider()
: QCoro::ImageProvider()
{
}
QString IconImageProvider::providerId()
{
return QStringLiteral("angelfish-favicon");
}
QCoro::Task<QImage> IconImageProvider::asyncRequestImage(const QString &id, const QSize & /*requestedSize*/)
{
auto url = QStringLiteral("image://%1/%2%").arg(providerId(), id);
auto icon = co_await BrowserManager::instance()
->databaseManager()
->database()
->getResult<SingleValue<QByteArray>>(QStringLiteral("SELECT icon FROM icons WHERE url LIKE ? LIMIT 1"), url);
if (icon) {
co_return QImage::fromData(icon->value);
}
qWarning() << "Failed to find icon for" << id;
co_return {};
}
QCoro::Task<QString> storeIcon(QQmlEngine *engine, const QString &iconSource)
{
if (iconSource.isEmpty()) {
co_return {};
}
const QLatin1String prefix_favicon = QLatin1String("image://favicon/");
if (!iconSource.startsWith(prefix_favicon)) {
// don't know what to do with it, return as it is
qWarning() << Q_FUNC_INFO << "Don't know how to store image" << iconSource;
co_return iconSource;
}
// new uri for image
QString url = QStringLiteral("image://%1/%2").arg(IconImageProvider::providerId(), iconSource.mid(prefix_favicon.size()));
// check if we have that image already
bool alreadyExists = (co_await BrowserManager::instance()
->databaseManager()
->database()
->getResult<SingleValue<bool>>(
QStringLiteral("SELECT COUNT(url) > 0 FROM icons WHERE url = ? LIMIT 1"), url))
.value()
.value;
if (alreadyExists) {
co_return url;
}
// Store new icon
QQuickAsyncImageProvider *provider = dynamic_cast<QQuickAsyncImageProvider *>(engine->imageProvider(QStringLiteral("favicon")));
if (!provider) {
qWarning() << Q_FUNC_INFO << "Failed to load image provider" << url;
co_return iconSource; // as something is wrong
}
QByteArray data;
QBuffer buffer(&data);
buffer.open(QIODevice::WriteOnly);
const QSize szRequested;
const QString providerIconName = iconSource.mid(prefix_favicon.size());
const QImage imageToSave = co_await [=]() -> QCoro::Task<QImage> {
switch (provider->imageType()) {
case QQmlImageProviderBase::Image: {
co_return provider->requestImage(providerIconName, nullptr, szRequested);
}
case QQmlImageProviderBase::Pixmap: {
const QPixmap image = provider->requestPixmap(providerIconName, nullptr, szRequested);
co_return image.toImage();
}
case QQmlImageProviderBase::Texture: {
co_return provider->requestTexture(providerIconName, nullptr, szRequested)->image();
}
case QQmlImageProviderBase::ImageResponse: {
auto response = provider->requestImageResponse(providerIconName, szRequested);
co_await qCoro(response, &QQuickImageResponse::finished);
co_return response->textureFactory()->image();
}
default:
qWarning() << Q_FUNC_INFO << "Unsupported image provider" << provider->imageType();
co_return {}; // as something is wrong
}
}();
if (!imageToSave.save(&buffer, "PNG")) {
qWarning() << Q_FUNC_INFO << "Failed to save image" << url;
co_return iconSource; // as something is wrong
}
co_await BrowserManager::instance()
->databaseManager()
->database()
->execute(QStringLiteral("INSERT INTO icons(url, icon) VALUES (?, ?)"), url, data);
co_return url;
}
|