mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-28 12:40:12 +00:00
GUI: Add recent games menu (#2843)
* add recent games menu * remove invalid paths from list * push InvalidRecentAction into BootRecentAction * disable actions on boot disable clear recent on freeze recent * fix gamelist games not booting on recent list * minor fix for list disable error
This commit is contained in:
parent
0f433ea882
commit
6cb7a17814
@ -345,6 +345,7 @@ void game_list_frame::doubleClickedSlot(const QModelIndex& index)
|
||||
{
|
||||
const std::string& path = Emu.GetGameDir() + m_game_data[i].root;
|
||||
emit RequestIconPathSet(path);
|
||||
emit RequestAddRecentGame(qstr(path), qstr("[" + m_game_data[i].serial + "] " + m_game_data[i].name));
|
||||
|
||||
Emu.Stop();
|
||||
|
||||
@ -438,6 +439,7 @@ void game_list_frame::Boot(int row)
|
||||
{
|
||||
const std::string& path = Emu.GetGameDir() + m_game_data[row].root;
|
||||
emit RequestIconPathSet(path);
|
||||
emit RequestAddRecentGame(qstr(path), qstr("[" + m_game_data[row].serial + "] " + m_game_data[row].name));
|
||||
|
||||
Emu.Stop();
|
||||
|
||||
|
@ -109,6 +109,7 @@ private slots:
|
||||
signals:
|
||||
void game_list_frameClosed();
|
||||
void RequestIconPathSet(const std::string path);
|
||||
void RequestAddRecentGame(const QString path, const QString name);
|
||||
protected:
|
||||
/** Override inherited method from Qt to allow signalling when close happened.*/
|
||||
void closeEvent(QCloseEvent* event);
|
||||
|
@ -45,6 +45,10 @@ namespace GUI
|
||||
const QString logger = "Logger";
|
||||
const QString meta = "Meta";
|
||||
|
||||
const GUI_SAVE rg_freeze = GUI_SAVE(main_window, "recentGamesFrozen", false);
|
||||
const GUI_SAVE rg_names = GUI_SAVE(main_window, "recentGamesNames", QStringList());
|
||||
const GUI_SAVE rg_paths = GUI_SAVE(main_window, "recentGamesPaths", QStringList());
|
||||
|
||||
const GUI_SAVE ib_pkg_success = GUI_SAVE( main_window, "infoBoxEnabledInstallPKG", true );
|
||||
const GUI_SAVE ib_pup_success = GUI_SAVE( main_window, "infoBoxEnabledInstallPUP", true );
|
||||
const GUI_SAVE ib_show_welcome = GUI_SAVE(main_window, "infoBoxEnabledWelcome", true);
|
||||
|
@ -131,7 +131,7 @@ QIcon main_window::GetAppIcon()
|
||||
void main_window::SetAppIconFromPath(const std::string path)
|
||||
{
|
||||
// get Icon for the gs_frame from path. this handles presumably all possible use cases
|
||||
QString qpath = QString::fromUtf8(path.data(), path.size());
|
||||
QString qpath = qstr(path);
|
||||
std::string icon_list[] = { "/ICON0.PNG", "/PS3_GAME/ICON0.PNG" };
|
||||
std::string path_list[] = { path, sstr(qpath.section("/", 0, -2)) ,sstr(qpath.section("/", 0, -3)) };
|
||||
for (std::string pth : path_list)
|
||||
@ -142,7 +142,7 @@ void main_window::SetAppIconFromPath(const std::string path)
|
||||
if (fs::is_file(ico))
|
||||
{
|
||||
// load the image from path. It will most likely be a rectangle
|
||||
QImage source = QImage(QString::fromUtf8(ico.data(), ico.size()));
|
||||
QImage source = QImage(qstr(ico));
|
||||
int edgeMax = std::max(source.width(), source.height());
|
||||
|
||||
// create a new transparent image with square size and same format as source (maybe handle other formats than RGB32 as well?)
|
||||
@ -203,6 +203,9 @@ void main_window::BootElf()
|
||||
guiSettings->SetValue(GUI::fd_boot_elf, filePath);
|
||||
const std::string path = sstr(QFileInfo(filePath).canonicalFilePath());
|
||||
|
||||
const std::string serial = Emu.GetTitleID().empty() ? "" : "[" + Emu.GetTitleID() + "] ";
|
||||
AddRecentAction(qstr(path), qstr(serial + Emu.GetTitle()));
|
||||
|
||||
SetAppIconFromPath(path);
|
||||
Emu.Stop();
|
||||
Emu.SetPath(path);
|
||||
@ -234,6 +237,9 @@ void main_window::BootGame()
|
||||
const std::string path = sstr(dirPath);
|
||||
SetAppIconFromPath(path);
|
||||
|
||||
const std::string serial = Emu.GetTitleID().empty() ? "" : "[" + Emu.GetTitleID() + "] ";
|
||||
AddRecentAction(qstr(path), qstr(serial + Emu.GetTitle()));
|
||||
|
||||
if (!Emu.BootGame(path))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "PS3 executable not found in selected folder (%s)", path);
|
||||
@ -674,6 +680,15 @@ void main_window::OnEmuRun()
|
||||
menu_run->setText(tr("&Pause"));
|
||||
menu_run->setIcon(icon_pause);
|
||||
EnableMenus(true);
|
||||
|
||||
// Disable Recent Games
|
||||
for (auto act : m_bootRecentMenu->actions())
|
||||
{
|
||||
if (act != freezeRecentAct && act != clearRecentAct)
|
||||
{
|
||||
act->setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main_window::OnEmuResume()
|
||||
@ -725,6 +740,15 @@ void main_window::OnEmuStop()
|
||||
sysPauseAct->setText(Emu.IsReady() ? tr("&Start\tCtrl+E") : tr("&Resume\tCtrl+E"));
|
||||
sysPauseAct->setIcon(icon_play);
|
||||
}
|
||||
|
||||
// Enable Recent Games
|
||||
for (auto act : m_bootRecentMenu->actions())
|
||||
{
|
||||
if (act != freezeRecentAct && act != clearRecentAct)
|
||||
{
|
||||
act->setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main_window::OnEmuReady()
|
||||
@ -771,6 +795,173 @@ void main_window::EnableMenus(bool enabled)
|
||||
toolsStringSearchAct->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void main_window::BootRecentAction(const QAction* act)
|
||||
{
|
||||
if (Emu.IsRunning())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const QString pth = act->data().toString();
|
||||
|
||||
// path is invalid: remove action from list return
|
||||
if (!QFileInfo(pth).isDir() && !QFileInfo(pth).isFile())
|
||||
{
|
||||
if (m_rg_paths.contains(pth))
|
||||
{
|
||||
// clear menu of actions
|
||||
for (auto act : m_recentGameActs)
|
||||
{
|
||||
m_bootRecentMenu->removeAction(act);
|
||||
}
|
||||
|
||||
// remove action from list
|
||||
int idx = m_rg_paths.indexOf(pth);
|
||||
m_rg_names.removeAt(idx);
|
||||
m_rg_paths.removeAt(idx);
|
||||
m_recentGameActs.removeAt(idx);
|
||||
|
||||
guiSettings->SetValue(GUI::rg_paths, m_rg_paths);
|
||||
guiSettings->SetValue(GUI::rg_names, m_rg_names);
|
||||
|
||||
LOG_ERROR(GENERAL, "Recent Game not valid, removed from Boot Recent list: %s", sstr(pth));
|
||||
|
||||
// refill menu with actions
|
||||
for (uint i = 0; i < m_recentGameActs.count(); i++)
|
||||
{
|
||||
m_recentGameActs[i]->setShortcut(tr("Ctrl+%1").arg(i + 1));
|
||||
m_recentGameActs[i]->setToolTip(m_rg_names[i]);
|
||||
m_bootRecentMenu->addAction(m_recentGameActs[i]);
|
||||
}
|
||||
|
||||
LOG_WARNING(GENERAL, "Boot Recent list refreshed");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(GENERAL, "Path invalid and not in m_rg_paths: %s", sstr(pth));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SetAppIconFromPath(sstr(pth));
|
||||
|
||||
Emu.Stop();
|
||||
|
||||
AddRecentAction(act->property("path").toString(), act->property("shown_name").toString());
|
||||
|
||||
if (!Emu.BootGame(sstr(pth), true))
|
||||
{
|
||||
LOG_ERROR(LOADER, "Failed to boot %s", sstr(pth));
|
||||
}
|
||||
};
|
||||
|
||||
QAction* main_window::CreateRecentAction(const QString& path, const QString& name, const uint& sc_idx)
|
||||
{
|
||||
// if path is not valid remove from list
|
||||
if (!QFileInfo(path).isDir() && !QFileInfo(path).isFile())
|
||||
{
|
||||
if (m_rg_paths.contains(path))
|
||||
{
|
||||
int idx = m_rg_paths.indexOf(path);
|
||||
m_rg_names.removeAt(idx);
|
||||
m_rg_paths.removeAt(idx);
|
||||
|
||||
guiSettings->SetValue(GUI::rg_names, m_rg_names);
|
||||
guiSettings->SetValue(GUI::rg_paths, m_rg_paths);
|
||||
|
||||
LOG_ERROR(GENERAL, "Recent Game not valid, removed from Boot Recent list: %s", sstr(path));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// if name is a path get filename
|
||||
QString shown_name = name;
|
||||
if (QFileInfo(name).isFile())
|
||||
{
|
||||
shown_name = name.section('/', -1);
|
||||
}
|
||||
|
||||
// create new action
|
||||
QAction* act = new QAction(shown_name, this);
|
||||
act->setData(path);
|
||||
act->setToolTip(name);
|
||||
act->setShortcut(tr("Ctrl+%1").arg(sc_idx));
|
||||
|
||||
// truncate if too long
|
||||
if (shown_name.length() > 60)
|
||||
{
|
||||
act->setText(shown_name.left(27) + "(....)" + shown_name.right(27));
|
||||
}
|
||||
|
||||
// connect boot
|
||||
connect(act, &QAction::triggered, [=]() {BootRecentAction(act); });
|
||||
|
||||
return act;
|
||||
};
|
||||
|
||||
void main_window::AddRecentAction(const QString path, QString name)
|
||||
{
|
||||
// don't change list on freeze
|
||||
if (freezeRecentAct->isChecked())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// create new action, return if not valid
|
||||
QAction* act = CreateRecentAction(path, name, 1);
|
||||
if (!act)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// clear menu of actions
|
||||
for (auto act : m_recentGameActs)
|
||||
{
|
||||
m_bootRecentMenu->removeAction(act);
|
||||
}
|
||||
|
||||
// if path already exists, remove it in order to get it to beginning
|
||||
if (m_rg_paths.contains(path))
|
||||
{
|
||||
int idx = m_rg_paths.indexOf(path);
|
||||
m_rg_names.removeAt(idx);
|
||||
m_rg_paths.removeAt(idx);
|
||||
m_recentGameActs.removeAt(idx);
|
||||
}
|
||||
|
||||
// remove oldest action at the end if needed
|
||||
if (m_rg_names.count() == 9 && m_rg_paths.count() == 9)
|
||||
{
|
||||
m_rg_names.removeLast();
|
||||
m_rg_paths.removeLast();
|
||||
m_recentGameActs.removeLast();
|
||||
}
|
||||
else if (m_rg_names.count() != m_rg_paths.count())
|
||||
{
|
||||
LOG_ERROR(LOADER, "Recent games pathlist and namelist have different count");
|
||||
}
|
||||
|
||||
if (m_rg_paths.count() < 9)
|
||||
{
|
||||
// add new action at the beginning
|
||||
m_rg_names.prepend(name);
|
||||
m_rg_paths.prepend(path);
|
||||
m_recentGameActs.prepend(act);
|
||||
}
|
||||
|
||||
// refill menu with actions
|
||||
for (uint i = 0; i < m_recentGameActs.count(); i++)
|
||||
{
|
||||
m_recentGameActs[i]->setShortcut(tr("Ctrl+%1").arg(i+1));
|
||||
m_recentGameActs[i]->setToolTip(m_rg_names[i]);
|
||||
m_bootRecentMenu->addAction(m_recentGameActs[i]);
|
||||
}
|
||||
|
||||
guiSettings->SetValue(GUI::rg_names, m_rg_names);
|
||||
guiSettings->SetValue(GUI::rg_paths, m_rg_paths);
|
||||
}
|
||||
|
||||
void main_window::CreateActions()
|
||||
{
|
||||
bootElfAct = new QAction(tr("Boot (S)ELF file"), this);
|
||||
@ -778,6 +969,10 @@ void main_window::CreateActions()
|
||||
bootInstallPkgAct = new QAction(tr("&Install PKG"), this);
|
||||
bootInstallPupAct = new QAction(tr("&Install Firmware"), this);
|
||||
|
||||
clearRecentAct = new QAction(tr("&Clear List"), this);
|
||||
freezeRecentAct = new QAction(tr("&Freeze List"), this);
|
||||
freezeRecentAct->setCheckable(true);
|
||||
|
||||
exitAct = new QAction(tr("E&xit"), this);
|
||||
exitAct->setShortcuts(QKeySequence::Quit);
|
||||
exitAct->setStatusTip(tr("Exit the application"));
|
||||
@ -880,6 +1075,21 @@ void main_window::CreateConnects()
|
||||
{
|
||||
connect(bootElfAct, &QAction::triggered, this, &main_window::BootElf);
|
||||
connect(bootGameAct, &QAction::triggered, this, &main_window::BootGame);
|
||||
connect(clearRecentAct, &QAction::triggered, [this](){
|
||||
if (freezeRecentAct->isChecked()) { return; }
|
||||
m_rg_names.clear();
|
||||
m_rg_paths.clear();
|
||||
for (auto act : m_recentGameActs)
|
||||
{
|
||||
m_bootRecentMenu->removeAction(act);
|
||||
}
|
||||
m_recentGameActs.clear();
|
||||
guiSettings->SetValue(GUI::rg_paths, QStringList());
|
||||
guiSettings->SetValue(GUI::rg_names, QStringList());
|
||||
});
|
||||
connect(freezeRecentAct, &QAction::triggered, [=](bool checked) {
|
||||
guiSettings->SetValue(GUI::rg_freeze, checked);
|
||||
});
|
||||
connect(bootInstallPkgAct, &QAction::triggered, this, &main_window::InstallPkg);
|
||||
connect(bootInstallPupAct, &QAction::triggered, this, &main_window::InstallPup);
|
||||
connect(exitAct, &QAction::triggered, this, &QWidget::close);
|
||||
@ -1002,6 +1212,13 @@ void main_window::CreateMenus()
|
||||
QMenu *bootMenu = menuBar()->addMenu(tr("&Boot"));
|
||||
bootMenu->addAction(bootElfAct);
|
||||
bootMenu->addAction(bootGameAct);
|
||||
|
||||
m_bootRecentMenu = bootMenu->addMenu(tr("Boot Recent"));
|
||||
m_bootRecentMenu->setToolTipsVisible(true);
|
||||
m_bootRecentMenu->addAction(clearRecentAct);
|
||||
m_bootRecentMenu->addAction(freezeRecentAct);
|
||||
m_bootRecentMenu->addSeparator();
|
||||
|
||||
bootMenu->addSeparator();
|
||||
bootMenu->addAction(bootInstallPkgAct);
|
||||
bootMenu->addAction(bootInstallPupAct);
|
||||
@ -1115,6 +1332,7 @@ void main_window::CreateDockWindows()
|
||||
}
|
||||
});
|
||||
connect(gameListFrame, &game_list_frame::RequestIconPathSet, this, &main_window::SetAppIconFromPath);
|
||||
connect(gameListFrame, &game_list_frame::RequestAddRecentGame, this, &main_window::AddRecentAction);
|
||||
}
|
||||
|
||||
void main_window::ConfigureGuiFromSettings(bool configureAll)
|
||||
@ -1135,6 +1353,28 @@ void main_window::ConfigureGuiFromSettings(bool configureAll)
|
||||
|
||||
restoreState(guiSettings->GetValue(GUI::mw_windowState).toByteArray());
|
||||
|
||||
freezeRecentAct->setChecked(guiSettings->GetValue(GUI::rg_freeze).toBool());
|
||||
m_rg_names = guiSettings->GetValue(GUI::rg_names).toStringList();
|
||||
m_rg_paths = guiSettings->GetValue(GUI::rg_paths).toStringList();
|
||||
|
||||
// Fill the recent games menu
|
||||
for (uint i = 0; i < m_rg_paths.count(); i++)
|
||||
{
|
||||
// create new action
|
||||
QAction* act = CreateRecentAction(m_rg_paths[i], m_rg_names[i], i + 1);
|
||||
|
||||
// add action to menu
|
||||
if (act)
|
||||
{
|
||||
m_recentGameActs.append(act);
|
||||
m_bootRecentMenu->addAction(act);
|
||||
}
|
||||
else
|
||||
{
|
||||
i--; // list count is now an entry shorter so we have to repeat the same index in order to load all other entries
|
||||
}
|
||||
}
|
||||
|
||||
showLogAct->setChecked(guiSettings->GetValue(GUI::mw_logger).toBool());
|
||||
showGameListAct->setChecked(guiSettings->GetValue(GUI::mw_gamelist).toBool());
|
||||
showDebuggerAct->setChecked(guiSettings->GetValue(GUI::mw_debugger).toBool());
|
||||
|
@ -89,10 +89,21 @@ private:
|
||||
void EnableMenus(bool enabled);
|
||||
void keyPressEvent(QKeyEvent *keyEvent);
|
||||
|
||||
QAction* CreateRecentAction(const QString& path, const QString& name, const uint& sc_idx);
|
||||
void BootRecentAction(const QAction* act);
|
||||
void AddRecentAction(const QString path, QString name);
|
||||
|
||||
QStringList m_rg_names;
|
||||
QStringList m_rg_paths;
|
||||
QMenu* m_bootRecentMenu;
|
||||
QList<QAction*> m_recentGameActs;
|
||||
|
||||
QActionGroup* iconSizeActGroup;
|
||||
|
||||
QAction *bootElfAct;
|
||||
QAction *bootGameAct;
|
||||
QAction *clearRecentAct;
|
||||
QAction *freezeRecentAct;
|
||||
QAction *bootInstallPkgAct;
|
||||
QAction *bootInstallPupAct;
|
||||
QAction *sysPauseAct;
|
||||
|
Loading…
x
Reference in New Issue
Block a user