mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-30 01:25:51 +00:00
FullscreenUI: Various improvements
This commit is contained in:
parent
91c8681bed
commit
ef3ad91ad0
|
@ -69,7 +69,7 @@ public:
|
||||||
|
|
||||||
void Evict(std::size_t count = 1)
|
void Evict(std::size_t count = 1)
|
||||||
{
|
{
|
||||||
while (m_items.size() >= count)
|
while (!m_items.empty() && count > 0)
|
||||||
{
|
{
|
||||||
typename MapType::iterator lowest = m_items.end();
|
typename MapType::iterator lowest = m_items.end();
|
||||||
for (auto iter = m_items.begin(); iter != m_items.end(); ++iter)
|
for (auto iter = m_items.begin(); iter != m_items.end(); ++iter)
|
||||||
|
@ -78,6 +78,7 @@ public:
|
||||||
lowest = iter;
|
lowest = iter;
|
||||||
}
|
}
|
||||||
m_items.erase(lowest);
|
m_items.erase(lowest);
|
||||||
|
count--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,23 +88,20 @@ public:
|
||||||
auto iter = m_items.find(key);
|
auto iter = m_items.find(key);
|
||||||
if (iter == m_items.end())
|
if (iter == m_items.end())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_items.erase(iter);
|
m_items.erase(iter);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetManualEvict(bool block)
|
void SetManualEvict(bool block)
|
||||||
{
|
{
|
||||||
m_manual_evict = block;
|
m_manual_evict = block;
|
||||||
if (!m_manual_evict)
|
if (!m_manual_evict)
|
||||||
ManualEvict();
|
ManualEvict();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManualEvict()
|
void ManualEvict()
|
||||||
{
|
{
|
||||||
// evict if we went over
|
// evict if we went over
|
||||||
while (m_items.size() > m_max_capacity)
|
while (m_items.size() > m_max_capacity)
|
||||||
Evict(m_items.size() - (m_max_capacity - 1));
|
Evict(m_items.size() - m_max_capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -255,6 +255,31 @@ std::vector<std::string_view> StringUtil::SplitString(const std::string_view& st
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> StringUtil::SplitNewString(const std::string_view& str, char delimiter,
|
||||||
|
bool skip_empty /*= true*/)
|
||||||
|
{
|
||||||
|
std::vector<std::string> res;
|
||||||
|
std::string_view::size_type last_pos = 0;
|
||||||
|
std::string_view::size_type pos;
|
||||||
|
while (last_pos < str.size() && (pos = str.find(delimiter, last_pos)) != std::string_view::npos)
|
||||||
|
{
|
||||||
|
std::string_view part(StripWhitespace(str.substr(last_pos, pos - last_pos)));
|
||||||
|
if (!skip_empty || !part.empty())
|
||||||
|
res.emplace_back(part);
|
||||||
|
|
||||||
|
last_pos = pos + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_pos < str.size())
|
||||||
|
{
|
||||||
|
std::string_view part(StripWhitespace(str.substr(last_pos)));
|
||||||
|
if (!skip_empty || !part.empty())
|
||||||
|
res.emplace_back(part);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
std::string StringUtil::ReplaceAll(const std::string_view& subject, const std::string_view& search,
|
std::string StringUtil::ReplaceAll(const std::string_view& subject, const std::string_view& search,
|
||||||
const std::string_view& replacement)
|
const std::string_view& replacement)
|
||||||
{
|
{
|
||||||
|
|
|
@ -149,6 +149,7 @@ void StripWhitespace(std::string* str);
|
||||||
|
|
||||||
/// Splits a string based on a single character delimiter.
|
/// Splits a string based on a single character delimiter.
|
||||||
std::vector<std::string_view> SplitString(const std::string_view& str, char delimiter, bool skip_empty = true);
|
std::vector<std::string_view> SplitString(const std::string_view& str, char delimiter, bool skip_empty = true);
|
||||||
|
std::vector<std::string> SplitNewString(const std::string_view& str, char delimiter, bool skip_empty = true);
|
||||||
|
|
||||||
/// Joins a string together using the specified delimiter.
|
/// Joins a string together using the specified delimiter.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -376,68 +376,6 @@ void Host::CheckForSettingsChanges(const Settings& old_settings)
|
||||||
CommonHost::CheckForSettingsChanges(old_settings);
|
CommonHost::CheckForSettingsChanges(old_settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::SetBaseBoolSettingValue(const char* section, const char* key, bool value)
|
|
||||||
{
|
|
||||||
auto lock = Host::GetSettingsLock();
|
|
||||||
s_base_settings_interface->SetBoolValue(section, key, value);
|
|
||||||
NoGUIHost::SaveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Host::SetBaseIntSettingValue(const char* section, const char* key, int value)
|
|
||||||
{
|
|
||||||
auto lock = Host::GetSettingsLock();
|
|
||||||
s_base_settings_interface->SetIntValue(section, key, value);
|
|
||||||
NoGUIHost::SaveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Host::SetBaseFloatSettingValue(const char* section, const char* key, float value)
|
|
||||||
{
|
|
||||||
auto lock = Host::GetSettingsLock();
|
|
||||||
s_base_settings_interface->SetFloatValue(section, key, value);
|
|
||||||
NoGUIHost::SaveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Host::SetBaseStringSettingValue(const char* section, const char* key, const char* value)
|
|
||||||
{
|
|
||||||
auto lock = Host::GetSettingsLock();
|
|
||||||
s_base_settings_interface->SetStringValue(section, key, value);
|
|
||||||
NoGUIHost::SaveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
NoGUIHost::SaveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
NoGUIHost::SaveSettings();
|
|
||||||
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;
|
|
||||||
|
|
||||||
NoGUIHost::SaveSettings();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Host::DeleteBaseSettingValue(const char* section, const char* key)
|
|
||||||
{
|
|
||||||
auto lock = Host::GetSettingsLock();
|
|
||||||
s_base_settings_interface->DeleteValue(section, key);
|
|
||||||
NoGUIHost::SaveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Host::CommitBaseSettingChanges()
|
void Host::CommitBaseSettingChanges()
|
||||||
{
|
{
|
||||||
NoGUIHost::SaveSettings();
|
NoGUIHost::SaveSettings();
|
||||||
|
@ -1008,23 +946,6 @@ void Host::CancelGameListRefresh()
|
||||||
NoGUIHost::CancelAsyncOp();
|
NoGUIHost::CancelAsyncOp();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::DownloadCoversAsync(std::vector<std::string> url_templates)
|
|
||||||
{
|
|
||||||
NoGUIHost::StartAsyncOp([url_templates = std::move(url_templates)](ProgressCallback* progress) {
|
|
||||||
GameList::DownloadCovers(url_templates, progress);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void Host::CancelCoversDownload()
|
|
||||||
{
|
|
||||||
NoGUIHost::CancelAsyncOp();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Host::CoversChanged()
|
|
||||||
{
|
|
||||||
Host::RunOnCPUThread([]() { FullscreenUI::InvalidateCoverCache(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Host::IsFullscreen()
|
bool Host::IsFullscreen()
|
||||||
{
|
{
|
||||||
return s_is_fullscreen;
|
return s_is_fullscreen;
|
||||||
|
|
|
@ -162,6 +162,7 @@ void AudioSettingsWidget::onOutputVolumeChanged(int new_value)
|
||||||
// only called for base settings
|
// only called for base settings
|
||||||
DebugAssert(!m_dialog->isPerGameSettings());
|
DebugAssert(!m_dialog->isPerGameSettings());
|
||||||
Host::SetBaseIntSettingValue("Audio", "OutputVolume", new_value);
|
Host::SetBaseIntSettingValue("Audio", "OutputVolume", new_value);
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->setAudioOutputVolume(new_value, m_ui.fastForwardVolume->value());
|
g_emu_thread->setAudioOutputVolume(new_value, m_ui.fastForwardVolume->value());
|
||||||
|
|
||||||
updateVolumeLabel();
|
updateVolumeLabel();
|
||||||
|
@ -172,6 +173,7 @@ void AudioSettingsWidget::onFastForwardVolumeChanged(int new_value)
|
||||||
// only called for base settings
|
// only called for base settings
|
||||||
DebugAssert(!m_dialog->isPerGameSettings());
|
DebugAssert(!m_dialog->isPerGameSettings());
|
||||||
Host::SetBaseIntSettingValue("Audio", "FastForwardVolume", new_value);
|
Host::SetBaseIntSettingValue("Audio", "FastForwardVolume", new_value);
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->setAudioOutputVolume(m_ui.volume->value(), new_value);
|
g_emu_thread->setAudioOutputVolume(m_ui.volume->value(), new_value);
|
||||||
|
|
||||||
updateVolumeLabel();
|
updateVolumeLabel();
|
||||||
|
@ -184,5 +186,6 @@ void AudioSettingsWidget::onOutputMutedChanged(int new_state)
|
||||||
|
|
||||||
const bool muted = (new_state != 0);
|
const bool muted = (new_state != 0);
|
||||||
Host::SetBaseBoolSettingValue("Audio", "OutputMuted", muted);
|
Host::SetBaseBoolSettingValue("Audio", "OutputMuted", muted);
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->setAudioOutputMuted(muted);
|
g_emu_thread->setAudioOutputMuted(muted);
|
||||||
}
|
}
|
||||||
|
|
|
@ -436,6 +436,7 @@ bool AutoUpdaterDialog::updateNeeded() const
|
||||||
void AutoUpdaterDialog::skipThisUpdateClicked()
|
void AutoUpdaterDialog::skipThisUpdateClicked()
|
||||||
{
|
{
|
||||||
Host::SetBaseStringSettingValue("AutoUpdater", "LastVersion", m_latest_sha.toUtf8().constData());
|
Host::SetBaseStringSettingValue("AutoUpdater", "LastVersion", m_latest_sha.toUtf8().constData());
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
done(0);
|
done(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -156,6 +156,7 @@ void ConsoleSettingsWidget::onEnableCPUClockSpeedControlChecked(int state)
|
||||||
}
|
}
|
||||||
|
|
||||||
Host::SetBaseBoolSettingValue("UI", "CPUOverclockingWarningShown", true);
|
Host::SetBaseBoolSettingValue("UI", "CPUOverclockingWarningShown", true);
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ui.cpuClockSpeed->setEnabled(m_dialog->getEffectiveBoolValue("CPU", "OverclockEnable", false));
|
m_ui.cpuClockSpeed->setEnabled(m_dialog->getEffectiveBoolValue("CPU", "OverclockEnable", false));
|
||||||
|
|
|
@ -177,6 +177,7 @@ void ControllerBindingWidget::onTypeChanged()
|
||||||
{
|
{
|
||||||
Host::SetBaseStringSettingValue(m_config_section.c_str(), "Type",
|
Host::SetBaseStringSettingValue(m_config_section.c_str(), "Type",
|
||||||
Settings::GetControllerTypeName(m_controller_type));
|
Settings::GetControllerTypeName(m_controller_type));
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->applySettings();
|
g_emu_thread->applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -308,6 +308,7 @@ void ControllerSettingsDialog::setStringValue(const char* section, const char* k
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Host::SetBaseStringSettingValue(section, key, value);
|
Host::SetBaseStringSettingValue(section, key, value);
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->applySettings();
|
g_emu_thread->applySettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ static void BindWidgetToInputProfileBool(SettingsInterface* sif, WidgetType* wid
|
||||||
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);
|
||||||
Host::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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -78,6 +79,7 @@ static void BindWidgetToInputProfileFloat(SettingsInterface* sif, WidgetType* wi
|
||||||
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);
|
||||||
Host::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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -110,6 +112,7 @@ static void BindWidgetToInputProfileNormalized(SettingsInterface* sif, WidgetTyp
|
||||||
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);
|
||||||
Host::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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -153,7 +156,7 @@ static void BindWidgetToInputProfileString(SettingsInterface* sif, WidgetType* w
|
||||||
Host::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
|
||||||
Host::DeleteBaseSettingValue(section.c_str(), key.c_str());
|
Host::DeleteBaseSettingValue(section.c_str(), key.c_str());
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->applySettings();
|
g_emu_thread->applySettings();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
CoverDownloadDialog::CoverDownloadDialog(QWidget* parent /*= nullptr*/) : QDialog(parent)
|
CoverDownloadDialog::CoverDownloadDialog(QWidget* parent /*= nullptr*/) : QDialog(parent)
|
||||||
{
|
{
|
||||||
m_ui.setupUi(this);
|
m_ui.setupUi(this);
|
||||||
|
m_ui.coverIcon->setPixmap(QIcon::fromTheme("image-fill").pixmap(32));
|
||||||
updateEnabled();
|
updateEnabled();
|
||||||
|
|
||||||
connect(m_ui.start, &QPushButton::clicked, this, &CoverDownloadDialog::onStartClicked);
|
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)
|
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)
|
if (m_last_refresh_time.GetTimeSeconds() >= 5.0f)
|
||||||
{
|
{
|
||||||
emit coverRefreshRequested();
|
emit coverRefreshRequested();
|
||||||
|
@ -83,7 +85,8 @@ void CoverDownloadDialog::updateEnabled()
|
||||||
|
|
||||||
void CoverDownloadDialog::startThread()
|
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::statusUpdated, this, &CoverDownloadDialog::onDownloadStatus);
|
||||||
connect(m_thread.get(), &CoverDownloadThread::progressUpdated, this, &CoverDownloadDialog::onDownloadProgress);
|
connect(m_thread.get(), &CoverDownloadThread::progressUpdated, this, &CoverDownloadDialog::onDownloadProgress);
|
||||||
connect(m_thread.get(), &CoverDownloadThread::threadFinished, this, &CoverDownloadDialog::onDownloadComplete);
|
connect(m_thread.get(), &CoverDownloadThread::threadFinished, this, &CoverDownloadDialog::onDownloadComplete);
|
||||||
|
@ -101,8 +104,8 @@ void CoverDownloadDialog::cancelThread()
|
||||||
m_thread.reset();
|
m_thread.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
CoverDownloadDialog::CoverDownloadThread::CoverDownloadThread(QWidget* parent, const QString& urls)
|
CoverDownloadDialog::CoverDownloadThread::CoverDownloadThread(QWidget* parent, const QString& urls, bool use_serials)
|
||||||
: QtAsyncProgressThread(parent)
|
: QtAsyncProgressThread(parent), m_use_serials(use_serials)
|
||||||
{
|
{
|
||||||
for (const QString& str : urls.split(QChar('\n')))
|
for (const QString& str : urls.split(QChar('\n')))
|
||||||
m_urls.push_back(str.toStdString());
|
m_urls.push_back(str.toStdString());
|
||||||
|
@ -112,5 +115,5 @@ CoverDownloadDialog::CoverDownloadThread::~CoverDownloadThread() = default;
|
||||||
|
|
||||||
void CoverDownloadDialog::CoverDownloadThread::runAsync()
|
void CoverDownloadDialog::CoverDownloadThread::runAsync()
|
||||||
{
|
{
|
||||||
GameList::DownloadCovers(m_urls, this);
|
GameList::DownloadCovers(m_urls, m_use_serials, this);
|
||||||
}
|
}
|
|
@ -34,7 +34,7 @@ private:
|
||||||
class CoverDownloadThread : public QtAsyncProgressThread
|
class CoverDownloadThread : public QtAsyncProgressThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CoverDownloadThread(QWidget* parent, const QString& urls);
|
CoverDownloadThread(QWidget* parent, const QString& urls, bool use_serials);
|
||||||
~CoverDownloadThread();
|
~CoverDownloadThread();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -42,6 +42,7 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> m_urls;
|
std::vector<std::string> m_urls;
|
||||||
|
bool m_use_serials;
|
||||||
};
|
};
|
||||||
|
|
||||||
void startThread();
|
void startThread();
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>656</width>
|
<width>720</width>
|
||||||
<height>343</height>
|
<height>380</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -15,9 +15,39 @@
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<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">
|
<property name="text">
|
||||||
<string><html><head/><body><p>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.</p><p>In the form below, specify the URLs to download covers from, with one template URL per line. The following variables are available:</p><p><span style=" font-style:italic;">${title}:</span> Title of the game.<br/><span style=" font-style:italic;">${filetitle}:</span> Name component of the game's filename.<br/><span style=" font-style:italic;">${serial}:</span> Serial of the game.</p><p><span style=" font-weight:700;">Example:</span> https://www.example-not-a-real-domain.com/covers/${serial}.jpg</p></body></html></string>
|
<string><html><head/><body><p>In the box below, specify the URLs to download covers from, with one template URL per line. The following variables are available:</p><p><span style=" font-style:italic;">${title}:</span> Title of the game.<br/><span style=" font-style:italic;">${filetitle}:</span> Name component of the game's filename.<br/><span style=" font-style:italic;">${serial}:</span> Serial of the game.</p><p><span style=" font-weight:700;">Example:</span> https://www.example-not-a-real-domain.com/covers/${serial}.jpg</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="wordWrap">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
@ -25,20 +55,24 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer">
|
<widget class="QTextEdit" name="urls"/>
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
</item>
|
||||||
<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 "Use Serial File Names" 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>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="status">
|
<widget class="QLabel" name="status">
|
||||||
|
@ -76,6 +110,8 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources>
|
||||||
|
<include location="resources/resources.qrc"/>
|
||||||
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
|
@ -225,7 +225,10 @@ bool DisplayWidget::event(QEvent* event)
|
||||||
|
|
||||||
if (ImGuiManager::WantsTextInput() && key_event->type() == QEvent::KeyPress)
|
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())
|
if (!text.isEmpty())
|
||||||
emit windowTextEntered(text);
|
emit windowTextEntered(text);
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,4 +176,6 @@ void GameListSearchDirectoriesModel::saveToSettings()
|
||||||
Host::DeleteBaseSettingValue("GameList", "RecursivePaths");
|
Host::DeleteBaseSettingValue("GameList", "RecursivePaths");
|
||||||
else
|
else
|
||||||
Host::SetBaseStringListSettingValue("GameList", "RecursivePaths", recursive_paths);
|
Host::SetBaseStringListSettingValue("GameList", "RecursivePaths", recursive_paths);
|
||||||
|
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ bool GameListSettingsWidget::addExcludedPath(const std::string& path)
|
||||||
if (!Host::AddValueToBaseStringListSetting("GameList", "ExcludedPaths", path.c_str()))
|
if (!Host::AddValueToBaseStringListSetting("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;
|
||||||
|
@ -158,7 +159,8 @@ void GameListSettingsWidget::onRemoveExcludedPathButtonClicked()
|
||||||
if (!item)
|
if (!item)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Host::RemoveValueFromBaseStringListSetting("GameList", "ExcludedPaths", item->text().toUtf8().constData());
|
if (Host::RemoveValueFromBaseStringListSetting("GameList", "ExcludedPaths", item->text().toUtf8().constData()))
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
delete item;
|
delete item;
|
||||||
|
|
||||||
g_main_window->refreshGameList(false);
|
g_main_window->refreshGameList(false);
|
||||||
|
|
|
@ -322,6 +322,7 @@ 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);
|
||||||
Host::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();
|
||||||
|
@ -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);
|
const float new_scale = std::clamp(static_cast<float>(int_scale) / 100.0f, MIN_SCALE, MAX_SCALE);
|
||||||
|
|
||||||
Host::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();
|
||||||
|
@ -367,6 +369,7 @@ void GameListWidget::showGameList()
|
||||||
}
|
}
|
||||||
|
|
||||||
Host::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();
|
||||||
|
@ -382,6 +385,7 @@ void GameListWidget::showGameGrid()
|
||||||
}
|
}
|
||||||
|
|
||||||
Host::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();
|
||||||
|
@ -396,6 +400,7 @@ void GameListWidget::setShowCoverTitles(bool enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
Host::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();
|
||||||
|
@ -499,6 +504,7 @@ void GameListWidget::saveTableViewColumnVisibilitySettings()
|
||||||
{
|
{
|
||||||
const bool visible = !m_table_view->isColumnHidden(column);
|
const bool visible = !m_table_view->isColumnHidden(column);
|
||||||
Host::SetBaseBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column), visible);
|
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);
|
const bool visible = !m_table_view->isColumnHidden(column);
|
||||||
Host::SetBaseBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column), visible);
|
Host::SetBaseBoolSettingValue("GameListTableView", getColumnVisibilitySettingsKeyName(column), visible);
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameListWidget::loadTableViewColumnSortSettings()
|
void GameListWidget::loadTableViewColumnSortSettings()
|
||||||
|
@ -533,6 +540,7 @@ void GameListWidget::saveTableViewColumnSortSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
Host::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
|
||||||
|
|
|
@ -238,6 +238,7 @@ void InputBindingDialog::saveListToSettings()
|
||||||
Host::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
|
||||||
Host::DeleteBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
|
Host::DeleteBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->reloadInputBindings();
|
g_emu_thread->reloadInputBindings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,6 +215,7 @@ void InputBindingWidget::setNewBinding()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Host::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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,6 +236,7 @@ void InputBindingWidget::clearBinding()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Host::DeleteBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
|
Host::DeleteBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->reloadInputBindings();
|
g_emu_thread->reloadInputBindings();
|
||||||
}
|
}
|
||||||
reloadBinding();
|
reloadBinding();
|
||||||
|
@ -391,6 +393,7 @@ void InputVibrationBindingWidget::clearBinding()
|
||||||
{
|
{
|
||||||
m_binding = {};
|
m_binding = {};
|
||||||
Host::DeleteBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
|
Host::DeleteBaseSettingValue(m_section_name.c_str(), m_key_name.c_str());
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->reloadInputBindings();
|
g_emu_thread->reloadInputBindings();
|
||||||
setText(QString());
|
setText(QString());
|
||||||
}
|
}
|
||||||
|
@ -428,6 +431,7 @@ 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();
|
||||||
Host::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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1119,18 +1119,21 @@ void MainWindow::onRemoveDiscActionTriggered()
|
||||||
void MainWindow::onViewToolbarActionToggled(bool checked)
|
void MainWindow::onViewToolbarActionToggled(bool checked)
|
||||||
{
|
{
|
||||||
Host::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)
|
||||||
{
|
{
|
||||||
Host::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)
|
||||||
{
|
{
|
||||||
Host::SetBaseBoolSettingValue("UI", "ShowStatusBar", checked);
|
Host::SetBaseBoolSettingValue("UI", "ShowStatusBar", checked);
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
m_ui.statusBar->setVisible(checked);
|
m_ui.statusBar->setVisible(checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1343,7 +1346,7 @@ void MainWindow::setGameListEntryCoverImage(const GameList::Entry* entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
QString new_filename =
|
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())
|
if (new_filename.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1427,6 +1430,7 @@ void MainWindow::setupAdditionalUi()
|
||||||
action->setCheckable(true);
|
action->setCheckable(true);
|
||||||
connect(action, &QAction::triggered, [this, mode]() {
|
connect(action, &QAction::triggered, [this, mode]() {
|
||||||
Host::SetBaseStringSettingValue("CPU", "ExecutionMode", Settings::GetCPUExecutionModeName(mode));
|
Host::SetBaseStringSettingValue("CPU", "ExecutionMode", Settings::GetCPUExecutionModeName(mode));
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->applySettings();
|
g_emu_thread->applySettings();
|
||||||
updateDebugMenuCPUExecutionMode();
|
updateDebugMenuCPUExecutionMode();
|
||||||
});
|
});
|
||||||
|
@ -1441,6 +1445,7 @@ void MainWindow::setupAdditionalUi()
|
||||||
action->setCheckable(true);
|
action->setCheckable(true);
|
||||||
connect(action, &QAction::triggered, [this, renderer]() {
|
connect(action, &QAction::triggered, [this, renderer]() {
|
||||||
Host::SetBaseStringSettingValue("GPU", "Renderer", Settings::GetRendererName(renderer));
|
Host::SetBaseStringSettingValue("GPU", "Renderer", Settings::GetRendererName(renderer));
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->applySettings();
|
g_emu_thread->applySettings();
|
||||||
updateDebugMenuGPURenderer();
|
updateDebugMenuGPURenderer();
|
||||||
});
|
});
|
||||||
|
@ -1455,6 +1460,7 @@ void MainWindow::setupAdditionalUi()
|
||||||
action->setCheckable(true);
|
action->setCheckable(true);
|
||||||
connect(action, &QAction::triggered, [this, crop_mode]() {
|
connect(action, &QAction::triggered, [this, crop_mode]() {
|
||||||
Host::SetBaseStringSettingValue("Display", "CropMode", Settings::GetDisplayCropModeName(crop_mode));
|
Host::SetBaseStringSettingValue("Display", "CropMode", Settings::GetDisplayCropModeName(crop_mode));
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->applySettings();
|
g_emu_thread->applySettings();
|
||||||
updateDebugMenuCropMode();
|
updateDebugMenuCropMode();
|
||||||
});
|
});
|
||||||
|
@ -1484,6 +1490,7 @@ void MainWindow::setupAdditionalUi()
|
||||||
connect(action, &QAction::triggered, [this, action]() {
|
connect(action, &QAction::triggered, [this, action]() {
|
||||||
const QString new_language = action->data().toString();
|
const QString new_language = action->data().toString();
|
||||||
Host::SetBaseStringSettingValue("Main", "Language", new_language.toUtf8().constData());
|
Host::SetBaseStringSettingValue("Main", "Language", new_language.toUtf8().constData());
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
QtHost::InstallTranslator();
|
QtHost::InstallTranslator();
|
||||||
recreate();
|
recreate();
|
||||||
});
|
});
|
||||||
|
@ -1950,6 +1957,7 @@ void MainWindow::addThemeToMenu(const QString& name, const QString& key)
|
||||||
void MainWindow::setTheme(const QString& theme)
|
void MainWindow::setTheme(const QString& theme)
|
||||||
{
|
{
|
||||||
Host::SetBaseStringSettingValue("UI", "Theme", theme.toUtf8().constData());
|
Host::SetBaseStringSettingValue("UI", "Theme", theme.toUtf8().constData());
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
updateApplicationTheme();
|
updateApplicationTheme();
|
||||||
updateMenuSelectedTheme();
|
updateMenuSelectedTheme();
|
||||||
m_game_list_widget->reloadCommonImages();
|
m_game_list_widget->reloadCommonImages();
|
||||||
|
@ -2097,7 +2105,10 @@ void MainWindow::saveGeometryToConfig()
|
||||||
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())
|
||||||
|
{
|
||||||
Host::SetBaseStringSettingValue("UI", "MainWindowGeometry", geometry_b64.constData());
|
Host::SetBaseStringSettingValue("UI", "MainWindowGeometry", geometry_b64.constData());
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::restoreGeometryFromConfig()
|
void MainWindow::restoreGeometryFromConfig()
|
||||||
|
@ -2114,7 +2125,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())
|
||||||
|
{
|
||||||
Host::SetBaseStringSettingValue("UI", "DisplayWindowGeometry", geometry_b64.constData());
|
Host::SetBaseStringSettingValue("UI", "DisplayWindowGeometry", geometry_b64.constData());
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::restoreDisplayWindowGeometryFromConfig()
|
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.
|
// Wipe out the last version, that way it displays the update if we've previously skipped it.
|
||||||
Host::DeleteBaseSettingValue("AutoUpdater", "LastVersion");
|
Host::DeleteBaseSettingValue("AutoUpdater", "LastVersion");
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
checkForUpdates(true);
|
checkForUpdates(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2553,6 +2568,7 @@ void MainWindow::onToolsCheatManagerTriggered()
|
||||||
|
|
||||||
connect(cb, &QCheckBox::stateChanged, [](int state) {
|
connect(cb, &QCheckBox::stateChanged, [](int state) {
|
||||||
Host::SetBaseBoolSettingValue("UI", "DisplayCheatWarning", (state != Qt::CheckState::Checked));
|
Host::SetBaseBoolSettingValue("UI", "DisplayCheatWarning", (state != Qt::CheckState::Checked));
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (mb.exec() == QMessageBox::No)
|
if (mb.exec() == QMessageBox::No)
|
||||||
|
|
|
@ -1078,21 +1078,6 @@ void Host::CancelGameListRefresh()
|
||||||
QMetaObject::invokeMethod(g_main_window, "cancelGameListRefresh", Qt::BlockingQueuedConnection);
|
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)
|
void EmuThread::loadState(const QString& filename)
|
||||||
{
|
{
|
||||||
if (!isOnThread())
|
if (!isOnThread())
|
||||||
|
@ -1579,68 +1564,6 @@ std::optional<std::time_t> Host::GetResourceFileTimestamp(const char* filename)
|
||||||
return sd.ModificationTime;
|
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()
|
void Host::CommitBaseSettingChanges()
|
||||||
{
|
{
|
||||||
if (g_emu_thread->isOnThread())
|
if (g_emu_thread->isOnThread())
|
||||||
|
|
|
@ -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 |
|
@ -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 |
|
@ -178,6 +178,7 @@
|
||||||
<file>icons/black/svg/gamepad-line.svg</file>
|
<file>icons/black/svg/gamepad-line.svg</file>
|
||||||
<file>icons/black/svg/global-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/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/keyboard-line.svg</file>
|
||||||
<file>icons/black/svg/layout-grid-line.svg</file>
|
<file>icons/black/svg/layout-grid-line.svg</file>
|
||||||
<file>icons/black/svg/list-check.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/gamepad-line.svg</file>
|
||||||
<file>icons/white/svg/global-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/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/keyboard-line.svg</file>
|
||||||
<file>icons/white/svg/layout-grid-line.svg</file>
|
<file>icons/white/svg/layout-grid-line.svg</file>
|
||||||
<file>icons/white/svg/list-check.svg</file>
|
<file>icons/white/svg/list-check.svg</file>
|
||||||
|
|
|
@ -407,6 +407,7 @@ void SettingsDialog::setBoolSettingValue(const char* section, const char* key, s
|
||||||
{
|
{
|
||||||
value.has_value() ? Host::SetBaseBoolSettingValue(section, key, value.value()) :
|
value.has_value() ? Host::SetBaseBoolSettingValue(section, key, value.value()) :
|
||||||
Host::DeleteBaseSettingValue(section, key);
|
Host::DeleteBaseSettingValue(section, key);
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->applySettings();
|
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()) :
|
value.has_value() ? Host::SetBaseIntSettingValue(section, key, value.value()) :
|
||||||
Host::DeleteBaseSettingValue(section, key);
|
Host::DeleteBaseSettingValue(section, key);
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->applySettings();
|
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()) :
|
value.has_value() ? Host::SetBaseFloatSettingValue(section, key, value.value()) :
|
||||||
Host::DeleteBaseSettingValue(section, key);
|
Host::DeleteBaseSettingValue(section, key);
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->applySettings();
|
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()) :
|
value.has_value() ? Host::SetBaseStringSettingValue(section, key, value.value()) :
|
||||||
Host::DeleteBaseSettingValue(section, key);
|
Host::DeleteBaseSettingValue(section, key);
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->applySettings();
|
g_emu_thread->applySettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -470,6 +474,7 @@ void SettingsDialog::removeSettingValue(const char* section, const char* key)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Host::DeleteBaseSettingValue(section, key);
|
Host::DeleteBaseSettingValue(section, key);
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->applySettings();
|
g_emu_thread->applySettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -651,6 +651,7 @@ static void BindWidgetToBoolSetting(SettingsInterface* sif, WidgetType* widget,
|
||||||
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);
|
||||||
Host::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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -694,6 +695,7 @@ static void BindWidgetToIntSetting(SettingsInterface* sif, WidgetType* widget, s
|
||||||
widget, [widget, section = std::move(section), key = std::move(key), option_offset]() {
|
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);
|
||||||
Host::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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -734,6 +736,7 @@ static void BindWidgetToFloatSetting(SettingsInterface* sif, WidgetType* widget,
|
||||||
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);
|
||||||
Host::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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -774,6 +777,7 @@ static void BindWidgetToNormalizedSetting(SettingsInterface* sif, WidgetType* wi
|
||||||
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);
|
||||||
Host::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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -819,6 +823,7 @@ static void BindWidgetToStringSetting(SettingsInterface* sif, WidgetType* widget
|
||||||
else
|
else
|
||||||
Host::DeleteBaseSettingValue(section.c_str(), key.c_str());
|
Host::DeleteBaseSettingValue(section.c_str(), key.c_str());
|
||||||
|
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->applySettings();
|
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 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);
|
||||||
Host::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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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]() {
|
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));
|
||||||
Host::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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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]() {
|
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);
|
||||||
Host::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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1054,6 +1062,7 @@ static void BindWidgetToFolderSetting(SettingsInterface* sif, WidgetType* widget
|
||||||
Host::DeleteBaseSettingValue(section.c_str(), key.c_str());
|
Host::DeleteBaseSettingValue(section.c_str(), key.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
g_emu_thread->updateEmuFolders();
|
g_emu_thread->updateEmuFolders();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -33,6 +33,8 @@ public:
|
||||||
ProgressCallback(std::string name);
|
ProgressCallback(std::string name);
|
||||||
~ProgressCallback() override;
|
~ProgressCallback() override;
|
||||||
|
|
||||||
|
ALWAYS_INLINE const std::string& GetName() const { return m_name; }
|
||||||
|
|
||||||
void PushState() override;
|
void PushState() override;
|
||||||
void PopState() override;
|
void PopState() override;
|
||||||
|
|
||||||
|
|
|
@ -647,7 +647,7 @@ std::string GameList::GetCoverImagePath(const std::string& path, const std::stri
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GameList::GetNewCoverImagePathForEntry(const Entry* entry, const char* new_filename)
|
std::string GameList::GetNewCoverImagePathForEntry(const Entry* entry, const char* new_filename, bool use_serial)
|
||||||
{
|
{
|
||||||
const char* extension = std::strrchr(new_filename, '.');
|
const char* extension = std::strrchr(new_filename, '.');
|
||||||
if (!extension)
|
if (!extension)
|
||||||
|
@ -665,12 +665,12 @@ std::string GameList::GetNewCoverImagePathForEntry(const Entry* entry, const cha
|
||||||
const std::string sanitized_name(Path::SanitizeFileName(entry->title));
|
const std::string sanitized_name(Path::SanitizeFileName(entry->title));
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
if (sanitized_name != entry->title)
|
if (sanitized_name != entry->title || use_serial)
|
||||||
name = fmt::format("{}{}", entry->serial, extension);
|
name = fmt::format("{}{}", entry->serial, extension);
|
||||||
else
|
else
|
||||||
name = fmt::format("{}{}", entry->title, extension);
|
name = fmt::format("{}{}", entry->title, extension);
|
||||||
|
|
||||||
return Path::Combine(EmuFolders::Covers, name);
|
return Path::Combine(EmuFolders::Covers, Path::SanitizeFileName(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GameList::Entry::GetReleaseDateString(char* buffer, size_t buffer_size) const
|
size_t GameList::Entry::GetReleaseDateString(char* buffer, size_t buffer_size) const
|
||||||
|
@ -690,7 +690,8 @@ size_t GameList::Entry::GetReleaseDateString(char* buffer, size_t buffer_size) c
|
||||||
return std::strftime(buffer, buffer_size, "%d %B %Y", &date_tm);
|
return std::strftime(buffer, buffer_size, "%d %B %Y", &date_tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameList::DownloadCovers(const std::vector<std::string>& url_templates, ProgressCallback* progress /*= nullptr*/)
|
bool GameList::DownloadCovers(const std::vector<std::string>& url_templates, bool use_serial,
|
||||||
|
ProgressCallback* progress, std::function<void(const Entry*, std::string)> save_callback)
|
||||||
{
|
{
|
||||||
if (!progress)
|
if (!progress)
|
||||||
progress = ProgressCallback::NullProgressCallback;
|
progress = ProgressCallback::NullProgressCallback;
|
||||||
|
@ -776,23 +777,25 @@ bool GameList::DownloadCovers(const std::vector<std::string>& url_templates, Pro
|
||||||
|
|
||||||
// we could actually do a few in parallel here...
|
// we could actually do a few in parallel here...
|
||||||
std::string filename(Common::HTTPDownloader::URLDecode(url));
|
std::string filename(Common::HTTPDownloader::URLDecode(url));
|
||||||
downloader->CreateRequest(std::move(url), [entry_path = std::move(entry_path), filename = std::move(filename)](
|
downloader->CreateRequest(
|
||||||
s32 status_code, Common::HTTPDownloader::Request::Data data) {
|
std::move(url), [use_serial, &save_callback, entry_path = std::move(entry_path),
|
||||||
if (status_code != Common::HTTPDownloader::HTTP_OK || data.empty())
|
filename = std::move(filename)](s32 status_code, Common::HTTPDownloader::Request::Data data) {
|
||||||
return;
|
if (status_code != Common::HTTPDownloader::HTTP_OK || data.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
std::unique_lock lock(s_mutex);
|
std::unique_lock lock(s_mutex);
|
||||||
const GameList::Entry* entry = GetEntryForPath(entry_path.c_str());
|
const GameList::Entry* entry = GetEntryForPath(entry_path.c_str());
|
||||||
if (!entry || !GetCoverImagePathForEntry(entry).empty())
|
if (!entry || !GetCoverImagePathForEntry(entry).empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string write_path(GetNewCoverImagePathForEntry(entry, filename.c_str()));
|
std::string write_path(GetNewCoverImagePathForEntry(entry, filename.c_str(), use_serial));
|
||||||
if (write_path.empty())
|
if (write_path.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
FileSystem::WriteBinaryFile(write_path.c_str(), data.data(), data.size());
|
FileSystem::WriteBinaryFile(write_path.c_str(), data.data(), data.size());
|
||||||
Host::CoversChanged();
|
if (save_callback)
|
||||||
});
|
save_callback(entry, std::move(write_path));
|
||||||
|
});
|
||||||
downloader->WaitForAllRequests();
|
downloader->WaitForAllRequests();
|
||||||
progress->IncrementProgressValue();
|
progress->IncrementProgressValue();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
#include "util/cd_image.h"
|
#include "util/cd_image.h"
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <functional>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -74,9 +75,13 @@ void Refresh(bool invalidate_cache, bool only_cache = false, ProgressCallback* p
|
||||||
|
|
||||||
std::string GetCoverImagePathForEntry(const Entry* entry);
|
std::string GetCoverImagePathForEntry(const Entry* entry);
|
||||||
std::string GetCoverImagePath(const std::string& path, const std::string& serial, const std::string& title);
|
std::string GetCoverImagePath(const std::string& path, const std::string& serial, const std::string& title);
|
||||||
std::string GetNewCoverImagePathForEntry(const Entry* entry, const char* new_filename);
|
std::string GetNewCoverImagePathForEntry(const Entry* entry, const char* new_filename, bool use_serial);
|
||||||
|
|
||||||
bool DownloadCovers(const std::vector<std::string>& url_templates, ProgressCallback* progress = nullptr);
|
/// Downloads covers using the specified URL templates. By default, covers are saved by title, but this can be changed
|
||||||
|
/// with the use_serial parameter. save_callback optionall takes the entry and the path the new cover is saved to.
|
||||||
|
bool DownloadCovers(const std::vector<std::string>& url_templates, bool use_serial = false,
|
||||||
|
ProgressCallback* progress = nullptr,
|
||||||
|
std::function<void(const Entry*, std::string)> save_callback = {});
|
||||||
}; // namespace GameList
|
}; // namespace GameList
|
||||||
|
|
||||||
namespace Host {
|
namespace Host {
|
||||||
|
@ -85,8 +90,4 @@ void RefreshGameListAsync(bool invalidate_cache);
|
||||||
|
|
||||||
/// Cancels game list refresh, if there is one in progress.
|
/// Cancels game list refresh, if there is one in progress.
|
||||||
void CancelGameListRefresh();
|
void CancelGameListRefresh();
|
||||||
|
|
||||||
void DownloadCoversAsync(std::vector<std::string> url_templates);
|
|
||||||
void CancelCoversDownload();
|
|
||||||
void CoversChanged();
|
|
||||||
} // namespace Host
|
} // namespace Host
|
||||||
|
|
|
@ -106,6 +106,55 @@ std::vector<std::string> Host::GetStringListSetting(const char* section, const c
|
||||||
return s_layered_settings_interface.GetStringList(section, key);
|
return s_layered_settings_interface.GetStringList(section, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Host::SetBaseBoolSettingValue(const char* section, const char* key, bool value)
|
||||||
|
{
|
||||||
|
std::unique_lock lock(s_settings_mutex);
|
||||||
|
s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetBoolValue(section, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Host::SetBaseIntSettingValue(const char* section, const char* key, int value)
|
||||||
|
{
|
||||||
|
std::unique_lock lock(s_settings_mutex);
|
||||||
|
s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetIntValue(section, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Host::SetBaseFloatSettingValue(const char* section, const char* key, float value)
|
||||||
|
{
|
||||||
|
std::unique_lock lock(s_settings_mutex);
|
||||||
|
s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetFloatValue(section, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Host::SetBaseStringSettingValue(const char* section, const char* key, const char* value)
|
||||||
|
{
|
||||||
|
std::unique_lock lock(s_settings_mutex);
|
||||||
|
s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetStringValue(section, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Host::SetBaseStringListSettingValue(const char* section, const char* key, const std::vector<std::string>& values)
|
||||||
|
{
|
||||||
|
std::unique_lock lock(s_settings_mutex);
|
||||||
|
s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->SetStringList(section, key, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Host::AddValueToBaseStringListSetting(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::RemoveValueFromBaseStringListSetting(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::DeleteBaseSettingValue(const char* section, const char* key)
|
||||||
|
{
|
||||||
|
std::unique_lock lock(s_settings_mutex);
|
||||||
|
s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE)->DeleteValue(section, key);
|
||||||
|
}
|
||||||
|
|
||||||
SettingsInterface* Host::Internal::GetBaseSettingsLayer()
|
SettingsInterface* Host::Internal::GetBaseSettingsLayer()
|
||||||
{
|
{
|
||||||
return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE);
|
return s_layered_settings_interface.GetLayer(LayeredSettingsInterface::LAYER_BASE);
|
||||||
|
|
|
@ -17,15 +17,20 @@
|
||||||
#include "fmt/core.h"
|
#include "fmt/core.h"
|
||||||
#include "imgui_internal.h"
|
#include "imgui_internal.h"
|
||||||
#include "imgui_stdlib.h"
|
#include "imgui_stdlib.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
Log_SetChannel(ImGuiFullscreen);
|
Log_SetChannel(ImGuiFullscreen);
|
||||||
|
|
||||||
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();
|
||||||
|
@ -33,6 +38,7 @@ static void TextureLoaderThread();
|
||||||
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();
|
||||||
|
@ -98,6 +104,12 @@ static std::string s_input_dialog_text;
|
||||||
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;
|
||||||
|
@ -201,6 +213,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 = {};
|
||||||
|
@ -431,6 +444,16 @@ void ImGuiFullscreen::BeginLayout()
|
||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(8.0f, 8.0f));
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(4.0f, 3.0f));
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, LayoutScale(8.0f, 4.0f));
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, LayoutScale(4.0f, 4.0f));
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, LayoutScale(4.0f, 2.0f));
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, LayoutScale(21.0f));
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize, LayoutScale(14.0f));
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarRounding, 0.0f);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, LayoutScale(10.0f));
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_TabRounding, LayoutScale(4.0f));
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, UISecondaryTextColor);
|
ImGui::PushStyleColor(ImGuiCol_Text, UISecondaryTextColor);
|
||||||
ImGui::PushStyleColor(ImGuiCol_TextDisabled, UIDisabledColor);
|
ImGui::PushStyleColor(ImGuiCol_TextDisabled, UIDisabledColor);
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button, UISecondaryColor);
|
ImGui::PushStyleColor(ImGuiCol_Button, UISecondaryColor);
|
||||||
|
@ -448,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);
|
||||||
|
@ -460,7 +484,7 @@ void ImGuiFullscreen::EndLayout()
|
||||||
DrawToast();
|
DrawToast();
|
||||||
|
|
||||||
ImGui::PopStyleColor(10);
|
ImGui::PopStyleColor(10);
|
||||||
ImGui::PopStyleVar(2);
|
ImGui::PopStyleVar(12);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiFullscreen::QueueResetFocus()
|
void ImGuiFullscreen::QueueResetFocus()
|
||||||
|
@ -536,10 +560,12 @@ void ImGuiFullscreen::PopSecondaryColor()
|
||||||
ImGui::PopStyleColor(5);
|
ImGui::PopStyleColor(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGuiFullscreen::BeginFullscreenColumns(const char* title)
|
bool ImGuiFullscreen::BeginFullscreenColumns(const char* title, float pos_y, bool expand_to_screen_width)
|
||||||
{
|
{
|
||||||
ImGui::SetNextWindowPos(ImVec2(g_layout_padding_left, 0.0f));
|
ImGui::SetNextWindowPos(ImVec2(expand_to_screen_width ? 0.0f : g_layout_padding_left, pos_y));
|
||||||
ImGui::SetNextWindowSize(ImVec2(LayoutScale(LAYOUT_SCREEN_WIDTH), ImGui::GetIO().DisplaySize.y));
|
ImGui::SetNextWindowSize(
|
||||||
|
ImVec2(expand_to_screen_width ? ImGui::GetIO().DisplaySize.x : LayoutScale(LAYOUT_SCREEN_WIDTH),
|
||||||
|
ImGui::GetIO().DisplaySize.y - pos_y));
|
||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||||
|
@ -569,8 +595,16 @@ void ImGuiFullscreen::EndFullscreenColumns()
|
||||||
|
|
||||||
bool ImGuiFullscreen::BeginFullscreenColumnWindow(float start, float end, const char* name, const ImVec4& background)
|
bool ImGuiFullscreen::BeginFullscreenColumnWindow(float start, float end, const char* name, const ImVec4& background)
|
||||||
{
|
{
|
||||||
const ImVec2 pos(LayoutScale(start), 0.0f);
|
start = LayoutScale(start);
|
||||||
const ImVec2 size(LayoutScale(end - start), ImGui::GetIO().DisplaySize.y);
|
end = LayoutScale(end);
|
||||||
|
|
||||||
|
if (start < 0.0f)
|
||||||
|
start = ImGui::GetIO().DisplaySize.x + start;
|
||||||
|
if (end <= 0.0f)
|
||||||
|
end = ImGui::GetIO().DisplaySize.x + end;
|
||||||
|
|
||||||
|
const ImVec2 pos(start, 0.0f);
|
||||||
|
const ImVec2 size(end - start, ImGui::GetCurrentWindow()->Size.y);
|
||||||
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, background);
|
ImGui::PushStyleColor(ImGuiCol_ChildBg, background);
|
||||||
|
|
||||||
|
@ -891,6 +925,33 @@ bool ImGuiFullscreen::MenuButton(const char* title, const char* summary, bool en
|
||||||
return pressed;
|
return pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ImGuiFullscreen::MenuButtonWithoutSummary(const char* title, bool enabled, float height, ImFont* font,
|
||||||
|
const ImVec2& text_align)
|
||||||
|
{
|
||||||
|
ImRect bb;
|
||||||
|
bool visible, hovered;
|
||||||
|
bool pressed = MenuButtonFrame(title, enabled, height, &visible, &hovered, &bb);
|
||||||
|
if (!visible)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const float midpoint = bb.Min.y + font->FontSize + LayoutScale(4.0f);
|
||||||
|
const ImRect title_bb(bb.Min, ImVec2(bb.Max.x, midpoint));
|
||||||
|
const ImRect summary_bb(ImVec2(bb.Min.x, midpoint), bb.Max);
|
||||||
|
|
||||||
|
if (!enabled)
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled));
|
||||||
|
|
||||||
|
ImGui::PushFont(font);
|
||||||
|
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, title, nullptr, nullptr, text_align, &title_bb);
|
||||||
|
ImGui::PopFont();
|
||||||
|
|
||||||
|
if (!enabled)
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
|
s_menu_button_index++;
|
||||||
|
return pressed;
|
||||||
|
}
|
||||||
|
|
||||||
bool ImGuiFullscreen::MenuImageButton(const char* title, const char* summary, ImTextureID user_texture_id,
|
bool ImGuiFullscreen::MenuImageButton(const char* title, const char* summary, ImTextureID user_texture_id,
|
||||||
const ImVec2& image_size, bool enabled, float height, const ImVec2& uv0,
|
const ImVec2& image_size, bool enabled, float height, const ImVec2& uv0,
|
||||||
const ImVec2& uv1, ImFont* title_font, ImFont* summary_font)
|
const ImVec2& uv1, ImFont* title_font, ImFont* summary_font)
|
||||||
|
@ -1215,6 +1276,7 @@ bool ImGuiFullscreen::RangeButton(const char* title, const char* summary, s32* v
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(LayoutScale(500.0f, 180.0f));
|
ImGui::SetNextWindowSize(LayoutScale(500.0f, 180.0f));
|
||||||
|
ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||||
|
|
||||||
ImGui::PushFont(g_large_font);
|
ImGui::PushFont(g_large_font);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f));
|
||||||
|
@ -1286,6 +1348,7 @@ bool ImGuiFullscreen::RangeButton(const char* title, const char* summary, float*
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(LayoutScale(500.0f, 180.0f));
|
ImGui::SetNextWindowSize(LayoutScale(500.0f, 180.0f));
|
||||||
|
ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||||
|
|
||||||
ImGui::PushFont(g_large_font);
|
ImGui::PushFont(g_large_font);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f));
|
||||||
|
@ -1531,7 +1594,7 @@ void ImGuiFullscreen::PopulateFileSelectorItems()
|
||||||
{
|
{
|
||||||
for (std::string& root_path : FileSystem::GetRootDirectoryList())
|
for (std::string& root_path : FileSystem::GetRootDirectoryList())
|
||||||
{
|
{
|
||||||
s_file_selector_items.emplace_back(StringUtil::StdStringFromFormat(ICON_FA_FOLDER " %s", root_path.c_str()),
|
s_file_selector_items.emplace_back(StringUtil::StdStringFromFormat(ICON_FA_FOLDER " %s", root_path.c_str()),
|
||||||
std::move(root_path), false);
|
std::move(root_path), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1566,7 +1629,7 @@ void ImGuiFullscreen::PopulateFileSelectorItems()
|
||||||
|
|
||||||
if (fd.Attributes & FILESYSTEM_FILE_ATTRIBUTE_DIRECTORY)
|
if (fd.Attributes & FILESYSTEM_FILE_ATTRIBUTE_DIRECTORY)
|
||||||
{
|
{
|
||||||
std::string title(StringUtil::StdStringFromFormat(ICON_FA_FOLDER " %s", fd.FileName.c_str()));
|
std::string title(StringUtil::StdStringFromFormat(ICON_FA_FOLDER " %s", fd.FileName.c_str()));
|
||||||
s_file_selector_items.emplace_back(std::move(title), std::move(full_path), false);
|
s_file_selector_items.emplace_back(std::move(title), std::move(full_path), false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1580,7 +1643,7 @@ void ImGuiFullscreen::PopulateFileSelectorItems()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string title(StringUtil::StdStringFromFormat(ICON_FA_FILE " %s", fd.FileName.c_str()));
|
std::string title(StringUtil::StdStringFromFormat(ICON_FA_FILE " %s", fd.FileName.c_str()));
|
||||||
s_file_selector_items.emplace_back(std::move(title), std::move(full_path), true);
|
s_file_selector_items.emplace_back(std::move(title), std::move(full_path), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1652,7 +1715,7 @@ void ImGuiFullscreen::DrawFileSelector()
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, UIPrimaryTextColor);
|
ImGui::PushStyleColor(ImGuiCol_Text, UIPrimaryTextColor);
|
||||||
ImGui::PushStyleColor(ImGuiCol_TitleBg, UIPrimaryDarkColor);
|
ImGui::PushStyleColor(ImGuiCol_TitleBg, UIPrimaryDarkColor);
|
||||||
ImGui::PushStyleColor(ImGuiCol_TitleBgActive, UIPrimaryColor);
|
ImGui::PushStyleColor(ImGuiCol_TitleBgActive, UIPrimaryColor);
|
||||||
ImGui::PushStyleColor(ImGuiCol_PopupBg, UIBackgroundColor);
|
ImGui::PushStyleColor(ImGuiCol_PopupBg, MulAlpha(UIBackgroundColor, 0.95f));
|
||||||
|
|
||||||
bool is_open = !WantsToCloseMenu();
|
bool is_open = !WantsToCloseMenu();
|
||||||
bool directory_selected = false;
|
bool directory_selected = false;
|
||||||
|
@ -1665,13 +1728,13 @@ void ImGuiFullscreen::DrawFileSelector()
|
||||||
|
|
||||||
if (!s_file_selector_current_directory.empty())
|
if (!s_file_selector_current_directory.empty())
|
||||||
{
|
{
|
||||||
MenuButton(fmt::format(ICON_FA_FOLDER_OPEN " {}", s_file_selector_current_directory).c_str(), nullptr, false,
|
MenuButton(fmt::format(ICON_FA_FOLDER_OPEN " {}", s_file_selector_current_directory).c_str(), nullptr, false,
|
||||||
LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
|
LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_file_selector_directory && !s_file_selector_current_directory.empty())
|
if (s_file_selector_directory && !s_file_selector_current_directory.empty())
|
||||||
{
|
{
|
||||||
if (MenuButton(ICON_FA_FOLDER_PLUS " <Use This Directory>", nullptr, true, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY))
|
if (MenuButton(ICON_FA_FOLDER_PLUS " <Use This Directory>", nullptr, true, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY))
|
||||||
directory_selected = true;
|
directory_selected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1755,16 +1818,6 @@ void ImGuiFullscreen::DrawChoiceDialog()
|
||||||
if (!s_choice_dialog_open)
|
if (!s_choice_dialog_open)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const float width = 600.0f;
|
|
||||||
const float title_height =
|
|
||||||
g_large_font->FontSize + ImGui::GetStyle().FramePadding.y * 2.0f + ImGui::GetStyle().WindowPadding.y * 2.0f;
|
|
||||||
const float height =
|
|
||||||
std::min(400.0f, title_height + (LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY + (LAYOUT_MENU_BUTTON_Y_PADDING * 2.0f)) *
|
|
||||||
static_cast<float>(s_choice_dialog_options.size()));
|
|
||||||
ImGui::SetNextWindowSize(LayoutScale(width, height));
|
|
||||||
ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
|
||||||
ImGui::OpenPopup(s_choice_dialog_title.c_str());
|
|
||||||
|
|
||||||
ImGui::PushFont(g_large_font);
|
ImGui::PushFont(g_large_font);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,
|
||||||
|
@ -1772,7 +1825,18 @@ void ImGuiFullscreen::DrawChoiceDialog()
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, UIPrimaryTextColor);
|
ImGui::PushStyleColor(ImGuiCol_Text, UIPrimaryTextColor);
|
||||||
ImGui::PushStyleColor(ImGuiCol_TitleBg, UIPrimaryDarkColor);
|
ImGui::PushStyleColor(ImGuiCol_TitleBg, UIPrimaryDarkColor);
|
||||||
ImGui::PushStyleColor(ImGuiCol_TitleBgActive, UIPrimaryColor);
|
ImGui::PushStyleColor(ImGuiCol_TitleBgActive, UIPrimaryColor);
|
||||||
ImGui::PushStyleColor(ImGuiCol_PopupBg, UIBackgroundColor);
|
ImGui::PushStyleColor(ImGuiCol_PopupBg, MulAlpha(UIBackgroundColor, 0.95f));
|
||||||
|
|
||||||
|
const float width = LayoutScale(600.0f);
|
||||||
|
const float title_height =
|
||||||
|
g_large_font->FontSize + ImGui::GetStyle().FramePadding.y * 2.0f + ImGui::GetStyle().WindowPadding.y * 2.0f;
|
||||||
|
const float height =
|
||||||
|
std::min(LayoutScale(400.0f),
|
||||||
|
title_height + LayoutScale(LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY + (LAYOUT_MENU_BUTTON_Y_PADDING * 2.0f)) *
|
||||||
|
static_cast<float>(s_choice_dialog_options.size()));
|
||||||
|
ImGui::SetNextWindowSize(ImVec2(width, height));
|
||||||
|
ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||||
|
ImGui::OpenPopup(s_choice_dialog_title.c_str());
|
||||||
|
|
||||||
bool is_open = !WantsToCloseMenu();
|
bool is_open = !WantsToCloseMenu();
|
||||||
s32 choice = -1;
|
s32 choice = -1;
|
||||||
|
@ -1791,7 +1855,7 @@ void ImGuiFullscreen::DrawChoiceDialog()
|
||||||
auto& option = s_choice_dialog_options[i];
|
auto& option = s_choice_dialog_options[i];
|
||||||
|
|
||||||
const std::string title(
|
const std::string title(
|
||||||
fmt::format("{0} {1}", option.second ? ICON_FA_CHECK_SQUARE : ICON_FA_SQUARE, option.first));
|
fmt::format("{0} {1}", option.second ? ICON_FA_CHECK_SQUARE : ICON_FA_SQUARE, option.first));
|
||||||
if (MenuButton(title.c_str(), nullptr, true, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY))
|
if (MenuButton(title.c_str(), nullptr, true, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY))
|
||||||
{
|
{
|
||||||
choice = i;
|
choice = i;
|
||||||
|
@ -1806,7 +1870,7 @@ void ImGuiFullscreen::DrawChoiceDialog()
|
||||||
auto& option = s_choice_dialog_options[i];
|
auto& option = s_choice_dialog_options[i];
|
||||||
std::string title;
|
std::string title;
|
||||||
if (option.second)
|
if (option.second)
|
||||||
title += ICON_FA_CHECK " ";
|
title += ICON_FA_CHECK " ";
|
||||||
title += option.first;
|
title += option.first;
|
||||||
|
|
||||||
if (ActiveButton(title.c_str(), option.second, true, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY))
|
if (ActiveButton(title.c_str(), option.second, true, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY))
|
||||||
|
@ -1871,9 +1935,14 @@ 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, MulAlpha(UIBackgroundColor, 0.95f));
|
||||||
|
|
||||||
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,
|
||||||
|
@ -1881,16 +1950,25 @@ void ImGuiFullscreen::DrawInputDialog()
|
||||||
ImGuiWindowFlags_NoMove))
|
ImGuiWindowFlags_NoMove))
|
||||||
{
|
{
|
||||||
ImGui::TextWrapped("%s", s_input_dialog_message.c_str());
|
ImGui::TextWrapped("%s", s_input_dialog_message.c_str());
|
||||||
ImGui::NewLine();
|
|
||||||
|
|
||||||
if (!s_input_dialog_caption.empty())
|
|
||||||
ImGui::TextUnformatted(s_input_dialog_caption.c_str());
|
|
||||||
ImGui::InputText("##input", &s_input_dialog_text);
|
|
||||||
|
|
||||||
ImGui::NewLine();
|
|
||||||
|
|
||||||
BeginMenuButtons();
|
BeginMenuButtons();
|
||||||
|
|
||||||
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + LayoutScale(10.0f));
|
||||||
|
|
||||||
|
if (!s_input_dialog_caption.empty())
|
||||||
|
{
|
||||||
|
const float prev = ImGui::GetCursorPosX();
|
||||||
|
ImGui::TextUnformatted(s_input_dialog_caption.c_str());
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetCursorPosX() - prev);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetCurrentWindow()->WorkRect.GetWidth());
|
||||||
|
}
|
||||||
|
ImGui::InputText("##input", &s_input_dialog_text);
|
||||||
|
|
||||||
|
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + LayoutScale(10.0f));
|
||||||
|
|
||||||
const bool ok_enabled = !s_input_dialog_text.empty();
|
const bool ok_enabled = !s_input_dialog_text.empty();
|
||||||
|
|
||||||
if (ActiveButton(s_input_dialog_ok_text.c_str(), false, ok_enabled) && ok_enabled)
|
if (ActiveButton(s_input_dialog_ok_text.c_str(), false, ok_enabled) && ok_enabled)
|
||||||
|
@ -1903,7 +1981,7 @@ void ImGuiFullscreen::DrawInputDialog()
|
||||||
cb(std::move(text));
|
cb(std::move(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ActiveButton(ICON_FA_TIMES " Cancel", false))
|
if (ActiveButton(ICON_FA_TIMES " Cancel", false))
|
||||||
{
|
{
|
||||||
CloseInputDialog();
|
CloseInputDialog();
|
||||||
|
|
||||||
|
@ -1917,8 +1995,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()
|
||||||
|
@ -1935,6 +2014,137 @@ 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, MulAlpha(UIBackgroundColor, 0.95f));
|
||||||
|
|
||||||
|
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(20.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))
|
||||||
|
{
|
||||||
|
const InfoMessageDialogCallback& func = std::get<InfoMessageDialogCallback>(cb);
|
||||||
|
if (func)
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
else if (std::holds_alternative<ConfirmMessageDialogCallback>(cb))
|
||||||
|
{
|
||||||
|
const ConfirmMessageDialogCallback& func = std::get<ConfirmMessageDialogCallback>(cb);
|
||||||
|
if (func)
|
||||||
|
func(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;
|
||||||
|
|
||||||
|
@ -1965,10 +2175,12 @@ void ImGuiFullscreen::OpenBackgroundProgressDialog(const char* str_id, std::stri
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(s_background_progress_lock);
|
std::unique_lock<std::mutex> lock(s_background_progress_lock);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
for (const BackgroundProgressDialogData& data : s_background_progress_dialogs)
|
for (const BackgroundProgressDialogData& data : s_background_progress_dialogs)
|
||||||
{
|
{
|
||||||
DebugAssert(data.id != id);
|
DebugAssert(data.id != id);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
BackgroundProgressDialogData data;
|
BackgroundProgressDialogData data;
|
||||||
data.id = id;
|
data.id = id;
|
||||||
|
@ -2271,41 +2483,44 @@ void ImGuiFullscreen::DrawToast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiFullscreen::SetTheme()
|
void ImGuiFullscreen::SetTheme(bool light)
|
||||||
{
|
{
|
||||||
#if 1
|
if (!light)
|
||||||
// dark
|
{
|
||||||
UIBackgroundColor = HEX_TO_IMVEC4(0x212121, 0xff);
|
// dark
|
||||||
UIBackgroundTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
|
UIBackgroundColor = HEX_TO_IMVEC4(0x212121, 0xff);
|
||||||
UIBackgroundLineColor = HEX_TO_IMVEC4(0xf0f0f0, 0xff);
|
UIBackgroundTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
|
||||||
UIBackgroundHighlightColor = HEX_TO_IMVEC4(0x4b4b4b, 0xff);
|
UIBackgroundLineColor = HEX_TO_IMVEC4(0xf0f0f0, 0xff);
|
||||||
UIPrimaryColor = HEX_TO_IMVEC4(0x2e2e2e, 0xff);
|
UIBackgroundHighlightColor = HEX_TO_IMVEC4(0x4b4b4b, 0xff);
|
||||||
UIPrimaryLightColor = HEX_TO_IMVEC4(0x484848, 0xff);
|
UIPrimaryColor = HEX_TO_IMVEC4(0x2e2e2e, 0xff);
|
||||||
UIPrimaryDarkColor = HEX_TO_IMVEC4(0x000000, 0xff);
|
UIPrimaryLightColor = HEX_TO_IMVEC4(0x484848, 0xff);
|
||||||
UIPrimaryTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
|
UIPrimaryDarkColor = HEX_TO_IMVEC4(0x000000, 0xff);
|
||||||
UIDisabledColor = HEX_TO_IMVEC4(0xaaaaaa, 0xff);
|
UIPrimaryTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
|
||||||
UITextHighlightColor = HEX_TO_IMVEC4(0x90caf9, 0xff);
|
UIDisabledColor = HEX_TO_IMVEC4(0xaaaaaa, 0xff);
|
||||||
UIPrimaryLineColor = HEX_TO_IMVEC4(0xffffff, 0xff);
|
UITextHighlightColor = HEX_TO_IMVEC4(0x90caf9, 0xff);
|
||||||
UISecondaryColor = HEX_TO_IMVEC4(0x0d47a1, 0xff);
|
UIPrimaryLineColor = HEX_TO_IMVEC4(0xffffff, 0xff);
|
||||||
UISecondaryLightColor = HEX_TO_IMVEC4(0x63a4ff, 0xff);
|
UISecondaryColor = HEX_TO_IMVEC4(0x0d47a1, 0xff);
|
||||||
UISecondaryDarkColor = HEX_TO_IMVEC4(0x002171, 0xff);
|
UISecondaryLightColor = HEX_TO_IMVEC4(0x63a4ff, 0xff);
|
||||||
UISecondaryTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
|
UISecondaryDarkColor = HEX_TO_IMVEC4(0x002171, 0xff);
|
||||||
#elif 1
|
UISecondaryTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
|
||||||
// light
|
}
|
||||||
UIBackgroundColor = HEX_TO_IMVEC4(0xf5f5f6, 0xff);
|
else
|
||||||
UIBackgroundTextColor = HEX_TO_IMVEC4(0x000000, 0xff);
|
{
|
||||||
UIBackgroundLineColor = HEX_TO_IMVEC4(0xe1e2e1, 0xff);
|
// light
|
||||||
UIBackgroundHighlightColor = HEX_TO_IMVEC4(0xe1e2e1, 0xff);
|
UIBackgroundColor = HEX_TO_IMVEC4(0xf5f5f6, 0xff);
|
||||||
UIPrimaryColor = HEX_TO_IMVEC4(0x0d47a1, 0xff);
|
UIBackgroundTextColor = HEX_TO_IMVEC4(0x000000, 0xff);
|
||||||
UIPrimaryLightColor = HEX_TO_IMVEC4(0x5472d3, 0xff);
|
UIBackgroundLineColor = HEX_TO_IMVEC4(0xe1e2e1, 0xff);
|
||||||
UIPrimaryDarkColor = HEX_TO_IMVEC4(0x002171, 0xff);
|
UIBackgroundHighlightColor = HEX_TO_IMVEC4(0xe1e2e1, 0xff);
|
||||||
UIPrimaryTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
|
UIPrimaryColor = HEX_TO_IMVEC4(0x0d47a1, 0xff);
|
||||||
UIDisabledColor = HEX_TO_IMVEC4(0xaaaaaa, 0xff);
|
UIPrimaryLightColor = HEX_TO_IMVEC4(0x5472d3, 0xff);
|
||||||
UITextHighlightColor = HEX_TO_IMVEC4(0x8e8e8e, 0xff);
|
UIPrimaryDarkColor = HEX_TO_IMVEC4(0x002171, 0xff);
|
||||||
UIPrimaryLineColor = HEX_TO_IMVEC4(0x000000, 0xff);
|
UIPrimaryTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
|
||||||
UISecondaryColor = HEX_TO_IMVEC4(0x3d5afe, 0xff);
|
UIDisabledColor = HEX_TO_IMVEC4(0xaaaaaa, 0xff);
|
||||||
UISecondaryLightColor = HEX_TO_IMVEC4(0xc0cfff, 0xff);
|
UITextHighlightColor = HEX_TO_IMVEC4(0x8e8e8e, 0xff);
|
||||||
UISecondaryDarkColor = HEX_TO_IMVEC4(0x0031ca, 0xff);
|
UIPrimaryLineColor = HEX_TO_IMVEC4(0x000000, 0xff);
|
||||||
UISecondaryTextColor = HEX_TO_IMVEC4(0x000000, 0xff);
|
UISecondaryColor = HEX_TO_IMVEC4(0x3d5afe, 0xff);
|
||||||
#endif
|
UISecondaryLightColor = HEX_TO_IMVEC4(0xc0cfff, 0xff);
|
||||||
}
|
UISecondaryDarkColor = HEX_TO_IMVEC4(0x0031ca, 0xff);
|
||||||
|
UISecondaryTextColor = HEX_TO_IMVEC4(0x000000, 0xff);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "IconsFontAwesome5.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "imgui_internal.h"
|
#include "imgui_internal.h"
|
||||||
|
@ -100,6 +101,11 @@ static ALWAYS_INLINE 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE ImVec4 MulAlpha(const ImVec4& v, float a)
|
||||||
|
{
|
||||||
|
return ImVec4(v.x, v.y, v.z, v.w * 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);
|
||||||
ImRect CenterImage(const ImRect& fit_rect, const ImVec2& image_size);
|
ImRect CenterImage(const ImRect& fit_rect, const ImVec2& image_size);
|
||||||
|
@ -107,7 +113,7 @@ ImRect CenterImage(const ImRect& fit_rect, const ImVec2& image_size);
|
||||||
/// Initializes, setting up any state.
|
/// Initializes, setting up any state.
|
||||||
bool Initialize(const char* placeholder_image_path);
|
bool Initialize(const char* placeholder_image_path);
|
||||||
|
|
||||||
void SetTheme();
|
void SetTheme(bool light);
|
||||||
void SetFonts(ImFont* standard_font, ImFont* medium_font, ImFont* large_font);
|
void SetFonts(ImFont* standard_font, ImFont* medium_font, ImFont* large_font);
|
||||||
bool UpdateLayoutScale();
|
bool UpdateLayoutScale();
|
||||||
|
|
||||||
|
@ -137,7 +143,7 @@ void PopSecondaryColor();
|
||||||
|
|
||||||
void DrawWindowTitle(const char* title);
|
void DrawWindowTitle(const char* title);
|
||||||
|
|
||||||
bool BeginFullscreenColumns(const char* title = nullptr);
|
bool BeginFullscreenColumns(const char* title = nullptr, float pos_y = 0.0f, bool expand_to_screen_width = false);
|
||||||
void EndFullscreenColumns();
|
void EndFullscreenColumns();
|
||||||
|
|
||||||
bool BeginFullscreenColumnWindow(float start, float end, const char* name,
|
bool BeginFullscreenColumnWindow(float start, float end, const char* name,
|
||||||
|
@ -163,6 +169,9 @@ bool ActiveButton(const char* title, bool is_active, bool enabled = true,
|
||||||
float height = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, ImFont* font = g_large_font);
|
float height = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, ImFont* font = g_large_font);
|
||||||
bool MenuButton(const char* title, const char* summary, bool enabled = true, float height = LAYOUT_MENU_BUTTON_HEIGHT,
|
bool MenuButton(const char* title, const char* summary, bool enabled = true, float height = LAYOUT_MENU_BUTTON_HEIGHT,
|
||||||
ImFont* font = g_large_font, ImFont* summary_font = g_medium_font);
|
ImFont* font = g_large_font, ImFont* summary_font = g_medium_font);
|
||||||
|
bool MenuButtonWithoutSummary(const char* title, bool enabled = true,
|
||||||
|
float height = LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, ImFont* font = g_large_font,
|
||||||
|
const ImVec2& text_align = ImVec2(0.0f, 0.0f));
|
||||||
bool MenuButtonWithValue(const char* title, const char* summary, const char* value, bool enabled = true,
|
bool MenuButtonWithValue(const char* title, const char* summary, const char* value, bool enabled = true,
|
||||||
float height = LAYOUT_MENU_BUTTON_HEIGHT, ImFont* font = g_large_font,
|
float height = LAYOUT_MENU_BUTTON_HEIGHT, ImFont* font = g_large_font,
|
||||||
ImFont* summary_font = g_medium_font);
|
ImFont* summary_font = g_medium_font);
|
||||||
|
@ -236,9 +245,23 @@ void CloseChoiceDialog();
|
||||||
|
|
||||||
using InputStringDialogCallback = std::function<void(std::string text)>;
|
using InputStringDialogCallback = std::function<void(std::string text)>;
|
||||||
bool IsInputDialogOpen();
|
bool IsInputDialogOpen();
|
||||||
void OpenInputStringDialog(std::string title, std::string message, std::string caption, std::string ok_button_text, InputStringDialogCallback callback);
|
void OpenInputStringDialog(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);
|
||||||
|
|
|
@ -458,18 +458,7 @@ ImFont* ImGuiManager::AddFixedFont(float size)
|
||||||
|
|
||||||
bool ImGuiManager::AddIconFonts(float size)
|
bool ImGuiManager::AddIconFonts(float size)
|
||||||
{
|
{
|
||||||
static constexpr ImWchar range_fa[] = {
|
static constexpr ImWchar range_fa[] = { 0xf002,0xf002,0xf005,0xf005,0xf007,0xf007,0xf00c,0xf00e,0xf011,0xf011,0xf013,0xf013,0xf017,0xf017,0xf019,0xf019,0xf021,0xf021,0xf025,0xf025,0xf027,0xf028,0xf02d,0xf02e,0xf030,0xf030,0xf03a,0xf03a,0xf03d,0xf03d,0xf049,0xf04c,0xf050,0xf050,0xf059,0xf059,0xf05e,0xf05e,0xf065,0xf065,0xf067,0xf067,0xf071,0xf071,0xf075,0xf075,0xf077,0xf078,0xf07b,0xf07c,0xf084,0xf085,0xf091,0xf091,0xf0a0,0xf0a0,0xf0ac,0xf0ad,0xf0c5,0xf0c5,0xf0c7,0xf0c8,0xf0cb,0xf0cb,0xf0d0,0xf0d0,0xf0e2,0xf0e2,0xf0eb,0xf0eb,0xf0f1,0xf0f1,0xf0f3,0xf0f3,0xf0fe,0xf0fe,0xf110,0xf110,0xf119,0xf119,0xf11b,0xf11c,0xf140,0xf140,0xf144,0xf144,0xf14a,0xf14a,0xf15b,0xf15b,0xf188,0xf188,0xf191,0xf192,0xf1dd,0xf1de,0xf1e6,0xf1e6,0xf1eb,0xf1eb,0xf1f8,0xf1f8,0xf1fc,0xf1fc,0xf242,0xf242,0xf245,0xf245,0xf26c,0xf26c,0xf279,0xf279,0xf2d0,0xf2d0,0xf2db,0xf2db,0xf2f2,0xf2f2,0xf2f5,0xf2f5,0xf410,0xf410,0xf466,0xf466,0xf500,0xf500,0xf51f,0xf51f,0xf545,0xf545,0xf548,0xf548,0xf552,0xf552,0xf57a,0xf57a,0xf5a2,0xf5a2,0xf5e7,0xf5e7,0xf65d,0xf65e,0xf6a9,0xf6a9,0xf7c2,0xf7c2,0xf807,0xf807,0xf815,0xf815,0xf818,0xf818,0xf84c,0xf84c,0xf8cc,0xf8cc,0x0,0x0 };
|
||||||
0xf002, 0xf002, 0xf005, 0xf005, 0xf007, 0xf007, 0xf00c, 0xf00e, 0xf011, 0xf011, 0xf013, 0xf013, 0xf017, 0xf017,
|
|
||||||
0xf019, 0xf019, 0xf021, 0xf021, 0xf025, 0xf025, 0xf027, 0xf028, 0xf02d, 0xf02e, 0xf030, 0xf030, 0xf03a, 0xf03a,
|
|
||||||
0xf03d, 0xf03d, 0xf049, 0xf04c, 0xf050, 0xf050, 0xf059, 0xf059, 0xf05e, 0xf05e, 0xf065, 0xf065, 0xf067, 0xf067,
|
|
||||||
0xf071, 0xf071, 0xf075, 0xf075, 0xf077, 0xf078, 0xf07b, 0xf07c, 0xf084, 0xf085, 0xf091, 0xf091, 0xf0a0, 0xf0a0,
|
|
||||||
0xf0ac, 0xf0ad, 0xf0c5, 0xf0c5, 0xf0c7, 0xf0c8, 0xf0cb, 0xf0cb, 0xf0d0, 0xf0d0, 0xf0e2, 0xf0e2, 0xf0eb, 0xf0eb,
|
|
||||||
0xf0f1, 0xf0f1, 0xf0f3, 0xf0f3, 0xf0fe, 0xf0fe, 0xf110, 0xf110, 0xf119, 0xf119, 0xf11b, 0xf11c, 0xf140, 0xf140,
|
|
||||||
0xf144, 0xf144, 0xf14a, 0xf14a, 0xf15b, 0xf15b, 0xf188, 0xf188, 0xf191, 0xf192, 0xf1dd, 0xf1de, 0xf1e6, 0xf1e6,
|
|
||||||
0xf1eb, 0xf1eb, 0xf1f8, 0xf1f8, 0xf242, 0xf242, 0xf245, 0xf245, 0xf26c, 0xf26c, 0xf279, 0xf279, 0xf2d0, 0xf2d0,
|
|
||||||
0xf2db, 0xf2db, 0xf2f2, 0xf2f2, 0xf2f5, 0xf2f5, 0xf410, 0xf410, 0xf466, 0xf466, 0xf500, 0xf500, 0xf51f, 0xf51f,
|
|
||||||
0xf545, 0xf545, 0xf548, 0xf548, 0xf552, 0xf552, 0xf57a, 0xf57a, 0xf5a2, 0xf5a2, 0xf5e7, 0xf5e7, 0xf65d, 0xf65e,
|
|
||||||
0xf6a9, 0xf6a9, 0xf7c2, 0xf7c2, 0xf807, 0xf807, 0xf815, 0xf815, 0xf818, 0xf818, 0xf8cc, 0xf8cc, 0x0, 0x0};
|
|
||||||
|
|
||||||
ImFontConfig cfg;
|
ImFontConfig cfg;
|
||||||
cfg.MergeMode = true;
|
cfg.MergeMode = true;
|
||||||
|
|
Loading…
Reference in a new issue