Path: blob/master/src/duckstation-qt/asyncpixmaploader.cpp
14138 views
// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin <[email protected]>1// SPDX-License-Identifier: CC-BY-NC-ND-4.023#include "asyncpixmaploader.h"4#include "qtutils.h"56#include "core/host.h"78#include "util/http_cache.h"9#include "util/object_archive.h"1011#include "common/error.h"12#include "common/heap_array.h"13#include "common/log.h"14#include "common/path.h"15#include "common/small_string.h"1617#include "moc_asyncpixmaploader.cpp"1819LOG_CHANNEL(Host);2021AsyncPixmapLoader::AsyncPixmapLoader(QObject* parent /*= nullptr*/) : QObject(parent)22{23}2425AsyncPixmapLoader::~AsyncPixmapLoader() = default;2627bool AsyncPixmapLoader::isQueueNeeded(std::string_view url_or_path)28{29if (!HTTPCache::IsHTTPURL(url_or_path))30return false;3132// Don't try to async load when we don't have cache.33const auto cache = HTTPCache::GetCacheArchive();34return (cache->IsOpen() && !cache->Contains(url_or_path));35}3637static std::string_view GetExtensionFromURL(std::string_view url)38{39return Path::GetExtension(HTTPCache::GetURLFilename(url));40}4142static QPixmap LoadPixmapFromSpan(std::string_view extension, std::span<const u8> data)43{44QPixmap ret;45TinyString extension_cstr(extension);46if (!ret.loadFromData(data.data(), static_cast<uint>(data.size()),47extension_cstr.empty() ? nullptr : extension_cstr.c_str()))48{49ERROR_LOG("Failed to load pixmap from data for extension '{}'", extension);50}5152return ret;53}5455QPixmap AsyncPixmapLoader::load(std::string_view url_or_path)56{57if (!HTTPCache::IsHTTPURL(url_or_path))58return QPixmap(QtUtils::StringViewToQString(url_or_path));5960Error error;61const HTTPCache::LookupResult result = HTTPCache::Lookup(url_or_path, &error);62if (result.status() != HTTPCache::LookupStatus::Hit)63{64ERROR_LOG("Failed to lookup pixmap for URL '{}': {}", url_or_path, error.GetDescription());65return QPixmap();66}6768return LoadPixmapFromSpan(GetExtensionFromURL(url_or_path), result->cspan());69}7071void AsyncPixmapLoader::enqueue(std::string_view url_or_path)72{73if (!HTTPCache::IsHTTPURL(url_or_path))74{75QPixmap pm(QtUtils::StringViewToQString(url_or_path));76emit pixmapLoaded(pm);77deleteLater();78return;79}8081Error error;82HTTPCache::LookupResult result = HTTPCache::Lookup(url_or_path, &error);8384// gotta load it, this is the yuck part.85if (result.status() == HTTPCache::LookupStatus::Miss)86{87m_extension = GetExtensionFromURL(url_or_path);88result = HTTPCache::LookupOrFetch(url_or_path, &error, [this](std::span<const u8> data) mutable {89if (!data.empty())90m_data.assign(data);91QMetaObject::invokeMethod(this, &AsyncPixmapLoader::finishLoad, Qt::QueuedConnection);92});93}9495if (result.status() == HTTPCache::LookupStatus::Hit)96{97QPixmap pm = LoadPixmapFromSpan(GetExtensionFromURL(url_or_path), result->cspan());98emit pixmapLoaded(pm);99deleteLater();100return;101}102else if (result.status() != HTTPCache::LookupStatus::Miss)103{104ERROR_LOG("Failed to lookup pixmap for URL '{}': {}", url_or_path, error.GetDescription());105QPixmap pm;106emit pixmapLoaded(pm);107deleteLater();108return;109}110}111112void AsyncPixmapLoader::finishLoad()113{114QPixmap pm = LoadPixmapFromSpan(m_extension, m_data);115emit pixmapLoaded(pm);116deleteLater();117}118119120