mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-13 05:05:57 +00:00
* Fix #2613: Game icon size not working properly on grid view When you select grid view mode and try to change the game icon size, the icons change to the wrong size, or don't change at all. To solve this I added a line to call the function that populates the game grid with the games when the user changes the icon size. That way the size of the icons is updated to match the size selected by the user, which is the intended behaviour. I also added code to update the check on the size when changing view mode. * Fix #2613: fixed clang format issue
1242 lines
47 KiB
C++
1242 lines
47 KiB
C++
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include "SDL3/SDL_events.h"
|
|
|
|
#include <QDockWidget>
|
|
#include <QKeyEvent>
|
|
#include <QPlainTextEdit>
|
|
#include <QProgressDialog>
|
|
#include <QStatusBar>
|
|
|
|
#include "about_dialog.h"
|
|
#include "cheats_patches.h"
|
|
#ifdef ENABLE_UPDATER
|
|
#include "check_update.h"
|
|
#endif
|
|
#include "common/io_file.h"
|
|
#include "common/path_util.h"
|
|
#include "common/scm_rev.h"
|
|
#include "common/string_util.h"
|
|
#include "control_settings.h"
|
|
#include "game_install_dialog.h"
|
|
#include "kbm_gui.h"
|
|
#include "main_window.h"
|
|
#include "settings_dialog.h"
|
|
|
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
|
#ifdef ENABLE_DISCORD_RPC
|
|
#include "common/discord_rpc_handler.h"
|
|
#endif
|
|
|
|
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
|
|
ui->setupUi(this);
|
|
installEventFilter(this);
|
|
setAttribute(Qt::WA_DeleteOnClose);
|
|
}
|
|
|
|
MainWindow::~MainWindow() {
|
|
SaveWindowState();
|
|
const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
|
|
Config::saveMainWindow(config_dir / "config.toml");
|
|
}
|
|
|
|
bool MainWindow::Init() {
|
|
auto start = std::chrono::steady_clock::now();
|
|
// setup ui
|
|
LoadTranslation();
|
|
AddUiWidgets();
|
|
CreateActions();
|
|
CreateRecentGameActions();
|
|
ConfigureGuiFromSettings();
|
|
CreateDockWindows();
|
|
CreateConnects();
|
|
SetLastUsedTheme();
|
|
SetLastIconSizeBullet();
|
|
GetPhysicalDevices();
|
|
// show ui
|
|
setMinimumSize(720, 405);
|
|
std::string window_title = "";
|
|
if (Common::g_is_release) {
|
|
window_title = fmt::format("shadPS4 v{}", Common::g_version);
|
|
} else {
|
|
std::string remote_url(Common::g_scm_remote_url);
|
|
std::string remote_host;
|
|
try {
|
|
remote_host = remote_url.substr(19, remote_url.rfind('/') - 19);
|
|
} catch (...) {
|
|
remote_host = "unknown";
|
|
}
|
|
if (remote_host == "shadps4-emu" || remote_url.length() == 0) {
|
|
window_title = fmt::format("shadPS4 v{} {} {}", Common::g_version, Common::g_scm_branch,
|
|
Common::g_scm_desc);
|
|
} else {
|
|
window_title = fmt::format("shadPS4 v{} {}/{} {}", Common::g_version, remote_host,
|
|
Common::g_scm_branch, Common::g_scm_desc);
|
|
}
|
|
}
|
|
setWindowTitle(QString::fromStdString(window_title));
|
|
this->show();
|
|
// load game list
|
|
LoadGameLists();
|
|
#ifdef ENABLE_UPDATER
|
|
// Check for update
|
|
CheckUpdateMain(true);
|
|
#endif
|
|
|
|
auto end = std::chrono::steady_clock::now();
|
|
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
|
statusBar.reset(new QStatusBar);
|
|
this->setStatusBar(statusBar.data());
|
|
// Update status bar
|
|
int numGames = m_game_info->m_games.size();
|
|
QString statusMessage = tr("Games: ") + QString::number(numGames) + " (" +
|
|
QString::number(duration.count()) + "ms)";
|
|
statusBar->showMessage(statusMessage);
|
|
|
|
#ifdef ENABLE_DISCORD_RPC
|
|
if (Config::getEnableDiscordRPC()) {
|
|
auto* rpc = Common::Singleton<DiscordRPCHandler::RPC>::Instance();
|
|
rpc->init();
|
|
rpc->setStatusIdling();
|
|
}
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
void MainWindow::CreateActions() {
|
|
// create action group for icon size
|
|
m_icon_size_act_group = new QActionGroup(this);
|
|
m_icon_size_act_group->addAction(ui->setIconSizeTinyAct);
|
|
m_icon_size_act_group->addAction(ui->setIconSizeSmallAct);
|
|
m_icon_size_act_group->addAction(ui->setIconSizeMediumAct);
|
|
m_icon_size_act_group->addAction(ui->setIconSizeLargeAct);
|
|
|
|
// create action group for list mode
|
|
m_list_mode_act_group = new QActionGroup(this);
|
|
m_list_mode_act_group->addAction(ui->setlistModeListAct);
|
|
m_list_mode_act_group->addAction(ui->setlistModeGridAct);
|
|
m_list_mode_act_group->addAction(ui->setlistElfAct);
|
|
|
|
// create action group for themes
|
|
m_theme_act_group = new QActionGroup(this);
|
|
m_theme_act_group->addAction(ui->setThemeDark);
|
|
m_theme_act_group->addAction(ui->setThemeLight);
|
|
m_theme_act_group->addAction(ui->setThemeGreen);
|
|
m_theme_act_group->addAction(ui->setThemeBlue);
|
|
m_theme_act_group->addAction(ui->setThemeViolet);
|
|
m_theme_act_group->addAction(ui->setThemeGruvbox);
|
|
m_theme_act_group->addAction(ui->setThemeTokyoNight);
|
|
m_theme_act_group->addAction(ui->setThemeOled);
|
|
}
|
|
|
|
void MainWindow::PauseGame() {
|
|
SDL_Event event;
|
|
SDL_memset(&event, 0, sizeof(event));
|
|
event.type = SDL_EVENT_TOGGLE_PAUSE;
|
|
is_paused = !is_paused;
|
|
UpdateToolbarButtons();
|
|
SDL_PushEvent(&event);
|
|
}
|
|
|
|
void MainWindow::toggleLabelsUnderIcons() {
|
|
bool showLabels = ui->toggleLabelsAct->isChecked();
|
|
Config::setShowLabelsUnderIcons();
|
|
UpdateToolbarLabels();
|
|
if (isGameRunning) {
|
|
UpdateToolbarButtons();
|
|
}
|
|
}
|
|
|
|
void MainWindow::toggleFullscreen() {
|
|
SDL_Event event;
|
|
SDL_memset(&event, 0, sizeof(event));
|
|
event.type = SDL_EVENT_TOGGLE_FULLSCREEN;
|
|
SDL_PushEvent(&event);
|
|
}
|
|
|
|
QWidget* MainWindow::createButtonWithLabel(QPushButton* button, const QString& labelText,
|
|
bool showLabel) {
|
|
QWidget* container = new QWidget(this);
|
|
QVBoxLayout* layout = new QVBoxLayout(container);
|
|
layout->setAlignment(Qt::AlignCenter | Qt::AlignBottom);
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
|
layout->addWidget(button);
|
|
|
|
QLabel* label = nullptr;
|
|
if (showLabel && ui->toggleLabelsAct->isChecked()) {
|
|
label = new QLabel(labelText, this);
|
|
label->setAlignment(Qt::AlignCenter | Qt::AlignBottom);
|
|
layout->addWidget(label);
|
|
button->setToolTip("");
|
|
} else {
|
|
button->setToolTip(labelText);
|
|
}
|
|
|
|
container->setLayout(layout);
|
|
container->setProperty("buttonLabel", QVariant::fromValue(label));
|
|
return container;
|
|
}
|
|
|
|
QWidget* createSpacer(QWidget* parent) {
|
|
QWidget* spacer = new QWidget(parent);
|
|
spacer->setFixedWidth(15);
|
|
spacer->setFixedHeight(15);
|
|
return spacer;
|
|
}
|
|
|
|
void MainWindow::AddUiWidgets() {
|
|
// add toolbar widgets
|
|
QApplication::setStyle("Fusion");
|
|
|
|
bool showLabels = ui->toggleLabelsAct->isChecked();
|
|
ui->toolBar->clear();
|
|
|
|
ui->toolBar->addWidget(createSpacer(this));
|
|
ui->toolBar->addWidget(createButtonWithLabel(ui->playButton, tr("Play"), showLabels));
|
|
ui->toolBar->addWidget(createButtonWithLabel(ui->pauseButton, tr("Pause"), showLabels));
|
|
ui->toolBar->addWidget(createButtonWithLabel(ui->stopButton, tr("Stop"), showLabels));
|
|
ui->toolBar->addWidget(createButtonWithLabel(ui->restartButton, tr("Restart"), showLabels));
|
|
ui->toolBar->addWidget(createSpacer(this));
|
|
ui->toolBar->addWidget(createButtonWithLabel(ui->settingsButton, tr("Settings"), showLabels));
|
|
ui->toolBar->addWidget(
|
|
createButtonWithLabel(ui->fullscreenButton, tr("Full Screen"), showLabels));
|
|
ui->toolBar->addWidget(createSpacer(this));
|
|
ui->toolBar->addWidget(
|
|
createButtonWithLabel(ui->controllerButton, tr("Controllers"), showLabels));
|
|
ui->toolBar->addWidget(createButtonWithLabel(ui->keyboardButton, tr("Keyboard"), showLabels));
|
|
ui->toolBar->addWidget(createSpacer(this));
|
|
QFrame* line = new QFrame(this);
|
|
line->setFrameShape(QFrame::VLine);
|
|
line->setFrameShadow(QFrame::Sunken);
|
|
line->setMinimumWidth(2);
|
|
ui->toolBar->addWidget(line);
|
|
ui->toolBar->addWidget(createSpacer(this));
|
|
if (showLabels) {
|
|
QLabel* pauseButtonLabel = ui->pauseButton->parentWidget()->findChild<QLabel*>();
|
|
if (pauseButtonLabel) {
|
|
pauseButtonLabel->setVisible(false);
|
|
}
|
|
}
|
|
ui->toolBar->addWidget(
|
|
createButtonWithLabel(ui->refreshButton, tr("Refresh List"), showLabels));
|
|
ui->toolBar->addWidget(createSpacer(this));
|
|
|
|
QBoxLayout* toolbarLayout = new QBoxLayout(QBoxLayout::TopToBottom);
|
|
toolbarLayout->setSpacing(2);
|
|
toolbarLayout->setContentsMargins(2, 2, 2, 2);
|
|
ui->sizeSliderContainer->setFixedWidth(150);
|
|
|
|
QWidget* searchSliderContainer = new QWidget(this);
|
|
QBoxLayout* searchSliderLayout = new QBoxLayout(QBoxLayout::TopToBottom);
|
|
searchSliderLayout->setContentsMargins(0, 0, 6, 6);
|
|
searchSliderLayout->setSpacing(2);
|
|
ui->mw_searchbar->setFixedWidth(150);
|
|
|
|
searchSliderLayout->addWidget(ui->sizeSliderContainer);
|
|
searchSliderLayout->addWidget(ui->mw_searchbar);
|
|
|
|
searchSliderContainer->setLayout(searchSliderLayout);
|
|
|
|
ui->toolBar->addWidget(searchSliderContainer);
|
|
|
|
if (!showLabels) {
|
|
toolbarLayout->addWidget(searchSliderContainer);
|
|
}
|
|
|
|
ui->playButton->setVisible(true);
|
|
ui->pauseButton->setVisible(false);
|
|
}
|
|
|
|
void MainWindow::UpdateToolbarButtons() {
|
|
// add toolbar widgets when game is running
|
|
bool showLabels = ui->toggleLabelsAct->isChecked();
|
|
|
|
ui->playButton->setVisible(false);
|
|
ui->pauseButton->setVisible(true);
|
|
|
|
if (showLabels) {
|
|
QLabel* playButtonLabel = ui->playButton->parentWidget()->findChild<QLabel*>();
|
|
if (playButtonLabel)
|
|
playButtonLabel->setVisible(false);
|
|
}
|
|
|
|
if (is_paused) {
|
|
ui->pauseButton->setIcon(ui->playButton->icon());
|
|
ui->pauseButton->setToolTip(tr("Resume"));
|
|
} else {
|
|
if (isIconBlack) {
|
|
ui->pauseButton->setIcon(QIcon(":images/pause_icon.png"));
|
|
} else {
|
|
ui->pauseButton->setIcon(RecolorIcon(QIcon(":images/pause_icon.png"), isWhite));
|
|
}
|
|
ui->pauseButton->setToolTip(tr("Pause"));
|
|
}
|
|
|
|
if (showLabels) {
|
|
QLabel* pauseButtonLabel = ui->pauseButton->parentWidget()->findChild<QLabel*>();
|
|
if (pauseButtonLabel) {
|
|
pauseButtonLabel->setText(is_paused ? tr("Resume") : tr("Pause"));
|
|
pauseButtonLabel->setVisible(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::UpdateToolbarLabels() {
|
|
AddUiWidgets();
|
|
}
|
|
|
|
void MainWindow::CreateDockWindows() {
|
|
// place holder widget is needed for good health they say :)
|
|
QWidget* phCentralWidget = new QWidget(this);
|
|
setCentralWidget(phCentralWidget);
|
|
|
|
m_dock_widget.reset(new QDockWidget(tr("Game List"), this));
|
|
m_game_list_frame.reset(new GameListFrame(m_game_info, m_compat_info, this));
|
|
m_game_list_frame->setObjectName("gamelist");
|
|
m_game_grid_frame.reset(new GameGridFrame(m_game_info, m_compat_info, this));
|
|
m_game_grid_frame->setObjectName("gamegridlist");
|
|
m_elf_viewer.reset(new ElfViewer(this));
|
|
m_elf_viewer->setObjectName("elflist");
|
|
|
|
int table_mode = Config::getTableMode();
|
|
int slider_pos = 0;
|
|
if (table_mode == 0) { // List
|
|
m_game_grid_frame->hide();
|
|
m_elf_viewer->hide();
|
|
m_game_list_frame->show();
|
|
m_dock_widget->setWidget(m_game_list_frame.data());
|
|
slider_pos = Config::getSliderPosition();
|
|
ui->sizeSlider->setSliderPosition(slider_pos); // set slider pos at start;
|
|
isTableList = true;
|
|
} else if (table_mode == 1) { // Grid
|
|
m_game_list_frame->hide();
|
|
m_elf_viewer->hide();
|
|
m_game_grid_frame->show();
|
|
m_dock_widget->setWidget(m_game_grid_frame.data());
|
|
slider_pos = Config::getSliderPositionGrid();
|
|
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_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);
|
|
|
|
// 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() {
|
|
// Load compatibility database
|
|
if (Config::getCompatibilityEnabled())
|
|
m_compat_info->LoadCompatibilityFile();
|
|
|
|
// Update compatibility database
|
|
if (Config::getCheckCompatibilityOnStartup())
|
|
m_compat_info->UpdateCompatibilityDatabase(this);
|
|
|
|
// Get game info from game folders.
|
|
m_game_info->GetGameInfo(this);
|
|
if (isTableList) {
|
|
m_game_list_frame->PopulateGameList();
|
|
} else {
|
|
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
|
|
}
|
|
}
|
|
|
|
#ifdef ENABLE_UPDATER
|
|
void MainWindow::CheckUpdateMain(bool checkSave) {
|
|
if (checkSave) {
|
|
if (!Config::autoUpdate()) {
|
|
return;
|
|
}
|
|
}
|
|
auto checkUpdate = new CheckUpdate(false);
|
|
checkUpdate->exec();
|
|
}
|
|
#endif
|
|
|
|
void MainWindow::GetPhysicalDevices() {
|
|
Vulkan::Instance instance(false, false);
|
|
auto physical_devices = instance.GetPhysicalDevices();
|
|
for (const vk::PhysicalDevice physical_device : physical_devices) {
|
|
auto prop = physical_device.getProperties();
|
|
QString name = QString::fromUtf8(prop.deviceName, -1);
|
|
if (prop.apiVersion < Vulkan::TargetVulkanApiVersion) {
|
|
name += tr(" * Unsupported Vulkan Version");
|
|
}
|
|
m_physical_devices.push_back(name);
|
|
}
|
|
}
|
|
|
|
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(ui->refreshButton, &QPushButton::clicked, this, &MainWindow::RefreshGameTable);
|
|
connect(ui->showGameListAct, &QAction::triggered, this, &MainWindow::ShowGameList);
|
|
connect(this, &MainWindow::ExtractionFinished, this, &MainWindow::RefreshGameTable);
|
|
connect(ui->toggleLabelsAct, &QAction::toggled, this, &MainWindow::toggleLabelsUnderIcons);
|
|
connect(ui->fullscreenButton, &QPushButton::clicked, this, &MainWindow::toggleFullscreen);
|
|
|
|
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);
|
|
Config::setIconSize(36 + value);
|
|
Config::setSliderPosition(value);
|
|
} else {
|
|
m_game_grid_frame->icon_size = 69 + value;
|
|
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
|
|
Config::setIconSizeGrid(69 + value);
|
|
Config::setSliderPositionGrid(value);
|
|
}
|
|
});
|
|
|
|
connect(ui->shadFolderAct, &QAction::triggered, this, [this]() {
|
|
QString userPath;
|
|
Common::FS::PathToQString(userPath, Common::FS::GetUserPath(Common::FS::PathType::UserDir));
|
|
QDesktopServices::openUrl(QUrl::fromLocalFile(userPath));
|
|
});
|
|
|
|
connect(ui->playButton, &QPushButton::clicked, this, &MainWindow::StartGame);
|
|
connect(ui->pauseButton, &QPushButton::clicked, this, &MainWindow::PauseGame);
|
|
connect(m_game_grid_frame.get(), &QTableWidget::cellDoubleClicked, this,
|
|
&MainWindow::StartGame);
|
|
connect(m_game_list_frame.get(), &QTableWidget::cellDoubleClicked, this,
|
|
&MainWindow::StartGame);
|
|
|
|
connect(ui->configureAct, &QAction::triggered, this, [this]() {
|
|
auto settingsDialog = new SettingsDialog(m_physical_devices, m_compat_info, this);
|
|
|
|
connect(settingsDialog, &SettingsDialog::LanguageChanged, this,
|
|
&MainWindow::OnLanguageChanged);
|
|
|
|
connect(settingsDialog, &SettingsDialog::CompatibilityChanged, this,
|
|
&MainWindow::RefreshGameTable);
|
|
|
|
connect(settingsDialog, &SettingsDialog::accepted, this, &MainWindow::RefreshGameTable);
|
|
connect(settingsDialog, &SettingsDialog::rejected, this, &MainWindow::RefreshGameTable);
|
|
connect(settingsDialog, &SettingsDialog::close, this, &MainWindow::RefreshGameTable);
|
|
|
|
connect(settingsDialog, &SettingsDialog::BackgroundOpacityChanged, this,
|
|
[this](int opacity) {
|
|
Config::setBackgroundImageOpacity(opacity);
|
|
if (m_game_list_frame) {
|
|
QTableWidgetItem* current = m_game_list_frame->GetCurrentItem();
|
|
if (current) {
|
|
m_game_list_frame->SetListBackgroundImage(current);
|
|
}
|
|
}
|
|
if (m_game_grid_frame) {
|
|
if (m_game_grid_frame->IsValidCellSelected()) {
|
|
m_game_grid_frame->SetGridBackgroundImage(m_game_grid_frame->crtRow,
|
|
m_game_grid_frame->crtColumn);
|
|
}
|
|
}
|
|
});
|
|
|
|
settingsDialog->exec();
|
|
});
|
|
|
|
connect(ui->settingsButton, &QPushButton::clicked, this, [this]() {
|
|
auto settingsDialog = new SettingsDialog(m_physical_devices, m_compat_info, this);
|
|
|
|
connect(settingsDialog, &SettingsDialog::LanguageChanged, this,
|
|
&MainWindow::OnLanguageChanged);
|
|
|
|
connect(settingsDialog, &SettingsDialog::CompatibilityChanged, this,
|
|
&MainWindow::RefreshGameTable);
|
|
|
|
connect(settingsDialog, &SettingsDialog::accepted, this, &MainWindow::RefreshGameTable);
|
|
connect(settingsDialog, &SettingsDialog::rejected, this, &MainWindow::RefreshGameTable);
|
|
connect(settingsDialog, &SettingsDialog::close, this, &MainWindow::RefreshGameTable);
|
|
|
|
connect(settingsDialog, &SettingsDialog::BackgroundOpacityChanged, this,
|
|
[this](int opacity) {
|
|
Config::setBackgroundImageOpacity(opacity);
|
|
if (m_game_list_frame) {
|
|
QTableWidgetItem* current = m_game_list_frame->GetCurrentItem();
|
|
if (current) {
|
|
m_game_list_frame->SetListBackgroundImage(current);
|
|
}
|
|
}
|
|
if (m_game_grid_frame) {
|
|
if (m_game_grid_frame->IsValidCellSelected()) {
|
|
m_game_grid_frame->SetGridBackgroundImage(m_game_grid_frame->crtRow,
|
|
m_game_grid_frame->crtColumn);
|
|
}
|
|
}
|
|
});
|
|
|
|
settingsDialog->exec();
|
|
});
|
|
|
|
connect(ui->controllerButton, &QPushButton::clicked, this, [this]() {
|
|
auto configWindow = new ControlSettings(m_game_info, this);
|
|
configWindow->exec();
|
|
});
|
|
|
|
connect(ui->keyboardButton, &QPushButton::clicked, this, [this]() {
|
|
auto kbmWindow = new KBMSettings(m_game_info, this);
|
|
kbmWindow->exec();
|
|
});
|
|
|
|
#ifdef ENABLE_UPDATER
|
|
connect(ui->updaterAct, &QAction::triggered, this, [this]() {
|
|
auto checkUpdate = new CheckUpdate(true);
|
|
checkUpdate->exec();
|
|
});
|
|
#endif
|
|
|
|
connect(ui->aboutAct, &QAction::triggered, this, [this]() {
|
|
auto aboutDialog = new AboutDialog(this);
|
|
aboutDialog->exec();
|
|
});
|
|
|
|
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.
|
|
ui->sizeSlider->setValue(0); // icone_size - 36
|
|
Config::setIconSize(36);
|
|
Config::setSliderPosition(0);
|
|
} else {
|
|
m_game_grid_frame->icon_size = 69;
|
|
ui->sizeSlider->setValue(0); // icone_size - 36
|
|
Config::setIconSizeGrid(69);
|
|
Config::setSliderPositionGrid(0);
|
|
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
|
|
}
|
|
});
|
|
|
|
connect(ui->setIconSizeSmallAct, &QAction::triggered, this, [this]() {
|
|
if (isTableList) {
|
|
m_game_list_frame->icon_size = 64;
|
|
ui->sizeSlider->setValue(28);
|
|
Config::setIconSize(64);
|
|
Config::setSliderPosition(28);
|
|
} else {
|
|
m_game_grid_frame->icon_size = 97;
|
|
ui->sizeSlider->setValue(28);
|
|
Config::setIconSizeGrid(97);
|
|
Config::setSliderPositionGrid(28);
|
|
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
|
|
}
|
|
});
|
|
|
|
connect(ui->setIconSizeMediumAct, &QAction::triggered, this, [this]() {
|
|
if (isTableList) {
|
|
m_game_list_frame->icon_size = 128;
|
|
ui->sizeSlider->setValue(92);
|
|
Config::setIconSize(128);
|
|
Config::setSliderPosition(92);
|
|
} else {
|
|
m_game_grid_frame->icon_size = 161;
|
|
ui->sizeSlider->setValue(92);
|
|
Config::setIconSizeGrid(161);
|
|
Config::setSliderPositionGrid(92);
|
|
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
|
|
}
|
|
});
|
|
|
|
connect(ui->setIconSizeLargeAct, &QAction::triggered, this, [this]() {
|
|
if (isTableList) {
|
|
m_game_list_frame->icon_size = 256;
|
|
ui->sizeSlider->setValue(220);
|
|
Config::setIconSize(256);
|
|
Config::setSliderPosition(220);
|
|
} else {
|
|
m_game_grid_frame->icon_size = 256;
|
|
ui->sizeSlider->setValue(220);
|
|
Config::setIconSizeGrid(256);
|
|
Config::setSliderPositionGrid(220);
|
|
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
|
|
}
|
|
});
|
|
// List
|
|
connect(ui->setlistModeListAct, &QAction::triggered, m_dock_widget.data(), [this]() {
|
|
BackgroundMusicPlayer::getInstance().stopMusic();
|
|
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;
|
|
Config::setTableMode(0);
|
|
int slider_pos = Config::getSliderPosition();
|
|
ui->sizeSlider->setEnabled(true);
|
|
ui->sizeSlider->setSliderPosition(slider_pos);
|
|
ui->mw_searchbar->setText("");
|
|
SetLastIconSizeBullet();
|
|
});
|
|
// Grid
|
|
connect(ui->setlistModeGridAct, &QAction::triggered, m_dock_widget.data(), [this]() {
|
|
BackgroundMusicPlayer::getInstance().stopMusic();
|
|
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;
|
|
Config::setTableMode(1);
|
|
int slider_pos_grid = Config::getSliderPositionGrid();
|
|
ui->sizeSlider->setEnabled(true);
|
|
ui->sizeSlider->setSliderPosition(slider_pos_grid);
|
|
ui->mw_searchbar->setText("");
|
|
SetLastIconSizeBullet();
|
|
});
|
|
// Elf Viewer
|
|
connect(ui->setlistElfAct, &QAction::triggered, m_dock_widget.data(), [this]() {
|
|
BackgroundMusicPlayer::getInstance().stopMusic();
|
|
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);
|
|
SetLastIconSizeBullet();
|
|
});
|
|
|
|
// Cheats/Patches Download.
|
|
connect(ui->downloadCheatsPatchesAct, &QAction::triggered, this, [this]() {
|
|
QDialog* panelDialog = new QDialog(this);
|
|
QVBoxLayout* layout = new QVBoxLayout(panelDialog);
|
|
QPushButton* downloadAllCheatsButton =
|
|
new QPushButton(tr("Download Cheats For All Installed Games"), panelDialog);
|
|
QPushButton* downloadAllPatchesButton =
|
|
new QPushButton(tr("Download Patches For All Games"), panelDialog);
|
|
|
|
layout->addWidget(downloadAllCheatsButton);
|
|
layout->addWidget(downloadAllPatchesButton);
|
|
|
|
panelDialog->setLayout(layout);
|
|
|
|
connect(downloadAllCheatsButton, &QPushButton::clicked, this, [this, panelDialog]() {
|
|
QEventLoop eventLoop;
|
|
int pendingDownloads = 0;
|
|
|
|
auto onDownloadFinished = [&]() {
|
|
if (--pendingDownloads <= 0) {
|
|
eventLoop.quit();
|
|
}
|
|
};
|
|
|
|
for (const GameInfo& game : m_game_info->m_games) {
|
|
QString empty = "";
|
|
QString gameSerial = QString::fromStdString(game.serial);
|
|
QString gameVersion = QString::fromStdString(game.version);
|
|
|
|
CheatsPatches* cheatsPatches =
|
|
new CheatsPatches(empty, empty, empty, empty, empty, nullptr);
|
|
connect(cheatsPatches, &CheatsPatches::downloadFinished, onDownloadFinished);
|
|
|
|
pendingDownloads += 3;
|
|
|
|
cheatsPatches->downloadCheats("wolf2022", gameSerial, gameVersion, false);
|
|
cheatsPatches->downloadCheats("GoldHEN", gameSerial, gameVersion, false);
|
|
cheatsPatches->downloadCheats("shadPS4", gameSerial, gameVersion, false);
|
|
}
|
|
eventLoop.exec();
|
|
|
|
QMessageBox::information(
|
|
nullptr, tr("Download Complete"),
|
|
tr("You have downloaded cheats for all the games you have installed."));
|
|
|
|
panelDialog->accept();
|
|
});
|
|
connect(downloadAllPatchesButton, &QPushButton::clicked, [panelDialog]() {
|
|
QEventLoop eventLoop;
|
|
int pendingDownloads = 0;
|
|
|
|
auto onDownloadFinished = [&]() {
|
|
if (--pendingDownloads <= 0) {
|
|
eventLoop.quit();
|
|
}
|
|
};
|
|
|
|
QString empty = "";
|
|
CheatsPatches* cheatsPatches =
|
|
new CheatsPatches(empty, empty, empty, empty, empty, nullptr);
|
|
connect(cheatsPatches, &CheatsPatches::downloadFinished, onDownloadFinished);
|
|
|
|
pendingDownloads += 2;
|
|
|
|
cheatsPatches->downloadPatches("GoldHEN", false);
|
|
cheatsPatches->downloadPatches("shadPS4", false);
|
|
|
|
eventLoop.exec();
|
|
QMessageBox::information(
|
|
nullptr, tr("Download Complete"),
|
|
QString(tr("Patches Downloaded Successfully!") + "\n" +
|
|
tr("All Patches available for all games have been downloaded.")));
|
|
cheatsPatches->createFilesJson("GoldHEN");
|
|
cheatsPatches->createFilesJson("shadPS4");
|
|
panelDialog->accept();
|
|
});
|
|
panelDialog->exec();
|
|
});
|
|
|
|
// Dump game list.
|
|
connect(ui->dumpGameListAct, &QAction::triggered, this, [&] {
|
|
QString filePath = qApp->applicationDirPath().append("/GameList.txt");
|
|
QFile file(filePath);
|
|
QTextStream out(&file);
|
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
qDebug() << "Failed to open file for writing:" << file.errorString();
|
|
return;
|
|
}
|
|
out << QString("%1 %2 %3 %4 %5\n")
|
|
.arg(" NAME", -50)
|
|
.arg(" ID", -10)
|
|
.arg("FW", -4)
|
|
.arg(" APP VERSION", -11)
|
|
.arg(" Path");
|
|
for (const GameInfo& game : m_game_info->m_games) {
|
|
QString game_path;
|
|
Common::FS::PathToQString(game_path, game.path);
|
|
out << QString("%1 %2 %3 %4 %5\n")
|
|
.arg(QString::fromStdString(game.name), -50)
|
|
.arg(QString::fromStdString(game.serial), -10)
|
|
.arg(QString::fromStdString(game.fw), -4)
|
|
.arg(QString::fromStdString(game.version), -11)
|
|
.arg(game_path);
|
|
}
|
|
});
|
|
|
|
// Package install.
|
|
connect(ui->bootGameAct, &QAction::triggered, this, &MainWindow::BootGame);
|
|
connect(ui->gameInstallPathAct, &QAction::triggered, this, &MainWindow::InstallDirectory);
|
|
|
|
// elf viewer
|
|
connect(ui->addElfFolderAct, &QAction::triggered, m_elf_viewer.data(),
|
|
&ElfViewer::OpenElfFolder);
|
|
|
|
// Trophy Viewer
|
|
connect(ui->trophyViewerAct, &QAction::triggered, this, [this]() {
|
|
if (m_game_info->m_games.empty()) {
|
|
QMessageBox::information(
|
|
this, tr("Trophy Viewer"),
|
|
tr("No games found. Please add your games to your library first."));
|
|
return;
|
|
}
|
|
|
|
const auto& firstGame = m_game_info->m_games[0];
|
|
QString trophyPath, gameTrpPath;
|
|
Common::FS::PathToQString(trophyPath, firstGame.serial);
|
|
Common::FS::PathToQString(gameTrpPath, firstGame.path);
|
|
|
|
auto game_update_path = Common::FS::PathFromQString(gameTrpPath);
|
|
game_update_path += "-UPDATE";
|
|
if (std::filesystem::exists(game_update_path)) {
|
|
Common::FS::PathToQString(gameTrpPath, game_update_path);
|
|
} else {
|
|
game_update_path = Common::FS::PathFromQString(gameTrpPath);
|
|
game_update_path += "-patch";
|
|
if (std::filesystem::exists(game_update_path)) {
|
|
Common::FS::PathToQString(gameTrpPath, game_update_path);
|
|
}
|
|
}
|
|
|
|
QVector<TrophyGameInfo> allTrophyGames;
|
|
for (const auto& game : m_game_info->m_games) {
|
|
TrophyGameInfo gameInfo;
|
|
gameInfo.name = QString::fromStdString(game.name);
|
|
Common::FS::PathToQString(gameInfo.trophyPath, game.serial);
|
|
Common::FS::PathToQString(gameInfo.gameTrpPath, game.path);
|
|
|
|
auto update_path = Common::FS::PathFromQString(gameInfo.gameTrpPath);
|
|
update_path += "-UPDATE";
|
|
if (std::filesystem::exists(update_path)) {
|
|
Common::FS::PathToQString(gameInfo.gameTrpPath, update_path);
|
|
} else {
|
|
update_path = Common::FS::PathFromQString(gameInfo.gameTrpPath);
|
|
update_path += "-patch";
|
|
if (std::filesystem::exists(update_path)) {
|
|
Common::FS::PathToQString(gameInfo.gameTrpPath, update_path);
|
|
}
|
|
}
|
|
|
|
allTrophyGames.append(gameInfo);
|
|
}
|
|
|
|
QString gameName = QString::fromStdString(firstGame.name);
|
|
TrophyViewer* trophyViewer =
|
|
new TrophyViewer(trophyPath, gameTrpPath, gameName, allTrophyGames);
|
|
trophyViewer->show();
|
|
});
|
|
|
|
// Themes
|
|
connect(ui->setThemeDark, &QAction::triggered, &m_window_themes, [this]() {
|
|
m_window_themes.SetWindowTheme(Theme::Dark, ui->mw_searchbar);
|
|
Config::setMainWindowTheme(static_cast<int>(Theme::Dark));
|
|
if (isIconBlack) {
|
|
SetUiIcons(false);
|
|
isIconBlack = false;
|
|
}
|
|
});
|
|
connect(ui->setThemeLight, &QAction::triggered, &m_window_themes, [this]() {
|
|
m_window_themes.SetWindowTheme(Theme::Light, ui->mw_searchbar);
|
|
Config::setMainWindowTheme(static_cast<int>(Theme::Light));
|
|
if (!isIconBlack) {
|
|
SetUiIcons(true);
|
|
isIconBlack = true;
|
|
}
|
|
});
|
|
connect(ui->setThemeGreen, &QAction::triggered, &m_window_themes, [this]() {
|
|
m_window_themes.SetWindowTheme(Theme::Green, ui->mw_searchbar);
|
|
Config::setMainWindowTheme(static_cast<int>(Theme::Green));
|
|
if (isIconBlack) {
|
|
SetUiIcons(false);
|
|
isIconBlack = false;
|
|
}
|
|
});
|
|
connect(ui->setThemeBlue, &QAction::triggered, &m_window_themes, [this]() {
|
|
m_window_themes.SetWindowTheme(Theme::Blue, ui->mw_searchbar);
|
|
Config::setMainWindowTheme(static_cast<int>(Theme::Blue));
|
|
if (isIconBlack) {
|
|
SetUiIcons(false);
|
|
isIconBlack = false;
|
|
}
|
|
});
|
|
connect(ui->setThemeViolet, &QAction::triggered, &m_window_themes, [this]() {
|
|
m_window_themes.SetWindowTheme(Theme::Violet, ui->mw_searchbar);
|
|
Config::setMainWindowTheme(static_cast<int>(Theme::Violet));
|
|
if (isIconBlack) {
|
|
SetUiIcons(false);
|
|
isIconBlack = false;
|
|
}
|
|
});
|
|
connect(ui->setThemeGruvbox, &QAction::triggered, &m_window_themes, [this]() {
|
|
m_window_themes.SetWindowTheme(Theme::Gruvbox, ui->mw_searchbar);
|
|
Config::setMainWindowTheme(static_cast<int>(Theme::Gruvbox));
|
|
if (isIconBlack) {
|
|
SetUiIcons(false);
|
|
isIconBlack = false;
|
|
}
|
|
});
|
|
connect(ui->setThemeTokyoNight, &QAction::triggered, &m_window_themes, [this]() {
|
|
m_window_themes.SetWindowTheme(Theme::TokyoNight, ui->mw_searchbar);
|
|
Config::setMainWindowTheme(static_cast<int>(Theme::TokyoNight));
|
|
if (isIconBlack) {
|
|
SetUiIcons(false);
|
|
isIconBlack = false;
|
|
}
|
|
});
|
|
connect(ui->setThemeOled, &QAction::triggered, &m_window_themes, [this]() {
|
|
m_window_themes.SetWindowTheme(Theme::Oled, ui->mw_searchbar);
|
|
Config::setMainWindowTheme(static_cast<int>(Theme::Oled));
|
|
if (isIconBlack) {
|
|
SetUiIcons(false);
|
|
isIconBlack = false;
|
|
}
|
|
});
|
|
}
|
|
|
|
void MainWindow::StartGame() {
|
|
BackgroundMusicPlayer::getInstance().stopMusic();
|
|
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();
|
|
Common::FS::PathToQString(gamePath, 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;
|
|
Common::FS::PathToQString(gamePath, m_game_info->m_games[itemID].path / "eboot.bin");
|
|
}
|
|
} else {
|
|
if (m_elf_viewer->currentItem()) {
|
|
int itemID = m_elf_viewer->currentItem()->row();
|
|
gamePath = m_elf_viewer->m_elf_list[itemID];
|
|
}
|
|
}
|
|
if (gamePath != "") {
|
|
AddRecentFiles(gamePath);
|
|
const auto path = Common::FS::PathFromQString(gamePath);
|
|
if (!std::filesystem::exists(path)) {
|
|
QMessageBox::critical(nullptr, tr("Run Game"), QString(tr("Eboot.bin file not found")));
|
|
return;
|
|
}
|
|
StartEmulator(path);
|
|
|
|
UpdateToolbarButtons();
|
|
}
|
|
}
|
|
|
|
bool isTable;
|
|
void MainWindow::SearchGameTable(const QString& text) {
|
|
if (isTableList) {
|
|
if (isTable != true) {
|
|
m_game_info->m_games = m_game_info->m_games_backup;
|
|
m_game_list_frame->PopulateGameList();
|
|
isTable = true;
|
|
}
|
|
for (int row = 0; row < m_game_list_frame->rowCount(); row++) {
|
|
QString game_name = QString::fromStdString(m_game_info->m_games[row].name);
|
|
bool match = (game_name.contains(text, Qt::CaseInsensitive)); // Check only in column 1
|
|
m_game_list_frame->setRowHidden(row, !match);
|
|
}
|
|
} else {
|
|
isTable = false;
|
|
m_game_info->m_games = m_game_info->m_games_backup;
|
|
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
|
|
|
|
QVector<GameInfo> filteredGames;
|
|
for (const auto& gameInfo : m_game_info->m_games) {
|
|
QString game_name = QString::fromStdString(gameInfo.name);
|
|
if (game_name.contains(text, Qt::CaseInsensitive)) {
|
|
filteredGames.push_back(gameInfo);
|
|
}
|
|
}
|
|
std::sort(filteredGames.begin(), filteredGames.end(), m_game_info->CompareStrings);
|
|
m_game_info->m_games = filteredGames;
|
|
m_game_grid_frame->PopulateGameGrid(filteredGames, true);
|
|
}
|
|
}
|
|
|
|
void MainWindow::ShowGameList() {
|
|
if (ui->showGameListAct->isChecked()) {
|
|
RefreshGameTable();
|
|
} else {
|
|
m_game_grid_frame->clearContents();
|
|
m_game_list_frame->clearContents();
|
|
}
|
|
};
|
|
|
|
void MainWindow::RefreshGameTable() {
|
|
// 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();
|
|
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
|
|
statusBar->clearMessage();
|
|
int numGames = m_game_info->m_games.size();
|
|
QString statusMessage = tr("Games: ") + QString::number(numGames);
|
|
statusBar->showMessage(statusMessage);
|
|
}
|
|
|
|
void MainWindow::ConfigureGuiFromSettings() {
|
|
setGeometry(Config::getMainWindowGeometryX(), Config::getMainWindowGeometryY(),
|
|
Config::getMainWindowGeometryW(), Config::getMainWindowGeometryH());
|
|
|
|
ui->showGameListAct->setChecked(true);
|
|
if (Config::getTableMode() == 0) {
|
|
ui->setlistModeListAct->setChecked(true);
|
|
} else if (Config::getTableMode() == 1) {
|
|
ui->setlistModeGridAct->setChecked(true);
|
|
} else if (Config::getTableMode() == 2) {
|
|
ui->setlistElfAct->setChecked(true);
|
|
}
|
|
BackgroundMusicPlayer::getInstance().setVolume(Config::getBGMvolume());
|
|
}
|
|
|
|
void MainWindow::SaveWindowState() const {
|
|
Config::setMainWindowWidth(this->width());
|
|
Config::setMainWindowHeight(this->height());
|
|
Config::setMainWindowGeometry(this->geometry().x(), this->geometry().y(),
|
|
this->geometry().width(), this->geometry().height());
|
|
}
|
|
|
|
void MainWindow::BootGame() {
|
|
QFileDialog dialog;
|
|
dialog.setFileMode(QFileDialog::ExistingFile);
|
|
dialog.setNameFilter(tr("ELF files (*.bin *.elf *.oelf)"));
|
|
if (dialog.exec()) {
|
|
QStringList fileNames = dialog.selectedFiles();
|
|
int nFiles = fileNames.size();
|
|
|
|
if (nFiles > 1) {
|
|
QMessageBox::critical(nullptr, tr("Game Boot"),
|
|
QString(tr("Only one file can be selected!")));
|
|
} else {
|
|
std::filesystem::path path = Common::FS::PathFromQString(fileNames[0]);
|
|
if (!std::filesystem::exists(path)) {
|
|
QMessageBox::critical(nullptr, tr("Run Game"),
|
|
QString(tr("Eboot.bin file not found")));
|
|
return;
|
|
}
|
|
StartEmulator(path);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::InstallDirectory() {
|
|
GameInstallDialog dlg;
|
|
dlg.exec();
|
|
RefreshGameTable();
|
|
}
|
|
|
|
void MainWindow::SetLastUsedTheme() {
|
|
Theme lastTheme = static_cast<Theme>(Config::getMainWindowTheme());
|
|
m_window_themes.SetWindowTheme(lastTheme, ui->mw_searchbar);
|
|
|
|
switch (lastTheme) {
|
|
case Theme::Light:
|
|
ui->setThemeLight->setChecked(true);
|
|
isIconBlack = true;
|
|
break;
|
|
case Theme::Dark:
|
|
ui->setThemeDark->setChecked(true);
|
|
isIconBlack = false;
|
|
SetUiIcons(false);
|
|
break;
|
|
case Theme::Green:
|
|
ui->setThemeGreen->setChecked(true);
|
|
isIconBlack = false;
|
|
SetUiIcons(false);
|
|
break;
|
|
case Theme::Blue:
|
|
ui->setThemeBlue->setChecked(true);
|
|
isIconBlack = false;
|
|
SetUiIcons(false);
|
|
break;
|
|
case Theme::Violet:
|
|
ui->setThemeViolet->setChecked(true);
|
|
isIconBlack = false;
|
|
SetUiIcons(false);
|
|
break;
|
|
case Theme::Gruvbox:
|
|
ui->setThemeGruvbox->setChecked(true);
|
|
isIconBlack = false;
|
|
SetUiIcons(false);
|
|
break;
|
|
case Theme::TokyoNight:
|
|
ui->setThemeTokyoNight->setChecked(true);
|
|
isIconBlack = false;
|
|
SetUiIcons(false);
|
|
break;
|
|
case Theme::Oled:
|
|
ui->setThemeOled->setChecked(true);
|
|
isIconBlack = false;
|
|
SetUiIcons(false);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void MainWindow::SetLastIconSizeBullet() {
|
|
// set QAction bullet point if applicable
|
|
int lastSize = Config::getIconSize();
|
|
int lastSizeGrid = Config::getIconSizeGrid();
|
|
if (isTableList) {
|
|
switch (lastSize) {
|
|
case 36:
|
|
ui->setIconSizeTinyAct->setChecked(true);
|
|
break;
|
|
case 64:
|
|
ui->setIconSizeSmallAct->setChecked(true);
|
|
break;
|
|
case 128:
|
|
ui->setIconSizeMediumAct->setChecked(true);
|
|
break;
|
|
case 256:
|
|
ui->setIconSizeLargeAct->setChecked(true);
|
|
break;
|
|
}
|
|
} else {
|
|
switch (lastSizeGrid) {
|
|
case 69:
|
|
ui->setIconSizeTinyAct->setChecked(true);
|
|
break;
|
|
case 97:
|
|
ui->setIconSizeSmallAct->setChecked(true);
|
|
break;
|
|
case 161:
|
|
ui->setIconSizeMediumAct->setChecked(true);
|
|
break;
|
|
case 256:
|
|
ui->setIconSizeLargeAct->setChecked(true);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
QIcon MainWindow::RecolorIcon(const QIcon& icon, bool isWhite) {
|
|
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);
|
|
return QIcon(pixmap);
|
|
}
|
|
|
|
void MainWindow::SetUiIcons(bool isWhite) {
|
|
ui->bootGameAct->setIcon(RecolorIcon(ui->bootGameAct->icon(), isWhite));
|
|
ui->shadFolderAct->setIcon(RecolorIcon(ui->shadFolderAct->icon(), isWhite));
|
|
ui->exitAct->setIcon(RecolorIcon(ui->exitAct->icon(), isWhite));
|
|
#ifdef ENABLE_UPDATER
|
|
ui->updaterAct->setIcon(RecolorIcon(ui->updaterAct->icon(), isWhite));
|
|
#endif
|
|
ui->downloadCheatsPatchesAct->setIcon(
|
|
RecolorIcon(ui->downloadCheatsPatchesAct->icon(), isWhite));
|
|
ui->dumpGameListAct->setIcon(RecolorIcon(ui->dumpGameListAct->icon(), isWhite));
|
|
ui->aboutAct->setIcon(RecolorIcon(ui->aboutAct->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->menuUtils->setIcon(RecolorIcon(ui->menuUtils->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->refreshButton->setIcon(RecolorIcon(ui->refreshButton->icon(), isWhite));
|
|
ui->restartButton->setIcon(RecolorIcon(ui->restartButton->icon(), isWhite));
|
|
ui->settingsButton->setIcon(RecolorIcon(ui->settingsButton->icon(), isWhite));
|
|
ui->fullscreenButton->setIcon(RecolorIcon(ui->fullscreenButton->icon(), isWhite));
|
|
ui->controllerButton->setIcon(RecolorIcon(ui->controllerButton->icon(), isWhite));
|
|
ui->keyboardButton->setIcon(RecolorIcon(ui->keyboardButton->icon(), isWhite));
|
|
ui->refreshGameListAct->setIcon(RecolorIcon(ui->refreshGameListAct->icon(), isWhite));
|
|
ui->menuGame_List_Mode->setIcon(RecolorIcon(ui->menuGame_List_Mode->icon(), isWhite));
|
|
ui->trophyViewerAct->setIcon(RecolorIcon(ui->trophyViewerAct->icon(), isWhite));
|
|
ui->configureAct->setIcon(RecolorIcon(ui->configureAct->icon(), isWhite));
|
|
ui->addElfFolderAct->setIcon(RecolorIcon(ui->addElfFolderAct->icon(), isWhite));
|
|
}
|
|
|
|
void MainWindow::resizeEvent(QResizeEvent* event) {
|
|
emit WindowResized(event);
|
|
QMainWindow::resizeEvent(event);
|
|
}
|
|
|
|
void MainWindow::HandleResize(QResizeEvent* event) {
|
|
if (isTableList) {
|
|
m_game_list_frame->RefreshListBackgroundImage();
|
|
} else {
|
|
m_game_grid_frame->windowWidth = this->width();
|
|
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::saveMainWindow(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) {
|
|
auto gamePath = Common::FS::PathFromQString(action->text());
|
|
AddRecentFiles(action->text()); // Update the list.
|
|
if (!std::filesystem::exists(gamePath)) {
|
|
QMessageBox::critical(nullptr, tr("Run Game"), QString(tr("Eboot.bin file not found")));
|
|
return;
|
|
}
|
|
StartEmulator(gamePath);
|
|
});
|
|
}
|
|
|
|
void MainWindow::LoadTranslation() {
|
|
auto language = QString::fromStdString(Config::getEmulatorLanguage());
|
|
|
|
const QString base_dir = QStringLiteral(":/translations");
|
|
QString base_path = QStringLiteral("%1/%2.qm").arg(base_dir).arg(language);
|
|
|
|
if (QFile::exists(base_path)) {
|
|
if (translator != nullptr) {
|
|
qApp->removeTranslator(translator);
|
|
}
|
|
|
|
translator = new QTranslator(qApp);
|
|
if (!translator->load(base_path)) {
|
|
QMessageBox::warning(
|
|
nullptr, QStringLiteral("Translation Error"),
|
|
QStringLiteral("Failed to find load translation file for '%1':\n%2")
|
|
.arg(language)
|
|
.arg(base_path));
|
|
delete translator;
|
|
} else {
|
|
qApp->installTranslator(translator);
|
|
ui->retranslateUi(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::OnLanguageChanged(const std::string& locale) {
|
|
Config::setEmulatorLanguage(locale);
|
|
|
|
LoadTranslation();
|
|
}
|
|
|
|
bool MainWindow::eventFilter(QObject* obj, QEvent* event) {
|
|
if (event->type() == QEvent::KeyPress) {
|
|
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
|
if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) {
|
|
auto tblMode = Config::getTableMode();
|
|
if (tblMode != 2 && (tblMode != 1 || m_game_grid_frame->IsValidCellSelected())) {
|
|
StartGame();
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return QMainWindow::eventFilter(obj, event);
|
|
}
|
|
|
|
void MainWindow::StartEmulator(std::filesystem::path path) {
|
|
if (isGameRunning) {
|
|
QMessageBox::critical(nullptr, tr("Run Game"), QString(tr("Game is already running!")));
|
|
return;
|
|
}
|
|
isGameRunning = true;
|
|
#ifdef __APPLE__
|
|
// SDL on macOS requires main thread.
|
|
Core::Emulator emulator;
|
|
emulator.Run(path);
|
|
#else
|
|
std::thread emulator_thread([=] {
|
|
Core::Emulator emulator;
|
|
emulator.Run(path);
|
|
});
|
|
emulator_thread.detach();
|
|
#endif
|
|
}
|