mirror of
https://github.com/stenzek/duckstation.git
synced 2025-12-28 05:24:19 +00:00
GameList: Improve custom title cover handling
Some checks are pending
Automated Builds / 💻 Windows (push) Waiting to run
Automated Builds / 🐧 Linux AppImage (push) Waiting to run
Automated Builds / 🐧 Linux Cross-Compiled AppImage (push) Waiting to run
Automated Builds / 📦 Linux Flatpak (push) Waiting to run
Automated Builds / 🍎 MacOS (push) Waiting to run
Automated Builds / 📤 Create Release (push) Blocked by required conditions
Some checks are pending
Automated Builds / 💻 Windows (push) Waiting to run
Automated Builds / 🐧 Linux AppImage (push) Waiting to run
Automated Builds / 🐧 Linux Cross-Compiled AppImage (push) Waiting to run
Automated Builds / 📦 Linux Flatpak (push) Waiting to run
Automated Builds / 🍎 MacOS (push) Waiting to run
Automated Builds / 📤 Create Release (push) Blocked by required conditions
Prefer the custom title path over the serial if one is present. Also use sanitized names.
This commit is contained in:
parent
f45350898b
commit
f0ff520a9d
@ -1201,56 +1201,51 @@ void GameList::CreateDiscSetEntries(const std::vector<std::string>& excluded_pat
|
||||
|
||||
std::string GameList::GetCoverImagePathForEntry(const Entry* entry)
|
||||
{
|
||||
return GetCoverImagePath(entry->path, entry->serial, entry->GetSaveTitle());
|
||||
return GetCoverImagePath(entry->path, entry->serial, entry->GetSaveTitle(), entry->has_custom_title);
|
||||
}
|
||||
|
||||
static std::string GetFullCoverPath(std::string_view filename, std::string_view extension)
|
||||
static std::string GetFullCoverPath(std::string_view title, std::string_view extension)
|
||||
{
|
||||
return fmt::format("{}" FS_OSPATH_SEPARATOR_STR "{}.{}", EmuFolders::Covers, filename, extension);
|
||||
std::string filename = fmt::format("{}.{}", title, extension);
|
||||
Path::SanitizeFileName(&filename);
|
||||
return Path::Combine(EmuFolders::Covers, filename);
|
||||
}
|
||||
|
||||
std::string GameList::GetCoverImagePath(const std::string_view path, const std::string_view serial,
|
||||
const std::string_view title)
|
||||
const std::string_view title, bool is_custom_title)
|
||||
{
|
||||
static constexpr const std::array extensions = {"jpg", "jpeg", "png", "webp"};
|
||||
std::string ret;
|
||||
|
||||
for (const char* extension : extensions)
|
||||
{
|
||||
// Prioritize lookup by serial (Most specific)
|
||||
if (!serial.empty())
|
||||
const auto try_name = [&ret](std::string_view name) {
|
||||
for (const char* extension : extensions)
|
||||
{
|
||||
std::string cover_path(GetFullCoverPath(serial, extension));
|
||||
std::string cover_path = GetFullCoverPath(name, extension);
|
||||
if (FileSystem::FileExists(cover_path.c_str()))
|
||||
{
|
||||
ret = std::move(cover_path);
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Try file title (for modded games or specific like above)
|
||||
const std::string_view file_title(Path::GetFileTitle(path));
|
||||
if (!file_title.empty() && title != file_title)
|
||||
{
|
||||
std::string cover_path(GetFullCoverPath(file_title, extension));
|
||||
if (FileSystem::FileExists(cover_path.c_str()))
|
||||
{
|
||||
ret = std::move(cover_path);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
// Check the title first if this is a custom title
|
||||
if (is_custom_title && try_name(title))
|
||||
return ret;
|
||||
|
||||
// Last resort, check the game title
|
||||
if (!title.empty())
|
||||
{
|
||||
std::string cover_path(GetFullCoverPath(title, extension));
|
||||
if (FileSystem::FileExists(cover_path.c_str()))
|
||||
{
|
||||
ret = std::move(cover_path);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Prioritize lookup by serial (Most specific)
|
||||
if (!serial.empty() && try_name(serial))
|
||||
return ret;
|
||||
|
||||
// Try file title (for modded games or specific like above)
|
||||
const std::string_view file_title = Path::GetFileTitle(path);
|
||||
if (!file_title.empty() && (title != file_title || is_custom_title) && try_name(file_title))
|
||||
return ret;
|
||||
|
||||
// Last resort, check the game title
|
||||
if (!title.empty() && !is_custom_title && try_name(title))
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -143,7 +143,8 @@ std::string FormatTimestamp(std::time_t timestamp);
|
||||
TinyString FormatTimespan(std::time_t timespan, bool long_format = false);
|
||||
|
||||
std::string GetCoverImagePathForEntry(const Entry* entry);
|
||||
std::string GetCoverImagePath(const std::string_view path, const std::string_view serial, const std::string_view title);
|
||||
std::string GetCoverImagePath(const std::string_view path, const std::string_view serial, const std::string_view title,
|
||||
bool is_custom_title);
|
||||
std::string GetNewCoverImagePathForEntry(const Entry* entry, const char* new_filename, bool use_serial);
|
||||
|
||||
/// Returns a list of (title, entry) for entries matching serials. Titles will match the gamedb title,
|
||||
|
||||
@ -312,9 +312,11 @@ void GameListModel::loadOrGenerateCover(const GameList::Entry* ge)
|
||||
QtAsyncTask::create(this, [path = ge->path, serial = ge->serial, save_title = std::string(ge->GetSaveTitle()),
|
||||
display_title = QtUtils::StringViewToQString(ge->GetDisplayTitle(m_show_localized_titles)),
|
||||
placeholder_image = m_placeholder_image, list = this, width = getCoverArtSize(),
|
||||
height = getCoverArtSize(), scale = m_cover_scale, dpr = m_device_pixel_ratio]() mutable {
|
||||
height = getCoverArtSize(), scale = m_cover_scale, dpr = m_device_pixel_ratio,
|
||||
is_custom_title = ge->has_custom_title]() mutable {
|
||||
QImage image;
|
||||
loadOrGenerateCover(image, placeholder_image, width, height, scale, dpr, path, serial, save_title, display_title);
|
||||
loadOrGenerateCover(image, placeholder_image, width, height, scale, dpr, path, serial, save_title, display_title,
|
||||
is_custom_title);
|
||||
return [path = std::move(path), image = std::move(image), list, scale]() { list->coverLoaded(path, image, scale); };
|
||||
});
|
||||
}
|
||||
@ -353,9 +355,10 @@ void GameListModel::createPlaceholderImage(QImage& image, const QImage& placehol
|
||||
|
||||
void GameListModel::loadOrGenerateCover(QImage& image, const QImage& placeholder_image, int width, int height,
|
||||
float scale, qreal dpr, const std::string& path, const std::string& serial,
|
||||
const std::string& save_title, const QString& display_title)
|
||||
const std::string& save_title, const QString& display_title,
|
||||
bool is_custom_title)
|
||||
{
|
||||
const std::string cover_path(GameList::GetCoverImagePath(path, serial, save_title));
|
||||
const std::string cover_path = GameList::GetCoverImagePath(path, serial, save_title, is_custom_title);
|
||||
if (!cover_path.empty())
|
||||
{
|
||||
image.load(QString::fromStdString(cover_path));
|
||||
|
||||
@ -130,7 +130,7 @@ private:
|
||||
|
||||
static void loadOrGenerateCover(QImage& image, const QImage& placeholder_image, int width, int height, float scale,
|
||||
qreal dpr, const std::string& path, const std::string& serial,
|
||||
const std::string& save_title, const QString& display_title);
|
||||
const std::string& save_title, const QString& display_title, bool is_custom_title);
|
||||
static void createPlaceholderImage(QImage& image, const QImage& placeholder_image, int width, int height, float scale,
|
||||
const QString& title);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user