Skip to content

Commit

Permalink
Qt: Allow editing folder settings
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek authored and refractionpcsx2 committed Jun 20, 2022
1 parent a07ef0f commit 02d3c93
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 52 deletions.
11 changes: 11 additions & 0 deletions pcsx2-qt/EmuThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,17 @@ void EmuThread::reloadGameSettings()
}
}

void EmuThread::updateEmuFolders()
{
if (!isOnEmuThread())
{
QMetaObject::invokeMethod(this, &EmuThread::updateEmuFolders, Qt::QueuedConnection);
return;
}

Host::Internal::UpdateEmuFolders();
}

void EmuThread::loadOurSettings()
{
m_verbose_status = Host::GetBaseBoolSettingValue("UI", "VerboseStatusBar", false);
Expand Down
1 change: 1 addition & 0 deletions pcsx2-qt/EmuThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public Q_SLOTS:
void setSurfaceless(bool surfaceless);
void applySettings();
void reloadGameSettings();
void updateEmuFolders();
void toggleSoftwareRendering();
void switchRenderer(GSRendererType renderer);
void changeDisc(const QString& path);
Expand Down
8 changes: 0 additions & 8 deletions pcsx2-qt/QtHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,14 +228,6 @@ void QtHost::SetDataDirectory()
EmuFolders::DataRoot = EmuFolders::AppRoot;
}

void QtHost::UpdateFolders()
{
// TODO: This should happen with the VM thread paused.
auto lock = Host::GetSettingsLock();
EmuFolders::LoadConfig(*s_base_settings_interface.get());
EmuFolders::EnsureFoldersExist();
}

bool QtHost::InitializeConfig()
{
if (!SetCriticalFolders())
Expand Down
2 changes: 0 additions & 2 deletions pcsx2-qt/QtHost.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ namespace QtHost
bool Initialize();
void Shutdown();

void UpdateFolders();

/// Sets batch mode (exit after game shutdown).
bool InBatchMode();
void SetBatchMode(bool enabled);
Expand Down
74 changes: 73 additions & 1 deletion pcsx2-qt/SettingWidgetBinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,23 @@

#include <QtCore/QtCore>
#include <QtGui/QAction>
#include <QtWidgets/QAbstractButton>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDoubleSpinBox>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QSlider>
#include <QtWidgets/QSpinBox>

#include "common/Path.h"

#include "pcsx2/Config.h"
#include "pcsx2/HostSettings.h"

#include "EmuThread.h"
#include "QtHost.h"
#include "QtUtils.h"
#include "Settings/SettingsDialog.h"

namespace SettingWidgetBinder
Expand Down Expand Up @@ -228,7 +234,7 @@ namespace SettingWidgetBinder
static std::optional<QString> getNullableStringValue(const QCheckBox* widget)
{
return (widget->checkState() == Qt::PartiallyChecked) ?
std::nullopt :
std::nullopt :
std::optional<QString>(widget->isChecked() ? QStringLiteral("1") : QStringLiteral("0"));
}
static void setNullableStringValue(QCheckBox* widget, std::optional<QString> value)
Expand Down Expand Up @@ -769,4 +775,70 @@ namespace SettingWidgetBinder
}
}

template <typename WidgetType>
static void BindWidgetToFolderSetting(SettingsInterface* sif, WidgetType* widget,
QAbstractButton* browse_button, QAbstractButton* open_button, QAbstractButton* reset_button,
std::string section, std::string key, std::string default_value)
{
using Accessor = SettingAccessor<WidgetType>;

std::string current_path(Host::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value.c_str()));
if (!Path::IsAbsolute(current_path))
current_path = Path::Combine(EmuFolders::DataRoot, current_path);

const QString value(QString::fromStdString(current_path));
Accessor::setStringValue(widget, value);

// if we're doing per-game settings, disable the widget, we only allow folder changes in the base config
if (sif)
{
widget->setEnabled(false);
if (browse_button)
browse_button->setEnabled(false);
if (reset_button)
reset_button->setEnabled(false);
return;
}

Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const std::string new_value(Accessor::getStringValue(widget).toStdString());
if (!new_value.empty())
{
std::string relative_path(Path::MakeRelative(new_value, EmuFolders::DataRoot));
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), relative_path.c_str());
}
else
{
QtHost::RemoveBaseSettingValue(section.c_str(), key.c_str());
}

g_emu_thread->updateEmuFolders();
});

if (browse_button)
{
QObject::connect(browse_button, &QAbstractButton::clicked, browse_button, [widget, key]() {
const QString path(QDir::toNativeSeparators(QFileDialog::getExistingDirectory(QtUtils::GetRootWidget(widget),
qApp->translate("SettingWidgetBinder", "Select folder for %1").arg(QString::fromStdString(key)))));
if (path.isEmpty())
return;

Accessor::setStringValue(widget, path);
});
}
if (open_button)
{
QObject::connect(open_button, &QAbstractButton::clicked, open_button, [widget]() {
QString path(Accessor::getStringValue(widget));
if (!path.isEmpty())
QtUtils::OpenURL(QtUtils::GetRootWidget(widget), QUrl::fromLocalFile(path));
});
}
if (reset_button)
{
QObject::connect(reset_button, &QAbstractButton::clicked, reset_button, [widget, default_value = std::move(default_value)]() {
Accessor::setStringValue(widget, QString::fromStdString(Path::Combine(EmuFolders::AppRoot, default_value)));
});
}
}
} // namespace SettingWidgetBinder
40 changes: 4 additions & 36 deletions pcsx2-qt/Settings/BIOSSettingsWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,28 +38,17 @@ BIOSSettingsWidget::BIOSSettingsWidget(SettingsDialog* dialog, QWidget* parent)
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.fastBoot, "EmuCore", "EnableFastBoot", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.patchRegion, "EmuCore", "PatchBios", false);
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.regionComboBox, "EmuCore", "PatchRegion", BiosZoneStrings, BiosZoneBytes, BiosZoneBytes[0]);
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.searchDirectory, m_ui.browseSearchDirectory, m_ui.openSearchDirectory,
m_ui.resetSearchDirectory, "Folders", "Bios", "bios");

dialog->registerWidgetHelp(m_ui.patchRegion, tr("Patch Region"),tr("Unchecked"),
dialog->registerWidgetHelp(m_ui.patchRegion, tr("Patch Region"), tr("Unchecked"),
tr("Patches the BIOS region byte in ROM. Not recommended unless you really know what you're doing."));
dialog->registerWidgetHelp(m_ui.fastBoot, tr("Fast Boot"), tr("Unchecked"),
tr("Patches the BIOS to skip the console's boot animation."));

updateSearchDirectory();
refreshList();

connect(m_ui.searchDirectory, &QLineEdit::textChanged, [this](const QString& text) {
QtHost::SetBaseStringSettingValue("Folders", "Bios", text.toUtf8().constData());
QtHost::UpdateFolders();
refreshList();
});
connect(m_ui.resetSearchDirectory, &QPushButton::clicked, [this]() {
QtHost::RemoveBaseSettingValue("Folders", "Bios");
QtHost::UpdateFolders();
updateSearchDirectory();
refreshList();
});
connect(m_ui.browseSearchDirectory, &QPushButton::clicked, this, &BIOSSettingsWidget::browseSearchDirectory);
connect(m_ui.openSearchDirectory, &QPushButton::clicked, this, &BIOSSettingsWidget::openSearchDirectory);
connect(m_ui.searchDirectory, &QLineEdit::textChanged, this, &BIOSSettingsWidget::refreshList);
connect(m_ui.refresh, &QPushButton::clicked, this, &BIOSSettingsWidget::refreshList);
connect(m_ui.fileList, &QTreeWidget::currentItemChanged, this, &BIOSSettingsWidget::listItemChanged);

Expand Down Expand Up @@ -89,27 +78,6 @@ void BIOSSettingsWidget::refreshList()
m_refresh_thread->start();
}

void BIOSSettingsWidget::browseSearchDirectory()
{
QString directory = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(
QtUtils::GetRootWidget(this), tr("Select Directory"), m_ui.searchDirectory->text()));
if (directory.isEmpty())
return;

m_ui.searchDirectory->setText(directory);
}

void BIOSSettingsWidget::openSearchDirectory()
{
QtUtils::OpenURL(this, QUrl::fromLocalFile(m_ui.searchDirectory->text()));
}

void BIOSSettingsWidget::updateSearchDirectory()
{
// this will generate a full path
m_ui.searchDirectory->setText(QString::fromStdString(EmuFolders::Bios));
}

void BIOSSettingsWidget::listRefreshed(const QVector<BIOSInfo>& items)
{
const std::string selected_bios(Host::GetBaseStringSettingValue("Filenames", "BIOS"));
Expand Down
3 changes: 0 additions & 3 deletions pcsx2-qt/Settings/BIOSSettingsWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,6 @@ class BIOSSettingsWidget : public QWidget

private Q_SLOTS:
void refreshList();
void browseSearchDirectory();
void openSearchDirectory();
void updateSearchDirectory();

void listItemChanged(const QTreeWidgetItem* current, const QTreeWidgetItem* previous);
void listRefreshed(const QVector<BIOSInfo>& items);
Expand Down
2 changes: 1 addition & 1 deletion pcsx2-qt/Settings/BIOSSettingsWidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@
</layout>
</widget>
<resources>
<include location="resources/resources.qrc"/>
<include location="../resources/resources.qrc"/>
</resources>
<connections/>
</ui>
49 changes: 48 additions & 1 deletion pcsx2/HostSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@

#include "PrecompiledHeader.h"
#include "common/Assertions.h"
#include "Frontend/LayeredSettingsInterface.h"
#include "GS.h"
#include "GS/Renderers/HW/GSTextureReplacements.h"
#include "Host.h"
#include "HostSettings.h"
#include "Frontend/LayeredSettingsInterface.h"
#include "MemoryCardFile.h"
#include "Sio.h"
#include "VMManager.h"

static std::mutex s_settings_mutex;
static LayeredSettingsInterface s_layered_settings_interface;
Expand Down Expand Up @@ -202,3 +207,45 @@ void Host::Internal::SetInputSettingsLayer(SettingsInterface* sif)
std::unique_lock lock(s_settings_mutex);
s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_INPUT, sif);
}

void Host::Internal::UpdateEmuFolders()
{
const std::string old_cheats_directory(EmuFolders::Cheats);
const std::string old_cheats_ws_directory(EmuFolders::CheatsWS);
const std::string old_cheats_ni_directory(EmuFolders::CheatsNI);
const std::string old_memcards_directory(EmuFolders::MemoryCards);
const std::string old_textures_directory(EmuFolders::Textures);

EmuFolders::LoadConfig(*GetBaseSettingsLayer());
EmuFolders::EnsureFoldersExist();

if (VMManager::HasValidVM())
{
if (EmuFolders::Cheats != old_cheats_directory ||
EmuFolders::CheatsWS != old_cheats_ws_directory ||
EmuFolders::CheatsNI != old_cheats_ni_directory)
{
VMManager::ReloadPatches(true, true);
}

if (EmuFolders::MemoryCards != old_memcards_directory)
{
FileMcd_EmuClose();
FileMcd_EmuOpen();

for (u32 port = 0; port < 2; port++)
{
for (u32 slot = 0; slot < 4; slot++)
SetForceMcdEjectTimeoutNow(port, slot);
}
}

if (EmuFolders::Textures != old_textures_directory)
{
GetMTGS().RunOnGSThread([]() {
if (VMManager::HasValidVM())
GSTextureReplacements::ReloadReplacementMap();
});
}
}
}
3 changes: 3 additions & 0 deletions pcsx2/HostSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,8 @@ namespace Host

/// Sets the input profile settings layer. Called by VMManager when the game changes.
void SetInputSettingsLayer(SettingsInterface* sif);

/// Updates the variables in the EmuFolders namespace, reloading subsystems if needed. Must call with the lock held.
void UpdateEmuFolders();
} // namespace Internal
} // namespace Host

0 comments on commit 02d3c93

Please sign in to comment.