mirror of https://github.com/PCSX2/pcsx2.git
Qt: Implement settings reset
This commit is contained in:
parent
d86abebb50
commit
e4df563811
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -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.
|
||||||
|
}
|
|
@ -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
|
|
@ -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))
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
29
pcsx2/Host.h
29
pcsx2/Host.h
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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" />
|
||||||
|
|
|
@ -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">
|
||||||
|
|
Loading…
Reference in New Issue