Qt: add some batch operations

This commit is contained in:
Megamouse 2019-01-06 22:32:23 +01:00
parent 9c346c92f3
commit 8a4778ba8c
5 changed files with 363 additions and 37 deletions

View File

@ -355,6 +355,16 @@ void game_list_frame::SortGameList()
m_gameList->resizeColumnToContents(gui::column_count - 1);
}
std::string game_list_frame::GetCacheDirBySerial(const std::string& serial)
{
return fs::get_config_dir() + "cache/" + serial;
}
std::string game_list_frame::GetDataDirBySerial(const std::string& serial)
{
return fs::get_config_dir() + "data/" + serial;
}
void game_list_frame::Refresh(const bool fromDrive, const bool scrollAfter)
{
if (fromDrive)
@ -462,8 +472,8 @@ void game_list_frame::Refresh(const bool fromDrive, const bool scrollAfter)
const auto compat = m_game_compat->GetCompatibility(game.serial);
const bool hasCustomConfig = fs::is_file(Emu.GetCustomConfigPath(game.serial)) || fs::is_file(Emu.GetCustomConfigPath(game.serial, true));
const QColor color = getGridCompatibilityColor(compat.color);
const QColor color = getGridCompatibilityColor(compat.color);
const QPixmap pxmap = PaintedPixmap(img, hasCustomConfig, color);
m_game_data.push_back(game_info(new gui_game_info{ game, compat, img, pxmap, hasCustomConfig }));
@ -655,8 +665,8 @@ void game_list_frame::ShowContextMenu(const QPoint &pos)
const QString serial = qstr(currGame.serial);
const QString name = qstr(currGame.name).simplified();
const std::string cache_base_dir = fs::get_cache_dir() + "cache/" + currGame.serial;
const std::string data_base_dir = fs::get_config_dir() + "data/" + currGame.serial;
const std::string cache_base_dir = GetCacheDirBySerial(currGame.serial);
const std::string data_base_dir = GetDataDirBySerial(currGame.serial);
// Make Actions
QMenu myMenu;
@ -774,10 +784,7 @@ void game_list_frame::ShowContextMenu(const QPoint &pos)
});
connect(createPPUCache, &QAction::triggered, [=]
{
Emu.SetForceBoot(true);
Emu.Stop();
Emu.SetForceBoot(true);
Emu.BootGame(currGame.path, true);
CreatePPUCache(currGame.path);
});
connect(removeGame, &QAction::triggered, [=]
{
@ -902,16 +909,34 @@ void game_list_frame::ShowContextMenu(const QPoint &pos)
myMenu.exec(globalPos);
}
bool game_list_frame::CreatePPUCache(const std::string& path)
{
Emu.SetForceBoot(true);
Emu.Stop();
Emu.SetForceBoot(true);
const bool success = Emu.BootGame(path, true);
if (success)
{
LOG_WARNING(GENERAL, "Creating PPU Cache for %s", path);
}
else
{
LOG_ERROR(GENERAL, "Could not create PPU Cache for %s", path);
}
return success;
}
bool game_list_frame::RemoveCustomConfiguration(const std::string& title_id, bool is_interactive)
{
const std::string config_path_new = Emu.GetCustomConfigPath(title_id);
const std::string config_path_old = Emu.GetCustomConfigPath(title_id, true);
if (!fs::is_file(config_path_new) && !fs::is_file(config_path_old))
return false;
return true;
if (is_interactive && QMessageBox::question(this, tr("Confirm Removal"), tr("Remove custom game configuration?")) != QMessageBox::Yes)
return false;
return true;
bool result = true;
@ -943,10 +968,10 @@ bool game_list_frame::RemoveCustomConfiguration(const std::string& title_id, boo
bool game_list_frame::RemoveShadersCache(const std::string& base_dir, bool is_interactive)
{
if (!fs::is_dir(base_dir))
return false;
return true;
if (is_interactive && QMessageBox::question(this, tr("Confirm Removal"), tr("Remove shaders cache?")) != QMessageBox::Yes)
return false;
return true;
QDirIterator dir_iter(qstr(base_dir), QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
while (dir_iter.hasNext())
@ -956,23 +981,31 @@ bool game_list_frame::RemoveShadersCache(const std::string& base_dir, bool is_in
if (dir_iter.fileName() == "shaders_cache")
{
if (QDir(filepath).removeRecursively())
{
LOG_NOTICE(GENERAL, "Removed shaders cache dir: %s", sstr(filepath));
}
else
LOG_WARNING(GENERAL, "Could not remove shaders cache file: %s", sstr(filepath));
{
LOG_FATAL(GENERAL, "Could not completely remove shaders cache file: %s", sstr(filepath));
return false;
}
break;
}
}
LOG_SUCCESS(GENERAL, "Removed shaders cache in %s", base_dir);
return true;
}
bool game_list_frame::RemovePPUCache(const std::string& base_dir, bool is_interactive)
{
if (!fs::is_dir(base_dir))
return false;
return true;
if (is_interactive && QMessageBox::question(this, tr("Confirm Removal"), tr("Remove PPU cache?")) != QMessageBox::Yes)
return false;
return true;
u32 files_removed = 0;
u32 files_total = 0;
QDirIterator dir_iter(qstr(base_dir), QDir::Files | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
while (dir_iter.hasNext())
@ -982,23 +1015,38 @@ bool game_list_frame::RemovePPUCache(const std::string& base_dir, bool is_intera
if (dir_iter.fileInfo().absoluteFilePath().endsWith(".obj", Qt::CaseInsensitive))
{
if (QFile::remove(filepath))
{
++files_removed;
LOG_NOTICE(GENERAL, "Removed PPU cache file: %s", sstr(filepath));
}
else
{
LOG_WARNING(GENERAL, "Could not remove PPU cache file: %s", sstr(filepath));
}
++files_total;
}
}
LOG_SUCCESS(GENERAL, "Removed PPU cache in %s", base_dir);
return true;
const bool success = files_total == files_removed;
if (success)
LOG_SUCCESS(GENERAL, "Removed PPU cache in %s", base_dir);
else
LOG_FATAL(GENERAL, "Only %d/%d PPU cache files could be removed in %s", files_removed, files_total, base_dir);
return success;
}
bool game_list_frame::RemoveSPUCache(const std::string& base_dir, bool is_interactive)
{
if (!fs::is_dir(base_dir))
return false;
return true;
if (is_interactive && QMessageBox::question(this, tr("Confirm Removal"), tr("Remove SPU cache?")) != QMessageBox::Yes)
return false;
return true;
u32 files_removed = 0;
u32 files_total = 0;
QDirIterator dir_iter(qstr(base_dir), QDir::Files | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
while (dir_iter.hasNext())
@ -1008,14 +1056,244 @@ bool game_list_frame::RemoveSPUCache(const std::string& base_dir, bool is_intera
if (dir_iter.fileInfo().absoluteFilePath().endsWith(".dat", Qt::CaseInsensitive))
{
if (QFile::remove(filepath))
{
++files_removed;
LOG_NOTICE(GENERAL, "Removed SPU cache file: %s", sstr(filepath));
}
else
{
LOG_WARNING(GENERAL, "Could not remove SPU cache file: %s", sstr(filepath));
}
++files_total;
}
}
LOG_SUCCESS(GENERAL, "Removed SPU cache in %s", base_dir);
return true;
const bool success = files_total == files_removed;
if (success)
LOG_SUCCESS(GENERAL, "Removed SPU cache in %s", base_dir);
else
LOG_FATAL(GENERAL, "Only %d/%d SPU cache files could be removed in %s", files_removed, files_total, base_dir);
return success;
}
void game_list_frame::BatchCreatePPUCaches()
{
std::set<std::string> paths;
for (const auto& game : m_game_data)
{
paths.emplace(game->info.path);
}
const u32 total = paths.size();
if (total == 0)
{
QMessageBox::information(this, tr("PPU Cache Batch Creation"), tr("No titles found"), QMessageBox::Ok);
return;
}
progress_dialog* pdlg = new progress_dialog(tr("Creating all PPU caches"), tr("Cancel"), 0, m_game_data.size(), this);
pdlg->setWindowTitle(tr("PPU Cache Batch Creation"));
pdlg->setAutoClose(false);
pdlg->setAutoReset(false);
pdlg->show();
u32 created = 0;
for (const auto& path : paths)
{
if (pdlg->wasCanceled())
{
LOG_NOTICE(GENERAL, "PPU Cache Batch Creation was canceled");
break;
}
QApplication::processEvents();
if (CreatePPUCache(path))
{
while (!Emu.IsStopped())
{
QApplication::processEvents();
}
pdlg->SetValue(++created);
}
}
pdlg->setLabelText(tr("Created PPU Caches for %0 titles").arg(created));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
}
void game_list_frame::BatchRemovePPUCaches()
{
std::set<std::string> serials;
for (const auto& game : m_game_data)
{
serials.emplace(game->info.serial);
}
const u32 total = serials.size();
if (total == 0)
{
QMessageBox::information(this, tr("PPU Cache Batch Removal"), tr("No files found"), QMessageBox::Ok);
return;
}
progress_dialog* pdlg = new progress_dialog(tr("Removing all PPU caches"), tr("Cancel"), 0, total, this);
pdlg->setWindowTitle(tr("PPU Cache Batch Removal"));
pdlg->setAutoClose(false);
pdlg->setAutoReset(false);
pdlg->show();
u32 removed = 0;
for (const auto& serial : serials)
{
if (pdlg->wasCanceled())
{
LOG_NOTICE(GENERAL, "PPU Cache Batch Removal was canceled");
break;
}
QApplication::processEvents();
if (RemovePPUCache(GetCacheDirBySerial(serial)))
{
pdlg->SetValue(++removed);
}
}
pdlg->setLabelText(tr("%0/%1 caches cleared").arg(removed).arg(total));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
}
void game_list_frame::BatchRemoveSPUCaches()
{
std::set<std::string> serials;
for (const auto& game : m_game_data)
{
serials.emplace(game->info.serial);
}
const u32 total = serials.size();
if (total == 0)
{
QMessageBox::information(this, tr("SPU Cache Batch Removal"), tr("No files found"), QMessageBox::Ok);
return;
}
progress_dialog* pdlg = new progress_dialog(tr("Removing all SPU caches"), tr("Cancel"), 0, total, this);
pdlg->setWindowTitle(tr("SPU Cache Batch Removal"));
pdlg->setAutoClose(false);
pdlg->setAutoReset(false);
pdlg->show();
u32 removed = 0;
for (const auto& serial : serials)
{
if (pdlg->wasCanceled())
{
LOG_NOTICE(GENERAL, "SPU Cache Batch Removal was canceled. %d/%d folders cleared", removed, total);
break;
}
QApplication::processEvents();
if (RemoveSPUCache(GetCacheDirBySerial(serial)))
{
pdlg->SetValue(++removed);
}
}
pdlg->setLabelText(tr("%0/%1 caches cleared").arg(removed).arg(total));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
}
void game_list_frame::BatchRemoveCustomConfigurations()
{
std::set<std::string> serials;
for (const auto& game : m_game_data)
{
if (game->hasCustomConfig && !serials.count(game->info.serial))
{
serials.emplace(game->info.serial);
}
}
const u32 total = serials.size();
if (total == 0)
{
QMessageBox::information(this, tr("Custom Configuration Batch Removal"), tr("No files found"), QMessageBox::Ok);
return;
}
progress_dialog* pdlg = new progress_dialog(tr("Removing all custom configurations"), tr("Cancel"), 0, total, this);
pdlg->setWindowTitle(tr("Custom Configuration Batch Removal"));
pdlg->setAutoClose(false);
pdlg->setAutoReset(false);
pdlg->show();
u32 removed = 0;
for (const auto& serial : serials)
{
if (pdlg->wasCanceled())
{
LOG_NOTICE(GENERAL, "Custom Configuration Batch Removal was canceled. %d/%d custom configurations cleared", removed, total);
break;
}
QApplication::processEvents();
if (RemoveCustomConfiguration(serial))
{
pdlg->SetValue(++removed);
}
}
pdlg->setLabelText(tr("%0/%1 custom configurations cleared").arg(removed).arg(total));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
Refresh(true);
}
void game_list_frame::BatchRemoveShaderCaches()
{
std::set<std::string> serials;
for (const auto& game : m_game_data)
{
serials.emplace(game->info.serial);
}
const u32 total = serials.size();
if (total == 0)
{
QMessageBox::information(this, tr("Shader Cache Batch Removal"), tr("No files found"), QMessageBox::Ok);
return;
}
progress_dialog* pdlg = new progress_dialog(tr("Removing all shader caches"), tr("Cancel"), 0, total, this);
pdlg->setWindowTitle(tr("Shader Cache Batch Removal"));
pdlg->setAutoClose(false);
pdlg->setAutoReset(false);
pdlg->show();
u32 removed = 0;
for (const auto& serial : serials)
{
if (pdlg->wasCanceled())
{
LOG_NOTICE(GENERAL, "Shader Cache Batch Removal was canceled");
break;
}
QApplication::processEvents();
if (RemoveShadersCache(GetCacheDirBySerial(serial)))
{
pdlg->SetValue(++removed);
}
}
pdlg->setLabelText(tr("%0/%1 shader caches cleared").arg(removed).arg(total));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
}
QPixmap game_list_frame::PaintedPixmap(const QImage& img, bool paint_config_icon, const QColor& compatibility_color)

View File

@ -211,15 +211,16 @@ public:
void SetShowHidden(bool show);
public Q_SLOTS:
void BatchCreatePPUCaches();
void BatchRemovePPUCaches();
void BatchRemoveSPUCaches();
void BatchRemoveCustomConfigurations();
void BatchRemoveShaderCaches();
void SetListMode(const bool& isList);
void SetSearchText(const QString& text);
void SetShowCompatibilityInGrid(bool show);
private Q_SLOTS:
bool RemoveCustomConfiguration(const std::string& base_dir, bool is_interactive = false);
bool RemoveShadersCache(const std::string& base_dir, bool is_interactive = false);
bool RemovePPUCache(const std::string& base_dir, bool is_interactive = false);
bool RemoveSPUCache(const std::string& base_dir, bool is_interactive = false);
void OnColClicked(int col);
void ShowContextMenu(const QPoint &pos);
void doubleClickedSlot(QTableWidgetItem *item);
@ -243,6 +244,14 @@ private:
int PopulateGameList();
bool SearchMatchesApp(const std::string& name, const std::string& serial);
bool RemoveCustomConfiguration(const std::string& base_dir, bool is_interactive = false);
bool RemoveShadersCache(const std::string& base_dir, bool is_interactive = false);
bool RemovePPUCache(const std::string& base_dir, bool is_interactive = false);
bool RemoveSPUCache(const std::string& base_dir, bool is_interactive = false);
bool CreatePPUCache(const std::string& path);
std::string GetCacheDirBySerial(const std::string& serial);
std::string GetDataDirBySerial(const std::string& serial);
std::string CurrentSelectionIconPath();
std::string GetStringFromU32(const u32& key, const std::map<u32, QString>& map, bool combined = false);

View File

@ -465,8 +465,6 @@ void main_window::InstallPkg(const QString& dropPath, bool is_bulk)
progress_dialog pdlg(tr("Installing package ... please wait ..."), tr("Cancel"), 0, 1000, this);
pdlg.setWindowTitle(tr("RPCS3 Package Installer"));
pdlg.setWindowModality(Qt::WindowModal);
pdlg.setFixedWidth(QLabel("This is the very length of the progressdialog due to hidpi reasons.").sizeHint().width());
pdlg.show();
// Synchronization variable
@ -582,8 +580,6 @@ void main_window::InstallPup(const QString& dropPath)
progress_dialog pdlg(tr("Installing firmware version %1\nPlease wait...").arg(qstr(version_string)), tr("Cancel"), 0, static_cast<int>(updatefilenames.size()), this);
pdlg.setWindowTitle(tr("RPCS3 Firmware Installer"));
pdlg.setWindowModality(Qt::WindowModal);
pdlg.setFixedWidth(QLabel("This is the very length of the progressdialog due to hidpi reasons.").sizeHint().width());
pdlg.show();
// Synchronization variable
@ -1242,6 +1238,13 @@ void main_window::CreateConnects()
connect(ui->bootInstallPkgAct, &QAction::triggered, [this] {InstallPkg(); });
connect(ui->bootInstallPupAct, &QAction::triggered, [this] {InstallPup(); });
connect(ui->exitAct, &QAction::triggered, this, &QWidget::close);
connect(ui->batchCreatePPUCachesAct, &QAction::triggered, m_gameListFrame, &game_list_frame::BatchCreatePPUCaches);
connect(ui->batchRemovePPUCachesAct, &QAction::triggered, m_gameListFrame, &game_list_frame::BatchRemovePPUCaches);
connect(ui->batchRemoveSPUCachesAct, &QAction::triggered, m_gameListFrame, &game_list_frame::BatchRemoveSPUCaches);
connect(ui->batchRemoveShaderCachesAct, &QAction::triggered, m_gameListFrame, &game_list_frame::BatchRemoveShaderCaches);
connect(ui->batchRemoveCustomConfigurationsAct, &QAction::triggered, m_gameListFrame, &game_list_frame::BatchRemoveCustomConfigurations);
connect(ui->sysPauseAct, &QAction::triggered, this, &main_window::OnPlayOrPause);
connect(ui->sysStopAct, &QAction::triggered, [=]() { Emu.Stop(); });
connect(ui->sysRebootAct, &QAction::triggered, [=]() { Emu.Restart(); });

View File

@ -165,6 +165,17 @@
<addaction name="freezeRecentAct"/>
<addaction name="separator"/>
</widget>
<widget class="QMenu" name="menuBatch">
<property name="title">
<string>All Titles</string>
</property>
<addaction name="batchCreatePPUCachesAct"/>
<addaction name="separator"/>
<addaction name="batchRemoveCustomConfigurationsAct"/>
<addaction name="batchRemovePPUCachesAct"/>
<addaction name="batchRemoveSPUCachesAct"/>
<addaction name="batchRemoveShaderCachesAct"/>
</widget>
<addaction name="bootElfAct"/>
<addaction name="bootGameAct"/>
<addaction name="bootRecentMenu"/>
@ -174,6 +185,8 @@
<addaction name="bootInstallPkgAct"/>
<addaction name="bootInstallPupAct"/>
<addaction name="separator"/>
<addaction name="menuBatch"/>
<addaction name="separator"/>
<addaction name="exitAct"/>
</widget>
<widget class="QMenu" name="menuEmulation">
@ -931,14 +944,6 @@
<string>Other</string>
</property>
</action>
<action name="showGameToolBarAct">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Show Game Tool Bar</string>
</property>
</action>
<action name="showHiddenEntriesAct">
<property name="checkable">
<bool>true</bool>
@ -965,6 +970,31 @@
<string>Show Title Bars</string>
</property>
</action>
<action name="batchCreatePPUCachesAct">
<property name="text">
<string>Create PPU Caches</string>
</property>
</action>
<action name="batchRemoveCustomConfigurationsAct">
<property name="text">
<string>Remove Custom Configurations</string>
</property>
</action>
<action name="batchRemovePPUCachesAct">
<property name="text">
<string>Remove PPU Caches</string>
</property>
</action>
<action name="batchRemoveSPUCachesAct">
<property name="text">
<string>Remove SPU Caches</string>
</property>
</action>
<action name="batchRemoveShaderCachesAct">
<property name="text">
<string>Remove Shader Caches</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>

View File

@ -1,8 +1,14 @@
#include "progress_dialog.h"
#include <QLabel>
progress_dialog::progress_dialog(const QString &labelText, const QString &cancelButtonText, int minimum, int maximum, QWidget *parent, Qt::WindowFlags flags)
: QProgressDialog(labelText, cancelButtonText, minimum, maximum, parent, flags)
{
setFixedWidth(QLabel("This is the very length of the progressdialog due to hidpi reasons.").sizeHint().width());
setWindowModality(Qt::WindowModal);
connect(this, &QProgressDialog::canceled, this, &QProgressDialog::deleteLater);
#ifdef _WIN32
m_tb_button = std::make_unique<QWinTaskbarButton>();
m_tb_button->setWindow(parent ? parent->windowHandle() : windowHandle());