mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-05-25 12:55:00 +00:00
- Added trophy decryption when extracting a fpkg. trp icons and xmls are dumped to game_data/<title> (can be restored if deleted by accident by opening the trophy viewer)
- Added a trophy viewer (right click on game ==> trophy viewer) - Enabled Run button. - Switched gui settings to toml. - Added recent files (6 max) - Applied @raphaelthegreat suggestions and corrections (Thanks a lot). - Fixed several bugs and crashes. - Full screen should disabled by default. - Added region in list mode. - Added a simple temp elf list widget. - Added messages when extracting pkg (ex: installing a patch before the game...etc)
This commit is contained in:
parent
71dda8c776
commit
0f27e0edf2
49 changed files with 1616 additions and 891 deletions
|
@ -13,38 +13,41 @@
|
|||
#include "core/file_format/pkg.h"
|
||||
#include "core/loader.h"
|
||||
#include "game_install_dialog.h"
|
||||
#include "gui_settings.h"
|
||||
#include "main_window.h"
|
||||
|
||||
MainWindow::MainWindow(std::shared_ptr<GuiSettings> gui_settings, QWidget* parent)
|
||||
: QMainWindow(parent), ui(new Ui::MainWindow), m_gui_settings(std::move(gui_settings)) {
|
||||
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
SaveWindowState();
|
||||
const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
|
||||
Config::save(config_dir / "config.toml");
|
||||
}
|
||||
|
||||
bool MainWindow::Init() {
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
// setup ui
|
||||
AddUiWidgets();
|
||||
CreateActions();
|
||||
CreateRecentGameActions();
|
||||
ConfigureGuiFromSettings();
|
||||
CreateDockWindows();
|
||||
CreateConnects();
|
||||
SetLastUsedTheme();
|
||||
SetLastIconSizeBullet();
|
||||
ConfigureGuiFromSettings();
|
||||
LoadGameLists();
|
||||
|
||||
// show ui
|
||||
setMinimumSize(350, minimumSizeHint().height());
|
||||
setWindowTitle(QString::fromStdString("shadPS4 v" + std::string(Common::VERSION)));
|
||||
show();
|
||||
this->show();
|
||||
// load game list
|
||||
LoadGameLists();
|
||||
|
||||
auto end = std::chrono::steady_clock::now();
|
||||
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
||||
statusBar = new QStatusBar(this);
|
||||
m_main_window->setStatusBar(statusBar);
|
||||
statusBar.reset(new QStatusBar);
|
||||
this->setStatusBar(statusBar.data());
|
||||
// Update status bar
|
||||
int numGames = m_game_info->m_games.size();
|
||||
QString statusMessage = "Games: " + QString::number(numGames) + " (" +
|
||||
|
@ -93,45 +96,59 @@ void MainWindow::AddUiWidgets() {
|
|||
}
|
||||
|
||||
void MainWindow::CreateDockWindows() {
|
||||
m_main_window = new QMainWindow();
|
||||
m_main_window->setContextMenuPolicy(Qt::PreventContextMenu);
|
||||
// place holder widget is needed for good health they say :)
|
||||
QWidget* phCentralWidget = new QWidget(this);
|
||||
setCentralWidget(phCentralWidget);
|
||||
|
||||
// resize window to last W and H
|
||||
QSize window_size = m_gui_settings->GetValue(gui::m_window_size).toSize();
|
||||
m_main_window->resize(window_size.width(), window_size.height());
|
||||
|
||||
// Add the game table.
|
||||
m_dock_widget = new QDockWidget("Game List", m_main_window);
|
||||
m_game_list_frame = new GameListFrame(m_game_info, m_gui_settings, m_main_window);
|
||||
m_dock_widget.reset(new QDockWidget("Game List", this));
|
||||
m_game_list_frame.reset(new GameListFrame(m_game_info, this));
|
||||
m_game_list_frame->setObjectName("gamelist");
|
||||
m_game_grid_frame = new GameGridFrame(m_game_info, m_gui_settings, m_main_window);
|
||||
m_game_grid_frame.reset(new GameGridFrame(m_game_info, this));
|
||||
m_game_grid_frame->setObjectName("gamegridlist");
|
||||
m_elf_viewer.reset(new ElfViewer(this));
|
||||
m_elf_viewer->setObjectName("elflist");
|
||||
|
||||
int table_mode = m_gui_settings->GetValue(gui::m_table_mode).toInt();
|
||||
int table_mode = Config::getTableMode();
|
||||
int slider_pos = 0;
|
||||
if (table_mode == 0) { // List
|
||||
m_game_grid_frame->hide();
|
||||
m_dock_widget->setWidget(m_game_list_frame);
|
||||
slider_pos = m_gui_settings->GetValue(gui::m_slide_pos).toInt();
|
||||
m_elf_viewer->hide();
|
||||
m_game_list_frame->show();
|
||||
m_dock_widget->setWidget(m_game_list_frame.data());
|
||||
slider_pos = Config::getSliderPositon();
|
||||
ui->sizeSlider->setSliderPosition(slider_pos); // set slider pos at start;
|
||||
isTableList = true;
|
||||
} else { // Grid
|
||||
} else if (table_mode == 1) { // Grid
|
||||
m_game_list_frame->hide();
|
||||
m_dock_widget->setWidget(m_game_grid_frame);
|
||||
slider_pos = m_gui_settings->GetValue(gui::m_slide_pos_grid).toInt();
|
||||
m_elf_viewer->hide();
|
||||
m_game_grid_frame->show();
|
||||
m_dock_widget->setWidget(m_game_grid_frame.data());
|
||||
slider_pos = Config::getSliderPositonGrid();
|
||||
ui->sizeSlider->setSliderPosition(slider_pos); // set slider pos at start;
|
||||
isTableList = false;
|
||||
} else {
|
||||
m_game_list_frame->hide();
|
||||
m_game_grid_frame->hide();
|
||||
m_elf_viewer->show();
|
||||
m_dock_widget->setWidget(m_elf_viewer.data());
|
||||
isTableList = false;
|
||||
}
|
||||
|
||||
m_main_window->addDockWidget(Qt::LeftDockWidgetArea, m_dock_widget);
|
||||
m_main_window->setDockNestingEnabled(true);
|
||||
m_dock_widget->setAllowedAreas(Qt::AllDockWidgetAreas);
|
||||
m_dock_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
m_dock_widget->resize(this->width(), this->height());
|
||||
addDockWidget(Qt::LeftDockWidgetArea, m_dock_widget.data());
|
||||
this->setDockNestingEnabled(true);
|
||||
|
||||
setCentralWidget(m_main_window);
|
||||
// handle resize like this for now, we deal with it when we add more docks
|
||||
connect(this, &MainWindow::WindowResized, this, [&]() {
|
||||
this->resizeDocks({m_dock_widget.data()}, {this->width()}, Qt::Orientation::Horizontal);
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::LoadGameLists() {
|
||||
// Get game info from game folders.
|
||||
m_game_info->GetGameInfo();
|
||||
m_game_info->GetGameInfo(this);
|
||||
if (isTableList) {
|
||||
m_game_list_frame->PopulateGameList();
|
||||
} else {
|
||||
|
@ -141,111 +158,150 @@ void MainWindow::LoadGameLists() {
|
|||
|
||||
void MainWindow::CreateConnects() {
|
||||
connect(this, &MainWindow::WindowResized, this, &MainWindow::HandleResize);
|
||||
|
||||
connect(ui->mw_searchbar, &QLineEdit::textChanged, this, &MainWindow::SearchGameTable);
|
||||
|
||||
connect(ui->exitAct, &QAction::triggered, this, &QWidget::close);
|
||||
|
||||
connect(ui->refreshGameListAct, &QAction::triggered, this, &MainWindow::RefreshGameTable);
|
||||
connect(this, &MainWindow::ExtractionFinished, this, &MainWindow::RefreshGameTable);
|
||||
|
||||
connect(ui->sizeSlider, &QSlider::valueChanged, this, [this](int value) {
|
||||
if (isTableList) {
|
||||
m_game_list_frame->icon_size =
|
||||
36 + value; // 36 is the minimum icon size to use due to text disappearing.
|
||||
m_game_list_frame->ResizeIcons(36 + value);
|
||||
m_gui_settings->SetValue(gui::m_icon_size, 36 + value);
|
||||
m_gui_settings->SetValue(gui::m_slide_pos, value);
|
||||
Config::setIconSize(36 + value);
|
||||
Config::setSliderPositon(value);
|
||||
} else {
|
||||
m_game_grid_frame->icon_size = 69 + value;
|
||||
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
|
||||
m_gui_settings->SetValue(gui::m_icon_size_grid, 69 + value);
|
||||
m_gui_settings->SetValue(gui::m_slide_pos_grid, value);
|
||||
Config::setIconSizeGrid(69 + value);
|
||||
Config::setSliderPositonGrid(value);
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->setIconSizeTinyAct, &QAction::triggered, this, [this](int value) {
|
||||
connect(ui->playButton, &QPushButton::clicked, this, [this]() {
|
||||
QString gamePath = "";
|
||||
int table_mode = Config::getTableMode();
|
||||
if (table_mode == 0) {
|
||||
if (m_game_list_frame->currentItem()) {
|
||||
int itemID = m_game_list_frame->currentItem()->row();
|
||||
gamePath = QString::fromStdString(m_game_info->m_games[itemID].path + "/eboot.bin");
|
||||
}
|
||||
} else if (table_mode == 1) {
|
||||
if (m_game_grid_frame->cellClicked) {
|
||||
int itemID = (m_game_grid_frame->crtRow * m_game_grid_frame->columnCnt) +
|
||||
m_game_grid_frame->crtColumn;
|
||||
gamePath = QString::fromStdString(m_game_info->m_games[itemID].path + "/eboot.bin");
|
||||
}
|
||||
} else {
|
||||
if (m_elf_viewer->currentItem()) {
|
||||
int itemID = m_elf_viewer->currentItem()->row();
|
||||
gamePath = QString::fromStdString(m_elf_viewer->m_elf_list[itemID].toStdString());
|
||||
}
|
||||
}
|
||||
if (gamePath != "") {
|
||||
AddRecentFiles(gamePath);
|
||||
Core::Emulator emulator;
|
||||
emulator.Run(gamePath.toUtf8().constData());
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->setIconSizeTinyAct, &QAction::triggered, this, [this]() {
|
||||
if (isTableList) {
|
||||
m_game_list_frame->icon_size =
|
||||
36; // 36 is the minimum icon size to use due to text disappearing.
|
||||
m_gui_settings->SetValue(gui::m_icon_size, 36);
|
||||
ui->sizeSlider->setValue(0); // icone_size - 36
|
||||
m_gui_settings->SetValue(gui::m_slide_pos, 0);
|
||||
Config::setIconSize(36);
|
||||
Config::setSliderPositon(0);
|
||||
} else {
|
||||
m_gui_settings->SetValue(gui::m_icon_size_grid, 69); // nice :3
|
||||
ui->sizeSlider->setValue(0); // icone_size - 36
|
||||
m_gui_settings->SetValue(gui::m_slide_pos_grid, 0);
|
||||
ui->sizeSlider->setValue(0); // icone_size - 36
|
||||
Config::setIconSizeGrid(69);
|
||||
Config::setSliderPositonGrid(0);
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->setIconSizeSmallAct, &QAction::triggered, this, [this](int value) {
|
||||
connect(ui->setIconSizeSmallAct, &QAction::triggered, this, [this]() {
|
||||
if (isTableList) {
|
||||
m_game_list_frame->icon_size = 64;
|
||||
m_gui_settings->SetValue(gui::m_icon_size, 64);
|
||||
ui->sizeSlider->setValue(28);
|
||||
m_gui_settings->SetValue(gui::m_slide_pos, 28);
|
||||
Config::setIconSize(64);
|
||||
Config::setSliderPositon(28);
|
||||
} else {
|
||||
m_gui_settings->SetValue(gui::m_icon_size_grid, 97);
|
||||
ui->sizeSlider->setValue(28);
|
||||
m_gui_settings->SetValue(gui::m_slide_pos_grid, 28);
|
||||
Config::setIconSizeGrid(97);
|
||||
Config::setSliderPositonGrid(28);
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->setIconSizeMediumAct, &QAction::triggered, this, [this](int value) {
|
||||
connect(ui->setIconSizeMediumAct, &QAction::triggered, this, [this]() {
|
||||
if (isTableList) {
|
||||
m_game_list_frame->icon_size = 128;
|
||||
m_gui_settings->SetValue(gui::m_icon_size, 128);
|
||||
ui->sizeSlider->setValue(92);
|
||||
m_gui_settings->SetValue(gui::m_slide_pos, 92);
|
||||
Config::setIconSize(128);
|
||||
Config::setSliderPositon(92);
|
||||
} else {
|
||||
m_gui_settings->SetValue(gui::m_icon_size_grid, 160);
|
||||
ui->sizeSlider->setValue(92);
|
||||
m_gui_settings->SetValue(gui::m_slide_pos_grid, 92);
|
||||
Config::setIconSizeGrid(160);
|
||||
Config::setSliderPositonGrid(91);
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->setIconSizeLargeAct, &QAction::triggered, this, [this](int value) {
|
||||
connect(ui->setIconSizeLargeAct, &QAction::triggered, this, [this]() {
|
||||
if (isTableList) {
|
||||
m_game_list_frame->icon_size = 256;
|
||||
m_gui_settings->SetValue(gui::m_icon_size, 256);
|
||||
ui->sizeSlider->setValue(220);
|
||||
m_gui_settings->SetValue(gui::m_slide_pos, 220);
|
||||
Config::setIconSize(256);
|
||||
Config::setSliderPositon(220);
|
||||
} else {
|
||||
m_gui_settings->SetValue(gui::m_icon_size_grid, 256);
|
||||
ui->sizeSlider->setValue(220);
|
||||
m_gui_settings->SetValue(gui::m_slide_pos_grid, 220);
|
||||
Config::setIconSizeGrid(256);
|
||||
Config::setSliderPositonGrid(220);
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->setlistModeListAct, &QAction::triggered, m_dock_widget, [this]() {
|
||||
m_dock_widget->setWidget(m_game_list_frame);
|
||||
m_game_list_frame->show();
|
||||
// List
|
||||
connect(ui->setlistModeListAct, &QAction::triggered, m_dock_widget.data(), [this]() {
|
||||
m_dock_widget->setWidget(m_game_list_frame.data());
|
||||
m_game_grid_frame->hide();
|
||||
m_elf_viewer->hide();
|
||||
m_game_list_frame->show();
|
||||
if (m_game_list_frame->item(0, 0) == nullptr) {
|
||||
m_game_list_frame->clearContents();
|
||||
m_game_list_frame->PopulateGameList();
|
||||
}
|
||||
isTableList = true;
|
||||
m_gui_settings->SetValue(gui::m_table_mode, 0); // save table mode
|
||||
int slider_pos = m_gui_settings->GetValue(gui::m_slide_pos).toInt();
|
||||
Config::setTableMode(0);
|
||||
int slider_pos = Config::getSliderPositon();
|
||||
ui->sizeSlider->setEnabled(true);
|
||||
ui->sizeSlider->setSliderPosition(slider_pos);
|
||||
});
|
||||
|
||||
connect(ui->setlistModeGridAct, &QAction::triggered, m_dock_widget, [this]() {
|
||||
m_dock_widget->setWidget(m_game_grid_frame);
|
||||
// Grid
|
||||
connect(ui->setlistModeGridAct, &QAction::triggered, m_dock_widget.data(), [this]() {
|
||||
m_dock_widget->setWidget(m_game_grid_frame.data());
|
||||
m_game_grid_frame->show();
|
||||
m_game_list_frame->hide();
|
||||
m_elf_viewer->hide();
|
||||
if (m_game_grid_frame->item(0, 0) == nullptr) {
|
||||
m_game_grid_frame->clearContents();
|
||||
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
|
||||
}
|
||||
isTableList = false;
|
||||
m_gui_settings->SetValue(gui::m_table_mode, 1); // save table mode
|
||||
int slider_pos_grid = m_gui_settings->GetValue(gui::m_slide_pos_grid).toInt();
|
||||
Config::setTableMode(1);
|
||||
int slider_pos_grid = Config::getSliderPositonGrid();
|
||||
ui->sizeSlider->setEnabled(true);
|
||||
ui->sizeSlider->setSliderPosition(slider_pos_grid);
|
||||
});
|
||||
// Elf
|
||||
connect(ui->setlistElfAct, &QAction::triggered, m_dock_widget.data(), [this]() {
|
||||
m_dock_widget->setWidget(m_elf_viewer.data());
|
||||
m_game_grid_frame->hide();
|
||||
m_game_list_frame->hide();
|
||||
m_elf_viewer->show();
|
||||
isTableList = false;
|
||||
ui->sizeSlider->setDisabled(true);
|
||||
Config::setTableMode(2);
|
||||
});
|
||||
|
||||
// Dump game list.
|
||||
connect(ui->dumpGameListAct, &QAction::triggered, this, [this] {
|
||||
connect(ui->dumpGameListAct, &QAction::triggered, this, [&] {
|
||||
QString filePath = qApp->applicationDirPath().append("/GameList.txt");
|
||||
QFile file(filePath);
|
||||
QTextStream out(&file);
|
||||
|
@ -270,21 +326,26 @@ void MainWindow::CreateConnects() {
|
|||
});
|
||||
|
||||
// Package install.
|
||||
connect(ui->bootInstallPkgAct, &QAction::triggered, this, [this] { InstallPkg(); });
|
||||
connect(ui->gameInstallPathAct, &QAction::triggered, this, [this] { InstallDirectory(); });
|
||||
connect(ui->bootInstallPkgAct, &QAction::triggered, this, &MainWindow::InstallPkg);
|
||||
connect(ui->gameInstallPathAct, &QAction::triggered, this, &MainWindow::InstallDirectory);
|
||||
|
||||
// elf viewer
|
||||
connect(ui->addElfFolderAct, &QAction::triggered, m_elf_viewer.data(),
|
||||
&ElfViewer::OpenElfFolder);
|
||||
|
||||
// Package Viewer.
|
||||
connect(ui->pkgViewerAct, &QAction::triggered, this, [this]() {
|
||||
PKGViewer* pkgViewer = new PKGViewer(m_game_info, m_gui_settings,
|
||||
[this](std::string file, int pkgNum, int nPkg) {
|
||||
this->InstallDragDropPkg(file, pkgNum, nPkg);
|
||||
});
|
||||
PKGViewer* pkgViewer = new PKGViewer(
|
||||
m_game_info, this, [this](std::filesystem::path file, int pkgNum, int nPkg) {
|
||||
this->InstallDragDropPkg(file, pkgNum, nPkg);
|
||||
});
|
||||
pkgViewer->show();
|
||||
});
|
||||
|
||||
// Themes
|
||||
connect(ui->setThemeLight, &QAction::triggered, &m_window_themes, [this]() {
|
||||
m_window_themes.SetWindowTheme(Theme::Light, ui->mw_searchbar);
|
||||
m_gui_settings->SetValue(gui::mw_themes, static_cast<int>(Theme::Light));
|
||||
Config::setMainWindowTheme(static_cast<int>(Theme::Light));
|
||||
if (!isIconBlack) {
|
||||
SetUiIcons(true);
|
||||
isIconBlack = true;
|
||||
|
@ -292,7 +353,7 @@ void MainWindow::CreateConnects() {
|
|||
});
|
||||
connect(ui->setThemeDark, &QAction::triggered, &m_window_themes, [this]() {
|
||||
m_window_themes.SetWindowTheme(Theme::Dark, ui->mw_searchbar);
|
||||
m_gui_settings->SetValue(gui::mw_themes, static_cast<int>(Theme::Dark));
|
||||
Config::setMainWindowTheme(static_cast<int>(Theme::Dark));
|
||||
if (isIconBlack) {
|
||||
SetUiIcons(false);
|
||||
isIconBlack = false;
|
||||
|
@ -300,7 +361,7 @@ void MainWindow::CreateConnects() {
|
|||
});
|
||||
connect(ui->setThemeGreen, &QAction::triggered, &m_window_themes, [this]() {
|
||||
m_window_themes.SetWindowTheme(Theme::Green, ui->mw_searchbar);
|
||||
m_gui_settings->SetValue(gui::mw_themes, static_cast<int>(Theme::Green));
|
||||
Config::setMainWindowTheme(static_cast<int>(Theme::Green));
|
||||
if (isIconBlack) {
|
||||
SetUiIcons(false);
|
||||
isIconBlack = false;
|
||||
|
@ -308,7 +369,7 @@ void MainWindow::CreateConnects() {
|
|||
});
|
||||
connect(ui->setThemeBlue, &QAction::triggered, &m_window_themes, [this]() {
|
||||
m_window_themes.SetWindowTheme(Theme::Blue, ui->mw_searchbar);
|
||||
m_gui_settings->SetValue(gui::mw_themes, static_cast<int>(Theme::Blue));
|
||||
Config::setMainWindowTheme(static_cast<int>(Theme::Blue));
|
||||
if (isIconBlack) {
|
||||
SetUiIcons(false);
|
||||
isIconBlack = false;
|
||||
|
@ -316,7 +377,7 @@ void MainWindow::CreateConnects() {
|
|||
});
|
||||
connect(ui->setThemeViolet, &QAction::triggered, &m_window_themes, [this]() {
|
||||
m_window_themes.SetWindowTheme(Theme::Violet, ui->mw_searchbar);
|
||||
m_gui_settings->SetValue(gui::mw_themes, static_cast<int>(Theme::Violet));
|
||||
Config::setMainWindowTheme(static_cast<int>(Theme::Violet));
|
||||
if (isIconBlack) {
|
||||
SetUiIcons(false);
|
||||
isIconBlack = false;
|
||||
|
@ -345,8 +406,8 @@ void MainWindow::SearchGameTable(const QString& text) {
|
|||
}
|
||||
|
||||
void MainWindow::RefreshGameTable() {
|
||||
m_game_info->m_games.clear();
|
||||
m_game_info->GetGameInfo();
|
||||
// m_game_info->m_games.clear();
|
||||
m_game_info->GetGameInfo(this);
|
||||
m_game_list_frame->clearContents();
|
||||
m_game_list_frame->PopulateGameList();
|
||||
m_game_grid_frame->clearContents();
|
||||
|
@ -358,16 +419,10 @@ void MainWindow::RefreshGameTable() {
|
|||
}
|
||||
|
||||
void MainWindow::ConfigureGuiFromSettings() {
|
||||
// Restore GUI state if needed. We need to if they exist.
|
||||
if (!restoreGeometry(m_gui_settings->GetValue(gui::main_window_geometry).toByteArray())) {
|
||||
resize(QGuiApplication::primaryScreen()->availableSize() * 0.7);
|
||||
}
|
||||
|
||||
m_main_window->restoreState(m_gui_settings->GetValue(gui::main_window_mwState).toByteArray());
|
||||
|
||||
ui->showGameListAct->setChecked(
|
||||
m_gui_settings->GetValue(gui::main_window_gamelist_visible).toBool());
|
||||
setGeometry(Config::getMainWindowGeometryX(), Config::getMainWindowGeometryY(),
|
||||
Config::getMainWindowGeometryW(), Config::getMainWindowGeometryH());
|
||||
|
||||
ui->showGameListAct->setChecked(true);
|
||||
if (isTableList) {
|
||||
ui->setlistModeListAct->setChecked(true);
|
||||
} else {
|
||||
|
@ -376,87 +431,155 @@ void MainWindow::ConfigureGuiFromSettings() {
|
|||
}
|
||||
|
||||
void MainWindow::SaveWindowState() const {
|
||||
// Save gui settings
|
||||
m_gui_settings->SetValue(gui::main_window_geometry, saveGeometry());
|
||||
m_gui_settings->SetValue(gui::main_window_windowState, saveState());
|
||||
m_gui_settings->SetValue(gui::m_window_size,
|
||||
QSize(m_main_window->width(), m_main_window->height()));
|
||||
m_gui_settings->SetValue(gui::main_window_mwState, m_main_window->saveState());
|
||||
Config::setMainWindowWidth(this->width());
|
||||
Config::setMainWindowHeight(this->height());
|
||||
Config::setMainWindowGeometry(this->geometry().x(), this->geometry().y(),
|
||||
this->geometry().width(), this->geometry().height());
|
||||
}
|
||||
|
||||
void MainWindow::InstallPkg() {
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(
|
||||
this, tr("Install PKG Files"), QDir::currentPath(), tr("PKG File (*.PKG)"));
|
||||
int nPkg = fileNames.size();
|
||||
int pkgNum = 0;
|
||||
for (const QString& file : fileNames) {
|
||||
pkgNum++;
|
||||
MainWindow::InstallDragDropPkg(file.toStdString(), pkgNum, nPkg);
|
||||
QFileDialog dialog;
|
||||
dialog.setFileMode(QFileDialog::ExistingFiles);
|
||||
dialog.setNameFilter(tr("PKG File (*.PKG)"));
|
||||
if (dialog.exec()) {
|
||||
QStringList fileNames = dialog.selectedFiles();
|
||||
int nPkg = fileNames.size();
|
||||
int pkgNum = 0;
|
||||
for (const QString& file : fileNames) {
|
||||
++pkgNum;
|
||||
std::filesystem::path path(file.toStdString());
|
||||
#ifdef _WIN64
|
||||
path = std::filesystem::path(file.toStdWString());
|
||||
#endif
|
||||
MainWindow::InstallDragDropPkg(path, pkgNum, nPkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::InstallDragDropPkg(std::string file, int pkgNum, int nPkg) {
|
||||
void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int nPkg) {
|
||||
if (Loader::DetectFileType(file) == Loader::FileTypes::Pkg) {
|
||||
PKG pkg;
|
||||
pkg = PKG();
|
||||
pkg.Open(file);
|
||||
std::string failreason;
|
||||
const auto extract_path =
|
||||
std::filesystem::path(
|
||||
m_gui_settings->GetValue(gui::settings_install_dir).toString().toStdString()) /
|
||||
pkg.GetTitleID();
|
||||
std::filesystem::path(Config::getGameInstallDir()) / pkg.GetTitleID();
|
||||
QString pkgType = QString::fromStdString(pkg.GetPkgFlags());
|
||||
QDir game_dir(QString::fromStdString(extract_path.string()));
|
||||
if (game_dir.exists()) {
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle("PKG Extraction");
|
||||
if (pkgType.contains("PATCH")) {
|
||||
psf.open("", pkg.sfo);
|
||||
QString pkg_app_version = QString::fromStdString(psf.GetString("APP_VER"));
|
||||
psf.open(extract_path.string() + "/sce_sys/param.sfo", {});
|
||||
QString game_app_version = QString::fromStdString(psf.GetString("APP_VER"));
|
||||
double appD = game_app_version.toDouble();
|
||||
double pkgD = pkg_app_version.toDouble();
|
||||
if (pkgD == appD) {
|
||||
msgBox.setText(
|
||||
QString("Patch detected!\nPKG and Game versions match!: %1\nWould you like "
|
||||
"to overwrite?")
|
||||
.arg(pkg_app_version));
|
||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
msgBox.setDefaultButton(QMessageBox::No);
|
||||
} else if (pkgD < appD) {
|
||||
QMessageBox::information(this, "PKG Extraction",
|
||||
QString("Patch detected!\nPKG Version %1 is older "
|
||||
"than installed version!: %2\nWould you like "
|
||||
"to overwrite?")
|
||||
.arg(pkg_app_version, game_app_version));
|
||||
return;
|
||||
} else {
|
||||
msgBox.setText(QString("Patch detected!\nGame is installed: %1\nWould you like "
|
||||
"to install Patch: %2?")
|
||||
.arg(game_app_version, pkg_app_version));
|
||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
msgBox.setDefaultButton(QMessageBox::No);
|
||||
}
|
||||
int result = msgBox.exec();
|
||||
if (result == QMessageBox::Yes) {
|
||||
// Do nothing.
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
msgBox.setText(QString("Game already installed\n%1\nWould you like to overwrite?")
|
||||
.arg(QString::fromStdString(extract_path.string())));
|
||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
msgBox.setDefaultButton(QMessageBox::No);
|
||||
int result = msgBox.exec();
|
||||
if (result == QMessageBox::Yes) {
|
||||
// Do nothing.
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Do nothing;
|
||||
if (pkgType.contains("PATCH")) {
|
||||
QMessageBox::information(this, "PKG Extraction",
|
||||
"PKG is a patch, please install the game first!");
|
||||
return;
|
||||
}
|
||||
// what else?
|
||||
}
|
||||
|
||||
if (!pkg.Extract(file, extract_path, failreason)) {
|
||||
QMessageBox::critical(this, "PKG ERROR", QString::fromStdString(failreason),
|
||||
QMessageBox::Ok);
|
||||
QMessageBox::critical(this, "PKG ERROR", QString::fromStdString(failreason));
|
||||
} else {
|
||||
int nfiles = pkg.GetNumberOfFiles();
|
||||
|
||||
QList<int> indices;
|
||||
QVector<int> indices;
|
||||
for (int i = 0; i < nfiles; i++) {
|
||||
indices.append(i);
|
||||
}
|
||||
|
||||
QProgressDialog dialog;
|
||||
dialog.setWindowTitle("PKG Extraction");
|
||||
dialog.setWindowModality(Qt::WindowModal);
|
||||
QString extractmsg = QString("Extracting PKG %1/%2").arg(pkgNum).arg(nPkg);
|
||||
dialog.setLabelText(extractmsg);
|
||||
dialog.setAutoClose(true);
|
||||
dialog.setRange(0, nfiles);
|
||||
|
||||
// Create a QFutureWatcher and connect signals and slots.
|
||||
QFutureWatcher<void> futureWatcher;
|
||||
QObject::connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset()));
|
||||
QObject::connect(&dialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel()));
|
||||
QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int, int)), &dialog,
|
||||
SLOT(setRange(int, int)));
|
||||
QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog,
|
||||
SLOT(setValue(int)));
|
||||
|
||||
futureWatcher.setFuture(QtConcurrent::map(
|
||||
indices, std::bind(&PKG::ExtractFiles, pkg, std::placeholders::_1)));
|
||||
|
||||
// Display the dialog and start the event loop.
|
||||
connect(&futureWatcher, &QFutureWatcher<void>::finished, this, [=, this]() {
|
||||
if (pkgNum == nPkg) {
|
||||
QString path = QString::fromStdString(Config::getGameInstallDir());
|
||||
QMessageBox extractMsgBox(this);
|
||||
extractMsgBox.setWindowTitle("Extraction Finished");
|
||||
extractMsgBox.setText(QString("Game successfully installed at %1").arg(path));
|
||||
extractMsgBox.addButton(QMessageBox::Ok);
|
||||
extractMsgBox.setDefaultButton(QMessageBox::Ok);
|
||||
connect(&extractMsgBox, &QMessageBox::buttonClicked, this,
|
||||
[&](QAbstractButton* button) {
|
||||
if (extractMsgBox.button(QMessageBox::Ok) == button) {
|
||||
extractMsgBox.close();
|
||||
emit ExtractionFinished();
|
||||
}
|
||||
});
|
||||
extractMsgBox.exec();
|
||||
}
|
||||
});
|
||||
connect(&dialog, &QProgressDialog::canceled, [&]() { futureWatcher.cancel(); });
|
||||
connect(&futureWatcher, &QFutureWatcher<void>::progressValueChanged, &dialog,
|
||||
&QProgressDialog::setValue);
|
||||
futureWatcher.setFuture(
|
||||
QtConcurrent::map(indices, [&](int index) { pkg.ExtractFiles(index); }));
|
||||
dialog.exec();
|
||||
futureWatcher.waitForFinished();
|
||||
|
||||
auto path = m_gui_settings->GetValue(gui::settings_install_dir).toString();
|
||||
if (pkgNum == nPkg) {
|
||||
QMessageBox::information(this, "Extraction Finished",
|
||||
"Game successfully installed at " + path, QMessageBox::Ok);
|
||||
// Refresh game table after extraction.
|
||||
RefreshGameTable();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QMessageBox::critical(this, "PKG ERROR", "File doesn't appear to be a valid PKG file",
|
||||
QMessageBox::Ok);
|
||||
QMessageBox::critical(this, "PKG ERROR", "File doesn't appear to be a valid PKG file");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::InstallDirectory() {
|
||||
GameInstallDialog dlg(m_gui_settings);
|
||||
GameInstallDialog dlg;
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
void MainWindow::SetLastUsedTheme() {
|
||||
Theme lastTheme = static_cast<Theme>(m_gui_settings->GetValue(gui::mw_themes).toInt());
|
||||
Theme lastTheme = static_cast<Theme>(Config::getMainWindowTheme());
|
||||
m_window_themes.SetWindowTheme(lastTheme, ui->mw_searchbar);
|
||||
|
||||
switch (lastTheme) {
|
||||
|
@ -489,7 +612,7 @@ void MainWindow::SetLastUsedTheme() {
|
|||
|
||||
void MainWindow::SetLastIconSizeBullet() {
|
||||
// set QAction bullet point if applicable
|
||||
int lastSize = m_gui_settings->GetValue(gui::m_icon_size).toInt();
|
||||
int lastSize = Config::getIconSize();
|
||||
switch (lastSize) {
|
||||
case 36:
|
||||
ui->setIconSizeTinyAct->setChecked(true);
|
||||
|
@ -507,47 +630,30 @@ void MainWindow::SetLastIconSizeBullet() {
|
|||
}
|
||||
|
||||
QIcon MainWindow::RecolorIcon(const QIcon& icon, bool isWhite) {
|
||||
QPixmap pixmap(icon.pixmap(icon.actualSize(QSize(120, 120)), QIcon::Normal));
|
||||
QPixmap pixmap(icon.pixmap(icon.actualSize(QSize(120, 120))));
|
||||
QColor clr(isWhite ? Qt::white : Qt::black);
|
||||
QBitmap mask = pixmap.createMaskFromColor(clr, Qt::MaskOutColor);
|
||||
pixmap.fill(QColor(isWhite ? Qt::black : Qt::white));
|
||||
pixmap.setMask(mask);
|
||||
QIcon newIcon(pixmap);
|
||||
return newIcon;
|
||||
return QIcon(pixmap);
|
||||
}
|
||||
|
||||
void MainWindow::SetUiIcons(bool isWhite) {
|
||||
QIcon icon;
|
||||
icon = RecolorIcon(ui->bootInstallPkgAct->icon(), isWhite);
|
||||
ui->bootInstallPkgAct->setIcon(icon);
|
||||
icon = RecolorIcon(ui->exitAct->icon(), isWhite);
|
||||
ui->exitAct->setIcon(icon);
|
||||
icon = RecolorIcon(ui->setlistModeListAct->icon(), isWhite);
|
||||
ui->setlistModeListAct->setIcon(icon);
|
||||
icon = RecolorIcon(ui->setlistModeGridAct->icon(), isWhite);
|
||||
ui->setlistModeGridAct->setIcon(icon);
|
||||
icon = RecolorIcon(ui->gameInstallPathAct->icon(), isWhite);
|
||||
ui->gameInstallPathAct->setIcon(icon);
|
||||
icon = RecolorIcon(ui->menuThemes->icon(), isWhite);
|
||||
ui->menuThemes->setIcon(icon);
|
||||
icon = RecolorIcon(ui->menuGame_List_Icons->icon(), isWhite);
|
||||
ui->menuGame_List_Icons->setIcon(icon);
|
||||
icon = RecolorIcon(ui->playButton->icon(), isWhite);
|
||||
ui->playButton->setIcon(icon);
|
||||
icon = RecolorIcon(ui->pauseButton->icon(), isWhite);
|
||||
ui->pauseButton->setIcon(icon);
|
||||
icon = RecolorIcon(ui->stopButton->icon(), isWhite);
|
||||
ui->stopButton->setIcon(icon);
|
||||
icon = RecolorIcon(ui->settingsButton->icon(), isWhite);
|
||||
ui->settingsButton->setIcon(icon);
|
||||
icon = RecolorIcon(ui->controllerButton->icon(), isWhite);
|
||||
ui->controllerButton->setIcon(icon);
|
||||
icon = RecolorIcon(ui->refreshGameListAct->icon(), isWhite);
|
||||
ui->refreshGameListAct->setIcon(icon);
|
||||
icon = RecolorIcon(ui->menuGame_List_Mode->icon(), isWhite);
|
||||
ui->menuGame_List_Mode->setIcon(icon);
|
||||
icon = RecolorIcon(ui->pkgViewerAct->icon(), isWhite);
|
||||
ui->pkgViewerAct->setIcon(icon);
|
||||
ui->bootInstallPkgAct->setIcon(RecolorIcon(ui->bootInstallPkgAct->icon(), isWhite));
|
||||
ui->exitAct->setIcon(RecolorIcon(ui->exitAct->icon(), isWhite));
|
||||
ui->setlistModeListAct->setIcon(RecolorIcon(ui->setlistModeListAct->icon(), isWhite));
|
||||
ui->setlistModeGridAct->setIcon(RecolorIcon(ui->setlistModeGridAct->icon(), isWhite));
|
||||
ui->gameInstallPathAct->setIcon(RecolorIcon(ui->gameInstallPathAct->icon(), isWhite));
|
||||
ui->menuThemes->setIcon(RecolorIcon(ui->menuThemes->icon(), isWhite));
|
||||
ui->menuGame_List_Icons->setIcon(RecolorIcon(ui->menuGame_List_Icons->icon(), isWhite));
|
||||
ui->playButton->setIcon(RecolorIcon(ui->playButton->icon(), isWhite));
|
||||
ui->pauseButton->setIcon(RecolorIcon(ui->pauseButton->icon(), isWhite));
|
||||
ui->stopButton->setIcon(RecolorIcon(ui->stopButton->icon(), isWhite));
|
||||
ui->settingsButton->setIcon(RecolorIcon(ui->settingsButton->icon(), isWhite));
|
||||
ui->controllerButton->setIcon(RecolorIcon(ui->controllerButton->icon(), isWhite));
|
||||
ui->refreshGameListAct->setIcon(RecolorIcon(ui->refreshGameListAct->icon(), isWhite));
|
||||
ui->menuGame_List_Mode->setIcon(RecolorIcon(ui->menuGame_List_Mode->icon(), isWhite));
|
||||
ui->pkgViewerAct->setIcon(RecolorIcon(ui->pkgViewerAct->icon(), isWhite));
|
||||
}
|
||||
|
||||
void MainWindow::resizeEvent(QResizeEvent* event) {
|
||||
|
@ -563,4 +669,44 @@ void MainWindow::HandleResize(QResizeEvent* event) {
|
|||
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
|
||||
m_game_grid_frame->RefreshGridBackgroundImage();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::AddRecentFiles(QString filePath) {
|
||||
std::vector<std::string> vec = Config::getRecentFiles();
|
||||
if (!vec.empty()) {
|
||||
if (filePath.toStdString() == vec.at(0)) {
|
||||
return;
|
||||
}
|
||||
auto it = std::find(vec.begin(), vec.end(), filePath.toStdString());
|
||||
if (it != vec.end()) {
|
||||
vec.erase(it);
|
||||
}
|
||||
}
|
||||
vec.insert(vec.begin(), filePath.toStdString());
|
||||
if (vec.size() > 6) {
|
||||
vec.pop_back();
|
||||
}
|
||||
Config::setRecentFiles(vec);
|
||||
const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
|
||||
Config::save(config_dir / "config.toml");
|
||||
CreateRecentGameActions(); // Refresh the QActions.
|
||||
}
|
||||
|
||||
void MainWindow::CreateRecentGameActions() {
|
||||
m_recent_files_group = new QActionGroup(this);
|
||||
ui->menuRecent->clear();
|
||||
std::vector<std::string> vec = Config::getRecentFiles();
|
||||
for (int i = 0; i < vec.size(); i++) {
|
||||
QAction* recentFileAct = new QAction(this);
|
||||
recentFileAct->setText(QString::fromStdString(vec.at(i)));
|
||||
ui->menuRecent->addAction(recentFileAct);
|
||||
m_recent_files_group->addAction(recentFileAct);
|
||||
}
|
||||
|
||||
connect(m_recent_files_group, &QActionGroup::triggered, this, [this](QAction* action) {
|
||||
QString gamePath = action->text();
|
||||
AddRecentFiles(gamePath); // Update the list.
|
||||
Core::Emulator emulator;
|
||||
emulator.Run(gamePath.toUtf8().constData());
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue