mirror of
https://github.com/stenzek/duckstation.git
synced 2026-02-07 23:04:32 +00:00
GameDatabase: Add sort title, localized title, and save title fields
This commit is contained in:
@@ -1994,7 +1994,8 @@ bool Cheats::ImportOldChtFile(const std::string_view serial)
|
||||
if (!dbentry || dbentry->title.empty())
|
||||
return false;
|
||||
|
||||
const std::string old_path = fmt::format("{}" FS_OSPATH_SEPARATOR_STR "{}.cht", EmuFolders::Cheats, dbentry->title);
|
||||
const std::string old_path =
|
||||
fmt::format("{}" FS_OSPATH_SEPARATOR_STR "{}.cht", EmuFolders::Cheats, dbentry->GetSaveTitle());
|
||||
if (!FileSystem::FileExists(old_path.c_str()))
|
||||
return false;
|
||||
|
||||
|
||||
@@ -7873,7 +7873,7 @@ void FullscreenUI::PopulateGameListEntryList()
|
||||
}
|
||||
|
||||
// fallback to title when all else is equal
|
||||
const int res = StringUtil::Strcasecmp(lhs->title.c_str(), rhs->title.c_str());
|
||||
const int res = StringUtil::CompareNoCase(lhs->GetSortTitle(), rhs->GetSortTitle());
|
||||
return reverse ? (res > 0) : (res < 0);
|
||||
});
|
||||
}
|
||||
@@ -8026,7 +8026,7 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
|
||||
summary.format("{} | {} | {} MB", entry->serial, Path::GetFileName(entry->path), to_mb(entry->file_size));
|
||||
}
|
||||
|
||||
const ImGuiFullscreen::MenuButtonBounds mbb(entry->title, {}, summary, row_left_margin);
|
||||
const ImGuiFullscreen::MenuButtonBounds mbb(entry->GetDisplayTitle(), {}, summary, row_left_margin);
|
||||
|
||||
bool visible, hovered;
|
||||
bool pressed = MenuButtonFrame(entry->path, true, mbb.frame_bb, &visible, &hovered);
|
||||
@@ -8042,8 +8042,8 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
|
||||
ImGui::GetWindowDrawList()->AddImage(cover_texture, image_rect.Min, image_rect.Max, ImVec2(0.0f, 0.0f),
|
||||
ImVec2(1.0f, 1.0f), IM_COL32(255, 255, 255, 255));
|
||||
RenderShadowedTextClipped(UIStyle.Font, UIStyle.LargeFontSize, UIStyle.BoldFontWeight, mbb.title_bb.Min,
|
||||
mbb.title_bb.Max, text_color, entry->title, &mbb.title_size, ImVec2(0.0f, 0.0f),
|
||||
mbb.title_size.x, &mbb.title_bb);
|
||||
mbb.title_bb.Max, text_color, entry->GetDisplayTitle(), &mbb.title_size,
|
||||
ImVec2(0.0f, 0.0f), mbb.title_size.x, &mbb.title_bb);
|
||||
|
||||
if (!summary.empty())
|
||||
{
|
||||
@@ -8145,12 +8145,13 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
|
||||
if (selected_entry)
|
||||
{
|
||||
const ImVec4 subtitle_text_color = DarkerColor(ImGui::GetStyle().Colors[ImGuiCol_Text]);
|
||||
const std::string_view title = selected_entry->GetDisplayTitle();
|
||||
|
||||
// title
|
||||
ImGui::PushFont(UIStyle.Font, UIStyle.LargeFontSize, UIStyle.BoldFontWeight);
|
||||
text_width = ImGui::CalcTextSize(selected_entry->title.c_str(), nullptr, false, work_width).x;
|
||||
text_width = ImGui::CalcTextSize(IMSTR_START_END(title), false, work_width).x;
|
||||
ImGui::SetCursorPosX((work_width - text_width) / 2.0f);
|
||||
ImGui::TextWrapped("%s", selected_entry->title.c_str());
|
||||
ImGui::TextWrapped("%.*s", static_cast<int>(title.size()), title.data());
|
||||
ImGui::PopFont();
|
||||
|
||||
ImGui::PushFont(UIStyle.Font, UIStyle.MediumFontSize, UIStyle.BoldFontWeight);
|
||||
@@ -8388,8 +8389,9 @@ void FullscreenUI::DrawGameGrid(const ImVec2& heading_size)
|
||||
for (size_t row_entry_index = entry_index; row_entry_index < row_entry_index_end; row_entry_index++)
|
||||
{
|
||||
const GameList::Entry* row_entry = s_state.game_list_sorted_entries[row_entry_index];
|
||||
const std::string_view row_title = row_entry->GetDisplayTitle();
|
||||
const ImVec2 this_title_size = UIStyle.Font->CalcTextSizeA(title_font_size, title_font_weight, image_width,
|
||||
image_width, IMSTR_START_END(row_entry->title));
|
||||
image_width, IMSTR_START_END(row_title));
|
||||
row_item_height = std::max(row_item_height, this_title_size.y);
|
||||
}
|
||||
|
||||
@@ -8399,8 +8401,9 @@ void FullscreenUI::DrawGameGrid(const ImVec2& heading_size)
|
||||
ImVec2 title_size;
|
||||
if (s_state.game_grid_show_titles)
|
||||
{
|
||||
const std::string_view title = entry->GetDisplayTitle();
|
||||
title_size = UIStyle.Font->CalcTextSizeA(title_font_size, title_font_weight, image_width, image_width,
|
||||
IMSTR_START_END(entry->title));
|
||||
IMSTR_START_END(title));
|
||||
}
|
||||
|
||||
const ImGuiID id = window->GetID(entry->path.c_str(), entry->path.c_str() + entry->path.length());
|
||||
@@ -8448,9 +8451,9 @@ void FullscreenUI::DrawGameGrid(const ImVec2& heading_size)
|
||||
if (draw_title)
|
||||
{
|
||||
const ImRect title_bb(ImVec2(bb.Min.x, bb.Min.y + image_height + title_spacing), bb.Max);
|
||||
ImGuiFullscreen::RenderMultiLineShadowedTextClipped(dl, UIStyle.Font, title_font_size, title_font_weight,
|
||||
title_bb.Min, title_bb.Max, text_color, entry->title,
|
||||
LAYOUT_CENTER_ALIGN_TEXT, image_width, &title_bb);
|
||||
ImGuiFullscreen::RenderMultiLineShadowedTextClipped(
|
||||
dl, UIStyle.Font, title_font_size, title_font_weight, title_bb.Min, title_bb.Max, text_color,
|
||||
entry->GetDisplayTitle(), LAYOUT_CENTER_ALIGN_TEXT, image_width, &title_bb);
|
||||
}
|
||||
|
||||
if (pressed)
|
||||
@@ -8517,7 +8520,7 @@ void FullscreenUI::HandleGameListOptions(const GameList::Entry* entry)
|
||||
};
|
||||
|
||||
OpenChoiceDialog(
|
||||
entry->title.c_str(), false, std::move(options),
|
||||
entry->GetDisplayTitle(), false, std::move(options),
|
||||
[entry_path = entry->path, entry_serial = entry->serial](s32 index, const std::string& title,
|
||||
bool checked) mutable {
|
||||
switch (index)
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace GameDatabase {
|
||||
enum : u32
|
||||
{
|
||||
GAME_DATABASE_CACHE_SIGNATURE = 0x45434C48,
|
||||
GAME_DATABASE_CACHE_VERSION = 28,
|
||||
GAME_DATABASE_CACHE_VERSION = 29,
|
||||
};
|
||||
|
||||
static const Entry* GetEntryForId(std::string_view code);
|
||||
@@ -360,6 +360,21 @@ SmallString GameDatabase::Entry::GetLanguagesString() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string_view GameDatabase::Entry::GetDisplayTitle() const
|
||||
{
|
||||
return !localized_title.empty() ? localized_title : title;
|
||||
}
|
||||
|
||||
std::string_view GameDatabase::Entry::GetSortTitle() const
|
||||
{
|
||||
return !sort_title.empty() ? sort_title : title;
|
||||
}
|
||||
|
||||
std::string_view GameDatabase::Entry::GetSaveTitle() const
|
||||
{
|
||||
return !save_title.empty() ? save_title : title;
|
||||
}
|
||||
|
||||
void GameDatabase::Entry::ApplySettings(Settings& settings, bool display_osd_messages) const
|
||||
{
|
||||
if (display_active_start_offset.has_value())
|
||||
@@ -917,8 +932,14 @@ static inline void AppendEnumSetting(SmallStringBase& str, bool& heading, std::s
|
||||
std::string GameDatabase::Entry::GenerateCompatibilityReport() const
|
||||
{
|
||||
LargeString ret;
|
||||
ret.append_format("**{}:** {}\n\n", TRANSLATE_SV("GameDatabase", "Title"), title);
|
||||
ret.append_format("**{}:** {}\n\n", TRANSLATE_SV("GameDatabase", "Serial"), serial);
|
||||
ret.append_format("**{}:** {}\n\n", TRANSLATE_SV("GameDatabase", "Title"), title);
|
||||
if (!sort_title.empty())
|
||||
ret.append_format("**{}:** {}\n\n", TRANSLATE_SV("GameDatabase", "Sort Title"), title);
|
||||
if (!localized_title.empty())
|
||||
ret.append_format("**{}:** {}\n\n", TRANSLATE_SV("GameDatabase", "Localized Title"), title);
|
||||
if (!save_title.empty())
|
||||
ret.append_format("**{}:** {}\n\n", TRANSLATE_SV("GameDatabase", "Save Title"), title);
|
||||
|
||||
if (languages.any())
|
||||
ret.append_format("**{}:** {}\n\n", TRANSLATE_SV("GameDatabase", "Languages"), GetLanguagesString());
|
||||
@@ -1052,8 +1073,9 @@ bool GameDatabase::LoadFromCache()
|
||||
u32 num_disc_set_serials;
|
||||
|
||||
if (!reader.ReadSizePrefixedString(&entry.serial) || !reader.ReadSizePrefixedString(&entry.title) ||
|
||||
!reader.ReadSizePrefixedString(&entry.genre) || !reader.ReadSizePrefixedString(&entry.developer) ||
|
||||
!reader.ReadSizePrefixedString(&entry.publisher) ||
|
||||
!reader.ReadSizePrefixedString(&entry.sort_title) || !reader.ReadSizePrefixedString(&entry.localized_title) ||
|
||||
!reader.ReadSizePrefixedString(&entry.save_title) || !reader.ReadSizePrefixedString(&entry.genre) ||
|
||||
!reader.ReadSizePrefixedString(&entry.developer) || !reader.ReadSizePrefixedString(&entry.publisher) ||
|
||||
!reader.ReadSizePrefixedString(&entry.compatibility_version_tested) ||
|
||||
!reader.ReadSizePrefixedString(&entry.compatibility_comments) || !reader.ReadU64(&entry.release_date) ||
|
||||
!reader.ReadU8(&entry.min_players) || !reader.ReadU8(&entry.max_players) || !reader.ReadU8(&entry.min_blocks) ||
|
||||
@@ -1145,6 +1167,9 @@ bool GameDatabase::SaveToCache()
|
||||
{
|
||||
writer.WriteSizePrefixedString(entry.serial);
|
||||
writer.WriteSizePrefixedString(entry.title);
|
||||
writer.WriteSizePrefixedString(entry.sort_title);
|
||||
writer.WriteSizePrefixedString(entry.localized_title);
|
||||
writer.WriteSizePrefixedString(entry.save_title);
|
||||
writer.WriteSizePrefixedString(entry.genre);
|
||||
writer.WriteSizePrefixedString(entry.developer);
|
||||
writer.WriteSizePrefixedString(entry.publisher);
|
||||
@@ -1282,6 +1307,9 @@ bool GameDatabase::LoadGameDBYaml()
|
||||
bool GameDatabase::ParseYamlEntry(Entry* entry, const ryml::ConstNodeRef& value)
|
||||
{
|
||||
GetStringFromObject(value, "name", &entry->title);
|
||||
GetStringFromObject(value, "sortName", &entry->sort_title);
|
||||
GetStringFromObject(value, "localizedName", &entry->localized_title);
|
||||
GetStringFromObject(value, "saveName", &entry->save_title);
|
||||
|
||||
entry->supported_controllers = static_cast<u16>(~0u);
|
||||
|
||||
|
||||
@@ -100,53 +100,75 @@ struct Entry
|
||||
{
|
||||
static constexpr u16 SUPPORTS_MULTITAP_BIT = (1u << static_cast<u8>(ControllerType::Count));
|
||||
|
||||
std::string_view serial;
|
||||
std::string_view title;
|
||||
std::string_view genre;
|
||||
std::string_view developer;
|
||||
std::string_view publisher;
|
||||
std::string_view compatibility_version_tested;
|
||||
std::string_view compatibility_comments;
|
||||
u64 release_date; ///< Number of seconds since Epoch.
|
||||
u8 min_players;
|
||||
u8 max_players;
|
||||
u8 min_blocks;
|
||||
u8 max_blocks;
|
||||
u16 supported_controllers;
|
||||
CompatibilityRating compatibility;
|
||||
std::string_view serial; ///< Official serial of the game, e.g. "SLUS-00001".
|
||||
std::string_view title; ///< Official title of the game.
|
||||
std::string_view sort_title; ///< Title used for sorting in game lists.
|
||||
std::string_view localized_title; ///< Title in the native language, if available.
|
||||
std::string_view save_title; ///< Title used for per-game memory cards.
|
||||
std::string_view genre; ///< Genre of the game.
|
||||
std::string_view developer; ///< Developer of the game.
|
||||
std::string_view publisher; ///< Publisher of the game.
|
||||
std::string_view compatibility_version_tested; ///< Version of the application the game was tested with.
|
||||
std::string_view compatibility_comments; ///< Comments about the game's compatibility.
|
||||
u64 release_date; ///< Number of seconds since Epoch.
|
||||
u8 min_players; ///< Minimum number of players supported.
|
||||
u8 max_players; ///< Maximum number of players supported.
|
||||
u8 min_blocks; ///< Minimum number of blocks the game uses.
|
||||
u8 max_blocks; ///< Maximum number of blocks the game uses.
|
||||
u16 supported_controllers; ///< Bitfield of supported controllers.
|
||||
CompatibilityRating compatibility; ///< Compatibility rating of the game.
|
||||
|
||||
std::bitset<static_cast<size_t>(Trait::MaxCount)> traits{};
|
||||
std::bitset<static_cast<size_t>(Language::MaxCount)> languages{};
|
||||
std::optional<s16> display_active_start_offset;
|
||||
std::optional<s16> display_active_end_offset;
|
||||
std::optional<s8> display_line_start_offset;
|
||||
std::optional<s8> display_line_end_offset;
|
||||
std::optional<DisplayCropMode> display_crop_mode;
|
||||
std::optional<DisplayDeinterlacingMode> display_deinterlacing_mode;
|
||||
std::optional<GPULineDetectMode> gpu_line_detect_mode;
|
||||
std::optional<u8> cpu_overclock;
|
||||
std::optional<u32> dma_max_slice_ticks;
|
||||
std::optional<u32> dma_halt_ticks;
|
||||
std::optional<u32> cdrom_max_seek_speedup_cycles;
|
||||
std::optional<u32> cdrom_max_read_speedup_cycles;
|
||||
std::optional<u32> gpu_fifo_size;
|
||||
std::optional<u32> gpu_max_run_ahead;
|
||||
std::optional<float> gpu_pgxp_tolerance;
|
||||
std::optional<float> gpu_pgxp_depth_threshold;
|
||||
std::optional<bool> gpu_pgxp_preserve_proj_fp;
|
||||
std::bitset<static_cast<size_t>(Trait::MaxCount)> traits{}; ///< Traits for the game.
|
||||
std::bitset<static_cast<size_t>(Language::MaxCount)> languages{}; ///< Languages supported by the game.
|
||||
std::optional<s16> display_active_start_offset; ///< Display active start offset override.
|
||||
std::optional<s16> display_active_end_offset; ///< Display active end offset override.
|
||||
std::optional<s8> display_line_start_offset; ///< Display line start offset override.
|
||||
std::optional<s8> display_line_end_offset; ///< Display line end offset override.
|
||||
std::optional<DisplayCropMode> display_crop_mode; ///< Display crop mode override.
|
||||
std::optional<DisplayDeinterlacingMode> display_deinterlacing_mode; ///< Display deinterlacing mode override.
|
||||
std::optional<GPULineDetectMode> gpu_line_detect_mode; ///< GPU line detect mode override.
|
||||
std::optional<u8> cpu_overclock; ///< CPU overclock percentage override.
|
||||
std::optional<u32> dma_max_slice_ticks; ///< DMA max slice ticks override.
|
||||
std::optional<u32> dma_halt_ticks; ///< DMA halt ticks override.
|
||||
std::optional<u32> cdrom_max_seek_speedup_cycles; ///< CD-ROM max seek speedup cycles override.
|
||||
std::optional<u32> cdrom_max_read_speedup_cycles; ///< CD-ROM max read speedup cycles override.
|
||||
std::optional<u32> gpu_fifo_size; ///< GPU FIFO size override.
|
||||
std::optional<u32> gpu_max_run_ahead; ///< GPU max runahead override.
|
||||
std::optional<float> gpu_pgxp_tolerance; ///< GPU PGXP tolerance override.
|
||||
std::optional<float> gpu_pgxp_depth_threshold; ///< GPU PGXP depth threshold override.
|
||||
std::optional<bool> gpu_pgxp_preserve_proj_fp; ///< GPU PGXP preserve projection precision override.
|
||||
|
||||
std::string_view disc_set_name;
|
||||
std::vector<std::string_view> disc_set_serials;
|
||||
std::string_view disc_set_name; ///< Name of the disc set, if applicable.
|
||||
std::vector<std::string_view> disc_set_serials; ///< Serials of all discs in the set.
|
||||
|
||||
/// Checks if a trait is present.
|
||||
ALWAYS_INLINE bool HasTrait(Trait trait) const { return traits[static_cast<int>(trait)]; }
|
||||
|
||||
/// Checks if a language is present.
|
||||
ALWAYS_INLINE bool HasLanguage(Language language) const { return languages.test(static_cast<size_t>(language)); }
|
||||
|
||||
/// Checks if any language is present.
|
||||
ALWAYS_INLINE bool HasAnyLanguage() const { return languages.any(); }
|
||||
|
||||
/// Returns the flag for the game's language if it only has one, and it is not English. Otherwise the region.
|
||||
std::string_view GetLanguageFlagName(DiscRegion region) const;
|
||||
|
||||
/// Returns a comma-separated list of language names.
|
||||
SmallString GetLanguagesString() const;
|
||||
|
||||
/// Returns the title that should be displayed for this game.
|
||||
std::string_view GetDisplayTitle() const;
|
||||
|
||||
/// Returns the sort name if present, otherwise the title.
|
||||
std::string_view GetSortTitle() const;
|
||||
|
||||
/// Returns the name to use when creating memory cards for this game.
|
||||
std::string_view GetSaveTitle() const;
|
||||
|
||||
/// Applies any settings overrides to the given settings object.
|
||||
void ApplySettings(Settings& settings, bool display_osd_messages) const;
|
||||
|
||||
/// Generates a compatibility report in markdown format.
|
||||
std::string GenerateCompatibilityReport() const;
|
||||
};
|
||||
|
||||
|
||||
@@ -319,7 +319,7 @@ bool GameList::GetDiscListEntry(const std::string& path, Entry* entry)
|
||||
{
|
||||
// pull from database
|
||||
entry->serial = dentry->serial;
|
||||
entry->title = dentry->title;
|
||||
entry->title = dentry->GetDisplayTitle();
|
||||
entry->dbentry = dentry;
|
||||
|
||||
if (!cdi->HasSubImages())
|
||||
@@ -1255,6 +1255,24 @@ std::string GameList::GetNewCoverImagePathForEntry(const Entry* entry, const cha
|
||||
return Path::Combine(EmuFolders::Covers, Path::SanitizeFileName(name));
|
||||
}
|
||||
|
||||
std::string_view GameList::Entry::GetDisplayTitle() const
|
||||
{
|
||||
// if custom title is present, use that for display too
|
||||
return has_custom_title ? title : (dbentry ? dbentry->GetDisplayTitle() : title);
|
||||
}
|
||||
|
||||
std::string_view GameList::Entry::GetSortTitle() const
|
||||
{
|
||||
// if custom title is present, use that for sorting too
|
||||
return has_custom_title ? title : (dbentry ? dbentry->GetSortTitle() : title);
|
||||
}
|
||||
|
||||
std::string_view GameList::Entry::GetSaveTitle() const
|
||||
{
|
||||
// if custom title is present, use that for save folder too
|
||||
return has_custom_title ? title : (dbentry ? dbentry->GetSaveTitle() : title);
|
||||
}
|
||||
|
||||
std::string_view GameList::Entry::GetLanguageIcon() const
|
||||
{
|
||||
std::string_view ret;
|
||||
|
||||
@@ -60,6 +60,12 @@ struct Entry
|
||||
u16 unlocked_achievements = 0;
|
||||
u16 unlocked_achievements_hc = 0;
|
||||
|
||||
std::string_view GetDisplayTitle() const;
|
||||
|
||||
std::string_view GetSortTitle() const;
|
||||
|
||||
std::string_view GetSaveTitle() const;
|
||||
|
||||
std::string_view GetLanguageIcon() const;
|
||||
|
||||
TinyString GetLanguageIconName() const;
|
||||
|
||||
@@ -3445,8 +3445,7 @@ u32 System::CompressAndWriteStateData(std::FILE* fp, std::span<const u8> src, Sa
|
||||
{
|
||||
ctype = CompressHelpers::CompressType::XZ;
|
||||
*header_type = static_cast<u32>(SAVE_STATE_HEADER::CompressionType::XZ);
|
||||
clevel =
|
||||
((method == SaveStateCompressionMode::XZLow) ? 1 : ((method == SaveStateCompressionMode::XZHigh) ? 9 : 5));
|
||||
clevel = ((method == SaveStateCompressionMode::XZLow) ? 1 : ((method == SaveStateCompressionMode::XZHigh) ? 9 : 5));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3808,11 +3807,12 @@ std::unique_ptr<MemoryCard> System::GetMemoryCardForSlot(u32 slot, MemoryCardTyp
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::string_view game_title =
|
||||
s_state.running_game_custom_title ? s_state.running_game_title : s_state.running_game_entry->GetSaveTitle();
|
||||
std::string card_path;
|
||||
|
||||
// Playlist - use title if different.
|
||||
if (HasMediaSubImages() && s_state.running_game_entry &&
|
||||
s_state.running_game_title != s_state.running_game_entry->title)
|
||||
if (HasMediaSubImages() && s_state.running_game_entry && s_state.running_game_title != game_title)
|
||||
{
|
||||
card_path = g_settings.GetGameMemoryCardPath(Path::SanitizeFileName(s_state.running_game_title), slot);
|
||||
}
|
||||
@@ -3824,11 +3824,7 @@ std::unique_ptr<MemoryCard> System::GetMemoryCardForSlot(u32 slot, MemoryCardTyp
|
||||
}
|
||||
|
||||
// But prefer a disc-specific card if one already exists.
|
||||
std::string disc_card_path = g_settings.GetGameMemoryCardPath(
|
||||
Path::SanitizeFileName((s_state.running_game_entry && !s_state.running_game_custom_title) ?
|
||||
s_state.running_game_entry->title :
|
||||
s_state.running_game_title),
|
||||
slot);
|
||||
std::string disc_card_path = g_settings.GetGameMemoryCardPath(Path::SanitizeFileName(game_title), slot);
|
||||
if (disc_card_path != card_path)
|
||||
{
|
||||
if (card_path.empty() || !g_settings.memory_card_use_playlist_title ||
|
||||
@@ -4157,7 +4153,7 @@ void System::UpdateRunningGame(const std::string& path, CDImage* image, bool boo
|
||||
{
|
||||
s_state.running_game_entry = GameDatabase::GetEntryForSerial(s_state.running_game_serial);
|
||||
if (s_state.running_game_entry && s_state.running_game_title.empty())
|
||||
s_state.running_game_title = s_state.running_game_entry->title;
|
||||
s_state.running_game_title = s_state.running_game_entry->GetDisplayTitle();
|
||||
else if (s_state.running_game_title.empty())
|
||||
s_state.running_game_title = s_state.running_game_serial;
|
||||
}
|
||||
@@ -4176,7 +4172,7 @@ void System::UpdateRunningGame(const std::string& path, CDImage* image, bool boo
|
||||
{
|
||||
s_state.running_game_serial = s_state.running_game_entry->serial;
|
||||
if (s_state.running_game_title.empty())
|
||||
s_state.running_game_title = s_state.running_game_entry->title;
|
||||
s_state.running_game_title = s_state.running_game_entry->GetDisplayTitle();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5775,7 +5771,7 @@ std::string System::GetGameMemoryCardPath(std::string_view serial, std::string_v
|
||||
const GameDatabase::Entry* entry = GameDatabase::GetEntryForSerial(serial);
|
||||
if (entry)
|
||||
{
|
||||
ret = g_settings.GetGameMemoryCardPath(Path::SanitizeFileName(entry->title), slot);
|
||||
ret = g_settings.GetGameMemoryCardPath(Path::SanitizeFileName(entry->GetSaveTitle()), slot);
|
||||
|
||||
// Use disc set name if there isn't a per-disc card present.
|
||||
const bool global_use_playlist_title = Host::GetBaseBoolSettingValue(section, "UsePlaylistTitle", true);
|
||||
@@ -6193,7 +6189,7 @@ void System::UpdateRichPresence(bool update_session_time)
|
||||
{
|
||||
// Use disc set name if it's not a custom title.
|
||||
if (s_state.running_game_entry && !s_state.running_game_entry->disc_set_name.empty() &&
|
||||
s_state.running_game_title == s_state.running_game_entry->title)
|
||||
s_state.running_game_title == s_state.running_game_entry->GetDisplayTitle())
|
||||
{
|
||||
game_details = s_state.running_game_entry->disc_set_name;
|
||||
}
|
||||
|
||||
@@ -529,7 +529,7 @@ QVariant GameListModel::data(const QModelIndex& index, int role, const GameList:
|
||||
return QtUtils::StringViewToQString(ge->serial);
|
||||
|
||||
case Column_Title:
|
||||
return QtUtils::StringViewToQString(ge->title);
|
||||
return QtUtils::StringViewToQString(ge->GetDisplayTitle());
|
||||
|
||||
case Column_FileTitle:
|
||||
return QtUtils::StringViewToQString(Path::GetFileTitle(ge->path));
|
||||
@@ -589,7 +589,7 @@ QVariant GameListModel::data(const QModelIndex& index, int role, const GameList:
|
||||
case Column_Cover:
|
||||
{
|
||||
if (m_show_titles_for_covers)
|
||||
return QString::fromStdString(ge->title);
|
||||
return QtUtils::StringViewToQString(ge->GetDisplayTitle());
|
||||
else
|
||||
return {};
|
||||
}
|
||||
@@ -665,7 +665,7 @@ QVariant GameListModel::data(const QModelIndex& index, int role, const GameList:
|
||||
return QtUtils::StringViewToQString(ge->serial);
|
||||
|
||||
case Column_Title:
|
||||
return QtUtils::StringViewToQString(ge->title);
|
||||
return QtUtils::StringViewToQString(ge->GetDisplayTitle());
|
||||
|
||||
case Column_FileTitle:
|
||||
return QtUtils::StringViewToQString(Path::GetFileTitle(ge->path));
|
||||
@@ -761,7 +761,7 @@ void GameListModel::refresh()
|
||||
|
||||
bool GameListModel::titlesLessThan(const GameList::Entry* left, const GameList::Entry* right) const
|
||||
{
|
||||
return (StringUtil::Strcasecmp(left->title.c_str(), right->title.c_str()) < 0);
|
||||
return (StringUtil::CompareNoCase(left->GetSortTitle(), right->GetSortTitle()) < 0);
|
||||
}
|
||||
|
||||
bool GameListModel::lessThan(const QModelIndex& left_index, const QModelIndex& right_index, int column) const
|
||||
@@ -1070,9 +1070,9 @@ public:
|
||||
|
||||
if (!m_filter_name.empty())
|
||||
{
|
||||
if (!((!entry->IsDiscSet() && !entry->path.empty() && StringUtil::ContainsNoCase(entry->path, m_filter_name)) ||
|
||||
(!entry->serial.empty() && StringUtil::ContainsNoCase(entry->serial, m_filter_name)) ||
|
||||
(!entry->title.empty() && StringUtil::ContainsNoCase(entry->title, m_filter_name))))
|
||||
if (!((!entry->IsDiscSet() && StringUtil::ContainsNoCase(entry->path, m_filter_name)) ||
|
||||
StringUtil::ContainsNoCase(entry->serial, m_filter_name) ||
|
||||
StringUtil::ContainsNoCase(entry->GetDisplayTitle(), m_filter_name)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1445,7 +1445,10 @@ void GameListWidget::onListViewItemActivated(const QModelIndex& index)
|
||||
const auto lock = GameList::GetLock();
|
||||
const GameList::Entry* entry = GameList::GetEntryByIndex(static_cast<u32>(source_index.row()));
|
||||
if (entry)
|
||||
SettingsWindow::openGamePropertiesDialog(entry->path, entry->title, entry->serial, entry->hash, entry->region);
|
||||
{
|
||||
SettingsWindow::openGamePropertiesDialog(entry->path, std::string(entry->GetDisplayTitle()), entry->serial,
|
||||
entry->hash, entry->region);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1678,9 +1681,8 @@ void GameListListView::setFixedColumnWidth(const QFontMetrics& fm, int column, i
|
||||
const int margin = style()->pixelMetric(QStyle::PM_HeaderMargin, nullptr, this);
|
||||
const int header_width = fm.size(0, m_model->getColumnDisplayName(column)).width() +
|
||||
style()->pixelMetric(QStyle::PM_HeaderMarkSize, nullptr, this) + // sort indicator
|
||||
margin; // space between text and sort indicator
|
||||
const int width = std::max(header_width, str_width) +
|
||||
2 * margin; // left and right margins
|
||||
margin; // space between text and sort indicator
|
||||
const int width = std::max(header_width, str_width) + 2 * margin; // left and right margins
|
||||
setFixedColumnWidth(column, width);
|
||||
}
|
||||
|
||||
@@ -1703,11 +1705,12 @@ void GameListListView::setFixedColumnWidths()
|
||||
// And this is a monstrosity.
|
||||
setFixedColumnWidth(
|
||||
fm, GameListModel::Column_LastPlayed,
|
||||
std::max(width_for(qApp->translate("GameList", "Today")),
|
||||
std::max(width_for(qApp->translate("GameList", "Yesterday")),
|
||||
std::max(width_for(qApp->translate("GameList", "Never")),
|
||||
width_for(QtHost::FormatNumber(Host::NumberFormatType::ShortDate,
|
||||
static_cast<s64>(QDateTime::currentSecsSinceEpoch())))))));
|
||||
std::max(
|
||||
width_for(qApp->translate("GameList", "Today")),
|
||||
std::max(width_for(qApp->translate("GameList", "Yesterday")),
|
||||
std::max(width_for(qApp->translate("GameList", "Never")),
|
||||
width_for(QtHost::FormatNumber(Host::NumberFormatType::ShortDate,
|
||||
static_cast<s64>(QDateTime::currentSecsSinceEpoch())))))));
|
||||
|
||||
// Assume 8 is the widest digit.
|
||||
int size_width = width_for(QStringLiteral("%1 MB").arg(8888.88, 0, 'f', 2));
|
||||
|
||||
@@ -126,7 +126,7 @@ void GameSummaryWidget::populateUi(const std::string& path, const std::string& s
|
||||
|
||||
if (entry)
|
||||
{
|
||||
m_ui.title->setText(QtUtils::StringViewToQString(entry->title));
|
||||
m_ui.title->setText(QtUtils::StringViewToQString(entry->GetDisplayTitle()));
|
||||
m_ui.compatibility->setCurrentIndex(static_cast<int>(entry->compatibility));
|
||||
m_ui.genre->setText(entry->genre.empty() ? tr("Unknown") : QtUtils::StringViewToQString(entry->genre));
|
||||
if (!entry->developer.empty() && !entry->publisher.empty() && entry->developer != entry->publisher)
|
||||
@@ -268,7 +268,7 @@ void GameSummaryWidget::populateCustomAttributes()
|
||||
|
||||
{
|
||||
QSignalBlocker sb(m_ui.title);
|
||||
m_ui.title->setText(QString::fromStdString(entry->title));
|
||||
m_ui.title->setText(QtUtils::StringViewToQString(entry->GetDisplayTitle()));
|
||||
m_ui.restoreTitle->setEnabled(entry->has_custom_title);
|
||||
}
|
||||
|
||||
|
||||
@@ -1565,8 +1565,8 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
SettingsWindow::openGamePropertiesDialog(entry->path, entry->title, entry->serial, entry->hash,
|
||||
entry->region);
|
||||
SettingsWindow::openGamePropertiesDialog(entry->path, std::string(entry->GetDisplayTitle()), entry->serial,
|
||||
entry->hash, entry->region);
|
||||
});
|
||||
|
||||
connect(menu.addAction(tr("Open Containing Directory...")), &QAction::triggered, [this, qpath]() {
|
||||
@@ -1644,8 +1644,8 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
|
||||
const GameList::Entry* first_disc = GameList::GetFirstDiscSetMember(disc_set_name.toStdString());
|
||||
if (first_disc)
|
||||
{
|
||||
SettingsWindow::openGamePropertiesDialog(first_disc->path, first_disc->title, first_disc->serial,
|
||||
first_disc->hash, first_disc->region);
|
||||
SettingsWindow::openGamePropertiesDialog(first_disc->path, std::string(first_disc->GetDisplayTitle()),
|
||||
first_disc->serial, first_disc->hash, first_disc->region);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1743,7 +1743,7 @@ void MainWindow::clearGameListEntryPlayTime(const GameList::Entry* entry)
|
||||
if (QMessageBox::question(
|
||||
this, tr("Confirm Reset"),
|
||||
tr("Are you sure you want to reset the play time for '%1'?\n\nThis action cannot be undone.")
|
||||
.arg(QString::fromStdString(entry->title))) != QMessageBox::Yes)
|
||||
.arg(QtUtils::StringViewToQString(entry->GetDisplayTitle()))) != QMessageBox::Yes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user