Qt: Use disc sets for changing discs

This commit is contained in:
Stenzek
2023-08-23 18:12:10 +10:00
parent 381bd92f87
commit 7d914a9384
7 changed files with 169 additions and 44 deletions

View File

@ -996,40 +996,85 @@ void FullscreenUI::DoChangeDiscFromFile()
void FullscreenUI::DoChangeDisc()
{
if (!System::HasMediaSubImages())
ImGuiFullscreen::ChoiceDialogOptions options;
if (System::HasMediaSubImages())
{
DoChangeDiscFromFile();
const u32 current_index = System::GetMediaSubImageIndex();
const u32 count = System::GetMediaSubImageCount();
options.reserve(count + 1);
options.emplace_back(FSUI_STR("From File..."), false);
for (u32 i = 0; i < count; i++)
options.emplace_back(System::GetMediaSubImageTitle(i), i == current_index);
auto callback = [](s32 index, const std::string& title, bool checked) {
if (index == 0)
{
CloseChoiceDialog();
DoChangeDiscFromFile();
return;
}
else if (index > 0)
{
System::SwitchMediaSubImage(static_cast<u32>(index - 1));
}
QueueResetFocus();
CloseChoiceDialog();
ReturnToMainWindow();
};
OpenChoiceDialog(FSUI_ICONSTR(ICON_FA_COMPACT_DISC, "Select Disc Image"), true, std::move(options),
std::move(callback));
return;
}
const u32 current_index = System::GetMediaSubImageIndex();
const u32 count = System::GetMediaSubImageCount();
ImGuiFullscreen::ChoiceDialogOptions options;
options.reserve(count + 1);
options.emplace_back("From File...", false);
for (u32 i = 0; i < count; i++)
options.emplace_back(System::GetMediaSubImageTitle(i), i == current_index);
auto callback = [](s32 index, const std::string& title, bool checked) {
if (index == 0)
if (const GameDatabase::Entry* entry = System::GetGameDatabaseEntry(); entry && !entry->disc_set_serials.empty())
{
const auto lock = GameList::GetLock();
const auto matches = GameList::GetMatchingEntriesForSerial(entry->disc_set_serials);
if (matches.size() > 1)
{
CloseChoiceDialog();
DoChangeDiscFromFile();
options.reserve(matches.size() + 1);
options.emplace_back(FSUI_STR("From File..."), false);
std::vector<std::string> paths;
paths.reserve(matches.size());
const std::string& current_path = System::GetDiscPath();
for (auto& [title, glentry] : matches)
{
options.emplace_back(std::move(title), current_path == glentry->path);
paths.push_back(glentry->path);
}
auto callback = [paths = std::move(paths)](s32 index, const std::string& title, bool checked) {
if (index == 0)
{
CloseChoiceDialog();
DoChangeDiscFromFile();
return;
}
else if (index > 0)
{
System::InsertMedia(paths[index - 1].c_str());
}
QueueResetFocus();
CloseChoiceDialog();
ReturnToMainWindow();
};
OpenChoiceDialog(FSUI_ICONSTR(ICON_FA_COMPACT_DISC, "Select Disc Image"), true, std::move(options),
std::move(callback));
return;
}
else if (index > 0)
{
System::SwitchMediaSubImage(static_cast<u32>(index - 1));
}
}
QueueResetFocus();
CloseChoiceDialog();
ReturnToMainWindow();
};
OpenChoiceDialog(FSUI_ICONSTR(ICON_FA_COMPACT_DISC, "Select Disc Image"), true, std::move(options),
std::move(callback));
DoChangeDiscFromFile();
}
void FullscreenUI::DoCheatsMenu()

View File

@ -1033,6 +1033,50 @@ TinyString GameList::FormatTimespan(std::time_t timespan, bool long_format)
return ret;
}
std::vector<std::pair<std::string, const GameList::Entry*>>
GameList::GetMatchingEntriesForSerial(const gsl::span<const std::string> serials)
{
std::vector<std::pair<std::string, const GameList::Entry*>> ret;
ret.reserve(serials.size());
for (const std::string& serial : serials)
{
const Entry* matching_entry = nullptr;
bool has_multiple_entries = false;
for (const Entry& entry : s_entries)
{
if (entry.serial != serial)
continue;
if (!matching_entry)
matching_entry = &entry;
else
has_multiple_entries = true;
}
if (!matching_entry)
continue;
if (!has_multiple_entries)
{
ret.emplace_back(matching_entry->title, matching_entry);
continue;
}
// Have to add all matching files.
for (const Entry& entry : s_entries)
{
if (entry.serial != serial)
continue;
ret.emplace_back(Path::GetFileName(entry.path), &entry);
}
}
return ret;
}
bool GameList::DownloadCovers(const std::vector<std::string>& url_templates, bool use_serial,
ProgressCallback* progress, std::function<void(const Entry*, std::string)> save_callback)
{

View File

@ -10,6 +10,8 @@
#include "common/string.h"
#include "gsl/span"
#include <ctime>
#include <functional>
#include <mutex>
@ -102,6 +104,11 @@ std::string GetCoverImagePathForEntry(const Entry* entry);
std::string GetCoverImagePath(const std::string& path, const std::string& serial, const std::string& 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,
/// except when two files have the same serial, in which case the filename will be used instead.
std::vector<std::pair<std::string, const Entry*>>
GetMatchingEntriesForSerial(const gsl::span<const std::string> serials);
/// Downloads covers using the specified URL templates. By default, covers are saved by title, but this can be changed
/// with the use_serial parameter. save_callback optionall takes the entry and the path the new cover is saved to.
bool DownloadCovers(const std::vector<std::string>& url_templates, bool use_serial = false,

View File

@ -333,6 +333,11 @@ const std::string& System::GetGameTitle()
return s_running_game_title;
}
const GameDatabase::Entry* System::GetGameDatabaseEntry()
{
return s_running_game_entry;
}
System::GameHash System::GetGameHash()
{
return s_running_game_hash;

View File

@ -25,6 +25,11 @@ struct ImageInfo;
struct Hash;
}
namespace GameDatabase
{
struct Entry;
}
struct SystemBootParameters
{
SystemBootParameters();
@ -184,6 +189,7 @@ void FrameDone();
const std::string& GetDiscPath();
const std::string& GetGameSerial();
const std::string& GetGameTitle();
const GameDatabase::Entry* GetGameDatabaseEntry();
GameHash GetGameHash();
bool IsRunningUnknownGame();
bool WasFastBooted();