Qt: Implement settings reset

This commit is contained in:
Connor McLaughlin 2022-09-07 17:44:10 +10:00 committed by refractionpcsx2
parent d86abebb50
commit e4df563811
35 changed files with 771 additions and 491 deletions

View File

@ -454,7 +454,8 @@ void AutoUpdaterDialog::checkIfUpdateNeeded()
void AutoUpdaterDialog::skipThisUpdateClicked() void AutoUpdaterDialog::skipThisUpdateClicked()
{ {
QtHost::SetBaseStringSettingValue("AutoUpdater", "LastVersion", m_latest_version.toUtf8().constData()); Host::SetBaseStringSettingValue("AutoUpdater", "LastVersion", m_latest_version.toUtf8().constData());
Host::CommitBaseSettingChanges();
done(0); done(0);
} }

View File

@ -347,7 +347,8 @@ void GameListWidget::onTableViewHeaderSortIndicatorChanged(int, Qt::SortOrder)
void GameListWidget::listZoom(float delta) void GameListWidget::listZoom(float delta)
{ {
const float new_scale = std::clamp(m_model->getCoverScale() + delta, MIN_SCALE, MAX_SCALE); const float new_scale = std::clamp(m_model->getCoverScale() + delta, MIN_SCALE, MAX_SCALE);
QtHost::SetBaseFloatSettingValue("UI", "GameListCoverArtScale", new_scale); Host::SetBaseFloatSettingValue("UI", "GameListCoverArtScale", new_scale);
Host::CommitBaseSettingChanges();
m_model->setCoverScale(new_scale); m_model->setCoverScale(new_scale);
m_model->updateCacheSize(width(), height()); m_model->updateCacheSize(width(), height());
updateListFont(); updateListFont();
@ -368,7 +369,8 @@ void GameListWidget::gridIntScale(int int_scale)
{ {
const float new_scale = std::clamp(static_cast<float>(int_scale) / 100.0f, MIN_SCALE, MAX_SCALE); const float new_scale = std::clamp(static_cast<float>(int_scale) / 100.0f, MIN_SCALE, MAX_SCALE);
QtHost::SetBaseFloatSettingValue("UI", "GameListCoverArtScale", new_scale); Host::SetBaseFloatSettingValue("UI", "GameListCoverArtScale", new_scale);
Host::CommitBaseSettingChanges();
m_model->setCoverScale(new_scale); m_model->setCoverScale(new_scale);
m_model->updateCacheSize(width(), height()); m_model->updateCacheSize(width(), height());
updateListFont(); updateListFont();
@ -389,7 +391,8 @@ void GameListWidget::showGameList()
return; return;
} }
QtHost::SetBaseBoolSettingValue("UI", "GameListGridView", false); Host::SetBaseBoolSettingValue("UI", "GameListGridView", false);
Host::CommitBaseSettingChanges();
m_ui.stack->setCurrentIndex(0); m_ui.stack->setCurrentIndex(0);
resizeTableViewColumnsToFit(); resizeTableViewColumnsToFit();
updateToolbar(); updateToolbar();
@ -405,7 +408,8 @@ void GameListWidget::showGameGrid()
return; return;
} }
QtHost::SetBaseBoolSettingValue("UI", "GameListGridView", true); Host::SetBaseBoolSettingValue("UI", "GameListGridView", true);
Host::CommitBaseSettingChanges();
m_ui.stack->setCurrentIndex(1); m_ui.stack->setCurrentIndex(1);
updateToolbar(); updateToolbar();
emit layoutChange(); emit layoutChange();
@ -416,7 +420,8 @@ void GameListWidget::setShowCoverTitles(bool enabled)
if (m_model->getShowCoverTitles() == enabled) if (m_model->getShowCoverTitles() == enabled)
return; return;
QtHost::SetBaseBoolSettingValue("UI", "GameListShowCoverTitles", enabled); Host::SetBaseBoolSettingValue("UI", "GameListShowCoverTitles", enabled);
Host::CommitBaseSettingChanges();
m_model->setShowCoverTitles(enabled); m_model->setShowCoverTitles(enabled);
if (isShowingGameGrid()) if (isShowingGameGrid())
m_model->refresh(); m_model->refresh();
@ -508,14 +513,16 @@ void GameListWidget::saveTableViewColumnVisibilitySettings()
for (int column = 0; column < GameListModel::Column_Count; column++) for (int column = 0; column < GameListModel::Column_Count; column++)
{ {
const bool visible = !m_table_view->isColumnHidden(column); const bool visible = !m_table_view->isColumnHidden(column);
QtHost::SetBaseBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column).c_str(), visible); Host::SetBaseBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column).c_str(), visible);
Host::CommitBaseSettingChanges();
} }
} }
void GameListWidget::saveTableViewColumnVisibilitySettings(int column) void GameListWidget::saveTableViewColumnVisibilitySettings(int column)
{ {
const bool visible = !m_table_view->isColumnHidden(column); const bool visible = !m_table_view->isColumnHidden(column);
QtHost::SetBaseBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column).c_str(), visible); Host::SetBaseBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column).c_str(), visible);
Host::CommitBaseSettingChanges();
} }
void GameListWidget::loadTableViewColumnSortSettings() void GameListWidget::loadTableViewColumnSortSettings()
@ -538,11 +545,12 @@ void GameListWidget::saveTableViewColumnSortSettings()
if (sort_column >= 0 && sort_column < GameListModel::Column_Count) if (sort_column >= 0 && sort_column < GameListModel::Column_Count)
{ {
QtHost::SetBaseStringSettingValue( Host::SetBaseStringSettingValue(
"GameListTableView", "SortColumn", GameListModel::getColumnName(static_cast<GameListModel::Column>(sort_column))); "GameListTableView", "SortColumn", GameListModel::getColumnName(static_cast<GameListModel::Column>(sort_column)));
} }
QtHost::SetBaseBoolSettingValue("GameListTableView", "SortDescending", sort_descending); Host::SetBaseBoolSettingValue("GameListTableView", "SortDescending", sort_descending);
Host::CommitBaseSettingChanges();
} }
const GameList::Entry* GameListWidget::getSelectedEntry() const const GameList::Entry* GameListWidget::getSelectedEntry() const

View File

@ -401,6 +401,37 @@ void MainWindow::recreate()
deleteLater(); deleteLater();
} }
void MainWindow::recreateSettings()
{
QString current_category;
if (m_settings_dialog)
{
current_category = m_settings_dialog->getCategory();
m_settings_dialog->hide();
m_settings_dialog->deleteLater();
m_settings_dialog = nullptr;
}
doSettings(current_category.toUtf8().constData());
}
void MainWindow::resetSettings(bool ui)
{
Host::RequestResetSettings(false, true, false, false, ui);
if (ui)
{
// UI reset includes theme (and eventually language).
// Just updating the theme here, when there's no change, causes Qt to get very confused..
// So, we'll just tear down everything and recreate. We'll need to do that for language
// resets eventaully anyway.
recreate();
}
// g_main_window here for recreate() case above.
g_main_window->recreateSettings();
}
void MainWindow::updateApplicationTheme() void MainWindow::updateApplicationTheme()
{ {
if (!s_unthemed_style_name_set) if (!s_unthemed_style_name_set)
@ -734,7 +765,8 @@ void MainWindow::onBlockDumpActionToggled(bool checked)
return; return;
} }
QtHost::SetBaseStringSettingValue("EmuCore", "BlockDumpSaveDirectory", new_dir.toUtf8().constData()); Host::SetBaseStringSettingValue("EmuCore", "BlockDumpSaveDirectory", new_dir.toUtf8().constData());
Host::CommitBaseSettingChanges();
} }
void MainWindow::saveStateToConfig() void MainWindow::saveStateToConfig()
@ -747,7 +779,10 @@ void MainWindow::saveStateToConfig()
const QByteArray geometry_b64 = geometry.toBase64(); const QByteArray geometry_b64 = geometry.toBase64();
const std::string old_geometry_b64 = Host::GetBaseStringSettingValue("UI", "MainWindowGeometry"); const std::string old_geometry_b64 = Host::GetBaseStringSettingValue("UI", "MainWindowGeometry");
if (old_geometry_b64 != geometry_b64.constData()) if (old_geometry_b64 != geometry_b64.constData())
QtHost::SetBaseStringSettingValue("UI", "MainWindowGeometry", geometry_b64.constData()); {
Host::SetBaseStringSettingValue("UI", "MainWindowGeometry", geometry_b64.constData());
Host::CommitBaseSettingChanges();
}
} }
{ {
@ -755,7 +790,10 @@ void MainWindow::saveStateToConfig()
const QByteArray state_b64 = state.toBase64(); const QByteArray state_b64 = state.toBase64();
const std::string old_state_b64 = Host::GetBaseStringSettingValue("UI", "MainWindowState"); const std::string old_state_b64 = Host::GetBaseStringSettingValue("UI", "MainWindowState");
if (old_state_b64 != state_b64.constData()) if (old_state_b64 != state_b64.constData())
QtHost::SetBaseStringSettingValue("UI", "MainWindowState", state_b64.constData()); {
Host::SetBaseStringSettingValue("UI", "MainWindowState", state_b64.constData());
Host::CommitBaseSettingChanges();
}
} }
} }
@ -1306,19 +1344,22 @@ void MainWindow::onSaveStateMenuAboutToShow()
void MainWindow::onViewToolbarActionToggled(bool checked) void MainWindow::onViewToolbarActionToggled(bool checked)
{ {
QtHost::SetBaseBoolSettingValue("UI", "ShowToolbar", checked); Host::SetBaseBoolSettingValue("UI", "ShowToolbar", checked);
Host::CommitBaseSettingChanges();
m_ui.toolBar->setVisible(checked); m_ui.toolBar->setVisible(checked);
} }
void MainWindow::onViewLockToolbarActionToggled(bool checked) void MainWindow::onViewLockToolbarActionToggled(bool checked)
{ {
QtHost::SetBaseBoolSettingValue("UI", "LockToolbar", checked); Host::SetBaseBoolSettingValue("UI", "LockToolbar", checked);
Host::CommitBaseSettingChanges();
m_ui.toolBar->setMovable(!checked); m_ui.toolBar->setMovable(!checked);
} }
void MainWindow::onViewStatusBarActionToggled(bool checked) void MainWindow::onViewStatusBarActionToggled(bool checked)
{ {
QtHost::SetBaseBoolSettingValue("UI", "ShowStatusBar", checked); Host::SetBaseBoolSettingValue("UI", "ShowStatusBar", checked);
Host::CommitBaseSettingChanges();
m_ui.statusBar->setVisible(checked); m_ui.statusBar->setVisible(checked);
} }
@ -1386,7 +1427,8 @@ void MainWindow::onAboutActionTriggered()
void MainWindow::onCheckForUpdatesActionTriggered() void MainWindow::onCheckForUpdatesActionTriggered()
{ {
// Wipe out the last version, that way it displays the update if we've previously skipped it. // Wipe out the last version, that way it displays the update if we've previously skipped it.
QtHost::RemoveBaseSettingValue("AutoUpdater", "LastVersion"); Host::RemoveBaseSettingValue("AutoUpdater", "LastVersion");
Host::CommitBaseSettingChanges();
checkForUpdates(true); checkForUpdates(true);
} }
@ -2029,7 +2071,10 @@ void MainWindow::saveDisplayWindowGeometryToConfig()
const QByteArray geometry_b64 = geometry.toBase64(); const QByteArray geometry_b64 = geometry.toBase64();
const std::string old_geometry_b64 = Host::GetBaseStringSettingValue("UI", "DisplayWindowGeometry"); const std::string old_geometry_b64 = Host::GetBaseStringSettingValue("UI", "DisplayWindowGeometry");
if (old_geometry_b64 != geometry_b64.constData()) if (old_geometry_b64 != geometry_b64.constData())
QtHost::SetBaseStringSettingValue("UI", "DisplayWindowGeometry", geometry_b64.constData()); {
Host::SetBaseStringSettingValue("UI", "DisplayWindowGeometry", geometry_b64.constData());
Host::CommitBaseSettingChanges();
}
} }
void MainWindow::restoreDisplayWindowGeometryFromConfig() void MainWindow::restoreDisplayWindowGeometryFromConfig()

View File

@ -85,6 +85,7 @@ public:
void initialize(); void initialize();
void connectVMThreadSignals(EmuThread* thread); void connectVMThreadSignals(EmuThread* thread);
void startupUpdateCheck(); void startupUpdateCheck();
void resetSettings(bool ui);
/// Locks the VM by pausing it, while a popup dialog is displayed. /// Locks the VM by pausing it, while a popup dialog is displayed.
VMLock pauseAndLockVM(); VMLock pauseAndLockVM();
@ -167,8 +168,6 @@ private Q_SLOTS:
void onGameChanged(const QString& path, const QString& serial, const QString& name, quint32 crc); void onGameChanged(const QString& path, const QString& serial, const QString& name, quint32 crc);
void recreate();
protected: protected:
void showEvent(QShowEvent* event) override; void showEvent(QShowEvent* event) override;
void closeEvent(QCloseEvent* event) override; void closeEvent(QCloseEvent* event) override;
@ -186,6 +185,8 @@ private:
void setupAdditionalUi(); void setupAdditionalUi();
void connectSignals(); void connectSignals();
void recreate();
void recreateSettings();
void saveStateToConfig(); void saveStateToConfig();
void restoreStateFromConfig(); void restoreStateFromConfig();

View File

@ -24,8 +24,6 @@
#ifdef _WIN32 #ifdef _WIN32
#include "common/RedtapeWindows.h" #include "common/RedtapeWindows.h"
#include <KnownFolders.h>
#include <ShlObj.h>
#endif #endif
#include "common/Assertions.h" #include "common/Assertions.h"
@ -39,6 +37,7 @@
#include "pcsx2/CDVD/CDVDcommon.h" #include "pcsx2/CDVD/CDVDcommon.h"
#include "pcsx2/DebugTools/Debug.h" #include "pcsx2/DebugTools/Debug.h"
#include "pcsx2/Frontend/CommonHost.h"
#include "pcsx2/Frontend/GameList.h" #include "pcsx2/Frontend/GameList.h"
#include "pcsx2/Frontend/INISettingsInterface.h" #include "pcsx2/Frontend/INISettingsInterface.h"
#include "pcsx2/Frontend/LogSink.h" #include "pcsx2/Frontend/LogSink.h"
@ -52,7 +51,6 @@
#include "QtUtils.h" #include "QtUtils.h"
#include "svnrev.h" #include "svnrev.h"
static constexpr u32 SETTINGS_VERSION = 1;
static constexpr u32 SETTINGS_SAVE_DELAY = 1000; static constexpr u32 SETTINGS_SAVE_DELAY = 1000;
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -64,14 +62,8 @@ static void PrintCommandLineHelp(const char* progname);
static std::shared_ptr<VMBootParameters>& AutoBoot(std::shared_ptr<VMBootParameters>& autoboot); static std::shared_ptr<VMBootParameters>& AutoBoot(std::shared_ptr<VMBootParameters>& autoboot);
static bool ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr<VMBootParameters>& autoboot); static bool ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr<VMBootParameters>& autoboot);
static bool InitializeConfig(); static bool InitializeConfig();
static bool ShouldUsePortableMode();
static void SetAppRoot();
static void SetResourcesDirectory();
static void SetDataDirectory();
static void HookSignals();
static bool SetCriticalFolders();
static void SetDefaultConfig();
static void SaveSettings(); static void SaveSettings();
static void HookSignals();
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -89,225 +81,54 @@ static bool s_start_fullscreen_ui_fullscreen = false;
// Initialization/Shutdown // Initialization/Shutdown
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
bool QtHost::SetCriticalFolders()
{
SetAppRoot();
SetResourcesDirectory();
SetDataDirectory();
// logging of directories in case something goes wrong super early
Console.WriteLn("AppRoot Directory: %s", EmuFolders::AppRoot.c_str());
Console.WriteLn("DataRoot Directory: %s", EmuFolders::DataRoot.c_str());
Console.WriteLn("Resources Directory: %s", EmuFolders::Resources.c_str());
// allow SetDataDirectory() to change settings directory (if we want to split config later on)
if (EmuFolders::Settings.empty())
EmuFolders::Settings = Path::Combine(EmuFolders::DataRoot, "inis");
// Write crash dumps to the data directory, since that'll be accessible for certain.
CrashHandler::SetWriteDirectory(EmuFolders::DataRoot);
// the resources directory should exist, bail out if not
if (!FileSystem::DirectoryExists(EmuFolders::Resources.c_str()))
{
QMessageBox::critical(nullptr, QStringLiteral("Error"),
QStringLiteral("Resources directory is missing, your installation is incomplete."));
return false;
}
return true;
}
bool QtHost::ShouldUsePortableMode()
{
// Check whether portable.ini exists in the program directory.
return FileSystem::FileExists(Path::Combine(EmuFolders::AppRoot, "portable.ini").c_str());
}
void QtHost::SetAppRoot()
{
std::string program_path(FileSystem::GetProgramPath());
Console.WriteLn("Program Path: %s", program_path.c_str());
EmuFolders::AppRoot = Path::Canonicalize(Path::GetDirectory(program_path));
}
void QtHost::SetResourcesDirectory()
{
#ifndef __APPLE__
// On Windows/Linux, these are in the binary directory.
EmuFolders::Resources = Path::Combine(EmuFolders::AppRoot, "resources");
#else
// On macOS, this is in the bundle resources directory.
EmuFolders::Resources = Path::Canonicalize(Path::Combine(EmuFolders::AppRoot, "../Resources"));
#endif
}
void QtHost::SetDataDirectory()
{
if (ShouldUsePortableMode())
{
EmuFolders::DataRoot = EmuFolders::AppRoot;
return;
}
#if defined(_WIN32)
// On Windows, use My Documents\PCSX2 to match old installs.
PWSTR documents_directory;
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &documents_directory)))
{
if (std::wcslen(documents_directory) > 0)
EmuFolders::DataRoot = Path::Combine(StringUtil::WideStringToUTF8String(documents_directory), "PCSX2");
CoTaskMemFree(documents_directory);
}
#elif defined(__linux__)
// Use $XDG_CONFIG_HOME/PCSX2 if it exists.
const char* xdg_config_home = getenv("XDG_CONFIG_HOME");
if (xdg_config_home && Path::IsAbsolute(xdg_config_home))
{
EmuFolders::DataRoot = Path::Combine(xdg_config_home, "PCSX2");
}
else
{
// Use ~/PCSX2 for non-XDG, and ~/.config/PCSX2 for XDG.
// Maybe we should drop the former when Qt goes live.
const char* home_dir = getenv("HOME");
if (home_dir)
{
#ifndef XDG_STD
EmuFolders::DataRoot = Path::Combine(home_dir, "PCSX2");
#else
// ~/.config should exist, but just in case it doesn't and this is a fresh profile..
const std::string config_dir(Path::Combine(home_dir, ".config"));
if (!FileSystem::DirectoryExists(config_dir.c_str()))
FileSystem::CreateDirectoryPath(config_dir.c_str(), false);
EmuFolders::DataRoot = Path::Combine(config_dir, "PCSX2");
#endif
}
}
#elif defined(__APPLE__)
static constexpr char MAC_DATA_DIR[] = "Library/Application Support/PCSX2";
const char* home_dir = getenv("HOME");
if (home_dir)
EmuFolders::DataRoot = Path::Combine(home_dir, MAC_DATA_DIR);
#endif
// make sure it exists
if (!EmuFolders::DataRoot.empty() && !FileSystem::DirectoryExists(EmuFolders::DataRoot.c_str()))
{
// we're in trouble if we fail to create this directory... but try to hobble on with portable
if (!FileSystem::CreateDirectoryPath(EmuFolders::DataRoot.c_str(), false))
EmuFolders::DataRoot.clear();
}
// couldn't determine the data directory? fallback to portable.
if (EmuFolders::DataRoot.empty())
EmuFolders::DataRoot = EmuFolders::AppRoot;
}
bool QtHost::InitializeConfig() bool QtHost::InitializeConfig()
{ {
if (!SetCriticalFolders()) if (!CommonHost::InitializeCriticalFolders())
{
QMessageBox::critical(nullptr, QStringLiteral("PCSX2"),
QStringLiteral("One or more critical directories are missing, your installation may be incomplete."));
return false; return false;
}
const std::string path(Path::Combine(EmuFolders::Settings, "PCSX2.ini")); const std::string path(Path::Combine(EmuFolders::Settings, "PCSX2.ini"));
Console.WriteLn("Loading config from %s.", path.c_str()); Console.WriteLn("Loading config from %s.", path.c_str());
s_base_settings_interface = std::make_unique<INISettingsInterface>(std::move(path)); s_base_settings_interface = std::make_unique<INISettingsInterface>(std::move(path));
Host::Internal::SetBaseSettingsLayer(s_base_settings_interface.get()); Host::Internal::SetBaseSettingsLayer(s_base_settings_interface.get());
if (!s_base_settings_interface->Load() || !CommonHost::CheckSettingsVersion())
uint settings_version;
if (!s_base_settings_interface->Load() ||
!s_base_settings_interface->GetUIntValue("UI", "SettingsVersion", &settings_version) ||
settings_version != SETTINGS_VERSION)
{ {
QMessageBox::critical( // If the config file doesn't exist, assume this is a new install and don't prompt to overwrite.
g_main_window, qApp->translate("QtHost", "Settings Reset"), if (FileSystem::FileExists(s_base_settings_interface->GetFileName().c_str()) &&
qApp->translate("QtHost", "Settings do not exist or are the incorrect version, resetting to defaults.")); QMessageBox::question(nullptr, QStringLiteral("PCSX2"),
SetDefaultConfig(); QStringLiteral("Settings failed to load, or are the incorrect version. Clicking Yes will reset all settings to defaults. Do you want to continue?")) != QMessageBox::Yes)
s_base_settings_interface->Save(); {
return false;
} }
// TODO: Handle reset to defaults if load fails. CommonHost::SetDefaultSettings(*s_base_settings_interface, true, true, true, true, true);
EmuFolders::LoadConfig(*s_base_settings_interface.get()); SaveSettings();
EmuFolders::EnsureFoldersExist(); }
CommonHost::LoadStartupSettings();
Host::UpdateLogging(QtHost::InNoGUIMode()); Host::UpdateLogging(QtHost::InNoGUIMode());
return true; return true;
} }
void QtHost::SetDefaultConfig() void Host::SetDefaultUISettings(SettingsInterface& si)
{ {
EmuFolders::SetDefaults(); Host::SetDefaultLoggingSettings(si);
EmuFolders::EnsureFoldersExist();
SettingsInterface& si = *s_base_settings_interface.get(); si.SetBoolValue("UI", "InhibitScreensaver", true);
si.SetUIntValue("UI", "SettingsVersion", SETTINGS_VERSION); si.SetBoolValue("UI", "ConfirmShutdown", true);
VMManager::SetDefaultSettings(si); si.SetBoolValue("UI", "StartPaused", false);
EmuFolders::Save(si); si.SetBoolValue("UI", "PauseOnFocusLoss", false);
PAD::SetDefaultControllerConfig(si); si.SetBoolValue("UI", "StartFullscreen", false);
PAD::SetDefaultHotkeyConfig(si); si.SetBoolValue("UI", "DoubleClickTogglesFullscreen", true);
} si.SetBoolValue("UI", "HideMouseCursor", false);
si.SetBoolValue("UI", "RenderToSeparateWindow", false);
void QtHost::SetBaseBoolSettingValue(const char* section, const char* key, bool value) si.SetBoolValue("UI", "HideMainWindowWhenRunning", false);
{ si.SetBoolValue("UI", "DisableWindowResize", false);
auto lock = Host::GetSettingsLock(); si.SetStringValue("UI", "Theme", MainWindow::DEFAULT_THEME_NAME);
s_base_settings_interface->SetBoolValue(section, key, value);
QueueSettingsSave();
}
void QtHost::SetBaseIntSettingValue(const char* section, const char* key, int value)
{
auto lock = Host::GetSettingsLock();
s_base_settings_interface->SetIntValue(section, key, value);
QueueSettingsSave();
}
void QtHost::SetBaseFloatSettingValue(const char* section, const char* key, float value)
{
auto lock = Host::GetSettingsLock();
s_base_settings_interface->SetFloatValue(section, key, value);
QueueSettingsSave();
}
void QtHost::SetBaseStringSettingValue(const char* section, const char* key, const char* value)
{
auto lock = Host::GetSettingsLock();
s_base_settings_interface->SetStringValue(section, key, value);
QueueSettingsSave();
}
void QtHost::SetBaseStringListSettingValue(const char* section, const char* key, const std::vector<std::string>& values)
{
auto lock = Host::GetSettingsLock();
s_base_settings_interface->SetStringList(section, key, values);
QueueSettingsSave();
}
bool QtHost::AddBaseValueToStringList(const char* section, const char* key, const char* value)
{
auto lock = Host::GetSettingsLock();
if (!s_base_settings_interface->AddToStringList(section, key, value))
return false;
QueueSettingsSave();
return true;
}
bool QtHost::RemoveBaseValueFromStringList(const char* section, const char* key, const char* value)
{
auto lock = Host::GetSettingsLock();
if (!s_base_settings_interface->RemoveFromStringList(section, key, value))
return false;
QueueSettingsSave();
return true;
}
void QtHost::RemoveBaseSettingValue(const char* section, const char* key)
{
auto lock = Host::GetSettingsLock();
s_base_settings_interface->DeleteValue(section, key);
QueueSettingsSave();
} }
void QtHost::SaveSettings() void QtHost::SaveSettings()
@ -324,13 +145,20 @@ void QtHost::SaveSettings()
s_settings_save_timer.release(); s_settings_save_timer.release();
} }
void QtHost::QueueSettingsSave() void Host::CommitBaseSettingChanges()
{ {
if (!QtHost::IsOnUIThread())
{
QtHost::RunOnUIThread(&Host::CommitBaseSettingChanges);
return;
}
auto lock = Host::GetSettingsLock();
if (s_settings_save_timer) if (s_settings_save_timer)
return; return;
s_settings_save_timer = std::make_unique<QTimer>(); s_settings_save_timer = std::make_unique<QTimer>();
s_settings_save_timer->connect(s_settings_save_timer.get(), &QTimer::timeout, SaveSettings); s_settings_save_timer->connect(s_settings_save_timer.get(), &QTimer::timeout, &QtHost::SaveSettings);
s_settings_save_timer->setSingleShot(true); s_settings_save_timer->setSingleShot(true);
s_settings_save_timer->start(SETTINGS_SAVE_DELAY); s_settings_save_timer->start(SETTINGS_SAVE_DELAY);
} }
@ -345,6 +173,12 @@ bool QtHost::InNoGUIMode()
return s_nogui_mode; return s_nogui_mode;
} }
bool QtHost::IsOnUIThread()
{
QThread* ui_thread = qApp->thread();
return (QThread::currentThread() == ui_thread);
}
void QtHost::RunOnUIThread(const std::function<void()>& func, bool block /*= false*/) void QtHost::RunOnUIThread(const std::function<void()>& func, bool block /*= false*/)
{ {
// main window always exists, so it's fine to attach it to that. // main window always exists, so it's fine to attach it to that.
@ -353,6 +187,21 @@ void QtHost::RunOnUIThread(const std::function<void()>& func, bool block /*= fal
Q_ARG(const std::function<void()>&, func)); Q_ARG(const std::function<void()>&, func));
} }
bool Host::RequestResetSettings(bool folders, bool core, bool controllers, bool hotkeys, bool ui)
{
{
auto lock = Host::GetSettingsLock();
CommonHost::SetDefaultSettings(*s_base_settings_interface.get(), folders, core, controllers, hotkeys, ui);
}
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
if (folders)
g_emu_thread->updateEmuFolders();
return true;
}
QString QtHost::GetAppNameAndVersion() QString QtHost::GetAppNameAndVersion()
{ {
QString ret; QString ret;
@ -725,11 +574,7 @@ int main(int argc, char* argv[])
// Bail out if we can't find any config. // Bail out if we can't find any config.
if (!QtHost::InitializeConfig()) if (!QtHost::InitializeConfig())
{
// NOTE: No point translating this, because no config means the language won't be loaded anyway.
QMessageBox::critical(nullptr, QStringLiteral("Error"), QStringLiteral("Failed to initialize config."));
return EXIT_FAILURE; return EXIT_FAILURE;
}
// Set theme before creating any windows. // Set theme before creating any windows.
MainWindow::updateApplicationTheme(); MainWindow::updateApplicationTheme();

View File

@ -46,6 +46,9 @@ namespace QtHost
/// Sets NoGUI mode (implys batch mode, does not display main window, exits on shutdown). /// Sets NoGUI mode (implys batch mode, does not display main window, exits on shutdown).
bool InNoGUIMode(); bool InNoGUIMode();
/// Returns true if the calling thread is the UI thread.
bool IsOnUIThread();
/// Executes a function on the UI thread. /// Executes a function on the UI thread.
void RunOnUIThread(const std::function<void()>& func, bool block = false); void RunOnUIThread(const std::function<void()>& func, bool block = false);
@ -58,17 +61,6 @@ namespace QtHost
/// Returns the base path for resources. This may be : prefixed, if we're using embedded resources. /// Returns the base path for resources. This may be : prefixed, if we're using embedded resources.
QString GetResourcesBasePath(); QString GetResourcesBasePath();
/// Thread-safe settings access.
void SetBaseBoolSettingValue(const char* section, const char* key, bool value);
void SetBaseIntSettingValue(const char* section, const char* key, int value);
void SetBaseFloatSettingValue(const char* section, const char* key, float value);
void SetBaseStringSettingValue(const char* section, const char* key, const char* value);
void SetBaseStringListSettingValue(const char* section, const char* key, const std::vector<std::string>& values);
bool AddBaseValueToStringList(const char* section, const char* key, const char* value);
bool RemoveBaseValueFromStringList(const char* section, const char* key, const char* value);
void RemoveBaseSettingValue(const char* section, const char* key);
void QueueSettingsSave();
/// VM state, safe to access on UI thread. /// VM state, safe to access on UI thread.
bool IsVMValid(); bool IsVMValid();
bool IsVMPaused(); bool IsVMPaused();

View File

@ -613,7 +613,8 @@ namespace SettingWidgetBinder
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() { Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const bool new_value = Accessor::getBoolValue(widget); const bool new_value = Accessor::getBoolValue(widget);
QtHost::SetBaseBoolSettingValue(section.c_str(), key.c_str(), new_value); Host::SetBaseBoolSettingValue(section.c_str(), key.c_str(), new_value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
}); });
} }
@ -653,7 +654,8 @@ namespace SettingWidgetBinder
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), option_offset]() { Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), option_offset]() {
const int new_value = Accessor::getIntValue(widget); const int new_value = Accessor::getIntValue(widget);
QtHost::SetBaseIntSettingValue(section.c_str(), key.c_str(), new_value + option_offset); Host::SetBaseIntSettingValue(section.c_str(), key.c_str(), new_value + option_offset);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
}); });
} }
@ -692,7 +694,8 @@ namespace SettingWidgetBinder
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() { Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const float new_value = Accessor::getFloatValue(widget); const float new_value = Accessor::getFloatValue(widget);
QtHost::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value); Host::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
}); });
} }
@ -732,7 +735,8 @@ namespace SettingWidgetBinder
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), range]() { Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), range]() {
const float new_value = (static_cast<float>(Accessor::getIntValue(widget)) / range); const float new_value = (static_cast<float>(Accessor::getIntValue(widget)) / range);
QtHost::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value); Host::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
}); });
} }
@ -773,10 +777,11 @@ namespace SettingWidgetBinder
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() { Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const QString new_value = Accessor::getStringValue(widget); const QString new_value = Accessor::getStringValue(widget);
if (!new_value.isEmpty()) if (!new_value.isEmpty())
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), new_value.toUtf8().constData()); Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), new_value.toUtf8().constData());
else else
QtHost::RemoveBaseSettingValue(section.c_str(), key.c_str()); Host::RemoveBaseSettingValue(section.c_str(), key.c_str());
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
}); });
} }
@ -835,7 +840,8 @@ namespace SettingWidgetBinder
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), to_string_function]() { Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), to_string_function]() {
const DataType value = static_cast<DataType>(static_cast<UnderlyingType>(Accessor::getIntValue(widget))); const DataType value = static_cast<DataType>(static_cast<UnderlyingType>(Accessor::getIntValue(widget)));
const char* string_value = to_string_function(value); const char* string_value = to_string_function(value);
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), string_value); Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), string_value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
}); });
} }
@ -896,7 +902,8 @@ namespace SettingWidgetBinder
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), enum_names]() { Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), enum_names]() {
const UnderlyingType value = static_cast<UnderlyingType>(Accessor::getIntValue(widget)); const UnderlyingType value = static_cast<UnderlyingType>(Accessor::getIntValue(widget));
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), enum_names[value]); Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), enum_names[value]);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
}); });
} }
@ -959,7 +966,8 @@ namespace SettingWidgetBinder
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), enum_values]() { Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), enum_values]() {
const int value = Accessor::getIntValue(widget); const int value = Accessor::getIntValue(widget);
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), enum_values[value]); Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), enum_values[value]);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
}); });
} }
@ -996,13 +1004,14 @@ namespace SettingWidgetBinder
if (!new_value.empty()) if (!new_value.empty())
{ {
std::string relative_path(Path::MakeRelative(new_value, EmuFolders::DataRoot)); std::string relative_path(Path::MakeRelative(new_value, EmuFolders::DataRoot));
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), relative_path.c_str()); Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), relative_path.c_str());
} }
else else
{ {
QtHost::RemoveBaseSettingValue(section.c_str(), key.c_str()); Host::RemoveBaseSettingValue(section.c_str(), key.c_str());
} }
Host::CommitBaseSettingChanges();
g_emu_thread->updateEmuFolders(); g_emu_thread->updateEmuFolders();
}); });

View File

@ -130,7 +130,8 @@ void BIOSSettingsWidget::listRefreshed(const QVector<BIOSInfo>& items)
void BIOSSettingsWidget::listItemChanged(const QTreeWidgetItem* current, const QTreeWidgetItem* previous) void BIOSSettingsWidget::listItemChanged(const QTreeWidgetItem* current, const QTreeWidgetItem* previous)
{ {
QtHost::SetBaseStringSettingValue("Filenames", "BIOS", current->text(0).toUtf8().constData()); Host::SetBaseStringSettingValue("Filenames", "BIOS", current->text(0).toUtf8().constData());
Host::CommitBaseSettingChanges();
} }
BIOSSettingsWidget::RefreshThread::RefreshThread(BIOSSettingsWidget* parent, const QString& directory) BIOSSettingsWidget::RefreshThread::RefreshThread(BIOSSettingsWidget* parent, const QString& directory)

View File

@ -199,13 +199,17 @@ void ControllerBindingWidget::onClearBindingsClicked()
{ {
auto lock = Host::GetSettingsLock(); auto lock = Host::GetSettingsLock();
PAD::ClearPortBindings(*Host::Internal::GetBaseSettingsLayer(), m_port_number); PAD::ClearPortBindings(*Host::Internal::GetBaseSettingsLayer(), m_port_number);
Host::CommitBaseSettingChanges();
} }
else else
{ {
PAD::ClearPortBindings(*m_dialog->getProfileSettingsInterface(), m_port_number); PAD::ClearPortBindings(*m_dialog->getProfileSettingsInterface(), m_port_number);
m_dialog->getProfileSettingsInterface()->Save();
} }
saveAndRefresh(); // force a refresh after clearing
g_emu_thread->applySettings();
onTypeChanged();
} }
void ControllerBindingWidget::doDeviceAutomaticBinding(const QString& device) void ControllerBindingWidget::doDeviceAutomaticBinding(const QString& device)
@ -223,26 +227,26 @@ void ControllerBindingWidget::doDeviceAutomaticBinding(const QString& device)
{ {
auto lock = Host::GetSettingsLock(); auto lock = Host::GetSettingsLock();
result = PAD::MapController(*Host::Internal::GetBaseSettingsLayer(), m_port_number, mapping); result = PAD::MapController(*Host::Internal::GetBaseSettingsLayer(), m_port_number, mapping);
if (result)
Host::CommitBaseSettingChanges();
} }
else else
{ {
result = PAD::MapController(*m_dialog->getProfileSettingsInterface(), m_port_number, mapping); result = PAD::MapController(*m_dialog->getProfileSettingsInterface(), m_port_number, mapping);
if (result)
{
m_dialog->getProfileSettingsInterface()->Save(); m_dialog->getProfileSettingsInterface()->Save();
g_emu_thread->reloadInputBindings(); g_emu_thread->reloadInputBindings();
} }
}
// force a refresh after mapping // force a refresh after mapping
if (result) if (result)
saveAndRefresh();
}
void ControllerBindingWidget::saveAndRefresh()
{ {
onTypeChanged();
QtHost::QueueSettingsSave();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
onTypeChanged();
}
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View File

@ -58,7 +58,6 @@ private:
void populateControllerTypes(); void populateControllerTypes();
void updateHeaderToolButtons(); void updateHeaderToolButtons();
void doDeviceAutomaticBinding(const QString& device); void doDeviceAutomaticBinding(const QString& device);
void saveAndRefresh();
Ui::ControllerBindingWidget m_ui; Ui::ControllerBindingWidget m_ui;

View File

@ -63,7 +63,8 @@ namespace ControllerSettingWidgetBinder
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() { Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const bool new_value = Accessor::getBoolValue(widget); const bool new_value = Accessor::getBoolValue(widget);
QtHost::SetBaseBoolSettingValue(section.c_str(), key.c_str(), new_value); Host::SetBaseBoolSettingValue(section.c_str(), key.c_str(), new_value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
}); });
} }
@ -94,7 +95,8 @@ namespace ControllerSettingWidgetBinder
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() { Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const float new_value = Accessor::getFloatValue(widget); const float new_value = Accessor::getFloatValue(widget);
QtHost::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value); Host::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
}); });
} }
@ -127,7 +129,8 @@ namespace ControllerSettingWidgetBinder
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), range]() { Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), range]() {
const float new_value = (static_cast<float>(Accessor::getIntValue(widget)) / range); const float new_value = (static_cast<float>(Accessor::getIntValue(widget)) / range);
QtHost::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value); Host::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
}); });
} }
@ -166,10 +169,11 @@ namespace ControllerSettingWidgetBinder
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() { Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const QString new_value = Accessor::getStringValue(widget); const QString new_value = Accessor::getStringValue(widget);
if (!new_value.isEmpty()) if (!new_value.isEmpty())
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), new_value.toUtf8().constData()); Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), new_value.toUtf8().constData());
else else
QtHost::RemoveBaseSettingValue(section.c_str(), key.c_str()); Host::RemoveBaseSettingValue(section.c_str(), key.c_str());
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
}); });
} }

View File

@ -22,6 +22,7 @@
#include "Settings/ControllerBindingWidgets.h" #include "Settings/ControllerBindingWidgets.h"
#include "Settings/HotkeySettingsWidget.h" #include "Settings/HotkeySettingsWidget.h"
#include "pcsx2/Frontend/CommonHost.h"
#include "pcsx2/Frontend/INISettingsInterface.h" #include "pcsx2/Frontend/INISettingsInterface.h"
#include "pcsx2/PAD/Host/PAD.h" #include "pcsx2/PAD/Host/PAD.h"
#include "pcsx2/Sio.h" #include "pcsx2/Sio.h"
@ -162,7 +163,7 @@ void ControllerSettingsDialog::onLoadProfileClicked()
{ {
auto lock = Host::GetSettingsLock(); auto lock = Host::GetSettingsLock();
PAD::CopyConfiguration(Host::Internal::GetBaseSettingsLayer(), *m_profile_interface, true, true, false); PAD::CopyConfiguration(Host::Internal::GetBaseSettingsLayer(), *m_profile_interface, true, true, false);
QtHost::QueueSettingsSave(); Host::CommitBaseSettingChanges();
} }
g_emu_thread->applySettings(); g_emu_thread->applySettings();
@ -206,9 +207,8 @@ void ControllerSettingsDialog::onRestoreDefaultsClicked()
// actually restore it // actually restore it
{ {
auto lock = Host::GetSettingsLock(); auto lock = Host::GetSettingsLock();
PAD::SetDefaultControllerConfig(*Host::Internal::GetBaseSettingsLayer()); CommonHost::SetDefaultSettings(*Host::Internal::GetBaseSettingsLayer(), false, false, true, true, false);
PAD::SetDefaultHotkeyConfig(*Host::Internal::GetBaseSettingsLayer()); Host::CommitBaseSettingChanges();
QtHost::QueueSettingsSave();
} }
g_emu_thread->applySettings(); g_emu_thread->applySettings();
@ -295,7 +295,8 @@ void ControllerSettingsDialog::setBoolValue(const char* section, const char* key
} }
else else
{ {
QtHost::SetBaseBoolSettingValue(section, key, value); Host::SetBaseBoolSettingValue(section, key, value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
} }
} }
@ -310,7 +311,8 @@ void ControllerSettingsDialog::setIntValue(const char* section, const char* key,
} }
else else
{ {
QtHost::SetBaseIntSettingValue(section, key, value); Host::SetBaseIntSettingValue(section, key, value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
} }
} }
@ -325,7 +327,8 @@ void ControllerSettingsDialog::setStringValue(const char* section, const char* k
} }
else else
{ {
QtHost::SetBaseStringSettingValue(section, key, value); Host::SetBaseStringSettingValue(section, key, value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
} }
} }
@ -340,7 +343,8 @@ void ControllerSettingsDialog::clearSettingValue(const char* section, const char
} }
else else
{ {
QtHost::RemoveBaseSettingValue(section, key); Host::RemoveBaseSettingValue(section, key);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
} }
} }

View File

@ -65,9 +65,10 @@ GameListSettingsWidget::~GameListSettingsWidget() = default;
bool GameListSettingsWidget::addExcludedPath(const std::string& path) bool GameListSettingsWidget::addExcludedPath(const std::string& path)
{ {
if (!QtHost::AddBaseValueToStringList("GameList", "ExcludedPaths", path.c_str())) if (!Host::AddBaseValueToStringList("GameList", "ExcludedPaths", path.c_str()))
return false; return false;
Host::CommitBaseSettingChanges();
m_ui.excludedPaths->addItem(QString::fromStdString(path)); m_ui.excludedPaths->addItem(QString::fromStdString(path));
g_main_window->refreshGameList(false); g_main_window->refreshGameList(false);
return true; return true;
@ -107,14 +108,15 @@ void GameListSettingsWidget::addPathToTable(const std::string& path, bool recurs
const std::string path(item->text().toStdString()); const std::string path(item->text().toStdString());
if (state == Qt::Checked) if (state == Qt::Checked)
{ {
QtHost::RemoveBaseValueFromStringList("GameList", "Paths", path.c_str()); Host::RemoveBaseValueFromStringList("GameList", "Paths", path.c_str());
QtHost::AddBaseValueToStringList("GameList", "RecursivePaths", path.c_str()); Host::AddBaseValueToStringList("GameList", "RecursivePaths", path.c_str());
} }
else else
{ {
QtHost::RemoveBaseValueFromStringList("GameList", "RecursivePaths", path.c_str()); Host::RemoveBaseValueFromStringList("GameList", "RecursivePaths", path.c_str());
QtHost::AddBaseValueToStringList("GameList", "Paths", path.c_str()); Host::AddBaseValueToStringList("GameList", "Paths", path.c_str());
} }
Host::CommitBaseSettingChanges();
}); });
} }
@ -138,8 +140,9 @@ void GameListSettingsWidget::refreshDirectoryList()
void GameListSettingsWidget::addSearchDirectory(const QString& path, bool recursive) void GameListSettingsWidget::addSearchDirectory(const QString& path, bool recursive)
{ {
const std::string spath(path.toStdString()); const std::string spath(path.toStdString());
QtHost::RemoveBaseValueFromStringList("GameList", recursive ? "Paths" : "RecursivePaths", spath.c_str()); Host::RemoveBaseValueFromStringList("GameList", recursive ? "Paths" : "RecursivePaths", spath.c_str());
QtHost::AddBaseValueToStringList("GameList", recursive ? "RecursivePaths" : "Paths", spath.c_str()); Host::AddBaseValueToStringList("GameList", recursive ? "RecursivePaths" : "Paths", spath.c_str());
Host::CommitBaseSettingChanges();
refreshDirectoryList(); refreshDirectoryList();
g_main_window->refreshGameList(false); g_main_window->refreshGameList(false);
} }
@ -147,12 +150,13 @@ void GameListSettingsWidget::addSearchDirectory(const QString& path, bool recurs
void GameListSettingsWidget::removeSearchDirectory(const QString& path) void GameListSettingsWidget::removeSearchDirectory(const QString& path)
{ {
const std::string spath(path.toStdString()); const std::string spath(path.toStdString());
if (!QtHost::RemoveBaseValueFromStringList("GameList", "Paths", spath.c_str()) && if (!Host::RemoveBaseValueFromStringList("GameList", "Paths", spath.c_str()) &&
!QtHost::RemoveBaseValueFromStringList("GameList", "RecursivePaths", spath.c_str())) !Host::RemoveBaseValueFromStringList("GameList", "RecursivePaths", spath.c_str()))
{ {
return; return;
} }
Host::CommitBaseSettingChanges();
refreshDirectoryList(); refreshDirectoryList();
g_main_window->refreshGameList(false); g_main_window->refreshGameList(false);
} }
@ -228,7 +232,9 @@ void GameListSettingsWidget::onRemoveExcludedPathButtonClicked()
if (!item) if (!item)
return; return;
QtHost::RemoveBaseValueFromStringList("GameList", "ExcludedPaths", item->text().toUtf8().constData()); if (Host::RemoveBaseValueFromStringList("GameList", "ExcludedPaths", item->text().toUtf8().constData()))
Host::CommitBaseSettingChanges();
delete item; delete item;
g_main_window->refreshGameList(false); g_main_window->refreshGameList(false);

View File

@ -259,9 +259,10 @@ void InputBindingDialog::saveListToSettings()
else else
{ {
if (!m_bindings.empty()) if (!m_bindings.empty())
QtHost::SetBaseStringListSettingValue(m_section_name.c_str(), m_key_name.c_str(), m_bindings); Host::SetBaseStringListSettingValue(m_section_name.c_str(), m_key_name.c_str(), m_bindings);
else else
QtHost::RemoveBaseSettingValue(m_section_name.c_str(), m_key_name.c_str()); Host::RemoveBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
Host::CommitBaseSettingChanges();
g_emu_thread->reloadInputBindings(); g_emu_thread->reloadInputBindings();
} }
} }

View File

@ -236,7 +236,8 @@ void InputBindingWidget::setNewBinding()
} }
else else
{ {
QtHost::SetBaseStringSettingValue(m_section_name.c_str(), m_key_name.c_str(), new_binding.c_str()); Host::SetBaseStringSettingValue(m_section_name.c_str(), m_key_name.c_str(), new_binding.c_str());
Host::CommitBaseSettingChanges();
g_emu_thread->reloadInputBindings(); g_emu_thread->reloadInputBindings();
} }
} }
@ -256,7 +257,8 @@ void InputBindingWidget::clearBinding()
} }
else else
{ {
QtHost::RemoveBaseSettingValue(m_section_name.c_str(), m_key_name.c_str()); Host::RemoveBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
Host::CommitBaseSettingChanges();
g_emu_thread->reloadInputBindings(); g_emu_thread->reloadInputBindings();
} }
reloadBinding(); reloadBinding();
@ -413,7 +415,8 @@ void InputVibrationBindingWidget::setKey(ControllerSettingsDialog* dialog, std::
void InputVibrationBindingWidget::clearBinding() void InputVibrationBindingWidget::clearBinding()
{ {
m_binding = {}; m_binding = {};
QtHost::RemoveBaseSettingValue(m_section_name.c_str(), m_key_name.c_str()); Host::RemoveBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
Host::CommitBaseSettingChanges();
g_emu_thread->reloadInputBindings(); g_emu_thread->reloadInputBindings();
setText(QString()); setText(QString());
} }
@ -448,7 +451,8 @@ void InputVibrationBindingWidget::onClicked()
const QString new_value(input_dialog.textValue()); const QString new_value(input_dialog.textValue());
m_binding = new_value.toStdString(); m_binding = new_value.toStdString();
QtHost::SetBaseStringSettingValue(m_section_name.c_str(), m_key_name.c_str(), m_binding.c_str()); Host::SetBaseStringSettingValue(m_section_name.c_str(), m_key_name.c_str(), m_binding.c_str());
Host::CommitBaseSettingChanges();
setText(new_value); setText(new_value);
} }

View File

@ -146,9 +146,6 @@ void SettingsDialog::setupUi(const GameList::Entry* game)
connect(m_ui.settingsCategory, &QListWidget::currentRowChanged, this, &SettingsDialog::onCategoryCurrentRowChanged); connect(m_ui.settingsCategory, &QListWidget::currentRowChanged, this, &SettingsDialog::onCategoryCurrentRowChanged);
connect(m_ui.closeButton, &QPushButton::clicked, this, &SettingsDialog::accept); connect(m_ui.closeButton, &QPushButton::clicked, this, &SettingsDialog::accept);
connect(m_ui.restoreDefaultsButton, &QPushButton::clicked, this, &SettingsDialog::onRestoreDefaultsClicked); connect(m_ui.restoreDefaultsButton, &QPushButton::clicked, this, &SettingsDialog::onRestoreDefaultsClicked);
// TODO: Remove this once they're implemented.
m_ui.restoreDefaultsButton->setVisible(false);
} }
SettingsDialog::~SettingsDialog() SettingsDialog::~SettingsDialog()
@ -164,6 +161,11 @@ void SettingsDialog::closeEvent(QCloseEvent*)
deleteLater(); deleteLater();
} }
QString SettingsDialog::getCategory() const
{
return m_ui.settingsCategory->item(m_ui.settingsCategory->currentRow())->text();
}
void SettingsDialog::setCategory(const char* category) void SettingsDialog::setCategory(const char* category)
{ {
// the titles in the category list will be translated. // the titles in the category list will be translated.
@ -188,14 +190,20 @@ void SettingsDialog::onCategoryCurrentRowChanged(int row)
void SettingsDialog::onRestoreDefaultsClicked() void SettingsDialog::onRestoreDefaultsClicked()
{ {
if (QMessageBox::question(this, tr("Confirm Restore Defaults"), QMessageBox msgbox(this);
tr("Are you sure you want to restore the default settings? Any preferences will be lost."), QMessageBox::Yes, msgbox.setIcon(QMessageBox::Question);
QMessageBox::No) != QMessageBox::Yes) msgbox.setWindowTitle(tr("Confirm Restore Defaults"));
{ msgbox.setText(tr("Are you sure you want to restore the default settings? Any preferences will be lost."));
return;
}
// TODO QCheckBox* ui_cb = new QCheckBox(tr("Reset UI Settings"), &msgbox);
msgbox.setCheckBox(ui_cb);
msgbox.addButton(QMessageBox::Yes);
msgbox.addButton(QMessageBox::No);
msgbox.setDefaultButton(QMessageBox::Yes);
if (msgbox.exec() != QMessageBox::Yes)
return;
g_main_window->resetSettings(ui_cb->isChecked());
} }
void SettingsDialog::addWidget(QWidget* widget, QString title, QString icon, QString help_text) void SettingsDialog::addWidget(QWidget* widget, QString title, QString icon, QString help_text)
@ -376,7 +384,8 @@ void SettingsDialog::setBoolSettingValue(const char* section, const char* key, s
} }
else else
{ {
value.has_value() ? QtHost::SetBaseBoolSettingValue(section, key, value.value()) : QtHost::RemoveBaseSettingValue(section, key); value.has_value() ? Host::SetBaseBoolSettingValue(section, key, value.value()) : Host::RemoveBaseSettingValue(section, key);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
} }
} }
@ -391,7 +400,8 @@ void SettingsDialog::setIntSettingValue(const char* section, const char* key, st
} }
else else
{ {
value.has_value() ? QtHost::SetBaseIntSettingValue(section, key, value.value()) : QtHost::RemoveBaseSettingValue(section, key); value.has_value() ? Host::SetBaseIntSettingValue(section, key, value.value()) : Host::RemoveBaseSettingValue(section, key);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
} }
} }
@ -406,7 +416,8 @@ void SettingsDialog::setFloatSettingValue(const char* section, const char* key,
} }
else else
{ {
value.has_value() ? QtHost::SetBaseFloatSettingValue(section, key, value.value()) : QtHost::RemoveBaseSettingValue(section, key); value.has_value() ? Host::SetBaseFloatSettingValue(section, key, value.value()) : Host::RemoveBaseSettingValue(section, key);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
} }
} }
@ -421,7 +432,8 @@ void SettingsDialog::setStringSettingValue(const char* section, const char* key,
} }
else else
{ {
value.has_value() ? QtHost::SetBaseStringSettingValue(section, key, value.value()) : QtHost::RemoveBaseSettingValue(section, key); value.has_value() ? Host::SetBaseStringSettingValue(section, key, value.value()) : Host::RemoveBaseSettingValue(section, key);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings(); g_emu_thread->applySettings();
} }
} }

View File

@ -72,6 +72,7 @@ public:
void registerWidgetHelp(QObject* object, QString title, QString recommended_value, QString text); void registerWidgetHelp(QObject* object, QString title, QString recommended_value, QString text);
bool eventFilter(QObject* object, QEvent* event) override; bool eventFilter(QObject* object, QEvent* event) override;
QString getCategory() const;
void setCategory(const char* category); void setCategory(const char* category);
// Helper functions for reading effective setting values (from game -> global settings). // Helper functions for reading effective setting values (from game -> global settings).

View File

@ -1063,8 +1063,10 @@ endif()
if(PCSX2_CORE) if(PCSX2_CORE)
list(APPEND pcsx2FrontendSources list(APPEND pcsx2FrontendSources
Frontend/CommonHost.cpp
Frontend/FullscreenUI.cpp Frontend/FullscreenUI.cpp
Frontend/GameList.cpp Frontend/GameList.cpp
Frontend/HostSettings.cpp
Frontend/ImGuiFullscreen.cpp Frontend/ImGuiFullscreen.cpp
Frontend/INISettingsInterface.cpp Frontend/INISettingsInterface.cpp
Frontend/InputManager.cpp Frontend/InputManager.cpp
@ -1072,10 +1074,10 @@ if(PCSX2_CORE)
Frontend/LayeredSettingsInterface.cpp Frontend/LayeredSettingsInterface.cpp
Frontend/LogSink.cpp Frontend/LogSink.cpp
GSDumpReplayer.cpp GSDumpReplayer.cpp
HostSettings.cpp
VMManager.cpp VMManager.cpp
) )
list(APPEND pcsx2FrontendHeaders list(APPEND pcsx2FrontendHeaders
Frontend/CommonHost.h
Frontend/FullscreenUI.h Frontend/FullscreenUI.h
Frontend/GameList.h Frontend/GameList.h
Frontend/ImGuiFullscreen.h Frontend/ImGuiFullscreen.h

View File

@ -1048,10 +1048,9 @@ namespace EmuFolders
extern std::string InputProfiles; extern std::string InputProfiles;
// Assumes that AppRoot and DataRoot have been initialized. // Assumes that AppRoot and DataRoot have been initialized.
void SetDefaults(); void SetDefaults(SettingsInterface& si);
bool EnsureFoldersExist();
void LoadConfig(SettingsInterface& si); void LoadConfig(SettingsInterface& si);
void Save(SettingsInterface& si); bool EnsureFoldersExist();
} // namespace EmuFolders } // namespace EmuFolders
///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,203 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "common/Assertions.h"
#include "common/CrashHandler.h"
#include "common/FileSystem.h"
#include "common/Path.h"
#include "Frontend/CommonHost.h"
#include "Frontend/LayeredSettingsInterface.h"
#include "GS.h"
#include "GS/Renderers/HW/GSTextureReplacements.h"
#include "Host.h"
#include "HostSettings.h"
#include "MemoryCardFile.h"
#include "PAD/Host/PAD.h"
#include "Sio.h"
#include "VMManager.h"
#ifdef _WIN32
#include "common/RedtapeWindows.h"
#include <KnownFolders.h>
#include <ShlObj.h>
#endif
static constexpr u32 SETTINGS_VERSION = 1;
namespace CommonHost
{
static void SetAppRoot();
static void SetResourcesDirectory();
static bool ShouldUsePortableMode();
static void SetDataDirectory();
static void SetCommonDefaultSettings(SettingsInterface& si);
} // namespace CommonHost
bool CommonHost::InitializeCriticalFolders()
{
SetAppRoot();
SetResourcesDirectory();
SetDataDirectory();
// logging of directories in case something goes wrong super early
Console.WriteLn("AppRoot Directory: %s", EmuFolders::AppRoot.c_str());
Console.WriteLn("DataRoot Directory: %s", EmuFolders::DataRoot.c_str());
Console.WriteLn("Resources Directory: %s", EmuFolders::Resources.c_str());
// allow SetDataDirectory() to change settings directory (if we want to split config later on)
if (EmuFolders::Settings.empty())
EmuFolders::Settings = Path::Combine(EmuFolders::DataRoot, "inis");
// Write crash dumps to the data directory, since that'll be accessible for certain.
CrashHandler::SetWriteDirectory(EmuFolders::DataRoot);
// the resources directory should exist, bail out if not
if (!FileSystem::DirectoryExists(EmuFolders::Resources.c_str()))
{
Console.Error("Resources directory is missing.");
return false;
}
return true;
}
void CommonHost::SetAppRoot()
{
std::string program_path(FileSystem::GetProgramPath());
Console.WriteLn("Program Path: %s", program_path.c_str());
EmuFolders::AppRoot = Path::Canonicalize(Path::GetDirectory(program_path));
}
void CommonHost::SetResourcesDirectory()
{
#ifndef __APPLE__
// On Windows/Linux, these are in the binary directory.
EmuFolders::Resources = Path::Combine(EmuFolders::AppRoot, "resources");
#else
// On macOS, this is in the bundle resources directory.
EmuFolders::Resources = Path::Canonicalize(Path::Combine(EmuFolders::AppRoot, "../Resources"));
#endif
}
bool CommonHost::ShouldUsePortableMode()
{
// Check whether portable.ini exists in the program directory.
return FileSystem::FileExists(Path::Combine(EmuFolders::AppRoot, "portable.ini").c_str());
}
void CommonHost::SetDataDirectory()
{
if (ShouldUsePortableMode())
{
EmuFolders::DataRoot = EmuFolders::AppRoot;
return;
}
#if defined(_WIN32)
// On Windows, use My Documents\PCSX2 to match old installs.
PWSTR documents_directory;
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &documents_directory)))
{
if (std::wcslen(documents_directory) > 0)
EmuFolders::DataRoot = Path::Combine(StringUtil::WideStringToUTF8String(documents_directory), "PCSX2");
CoTaskMemFree(documents_directory);
}
#elif defined(__linux__)
// Use $XDG_CONFIG_HOME/PCSX2 if it exists.
const char* xdg_config_home = getenv("XDG_CONFIG_HOME");
if (xdg_config_home && Path::IsAbsolute(xdg_config_home))
{
EmuFolders::DataRoot = Path::Combine(xdg_config_home, "PCSX2");
}
else
{
// Use ~/PCSX2 for non-XDG, and ~/.config/PCSX2 for XDG.
// Maybe we should drop the former when Qt goes live.
const char* home_dir = getenv("HOME");
if (home_dir)
{
#ifndef XDG_STD
EmuFolders::DataRoot = Path::Combine(home_dir, "PCSX2");
#else
// ~/.config should exist, but just in case it doesn't and this is a fresh profile..
const std::string config_dir(Path::Combine(home_dir, ".config"));
if (!FileSystem::DirectoryExists(config_dir.c_str()))
FileSystem::CreateDirectoryPath(config_dir.c_str(), false);
EmuFolders::DataRoot = Path::Combine(config_dir, "PCSX2");
#endif
}
}
#elif defined(__APPLE__)
static constexpr char MAC_DATA_DIR[] = "Library/Application Support/PCSX2";
const char* home_dir = getenv("HOME");
if (home_dir)
EmuFolders::DataRoot = Path::Combine(home_dir, MAC_DATA_DIR);
#endif
// make sure it exists
if (!EmuFolders::DataRoot.empty() && !FileSystem::DirectoryExists(EmuFolders::DataRoot.c_str()))
{
// we're in trouble if we fail to create this directory... but try to hobble on with portable
if (!FileSystem::CreateDirectoryPath(EmuFolders::DataRoot.c_str(), false))
EmuFolders::DataRoot.clear();
}
// couldn't determine the data directory? fallback to portable.
if (EmuFolders::DataRoot.empty())
EmuFolders::DataRoot = EmuFolders::AppRoot;
}
bool CommonHost::CheckSettingsVersion()
{
SettingsInterface* bsi = Host::Internal::GetBaseSettingsLayer();
uint settings_version;
return (bsi->GetUIntValue("UI", "SettingsVersion", &settings_version) && settings_version == SETTINGS_VERSION);
}
void CommonHost::LoadStartupSettings()
{
SettingsInterface* bsi = Host::Internal::GetBaseSettingsLayer();
EmuFolders::LoadConfig(*bsi);
EmuFolders::EnsureFoldersExist();
}
void CommonHost::SetDefaultSettings(SettingsInterface& si, bool folders, bool core, bool controllers, bool hotkeys, bool ui)
{
if (si.GetUIntValue("UI", "SettingsVersion", 0u) != SETTINGS_VERSION)
si.SetUIntValue("UI", "SettingsVersion", SETTINGS_VERSION);
if (folders)
EmuFolders::SetDefaults(si);
if (core)
{
VMManager::SetDefaultSettings(si);
SetCommonDefaultSettings(si);
}
if (controllers)
PAD::SetDefaultControllerConfig(si);
if (hotkeys)
PAD::SetDefaultHotkeyConfig(si);
if (ui)
Host::SetDefaultUISettings(si);
}
void CommonHost::SetCommonDefaultSettings(SettingsInterface& si)
{
// Nothing here yet.
}

View File

@ -0,0 +1,43 @@
/* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "common/Pcsx2Defs.h"
#include <string>
#include <mutex>
class SettingsInterface;
namespace Host
{
/// Sets host-specific default settings.
void SetDefaultUISettings(SettingsInterface& si);
} // namespace Host
namespace CommonHost
{
/// Initializes critical folders (AppRoot, DataRoot, Settings). Call once on startup.
bool InitializeCriticalFolders();
/// Checks settings version. Call once on startup. If it returns false, you should prompt the user to reset.
bool CheckSettingsVersion();
/// Loads early settings. Call once on startup.
void LoadStartupSettings();
/// Sets default settings for the specified categories.
void SetDefaultSettings(SettingsInterface& si, bool folders, bool core, bool controllers, bool hotkeys, bool ui);
} // namespace CommonHost

View File

@ -119,7 +119,9 @@ using ImGuiFullscreen::MenuImageButton;
using ImGuiFullscreen::NavButton; using ImGuiFullscreen::NavButton;
using ImGuiFullscreen::NavTitle; using ImGuiFullscreen::NavTitle;
using ImGuiFullscreen::OpenChoiceDialog; using ImGuiFullscreen::OpenChoiceDialog;
using ImGuiFullscreen::OpenConfirmMessageDialog;
using ImGuiFullscreen::OpenFileSelector; using ImGuiFullscreen::OpenFileSelector;
using ImGuiFullscreen::OpenInfoMessageDialog;
using ImGuiFullscreen::OpenInputStringDialog; using ImGuiFullscreen::OpenInputStringDialog;
using ImGuiFullscreen::PopPrimaryColor; using ImGuiFullscreen::PopPrimaryColor;
using ImGuiFullscreen::PushPrimaryColor; using ImGuiFullscreen::PushPrimaryColor;
@ -279,6 +281,7 @@ namespace FullscreenUI
static void DoLoadInputProfile(); static void DoLoadInputProfile();
static void DoSaveInputProfile(); static void DoSaveInputProfile();
static void DoSaveInputProfile(const std::string& name); static void DoSaveInputProfile(const std::string& name);
static void DoResetSettings();
static bool DrawToggleSetting(SettingsInterface* bsi, const char* title, const char* summary, const char* section, const char* key, static bool DrawToggleSetting(SettingsInterface* bsi, const char* title, const char* summary, const char* section, const char* key,
bool default_value, bool enabled = true, bool allow_tristate = true, float height = ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT, bool default_value, bool enabled = true, bool allow_tristate = true, float height = ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT,
@ -2022,6 +2025,13 @@ void FullscreenUI::DrawInterfaceSettingsPage()
DrawToggleSetting(bsi, ICON_FA_PLAY " Show Status Indicators", DrawToggleSetting(bsi, ICON_FA_PLAY " Show Status Indicators",
"Shows indicators when fast forwarding, pausing, and other abnormal states are active.", "EmuCore/GS", "OsdShowIndicators", true); "Shows indicators when fast forwarding, pausing, and other abnormal states are active.", "EmuCore/GS", "OsdShowIndicators", true);
MenuHeading("Operations");
if (MenuButton(ICON_FA_FOLDER_MINUS " Reset Settings", "Resets configuration to defaults (excluding controller settings).",
!IsEditingGameSettings(bsi)))
{
DoResetSettings();
}
EndMenuButtons(); EndMenuButtons();
} }
@ -3006,6 +3016,18 @@ void FullscreenUI::DoSaveInputProfile()
}); });
} }
void FullscreenUI::DoResetSettings()
{
OpenConfirmMessageDialog(ICON_FA_FOLDER_MINUS " Reset Settings",
"Are you sure you want to restore the default settings? Any preferences will be lost.", [](bool result) {
if (result)
{
Host::RunOnCPUThread([]() { Host::RequestResetSettings(false, true, false, false, false); });
ShowToast(std::string(), "Settings reset to defaults.");
}
});
}
void FullscreenUI::DrawControllerSettingsPage() void FullscreenUI::DrawControllerSettingsPage()
{ {
BeginMenuButtons(); BeginMenuButtons();
@ -4177,98 +4199,6 @@ void FullscreenUI::DrawAboutWindow()
ImGui::PopFont(); ImGui::PopFont();
} }
bool FullscreenUI::DrawErrorWindow(const char* message)
{
bool is_open = true;
ImGuiFullscreen::BeginLayout();
ImGui::SetNextWindowSize(LayoutScale(500.0f, 0.0f));
ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
ImGui::OpenPopup("ReportError");
ImGui::PushFont(g_large_font);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(10.0f, 10.0f));
if (ImGui::BeginPopupModal("ReportError", &is_open, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize))
{
ImGui::SetCursorPos(LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING, LAYOUT_MENU_BUTTON_Y_PADDING));
ImGui::TextWrapped("%s", message);
ImGui::GetCurrentWindow()->DC.CursorPos.y += LayoutScale(5.0f);
BeginMenuButtons();
if (ActiveButton(ICON_FA_WINDOW_CLOSE " Close", false))
{
ImGui::CloseCurrentPopup();
is_open = false;
}
EndMenuButtons();
ImGui::EndPopup();
}
ImGui::PopStyleVar(2);
ImGui::PopFont();
ImGuiFullscreen::EndLayout();
return !is_open;
}
bool FullscreenUI::DrawConfirmWindow(const char* message, bool* result)
{
bool is_open = true;
ImGuiFullscreen::BeginLayout();
ImGui::SetNextWindowSize(LayoutScale(500.0f, 0.0f));
ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
ImGui::OpenPopup("ConfirmMessage");
ImGui::PushFont(g_large_font);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(10.0f, 10.0f));
if (ImGui::BeginPopupModal("ConfirmMessage", &is_open, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize))
{
ImGui::SetCursorPos(LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING, LAYOUT_MENU_BUTTON_Y_PADDING));
ImGui::TextWrapped("%s", message);
ImGui::GetCurrentWindow()->DC.CursorPos.y += LayoutScale(5.0f);
BeginMenuButtons();
bool done = false;
if (ActiveButton(ICON_FA_CHECK " Yes", false))
{
*result = true;
done = true;
}
if (ActiveButton(ICON_FA_TIMES " No", false))
{
*result = false;
done = true;
}
if (done)
{
ImGui::CloseCurrentPopup();
is_open = false;
}
EndMenuButtons();
ImGui::EndPopup();
}
ImGui::PopStyleVar(2);
ImGui::PopFont();
ImGuiFullscreen::EndLayout();
return !is_open;
}
FullscreenUI::ProgressCallback::ProgressCallback(std::string name) FullscreenUI::ProgressCallback::ProgressCallback(std::string name)
: BaseProgressCallback() : BaseProgressCallback()
, m_name(std::move(name)) , m_name(std::move(name))

View File

@ -36,10 +36,6 @@ namespace FullscreenUI
void Shutdown(); void Shutdown();
void Render(); void Render();
// Returns true if the message has been dismissed.
bool DrawErrorWindow(const char* message);
bool DrawConfirmWindow(const char* message, bool* result);
class ProgressCallback final : public BaseProgressCallback class ProgressCallback final : public BaseProgressCallback
{ {
public: public:

View File

@ -15,6 +15,9 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "common/Assertions.h" #include "common/Assertions.h"
#include "common/CrashHandler.h"
#include "common/FileSystem.h"
#include "common/Path.h"
#include "Frontend/LayeredSettingsInterface.h" #include "Frontend/LayeredSettingsInterface.h"
#include "GS.h" #include "GS.h"
#include "GS/Renderers/HW/GSTextureReplacements.h" #include "GS/Renderers/HW/GSTextureReplacements.h"
@ -121,18 +124,24 @@ void Host::SetBaseStringListSettingValue(const char* section, const char* key, c
s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetStringList(section, key, values); s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetStringList(section, key, values);
} }
void Host::DeleteBaseSettingValue(const char* section, const char* key) bool Host::AddBaseValueToStringList(const char* section, const char* key, const char* value)
{
std::unique_lock lock(s_settings_mutex);
return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->AddToStringList(section, key, value);
}
bool Host::RemoveBaseValueFromStringList(const char* section, const char* key, const char* value)
{
std::unique_lock lock(s_settings_mutex);
return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->RemoveFromStringList(section, key, value);
}
void Host::RemoveBaseSettingValue(const char* section, const char* key)
{ {
std::unique_lock lock(s_settings_mutex); std::unique_lock lock(s_settings_mutex);
s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->DeleteValue(section, key); s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->DeleteValue(section, key);
} }
void Host::CommitBaseSettingChanges()
{
std::unique_lock lock(s_settings_mutex);
s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->Save();
}
std::string Host::GetStringSettingValue(const char* section, const char* key, const char* default_value /*= ""*/) std::string Host::GetStringSettingValue(const char* section, const char* key, const char* default_value /*= ""*/)
{ {
std::unique_lock lock(s_settings_mutex); std::unique_lock lock(s_settings_mutex);
@ -221,8 +230,7 @@ void Host::Internal::UpdateEmuFolders()
if (VMManager::HasValidVM()) if (VMManager::HasValidVM())
{ {
if (EmuFolders::Cheats != old_cheats_directory || if (EmuFolders::Cheats != old_cheats_directory || EmuFolders::CheatsWS != old_cheats_ws_directory ||
EmuFolders::CheatsWS != old_cheats_ws_directory ||
EmuFolders::CheatsNI != old_cheats_ni_directory) EmuFolders::CheatsNI != old_cheats_ni_directory)
{ {
VMManager::ReloadPatches(true, true); VMManager::ReloadPatches(true, true);

View File

@ -29,6 +29,7 @@ public:
~INISettingsInterface() override; ~INISettingsInterface() override;
const std::string& GetFileName() const { return m_filename; } const std::string& GetFileName() const { return m_filename; }
bool IsDirty() const { return m_dirty; }
bool Load(); bool Load();
bool Save() override; bool Save() override;

View File

@ -32,12 +32,16 @@
#include "HostDisplay.h" #include "HostDisplay.h"
#include "imgui_internal.h" #include "imgui_internal.h"
#include "misc/cpp/imgui_stdlib.h" #include "misc/cpp/imgui_stdlib.h"
#include <array>
#include <cmath> #include <cmath>
#include <deque> #include <deque>
#include <mutex> #include <mutex>
#include <variant>
namespace ImGuiFullscreen namespace ImGuiFullscreen
{ {
using MessageDialogCallbackVariant = std::variant<InfoMessageDialogCallback, ConfirmMessageDialogCallback>;
static std::optional<Common::RGBA8Image> LoadTextureImage(const char* path); static std::optional<Common::RGBA8Image> LoadTextureImage(const char* path);
static std::shared_ptr<HostDisplayTexture> UploadTexture(const char* path, const Common::RGBA8Image& image); static std::shared_ptr<HostDisplayTexture> UploadTexture(const char* path, const Common::RGBA8Image& image);
static void TextureLoaderThread(); static void TextureLoaderThread();
@ -45,6 +49,7 @@ namespace ImGuiFullscreen
static void DrawFileSelector(); static void DrawFileSelector();
static void DrawChoiceDialog(); static void DrawChoiceDialog();
static void DrawInputDialog(); static void DrawInputDialog();
static void DrawMessageDialog();
static void DrawBackgroundProgressDialogs(ImVec2& position, float spacing); static void DrawBackgroundProgressDialogs(ImVec2& position, float spacing);
static void DrawNotifications(ImVec2& position, float spacing); static void DrawNotifications(ImVec2& position, float spacing);
static void DrawToast(); static void DrawToast();
@ -110,6 +115,12 @@ namespace ImGuiFullscreen
static std::string s_input_dialog_ok_text; static std::string s_input_dialog_ok_text;
static InputStringDialogCallback s_input_dialog_callback; static InputStringDialogCallback s_input_dialog_callback;
static bool s_message_dialog_open = false;
static std::string s_message_dialog_title;
static std::string s_message_dialog_message;
static std::array<std::string, 3> s_message_dialog_buttons;
static MessageDialogCallbackVariant s_message_dialog_callback;
struct FileSelectorItem struct FileSelectorItem
{ {
FileSelectorItem() = default; FileSelectorItem() = default;
@ -215,6 +226,7 @@ void ImGuiFullscreen::Shutdown()
s_notifications.clear(); s_notifications.clear();
s_background_progress_dialogs.clear(); s_background_progress_dialogs.clear();
CloseInputDialog(); CloseInputDialog();
CloseMessageDialog();
s_choice_dialog_open = false; s_choice_dialog_open = false;
s_choice_dialog_checkable = false; s_choice_dialog_checkable = false;
s_choice_dialog_title = {}; s_choice_dialog_title = {};
@ -459,6 +471,7 @@ void ImGuiFullscreen::EndLayout()
DrawFileSelector(); DrawFileSelector();
DrawChoiceDialog(); DrawChoiceDialog();
DrawInputDialog(); DrawInputDialog();
DrawMessageDialog();
const float notification_margin = LayoutScale(10.0f); const float notification_margin = LayoutScale(10.0f);
const float spacing = LayoutScale(10.0f); const float spacing = LayoutScale(10.0f);
@ -1839,9 +1852,13 @@ void ImGuiFullscreen::DrawInputDialog()
ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
ImGui::OpenPopup(s_input_dialog_title.c_str()); ImGui::OpenPopup(s_input_dialog_title.c_str());
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f));
ImGui::PushFont(g_large_font); ImGui::PushFont(g_large_font);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING, LAYOUT_MENU_BUTTON_Y_PADDING));
ImGui::PushStyleColor(ImGuiCol_Text, UIPrimaryTextColor);
ImGui::PushStyleColor(ImGuiCol_TitleBg, UIPrimaryDarkColor);
ImGui::PushStyleColor(ImGuiCol_TitleBgActive, UIPrimaryColor);
ImGui::PushStyleColor(ImGuiCol_PopupBg, UIBackgroundColor);
bool is_open = true; bool is_open = true;
if (ImGui::BeginPopupModal(s_input_dialog_title.c_str(), &is_open, if (ImGui::BeginPopupModal(s_input_dialog_title.c_str(), &is_open,
@ -1884,8 +1901,9 @@ void ImGuiFullscreen::DrawInputDialog()
if (!is_open) if (!is_open)
CloseInputDialog(); CloseInputDialog();
ImGui::PopFont(); ImGui::PopStyleColor(4);
ImGui::PopStyleVar(2); ImGui::PopStyleVar(2);
ImGui::PopFont();
} }
void ImGuiFullscreen::CloseInputDialog() void ImGuiFullscreen::CloseInputDialog()
@ -1902,6 +1920,125 @@ void ImGuiFullscreen::CloseInputDialog()
s_input_dialog_callback = {}; s_input_dialog_callback = {};
} }
bool ImGuiFullscreen::IsMessageBoxDialogOpen()
{
return s_message_dialog_open;
}
void ImGuiFullscreen::OpenConfirmMessageDialog(
std::string title, std::string message, ConfirmMessageDialogCallback callback, std::string yes_button_text, std::string no_button_text)
{
CloseMessageDialog();
s_message_dialog_open = true;
s_message_dialog_title = std::move(title);
s_message_dialog_message = std::move(message);
s_message_dialog_callback = std::move(callback);
s_message_dialog_buttons[0] = std::move(yes_button_text);
s_message_dialog_buttons[1] = std::move(no_button_text);
}
void ImGuiFullscreen::OpenInfoMessageDialog(
std::string title, std::string message, InfoMessageDialogCallback callback, std::string button_text)
{
CloseMessageDialog();
s_message_dialog_open = true;
s_message_dialog_title = std::move(title);
s_message_dialog_message = std::move(message);
s_message_dialog_callback = std::move(callback);
s_message_dialog_buttons[0] = std::move(button_text);
}
void ImGuiFullscreen::OpenMessageDialog(std::string title, std::string message, MessageDialogCallback callback,
std::string first_button_text, std::string second_button_text, std::string third_button_text)
{
CloseMessageDialog();
s_message_dialog_open = true;
s_message_dialog_title = std::move(title);
s_message_dialog_message = std::move(message);
s_message_dialog_callback = std::move(callback);
s_message_dialog_buttons[0] = std::move(first_button_text);
s_message_dialog_buttons[1] = std::move(second_button_text);
s_message_dialog_buttons[2] = std::move(third_button_text);
}
void ImGuiFullscreen::CloseMessageDialog()
{
if (!s_message_dialog_open)
return;
s_message_dialog_open = false;
s_message_dialog_title = {};
s_message_dialog_message = {};
s_message_dialog_buttons = {};
s_message_dialog_callback = {};
}
void ImGuiFullscreen::DrawMessageDialog()
{
if (!s_message_dialog_open)
return;
const char* win_id = s_message_dialog_title.empty() ? "##messagedialog" : s_message_dialog_title.c_str();
ImGui::SetNextWindowSize(LayoutScale(700.0f, 0.0f));
ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
ImGui::OpenPopup(win_id);
ImGui::PushFont(g_large_font);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING, LAYOUT_MENU_BUTTON_Y_PADDING));
ImGui::PushStyleColor(ImGuiCol_Text, UIPrimaryTextColor);
ImGui::PushStyleColor(ImGuiCol_TitleBg, UIPrimaryDarkColor);
ImGui::PushStyleColor(ImGuiCol_TitleBgActive, UIPrimaryColor);
ImGui::PushStyleColor(ImGuiCol_PopupBg, UIBackgroundColor);
bool is_open = true;
const u32 flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
(s_message_dialog_title.empty() ? ImGuiWindowFlags_NoTitleBar : 0);
std::optional<s32> result;
if (ImGui::BeginPopupModal(win_id, &is_open, flags))
{
BeginMenuButtons();
ImGui::TextWrapped("%s", s_message_dialog_message.c_str());
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + LayoutScale(10.0f));
for (s32 button_index = 0; button_index < static_cast<s32>(s_message_dialog_buttons.size()); button_index++)
{
if (!s_message_dialog_buttons[button_index].empty() && ActiveButton(s_message_dialog_buttons[button_index].c_str(), false))
{
result = button_index;
ImGui::CloseCurrentPopup();
}
}
EndMenuButtons();
ImGui::EndPopup();
}
ImGui::PopStyleColor(4);
ImGui::PopStyleVar(3);
ImGui::PopFont();
if (!is_open || result.has_value())
{
// have to move out in case they open another dialog in the callback
auto cb = (std::move(s_message_dialog_callback));
CloseMessageDialog();
if (std::holds_alternative<InfoMessageDialogCallback>(cb))
std::get<InfoMessageDialogCallback>(cb)();
else if (std::holds_alternative<ConfirmMessageDialogCallback>(cb))
std::get<ConfirmMessageDialogCallback>(cb)(result.value_or(1) == 0);
}
}
static float s_notification_vertical_position = 0.3f; static float s_notification_vertical_position = 0.3f;
static float s_notification_vertical_direction = -1.0f; static float s_notification_vertical_direction = -1.0f;

View File

@ -15,6 +15,7 @@
#pragma once #pragma once
#include "common/Pcsx2Defs.h" #include "common/Pcsx2Defs.h"
#include "IconsFontAwesome5.h"
#include "imgui.h" #include "imgui.h"
#include "imgui_internal.h" #include "imgui_internal.h"
#include <functional> #include <functional>
@ -90,10 +91,7 @@ namespace ImGuiFullscreen
return ImVec2(g_layout_padding_left + x * g_layout_scale, g_layout_padding_top + y * g_layout_scale); return ImVec2(g_layout_padding_left + x * g_layout_scale, g_layout_padding_top + y * g_layout_scale);
} }
static __fi ImVec4 ModAlpha(const ImVec4& v, float a) static __fi ImVec4 ModAlpha(const ImVec4& v, float a) { return ImVec4(v.x, v.y, v.z, a); }
{
return ImVec4(v.x, v.y, v.z, a);
}
/// Centers an image within the specified bounds, scaling up or down as needed. /// Centers an image within the specified bounds, scaling up or down as needed.
ImRect CenterImage(const ImVec2& fit_size, const ImVec2& image_size); ImRect CenterImage(const ImVec2& fit_size, const ImVec2& image_size);
@ -223,6 +221,18 @@ namespace ImGuiFullscreen
std::string title, std::string message, std::string caption, std::string ok_button_text, InputStringDialogCallback callback); std::string title, std::string message, std::string caption, std::string ok_button_text, InputStringDialogCallback callback);
void CloseInputDialog(); void CloseInputDialog();
using ConfirmMessageDialogCallback = std::function<void(bool)>;
using InfoMessageDialogCallback = std::function<void()>;
using MessageDialogCallback = std::function<void(s32)>;
bool IsMessageBoxDialogOpen();
void OpenConfirmMessageDialog(std::string title, std::string message, ConfirmMessageDialogCallback callback,
std::string yes_button_text = ICON_FA_CHECK " Yes", std::string no_button_text = ICON_FA_TIMES " No");
void OpenInfoMessageDialog(std::string title, std::string message, InfoMessageDialogCallback callback,
std::string button_text = ICON_FA_WINDOW_CLOSE " Close");
void OpenMessageDialog(std::string title, std::string message, MessageDialogCallback callback, std::string first_button_text,
std::string second_button_text, std::string third_button_text);
void CloseMessageDialog();
float GetNotificationVerticalPosition(); float GetNotificationVerticalPosition();
float GetNotificationVerticalDirection(); float GetNotificationVerticalDirection();
void SetNotificationVerticalPosition(float position, float direction); void SetNotificationVerticalPosition(float position, float direction);

View File

@ -23,6 +23,7 @@
#include "common/Console.h" #include "common/Console.h"
#include "common/FileSystem.h" #include "common/FileSystem.h"
#include "common/Path.h" #include "common/Path.h"
#include "common/SettingsInterface.h"
#include "common/StringUtil.h" #include "common/StringUtil.h"
#include "common/Timer.h" #include "common/Timer.h"
@ -386,3 +387,15 @@ void Host::UpdateLogging(bool disable_system_console)
UpdateLoggingSinks(system_console_enabled, file_logging_enabled); UpdateLoggingSinks(system_console_enabled, file_logging_enabled);
} }
void Host::SetDefaultLoggingSettings(SettingsInterface& si)
{
si.SetBoolValue("Logging", "EnableSystemConsole", false);
si.SetBoolValue("Logging", "EnableFileLogging", false);
si.SetBoolValue("Logging", "EnableTimestamps", true);
si.SetBoolValue("Logging", "EnableVerbose", false);
si.SetBoolValue("Logging", "EnableEEConsole", false);
si.SetBoolValue("Logging", "EnableIOPConsole", false);
si.SetBoolValue("Logging", "EnableInputRecordingLogs", true);
si.SetBoolValue("Logging", "EnableControllerLogs", false);
}

View File

@ -15,6 +15,8 @@
#pragma once #pragma once
class SettingsInterface;
namespace Host namespace Host
{ {
/// Updates the Console handler based on the current configuration. /// Updates the Console handler based on the current configuration.
@ -22,4 +24,7 @@ namespace Host
/// Initializes early console logging (for printing command line arguments). /// Initializes early console logging (for printing command line arguments).
void InitializeEarlyConsole(); void InitializeEarlyConsole();
/// Stores default logging settings to the specified file.
void SetDefaultLoggingSettings(SettingsInterface& si);
} }

View File

@ -17,6 +17,7 @@
#include "common/Pcsx2Defs.h" #include "common/Pcsx2Defs.h"
#include <functional>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <optional> #include <optional>
@ -73,4 +74,32 @@ namespace Host
/// Copies the provided text to the host's clipboard, if present. /// Copies the provided text to the host's clipboard, if present.
bool CopyTextToClipboard(const std::string_view& text); bool CopyTextToClipboard(const std::string_view& text);
/// Requests settings reset. Can be called from any thread, will call back and apply on the CPU thread.
bool RequestResetSettings(bool folders, bool core, bool controllers, bool hotkeys, bool ui);
/// Requests a specific display window size.
void RequestResizeHostDisplay(s32 width, s32 height);
/// Safely executes a function on the VM thread.
void RunOnCPUThread(std::function<void()> function, bool block = false);
/// Asynchronously starts refreshing the game list.
void RefreshGameListAsync(bool invalidate_cache);
/// Cancels game list refresh, if there is one in progress.
void CancelGameListRefresh();
/// Requests shut down and exit of the hosting application. This may not actually exit,
/// if the user cancels the shutdown confirmation.
void RequestExit(bool save_state_if_running);
/// Requests shut down of the current virtual machine.
void RequestVMShutdown(bool allow_confirm, bool allow_save_state, bool default_save_state);
/// Returns true if the hosting application is currently fullscreen.
bool IsFullscreen();
/// Alters fullscreen state of hosting application.
void SetFullscreen(bool enabled);
} // namespace Host } // namespace Host

View File

@ -40,7 +40,9 @@ namespace Host
void SetBaseFloatSettingValue(const char* section, const char* key, float value); void SetBaseFloatSettingValue(const char* section, const char* key, float value);
void SetBaseStringSettingValue(const char* section, const char* key, const char* value); void SetBaseStringSettingValue(const char* section, const char* key, const char* value);
void SetBaseStringListSettingValue(const char* section, const char* key, const std::vector<std::string>& values); void SetBaseStringListSettingValue(const char* section, const char* key, const std::vector<std::string>& values);
void DeleteBaseSettingValue(const char* section, const char* key); bool AddBaseValueToStringList(const char* section, const char* key, const char* value);
bool RemoveBaseValueFromStringList(const char* section, const char* key, const char* value);
void RemoveBaseSettingValue(const char* section, const char* key);
void CommitBaseSettingChanges(); void CommitBaseSettingChanges();
// Settings access, thread-safe. // Settings access, thread-safe.

View File

@ -1231,21 +1231,19 @@ void Pcsx2Config::CopyConfig(const Pcsx2Config& cfg)
LimiterMode = cfg.LimiterMode; LimiterMode = cfg.LimiterMode;
} }
void EmuFolders::SetDefaults() void EmuFolders::SetDefaults(SettingsInterface& si)
{ {
Bios = Path::Combine(DataRoot, "bios"); si.SetStringValue("Folders", "Bios", "bios");
Snapshots = Path::Combine(DataRoot, "snaps"); si.SetStringValue("Folders", "Snapshots", "snaps");
Savestates = Path::Combine(DataRoot, "sstates"); si.SetStringValue("Folders", "Savestates", "sstates");
MemoryCards = Path::Combine(DataRoot, "memcards"); si.SetStringValue("Folders", "MemoryCards", "memcards");
Logs = Path::Combine(DataRoot, "logs"); si.SetStringValue("Folders", "Logs", "logs");
Cheats = Path::Combine(DataRoot, "cheats"); si.SetStringValue("Folders", "Cheats", "cheats");
CheatsWS = Path::Combine(DataRoot, "cheats_ws"); si.SetStringValue("Folders", "CheatsWS", "cheats_ws");
CheatsNI = Path::Combine(DataRoot, "cheats_ni"); si.SetStringValue("Folders", "CheatsNI", "cheats_ni");
Covers = Path::Combine(DataRoot, "covers"); si.SetStringValue("Folders", "Cache", "cache");
GameSettings = Path::Combine(DataRoot, "gamesettings"); si.SetStringValue("Folders", "Textures", "textures");
Cache = Path::Combine(DataRoot, "cache"); si.SetStringValue("Folders", "InputProfiles", "inputprofiles");
Textures = Path::Combine(DataRoot, "textures");
InputProfiles = Path::Combine(DataRoot, "inputprofiles");
} }
static std::string LoadPathFromSettings(SettingsInterface& si, const std::string& root, const char* name, const char* def) static std::string LoadPathFromSettings(SettingsInterface& si, const std::string& root, const char* name, const char* def)
@ -1287,22 +1285,6 @@ void EmuFolders::LoadConfig(SettingsInterface& si)
Console.WriteLn("Input Profile Directory: %s", InputProfiles.c_str()); Console.WriteLn("Input Profile Directory: %s", InputProfiles.c_str());
} }
void EmuFolders::Save(SettingsInterface& si)
{
// convert back to relative
si.SetStringValue("Folders", "Bios", Path::MakeRelative(Bios, DataRoot).c_str());
si.SetStringValue("Folders", "Snapshots", Path::MakeRelative(Snapshots, DataRoot).c_str());
si.SetStringValue("Folders", "Savestates", Path::MakeRelative(Savestates, DataRoot).c_str());
si.SetStringValue("Folders", "MemoryCards", Path::MakeRelative(MemoryCards, DataRoot).c_str());
si.SetStringValue("Folders", "Logs", Path::MakeRelative(Logs, DataRoot).c_str());
si.SetStringValue("Folders", "Cheats", Path::MakeRelative(Cheats, DataRoot).c_str());
si.SetStringValue("Folders", "CheatsWS", Path::MakeRelative(CheatsWS, DataRoot).c_str());
si.SetStringValue("Folders", "CheatsNI", Path::MakeRelative(CheatsNI, DataRoot).c_str());
si.SetStringValue("Folders", "Cache", Path::MakeRelative(Cache, DataRoot).c_str());
si.SetStringValue("Folders", "Textures", Path::MakeRelative(Textures, DataRoot).c_str());
si.SetStringValue("Folders", "InputProfiles", Path::MakeRelative(InputProfiles, DataRoot).c_str());
}
bool EmuFolders::EnsureFoldersExist() bool EmuFolders::EnsureFoldersExist()
{ {
bool result = FileSystem::CreateDirectoryPath(Bios.c_str(), false); bool result = FileSystem::CreateDirectoryPath(Bios.c_str(), false);

View File

@ -234,29 +234,4 @@ namespace Host
/// Provided by the host; called when a state is saved, and the frontend should invalidate its save state cache. /// Provided by the host; called when a state is saved, and the frontend should invalidate its save state cache.
void InvalidateSaveStateCache(); void InvalidateSaveStateCache();
/// Requests a specific display window size.
void RequestResizeHostDisplay(s32 width, s32 height);
/// Safely executes a function on the VM thread.
void RunOnCPUThread(std::function<void()> function, bool block = false);
/// Asynchronously starts refreshing the game list.
void RefreshGameListAsync(bool invalidate_cache);
/// Cancels game list refresh, if there is one in progress.
void CancelGameListRefresh();
/// Requests shut down and exit of the hosting application. This may not actually exit,
/// if the user cancels the shutdown confirmation.
void RequestExit(bool save_state_if_running);
/// Requests shut down of the current virtual machine.
void RequestVMShutdown(bool allow_confirm, bool allow_save_state, bool default_save_state);
/// Returns true if the hosting application is currently fullscreen.
bool IsFullscreen();
/// Alters fullscreen state of hosting application.
void SetFullscreen(bool enabled);
} }

View File

@ -186,6 +186,7 @@
<ClCompile Include="DEV9\sockets.cpp" /> <ClCompile Include="DEV9\sockets.cpp" />
<ClCompile Include="DEV9\net.cpp" /> <ClCompile Include="DEV9\net.cpp" />
<ClCompile Include="DEV9\Win32\tap-win32.cpp" /> <ClCompile Include="DEV9\Win32\tap-win32.cpp" />
<ClCompile Include="Frontend\CommonHost.cpp" />
<ClCompile Include="Frontend\D3D11HostDisplay.cpp" /> <ClCompile Include="Frontend\D3D11HostDisplay.cpp" />
<ClCompile Include="Frontend\D3D12HostDisplay.cpp" /> <ClCompile Include="Frontend\D3D12HostDisplay.cpp" />
<ClCompile Include="Frontend\FullscreenUI.cpp" /> <ClCompile Include="Frontend\FullscreenUI.cpp" />
@ -218,7 +219,7 @@
<ClCompile Include="GS\Renderers\Vulkan\GSTextureVK.cpp" /> <ClCompile Include="GS\Renderers\Vulkan\GSTextureVK.cpp" />
<ClCompile Include="Host.cpp" /> <ClCompile Include="Host.cpp" />
<ClCompile Include="HostDisplay.cpp" /> <ClCompile Include="HostDisplay.cpp" />
<ClCompile Include="HostSettings.cpp" /> <ClCompile Include="Frontend\HostSettings.cpp" />
<ClCompile Include="IopGte.cpp" /> <ClCompile Include="IopGte.cpp" />
<ClCompile Include="PAD\Host\KeyStatus.cpp" /> <ClCompile Include="PAD\Host\KeyStatus.cpp" />
<ClCompile Include="PAD\Host\PAD.cpp" /> <ClCompile Include="PAD\Host\PAD.cpp" />
@ -508,6 +509,7 @@
<ClInclude Include="DEV9\ThreadSafeMap.h" /> <ClInclude Include="DEV9\ThreadSafeMap.h" />
<ClInclude Include="DEV9\Win32\pcap_io_win32_funcs.h" /> <ClInclude Include="DEV9\Win32\pcap_io_win32_funcs.h" />
<ClInclude Include="DEV9\Win32\tap.h" /> <ClInclude Include="DEV9\Win32\tap.h" />
<ClInclude Include="Frontend\CommonHost.h" />
<ClInclude Include="Frontend\D3D11HostDisplay.h" /> <ClInclude Include="Frontend\D3D11HostDisplay.h" />
<ClInclude Include="Frontend\D3D12HostDisplay.h" /> <ClInclude Include="Frontend\D3D12HostDisplay.h" />
<ClInclude Include="Frontend\FullscreenUI.h" /> <ClInclude Include="Frontend\FullscreenUI.h" />

View File

@ -1205,7 +1205,7 @@
<ClCompile Include="USB\USBNull.cpp"> <ClCompile Include="USB\USBNull.cpp">
<Filter>System\Ps2\USB</Filter> <Filter>System\Ps2\USB</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="HostSettings.cpp"> <ClCompile Include="Frontend\HostSettings.cpp">
<Filter>Host</Filter> <Filter>Host</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="VMManager.cpp"> <ClCompile Include="VMManager.cpp">
@ -1281,6 +1281,9 @@
<ClCompile Include="Frontend\FullscreenUI.cpp"> <ClCompile Include="Frontend\FullscreenUI.cpp">
<Filter>Host</Filter> <Filter>Host</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Frontend\CommonHost.cpp">
<Filter>Host</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Patch.h"> <ClInclude Include="Patch.h">
@ -2131,6 +2134,9 @@
<ClInclude Include="Frontend\FullscreenUI.h"> <ClInclude Include="Frontend\FullscreenUI.h">
<Filter>Host</Filter> <Filter>Host</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Frontend\CommonHost.h">
<Filter>Host</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<CustomBuildStep Include="rdebug\deci2.h"> <CustomBuildStep Include="rdebug\deci2.h">