yuzu: Add support for multiple game directories

Ported from https://github.com/citra-emu/citra/pull/3617.
This commit is contained in:
fearlessTobi
2019-05-01 23:21:04 +02:00
committed by FearlessTobi
parent 7fc5af3622
commit 2d8eba5baf
12 changed files with 664 additions and 193 deletions

View File

@ -216,8 +216,7 @@ GMainWindow::GMainWindow()
OnReinitializeKeys(ReinitializeKeyBehavior::NoWarning);
game_list->LoadCompatibilityList();
game_list->PopulateAsync(UISettings::values.game_directory_path,
UISettings::values.game_directory_deepscan);
game_list->PopulateAsync(UISettings::values.game_dirs);
// Show one-time "callout" messages to the user
ShowTelemetryCallout();
@ -427,6 +426,10 @@ void GMainWindow::InitializeWidgets() {
game_list = new GameList(vfs, provider.get(), this);
ui.horizontalLayout->addWidget(game_list);
game_list_placeholder = new GameListPlaceholder(this);
ui.horizontalLayout->addWidget(game_list_placeholder);
game_list_placeholder->setVisible(false);
loading_screen = new LoadingScreen(this);
loading_screen->hide();
ui.horizontalLayout->addWidget(loading_screen);
@ -660,6 +663,7 @@ void GMainWindow::RestoreUIState() {
void GMainWindow::ConnectWidgetEvents() {
connect(game_list, &GameList::GameChosen, this, &GMainWindow::OnGameListLoadFile);
connect(game_list, &GameList::OpenDirectory, this, &GMainWindow::OnGameListOpenDirectory);
connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder);
connect(game_list, &GameList::OpenTransferableShaderCacheRequested, this,
&GMainWindow::OnTransferableShaderCacheOpenFile);
@ -667,6 +671,11 @@ void GMainWindow::ConnectWidgetEvents() {
connect(game_list, &GameList::CopyTIDRequested, this, &GMainWindow::OnGameListCopyTID);
connect(game_list, &GameList::NavigateToGamedbEntryRequested, this,
&GMainWindow::OnGameListNavigateToGamedbEntry);
connect(game_list, &GameList::AddDirectory, this, &GMainWindow::OnGameListAddDirectory);
connect(game_list_placeholder, &GameListPlaceholder::AddDirectory, this,
&GMainWindow::OnGameListAddDirectory);
connect(game_list, &GameList::ShowList, this, &GMainWindow::OnGameListShowList);
connect(game_list, &GameList::OpenPerGameGeneralRequested, this,
&GMainWindow::OnGameListOpenPerGameProperties);
@ -684,8 +693,6 @@ void GMainWindow::ConnectMenuEvents() {
connect(ui.action_Load_Folder, &QAction::triggered, this, &GMainWindow::OnMenuLoadFolder);
connect(ui.action_Install_File_NAND, &QAction::triggered, this,
&GMainWindow::OnMenuInstallToNAND);
connect(ui.action_Select_Game_List_Root, &QAction::triggered, this,
&GMainWindow::OnMenuSelectGameListRoot);
connect(ui.action_Select_NAND_Directory, &QAction::triggered, this,
[this] { OnMenuSelectEmulatedDirectory(EmulatedDirectoryTarget::NAND); });
connect(ui.action_Select_SDMC_Directory, &QAction::triggered, this,
@ -950,6 +957,7 @@ void GMainWindow::BootGame(const QString& filename) {
// Update the GUI
if (ui.action_Single_Window_Mode->isChecked()) {
game_list->hide();
game_list_placeholder->hide();
}
status_bar_update_timer.start(2000);
@ -1007,7 +1015,10 @@ void GMainWindow::ShutdownGame() {
render_window->hide();
loading_screen->hide();
loading_screen->Clear();
game_list->show();
if (game_list->isEmpty())
game_list_placeholder->show();
else
game_list->show();
game_list->setFilterFocus();
UpdateWindowTitle();
@ -1298,6 +1309,45 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id,
QDesktopServices::openUrl(QUrl(QStringLiteral("https://yuzu-emu.org/game/") + directory));
}
void GMainWindow::OnGameListOpenDirectory(QString directory) {
QString path;
if (directory == QStringLiteral("INSTALLED")) {
// TODO: Find a better solution when installing files to the SD card gets implemented
path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir).c_str() +
std::string("user/Contents/registered"));
} else if (directory == QStringLiteral("SYSTEM")) {
path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir).c_str() +
std::string("system/Contents/registered"));
} else {
path = directory;
}
if (!QFileInfo::exists(path)) {
QMessageBox::critical(this, tr("Error Opening %1").arg(path), tr("Folder does not exist!"));
return;
}
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
}
void GMainWindow::OnGameListAddDirectory() {
QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory"));
if (dir_path.isEmpty())
return;
UISettings::GameDir game_dir{dir_path, false, true};
if (!UISettings::values.game_dirs.contains(game_dir)) {
UISettings::values.game_dirs.append(game_dir);
game_list->PopulateAsync(UISettings::values.game_dirs);
} else {
LOG_WARNING(Frontend, "Selected directory is already in the game list");
}
}
void GMainWindow::OnGameListShowList(bool show) {
if (emulation_running && ui.action_Single_Window_Mode->isChecked())
return;
game_list->setVisible(show);
game_list_placeholder->setVisible(!show);
};
void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) {
u64 title_id{};
const auto v_file = Core::GetGameFileFromPath(vfs, file);
@ -1316,8 +1366,7 @@ void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) {
const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false);
if (reload) {
game_list->PopulateAsync(UISettings::values.game_directory_path,
UISettings::values.game_directory_deepscan);
game_list->PopulateAsync(UISettings::values.game_dirs);
}
config->Save();
@ -1407,8 +1456,7 @@ void GMainWindow::OnMenuInstallToNAND() {
const auto success = [this]() {
QMessageBox::information(this, tr("Successfully Installed"),
tr("The file was successfully installed."));
game_list->PopulateAsync(UISettings::values.game_directory_path,
UISettings::values.game_directory_deepscan);
game_list->PopulateAsync(UISettings::values.game_dirs);
FileUtil::DeleteDirRecursively(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) +
DIR_SEP + "game_list");
};
@ -1533,14 +1581,6 @@ void GMainWindow::OnMenuInstallToNAND() {
}
}
void GMainWindow::OnMenuSelectGameListRoot() {
QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory"));
if (!dir_path.isEmpty()) {
UISettings::values.game_directory_path = dir_path;
game_list->PopulateAsync(dir_path, UISettings::values.game_directory_deepscan);
}
}
void GMainWindow::OnMenuSelectEmulatedDirectory(EmulatedDirectoryTarget target) {
const auto res = QMessageBox::information(
this, tr("Changing Emulated Directory"),
@ -1559,8 +1599,7 @@ void GMainWindow::OnMenuSelectEmulatedDirectory(EmulatedDirectoryTarget target)
: FileUtil::UserPath::NANDDir,
dir_path.toStdString());
Service::FileSystem::CreateFactories(*vfs);
game_list->PopulateAsync(UISettings::values.game_directory_path,
UISettings::values.game_directory_deepscan);
game_list->PopulateAsync(UISettings::values.game_dirs);
}
}
@ -1724,11 +1763,11 @@ void GMainWindow::OnConfigure() {
if (UISettings::values.enable_discord_presence != old_discord_presence) {
SetDiscordEnabled(UISettings::values.enable_discord_presence);
}
emit UpdateThemedIcons();
const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false);
if (reload) {
game_list->PopulateAsync(UISettings::values.game_directory_path,
UISettings::values.game_directory_deepscan);
game_list->PopulateAsync(UISettings::values.game_dirs);
}
config->Save();
@ -1992,8 +2031,7 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
Service::FileSystem::CreateFactories(*vfs);
if (behavior == ReinitializeKeyBehavior::Warning) {
game_list->PopulateAsync(UISettings::values.game_directory_path,
UISettings::values.game_directory_deepscan);
game_list->PopulateAsync(UISettings::values.game_dirs);
}
}
@ -2158,7 +2196,6 @@ void GMainWindow::UpdateUITheme() {
}
QIcon::setThemeSearchPaths(theme_paths);
emit UpdateThemedIcons();
}
void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) {