Qt: Use disc sets for changing discs
This commit is contained in:
parent
381bd92f87
commit
7d914a9384
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -603,8 +603,9 @@ void MainWindow::onSystemDestroyed()
|
|||
|
||||
void MainWindow::onRunningGameChanged(const QString& filename, const QString& game_serial, const QString& game_title)
|
||||
{
|
||||
m_current_game_title = game_title.toStdString();
|
||||
m_current_game_serial = game_serial.toStdString();
|
||||
m_current_game_path = filename;
|
||||
m_current_game_title = game_title;
|
||||
m_current_game_serial = game_serial;
|
||||
|
||||
updateWindowTitle();
|
||||
// updateSaveStateMenus(path, serial, crc);
|
||||
|
@ -916,18 +917,34 @@ void MainWindow::populateSaveStateMenu(const char* game_serial, QMenu* menu)
|
|||
|
||||
void MainWindow::populateChangeDiscSubImageMenu(QMenu* menu, QActionGroup* action_group)
|
||||
{
|
||||
if (!s_system_valid || !System::HasMediaSubImages())
|
||||
if (!s_system_valid)
|
||||
return;
|
||||
|
||||
const u32 count = System::GetMediaSubImageCount();
|
||||
const u32 current = System::GetMediaSubImageIndex();
|
||||
for (u32 i = 0; i < count; i++)
|
||||
if (System::HasMediaSubImages())
|
||||
{
|
||||
QAction* action = action_group->addAction(QString::fromStdString(System::GetMediaSubImageTitle(i)));
|
||||
action->setCheckable(true);
|
||||
action->setChecked(i == current);
|
||||
connect(action, &QAction::triggered, [i]() { g_emu_thread->changeDiscFromPlaylist(i); });
|
||||
menu->addAction(action);
|
||||
const u32 count = System::GetMediaSubImageCount();
|
||||
const u32 current = System::GetMediaSubImageIndex();
|
||||
for (u32 i = 0; i < count; i++)
|
||||
{
|
||||
QAction* action = action_group->addAction(QString::fromStdString(System::GetMediaSubImageTitle(i)));
|
||||
action->setCheckable(true);
|
||||
action->setChecked(i == current);
|
||||
connect(action, &QAction::triggered, [i]() { g_emu_thread->changeDiscFromPlaylist(i); });
|
||||
menu->addAction(action);
|
||||
}
|
||||
}
|
||||
else if (const GameDatabase::Entry* entry = System::GetGameDatabaseEntry(); entry && !entry->disc_set_serials.empty())
|
||||
{
|
||||
auto lock = GameList::GetLock();
|
||||
for (const auto& [title, glentry] : GameList::GetMatchingEntriesForSerial(entry->disc_set_serials))
|
||||
{
|
||||
QAction* action = action_group->addAction(QString::fromStdString(title));
|
||||
QString path = QString::fromStdString(glentry->path);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(path == m_current_game_path);
|
||||
connect(action, &QAction::triggered, [path = std::move(path)]() { g_emu_thread->changeDisc(path); });
|
||||
menu->addAction(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1155,12 +1172,12 @@ void MainWindow::onChangeDiscMenuAboutToHide()
|
|||
|
||||
void MainWindow::onLoadStateMenuAboutToShow()
|
||||
{
|
||||
populateLoadStateMenu(m_current_game_serial.c_str(), m_ui.menuLoadState);
|
||||
populateLoadStateMenu(m_current_game_serial.toUtf8().constData(), m_ui.menuLoadState);
|
||||
}
|
||||
|
||||
void MainWindow::onSaveStateMenuAboutToShow()
|
||||
{
|
||||
populateSaveStateMenu(m_current_game_serial.c_str(), m_ui.menuSaveState);
|
||||
populateSaveStateMenu(m_current_game_serial.toUtf8().constData(), m_ui.menuSaveState);
|
||||
}
|
||||
|
||||
void MainWindow::onCheatsMenuAboutToShow()
|
||||
|
@ -1706,9 +1723,9 @@ void MainWindow::updateWindowTitle()
|
|||
{
|
||||
QString suffix(QtHost::GetAppConfigSuffix());
|
||||
QString main_title(QtHost::GetAppNameAndVersion() + suffix);
|
||||
QString display_title(QString::fromStdString(m_current_game_title) + suffix);
|
||||
QString display_title(m_current_game_title + suffix);
|
||||
|
||||
if (!s_system_valid || m_current_game_title.empty())
|
||||
if (!s_system_valid || m_current_game_title.isEmpty())
|
||||
display_title = main_title;
|
||||
else if (isRenderingToMain())
|
||||
main_title = display_title;
|
||||
|
@ -2464,7 +2481,7 @@ bool MainWindow::requestShutdown(bool allow_confirm /* = true */, bool allow_sav
|
|||
return true;
|
||||
|
||||
// If we don't have a serial, we can't save state.
|
||||
allow_save_to_state &= !m_current_game_serial.empty();
|
||||
allow_save_to_state &= !m_current_game_serial.isEmpty();
|
||||
save_state &= allow_save_to_state;
|
||||
|
||||
// Only confirm on UI thread because we need to display a msgbox.
|
||||
|
|
|
@ -277,8 +277,9 @@ private:
|
|||
CheatManagerDialog* m_cheat_manager_dialog = nullptr;
|
||||
DebuggerWindow* m_debugger_window = nullptr;
|
||||
|
||||
std::string m_current_game_title;
|
||||
std::string m_current_game_serial;
|
||||
QString m_current_game_path;
|
||||
QString m_current_game_title;
|
||||
QString m_current_game_serial;
|
||||
|
||||
bool m_was_paused_by_focus_loss = false;
|
||||
bool m_open_debugger_on_start = false;
|
||||
|
|
Loading…
Reference in New Issue