Snapshots: Clean up per-game snapshots folder code

This commit is contained in:
TheTechnician27 2025-10-25 20:43:27 -05:00 committed by Ty
parent 7c768b6833
commit d415f8364c
8 changed files with 36 additions and 59 deletions

View File

@ -1473,8 +1473,8 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
if (!entry->serial.empty())
connect(menu.addAction(tr("Check Wiki Page")), &QAction::triggered, [this, entry]() { goToWikiPage(entry); });
action = menu.addAction(tr("Open Screenshots Folder"));
connect(action, &QAction::triggered, [this, entry]() { openScreenshotsFolderForGame(entry); });
action = menu.addAction(tr("Open Snapshots Folder"));
connect(action, &QAction::triggered, [this, entry]() { openSnapshotsFolderForGame(entry); });
menu.addSeparator();
if (!s_vm_valid)
@ -2946,37 +2946,28 @@ void MainWindow::goToWikiPage(const GameList::Entry* entry)
QtUtils::OpenURL(this, fmt::format("https://wiki.pcsx2.net/{}", entry->serial).c_str());
}
void MainWindow::openScreenshotsFolderForGame(const GameList::Entry* entry)
void MainWindow::openSnapshotsFolderForGame(const GameList::Entry* entry)
{
if (!entry || entry->title.empty())
return;
// if disabled open the snapshots folder
if (!EmuConfig.GS.OrganizeScreenshotsByGame)
// Go to top-level snapshots directory if not organizing by game.
if (EmuConfig.GS.OrganizeSnapshotsByGame && entry && !entry->title.empty())
{
QtUtils::OpenURL(this, QUrl::fromLocalFile(QString::fromStdString(EmuFolders::Snapshots)));
return;
}
std::string game_name = entry->title;
Path::SanitizeFileName(&game_name);
std::string game_name = entry->title;
Path::SanitizeFileName(&game_name);
if (game_name.length() > 219)
{
game_name.resize(219);
}
const std::string game_dir = Path::Combine(EmuFolders::Snapshots, game_name);
const std::string game_dir = Path::Combine(EmuFolders::Snapshots, game_name);
if (!FileSystem::DirectoryExists(game_dir.c_str()))
{
if (!FileSystem::CreateDirectoryPath(game_dir.c_str(), false))
// Make sure the per-game directory exists or that we can successfully create it.
if (FileSystem::DirectoryExists(game_dir.c_str()) || FileSystem::CreateDirectoryPath(game_dir.c_str(), false))
{
QMessageBox::critical(this, tr("Error"), tr("Failed to create screenshots directory '%1'.").arg(QString::fromStdString(game_dir)));
const QFileInfo fi(QString::fromStdString(game_dir));
QtUtils::OpenURL(this, QUrl::fromLocalFile(fi.absoluteFilePath()));
return;
}
QMessageBox::critical(this, tr("Error"), tr("Failed to create snapshots directory '%1'\n\nOpening default directory.").arg(QString::fromStdString(game_dir)));
}
const QFileInfo fi(QString::fromStdString(game_dir));
QtUtils::OpenURL(this, QUrl::fromLocalFile(fi.absoluteFilePath()));
QtUtils::OpenURL(this, QUrl::fromLocalFile(QString::fromStdString(EmuFolders::Snapshots)));
}
std::optional<bool> MainWindow::promptForResumeState(const QString& save_state_path)

View File

@ -278,7 +278,7 @@ private:
void setGameListEntryCoverImage(const GameList::Entry* entry);
void clearGameListEntryPlayTime(const GameList::Entry* entry, const time_t entry_played_time);
void goToWikiPage(const GameList::Entry* entry);
void openScreenshotsFolderForGame(const GameList::Entry* entry);
void openSnapshotsFolderForGame(const GameList::Entry* entry);
std::optional<bool> promptForResumeState(const QString& save_state_path);
void loadSaveStateSlot(s32 slot, bool load_backup = false);

View File

@ -19,14 +19,13 @@ FolderSettingsWidget::FolderSettingsWidget(SettingsWindow* settings_dialog, QWid
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.cheats, m_ui.cheatsBrowse, m_ui.cheatsOpen, m_ui.cheatsReset, "Folders", "Cheats", Path::Combine(EmuFolders::DataRoot, "cheats"));
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.covers, m_ui.coversBrowse, m_ui.coversOpen, m_ui.coversReset, "Folders", "Covers", Path::Combine(EmuFolders::DataRoot, "covers"));
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.snapshots, m_ui.snapshotsBrowse, m_ui.snapshotsOpen, m_ui.snapshotsReset, "Folders", "Snapshots", Path::Combine(EmuFolders::DataRoot, "snaps"));
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.organizeScreenshotsByGame, "EmuCore/GS", "OrganizeScreenshotsByGame", false);
connect(m_ui.organizeScreenshotsByGame, &QCheckBox::checkStateChanged, this, [](int state) {
GSConfig.OrganizeScreenshotsByGame = (state == Qt::Checked);
});
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.saveStates, m_ui.saveStatesBrowse, m_ui.saveStatesOpen, m_ui.saveStatesReset, "Folders", "SaveStates", Path::Combine(EmuFolders::DataRoot, "sstates"));
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.videoDumpingDirectory, m_ui.videoDumpingDirectoryBrowse, m_ui.videoDumpingDirectoryOpen, m_ui.videoDumpingDirectoryReset, "Folders", "Videos", Path::Combine(EmuFolders::DataRoot, "videos"));
dialog()->registerWidgetHelp(m_ui.organizeScreenshotsByGame, tr("Organize Screenshots by Game"), tr("Unchecked"),
tr("When enabled, screenshots will be saved in a folder with the game's name, instead of all being saved in the Snapshots folder"));
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.organizeSnapshotsByGame, "EmuCore/GS", "OrganizeScreenshotsByGame", false);
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.saveStates, m_ui.saveStatesBrowse, m_ui.saveStatesOpen, m_ui.saveStatesReset,
"Folders", "SaveStates", Path::Combine(EmuFolders::DataRoot, "sstates"));
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.videoDumpingDirectory, m_ui.videoDumpingDirectoryBrowse, m_ui.videoDumpingDirectoryOpen, m_ui.videoDumpingDirectoryReset,
"Folders", "Videos", Path::Combine(EmuFolders::DataRoot, "videos"));
dialog()->registerWidgetHelp(m_ui.organizeSnapshotsByGame, tr("Organize Snapshots by Game"), tr("Unchecked"),
tr("Saves snapshots to per-game subfolders instead of a shared folder."));
}
FolderSettingsWidget::~FolderSettingsWidget() = default;

View File

@ -147,7 +147,7 @@
</widget>
</item>
<item row="2" column="0" colspan="4">
<widget class="QCheckBox" name="organizeScreenshotsByGame">
<widget class="QCheckBox" name="organizeSnapshotsByGame">
<property name="text">
<string>Save Snapshots in Game-Specific Folders</string>
</property>
@ -322,7 +322,7 @@
<tabstop>snapshotsBrowse</tabstop>
<tabstop>snapshotsOpen</tabstop>
<tabstop>snapshotsReset</tabstop>
<tabstop>organizeScreenshotsByGame</tabstop>
<tabstop>organizeSnapshotsByGame</tabstop>
<tabstop>saveStates</tabstop>
<tabstop>saveStatesBrowse</tabstop>
<tabstop>saveStatesOpen</tabstop>

View File

@ -789,7 +789,7 @@ struct Pcsx2Config
VideoCaptureAutoResolution : 1,
EnableAudioCapture : 1,
EnableAudioCaptureParameters : 1,
OrganizeScreenshotsByGame : 1;
OrganizeSnapshotsByGame : 1;
};
};

View File

@ -827,20 +827,16 @@ void GSRenderer::VSync(u32 field, bool registers_written, bool idle_frame)
}
}
void GSRenderer::QueueSnapshot(const std::string& path, u32 gsdump_frames)
void GSRenderer::QueueSnapshot(const std::string& path, const u32 gsdump_frames)
{
if (!m_snapshot.empty())
return;
// Allows for providing a complete path
if (path.size() > 4 && StringUtil::EndsWithNoCase(path, ".png"))
{
m_snapshot = path.substr(0, path.size() - 4);
}
else
{
m_snapshot = GSGetBaseSnapshotFilename();
}
// this is really gross, but wx we get the snapshot request after shift...
m_dump_frames = gsdump_frames;
@ -894,31 +890,22 @@ static std::string GSGetBaseFilename()
std::string GSGetBaseSnapshotFilename()
{
// prepend snapshots directory
std::string base_path = EmuFolders::Snapshots;
// If organize by game is enabled, create a game-specific folder
if (GSConfig.OrganizeScreenshotsByGame)
// If organize by game is enabled, use or create a game-specific folder.
if (GSConfig.OrganizeSnapshotsByGame)
{
std::string game_name = VMManager::GetTitle(true);
if (!game_name.empty())
{
Path::SanitizeFileName(&game_name);
if (game_name.length() > 219)
{
game_name.resize(219);
}
const std::string game_dir = Path::Combine(base_path, game_name);
if (!FileSystem::DirectoryExists(game_dir.c_str()))
{
FileSystem::CreateDirectoryPath(game_dir.c_str(), false);
}
const std::string game_dir = Path::Combine(EmuFolders::Snapshots, game_name);
base_path = game_dir;
// Make sure the per-game directory exists or that we can successfully create it.
if (FileSystem::DirectoryExists(game_dir.c_str()) || FileSystem::CreateDirectoryPath(game_dir.c_str(), false))
return Path::Combine(game_dir, GSGetBaseFilename());
}
}
return Path::Combine(base_path, GSGetBaseFilename());
return Path::Combine(EmuFolders::Snapshots, GSGetBaseFilename());
}
std::string GSGetBaseVideoFilename()

View File

@ -59,7 +59,7 @@ public:
bool SaveSnapshotToMemory(u32 window_width, u32 window_height, bool apply_aspect, bool crop_borders,
u32* width, u32* height, std::vector<u32>* pixels);
void QueueSnapshot(const std::string& path, u32 gsdump_frames);
void QueueSnapshot(const std::string& path, const u32 gsdump_frames);
void StopGSDump();
void PresentCurrentFrame();
bool BeginCapture(std::string filename, const GSVector2i& size = GSVector2i(0, 0));

View File

@ -923,7 +923,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
SettingsWrapIntEnumEx(ScreenshotSize, "ScreenshotSize");
SettingsWrapIntEnumEx(ScreenshotFormat, "ScreenshotFormat");
SettingsWrapEntry(ScreenshotQuality);
SettingsWrapBitBool(OrganizeScreenshotsByGame);
SettingsWrapBitBoolEx(OrganizeSnapshotsByGame, "OrganizeScreenshotsByGame");
SettingsWrapEntry(StretchY);
SettingsWrapEntryEx(Crop[0], "CropLeft");
SettingsWrapEntryEx(Crop[1], "CropTop");