FullscreenUI: Various improvements

This commit is contained in:
Connor McLaughlin
2022-09-17 15:51:05 +10:00
parent 91c8681bed
commit ef3ad91ad0
34 changed files with 1350 additions and 514 deletions

View File

@ -162,6 +162,7 @@ void AudioSettingsWidget::onOutputVolumeChanged(int new_value)
// only called for base settings
DebugAssert(!m_dialog->isPerGameSettings());
Host::SetBaseIntSettingValue("Audio", "OutputVolume", new_value);
Host::CommitBaseSettingChanges();
g_emu_thread->setAudioOutputVolume(new_value, m_ui.fastForwardVolume->value());
updateVolumeLabel();
@ -172,6 +173,7 @@ void AudioSettingsWidget::onFastForwardVolumeChanged(int new_value)
// only called for base settings
DebugAssert(!m_dialog->isPerGameSettings());
Host::SetBaseIntSettingValue("Audio", "FastForwardVolume", new_value);
Host::CommitBaseSettingChanges();
g_emu_thread->setAudioOutputVolume(m_ui.volume->value(), new_value);
updateVolumeLabel();
@ -184,5 +186,6 @@ void AudioSettingsWidget::onOutputMutedChanged(int new_state)
const bool muted = (new_state != 0);
Host::SetBaseBoolSettingValue("Audio", "OutputMuted", muted);
Host::CommitBaseSettingChanges();
g_emu_thread->setAudioOutputMuted(muted);
}

View File

@ -436,6 +436,7 @@ bool AutoUpdaterDialog::updateNeeded() const
void AutoUpdaterDialog::skipThisUpdateClicked()
{
Host::SetBaseStringSettingValue("AutoUpdater", "LastVersion", m_latest_sha.toUtf8().constData());
Host::CommitBaseSettingChanges();
done(0);
}

View File

@ -156,6 +156,7 @@ void ConsoleSettingsWidget::onEnableCPUClockSpeedControlChecked(int state)
}
Host::SetBaseBoolSettingValue("UI", "CPUOverclockingWarningShown", true);
Host::CommitBaseSettingChanges();
}
m_ui.cpuClockSpeed->setEnabled(m_dialog->getEffectiveBoolValue("CPU", "OverclockEnable", false));

View File

@ -177,6 +177,7 @@ void ControllerBindingWidget::onTypeChanged()
{
Host::SetBaseStringSettingValue(m_config_section.c_str(), "Type",
Settings::GetControllerTypeName(m_controller_type));
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
}

View File

@ -308,6 +308,7 @@ void ControllerSettingsDialog::setStringValue(const char* section, const char* k
else
{
Host::SetBaseStringSettingValue(section, key, value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
}
}

View File

@ -46,6 +46,7 @@ static void BindWidgetToInputProfileBool(SettingsInterface* sif, WidgetType* wid
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const bool new_value = Accessor::getBoolValue(widget);
Host::SetBaseBoolSettingValue(section.c_str(), key.c_str(), new_value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
});
}
@ -78,6 +79,7 @@ static void BindWidgetToInputProfileFloat(SettingsInterface* sif, WidgetType* wi
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const float new_value = Accessor::getFloatValue(widget);
Host::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
});
}
@ -110,6 +112,7 @@ static void BindWidgetToInputProfileNormalized(SettingsInterface* sif, WidgetTyp
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), range]() {
const float new_value = (static_cast<float>(Accessor::getIntValue(widget)) / range);
Host::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
});
}
@ -153,7 +156,7 @@ static void BindWidgetToInputProfileString(SettingsInterface* sif, WidgetType* w
Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), new_value.toUtf8().constData());
else
Host::DeleteBaseSettingValue(section.c_str(), key.c_str());
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
});
}

View File

@ -5,6 +5,7 @@
CoverDownloadDialog::CoverDownloadDialog(QWidget* parent /*= nullptr*/) : QDialog(parent)
{
m_ui.setupUi(this);
m_ui.coverIcon->setPixmap(QIcon::fromTheme("image-fill").pixmap(32));
updateEnabled();
connect(m_ui.start, &QPushButton::clicked, this, &CoverDownloadDialog::onStartClicked);
@ -29,7 +30,8 @@ void CoverDownloadDialog::onDownloadStatus(const QString& text)
void CoverDownloadDialog::onDownloadProgress(int value, int range)
{
// limit to once every five seconds
// Limit to once every five seconds, otherwise it's way too flickery.
// Ideally in the future we'd have some way to invalidate only a single cover.
if (m_last_refresh_time.GetTimeSeconds() >= 5.0f)
{
emit coverRefreshRequested();
@ -83,7 +85,8 @@ void CoverDownloadDialog::updateEnabled()
void CoverDownloadDialog::startThread()
{
m_thread = std::make_unique<CoverDownloadThread>(this, m_ui.urls->toPlainText());
m_thread = std::make_unique<CoverDownloadThread>(this, m_ui.urls->toPlainText(), m_ui.useSerialFileNames->isChecked());
m_last_refresh_time.Reset();
connect(m_thread.get(), &CoverDownloadThread::statusUpdated, this, &CoverDownloadDialog::onDownloadStatus);
connect(m_thread.get(), &CoverDownloadThread::progressUpdated, this, &CoverDownloadDialog::onDownloadProgress);
connect(m_thread.get(), &CoverDownloadThread::threadFinished, this, &CoverDownloadDialog::onDownloadComplete);
@ -101,8 +104,8 @@ void CoverDownloadDialog::cancelThread()
m_thread.reset();
}
CoverDownloadDialog::CoverDownloadThread::CoverDownloadThread(QWidget* parent, const QString& urls)
: QtAsyncProgressThread(parent)
CoverDownloadDialog::CoverDownloadThread::CoverDownloadThread(QWidget* parent, const QString& urls, bool use_serials)
: QtAsyncProgressThread(parent), m_use_serials(use_serials)
{
for (const QString& str : urls.split(QChar('\n')))
m_urls.push_back(str.toStdString());
@ -112,5 +115,5 @@ CoverDownloadDialog::CoverDownloadThread::~CoverDownloadThread() = default;
void CoverDownloadDialog::CoverDownloadThread::runAsync()
{
GameList::DownloadCovers(m_urls, this);
GameList::DownloadCovers(m_urls, m_use_serials, this);
}

View File

@ -34,7 +34,7 @@ private:
class CoverDownloadThread : public QtAsyncProgressThread
{
public:
CoverDownloadThread(QWidget* parent, const QString& urls);
CoverDownloadThread(QWidget* parent, const QString& urls, bool use_serials);
~CoverDownloadThread();
protected:
@ -42,6 +42,7 @@ private:
private:
std::vector<std::string> m_urls;
bool m_use_serials;
};
void startThread();

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>656</width>
<height>343</height>
<width>720</width>
<height>380</height>
</rect>
</property>
<property name="windowTitle">
@ -15,9 +15,39 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,1">
<property name="spacing">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="coverIcon">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="resources/resources.qrc">:/icons/black/svg/image-fill.svg</pixmap>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>DuckStation can automatically download covers for games which do not currently have a cover set. We do not host any cover images, the user must provide their own source for images.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;DuckStation can automatically download covers for games which do not currently have a cover set. We do not host any cover images, the user must provide their own source for images.&lt;/p&gt;&lt;p&gt;In the form below, specify the URLs to download covers from, with one template URL per line. The following variables are available:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;${title}:&lt;/span&gt; Title of the game.&lt;br/&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;${filetitle}:&lt;/span&gt; Name component of the game's filename.&lt;br/&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;${serial}:&lt;/span&gt; Serial of the game.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:700;&quot;&gt;Example:&lt;/span&gt; https://www.example-not-a-real-domain.com/covers/${serial}.jpg&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;In the box below, specify the URLs to download covers from, with one template URL per line. The following variables are available:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;${title}:&lt;/span&gt; Title of the game.&lt;br/&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;${filetitle}:&lt;/span&gt; Name component of the game's filename.&lt;br/&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;${serial}:&lt;/span&gt; Serial of the game.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:700;&quot;&gt;Example:&lt;/span&gt; https://www.example-not-a-real-domain.com/covers/${serial}.jpg&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@ -25,20 +55,24 @@
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
<widget class="QTextEdit" name="urls"/>
</item>
<item>
<widget class="QTextEdit" name="urls"/>
<widget class="QLabel" name="label_2">
<property name="text">
<string>By default, the downloaded covers will be saved with the game's title. If this is not desired, you can check the &quot;Use Serial File Names&quot; box below. Using serials instead of game titles will prevent conflicts when multiple regions of the same game are used.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="useSerialFileNames">
<property name="text">
<string>Use Serial File Names</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="status">
@ -76,6 +110,8 @@
</item>
</layout>
</widget>
<resources/>
<resources>
<include location="resources/resources.qrc"/>
</resources>
<connections/>
</ui>
</ui>

View File

@ -225,7 +225,10 @@ bool DisplayWidget::event(QEvent* event)
if (ImGuiManager::WantsTextInput() && key_event->type() == QEvent::KeyPress)
{
const QString text(key_event->text());
// Don't forward backspace characters. We send the backspace as a normal key event,
// so if we send the character too, it double-deletes.
QString text(key_event->text());
text.remove(QChar('\b'));
if (!text.isEmpty())
emit windowTextEntered(text);
}

View File

@ -176,4 +176,6 @@ void GameListSearchDirectoriesModel::saveToSettings()
Host::DeleteBaseSettingValue("GameList", "RecursivePaths");
else
Host::SetBaseStringListSettingValue("GameList", "RecursivePaths", recursive_paths);
Host::CommitBaseSettingChanges();
}

View File

@ -55,6 +55,7 @@ bool GameListSettingsWidget::addExcludedPath(const std::string& path)
if (!Host::AddValueToBaseStringListSetting("GameList", "ExcludedPaths", path.c_str()))
return false;
Host::CommitBaseSettingChanges();
m_ui.excludedPaths->addItem(QString::fromStdString(path));
g_main_window->refreshGameList(false);
return true;
@ -158,7 +159,8 @@ void GameListSettingsWidget::onRemoveExcludedPathButtonClicked()
if (!item)
return;
Host::RemoveValueFromBaseStringListSetting("GameList", "ExcludedPaths", item->text().toUtf8().constData());
if (Host::RemoveValueFromBaseStringListSetting("GameList", "ExcludedPaths", item->text().toUtf8().constData()))
Host::CommitBaseSettingChanges();
delete item;
g_main_window->refreshGameList(false);

View File

@ -322,6 +322,7 @@ void GameListWidget::listZoom(float delta)
{
const float new_scale = std::clamp(m_model->getCoverScale() + delta, MIN_SCALE, MAX_SCALE);
Host::SetBaseFloatSettingValue("UI", "GameListCoverArtScale", new_scale);
Host::CommitBaseSettingChanges();
m_model->setCoverScale(new_scale);
m_model->updateCacheSize(width(), height());
updateListFont();
@ -345,6 +346,7 @@ void GameListWidget::gridIntScale(int int_scale)
const float new_scale = std::clamp(static_cast<float>(int_scale) / 100.0f, MIN_SCALE, MAX_SCALE);
Host::SetBaseFloatSettingValue("UI", "GameListCoverArtScale", new_scale);
Host::CommitBaseSettingChanges();
m_model->setCoverScale(new_scale);
m_model->updateCacheSize(width(), height());
updateListFont();
@ -367,6 +369,7 @@ void GameListWidget::showGameList()
}
Host::SetBaseBoolSettingValue("UI", "GameListGridView", false);
Host::CommitBaseSettingChanges();
m_ui.stack->setCurrentIndex(0);
resizeTableViewColumnsToFit();
updateToolbar();
@ -382,6 +385,7 @@ void GameListWidget::showGameGrid()
}
Host::SetBaseBoolSettingValue("UI", "GameListGridView", true);
Host::CommitBaseSettingChanges();
m_ui.stack->setCurrentIndex(1);
updateToolbar();
emit layoutChange();
@ -396,6 +400,7 @@ void GameListWidget::setShowCoverTitles(bool enabled)
}
Host::SetBaseBoolSettingValue("UI", "GameListShowCoverTitles", enabled);
Host::CommitBaseSettingChanges();
m_model->setShowCoverTitles(enabled);
if (isShowingGameGrid())
m_model->refresh();
@ -499,6 +504,7 @@ void GameListWidget::saveTableViewColumnVisibilitySettings()
{
const bool visible = !m_table_view->isColumnHidden(column);
Host::SetBaseBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column), visible);
Host::CommitBaseSettingChanges();
}
}
@ -506,6 +512,7 @@ void GameListWidget::saveTableViewColumnVisibilitySettings(int column)
{
const bool visible = !m_table_view->isColumnHidden(column);
Host::SetBaseBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column), visible);
Host::CommitBaseSettingChanges();
}
void GameListWidget::loadTableViewColumnSortSettings()
@ -533,6 +540,7 @@ void GameListWidget::saveTableViewColumnSortSettings()
}
Host::SetBaseBoolSettingValue("GameListTableView", "SortDescending", sort_descending);
Host::CommitBaseSettingChanges();
}
const GameList::Entry* GameListWidget::getSelectedEntry() const

View File

@ -238,6 +238,7 @@ void InputBindingDialog::saveListToSettings()
Host::SetBaseStringListSettingValue(m_section_name.c_str(), m_key_name.c_str(), m_bindings);
else
Host::DeleteBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
Host::CommitBaseSettingChanges();
g_emu_thread->reloadInputBindings();
}
}

View File

@ -215,6 +215,7 @@ void InputBindingWidget::setNewBinding()
else
{
Host::SetBaseStringSettingValue(m_section_name.c_str(), m_key_name.c_str(), new_binding.c_str());
Host::CommitBaseSettingChanges();
g_emu_thread->reloadInputBindings();
}
}
@ -235,6 +236,7 @@ void InputBindingWidget::clearBinding()
else
{
Host::DeleteBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
Host::CommitBaseSettingChanges();
g_emu_thread->reloadInputBindings();
}
reloadBinding();
@ -391,6 +393,7 @@ void InputVibrationBindingWidget::clearBinding()
{
m_binding = {};
Host::DeleteBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
Host::CommitBaseSettingChanges();
g_emu_thread->reloadInputBindings();
setText(QString());
}
@ -428,6 +431,7 @@ void InputVibrationBindingWidget::onClicked()
const QString new_value(input_dialog.textValue());
m_binding = new_value.toStdString();
Host::SetBaseStringSettingValue(m_section_name.c_str(), m_key_name.c_str(), m_binding.c_str());
Host::CommitBaseSettingChanges();
setText(new_value);
}

View File

@ -1119,18 +1119,21 @@ void MainWindow::onRemoveDiscActionTriggered()
void MainWindow::onViewToolbarActionToggled(bool checked)
{
Host::SetBaseBoolSettingValue("UI", "ShowToolbar", checked);
Host::CommitBaseSettingChanges();
m_ui.toolBar->setVisible(checked);
}
void MainWindow::onViewLockToolbarActionToggled(bool checked)
{
Host::SetBaseBoolSettingValue("UI", "LockToolbar", checked);
Host::CommitBaseSettingChanges();
m_ui.toolBar->setMovable(!checked);
}
void MainWindow::onViewStatusBarActionToggled(bool checked)
{
Host::SetBaseBoolSettingValue("UI", "ShowStatusBar", checked);
Host::CommitBaseSettingChanges();
m_ui.statusBar->setVisible(checked);
}
@ -1343,7 +1346,7 @@ void MainWindow::setGameListEntryCoverImage(const GameList::Entry* entry)
}
QString new_filename =
QString::fromStdString(GameList::GetNewCoverImagePathForEntry(entry, filename.toStdString().c_str()));
QString::fromStdString(GameList::GetNewCoverImagePathForEntry(entry, filename.toStdString().c_str(), false));
if (new_filename.isEmpty())
return;
@ -1427,6 +1430,7 @@ void MainWindow::setupAdditionalUi()
action->setCheckable(true);
connect(action, &QAction::triggered, [this, mode]() {
Host::SetBaseStringSettingValue("CPU", "ExecutionMode", Settings::GetCPUExecutionModeName(mode));
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
updateDebugMenuCPUExecutionMode();
});
@ -1441,6 +1445,7 @@ void MainWindow::setupAdditionalUi()
action->setCheckable(true);
connect(action, &QAction::triggered, [this, renderer]() {
Host::SetBaseStringSettingValue("GPU", "Renderer", Settings::GetRendererName(renderer));
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
updateDebugMenuGPURenderer();
});
@ -1455,6 +1460,7 @@ void MainWindow::setupAdditionalUi()
action->setCheckable(true);
connect(action, &QAction::triggered, [this, crop_mode]() {
Host::SetBaseStringSettingValue("Display", "CropMode", Settings::GetDisplayCropModeName(crop_mode));
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
updateDebugMenuCropMode();
});
@ -1484,6 +1490,7 @@ void MainWindow::setupAdditionalUi()
connect(action, &QAction::triggered, [this, action]() {
const QString new_language = action->data().toString();
Host::SetBaseStringSettingValue("Main", "Language", new_language.toUtf8().constData());
Host::CommitBaseSettingChanges();
QtHost::InstallTranslator();
recreate();
});
@ -1950,6 +1957,7 @@ void MainWindow::addThemeToMenu(const QString& name, const QString& key)
void MainWindow::setTheme(const QString& theme)
{
Host::SetBaseStringSettingValue("UI", "Theme", theme.toUtf8().constData());
Host::CommitBaseSettingChanges();
updateApplicationTheme();
updateMenuSelectedTheme();
m_game_list_widget->reloadCommonImages();
@ -2097,7 +2105,10 @@ void MainWindow::saveGeometryToConfig()
const QByteArray geometry_b64 = geometry.toBase64();
const std::string old_geometry_b64 = Host::GetBaseStringSettingValue("UI", "MainWindowGeometry");
if (old_geometry_b64 != geometry_b64.constData())
{
Host::SetBaseStringSettingValue("UI", "MainWindowGeometry", geometry_b64.constData());
Host::CommitBaseSettingChanges();
}
}
void MainWindow::restoreGeometryFromConfig()
@ -2114,7 +2125,10 @@ void MainWindow::saveDisplayWindowGeometryToConfig()
const QByteArray geometry_b64 = geometry.toBase64();
const std::string old_geometry_b64 = Host::GetBaseStringSettingValue("UI", "DisplayWindowGeometry");
if (old_geometry_b64 != geometry_b64.constData())
{
Host::SetBaseStringSettingValue("UI", "DisplayWindowGeometry", geometry_b64.constData());
Host::CommitBaseSettingChanges();
}
}
void MainWindow::restoreDisplayWindowGeometryFromConfig()
@ -2443,6 +2457,7 @@ void MainWindow::onCheckForUpdatesActionTriggered()
{
// Wipe out the last version, that way it displays the update if we've previously skipped it.
Host::DeleteBaseSettingValue("AutoUpdater", "LastVersion");
Host::CommitBaseSettingChanges();
checkForUpdates(true);
}
@ -2553,6 +2568,7 @@ void MainWindow::onToolsCheatManagerTriggered()
connect(cb, &QCheckBox::stateChanged, [](int state) {
Host::SetBaseBoolSettingValue("UI", "DisplayCheatWarning", (state != Qt::CheckState::Checked));
Host::CommitBaseSettingChanges();
});
if (mb.exec() == QMessageBox::No)

View File

@ -1078,21 +1078,6 @@ void Host::CancelGameListRefresh()
QMetaObject::invokeMethod(g_main_window, "cancelGameListRefresh", Qt::BlockingQueuedConnection);
}
void Host::DownloadCoversAsync(std::vector<std::string> url_templates)
{
//
}
void Host::CancelCoversDownload()
{
//
}
void Host::CoversChanged()
{
//
}
void EmuThread::loadState(const QString& filename)
{
if (!isOnThread())
@ -1579,68 +1564,6 @@ std::optional<std::time_t> Host::GetResourceFileTimestamp(const char* filename)
return sd.ModificationTime;
}
void Host::SetBaseBoolSettingValue(const char* section, const char* key, bool value)
{
auto lock = Host::GetSettingsLock();
s_base_settings_interface->SetBoolValue(section, key, value);
QtHost::QueueSettingsSave();
}
void Host::SetBaseIntSettingValue(const char* section, const char* key, int value)
{
auto lock = Host::GetSettingsLock();
s_base_settings_interface->SetIntValue(section, key, value);
QtHost::QueueSettingsSave();
}
void Host::SetBaseFloatSettingValue(const char* section, const char* key, float value)
{
auto lock = Host::GetSettingsLock();
s_base_settings_interface->SetFloatValue(section, key, value);
QtHost::QueueSettingsSave();
}
void Host::SetBaseStringSettingValue(const char* section, const char* key, const char* value)
{
auto lock = Host::GetSettingsLock();
s_base_settings_interface->SetStringValue(section, key, value);
QtHost::QueueSettingsSave();
}
void Host::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);
QtHost::QueueSettingsSave();
}
bool Host::AddValueToBaseStringListSetting(const char* section, const char* key, const char* value)
{
auto lock = Host::GetSettingsLock();
if (!s_base_settings_interface->AddToStringList(section, key, value))
return false;
QtHost::QueueSettingsSave();
return true;
}
bool Host::RemoveValueFromBaseStringListSetting(const char* section, const char* key, const char* value)
{
auto lock = Host::GetSettingsLock();
if (!s_base_settings_interface->RemoveFromStringList(section, key, value))
return false;
QtHost::QueueSettingsSave();
return true;
}
void Host::DeleteBaseSettingValue(const char* section, const char* key)
{
auto lock = Host::GetSettingsLock();
s_base_settings_interface->DeleteValue(section, key);
QtHost::QueueSettingsSave();
}
void Host::CommitBaseSettingChanges()
{
if (g_emu_thread->isOnThread())

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M20 5H4v14l9.292-9.294a1 1 0 0 1 1.414 0L20 15.01V5zM2 3.993A1 1 0 0 1 2.992 3h18.016c.548 0 .992.445.992.993v16.014a1 1 0 0 1-.992.993H2.992A.993.993 0 0 1 2 20.007V3.993zM8 11a2 2 0 1 1 0-4 2 2 0 0 1 0 4z" fill="#000000"/></svg>

After

Width:  |  Height:  |  Size: 359 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M20 5H4v14l9.292-9.294a1 1 0 0 1 1.414 0L20 15.01V5zM2 3.993A1 1 0 0 1 2.992 3h18.016c.548 0 .992.445.992.993v16.014a1 1 0 0 1-.992.993H2.992A.993.993 0 0 1 2 20.007V3.993zM8 11a2 2 0 1 1 0-4 2 2 0 0 1 0 4z" fill="#ffffff"/></svg>

After

Width:  |  Height:  |  Size: 359 B

View File

@ -178,6 +178,7 @@
<file>icons/black/svg/gamepad-line.svg</file>
<file>icons/black/svg/global-line.svg</file>
<file>icons/black/svg/hard-drive-2-line.svg</file>
<file>icons/black/svg/image-fill.svg</file>
<file>icons/black/svg/keyboard-line.svg</file>
<file>icons/black/svg/layout-grid-line.svg</file>
<file>icons/black/svg/list-check.svg</file>
@ -508,6 +509,7 @@
<file>icons/white/svg/gamepad-line.svg</file>
<file>icons/white/svg/global-line.svg</file>
<file>icons/white/svg/hard-drive-2-line.svg</file>
<file>icons/white/svg/image-fill.svg</file>
<file>icons/white/svg/keyboard-line.svg</file>
<file>icons/white/svg/layout-grid-line.svg</file>
<file>icons/white/svg/list-check.svg</file>

View File

@ -407,6 +407,7 @@ void SettingsDialog::setBoolSettingValue(const char* section, const char* key, s
{
value.has_value() ? Host::SetBaseBoolSettingValue(section, key, value.value()) :
Host::DeleteBaseSettingValue(section, key);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
}
}
@ -423,6 +424,7 @@ void SettingsDialog::setIntSettingValue(const char* section, const char* key, st
{
value.has_value() ? Host::SetBaseIntSettingValue(section, key, value.value()) :
Host::DeleteBaseSettingValue(section, key);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
}
}
@ -439,6 +441,7 @@ void SettingsDialog::setFloatSettingValue(const char* section, const char* key,
{
value.has_value() ? Host::SetBaseFloatSettingValue(section, key, value.value()) :
Host::DeleteBaseSettingValue(section, key);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
}
}
@ -455,6 +458,7 @@ void SettingsDialog::setStringSettingValue(const char* section, const char* key,
{
value.has_value() ? Host::SetBaseStringSettingValue(section, key, value.value()) :
Host::DeleteBaseSettingValue(section, key);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
}
}
@ -470,6 +474,7 @@ void SettingsDialog::removeSettingValue(const char* section, const char* key)
else
{
Host::DeleteBaseSettingValue(section, key);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
}
}

View File

@ -651,6 +651,7 @@ static void BindWidgetToBoolSetting(SettingsInterface* sif, WidgetType* widget,
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const bool new_value = Accessor::getBoolValue(widget);
Host::SetBaseBoolSettingValue(section.c_str(), key.c_str(), new_value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
});
}
@ -694,6 +695,7 @@ static void BindWidgetToIntSetting(SettingsInterface* sif, WidgetType* widget, s
widget, [widget, section = std::move(section), key = std::move(key), option_offset]() {
const int new_value = Accessor::getIntValue(widget);
Host::SetBaseIntSettingValue(section.c_str(), key.c_str(), new_value + option_offset);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
});
}
@ -734,6 +736,7 @@ static void BindWidgetToFloatSetting(SettingsInterface* sif, WidgetType* widget,
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const float new_value = Accessor::getFloatValue(widget);
Host::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
});
}
@ -774,6 +777,7 @@ static void BindWidgetToNormalizedSetting(SettingsInterface* sif, WidgetType* wi
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), range]() {
const float new_value = (static_cast<float>(Accessor::getIntValue(widget)) / range);
Host::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
});
}
@ -819,6 +823,7 @@ static void BindWidgetToStringSetting(SettingsInterface* sif, WidgetType* widget
else
Host::DeleteBaseSettingValue(section.c_str(), key.c_str());
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
});
}
@ -884,6 +889,7 @@ static void BindWidgetToEnumSetting(SettingsInterface* sif, WidgetType* widget,
const DataType value = static_cast<DataType>(static_cast<UnderlyingType>(Accessor::getIntValue(widget)));
const char* string_value = to_string_function(value);
Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), string_value);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
});
}
@ -946,6 +952,7 @@ static void BindWidgetToEnumSetting(SettingsInterface* sif, WidgetType* widget,
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), enum_names]() {
const UnderlyingType value = static_cast<UnderlyingType>(Accessor::getIntValue(widget));
Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), enum_names[value]);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
});
}
@ -1010,6 +1017,7 @@ static void BindWidgetToEnumSetting(SettingsInterface* sif, WidgetType* widget,
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), enum_values]() {
const int value = Accessor::getIntValue(widget);
Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), enum_values[value]);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
});
}
@ -1054,6 +1062,7 @@ static void BindWidgetToFolderSetting(SettingsInterface* sif, WidgetType* widget
Host::DeleteBaseSettingValue(section.c_str(), key.c_str());
}
Host::CommitBaseSettingChanges();
g_emu_thread->updateEmuFolders();
});