File: iconimageprovider.cpp

package info (click to toggle)
angelfish 25.04.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,740 kB
  • sloc: cpp: 2,703; xml: 611; javascript: 273; makefile: 16; sh: 11; sql: 7
file content (124 lines) | stat: -rw-r--r-- 4,126 bytes parent folder | download
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;
}