| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- // SPDX-FileCopyrightText: 2016 Citra Emulator Project
- // SPDX-License-Identifier: GPL-2.0-or-later
- #include <memory>
- #include <QCheckBox>
- #include <QHBoxLayout>
- #include <QLabel>
- #include <QLineEdit>
- #include <QObject>
- #include <QString>
- #include <QWidget>
- #include <qnamespace.h>
- #include "common/settings.h"
- #include "yuzu/configuration/configuration_shared.h"
- #include "yuzu/configuration/configure_per_game.h"
- #include "yuzu/configuration/shared_translation.h"
- namespace ConfigurationShared {
- static std::pair<QWidget*, std::function<void()>> CreateCheckBox(Settings::BasicSetting* setting,
- const QString& label,
- QWidget* parent,
- std::list<CheckState>& trackers) {
- QCheckBox* checkbox = new QCheckBox(label, parent);
- checkbox->setObjectName(QString::fromStdString(setting->GetLabel()));
- checkbox->setCheckState(setting->ToString() == "true" ? Qt::CheckState::Checked
- : Qt::CheckState::Unchecked);
- CheckState* tracker{};
- // Per-game config highlight
- if (setting->Switchable() && !Settings::IsConfiguringGlobal()) {
- bool global_state = setting->ToStringGlobal() == "true";
- bool state = setting->ToString() == "true";
- bool global = setting->UsingGlobal();
- tracker = &trackers.emplace_front(CheckState{});
- SetColoredTristate(checkbox, global, state, global_state, *tracker);
- }
- auto load_func = [checkbox, setting, tracker]() {
- if (Settings::IsConfiguringGlobal()) {
- setting->LoadString(checkbox->checkState() == Qt::Checked ? "true" : "false");
- }
- if (Settings::IsConfiguringGlobal() || !setting->Switchable()) {
- return;
- }
- if (*tracker != CheckState::Global) {
- setting->SetGlobal(false);
- setting->LoadString(checkbox->checkState() == Qt::Checked ? "true" : "false");
- } else {
- setting->SetGlobal(true);
- }
- };
- return {checkbox, load_func};
- }
- static std::tuple<QWidget*, void*, std::function<void()>> CreateCombobox(
- Settings::BasicSetting* setting, const QString& label, QWidget* parent) {
- const auto type = setting->TypeId();
- QWidget* group = new QWidget(parent);
- group->setObjectName(QString::fromStdString(setting->GetLabel()));
- QLayout* combobox_layout = new QHBoxLayout(group);
- QLabel* qt_label = new QLabel(label, parent);
- QComboBox* combobox = new QComboBox(parent);
- std::forward_list<QString> combobox_enumerations = ComboboxEnumeration(type, parent);
- for (const auto& item : combobox_enumerations) {
- combobox->addItem(item);
- }
- combobox_layout->addWidget(qt_label);
- combobox_layout->addWidget(combobox);
- combobox_layout->setSpacing(6);
- combobox_layout->setContentsMargins(0, 0, 0, 0);
- if (setting->Switchable() && !Settings::IsConfiguringGlobal()) {
- int current = std::stoi(setting->ToString());
- int global_value = std::stoi(setting->ToStringGlobal());
- SetColoredComboBox(combobox, group, global_value);
- if (setting->UsingGlobal()) {
- combobox->setCurrentIndex(USE_GLOBAL_INDEX);
- } else {
- SetHighlight(group, true);
- combobox->setCurrentIndex(current + USE_GLOBAL_OFFSET);
- }
- } else {
- combobox->setCurrentIndex(std::stoi(setting->ToString()));
- }
- const auto load_func = [combobox, setting]() {
- if (Settings::IsConfiguringGlobal()) {
- setting->LoadString(std::to_string(combobox->currentIndex()));
- }
- if (Settings::IsConfiguringGlobal() || !setting->Switchable()) {
- return;
- }
- bool using_global = combobox->currentIndex() == USE_GLOBAL_INDEX;
- int index = combobox->currentIndex() - USE_GLOBAL_OFFSET;
- setting->SetGlobal(using_global);
- if (!using_global) {
- setting->LoadString(std::to_string(index));
- }
- };
- return {group, combobox, load_func};
- }
- static std::tuple<QWidget*, void*, std::function<void()>> CreateLineEdit(
- Settings::BasicSetting* setting, const QString& label, QWidget* parent) {
- QWidget* widget = new QWidget(parent);
- QHBoxLayout* layout = new QHBoxLayout(widget);
- QLabel* q_label = new QLabel(label, widget);
- QLineEdit* line_edit = new QLineEdit(widget);
- layout->addWidget(q_label);
- layout->addStretch();
- layout->addWidget(line_edit);
- layout->setContentsMargins(0, 0, 0, 0);
- return {widget, line_edit, []() {}};
- }
- std::pair<QWidget*, void*> CreateWidget(Settings::BasicSetting* setting,
- const TranslationMap& translations, QWidget* parent,
- bool runtime_lock,
- std::forward_list<std::function<void(bool)>>& apply_funcs,
- std::list<CheckState>& trackers, RequestType request) {
- const auto type = setting->TypeId();
- const int id = setting->Id();
- QWidget* widget{nullptr};
- void* extra{nullptr};
- std::function<void()> load_func;
- const auto [label, tooltip] = [&]() {
- const auto& setting_label = setting->GetLabel();
- if (translations.contains(id)) {
- return std::pair{translations.at(id).first, translations.at(id).second};
- }
- LOG_ERROR(Frontend, "Translation table lacks entry for \"{}\"", setting_label);
- return std::pair{QString::fromStdString(setting_label), QStringLiteral("")};
- }();
- if (label == QStringLiteral("")) {
- LOG_DEBUG(Frontend, "Translation table has emtpy entry for \"{}\", skipping...",
- setting->GetLabel());
- return {nullptr, nullptr};
- }
- if (type == typeid(bool)) {
- auto pair = CreateCheckBox(setting, label, parent, trackers);
- widget = pair.first;
- load_func = pair.second;
- } else if (setting->IsEnum()) {
- auto tuple = CreateCombobox(setting, label, parent);
- widget = std::get<0>(tuple);
- extra = std::get<1>(tuple);
- load_func = std::get<2>(tuple);
- } else if (type == typeid(u32) || type == typeid(int)) {
- switch (request) {
- case RequestType::Default: {
- auto tuple = CreateLineEdit(setting, label, parent);
- widget = std::get<0>(tuple);
- extra = std::get<1>(tuple);
- load_func = std::get<2>(tuple);
- break;
- }
- case RequestType::ComboBox: {
- auto tuple = CreateCombobox(setting, label, parent);
- widget = std::get<0>(tuple);
- extra = std::get<1>(tuple);
- load_func = std::get<2>(tuple);
- break;
- }
- case RequestType::SpinBox:
- case RequestType::Slider:
- case RequestType::MaxEnum:
- break;
- }
- }
- if (widget == nullptr) {
- LOG_ERROR(Frontend, "No widget was created for \"{}\"", setting->GetLabel());
- return {nullptr, nullptr};
- }
- apply_funcs.push_front([load_func, setting](bool powered_on) {
- if (setting->RuntimeModfiable() || !powered_on) {
- load_func();
- }
- });
- bool enable = runtime_lock || setting->RuntimeModfiable();
- enable &=
- setting->Switchable() && !(Settings::IsConfiguringGlobal() && !setting->UsingGlobal());
- enable |= !setting->Switchable() && Settings::IsConfiguringGlobal() && runtime_lock;
- widget->setEnabled(enable);
- widget->setVisible(Settings::IsConfiguringGlobal() || setting->Switchable());
- widget->setToolTip(tooltip);
- return {widget, extra};
- }
- Tab::Tab(std::shared_ptr<std::forward_list<Tab*>> group_, QWidget* parent)
- : QWidget(parent), group{group_} {
- if (group != nullptr) {
- group->push_front(this);
- }
- }
- Tab::~Tab() = default;
- } // namespace ConfigurationShared
- void ConfigurationShared::ApplyPerGameSetting(Settings::SwitchableSetting<bool>* setting,
- const QCheckBox* checkbox,
- const CheckState& tracker) {
- if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) {
- setting->SetValue(checkbox->checkState());
- } else if (!Settings::IsConfiguringGlobal()) {
- if (tracker == CheckState::Global) {
- setting->SetGlobal(true);
- } else {
- setting->SetGlobal(false);
- setting->SetValue(checkbox->checkState());
- }
- }
- }
- void ConfigurationShared::SetPerGameSetting(QCheckBox* checkbox,
- const Settings::SwitchableSetting<bool>* setting) {
- if (setting->UsingGlobal()) {
- checkbox->setCheckState(Qt::PartiallyChecked);
- } else {
- checkbox->setCheckState(setting->GetValue() ? Qt::Checked : Qt::Unchecked);
- }
- }
- void ConfigurationShared::SetHighlight(QWidget* widget, bool highlighted) {
- if (highlighted) {
- widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,203,255,0.5) }")
- .arg(widget->objectName()));
- } else {
- widget->setStyleSheet(QStringLiteral(""));
- }
- widget->show();
- }
- void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, bool global, bool state,
- bool global_state, CheckState& tracker) {
- if (global) {
- tracker = CheckState::Global;
- } else {
- tracker = (state == global_state) ? CheckState::On : CheckState::Off;
- }
- SetHighlight(checkbox, tracker != CheckState::Global);
- QObject::connect(checkbox, &QCheckBox::clicked, checkbox, [checkbox, global_state, &tracker] {
- tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) %
- static_cast<int>(CheckState::Count));
- if (tracker == CheckState::Global) {
- checkbox->setChecked(global_state);
- }
- SetHighlight(checkbox, tracker != CheckState::Global);
- });
- }
- void ConfigurationShared::SetColoredComboBox(QComboBox* combobox, QWidget* target, int global) {
- InsertGlobalItem(combobox, global);
- QObject::connect(combobox, qOverload<int>(&QComboBox::activated), target,
- [target](int index) { SetHighlight(target, index != 0); });
- }
- void ConfigurationShared::InsertGlobalItem(QComboBox* combobox, int global_index) {
- const QString use_global_text =
- ConfigurePerGame::tr("Use global configuration (%1)").arg(combobox->itemText(global_index));
- combobox->insertItem(ConfigurationShared::USE_GLOBAL_INDEX, use_global_text);
- combobox->insertSeparator(ConfigurationShared::USE_GLOBAL_SEPARATOR_INDEX);
- }
- int ConfigurationShared::GetComboboxIndex(int global_setting_index, const QComboBox* combobox) {
- if (Settings::IsConfiguringGlobal()) {
- return combobox->currentIndex();
- }
- if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
- return global_setting_index;
- }
- return combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET;
- }
|