Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/duckstation-qt/asyncpixmaploader.cpp
14138 views
1
// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#include "asyncpixmaploader.h"
5
#include "qtutils.h"
6
7
#include "core/host.h"
8
9
#include "util/http_cache.h"
10
#include "util/object_archive.h"
11
12
#include "common/error.h"
13
#include "common/heap_array.h"
14
#include "common/log.h"
15
#include "common/path.h"
16
#include "common/small_string.h"
17
18
#include "moc_asyncpixmaploader.cpp"
19
20
LOG_CHANNEL(Host);
21
22
AsyncPixmapLoader::AsyncPixmapLoader(QObject* parent /*= nullptr*/) : QObject(parent)
23
{
24
}
25
26
AsyncPixmapLoader::~AsyncPixmapLoader() = default;
27
28
bool AsyncPixmapLoader::isQueueNeeded(std::string_view url_or_path)
29
{
30
if (!HTTPCache::IsHTTPURL(url_or_path))
31
return false;
32
33
// Don't try to async load when we don't have cache.
34
const auto cache = HTTPCache::GetCacheArchive();
35
return (cache->IsOpen() && !cache->Contains(url_or_path));
36
}
37
38
static std::string_view GetExtensionFromURL(std::string_view url)
39
{
40
return Path::GetExtension(HTTPCache::GetURLFilename(url));
41
}
42
43
static QPixmap LoadPixmapFromSpan(std::string_view extension, std::span<const u8> data)
44
{
45
QPixmap ret;
46
TinyString extension_cstr(extension);
47
if (!ret.loadFromData(data.data(), static_cast<uint>(data.size()),
48
extension_cstr.empty() ? nullptr : extension_cstr.c_str()))
49
{
50
ERROR_LOG("Failed to load pixmap from data for extension '{}'", extension);
51
}
52
53
return ret;
54
}
55
56
QPixmap AsyncPixmapLoader::load(std::string_view url_or_path)
57
{
58
if (!HTTPCache::IsHTTPURL(url_or_path))
59
return QPixmap(QtUtils::StringViewToQString(url_or_path));
60
61
Error error;
62
const HTTPCache::LookupResult result = HTTPCache::Lookup(url_or_path, &error);
63
if (result.status() != HTTPCache::LookupStatus::Hit)
64
{
65
ERROR_LOG("Failed to lookup pixmap for URL '{}': {}", url_or_path, error.GetDescription());
66
return QPixmap();
67
}
68
69
return LoadPixmapFromSpan(GetExtensionFromURL(url_or_path), result->cspan());
70
}
71
72
void AsyncPixmapLoader::enqueue(std::string_view url_or_path)
73
{
74
if (!HTTPCache::IsHTTPURL(url_or_path))
75
{
76
QPixmap pm(QtUtils::StringViewToQString(url_or_path));
77
emit pixmapLoaded(pm);
78
deleteLater();
79
return;
80
}
81
82
Error error;
83
HTTPCache::LookupResult result = HTTPCache::Lookup(url_or_path, &error);
84
85
// gotta load it, this is the yuck part.
86
if (result.status() == HTTPCache::LookupStatus::Miss)
87
{
88
m_extension = GetExtensionFromURL(url_or_path);
89
result = HTTPCache::LookupOrFetch(url_or_path, &error, [this](std::span<const u8> data) mutable {
90
if (!data.empty())
91
m_data.assign(data);
92
QMetaObject::invokeMethod(this, &AsyncPixmapLoader::finishLoad, Qt::QueuedConnection);
93
});
94
}
95
96
if (result.status() == HTTPCache::LookupStatus::Hit)
97
{
98
QPixmap pm = LoadPixmapFromSpan(GetExtensionFromURL(url_or_path), result->cspan());
99
emit pixmapLoaded(pm);
100
deleteLater();
101
return;
102
}
103
else if (result.status() != HTTPCache::LookupStatus::Miss)
104
{
105
ERROR_LOG("Failed to lookup pixmap for URL '{}': {}", url_or_path, error.GetDescription());
106
QPixmap pm;
107
emit pixmapLoaded(pm);
108
deleteLater();
109
return;
110
}
111
}
112
113
void AsyncPixmapLoader::finishLoad()
114
{
115
QPixmap pm = LoadPixmapFromSpan(m_extension, m_data);
116
emit pixmapLoaded(pm);
117
deleteLater();
118
}
119
120