mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-25 15:15:40 +00:00
Qt: PCSX2 UI fix backports
This commit is contained in:
parent
546f73e36a
commit
dd1a00674d
|
@ -32,7 +32,8 @@ ControllerGlobalSettingsWidget::ControllerGlobalSettingsWidget(QWidget* parent,
|
|||
m_ui.enableXInputSource->setEnabled(false);
|
||||
m_ui.enableRawInput->setEnabled(false);
|
||||
#endif
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableMouseMapping, "UI", "EnableMouseMapping", false);
|
||||
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableMouseMapping, "UI", "EnableMouseMapping",
|
||||
false);
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.multitapMode, "ControllerPorts", "MultitapMode",
|
||||
&Settings::ParseMultitapModeName, &Settings::GetMultitapModeName,
|
||||
Settings::DEFAULT_MULTITAP_MODE);
|
||||
|
|
|
@ -114,11 +114,11 @@ const char* GameListModel::getColumnName(Column col)
|
|||
return s_column_names[static_cast<int>(col)];
|
||||
}
|
||||
|
||||
GameListModel::GameListModel(QObject* parent /* = nullptr */)
|
||||
: QAbstractTableModel(parent), m_cover_pixmap_cache(MIN_COVER_CACHE_SIZE)
|
||||
GameListModel::GameListModel(float cover_scale, bool show_cover_titles, QObject* parent /* = nullptr */)
|
||||
: QAbstractTableModel(parent), m_show_titles_for_covers(show_cover_titles)
|
||||
{
|
||||
loadCommonImages();
|
||||
setCoverScale(1.0f);
|
||||
setCoverScale(cover_scale);
|
||||
setColumnDisplayNames();
|
||||
}
|
||||
GameListModel::~GameListModel() = default;
|
||||
|
@ -132,6 +132,8 @@ void GameListModel::setCoverScale(float scale)
|
|||
m_cover_scale = scale;
|
||||
m_loading_pixmap = QPixmap(getCoverArtWidth(), getCoverArtHeight());
|
||||
m_loading_pixmap.fill(QColor(0, 0, 0, 0));
|
||||
|
||||
emit coverScaleChanged();
|
||||
}
|
||||
|
||||
void GameListModel::refreshCovers()
|
||||
|
@ -150,9 +152,9 @@ void GameListModel::updateCacheSize(int width, int height)
|
|||
m_cover_pixmap_cache.SetMaxCapacity(static_cast<int>(std::max(num_columns * num_rows, MIN_COVER_CACHE_SIZE)));
|
||||
}
|
||||
|
||||
void GameListModel::reloadCommonImages()
|
||||
void GameListModel::reloadThemeSpecificImages()
|
||||
{
|
||||
loadCommonImages();
|
||||
loadThemeSpecificImages();
|
||||
refresh();
|
||||
}
|
||||
|
||||
|
@ -585,17 +587,24 @@ bool GameListModel::lessThan(const QModelIndex& left_index, const QModelIndex& r
|
|||
}
|
||||
}
|
||||
|
||||
void GameListModel::loadCommonImages()
|
||||
void GameListModel::loadThemeSpecificImages()
|
||||
{
|
||||
for (u32 i = 0; i < static_cast<u32>(GameList::EntryType::Count); i++)
|
||||
m_type_pixmaps[i] = QtUtils::GetIconForEntryType(static_cast<GameList::EntryType>(i)).pixmap(QSize(24, 24));
|
||||
|
||||
for (u32 i = 0; i < static_cast<u32>(DiscRegion::Count); i++)
|
||||
m_region_pixmaps[i] = QtUtils::GetIconForRegion(static_cast<DiscRegion>(i)).pixmap(42, 30);
|
||||
}
|
||||
|
||||
void GameListModel::loadCommonImages()
|
||||
{
|
||||
loadThemeSpecificImages();
|
||||
|
||||
for (int i = 0; i < static_cast<int>(GameDatabase::CompatibilityRating::Count); i++)
|
||||
{
|
||||
m_compatibility_pixmaps[i] =
|
||||
QtUtils::GetIconForCompatibility(static_cast<GameDatabase::CompatibilityRating>(i)).pixmap(96, 24);
|
||||
}
|
||||
|
||||
m_placeholder_pixmap.load(QStringLiteral("%1/images/cover-placeholder.png").arg(QtHost::GetResourcesBasePath()));
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
static std::optional<Column> getColumnIdForName(std::string_view name);
|
||||
static const char* getColumnName(Column col);
|
||||
|
||||
GameListModel(QObject* parent = nullptr);
|
||||
GameListModel(float cover_scale, bool show_cover_titles, QObject* parent = nullptr);
|
||||
~GameListModel();
|
||||
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
|
@ -56,6 +56,7 @@ public:
|
|||
ALWAYS_INLINE const QString& getColumnDisplayName(int column) { return m_column_display_names[column]; }
|
||||
|
||||
void refresh();
|
||||
void reloadThemeSpecificImages();
|
||||
|
||||
bool titlesLessThan(int left_row, int right_row) const;
|
||||
|
||||
|
@ -71,10 +72,13 @@ public:
|
|||
int getCoverArtSpacing() const;
|
||||
void refreshCovers();
|
||||
void updateCacheSize(int width, int height);
|
||||
void reloadCommonImages();
|
||||
|
||||
Q_SIGNALS:
|
||||
void coverScaleChanged();
|
||||
|
||||
private:
|
||||
void loadCommonImages();
|
||||
void loadThemeSpecificImages();
|
||||
void setColumnDisplayNames();
|
||||
void loadOrGenerateCover(const GameList::Entry* ge);
|
||||
void invalidateCoverForPath(const std::string& path);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#include "gamelistwidget.h"
|
||||
|
@ -20,6 +20,7 @@
|
|||
#include <QtGui/QWheelEvent>
|
||||
#include <QtWidgets/QHeaderView>
|
||||
#include <QtWidgets/QMenu>
|
||||
#include <QtWidgets/QScrollBar>
|
||||
|
||||
static constexpr float MIN_SCALE = 0.1f;
|
||||
static constexpr float MAX_SCALE = 2.0f;
|
||||
|
@ -91,9 +92,9 @@ GameListWidget::~GameListWidget() = default;
|
|||
|
||||
void GameListWidget::initialize()
|
||||
{
|
||||
m_model = new GameListModel(this);
|
||||
m_model->setCoverScale(Host::GetBaseFloatSettingValue("UI", "GameListCoverArtScale", 0.45f));
|
||||
m_model->setShowCoverTitles(Host::GetBaseBoolSettingValue("UI", "GameListShowCoverTitles", true));
|
||||
const float cover_scale = Host::GetBaseFloatSettingValue("UI", "GameListCoverArtScale", 0.45f);
|
||||
const bool show_cover_titles = Host::GetBaseBoolSettingValue("UI", "GameListShowCoverTitles", true);
|
||||
m_model = new GameListModel(cover_scale, show_cover_titles, this);
|
||||
m_model->updateCacheSize(width(), height());
|
||||
|
||||
m_sort_model = new GameListSortModel(m_model);
|
||||
|
@ -162,17 +163,16 @@ void GameListWidget::initialize()
|
|||
m_list_view = new GameListGridListView(m_ui.stack);
|
||||
m_list_view->setModel(m_sort_model);
|
||||
m_list_view->setModelColumn(GameListModel::Column_Cover);
|
||||
m_list_view->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
m_list_view->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
m_list_view->setViewMode(QListView::IconMode);
|
||||
m_list_view->setResizeMode(QListView::Adjust);
|
||||
m_list_view->setUniformItemSizes(true);
|
||||
m_list_view->setItemAlignment(Qt::AlignHCenter);
|
||||
m_list_view->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
m_list_view->setFrameStyle(QFrame::NoFrame);
|
||||
m_list_view->setSpacing(m_model->getCoverArtSpacing());
|
||||
m_list_view->setVerticalScrollMode(QAbstractItemView::ScrollMode::ScrollPerPixel);
|
||||
|
||||
updateListFont();
|
||||
m_list_view->verticalScrollBar()->setSingleStep(15);
|
||||
onCoverScaleChanged();
|
||||
|
||||
connect(m_list_view->selectionModel(), &QItemSelectionModel::currentChanged, this,
|
||||
&GameListWidget::onSelectionModelCurrentChanged);
|
||||
|
@ -180,6 +180,7 @@ void GameListWidget::initialize()
|
|||
connect(m_list_view, &GameListGridListView::zoomOut, this, &GameListWidget::gridZoomOut);
|
||||
connect(m_list_view, &QListView::activated, this, &GameListWidget::onListViewItemActivated);
|
||||
connect(m_list_view, &QListView::customContextMenuRequested, this, &GameListWidget::onListViewContextMenuRequested);
|
||||
connect(m_model, &GameListModel::coverScaleChanged, this, &GameListWidget::onCoverScaleChanged);
|
||||
|
||||
m_ui.stack->insertWidget(1, m_list_view);
|
||||
|
||||
|
@ -237,6 +238,11 @@ void GameListWidget::cancelRefresh()
|
|||
AssertMsg(!m_refresh_thread, "Game list thread should be unreferenced by now");
|
||||
}
|
||||
|
||||
void GameListWidget::reloadThemeSpecificImages()
|
||||
{
|
||||
m_model->reloadThemeSpecificImages();
|
||||
}
|
||||
|
||||
void GameListWidget::onRefreshProgress(const QString& status, int current, int total)
|
||||
{
|
||||
// switch away from the placeholder while we scan, in case we find anything
|
||||
|
@ -326,14 +332,23 @@ void GameListWidget::onTableViewHeaderSortIndicatorChanged(int, Qt::SortOrder)
|
|||
saveTableViewColumnSortSettings();
|
||||
}
|
||||
|
||||
void GameListWidget::onCoverScaleChanged()
|
||||
{
|
||||
m_model->updateCacheSize(width(), height());
|
||||
|
||||
m_list_view->setSpacing(m_model->getCoverArtSpacing());
|
||||
|
||||
QFont font;
|
||||
font.setPointSizeF(16.0f * m_model->getCoverScale());
|
||||
m_list_view->setFont(font);
|
||||
}
|
||||
|
||||
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();
|
||||
updateToolbar();
|
||||
|
||||
m_model->refresh();
|
||||
|
@ -356,8 +371,6 @@ void GameListWidget::gridIntScale(int int_scale)
|
|||
Host::SetBaseFloatSettingValue("UI", "GameListCoverArtScale", new_scale);
|
||||
Host::CommitBaseSettingChanges();
|
||||
m_model->setCoverScale(new_scale);
|
||||
m_model->updateCacheSize(width(), height());
|
||||
updateListFont();
|
||||
updateToolbar();
|
||||
|
||||
m_model->refresh();
|
||||
|
@ -416,13 +429,6 @@ void GameListWidget::setShowCoverTitles(bool enabled)
|
|||
emit layoutChange();
|
||||
}
|
||||
|
||||
void GameListWidget::updateListFont()
|
||||
{
|
||||
QFont font;
|
||||
font.setPointSizeF(16.0f * m_model->getCoverScale());
|
||||
m_list_view->setFont(font);
|
||||
}
|
||||
|
||||
void GameListWidget::updateToolbar()
|
||||
{
|
||||
const bool grid_view = isShowingGameGrid();
|
||||
|
@ -473,11 +479,6 @@ void GameListWidget::resizeTableViewColumnsToFit()
|
|||
});
|
||||
}
|
||||
|
||||
void GameListWidget::reloadCommonImages()
|
||||
{
|
||||
m_model->reloadCommonImages();
|
||||
}
|
||||
|
||||
static TinyString getColumnVisibilitySettingsKeyName(int column)
|
||||
{
|
||||
return TinyString::FromFormat("Show%s", GameListModel::getColumnName(static_cast<GameListModel::Column>(column)));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
|
@ -43,10 +43,10 @@ public:
|
|||
|
||||
void initialize();
|
||||
void resizeTableViewColumnsToFit();
|
||||
void reloadCommonImages();
|
||||
|
||||
void refresh(bool invalidate_cache);
|
||||
void cancelRefresh();
|
||||
void reloadThemeSpecificImages();
|
||||
|
||||
bool isShowingGameList() const;
|
||||
bool isShowingGameGrid() const;
|
||||
|
@ -76,6 +76,7 @@ private Q_SLOTS:
|
|||
void onTableViewHeaderSortIndicatorChanged(int, Qt::SortOrder);
|
||||
void onListViewItemActivated(const QModelIndex& index);
|
||||
void onListViewContextMenuRequested(const QPoint& point);
|
||||
void onCoverScaleChanged();
|
||||
|
||||
public Q_SLOTS:
|
||||
void showGameList();
|
||||
|
@ -96,7 +97,6 @@ private:
|
|||
void loadTableViewColumnSortSettings();
|
||||
void saveTableViewColumnSortSettings();
|
||||
void listZoom(float delta);
|
||||
void updateListFont();
|
||||
void updateToolbar();
|
||||
|
||||
Ui::GameListWidget m_ui;
|
||||
|
|
|
@ -135,7 +135,7 @@ void InputBindingDialog::startListeningForInput(u32 timeout_in_seconds)
|
|||
{
|
||||
m_value_ranges.clear();
|
||||
m_new_bindings.clear();
|
||||
m_mouse_mapping_enabled = InputBindingWidget::isMouseMappingEnabled();
|
||||
m_mouse_mapping_enabled = InputBindingWidget::isMouseMappingEnabled(m_sif);
|
||||
m_input_listen_start_position = QCursor::pos();
|
||||
m_input_listen_timer = new QTimer(this);
|
||||
m_input_listen_timer->setSingleShot(false);
|
||||
|
|
|
@ -42,9 +42,10 @@ InputBindingWidget::~InputBindingWidget()
|
|||
Q_ASSERT(!isListeningForInput());
|
||||
}
|
||||
|
||||
bool InputBindingWidget::isMouseMappingEnabled()
|
||||
bool InputBindingWidget::isMouseMappingEnabled(SettingsInterface* sif)
|
||||
{
|
||||
return Host::GetBaseBoolSettingValue("UI", "EnableMouseMapping", false);
|
||||
return sif ? sif->GetBoolValue("UI", "EnableMouseMapping", false) :
|
||||
Host::GetBaseBoolSettingValue("UI", "EnableMouseMapping", false);
|
||||
}
|
||||
|
||||
void InputBindingWidget::initialize(SettingsInterface* sif, InputBindingInfo::Type bind_type, std::string section_name,
|
||||
|
@ -287,7 +288,7 @@ void InputBindingWidget::startListeningForInput(u32 timeout_in_seconds)
|
|||
{
|
||||
m_value_ranges.clear();
|
||||
m_new_bindings.clear();
|
||||
m_mouse_mapping_enabled = isMouseMappingEnabled();
|
||||
m_mouse_mapping_enabled = isMouseMappingEnabled(m_sif);
|
||||
m_input_listen_start_position = QCursor::pos();
|
||||
m_input_listen_timer = new QTimer(this);
|
||||
m_input_listen_timer->setSingleShot(false);
|
||||
|
|
|
@ -22,7 +22,7 @@ public:
|
|||
std::string section_name, std::string key_name);
|
||||
~InputBindingWidget();
|
||||
|
||||
static bool isMouseMappingEnabled();
|
||||
static bool isMouseMappingEnabled(SettingsInterface* sif);
|
||||
|
||||
void initialize(SettingsInterface* sif, InputBindingInfo::Type bind_type, std::string section_name,
|
||||
std::string key_name);
|
||||
|
|
|
@ -1417,13 +1417,25 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
|
|||
|
||||
void MainWindow::setGameListEntryCoverImage(const GameList::Entry* entry)
|
||||
{
|
||||
QString filename = QFileDialog::getOpenFileName(this, tr("Select Cover Image"), QString(),
|
||||
tr("All Cover Image Types (*.jpg *.jpeg *.png)"));
|
||||
const QString filename = QDir::toNativeSeparators(QFileDialog::getOpenFileName(
|
||||
this, tr("Select Cover Image"), QString(), tr("All Cover Image Types (*.jpg *.jpeg *.png *.webp)")));
|
||||
if (filename.isEmpty())
|
||||
return;
|
||||
|
||||
if (!GameList::GetCoverImagePathForEntry(entry).empty())
|
||||
const QString old_filename = QString::fromStdString(GameList::GetCoverImagePathForEntry(entry));
|
||||
const QString new_filename =
|
||||
QString::fromStdString(GameList::GetNewCoverImagePathForEntry(entry, filename.toUtf8().constData(), false));
|
||||
if (new_filename.isEmpty())
|
||||
return;
|
||||
|
||||
if (!old_filename.isEmpty())
|
||||
{
|
||||
if (QFileInfo(old_filename) == QFileInfo(filename))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Copy Error"), tr("You must select a different file to the current cover image."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (QMessageBox::question(this, tr("Cover Already Exists"),
|
||||
tr("A cover image for this game already exists, do you wish to replace it?"),
|
||||
QMessageBox::Yes, QMessageBox::No) != QMessageBox::Yes)
|
||||
|
@ -1432,23 +1444,21 @@ void MainWindow::setGameListEntryCoverImage(const GameList::Entry* entry)
|
|||
}
|
||||
}
|
||||
|
||||
QString new_filename =
|
||||
QString::fromStdString(GameList::GetNewCoverImagePathForEntry(entry, filename.toStdString().c_str(), false));
|
||||
if (new_filename.isEmpty())
|
||||
return;
|
||||
|
||||
if (QFile::exists(new_filename) && !QFile::remove(new_filename))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Copy Error"), tr("Failed to remove existing cover '%1'").arg(new_filename));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!QFile::copy(filename, new_filename))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Copy Error"), tr("Failed to copy '%1' to '%2'").arg(filename).arg(new_filename));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!old_filename.isEmpty() && old_filename != new_filename && !QFile::remove(old_filename))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Copy Error"), tr("Failed to remove '%1'").arg(old_filename));
|
||||
return;
|
||||
}
|
||||
m_game_list_widget->refreshGridCovers();
|
||||
}
|
||||
|
||||
|
@ -2068,7 +2078,12 @@ void MainWindow::updateTheme()
|
|||
{
|
||||
updateApplicationTheme();
|
||||
updateMenuSelectedTheme();
|
||||
m_game_list_widget->reloadCommonImages();
|
||||
reloadThemeSpecificImages();
|
||||
}
|
||||
|
||||
void MainWindow::reloadThemeSpecificImages()
|
||||
{
|
||||
m_game_list_widget->reloadThemeSpecificImages();
|
||||
}
|
||||
|
||||
void MainWindow::setStyleFromSettings()
|
||||
|
@ -2405,6 +2420,12 @@ void MainWindow::changeEvent(QEvent* event)
|
|||
g_emu_thread->redrawDisplayWindow();
|
||||
}
|
||||
|
||||
if (event->type() == QEvent::StyleChange)
|
||||
{
|
||||
setIconThemeFromSettings();
|
||||
reloadThemeSpecificImages();
|
||||
}
|
||||
|
||||
QMainWindow::changeEvent(event);
|
||||
}
|
||||
|
||||
|
|
|
@ -239,6 +239,7 @@ private:
|
|||
void clearGameListEntryPlayTime(const GameList::Entry* entry);
|
||||
void setTheme(const QString& theme);
|
||||
void updateTheme();
|
||||
void reloadThemeSpecificImages();
|
||||
void recreate();
|
||||
|
||||
void registerForDeviceNotifications();
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "core/settings.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/file_system.h"
|
||||
#include "common/path.h"
|
||||
|
||||
#include <QtCore/QtCore>
|
||||
|
@ -22,6 +23,7 @@
|
|||
#include <QtWidgets/QFileDialog>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QMenu>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QSlider>
|
||||
#include <QtWidgets/QSpinBox>
|
||||
#include <optional>
|
||||
|
@ -1030,22 +1032,20 @@ static void BindWidgetToEnumSetting(SettingsInterface* sif, WidgetType* widget,
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
static inline void BindWidgetToFolderSetting(SettingsInterface* sif, QLineEdit* widget, QAbstractButton* browse_button,
|
||||
QAbstractButton* open_button, QAbstractButton* reset_button,
|
||||
std::string section, std::string key, std::string default_value,
|
||||
bool use_relative = true)
|
||||
{
|
||||
using Accessor = SettingAccessor<WidgetType>;
|
||||
using Accessor = SettingAccessor<QLineEdit>;
|
||||
|
||||
std::string current_path(Host::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value.c_str()));
|
||||
if (current_path.empty())
|
||||
current_path = default_value;
|
||||
else if (!Path::IsAbsolute(current_path))
|
||||
current_path = Path::Combine(EmuFolders::DataRoot, current_path);
|
||||
|
||||
else if (use_relative && !Path::IsAbsolute(current_path))
|
||||
current_path = Path::Canonicalize(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)
|
||||
{
|
||||
|
@ -1057,32 +1057,65 @@ static void BindWidgetToFolderSetting(SettingsInterface* sif, WidgetType* widget
|
|||
return;
|
||||
}
|
||||
|
||||
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
|
||||
const std::string new_value(Accessor::getStringValue(widget).toStdString());
|
||||
auto value_changed = [widget, section = std::move(section), key = std::move(key), default_value, use_relative]() {
|
||||
const std::string new_value(widget->text().toStdString());
|
||||
if (!new_value.empty())
|
||||
{
|
||||
std::string relative_path(Path::MakeRelative(new_value, EmuFolders::DataRoot));
|
||||
if (FileSystem::DirectoryExists(new_value.c_str()) ||
|
||||
QMessageBox::question(
|
||||
QtUtils::GetRootWidget(widget), qApp->translate("SettingWidgetBinder", "Confirm Folder"),
|
||||
qApp
|
||||
->translate(
|
||||
"SettingWidgetBinder",
|
||||
"The chosen directory does not currently exist:\n\n%1\n\nDo you want to create this directory?")
|
||||
.arg(QString::fromStdString(new_value)),
|
||||
QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
|
||||
{
|
||||
if (use_relative)
|
||||
{
|
||||
const std::string relative_path(Path::MakeRelative(new_value, EmuFolders::DataRoot));
|
||||
Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), relative_path.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
Host::DeleteBaseSettingValue(section.c_str(), key.c_str());
|
||||
Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), new_value.c_str());
|
||||
}
|
||||
|
||||
Host::CommitBaseSettingChanges();
|
||||
g_emu_thread->updateEmuFolders();
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(QtUtils::GetRootWidget(widget), qApp->translate("SettingWidgetBinder", "Error"),
|
||||
qApp->translate("SettingWidgetBinder", "Folder path cannot be empty."));
|
||||
}
|
||||
|
||||
// reset to old value
|
||||
std::string current_path(Host::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value.c_str()));
|
||||
if (current_path.empty())
|
||||
current_path = default_value;
|
||||
else if (use_relative && !Path::IsAbsolute(current_path))
|
||||
current_path = Path::Canonicalize(Path::Combine(EmuFolders::DataRoot, current_path));
|
||||
|
||||
widget->setText(QString::fromStdString(current_path));
|
||||
};
|
||||
|
||||
if (browse_button)
|
||||
{
|
||||
QObject::connect(browse_button, &QAbstractButton::clicked, browse_button, [widget, key]() {
|
||||
QObject::connect(browse_button, &QAbstractButton::clicked, browse_button, [widget, key, value_changed]() {
|
||||
const QString path(QDir::toNativeSeparators(QFileDialog::getExistingDirectory(
|
||||
QtUtils::GetRootWidget(widget),
|
||||
// It seems that the latter half should show the types of folders that can be selected within Settings ->
|
||||
// Folders, but right now it's broken. It would be best for localization purposes to duplicate this into
|
||||
// multiple lines, each per type of folder.
|
||||
qApp->translate("SettingWidgetBinder", "Select folder for %1").arg(QString::fromStdString(key)))));
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
Accessor::setStringValue(widget, path);
|
||||
widget->setText(path);
|
||||
value_changed();
|
||||
});
|
||||
}
|
||||
if (open_button)
|
||||
|
@ -1096,9 +1129,12 @@ static void BindWidgetToFolderSetting(SettingsInterface* sif, WidgetType* widget
|
|||
if (reset_button)
|
||||
{
|
||||
QObject::connect(reset_button, &QAbstractButton::clicked, reset_button,
|
||||
[widget, default_value = std::move(default_value)]() {
|
||||
Accessor::setStringValue(widget, QString::fromStdString(default_value));
|
||||
[widget, default_value = std::move(default_value), value_changed]() {
|
||||
widget->setText(QString::fromStdString(default_value));
|
||||
value_changed();
|
||||
});
|
||||
}
|
||||
|
||||
widget->connect(widget, &QLineEdit::editingFinished, widget, std::move(value_changed));
|
||||
}
|
||||
} // namespace SettingWidgetBinder
|
||||
|
|
Loading…
Reference in a new issue