mirror of https://github.com/PCSX2/pcsx2.git
Qt: Add copy global settings/clear per-game settings
This commit is contained in:
parent
c16836e7c0
commit
7b45e9296a
|
@ -169,3 +169,60 @@ void SettingsSaveWrapper::_EnumEntry(const char* section, const char* var, int&
|
|||
const int index = (value < 0 || value >= cnt) ? defvalue : value;
|
||||
m_si.SetStringValue(section, var, enumArray[index]);
|
||||
}
|
||||
|
||||
SettingsClearWrapper::SettingsClearWrapper(SettingsInterface& si)
|
||||
: SettingsWrapper(si)
|
||||
{
|
||||
}
|
||||
|
||||
bool SettingsClearWrapper::IsLoading() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SettingsClearWrapper::IsSaving() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void SettingsClearWrapper::Entry(const char* section, const char* var, int& value, const int defvalue /*= 0*/)
|
||||
{
|
||||
m_si.DeleteValue(section, var);
|
||||
}
|
||||
|
||||
void SettingsClearWrapper::Entry(const char* section, const char* var, uint& value, const uint defvalue /*= 0*/)
|
||||
{
|
||||
m_si.DeleteValue(section, var);
|
||||
}
|
||||
|
||||
void SettingsClearWrapper::Entry(const char* section, const char* var, bool& value, const bool defvalue /*= false*/)
|
||||
{
|
||||
m_si.DeleteValue(section, var);
|
||||
}
|
||||
|
||||
void SettingsClearWrapper::Entry(const char* section, const char* var, float& value, const float defvalue /*= 0.0*/)
|
||||
{
|
||||
m_si.DeleteValue(section, var);
|
||||
}
|
||||
|
||||
void SettingsClearWrapper::Entry(const char* section, const char* var, std::string& value, const std::string& default_value /*= std::string()*/)
|
||||
{
|
||||
m_si.DeleteValue(section, var);
|
||||
}
|
||||
|
||||
bool SettingsClearWrapper::EntryBitBool(const char* section, const char* var, bool value, const bool defvalue /*= false*/)
|
||||
{
|
||||
m_si.DeleteValue(section, var);
|
||||
return defvalue;
|
||||
}
|
||||
|
||||
int SettingsClearWrapper::EntryBitfield(const char* section, const char* var, int value, const int defvalue /*= 0*/)
|
||||
{
|
||||
m_si.DeleteValue(section, var);
|
||||
return defvalue;
|
||||
}
|
||||
|
||||
void SettingsClearWrapper::_EnumEntry(const char* section, const char* var, int& value, const char* const* enumArray, int defvalue)
|
||||
{
|
||||
m_si.DeleteValue(section, var);
|
||||
}
|
||||
|
|
|
@ -96,6 +96,27 @@ protected:
|
|||
void _EnumEntry(const char* section, const char* var, int& value, const char* const* enumArray, int defvalue) override;
|
||||
};
|
||||
|
||||
class SettingsClearWrapper final : public SettingsWrapper
|
||||
{
|
||||
public:
|
||||
SettingsClearWrapper(SettingsInterface& si);
|
||||
|
||||
bool IsLoading() const override;
|
||||
bool IsSaving() const override;
|
||||
|
||||
void Entry(const char* section, const char* var, int& value, const int defvalue = 0) override;
|
||||
void Entry(const char* section, const char* var, uint& value, const uint defvalue = 0) override;
|
||||
void Entry(const char* section, const char* var, bool& value, const bool defvalue = false) override;
|
||||
void Entry(const char* section, const char* var, float& value, const float defvalue = 0.0) override;
|
||||
|
||||
void Entry(const char* section, const char* var, std::string& value, const std::string& default_value = std::string()) override;
|
||||
bool EntryBitBool(const char* section, const char* var, bool value, const bool defvalue = false) override;
|
||||
int EntryBitfield(const char* section, const char* var, int value, const int defvalue = 0) override;
|
||||
|
||||
protected:
|
||||
void _EnumEntry(const char* section, const char* var, int& value, const char* const* enumArray, int defvalue) override;
|
||||
};
|
||||
|
||||
#define SettingsWrapSection(section) const char* CURRENT_SETTINGS_SECTION = section;
|
||||
#define SettingsWrapEntry(var) wrap.Entry(CURRENT_SETTINGS_SECTION, #var, var, var)
|
||||
#define SettingsWrapEntryEx(var, name) wrap.Entry(CURRENT_SETTINGS_SECTION, name, var, var)
|
||||
|
|
|
@ -166,7 +166,7 @@ void EmulationSettingsWidget::initializeSpeedCombo(QComboBox* cb, const char* se
|
|||
if (m_dialog->isPerGameSettings())
|
||||
{
|
||||
cb->addItem(tr("Use Global Setting [%1%]").arg(value * 100.0f, 0, 'f', 0));
|
||||
if (!m_dialog->getSettingsInterface()->GetFloatValue(key, section, &value))
|
||||
if (!m_dialog->getSettingsInterface()->GetFloatValue(section, key, &value))
|
||||
{
|
||||
// set to something without data
|
||||
value = -1.0f;
|
||||
|
|
|
@ -58,11 +58,12 @@ SettingsDialog::SettingsDialog(QWidget* parent)
|
|||
setupUi(nullptr);
|
||||
}
|
||||
|
||||
SettingsDialog::SettingsDialog(QWidget* parent, std::unique_ptr<SettingsInterface> sif, const GameList::Entry* game,
|
||||
SettingsDialog::SettingsDialog(QWidget* parent, std::unique_ptr<INISettingsInterface> sif, const GameList::Entry* game,
|
||||
std::string serial, u32 disc_crc, QString filename)
|
||||
: QDialog(parent)
|
||||
, m_sif(std::move(sif))
|
||||
, m_filename(std::move(filename))
|
||||
, m_game_list_filename(game ? game->path : std::string())
|
||||
, m_serial(std::move(serial))
|
||||
, m_disc_crc(disc_crc)
|
||||
{
|
||||
|
@ -71,6 +72,11 @@ SettingsDialog::SettingsDialog(QWidget* parent, std::unique_ptr<SettingsInterfac
|
|||
s_open_game_properties_dialogs.push_back(this);
|
||||
}
|
||||
|
||||
SettingsInterface* SettingsDialog::getSettingsInterface() const
|
||||
{
|
||||
return m_sif.get();
|
||||
}
|
||||
|
||||
void SettingsDialog::setupUi(const GameList::Entry* game)
|
||||
{
|
||||
const bool show_advanced_settings = QtHost::ShouldShowAdvancedSettings();
|
||||
|
@ -98,6 +104,21 @@ void SettingsDialog::setupUi(const GameList::Entry* game)
|
|||
}
|
||||
|
||||
m_ui.restoreDefaultsButton->setVisible(false);
|
||||
m_ui.footerLayout->removeWidget(m_ui.restoreDefaultsButton);
|
||||
m_ui.restoreDefaultsButton->deleteLater();
|
||||
m_ui.restoreDefaultsButton = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui.copyGlobalSettingsButton->setVisible(false);
|
||||
m_ui.footerLayout->removeWidget(m_ui.copyGlobalSettingsButton);
|
||||
m_ui.copyGlobalSettingsButton->deleteLater();
|
||||
m_ui.copyGlobalSettingsButton = nullptr;
|
||||
|
||||
m_ui.clearGameSettingsButton->setVisible(false);
|
||||
m_ui.footerLayout->removeWidget(m_ui.clearGameSettingsButton);
|
||||
m_ui.clearGameSettingsButton->deleteLater();
|
||||
m_ui.clearGameSettingsButton = nullptr;
|
||||
}
|
||||
|
||||
addWidget(m_interface_settings = new InterfaceSettingsWidget(this, m_ui.settingsContainer), tr("Interface"),
|
||||
|
@ -213,7 +234,12 @@ void SettingsDialog::setupUi(const GameList::Entry* game)
|
|||
m_ui.helpText->setText(m_category_help_text[0]);
|
||||
connect(m_ui.settingsCategory, &QListWidget::currentRowChanged, this, &SettingsDialog::onCategoryCurrentRowChanged);
|
||||
connect(m_ui.closeButton, &QPushButton::clicked, this, &SettingsDialog::close);
|
||||
connect(m_ui.restoreDefaultsButton, &QPushButton::clicked, this, &SettingsDialog::onRestoreDefaultsClicked);
|
||||
if (m_ui.restoreDefaultsButton)
|
||||
connect(m_ui.restoreDefaultsButton, &QPushButton::clicked, this, &SettingsDialog::onRestoreDefaultsClicked);
|
||||
if (m_ui.copyGlobalSettingsButton)
|
||||
connect(m_ui.copyGlobalSettingsButton, &QPushButton::clicked, this, &SettingsDialog::onCopyGlobalSettingsClicked);
|
||||
if (m_ui.clearGameSettingsButton)
|
||||
connect(m_ui.clearGameSettingsButton, &QPushButton::clicked, this, &SettingsDialog::onClearSettingsClicked);
|
||||
}
|
||||
|
||||
SettingsDialog::~SettingsDialog()
|
||||
|
@ -274,6 +300,71 @@ void SettingsDialog::onRestoreDefaultsClicked()
|
|||
g_main_window->resetSettings(ui_cb->isChecked());
|
||||
}
|
||||
|
||||
void SettingsDialog::onCopyGlobalSettingsClicked()
|
||||
{
|
||||
if (!isPerGameSettings())
|
||||
return;
|
||||
|
||||
if (QMessageBox::question(this, tr("PCSX2 Settings"),
|
||||
tr("The configuration for this game will be replaced by the current global settings.\n\nAny current setting values will be "
|
||||
"overwritten.\n\nDo you want to continue?"),
|
||||
QMessageBox::Yes, QMessageBox::No) != QMessageBox::Yes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
auto lock = Host::GetSettingsLock();
|
||||
Pcsx2Config::CopyConfiguration(m_sif.get(), *Host::Internal::GetBaseSettingsLayer());
|
||||
}
|
||||
m_sif->Save();
|
||||
g_emu_thread->reloadGameSettings();
|
||||
|
||||
QMessageBox::information(reopen(), tr("PCSX2 Settings"), tr("Per-game configuration copied from global settings."));
|
||||
}
|
||||
|
||||
void SettingsDialog::onClearSettingsClicked()
|
||||
{
|
||||
if (!isPerGameSettings())
|
||||
return;
|
||||
|
||||
if (QMessageBox::question(this, tr("PCSX2 Settings"),
|
||||
tr("The configuration for this game will be cleared.\n\nAny current setting values will be lost.\n\nDo you want to continue?"),
|
||||
QMessageBox::Yes, QMessageBox::No) != QMessageBox::Yes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Pcsx2Config::ClearConfiguration(m_sif.get());
|
||||
m_sif->Save();
|
||||
g_emu_thread->reloadGameSettings();
|
||||
|
||||
QMessageBox::information(reopen(), tr("PCSX2 Settings"), tr("Per-game configuration cleared."));
|
||||
}
|
||||
|
||||
SettingsDialog* SettingsDialog::reopen()
|
||||
{
|
||||
// This doesn't work for global settings, because MainWindow maintains a pointer.
|
||||
if (!m_sif)
|
||||
return this;
|
||||
|
||||
close();
|
||||
|
||||
std::unique_ptr<INISettingsInterface> new_sif = std::make_unique<INISettingsInterface>(m_sif->GetFileName());
|
||||
if (FileSystem::FileExists(new_sif->GetFileName().c_str()))
|
||||
new_sif->Load();
|
||||
|
||||
auto lock = GameList::GetLock();
|
||||
const GameList::Entry* game = m_game_list_filename.empty() ? nullptr : GameList::GetEntryForPath(m_game_list_filename.c_str());
|
||||
|
||||
SettingsDialog* dlg = new SettingsDialog(g_main_window, std::move(new_sif), game, m_serial, m_disc_crc, m_filename);
|
||||
dlg->QDialog::setWindowTitle(windowTitle());
|
||||
dlg->setModal(false);
|
||||
dlg->show();
|
||||
|
||||
return dlg;
|
||||
}
|
||||
|
||||
void SettingsDialog::addWidget(QWidget* widget, QString title, QString icon, QString help_text)
|
||||
{
|
||||
const int index = m_ui.settingsCategory->count();
|
||||
|
@ -566,3 +657,4 @@ void SettingsDialog::openGamePropertiesDialog(const GameList::Entry* game, const
|
|||
dialog->setModal(false);
|
||||
dialog->show();
|
||||
}
|
||||
|
||||
|
|
|
@ -51,12 +51,13 @@ class SettingsDialog final : public QDialog
|
|||
|
||||
public:
|
||||
explicit SettingsDialog(QWidget* parent);
|
||||
SettingsDialog(QWidget* parent, std::unique_ptr<SettingsInterface> sif, const GameList::Entry* game, std::string serial, u32 disc_crc, QString filename = QString());
|
||||
SettingsDialog(QWidget* parent, std::unique_ptr<INISettingsInterface> sif, const GameList::Entry* game, std::string serial,
|
||||
u32 disc_crc, QString filename = QString());
|
||||
~SettingsDialog();
|
||||
|
||||
static void openGamePropertiesDialog(const GameList::Entry* game, const std::string_view& title, std::string serial, u32 disc_crc);
|
||||
|
||||
__fi SettingsInterface* getSettingsInterface() const { return m_sif.get(); }
|
||||
SettingsInterface* getSettingsInterface() const;
|
||||
__fi bool isPerGameSettings() const { return static_cast<bool>(m_sif); }
|
||||
__fi const std::string& getSerial() const { return m_serial; }
|
||||
__fi u32 getDiscCRC() const { return m_disc_crc; }
|
||||
|
@ -108,6 +109,8 @@ Q_SIGNALS:
|
|||
private Q_SLOTS:
|
||||
void onCategoryCurrentRowChanged(int row);
|
||||
void onRestoreDefaultsClicked();
|
||||
void onCopyGlobalSettingsClicked();
|
||||
void onClearSettingsClicked();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent*) override;
|
||||
|
@ -122,7 +125,9 @@ private:
|
|||
|
||||
void addWidget(QWidget* widget, QString title, QString icon, QString help_text);
|
||||
|
||||
std::unique_ptr<SettingsInterface> m_sif;
|
||||
SettingsDialog* reopen();
|
||||
|
||||
std::unique_ptr<INISettingsInterface> m_sif;
|
||||
|
||||
Ui::SettingsDialog m_ui;
|
||||
|
||||
|
@ -149,6 +154,7 @@ private:
|
|||
|
||||
QString m_filename;
|
||||
|
||||
std::string m_game_list_filename;
|
||||
std::string m_serial;
|
||||
u32 m_disc_crc;
|
||||
};
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<layout class="QHBoxLayout" name="footerLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="restoreDefaultsButton">
|
||||
<property name="text">
|
||||
|
@ -89,6 +89,20 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="copyGlobalSettingsButton">
|
||||
<property name="text">
|
||||
<string>Copy Global Settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="clearGameSettingsButton">
|
||||
<property name="text">
|
||||
<string>Clear Settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
|
|
|
@ -1350,6 +1350,7 @@ struct Pcsx2Config
|
|||
|
||||
Pcsx2Config();
|
||||
void LoadSave(SettingsWrapper& wrap);
|
||||
void LoadSaveCore(SettingsWrapper& wrap);
|
||||
void LoadSaveMemcards(SettingsWrapper& wrap);
|
||||
|
||||
/// Reloads options affected by patches.
|
||||
|
@ -1366,6 +1367,12 @@ struct Pcsx2Config
|
|||
|
||||
/// Copies runtime configuration settings (e.g. frame limiter state).
|
||||
void CopyRuntimeConfig(Pcsx2Config& cfg);
|
||||
|
||||
/// Copies configuration from one file to another. Does not copy controller settings.
|
||||
static void CopyConfiguration(SettingsInterface* dest_si, SettingsInterface& src_si);
|
||||
|
||||
/// Clears all core keys from the specified interface.
|
||||
static void ClearConfiguration(SettingsInterface* dest_si);
|
||||
};
|
||||
|
||||
extern Pcsx2Config EmuConfig;
|
||||
|
|
|
@ -2490,15 +2490,7 @@ void FullscreenUI::DoCopyGameSettings()
|
|||
if (!s_game_settings_interface)
|
||||
return;
|
||||
|
||||
Pcsx2Config temp;
|
||||
{
|
||||
SettingsLoadWrapper wrapper(*GetEditingSettingsInterface(false));
|
||||
temp.LoadSave(wrapper);
|
||||
}
|
||||
{
|
||||
SettingsSaveWrapper wrapper(*s_game_settings_interface.get());
|
||||
temp.LoadSave(wrapper);
|
||||
}
|
||||
Pcsx2Config::CopyConfiguration(s_game_settings_interface.get(), *GetEditingSettingsInterface(false));
|
||||
|
||||
SetSettingsChanged(s_game_settings_interface.get());
|
||||
|
||||
|
@ -2511,9 +2503,7 @@ void FullscreenUI::DoClearGameSettings()
|
|||
if (!s_game_settings_interface)
|
||||
return;
|
||||
|
||||
s_game_settings_interface->Clear();
|
||||
if (!s_game_settings_interface->GetFileName().empty())
|
||||
FileSystem::DeleteFilePath(s_game_settings_interface->GetFileName().c_str());
|
||||
Pcsx2Config::ClearConfiguration(s_game_settings_interface.get());
|
||||
|
||||
SetSettingsChanged(s_game_settings_interface.get());
|
||||
|
||||
|
|
|
@ -1485,7 +1485,7 @@ Pcsx2Config::Pcsx2Config()
|
|||
PINESlot = 28011;
|
||||
}
|
||||
|
||||
void Pcsx2Config::LoadSave(SettingsWrapper& wrap)
|
||||
void Pcsx2Config::LoadSaveCore(SettingsWrapper& wrap)
|
||||
{
|
||||
// Switch the rounding mode back to the system default for loading settings.
|
||||
// That way, we'll get exactly the same values as what we loaded when we first started.
|
||||
|
@ -1531,8 +1531,6 @@ void Pcsx2Config::LoadSave(SettingsWrapper& wrap)
|
|||
|
||||
Debugger.LoadSave(wrap);
|
||||
Trace.LoadSave(wrap);
|
||||
USB.LoadSave(wrap);
|
||||
Pad.LoadSave(wrap);
|
||||
|
||||
#ifdef ENABLE_ACHIEVEMENTS
|
||||
Achievements.LoadSave(wrap);
|
||||
|
@ -1560,6 +1558,13 @@ void Pcsx2Config::LoadSave(SettingsWrapper& wrap)
|
|||
SSE_MXCSR::SetCurrent(prev_mxcsr);
|
||||
}
|
||||
|
||||
void Pcsx2Config::LoadSave(SettingsWrapper& wrap)
|
||||
{
|
||||
LoadSaveCore(wrap);
|
||||
USB.LoadSave(wrap);
|
||||
Pad.LoadSave(wrap);
|
||||
}
|
||||
|
||||
void Pcsx2Config::LoadSaveMemcards(SettingsWrapper& wrap)
|
||||
{
|
||||
for (uint slot = 0; slot < 2; ++slot)
|
||||
|
@ -1635,6 +1640,26 @@ void Pcsx2Config::CopyRuntimeConfig(Pcsx2Config& cfg)
|
|||
}
|
||||
}
|
||||
|
||||
void Pcsx2Config::CopyConfiguration(SettingsInterface* dest_si, SettingsInterface& src_si)
|
||||
{
|
||||
Pcsx2Config temp;
|
||||
{
|
||||
SettingsLoadWrapper wrapper(src_si);
|
||||
temp.LoadSaveCore(wrapper);
|
||||
}
|
||||
{
|
||||
SettingsSaveWrapper wrapper(*dest_si);
|
||||
temp.LoadSaveCore(wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
void Pcsx2Config::ClearConfiguration(SettingsInterface* dest_si)
|
||||
{
|
||||
Pcsx2Config temp;
|
||||
SettingsClearWrapper wrapper(*dest_si);
|
||||
temp.LoadSaveCore(wrapper);
|
||||
}
|
||||
|
||||
bool EmuFolders::InitializeCriticalFolders()
|
||||
{
|
||||
SetAppRoot();
|
||||
|
|
Loading…
Reference in New Issue