/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2022 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see .
*/
#include "PrecompiledHeader.h"
#include "common/FileSystem.h"
#include "common/Path.h"
#include "common/StringUtil.h"
#include "pcsx2/HostSettings.h"
#include "pcsx2/Frontend/GameList.h"
#include "pcsx2/Frontend/INISettingsInterface.h"
#include "EmuThread.h"
#include "QtHost.h"
#include "QtUtils.h"
#include "SettingsDialog.h"
#include "AdvancedSystemSettingsWidget.h"
#include "AudioSettingsWidget.h"
#include "BIOSSettingsWidget.h"
#include "EmulationSettingsWidget.h"
#include "GameSummaryWidget.h"
#include "GameFixSettingsWidget.h"
#include "GameListSettingsWidget.h"
#include "GraphicsSettingsWidget.h"
#include "DEV9SettingsWidget.h"
#include "HotkeySettingsWidget.h"
#include "InterfaceSettingsWidget.h"
#include "MemoryCardSettingsWidget.h"
#include "SystemSettingsWidget.h"
#include
#include
static QList s_open_game_properties_dialogs;
SettingsDialog::SettingsDialog(QWidget* parent)
: QDialog(parent)
, m_game_crc(0)
{
setupUi(nullptr);
}
SettingsDialog::SettingsDialog(std::unique_ptr sif, const GameList::Entry* game, u32 game_crc)
: QDialog()
, m_sif(std::move(sif))
, m_game_crc(game_crc)
{
setupUi(game);
s_open_game_properties_dialogs.push_back(this);
}
void SettingsDialog::setupUi(const GameList::Entry* game)
{
const bool show_advanced_settings = true;
m_ui.setupUi(this);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
// We don't include interface/game list/bios settings from per-game settings.
if (!isPerGameSettings())
{
addWidget(m_interface_settings = new InterfaceSettingsWidget(this, m_ui.settingsContainer), tr("Interface"),
QStringLiteral("settings-3-line"),
tr("Interface SettingsThese options control how the software looks and behaves.
Mouse over an option for "
"additional information."));
addWidget(m_game_list_settings = new GameListSettingsWidget(this, m_ui.settingsContainer), tr("Game List"),
QStringLiteral("folder-settings-line"),
tr("Game List SettingsThe list above shows the directories which will be searched by PCSX2 to populate the game "
"list. Search directories can be added, removed, and switched to recursive/non-recursive."));
addWidget(m_bios_settings = new BIOSSettingsWidget(this, m_ui.settingsContainer), tr("BIOS"), QStringLiteral("hard-drive-2-line"),
tr("BIOS Settings"));
}
else
{
if (game)
{
addWidget(new GameSummaryWidget(game, this, m_ui.settingsContainer), tr("Summary"), QStringLiteral("file-list-line"),
tr("SummaryEventually this will be where we can see patches and compute hashes/verify dumps/etc."));
}
m_ui.restoreDefaultsButton->setVisible(false);
}
// Common to both per-game and global settings.
addWidget(m_emulation_settings = new EmulationSettingsWidget(this, m_ui.settingsContainer), tr("Emulation"), QStringLiteral("dashboard-line"),
tr("Emulation Settings"));
addWidget(m_system_settings = new SystemSettingsWidget(this, m_ui.settingsContainer), tr("System"), QStringLiteral("artboard-2-line"),
tr("System SettingsThese options determine the configuration of the simulated console.
Mouse over an option for "
"additional information."));
if (show_advanced_settings)
{
addWidget(m_advanced_system_settings = new AdvancedSystemSettingsWidget(this, m_ui.settingsContainer), tr("Advanced System"),
QStringLiteral("artboard-2-line"), tr("Advanced System Settings"));
// Only show the game fixes for per-game settings, there's really no reason to be setting them globally.
if (isPerGameSettings())
{
addWidget(m_game_fix_settings_widget = new GameFixSettingsWidget(this, m_ui.settingsContainer), tr("Game Fix"),
QStringLiteral("close-line"), tr("Game Fix Settings"));
}
}
addWidget(m_graphics_settings = new GraphicsSettingsWidget(this, m_ui.settingsContainer), tr("Graphics"), QStringLiteral("brush-line"),
tr("Graphics Settings"));
addWidget(m_audio_settings = new AudioSettingsWidget(this, m_ui.settingsContainer), tr("Audio"), QStringLiteral("volume-up-line"),
tr("Audio SettingsThese options control the audio output of the console. Mouse over an option for additional "
"information."));
// for now, memory cards aren't settable per-game
if (!isPerGameSettings())
{
addWidget(m_memory_card_settings = new MemoryCardSettingsWidget(this, m_ui.settingsContainer), tr("Memory Cards"),
QStringLiteral("sd-card-line"), tr("Memory Card Settings"));
}
addWidget(m_dev9_settings = new DEV9SettingsWidget(this, m_ui.settingsContainer), tr("Network & HDD"), QStringLiteral("dashboard-line"),
tr("Network & HDD SettingsThese options control the network connectivity and internal HDD storage of the console.
"
"Mouse over an option for additional information."));
m_ui.settingsCategory->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
m_ui.settingsCategory->setCurrentRow(0);
m_ui.settingsContainer->setCurrentIndex(0);
m_ui.helpText->setText(m_category_help_text[0]);
connect(m_ui.settingsCategory, &QListWidget::currentRowChanged, this, &SettingsDialog::onCategoryCurrentRowChanged);
connect(m_ui.closeButton, &QPushButton::clicked, this, &SettingsDialog::accept);
connect(m_ui.restoreDefaultsButton, &QPushButton::clicked, this, &SettingsDialog::onRestoreDefaultsClicked);
// TODO: Remove this once they're implemented.
m_ui.restoreDefaultsButton->setVisible(false);
}
SettingsDialog::~SettingsDialog()
{
if (isPerGameSettings())
s_open_game_properties_dialogs.removeOne(this);
}
void SettingsDialog::closeEvent(QCloseEvent*)
{
// we need to clean up ourselves, since we're not modal
if (isPerGameSettings())
deleteLater();
}
void SettingsDialog::setCategory(const char* category)
{
// the titles in the category list will be translated.
const QString translated_category(qApp->translate("SettingsDialog", category));
for (int i = 0; i < m_ui.settingsCategory->count(); i++)
{
if (translated_category == m_ui.settingsCategory->item(i)->text())
{
// will also update the visible widget
m_ui.settingsCategory->setCurrentRow(i);
break;
}
}
}
void SettingsDialog::onCategoryCurrentRowChanged(int row)
{
m_ui.settingsContainer->setCurrentIndex(row);
m_ui.helpText->setText(m_category_help_text[row]);
}
void SettingsDialog::onRestoreDefaultsClicked()
{
if (QMessageBox::question(this, tr("Confirm Restore Defaults"),
tr("Are you sure you want to restore the default settings? Any preferences will be lost."), QMessageBox::Yes,
QMessageBox::No) != QMessageBox::Yes)
{
return;
}
// TODO
}
void SettingsDialog::addWidget(QWidget* widget, QString title, QString icon, QString help_text)
{
const int index = m_ui.settingsCategory->count();
QListWidgetItem* item = new QListWidgetItem(m_ui.settingsCategory);
item->setText(title);
if (!icon.isEmpty())
item->setIcon(QIcon::fromTheme(icon));
m_ui.settingsContainer->addWidget(widget);
m_category_help_text[index] = std::move(help_text);
}
void SettingsDialog::registerWidgetHelp(QObject* object, QString title, QString recommended_value, QString text)
{
// construct rich text with formatted description
QString full_text;
full_text += "