code:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>ConfigureApplets</class>
 <widget class="QWidget" name="ConfigureApplets">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>605</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <property name="accessibleName">
   <string>Applets</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout_1">
   <item>
    <layout class="QVBoxLayout" name="verticalLayout">
     <item>
      <widget class="QGroupBox" name="group_library_applet_modes">
       <property name="title">
        <string>Applet mode preference</string>
       </property>
       <layout class="QVBoxLayout">
        <item>
         <widget class="QWidget" name="applets_widget" native="true">
          <layout class="QVBoxLayout" name="verticalLayout_3">
           <property name="leftMargin">
            <number>0</number>
           </property>
           <property name="topMargin">
            <number>0</number>
           </property>
           <property name="rightMargin">
            <number>0</number>
           </property>
          </layout>
         </widget>
        </item>
       </layout>
      </widget>
     </item>
    </layout>
   </item>
   <item>
    <spacer name="verticalSpacer">
     <property name="orientation">
      <enum>Qt::Vertical</enum>
     </property>
     <property name="sizeHint" stdset="0">
      <size>
       <width>20</width>
       <height>40</height>
      </size>
     </property>
    </spacer>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include <map>
#include <memory>
#include <vector>
#include <QComboBox>
#include <QPushButton>

#include "audio_core/sink/sink.h"
#include "audio_core/sink/sink_details.h"
#include "common/common_types.h"
#include "common/settings.h"
#include "common/settings_common.h"
#include "core/core.h"
#include "ui_configure_audio.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_audio.h"
#include "yuzu/configuration/shared_translation.h"
#include "yuzu/configuration/shared_widget.h"
#include "yuzu/uisettings.h"

ConfigureAudio::ConfigureAudio(const Core::System& system_,
                               std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_,
                               const ConfigurationShared::Builder& builder, QWidget* parent)
    : Tab(group_, parent), ui(std::make_unique<Ui::ConfigureAudio>()), system{system_} {
    ui->setupUi(this);
    Setup(builder);

    SetConfiguration();
}

ConfigureAudio::~ConfigureAudio() = default;

void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) {
    auto& layout = *ui->audio_widget->layout();

    std::vector<Settings::BasicSetting*> settings;

    std::map<u32, QWidget*> hold;

    auto push_settings = [&](Settings::Category category) {
        for (auto* setting : Settings::values.linkage.by_category[category]) {
            settings.push_back(setting);
        }
    };

    auto push_ui_settings = [&](Settings::Category category) {
        for (auto* setting : UISettings::values.linkage.by_category[category]) {
            settings.push_back(setting);
        }
    };

    push_settings(Settings::Category::Audio);
    push_settings(Settings::Category::SystemAudio);
    push_ui_settings(Settings::Category::UiAudio);

    for (auto* setting : settings) {
        auto* widget = builder.BuildWidget(setting, apply_funcs);

        if (widget == nullptr) {
            continue;
        }
        if (!widget->Valid()) {
            widget->deleteLater();
            continue;
        }

        hold.emplace(std::pair{setting->Id(), widget});

        auto global_sink_match = [this] {
            return static_cast<Settings::AudioEngine>(sink_combo_box->currentIndex()) ==
                   Settings::values.sink_id.GetValue(true);
        };
        if (setting->Id() == Settings::values.sink_id.Id()) {
            // TODO (lat9nq): Let the system manage sink_id
            sink_combo_box = widget->combobox;
            InitializeAudioSinkComboBox();

            if (Settings::IsConfiguringGlobal()) {
                connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this,
                        &ConfigureAudio::UpdateAudioDevices);
            } else {
                restore_sink_button = ConfigurationShared::Widget::CreateRestoreGlobalButton(
                    Settings::values.sink_id.UsingGlobal(), widget);
                widget->layout()->addWidget(restore_sink_button);
                connect(restore_sink_button, &QAbstractButton::clicked, [this](bool) {
                    Settings::values.sink_id.SetGlobal(true);
                    const int sink_index = static_cast<int>(Settings::values.sink_id.GetValue());
                    sink_combo_box->setCurrentIndex(sink_index);
                    ConfigureAudio::UpdateAudioDevices(sink_index);
                    Settings::values.audio_output_device_id.SetGlobal(true);
                    Settings::values.audio_input_device_id.SetGlobal(true);
                    restore_sink_button->setVisible(false);
                });
                connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged),
                        [this, global_sink_match](const int slot) {
                            Settings::values.sink_id.SetGlobal(false);
                            Settings::values.audio_output_device_id.SetGlobal(false);
                            Settings::values.audio_input_device_id.SetGlobal(false);

                            restore_sink_button->setVisible(true);
                            restore_sink_button->setEnabled(true);
                            output_device_combo_box->setCurrentIndex(0);
                            restore_output_device_button->setVisible(true);
                            restore_output_device_button->setEnabled(global_sink_match());
                            input_device_combo_box->setCurrentIndex(0);
                            restore_input_device_button->setVisible(true);
                            restore_input_device_button->setEnabled(global_sink_match());
                            ConfigureAudio::UpdateAudioDevices(slot);
                        });
            }
        } else if (setting->Id() == Settings::values.audio_output_device_id.Id()) {
            // Keep track of output (and input) device comboboxes to populate them with system
            // devices, which are determined at run time
            output_device_combo_box = widget->combobox;

            if (!Settings::IsConfiguringGlobal()) {
                restore_output_device_button =
                    ConfigurationShared::Widget::CreateRestoreGlobalButton(
                        Settings::values.audio_output_device_id.UsingGlobal(), widget);
                restore_output_device_button->setEnabled(global_sink_match());
                restore_output_device_button->setVisible(
                    !Settings::values.audio_output_device_id.UsingGlobal());
                widget->layout()->addWidget(restore_output_device_button);
                connect(restore_output_device_button, &QAbstractButton::clicked, [this](bool) {
                    Settings::values.audio_output_device_id.SetGlobal(true);
                    SetOutputDevicesFromDeviceID();
                    restore_output_device_button->setVisible(false);
                });
                connect(output_device_combo_box, qOverload<int>(&QComboBox::currentIndexChanged),
                        [this, global_sink_match](int) {
                            if (updating_devices) {
                                return;
                            }
                            Settings::values.audio_output_device_id.SetGlobal(false);
                            restore_output_device_button->setVisible(true);
                            restore_output_device_button->setEnabled(global_sink_match());
                        });
            }
        } else if (setting->Id() == Settings::values.audio_input_device_id.Id()) {
            input_device_combo_box = widget->combobox;

            if (!Settings::IsConfiguringGlobal()) {
                restore_input_device_button =
                    ConfigurationShared::Widget::CreateRestoreGlobalButton(
                        Settings::values.audio_input_device_id.UsingGlobal(), widget);
                widget->layout()->addWidget(restore_input_device_button);
                connect(restore_input_device_button, &QAbstractButton::clicked, [this](bool) {
                    Settings::values.audio_input_device_id.SetGlobal(true);
                    SetInputDevicesFromDeviceID();
                    restore_input_device_button->setVisible(false);
                });
                connect(input_device_combo_box, qOverload<int>(&QComboBox::currentIndexChanged),
                        [this, global_sink_match](int) {
                            if (updating_devices) {
                                return;
                            }
                            Settings::values.audio_input_device_id.SetGlobal(false);
                            restore_input_device_button->setVisible(true);
                            restore_input_device_button->setEnabled(global_sink_match());
                        });
            }
        }
    }

    for (const auto& [id, widget] : hold) {
        layout.addWidget(widget);
    }
}

void ConfigureAudio::SetConfiguration() {
    SetOutputSinkFromSinkID();

    // The device list cannot be pre-populated (nor listed) until the output sink is known.
    UpdateAudioDevices(sink_combo_box->currentIndex());

    SetOutputDevicesFromDeviceID();
    SetInputDevicesFromDeviceID();
}

void ConfigureAudio::SetOutputSinkFromSinkID() {
    [[maybe_unused]] const QSignalBlocker blocker(sink_combo_box);

    int new_sink_index = 0;
    const QString sink_id = QString::fromStdString(Settings::values.sink_id.ToString());
    for (int index = 0; index < sink_combo_box->count(); index++) {
        if (sink_combo_box->itemText(index) == sink_id) {
            new_sink_index = index;
            break;
        }
    }

    sink_combo_box->setCurrentIndex(new_sink_index);
}

void ConfigureAudio::SetOutputDevicesFromDeviceID() {
    int new_device_index = 0;

    const QString output_device_id =
        QString::fromStdString(Settings::values.audio_output_device_id.GetValue());
    for (int index = 0; index < output_device_combo_box->count(); index++) {
        if (output_device_combo_box->itemText(index) == output_device_id) {
            new_device_index = index;
            break;
        }
    }

    output_device_combo_box->setCurrentIndex(new_device_index);
}

void ConfigureAudio::SetInputDevicesFromDeviceID() {
    int new_device_index = 0;
    const QString input_device_id =
        QString::fromStdString(Settings::values.audio_input_device_id.GetValue());
    for (int index = 0; index < input_device_combo_box->count(); index++) {
        if (input_device_combo_box->itemText(index) == input_device_id) {
            new_device_index = index;
            break;
        }
    }

    input_device_combo_box->setCurrentIndex(new_device_index);
}

void ConfigureAudio::ApplyConfiguration() {
    const bool is_powered_on = system.IsPoweredOn();
    for (const auto& apply_func : apply_funcs) {
        apply_func(is_powered_on);
    }

    Settings::values.sink_id.LoadString(
        sink_combo_box->itemText(sink_combo_box->currentIndex()).toStdString());
    Settings::values.audio_output_device_id.SetValue(
        output_device_combo_box->itemText(output_device_combo_box->currentIndex()).toStdString());
    Settings::values.audio_input_device_id.SetValue(
        input_device_combo_box->itemText(input_device_combo_box->currentIndex()).toStdString());
}

void ConfigureAudio::changeEvent(QEvent* event) {
    if (event->type() == QEvent::LanguageChange) {
        RetranslateUI();
    }

    QWidget::changeEvent(event);
}

void ConfigureAudio::UpdateAudioDevices(int sink_index) {
    updating_devices = true;
    output_device_combo_box->clear();
    output_device_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name));

    const auto sink_id =
        Settings::ToEnum<Settings::AudioEngine>(sink_combo_box->itemText(sink_index).toStdString());
    for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, false)) {
        output_device_combo_box->addItem(QString::fromStdString(device));
    }

    input_device_combo_box->clear();
    input_device_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name));
    for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, true)) {
        input_device_combo_box->addItem(QString::fromStdString(device));
    }
    updating_devices = false;
}

void ConfigureAudio::InitializeAudioSinkComboBox() {
    sink_combo_box->clear();
    sink_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name));

    for (const auto& id : AudioCore::Sink::GetSinkIDs()) {
        sink_combo_box->addItem(QString::fromStdString(Settings::CanonicalizeEnum(id)));
    }
}

void ConfigureAudio::RetranslateUI() {
    ui->retranslateUi(this);
}

repo_name: litucks/torzu

license: mit


code:
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <functional>
#include <memory>
#include <vector>
#include <QWidget>
#include "yuzu/configuration/configuration_shared.h"

class QComboBox;

namespace Core {
class System;
}

namespace Ui {
class ConfigureAudio;
}

namespace ConfigurationShared {
class Builder;
}

class ConfigureAudio : public ConfigurationShared::Tab {
    Q_OBJECT

public:
    explicit ConfigureAudio(const Core::System& system_,
                            std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,
                            const ConfigurationShared::Builder& builder, QWidget* parent = nullptr);
    ~ConfigureAudio() override;

    void ApplyConfiguration() override;
    void SetConfiguration() override;

private:
    void changeEvent(QEvent* event) override;

    void InitializeAudioSinkComboBox();

    void RetranslateUI();

    void UpdateAudioDevices(int sink_index);

    void SetOutputSinkFromSinkID();
    void SetOutputDevicesFromDeviceID();
    void SetInputDevicesFromDeviceID();

    void Setup(const ConfigurationShared::Builder& builder);

    std::unique_ptr<Ui::ConfigureAudio> ui;

    const Core::System& system;

    std::vector<std::function<void(bool)>> apply_funcs{};

    bool updating_devices = false;
    QComboBox* sink_combo_box;
    QPushButton* restore_sink_button;
    QComboBox* output_device_combo_box;
    QPushButton* restore_output_device_button;
    QComboBox* input_device_combo_box;
    QPushButton* restore_input_device_button;
};


code:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>ConfigureAudio</class>
 <widget class="QWidget" name="ConfigureAudio">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>367</width>
    <height>368</height>
   </rect>
  </property>
  <property name="accessibleName">
   <string>Audio</string>
  </property>
  <layout class="QVBoxLayout">
   <item>
    <widget class="QGroupBox" name="groupBox">
     <property name="title">
      <string>Audio</string>
     </property>
     <layout class="QVBoxLayout">
      <item>
       <widget class="QWidget" name="audio_widget" native="true">
        <property name="maximumSize">
         <size>
          <width>16777215</width>
          <height>16777213</height>
         </size>
        </property>
        <layout class="QVBoxLayout" name="verticalLayout">
         <property name="leftMargin">
          <number>0</number>
         </property>
         <property name="topMargin">
          <number>0</number>
         </property>
         <property name="rightMargin">
          <number>0</number>
         </property>
         <property name="bottomMargin">
          <number>0</number>
         </property>
        </layout>
       </widget>
      </item>
     </layout>
    </widget>
   </item>
   <item>
    <spacer>
     <property name="orientation">
      <enum>Qt::Vertical</enum>
     </property>
     <property name="sizeHint" stdset="0">
      <size>
       <width>167</width>
       <height>55</height>
      </size>
     </property>
    </spacer>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>


code:
// Text : Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later

#include <memory>
#include <QtCore>
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA
#include <QCameraImageCapture>
#include <QCameraInfo>
#endif
#include <QStandardItemModel>
#include <QTimer>

#include "common/settings.h"
#include "input_common/drivers/camera.h"
#include "input_common/main.h"
#include "ui_configure_camera.h"
#include "yuzu/configuration/configure_camera.h"

ConfigureCamera::ConfigureCamera(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_)
    : QDialog(parent), input_subsystem{input_subsystem_},
      ui(std::make_unique<Ui::ConfigureCamera>()) {
    ui->setupUi(this);

    connect(ui->restore_defaults_button, &QPushButton::clicked, this,
            &ConfigureCamera::RestoreDefaults);
    connect(ui->preview_button, &QPushButton::clicked, this, &ConfigureCamera::PreviewCamera);

    auto blank_image = QImage(320, 240, QImage::Format::Format_RGB32);
    blank_image.fill(Qt::black);
    DisplayCapturedFrame(0, blank_image);

    LoadConfiguration();
    resize(0, 0);
}

ConfigureCamera::~ConfigureCamera() = default;

void ConfigureCamera::PreviewCamera() {
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA
    const auto index = ui->ir_sensor_combo_box->currentIndex();
    bool camera_found = false;
    const QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
    for (const QCameraInfo& cameraInfo : cameras) {
        if (input_devices[index] == cameraInfo.deviceName().toStdString() ||
            input_devices[index] == "Auto") {
            LOG_INFO(Frontend, "Selected Camera {} {}", cameraInfo.description().toStdString(),
                     cameraInfo.deviceName().toStdString());
            camera = std::make_unique<QCamera>(cameraInfo);
            if (!camera->isCaptureModeSupported(QCamera::CaptureMode::CaptureViewfinder) &&
                !camera->isCaptureModeSupported(QCamera::CaptureMode::CaptureStillImage)) {
                LOG_ERROR(Frontend,
                          "Camera doesn't support CaptureViewfinder or CaptureStillImage");
                continue;
            }
            camera_found = true;
            break;
        }
    }

    // Clear previous frame
    auto blank_image = QImage(320, 240, QImage::Format::Format_RGB32);
    blank_image.fill(Qt::black);
    DisplayCapturedFrame(0, blank_image);

    if (!camera_found) {
        return;
    }

    camera_capture = std::make_unique<QCameraImageCapture>(camera.get());

    if (!camera_capture->isCaptureDestinationSupported(
            QCameraImageCapture::CaptureDestination::CaptureToBuffer)) {
        LOG_ERROR(Frontend, "Camera doesn't support saving to buffer");
        return;
    }

    camera_capture->setCaptureDestination(QCameraImageCapture::CaptureDestination::CaptureToBuffer);
    connect(camera_capture.get(), &QCameraImageCapture::imageCaptured, this,
            &ConfigureCamera::DisplayCapturedFrame);
    camera->unload();
    if (camera->isCaptureModeSupported(QCamera::CaptureMode::CaptureViewfinder)) {
        camera->setCaptureMode(QCamera::CaptureViewfinder);
    } else if (camera->isCaptureModeSupported(QCamera::CaptureMode::CaptureStillImage)) {
        camera->setCaptureMode(QCamera::CaptureStillImage);
    }
    camera->load();
    camera->start();

    pending_snapshots = 0;
    is_virtual_camera = false;

    camera_timer = std::make_unique<QTimer>();
    connect(camera_timer.get(), &QTimer::timeout, [this] {
        // If the camera doesn't capture, test for virtual cameras
        if (pending_snapshots > 5) {
            is_virtual_camera = true;
        }
        // Virtual cameras like obs need to reset the camera every capture
        if (is_virtual_camera) {
            camera->stop();
            camera->start();
        }
        pending_snapshots++;
        camera_capture->capture();
    });

    camera_timer->start(250);
#endif
}

void ConfigureCamera::DisplayCapturedFrame(int requestId, const QImage& img) {
    LOG_INFO(Frontend, "ImageCaptured {} {}", img.width(), img.height());
    const auto converted = img.scaled(320, 240, Qt::AspectRatioMode::IgnoreAspectRatio,
                                      Qt::TransformationMode::SmoothTransformation);
    ui->preview_box->setPixmap(QPixmap::fromImage(converted));
    pending_snapshots = 0;
}

void ConfigureCamera::changeEvent(QEvent* event) {
    if (event->type() == QEvent::LanguageChange) {
        RetranslateUI();
    }

    QDialog::changeEvent(event);
}

void ConfigureCamera::RetranslateUI() {
    ui->retranslateUi(this);
}

void ConfigureCamera::ApplyConfiguration() {
    const auto index = ui->ir_sensor_combo_box->currentIndex();
    Settings::values.ir_sensor_device.SetValue(input_devices[index]);
}

void ConfigureCamera::LoadConfiguration() {
    input_devices.clear();
    ui->ir_sensor_combo_box->clear();
    input_devices.push_back("Auto");
    ui->ir_sensor_combo_box->addItem(tr("Auto"));
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA
    const auto cameras = QCameraInfo::availableCameras();
    for (const QCameraInfo& cameraInfo : cameras) {
        input_devices.push_back(cameraInfo.deviceName().toStdString());
        ui->ir_sensor_combo_box->addItem(cameraInfo.description());
    }
#endif

    const auto current_device = Settings::values.ir_sensor_device.GetValue();

    const auto devices_it = std::find_if(
        input_devices.begin(), input_devices.end(),
        [current_device](const std::string& device) { return device == current_device; });
    const int device_index =
        devices_it != input_devices.end()
            ? static_cast<int>(std::distance(input_devices.begin(), devices_it))
            : 0;
    ui->ir_sensor_combo_box->setCurrentIndex(device_index);
}

void ConfigureCamera::RestoreDefaults() {
    ui->ir_sensor_combo_box->setCurrentIndex(0);
}


code:
// Text : Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later

#pragma once

#include <memory>
#include <QDialog>

class QTimer;
class QCamera;
class QCameraImageCapture;

namespace InputCommon {
class InputSubsystem;
} // namespace InputCommon

namespace Ui {
class ConfigureCamera;
}

class ConfigureCamera : public QDialog {
    Q_OBJECT

public:
    explicit ConfigureCamera(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_);
    ~ConfigureCamera() override;

    void ApplyConfiguration();

private:
    void changeEvent(QEvent* event) override;
    void RetranslateUI();

    /// Load configuration settings.
    void LoadConfiguration();

    /// Restore all buttons to their default values.
    void RestoreDefaults();

    void DisplayCapturedFrame(int requestId, const QImage& img);

    /// Loads and signals the current selected camera to display a frame
    void PreviewCamera();

    InputCommon::InputSubsystem* input_subsystem;

    bool is_virtual_camera;
    int pending_snapshots;
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA
    std::unique_ptr<QCamera> camera;
    std::unique_ptr<QCameraImageCapture> camera_capture;
#endif
    std::unique_ptr<QTimer> camera_timer;
    std::vector<std::string> input_devices;
    std::unique_ptr<Ui::ConfigureCamera> ui;
};


code:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>ConfigureCamera</class>
 <widget class="QDialog" name="ConfigureCamera">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>298</width>
    <height>339</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Configure Infrared Camera</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
    <widget class="QLabel" name="label_2">
     <property name="minimumSize">
      <size>
       <width>280</width>
       <height>0</height>
      </size>
     </property>
     <property name="text">
      <string>Select where the image of the emulated camera comes from. It may be a virtual camera or a real camera.</string>
     </property>
     <property name="wordWrap">
      <bool>true</bool>
     </property>
    </widget>
   </item>
   <item>
    <spacer name="verticalSpacer_2">
     <property name="orientation">
      <enum>Qt::Vertical</enum>
     </property>
     <property name="sizeType">
      <enum>QSizePolicy::Fixed</enum>
     </property>
     <property name="sizeHint" stdset="0">
      <size>
       <width>20</width>
       <height>20</height>
      </size>
     </property>
    </spacer>
   </item>
   <item>
    <widget class="QGroupBox" name="gridGroupBox">
     <property name="title">
      <string>Camera Image Source:</string>
     </property>
     <layout class="QGridLayout" name="gridLayout">
      <item row="0" column="0">
       <spacer name="horizontalSpacer">
        <property name="orientation">
         <enum>Qt::Horizontal</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>40</width>
          <height>20</height>
         </size>
        </property>
       </spacer>
      </item>
       <item row="0" column="1">
         <widget class="QLabel" name="label_3">
           <property name="text">
             <string>Input device:</string>
           </property>
         </widget>
       </item>
       <item row="0" column="2">
         <widget class="QComboBox" name="ir_sensor_combo_box"/>
       </item>
      <item row="0" column="3">
       <spacer name="horizontalSpacer_2">
        <property name="orientation">
         <enum>Qt::Horizontal</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>40</width>
          <height>20</height>
         </size>
        </property>
       </spacer>
      </item>
     </layout>
    </widget>
   </item><item>
    <widget class="QGroupBox" name="previewBox">
     <property name="title">
      <string>Preview</string>
     </property>
     <layout class="QVBoxLayout" name="verticalLayout_3">
      <item>
       <widget class="QLabel" name="preview_box">
         <property name="minimumSize">
           <size>
             <width>320</width>
             <height>240</height>
           </size>
         </property>
        <property name="toolTip">
         <string>Resolution: 320*240</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QPushButton" name="preview_button">
        <property name="text">
         <string>Click to preview</string>
        </property>
       </widget>
      </item>
     </layout>
    </widget>
   </item>
   <item>
    <spacer name="verticalSpacer">
     <property name="orientation">
      <enum>Qt::Vertical</enum>
     </property>
     <property name="sizeHint" stdset="0">
      <size>
       <width>20</width>
       <height>40</height>
      </size>
     </property>
    </spacer>
   </item>
   <item>
    <layout class="QHBoxLayout" name="horizontalLayout">
     <item>
      <widget class="QPushButton" name="restore_defaults_button">
       <property name="text">
        <string>Restore Defaults</string>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QDialogButtonBox" name="buttonBox">
       <property name="standardButtons">
        <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
       </property>
      </widget>
     </item>
    </layout>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections>
  <connection>
   <sender>buttonBox</sender>
   <signal>accepted()</signal>
   <receiver>ConfigureCamera</receiver>
   <slot>accept()</slot>
  </connection>
  <connection>
   <sender>buttonBox</sender>
   <signal>rejected()</signal>
   <receiver>ConfigureCamera</receiver>
   <slot>reject()</slot>
   </connection>
 </connections>
</ui>


code:
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include <memory>
#include <typeinfo>
#include <vector>
#include <QComboBox>
#include "common/common_types.h"
#include "common/settings.h"
#include "common/settings_enums.h"
#include "configuration/shared_widget.h"
#include "core/core.h"
#include "ui_configure_cpu.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_cpu.h"

ConfigureCpu::ConfigureCpu(const Core::System& system_,
                           std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group_,
                           const ConfigurationShared::Builder& builder, QWidget* parent)
    : Tab(group_, parent), ui{std::make_unique<Ui::ConfigureCpu>()}, system{system_},
      combobox_translations(builder.ComboboxTranslations()) {
    ui->setupUi(this);

    Setup(builder);

    SetConfiguration();

    connect(accuracy_combobox, qOverload<int>(&QComboBox::currentIndexChanged), this,
            &ConfigureCpu::UpdateGroup);

    connect(backend_combobox, qOverload<int>(&QComboBox::currentIndexChanged), this,
            &ConfigureCpu::UpdateGroup);

#ifdef HAS_NCE
    ui->backend_group->setVisible(true);
#endif
}

ConfigureCpu::~ConfigureCpu() = default;

void ConfigureCpu::SetConfiguration() {}
void ConfigureCpu::Setup(const ConfigurationShared::Builder& builder) {
    auto* accuracy_layout = ui->widget_accuracy->layout();
    auto* backend_layout = ui->widget_backend->layout();
    auto* unsafe_layout = ui->unsafe_widget->layout();
    std::map<u32, QWidget*> unsafe_hold{};

    std::vector<Settings::BasicSetting*> settings;
    const auto push = [&](Settings::Category category) {
        for (const auto setting : Settings::values.linkage.by_category[category]) {
            settings.push_back(setting);
        }
    };

    push(Settings::Category::Cpu);
    push(Settings::Category::CpuUnsafe);

    for (const auto setting : settings) {
        auto* widget = builder.BuildWidget(setting, apply_funcs);

        if (widget == nullptr) {
            continue;
        }
        if (!widget->Valid()) {
            widget->deleteLater();
            continue;
        }

        if (setting->Id() == Settings::values.cpu_accuracy.Id()) {
            // Keep track of cpu_accuracy combobox to display/hide the unsafe settings
            accuracy_layout->addWidget(widget);
            accuracy_combobox = widget->combobox;
        } else if (setting->Id() == Settings::values.cpu_backend.Id()) {
            backend_layout->addWidget(widget);
            backend_combobox = widget->combobox;
        } else {
            // Presently, all other settings here are unsafe checkboxes
            unsafe_hold.insert({setting->Id(), widget});
        }
    }

    for (const auto& [label, widget] : unsafe_hold) {
        unsafe_layout->addWidget(widget);
    }

    UpdateGroup(accuracy_combobox->currentIndex());
    UpdateGroup(backend_combobox->currentIndex());
}

void ConfigureCpu::UpdateGroup(int index) {
    const auto accuracy = static_cast<Settings::CpuAccuracy>(
        combobox_translations.at(Settings::EnumMetadata<Settings::CpuAccuracy>::Index())[index]
            .first);
    ui->unsafe_group->setVisible(accuracy == Settings::CpuAccuracy::Unsafe);
}

void ConfigureCpu::ApplyConfiguration() {
    const bool is_powered_on = system.IsPoweredOn();
    for (const auto& apply_func : apply_funcs) {
        apply_func(is_powered_on);
    }
}

void ConfigureCpu::changeEvent(QEvent* event) {
    if (event->type() == QEvent::LanguageChange) {
        RetranslateUI();
    }

    QWidget::changeEvent(event);
}

void ConfigureCpu::RetranslateUI() {
    ui->retranslateUi(this);
}


code:
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <memory>
#include <vector>
#include <QWidget>
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/shared_translation.h"

class QComboBox;

namespace Core {
class System;
}

namespace Ui {
class ConfigureCpu;
}

namespace ConfigurationShared {
class Builder;
}

class ConfigureCpu : public ConfigurationShared::Tab {
    Q_OBJECT

public:
    explicit ConfigureCpu(const Core::System& system_,
                          std::shared_ptr<std::vector<ConfigurationShared::Tab*>> group,
                          const ConfigurationShared::Builder& builder, QWidget* parent = nullptr);
    ~ConfigureCpu() override;

    void ApplyConfiguration() override;
    void SetConfiguration() override;

private:
    void changeEvent(QEvent* event) override;
    void RetranslateUI();

    void UpdateGroup(int index);

    void Setup(const ConfigurationShared::Builder& builder);

    std::unique_ptr<Ui::ConfigureCpu> ui;

    const Core::System& system;

    const ConfigurationShared::ComboboxTranslationMap& combobox_translations;
    std::vector<std::function<void(bool)>> apply_funcs{};

    QComboBox* accuracy_combobox;
    QComboBox* backend_combobox;
};


code:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>ConfigureCpu</class>
 <widget class="QWidget" name="ConfigureCpu">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>448</width>
    <height>439</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <property name="accessibleName">
   <string>CPU</string>
  </property>
  <layout class="QVBoxLayout" name="vboxlayout_2" stretch="0">
   <item>
    <layout class="QVBoxLayout" name="vboxlayout">
     <property name="bottomMargin">
      <number>0</number>
     </property>
     <item>
      <widget class="QGroupBox" name="groupBox">
       <property name="title">
        <string>General</string>
       </property>
       <layout class="QVBoxLayout">
        <item>
         <widget class="QWidget" name="widget_accuracy" native="true">
          <layout class="QVBoxLayout" name="verticalLayout">
           <property name="leftMargin">
            <number>0</number>
           </property>
           <property name="topMargin">
            <number>0</number>
           </property>
           <property name="rightMargin">
            <number>0</number>
           </property>
           <property name="bottomMargin">
            <number>0</number>
           </property>
          </layout>
         </widget>
        </item>
        <item>
         <widget class="QLabel" name="label_recommended_accuracy">
          <property name="text">
           <string>We recommend setting accuracy to "Auto".</string>
          </property>
          <property name="wordWrap">
           <bool>false</bool>
          </property>
         </widget>
        </item>
       </layout>
      </widget>
     </item>
     <item>
      <widget class="QGroupBox" name="backend_group">
       <property name="title">
        <string>CPU Backend</string>
       </property>
       <layout class="QVBoxLayout">
        <item>
         <widget class="QWidget" name="widget_backend" native="true">
          <layout class="QVBoxLayout" name="verticalLayout1">
           <property name="leftMargin">
            <number>0</number>
           </property>
           <property name="topMargin">
            <number>0</number>
           </property>
           <property name="rightMargin">
            <number>0</number>
           </property>
           <property name="bottomMargin">
            <number>0</number>
           </property>
          </layout>
         </widget>
        </item>
       </layout>
       <property name="visible">
        <bool>false</bool>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QGroupBox" name="unsafe_group">
       <property name="title">
        <string>Unsafe CPU Optimization Settings</string>
       </property>
       <layout class="QVBoxLayout">
        <item>
         <widget class="QLabel" name="label_accuracy_description">
          <property name="text">
           <string>These settings reduce accuracy for speed.</string>
          </property>
          <property name="wordWrap">
           <bool>false</bool>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QWidget" name="unsafe_widget" native="true">
          <layout class="QVBoxLayout" name="unsafe_layout">
           <property name="leftMargin">
            <number>0</number>
           </property>
           <property name="topMargin">
            <number>0</number>
           </property>
           <property name="rightMargin">
            <number>0</number>
           </property>
           <property name="bottomMargin">
            <number>0</number>
           </property>
          </layout>
         </widget>
        </item>
       </layout>
      </widget>
     </item>
     <item>
      <spacer name="verticalSpacer">
       <property name="orientation">
        <enum>Qt::Vertical</enum>
       </property>
       <property name="sizeType">
        <enum>QSizePolicy::Expanding</enum>
       </property>
       <property name="sizeHint" stdset="0">
        <size>
         <width>20</width>
         <height>40</height>
        </size>
       </property>
      </spacer>
     </item>
    </layout>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>


code:
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "common/settings.h"
#include "core/core.h"
#include "ui_configure_cpu_debug.h"
#include "yuzu/configuration/configure_cpu_debug.h"

ConfigureCpuDebug::ConfigureCpuDebug(const Core::System& system_, QWidget* parent)
    : QWidget(parent), ui{std::make_unique<Ui::ConfigureCpuDebug>()}, system{system_} {
    ui->setupUi(this);

    SetConfiguration();
}

ConfigureCpuDebug::~ConfigureCpuDebug() = default;

void ConfigureCpuDebug::SetConfiguration() {
    const bool runtime_lock = !system.IsPoweredOn();

    ui->cpuopt_page_tables->setEnabled(runtime_lock);
    ui->cpuopt_page_tables->setChecked(Settings::values.cpuopt_page_tables.GetValue());
    ui->cpuopt_block_linking->setEnabled(runtime_lock);
    ui->cpuopt_block_linking->setChecked(Settings::values.cpuopt_block_linking.GetValue());
    ui->cpuopt_return_stack_buffer->setEnabled(runtime_lock);
    ui->cpuopt_return_stack_buffer->setChecked(
        Settings::values.cpuopt_return_stack_buffer.GetValue());
    ui->cpuopt_fast_dispatcher->setEnabled(runtime_lock);
    ui->cpuopt_fast_dispatcher->setChecked(Settings::values.cpuopt_fast_dispatcher.GetValue());
    ui->cpuopt_context_elimination->setEnabled(runtime_lock);
    ui->cpuopt_context_elimination->setChecked(
        Settings::values.cpuopt_context_elimination.GetValue());
    ui->cpuopt_const_prop->setEnabled(runtime_lock);
    ui->cpuopt_const_prop->setChecked(Settings::values.cpuopt_const_prop.GetValue());
    ui->cpuopt_misc_ir->setEnabled(runtime_lock);
    ui->cpuopt_misc_ir->setChecked(Settings::values.cpuopt_misc_ir.GetValue());
    ui->cpuopt_reduce_misalign_checks->setEnabled(runtime_lock);
    ui->cpuopt_reduce_misalign_checks->setChecked(
        Settings::values.cpuopt_reduce_misalign_checks.GetValue());
    ui->cpuopt_fastmem->setEnabled(runtime_lock);
    ui->cpuopt_fastmem->setChecked(Settings::values.cpuopt_fastmem.GetValue());
    ui->cpuopt_fastmem_exclusives->setEnabled(runtime_lock);
    ui->cpuopt_fastmem_exclusives->setChecked(
        Settings::values.cpuopt_fastmem_exclusives.GetValue());
    ui->cpuopt_recompile_exclusives->setEnabled(runtime_lock);
    ui->cpuopt_recompile_exclusives->setChecked(
        Settings::values.cpuopt_recompile_exclusives.GetValue());
    ui->cpuopt_ignore_memory_aborts->setEnabled(runtime_lock);
    ui->cpuopt_ignore_memory_aborts->setChecked(
        Settings::values.cpuopt_ignore_memory_aborts.GetValue());
}

void ConfigureCpuDebug::ApplyConfiguration() {
    Settings::values.cpuopt_page_tables = ui->cpuopt_page_tables->isChecked();
    Settings::values.cpuopt_block_linking = ui->cpuopt_block_linking->isChecked();
    Settings::values.cpuopt_return_stack_buffer = ui->cpuopt_return_stack_buffer->isChecked();
    Settings::values.cpuopt_fast_dispatcher = ui->cpuopt_fast_dispatcher->isChecked();
    Settings::values.cpuopt_context_elimination = ui->cpuopt_context_elimination->isChecked();
    Settings::values.cpuopt_const_prop = ui->cpuopt_const_prop->isChecked();
    Settings::values.cpuopt_misc_ir = ui->cpuopt_misc_ir->isChecked();
    Settings::values.cpuopt_reduce_misalign_checks = ui->cpuopt_reduce_misalign_checks->isChecked();
    Settings::values.cpuopt_fastmem = ui->cpuopt_fastmem->isChecked();
    Settings::values.cpuopt_fastmem_exclusives = ui->cpuopt_fastmem_exclusives->isChecked();
    Settings::values.cpuopt_recompile_exclusives = ui->cpuopt_recompile_exclusives->isChecked();
    Settings::values.cpuopt_ignore_memory_aborts = ui->cpuopt_ignore_memory_aborts->isChecked();
}

void ConfigureCpuDebug::changeEvent(QEvent* event) {
    if (event->type() == QEvent::LanguageChange) {
        RetranslateUI();
    }

    QWidget::changeEvent(event);
}

void ConfigureCpuDebug::RetranslateUI() {
    ui->retranslateUi(this);
}


code:
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <memory>
#include <QWidget>

namespace Core {
class System;
}

namespace Ui {
class ConfigureCpuDebug;
}

class ConfigureCpuDebug : public QWidget {
    Q_OBJECT

public:
    explicit ConfigureCpuDebug(const Core::System& system_, QWidget* parent = nullptr);
    ~ConfigureCpuDebug() override;

    void ApplyConfiguration();

private:
    void changeEvent(QEvent* event) override;
    void RetranslateUI();

    void SetConfiguration();

    std::unique_ptr<Ui::ConfigureCpuDebug> ui;

    const Core::System& system;
};


code:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>ConfigureCpuDebug</class>
 <widget class="QWidget" name="ConfigureCpuDebug">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>592</width>
    <height>503</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <property name="accessibleName">
   <string>CPU</string>
  </property>
  <layout class="QVBoxLayout">
   <item>
    <layout class="QVBoxLayout">
     <item>
      <widget class="QGroupBox" name="groupBox">
       <property name="title">
        <string>Toggle CPU Optimizations</string>
       </property>
       <layout class="QVBoxLayout">
        <item>
         <widget class="QLabel" name="label">
          <property name="text">
           <string>
For debugging only.
If you're not sure what these do, keep all of these enabled.
These settings, when disabled, only take effect when CPU Debugging is enabled.
</string>
          </property>
          <property name="wordWrap">
           <bool>false</bool>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QCheckBox" name="cpuopt_page_tables">
          <property name="toolTip">
           <string>

This optimization speeds up memory accesses by the guest program.

Enabling it inlines accesses to PageTable::pointers into emitted code.

Disabling this forces all memory accesses to go through the Memory::Read/Memory::Write functions.

           </string>
          </property>
          <property name="text">
           <string>Enable inline page tables</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QCheckBox" name="cpuopt_block_linking">
          <property name="toolTip">
           <string>

This optimization avoids dispatcher lookups by allowing emitted basic blocks to jump directly to other basic blocks if the destination PC is static.

           </string>
          </property>
          <property name="text">
           <string>Enable block linking</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QCheckBox" name="cpuopt_return_stack_buffer">
          <property name="toolTip">
           <string>

This optimization avoids dispatcher lookups by keeping track potential return addresses of BL instructions. This approximates what happens with a return stack buffer on a real CPU.

           </string>
          </property>
          <property name="text">
           <string>Enable return stack buffer</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QCheckBox" name="cpuopt_fast_dispatcher">
          <property name="toolTip">
           <string>

Enable a two-tiered dispatch system. A faster dispatcher written in assembly has a small MRU cache of jump destinations is used first. If that fails, dispatch falls back to the slower C++ dispatcher.

           </string>
          </property>
          <property name="text">
           <string>Enable fast dispatcher</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QCheckBox" name="cpuopt_context_elimination">
          <property name="toolTip">
           <string>

Enables an IR optimization that reduces unnecessary accesses to the CPU context structure.

           </string>
          </property>
          <property name="text">
           <string>Enable context elimination</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QCheckBox" name="cpuopt_const_prop">
          <property name="toolTip">
           <string>

Enables IR optimizations that involve constant propagation.

           </string>
          </property>
          <property name="text">
           <string>Enable constant propagation</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QCheckBox" name="cpuopt_misc_ir">
          <property name="toolTip">
           <string>

Enables miscellaneous IR optimizations.

           </string>
          </property>
          <property name="text">
           <string>Enable miscellaneous optimizations</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QCheckBox" name="cpuopt_reduce_misalign_checks">
          <property name="toolTip">
           <string>

When enabled, a misalignment is only triggered when an access crosses a page boundary.

When disabled, a misalignment is triggered on all misaligned accesses.

           </string>
          </property>
          <property name="text">
           <string>Enable misalignment check reduction</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QCheckBox" name="cpuopt_fastmem">
          <property name="toolTip">
           <string>

This optimization speeds up memory accesses by the guest program.

Enabling it causes guest memory reads/writes to be done directly into memory and make use of Host's MMU.

Disabling this forces all memory accesses to use Software MMU Emulation.

           </string>
          </property>
          <property name="text">
           <string>Enable Host MMU Emulation (general memory instructions)</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QCheckBox" name="cpuopt_fastmem_exclusives">
          <property name="toolTip">
           <string>

This optimization speeds up exclusive memory accesses by the guest program.

Enabling it causes guest exclusive memory reads/writes to be done directly into memory and make use of Host's MMU.

Disabling this forces all exclusive memory accesses to use Software MMU Emulation.

           </string>
          </property>
          <property name="text">
           <string>Enable Host MMU Emulation (exclusive memory instructions)</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QCheckBox" name="cpuopt_recompile_exclusives">
          <property name="toolTip">
           <string>

This optimization speeds up exclusive memory accesses by the guest program.

Enabling it reduces the overhead of fastmem failure of exclusive memory accesses.

           </string>
          </property>
          <property name="text">
           <string>Enable recompilation of exclusive memory instructions</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QCheckBox" name="cpuopt_ignore_memory_aborts">
          <property name="toolTip">
           <string>

This optimization speeds up memory accesses by allowing invalid memory accesses to succeed.

Enabling it reduces the overhead of all memory accesses and has no impact on programs that don't access invalid memory.

           </string>
          </property>
          <property name="text">
           <string>Enable fallbacks for invalid memory accesses</string>
          </property>
         </widget>
        </item>
       </layout>
      </widget>
     </item>
    </layout>
   </item>
   <item>
    <spacer name="verticalSpacer">
     <property name="orientation">
      <enum>Qt::Vertical</enum>
     </property>
     <property name="sizeHint" stdset="0">
      <size>
       <width>20</width>
       <height>40</height>
      </size>
     </property>
    </spacer>
   </item>
   <item>
    <widget class="QLabel" name="label_disable_info">
     <property name="text">
      <string>CPU settings are available only when game is not running.</string>
     </property>
     <property name="wordWrap">
      <bool>true</bool>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>


code:
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include <QDesktopServices>
#include <QMessageBox>
#include <QUrl>
#include "common/fs/path_util.h"
#include "common/logging/backend.h"
#include "common/logging/filter.h"
#include "common/settings.h"
#include "core/core.h"
#include "ui_configure_debug.h"
#include "yuzu/configuration/configure_debug.h"
#include "yuzu/debugger/console.h"
#include "yuzu/uisettings.h"

ConfigureDebug::ConfigureDebug(const Core::System& system_, QWidget* parent)
    : QScrollArea(parent), ui{std::make_unique<Ui::ConfigureDebug>()}, system{system_} {
    ui->setupUi(this);
    SetConfiguration();

    connect(ui->open_log_button, &QPushButton::clicked, []() {
        const auto path =
            QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::LogDir));
        QDesktopServices::openUrl(QUrl::fromLocalFile(path));
    });

    connect(ui->toggle_gdbstub, &QCheckBox::toggled,
            [&]() { ui->gdbport_spinbox->setEnabled(ui->toggle_gdbstub->isChecked()); });
}

ConfigureDebug::~ConfigureDebug() = default;

void ConfigureDebug::SetConfiguration() {
    const bool runtime_lock = !system.IsPoweredOn();
    ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub.GetValue());
    ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub.GetValue());
    ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port.GetValue());
    ui->toggle_console->setEnabled(runtime_lock);
    ui->toggle_console->setChecked(UISettings::values.show_console.GetValue());
    ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter.GetValue()));
    ui->homebrew_args_edit->setText(
        QString::fromStdString(Settings::values.program_args.GetValue()));
    ui->fs_access_log->setEnabled(runtime_lock);
    ui->fs_access_log->setChecked(Settings::values.enable_fs_access_log.GetValue());
    ui->reporting_services->setChecked(Settings::values.reporting_services.GetValue());
    ui->dump_audio_commands->setChecked(Settings::values.dump_audio_commands.GetValue());
    ui->quest_flag->setChecked(Settings::values.quest_flag.GetValue());
    ui->use_debug_asserts->setChecked(Settings::values.use_debug_asserts.GetValue());
    ui->use_auto_stub->setChecked(Settings::values.use_auto_stub.GetValue());
    ui->enable_all_controllers->setChecked(Settings::values.enable_all_controllers.GetValue());
    ui->enable_renderdoc_hotkey->setEnabled(runtime_lock);
    ui->enable_renderdoc_hotkey->setChecked(Settings::values.enable_renderdoc_hotkey.GetValue());
    ui->disable_buffer_reorder->setEnabled(runtime_lock);
    ui->disable_buffer_reorder->setChecked(Settings::values.disable_buffer_reorder.GetValue());
    ui->enable_graphics_debugging->setEnabled(runtime_lock);
    ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug.GetValue());
    ui->enable_shader_feedback->setEnabled(runtime_lock);
    ui->enable_shader_feedback->setChecked(Settings::values.renderer_shader_feedback.GetValue());
    ui->enable_cpu_debugging->setEnabled(runtime_lock);
    ui->enable_cpu_debugging->setChecked(Settings::values.cpu_debug_mode.GetValue());
    ui->enable_nsight_aftermath->setEnabled(runtime_lock);
    ui->enable_nsight_aftermath->setChecked(Settings::values.enable_nsight_aftermath.GetValue());
    ui->dump_shaders->setEnabled(runtime_lock);
    ui->dump_shaders->setChecked(Settings::values.dump_shaders.GetValue());
    ui->dump_macros->setEnabled(runtime_lock);
    ui->dump_macros->setChecked(Settings::values.dump_macros.GetValue());
    ui->disable_macro_jit->setEnabled(runtime_lock);
    ui->disable_macro_jit->setChecked(Settings::values.disable_macro_jit.GetValue());
    ui->disable_macro_hle->setEnabled(runtime_lock);
    ui->disable_macro_hle->setChecked(Settings::values.disable_macro_hle.GetValue());
    ui->disable_loop_safety_checks->setEnabled(runtime_lock);
    ui->disable_loop_safety_checks->setChecked(
        Settings::values.disable_shader_loop_safety_checks.GetValue());
    ui->extended_logging->setChecked(Settings::values.extended_logging.GetValue());
    ui->perform_vulkan_check->setChecked(Settings::values.perform_vulkan_check.GetValue());

#ifdef YUZU_USE_QT_WEB_ENGINE
    ui->disable_web_applet->setChecked(UISettings::values.disable_web_applet.GetValue());
#else
    ui->disable_web_applet->setEnabled(false);
    ui->disable_web_applet->setText(tr("Web applet not compiled"));
#endif
}

void ConfigureDebug::ApplyConfiguration() {
    Settings::values.use_gdbstub = ui->toggle_gdbstub->isChecked();
    Settings::values.gdbstub_port = ui->gdbport_spinbox->value();
    UISettings::values.show_console = ui->toggle_console->isChecked();
    Settings::values.log_filter = ui->log_filter_edit->text().toStdString();
    Settings::values.program_args = ui->homebrew_args_edit->text().toStdString();
    Settings::values.enable_fs_access_log = ui->fs_access_log->isChecked();
    Settings::values.reporting_services = ui->reporting_services->isChecked();
    Settings::values.dump_audio_commands = ui->dump_audio_commands->isChecked();
    Settings::values.quest_flag = ui->quest_flag->isChecked();
    Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked();
    Settings::values.use_auto_stub = ui->use_auto_stub->isChecked();
    Settings::values.enable_all_controllers = ui->enable_all_controllers->isChecked();
    Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked();
    Settings::values.enable_renderdoc_hotkey = ui->enable_renderdoc_hotkey->isChecked();
    Settings::values.disable_buffer_reorder = ui->disable_buffer_reorder->isChecked();
    Settings::values.renderer_shader_feedback = ui->enable_shader_feedback->isChecked();
    Settings::values.cpu_debug_mode = ui->enable_cpu_debugging->isChecked();
    Settings::values.enable_nsight_aftermath = ui->enable_nsight_aftermath->isChecked();
    Settings::values.dump_shaders = ui->dump_shaders->isChecked();
    Settings::values.dump_macros = ui->dump_macros->isChecked();
    Settings::values.disable_shader_loop_safety_checks =
        ui->disable_loop_safety_checks->isChecked();
    Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked();
    Settings::values.disable_macro_hle = ui->disable_macro_hle->isChecked();
    Settings::values.extended_logging = ui->extended_logging->isChecked();
    Settings::values.perform_vulkan_check = ui->perform_vulkan_check->isChecked();
    UISettings::values.disable_web_applet = ui->disable_web_applet->isChecked();
    Debugger::ToggleConsole();
    Common::Log::Filter filter;
    filter.ParseFilterString(Settings::values.log_filter.GetValue());
    Common::Log::SetGlobalFilter(filter);
}

void ConfigureDebug::changeEvent(QEvent* event) {
    if (event->type() == QEvent::LanguageChange) {
        RetranslateUI();
    }

    QWidget::changeEvent(event);
}

void ConfigureDebug::RetranslateUI() {
    ui->retranslateUi(this);
}


code:
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <memory>
#include <QScrollArea>

namespace Core {
class System;
}

namespace Ui {
class ConfigureDebug;
}

class ConfigureDebug : public QScrollArea {
    Q_OBJECT

public:
    explicit ConfigureDebug(const Core::System& system_, QWidget* parent = nullptr);
    ~ConfigureDebug() override;

    void ApplyConfiguration();

private:
    void changeEvent(QEvent* event) override;

    void RetranslateUI();
    void SetConfiguration();

    std::unique_ptr<Ui::ConfigureDebug> ui;

    const Core::System& system;

    bool crash_dump_warning_shown{false};
};


code:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>ConfigureDebug</class>
 <widget class="QScrollArea" name="ConfigureDebug">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>831</width>
    <height>760</height>
   </rect>
  </property>
  <property name="widgetResizable">
   <bool>true</bool>
  </property>
  <widget class="QWidget" name="widget">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>842</width>
     <height>741</height>
    </rect>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout_1">
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout">
      <property name="topMargin">
       <number>0</number>
      </property>
      <item>
       <widget class="QGroupBox" name="groupBox">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
        <property name="title">
         <string>Debugger</string>
        </property>
        <property name="alignment">
         <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
        </property>
        <property name="flat">
         <bool>false</bool>
        </property>
        <property name="checkable">
         <bool>false</bool>
        </property>
        <layout class="QVBoxLayout" name="verticalLayout_3">
         <item>
          <widget class="QWidget" name="debug_widget" native="true">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <layout class="QVBoxLayout" name="verticalLayout">
            <property name="sizeConstraint">
             <enum>QLayout::SetDefaultConstraint</enum>
            </property>
            <property name="leftMargin">
             <number>0</number>
            </property>
            <property name="topMargin">
             <number>0</number>
            </property>
            <property name="rightMargin">
             <number>0</number>
            </property>
            <property name="bottomMargin">
             <number>0</number>
            </property>
            <item>
             <widget class="QCheckBox" name="toggle_gdbstub">
              <property name="sizePolicy">
               <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
                <horstretch>0</horstretch>
                <verstretch>0</verstretch>
               </sizepolicy>
              </property>
              <property name="text">
               <string>Enable GDB Stub</string>
              </property>
             </widget>
            </item>
            <item>
             <widget class="QWidget" name="horizontalWidget_3" native="true">
              <property name="sizePolicy">
               <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
                <horstretch>0</horstretch>
                <verstretch>0</verstretch>
               </sizepolicy>
              </property>
              <layout class="QHBoxLayout" name="horizontalLayout_3">
               <property name="leftMargin">
                <number>0</number>
               </property>
               <property name="topMargin">
                <number>0</number>
               </property>
               <property name="rightMargin">
                <number>0</number>
               </property>
               <property name="bottomMargin">
                <number>0</number>
               </property>
               <item>
                <widget class="QLabel" name="label_11">
                 <property name="sizePolicy">
                  <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
                   <horstretch>0</horstretch>
                   <verstretch>0</verstretch>
                  </sizepolicy>
                 </property>
                 <property name="text">
                  <string>Port:</string>
                 </property>
                </widget>
               </item>
               <item>
                <widget class="QSpinBox" name="gdbport_spinbox">
                 <property name="sizePolicy">
                  <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
                   <horstretch>0</horstretch>
                   <verstretch>0</verstretch>
                  </sizepolicy>
                 </property>
                 <property name="minimum">
                  <number>1024</number>
                 </property>
                 <property name="maximum">
                  <number>65535</number>
                 </property>
                </widget>
               </item>
              </layout>
             </widget>
            </item>
           </layout>
          </widget>
         </item>
        </layout>
       </widget>
      </item>
      <item>
       <widget class="QGroupBox" name="groupBox_2">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
        <property name="title">
         <string>Logging</string>
        </property>
        <layout class="QGridLayout" name="gridLayout_1">
         <item row="1" column="1">
          <widget class="QPushButton" name="open_log_button">
           <property name="text">
            <string>Open Log Location</string>
           </property>
          </widget>
         </item>
         <item row="0" column="0" colspan="2">
          <widget class="QWidget" name="logging_widget" native="true">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <layout class="QHBoxLayout" name="horizontalLayout_1">
            <property name="leftMargin">
             <number>0</number>
            </property>
            <property name="topMargin">
             <number>0</number>
            </property>
            <property name="rightMargin">
             <number>0</number>
            </property>
            <property name="bottomMargin">
             <number>0</number>
            </property>
            <item>
             <widget class="QLabel" name="label_1">
              <property name="sizePolicy">
               <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
                <horstretch>0</horstretch>
                <verstretch>0</verstretch>
               </sizepolicy>
              </property>
              <property name="text">
               <string>Global Log Filter</string>
              </property>
             </widget>
            </item>
            <item>
             <widget class="QLineEdit" name="log_filter_edit"/>
            </item>
           </layout>
          </widget>
         </item>
         <item row="2" column="0">
          <widget class="QCheckBox" name="extended_logging">
           <property name="enabled">
            <bool>true</bool>
           </property>
           <property name="toolTip">
            <string>When checked, the max size of the log increases from 100 MB to 1 GB</string>
           </property>
           <property name="text">
            <string>Enable Extended Logging**</string>
           </property>
          </widget>
         </item>
         <item row="1" column="0">
          <widget class="QCheckBox" name="toggle_console">
           <property name="text">
            <string>Show Log in Console</string>
           </property>
          </widget>
         </item>
        </layout>
       </widget>
      </item>
     </layout>
    </item>
    <item>
     <widget class="QGroupBox" name="groupBox_3">
      <property name="title">
       <string>Homebrew</string>
      </property>
      <layout class="QVBoxLayout" name="verticalLayout_5">
       <item>
        <layout class="QHBoxLayout" name="horizontalLayout_4">
         <item>
          <widget class="QLabel" name="label_3">
           <property name="text">
            <string>Arguments String</string>
           </property>
          </widget>
         </item>
         <item>
          <widget class="QLineEdit" name="homebrew_args_edit"/>
         </item>
        </layout>
       </item>
      </layout>
     </widget>
    </item>
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout_2">
      <item>
       <widget class="QGroupBox" name="groupBox_4">
        <property name="title">
         <string>Graphics</string>
        </property>
        <layout class="QGridLayout" name="gridLayout_2">
         <item row="4" column="0">
          <widget class="QCheckBox" name="disable_loop_safety_checks">
           <property name="toolTip">
            <string>When checked, it executes shaders without loop logic changes</string>
           </property>
           <property name="text">
            <string>Disable Loop safety checks</string>
           </property>
          </widget>
         </item>
         <item row="8" column="0">
          <widget class="QCheckBox" name="dump_macros">
           <property name="enabled">
            <bool>true</bool>
           </property>
           <property name="toolTip">
            <string>When checked, it will dump all the macro programs of the GPU</string>
           </property>
           <property name="text">
            <string>Dump Maxwell Macros</string>
           </property>
          </widget>
         </item>
         <item row="3" column="0">
          <widget class="QCheckBox" name="enable_nsight_aftermath">
           <property name="toolTip">
            <string>When checked, it enables Nsight Aftermath crash dumps</string>
           </property>
           <property name="text">
            <string>Enable Nsight Aftermath</string>
           </property>
          </widget>
         </item>
         <item row="6" column="0">
          <widget class="QCheckBox" name="dump_shaders">
           <property name="enabled">
            <bool>true</bool>
           </property>
           <property name="toolTip">
            <string>When checked, it will dump all the original assembler shaders from the disk shader cache or game as found</string>
           </property>
           <property name="text">
            <string>Dump Game Shaders</string>
           </property>
          </widget>
         </item>
         <item row="1" column="0">
          <widget class="QCheckBox" name="enable_renderdoc_hotkey">
           <property name="text">
            <string>Enable Renderdoc Hotkey</string>
           </property>
          </widget>
         </item>
         <item row="7" column="0">
          <widget class="QCheckBox" name="disable_macro_jit">
           <property name="enabled">
            <bool>true</bool>
           </property>
           <property name="toolTip">
            <string>When checked, it disables the macro Just In Time compiler. Enabling this makes games run slower</string>
           </property>
           <property name="text">
            <string>Disable Macro JIT</string>
           </property>
          </widget>
         </item>
         <item row="9" column="0">
          <widget class="QCheckBox" name="disable_macro_hle">
           <property name="enabled">
            <bool>true</bool>
           </property>
           <property name="toolTip">
            <string>When checked, it disables the macro HLE functions. Enabling this makes games run slower</string>
           </property>
           <property name="text">
            <string>Disable Macro HLE</string>
           </property>
          </widget>
         </item>
         <item row="0" column="0">
          <widget class="QCheckBox" name="enable_graphics_debugging">
           <property name="enabled">
            <bool>true</bool>
           </property>
           <property name="toolTip">
            <string>When checked, the graphics API enters a slower debugging mode</string>
           </property>
           <property name="text">
            <string>Enable Graphics Debugging</string>
           </property>
          </widget>
         </item>
         <item row="10" column="0">
          <spacer name="verticalSpacer_5">
           <property name="orientation">
            <enum>Qt::Vertical</enum>
           </property>
           <property name="sizeType">
            <enum>QSizePolicy::Preferred</enum>
           </property>
           <property name="sizeHint" stdset="0">
            <size>
             <width>20</width>
             <height>0</height>
            </size>
           </property>
          </spacer>
         </item>
         <item row="2" column="0">
          <widget class="QCheckBox" name="enable_shader_feedback">
           <property name="toolTip">
            <string>When checked, yuzu will log statistics about the compiled pipeline cache</string>
           </property>
           <property name="text">
            <string>Enable Shader Feedback</string>
           </property>
          </widget>
         </item>
         <item row="5" column="0">
          <widget class="QCheckBox" name="disable_buffer_reorder">
           <property name="toolTip">
            <string>
When checked, disables reordering of mapped memory uploads which allows to associate uploads with specific draws. May reduce performance in some cases.
</string>
           </property>
           <property name="text">
            <string>Disable Buffer Reorder</string>
           </property>
          </widget>
         </item>
        </layout>
       </widget>
      </item>
      <item>
       <widget class="QGroupBox" name="groupBox_6">
        <property name="title">
         <string>Advanced</string>
        </property>
        <layout class="QGridLayout" name="gridLayout_4">
         <item row="3" column="0">
          <widget class="QCheckBox" name="perform_vulkan_check">
           <property name="toolTip">
            <string>Enables yuzu to check for a working Vulkan environment when the program starts up. Disable this if this is causing issues with external programs seeing yuzu.</string>
           </property>
           <property name="text">
            <string>Perform Startup Vulkan Check</string>
           </property>
          </widget>
         </item>
         <item row="4" column="0">
          <widget class="QCheckBox" name="disable_web_applet">
           <property name="text">
            <string>Disable Web Applet</string>
           </property>
          </widget>
         </item>
         <item row="5" column="0">
          <widget class="QCheckBox" name="enable_all_controllers">
           <property name="text">
            <string>Enable All Controller Types</string>
           </property>
          </widget>
         </item>
         <item row="6" column="0">
          <widget class="QCheckBox" name="use_auto_stub">
           <property name="text">
            <string>Enable Auto-Stub**</string>
           </property>
          </widget>
         </item>
         <item row="0" column="0">
          <widget class="QCheckBox" name="quest_flag">
           <property name="text">
            <string>Kiosk (Quest) Mode</string>
           </property>
          </widget>
         </item>
         <item row="1" column="0">
          <widget class="QCheckBox" name="enable_cpu_debugging">
           <property name="text">
            <string>Enable CPU Debugging</string>
           </property>
          </widget>
         </item>
         <item row="2" column="0">
          <widget class="QCheckBox" name="use_debug_asserts">
           <property name="text">
            <string>Enable Debug Asserts</string>
           </property>
          </widget>
         </item>
         <item row="7" column="0">
          <spacer name="verticalSpacer_4">
           <property name="orientation">
            <enum>Qt::Vertical</enum>
           </property>
           <property name="sizeType">
            <enum>QSizePolicy::Expanding</enum>
           </property>
           <property name="sizeHint" stdset="0">
            <size>
             <width>20</width>
             <height>0</height>
            </size>
           </property>
          </spacer>
         </item>
        </layout>
       </widget>
      </item>
      <item>
       <widget class="QGroupBox" name="groupBox_5">
        <property name="title">
         <string>Debugging</string>
        </property>
        <layout class="QGridLayout" name="gridLayout_3">
         <item row="0" column="0">
          <widget class="QCheckBox" name="fs_access_log">
           <property name="text">
            <string>Enable FS Access Log</string>
           </property>
          </widget>
         </item>
         <item row="3" column="0">
          <widget class="QCheckBox" name="dump_audio_commands">
           <property name="toolTip">
            <string>Enable this to output the latest generated audio command list to the console. Only affects games using the audio renderer.</string>
           </property>
           <property name="text">
            <string>Dump Audio Commands To Console**</string>
           </property>
          </widget>
         </item>
         <item row="2" column="0">
          <widget class="QCheckBox" name="reporting_services">
           <property name="text">
            <string>Enable Verbose Reporting Services**</string>
           </property>
          </widget>
         </item>
         <item row="5" column="0">
          <spacer name="verticalSpacer_3">
           <property name="orientation">
            <enum>Qt::Vertical</enum>
           </property>
           <property name="sizeType">
            <enum>QSizePolicy::Expanding</enum>
           </property>
           <property name="sizeHint" stdset="0">
            <size>
             <width>20</width>
             <height>0</height>
            </size>
           </property>
          </spacer>
         </item>
        </layout>
       </widget>
      </item>
     </layout>
    </item>
    <item>
     <spacer name="verticalSpacer">
      <property name="orientation">
       <enum>Qt::Vertical</enum>
      </property>
      <property name="sizeHint" stdset="0">
       <size>
        <width>20</width>
        <height>0</height>
       </size>
      </property>
     </spacer>
    </item>
    <item>
     <widget class="QLabel" name="label_5">
      <property name="sizePolicy">
       <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
      <property name="font">

        <italic>true</italic>

      </property>
      <property name="text">
       <string>**This will be reset automatically when yuzu closes.</string>
      </property>
      <property name="indent">
       <number>20</number>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
 </widget>
 <tabstops>
  <tabstop>log_filter_edit</tabstop>
  <tabstop>toggle_console</tabstop>
  <tabstop>extended_logging</tabstop>
  <tabstop>open_log_button</tabstop>
  <tabstop>homebrew_args_edit</tabstop>
  <tabstop>enable_graphics_debugging</tabstop>
  <tabstop>enable_shader_feedback</tabstop>
  <tabstop>enable_nsight_aftermath</tabstop>
  <tabstop>fs_access_log</tabstop>
  <tabstop>reporting_services</tabstop>
  <tabstop>quest_flag</tabstop>
  <tabstop>enable_cpu_debugging</tabstop>
  <tabstop>use_debug_asserts</tabstop>
 </tabstops>
 <resources/>
 <connections/>
</ui>


code:
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "hid_core/hid_core.h"
#include "ui_configure_debug_controller.h"
#include "yuzu/configuration/configure_debug_controller.h"
#include "yuzu/configuration/configure_input_player.h"

ConfigureDebugController::ConfigureDebugController(QWidget* parent,
                                                   InputCommon::InputSubsystem* input_subsystem,
                                                   InputProfiles* profiles,
                                                   Core::HID::HIDCore& hid_core, bool is_powered_on)
    : QDialog(parent), ui(std::make_unique<Ui::ConfigureDebugController>()),
      debug_controller(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles,
                                                hid_core, is_powered_on, true)) {
    ui->setupUi(this);

    ui->controllerLayout->addWidget(debug_controller);

    connect(ui->clear_all_button, &QPushButton::clicked, this,
            [this] { debug_controller->ClearAll(); });
    connect(ui->restore_defaults_button, &QPushButton::clicked, this,
            [this] { debug_controller->RestoreDefaults(); });

    RetranslateUI();
}

ConfigureDebugController::~ConfigureDebugController() = default;

void ConfigureDebugController::ApplyConfiguration() {
    debug_controller->ApplyConfiguration();
}

void ConfigureDebugController::changeEvent(QEvent* event) {
    if (event->type() == QEvent::LanguageChange) {
        RetranslateUI();
    }

    QDialog::changeEvent(event);
}

void ConfigureDebugController::RetranslateUI() {
    ui->retranslateUi(this);
}


code:
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <memory>
#include <QDialog>

class QPushButton;

class ConfigureInputPlayer;

class InputProfiles;

namespace Core::HID {
class HIDCore;
}

namespace InputCommon {
class InputSubsystem;
}

namespace Ui {
class ConfigureDebugController;
}

class ConfigureDebugController : public QDialog {
    Q_OBJECT

public:
    explicit ConfigureDebugController(QWidget* parent, InputCommon::InputSubsystem* input_subsystem,
                                      InputProfiles* profiles, Core::HID::HIDCore& hid_core,
                                      bool is_powered_on);
    ~ConfigureDebugController() override;

    void ApplyConfiguration();

private:
    void changeEvent(QEvent* event) override;
    void RetranslateUI();

    std::unique_ptr<Ui::ConfigureDebugController> ui;

    ConfigureInputPlayer* debug_controller;
};


code:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>ConfigureDebugController</class>
 <widget class="QDialog" name="ConfigureDebugController">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>780</width>
    <height>500</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Configure Debug Controller</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <property name="spacing">
    <number>2</number>
   </property>
   <property name="leftMargin">
    <number>9</number>
   </property>
   <property name="topMargin">
    <number>9</number>
   </property>
   <property name="rightMargin">
    <number>9</number>
   </property>
   <property name="bottomMargin">
    <number>9</number>
   </property>
   <item>
    <layout class="QHBoxLayout" name="controllerLayout"/>
   </item>
   <item>
    <layout class="QHBoxLayout" name="horizontalLayout">
     <item>
      <widget class="QPushButton" name="clear_all_button">
       <property name="text">
        <string>Clear</string>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QPushButton" name="restore_defaults_button">
       <property name="text">
        <string>Defaults</string>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QDialogButtonBox" name="buttonBox">
       <property name="standardButtons">
        <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
       </property>
      </widget>
     </item>
    </layout>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections>
  <connection>
   <sender>buttonBox</sender>
   <signal>accepted()</signal>
   <receiver>ConfigureDebugController</receiver>
   <slot>accept()</slot>
  </connection>
  <connection>
   <sender>buttonBox</sender>
   <signal>rejected()</signal>
   <receiver>ConfigureDebugController</receiver>
   <slot>reject()</slot>
  </connection>
 </connections>
</ui>


code:
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include <memory>
#include "ui_configure_debug_tab.h"
#include "yuzu/configuration/configure_cpu_debug.h"
#include "yuzu/configuration/configure_debug.h"
#include "yuzu/configuration/configure_debug_tab.h"

ConfigureDebugTab::ConfigureDebugTab(const Core::System& system_, QWidget* parent)
    : QWidget(parent), ui{std::make_unique<Ui::ConfigureDebugTab>()},
      debug_tab{std::make_unique<ConfigureDebug>(system_, this)},
      cpu_debug_tab{std::make_unique<ConfigureCpuDebug>(system_, this)} {
    ui->setupUi(this);

    ui->tabWidget->addTab(debug_tab.get(), tr("Debug"));
    ui->tabWidget->addTab(cpu_debug_tab.get(), tr("CPU"));

    SetConfiguration();
}

ConfigureDebugTab::~ConfigureDebugTab() = default;

void ConfigureDebugTab::ApplyConfiguration() {
    debug_tab->ApplyConfiguration();
    cpu_debug_tab->ApplyConfiguration();
}

void ConfigureDebugTab::SetCurrentIndex(int index) {
    ui->tabWidget->setCurrentIndex(index);
}

void ConfigureDebugTab::changeEvent(QEvent* event) {
    if (event->type() == QEvent::LanguageChange) {
        RetranslateUI();
    }

    QWidget::changeEvent(event);
}

void ConfigureDebugTab::RetranslateUI() {
    ui->retranslateUi(this);
}

void ConfigureDebugTab::SetConfiguration() {}


code:
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <memory>
#include <QWidget>

class ConfigureDebug;
class ConfigureCpuDebug;

namespace Core {
class System;
}

namespace Ui {
class ConfigureDebugTab;
}

class ConfigureDebugTab : public QWidget {
    Q_OBJECT

public:
    explicit ConfigureDebugTab(const Core::System& system_, QWidget* parent = nullptr);
    ~ConfigureDebugTab() override;

    void ApplyConfiguration();

    void SetCurrentIndex(int index);

private:
    void changeEvent(QEvent* event) override;
    void RetranslateUI();

    void SetConfiguration();

    std::unique_ptr<Ui::ConfigureDebugTab> ui;

    std::unique_ptr<ConfigureDebug> debug_tab;
    std::unique_ptr<ConfigureCpuDebug> cpu_debug_tab;
};


code:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>ConfigureDebugTab</class>
 <widget class="QWidget" name="ConfigureDebugTab">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>320</width>
    <height>240</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <property name="accessibleName">
   <string>Debug</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
    <widget class="QTabWidget" name="tabWidget">
     <property name="currentIndex">
      <number>-1</number>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>


code:
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include <memory>
#include "common/logging/log.h"
#include "common/settings.h"
#include "common/settings_enums.h"
#include "core/core.h"
#include "ui_configure.h"
#include "vk_device_info.h"
#include "yuzu/configuration/configure_applets.h"
#include "yuzu/configuration/configure_audio.h"
#include "yuzu/configuration/configure_cpu.h"
#include "yuzu/configuration/configure_debug_tab.h"
#include "yuzu/configuration/configure_dialog.h"
#include "yuzu/configuration/configure_filesystem.h"
#include "yuzu/configuration/configure_general.h"
#include "yuzu/configuration/configure_graphics.h"
#include "yuzu/configuration/configure_graphics_advanced.h"
#include "yuzu/configuration/configure_hotkeys.h"
#include "yuzu/configuration/configure_input.h"
#include "yuzu/configuration/configure_input_player.h"
#include "yuzu/configuration/configure_network.h"
#include "yuzu/configuration/configure_profile_manager.h"
#include "yuzu/configuration/configure_system.h"
#include "yuzu/configuration/configure_ui.h"
#include "yuzu/configuration/configure_web.h"
#include "yuzu/hotkeys.h"
#include "yuzu/uisettings.h"

ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
                                 InputCommon::InputSubsystem* input_subsystem,
                                 std::vector<VkDeviceInfo::Record>& vk_device_records,
                                 Core::System& system_, bool enable_web_config)
    : QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()},
      registry(registry_), system{system_}, builder{std::make_unique<ConfigurationShared::Builder>(
                                                this, !system_.IsPoweredOn())},
      applets_tab{std::make_unique<ConfigureApplets>(system_, nullptr, *builder, this)},
      audio_tab{std::make_unique<ConfigureAudio>(system_, nullptr, *builder, this)},
      cpu_tab{std::make_unique<ConfigureCpu>(system_, nullptr, *builder, this)},
      debug_tab_tab{std::make_unique<ConfigureDebugTab>(system_, this)},
      filesystem_tab{std::make_unique<ConfigureFilesystem>(this)},
      general_tab{std::make_unique<ConfigureGeneral>(system_, nullptr, *builder, this)},
      graphics_advanced_tab{
          std::make_unique<ConfigureGraphicsAdvanced>(system_, nullptr, *builder, this)},
      ui_tab{std::make_unique<ConfigureUi>(system_, this)},
      graphics_tab{std::make_unique<ConfigureGraphics>(
          system_, vk_device_records, [&]() { graphics_advanced_tab->ExposeComputeOption(); },
          [this](Settings::AspectRatio ratio, Settings::ResolutionSetup setup) {
              ui_tab->UpdateScreenshotInfo(ratio, setup);
          },
          nullptr, *builder, this)},
      hotkeys_tab{std::make_unique<ConfigureHotkeys>(system_.HIDCore(), this)},
      input_tab{std::make_unique<ConfigureInput>(system_, this)},
      network_tab{std::make_unique<ConfigureNetwork>(system_, this)},
      profile_tab{std::make_unique<ConfigureProfileManager>(system_, this)},
      system_tab{std::make_unique<ConfigureSystem>(system_, nullptr, *builder, this)},
      web_tab{std::make_unique<ConfigureWeb>(this)} {
    Settings::SetConfiguringGlobal(true);

    ui->setupUi(this);

    ui->tabWidget->addTab(applets_tab.get(), tr("Applets"));
    ui->tabWidget->addTab(audio_tab.get(), tr("Audio"));
    ui->tabWidget->addTab(cpu_tab.get(), tr("CPU"));
    ui->tabWidget->addTab(debug_tab_tab.get(), tr("Debug"));
    ui->tabWidget->addTab(filesystem_tab.get(), tr("Filesystem"));
    ui->tabWidget->addTab(general_tab.get(), tr("General"));
    ui->tabWidget->addTab(graphics_tab.get(), tr("Graphics"));
    ui->tabWidget->addTab(graphics_advanced_tab.get(), tr("GraphicsAdvanced"));
    ui->tabWidget->addTab(hotkeys_tab.get(), tr("Hotkeys"));
    ui->tabWidget->addTab(input_tab.get(), tr("Controls"));
    ui->tabWidget->addTab(profile_tab.get(), tr("Profiles"));
    ui->tabWidget->addTab(network_tab.get(), tr("Network"));
    ui->tabWidget->addTab(system_tab.get(), tr("System"));
    ui->tabWidget->addTab(ui_tab.get(), tr("Game List"));
    ui->tabWidget->addTab(web_tab.get(), tr("Web"));

    web_tab->SetWebServiceConfigEnabled(enable_web_config);
    hotkeys_tab->Populate(registry);

    input_tab->Initialize(input_subsystem);

    general_tab->SetResetCallback([&] { this->close(); });

    SetConfiguration();
    PopulateSelectionList();

    connect(ui->tabWidget, &QTabWidget::currentChanged, this, [this](int index) {
        if (index != -1) {
            debug_tab_tab->SetCurrentIndex(0);
        }
    });
    connect(ui_tab.get(), &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged);
    connect(ui->selectorList, &QListWidget::itemSelectionChanged, this,
            &ConfigureDialog::UpdateVisibleTabs);

    if (system.IsPoweredOn()) {
        QPushButton* apply_button = ui->buttonBox->addButton(QDialogButtonBox::Apply);
        connect(apply_button, &QAbstractButton::clicked, this,
                &ConfigureDialog::HandleApplyButtonClicked);
    }

    adjustSize();
    ui->selectorList->setCurrentRow(0);

    // Selects the leftmost button on the bottom bar (Cancel as of writing)
    ui->buttonBox->setFocus();
}

ConfigureDialog::~ConfigureDialog() = default;

void ConfigureDialog::SetConfiguration() {}

void ConfigureDialog::ApplyConfiguration() {
    general_tab->ApplyConfiguration();
    ui_tab->ApplyConfiguration();
    system_tab->ApplyConfiguration();
    profile_tab->ApplyConfiguration();
    filesystem_tab->ApplyConfiguration();
    input_tab->ApplyConfiguration();
    hotkeys_tab->ApplyConfiguration(registry);
    cpu_tab->ApplyConfiguration();
    graphics_tab->ApplyConfiguration();
    graphics_advanced_tab->ApplyConfiguration();
    audio_tab->ApplyConfiguration();
    debug_tab_tab->ApplyConfiguration();
    web_tab->ApplyConfiguration();
    network_tab->ApplyConfiguration();
    applets_tab->ApplyConfiguration();
    system.ApplySettings();
    Settings::LogSettings();
}

void ConfigureDialog::changeEvent(QEvent* event) {
    if (event->type() == QEvent::LanguageChange) {
        RetranslateUI();
    }

    QDialog::changeEvent(event);
}

void ConfigureDialog::RetranslateUI() {
    const int old_row = ui->selectorList->currentRow();
    const int old_index = ui->tabWidget->currentIndex();

    ui->retranslateUi(this);

    PopulateSelectionList();
    ui->selectorList->setCurrentRow(old_row);

    UpdateVisibleTabs();
    ui->tabWidget->setCurrentIndex(old_index);
}

void ConfigureDialog::HandleApplyButtonClicked() {
    UISettings::values.configuration_applied = true;
    ApplyConfiguration();
}

Q_DECLARE_METATYPE(QList<QWidget*>);

void ConfigureDialog::PopulateSelectionList() {
    const std::array<std::pair<QString, QList<QWidget*>>, 6> items{
        {{tr("General"),
          {general_tab.get(), hotkeys_tab.get(), ui_tab.get(), web_tab.get(), debug_tab_tab.get()}},
         {tr("System"),
          {system_tab.get(), profile_tab.get(), network_tab.get(), filesystem_tab.get(),
           applets_tab.get()}},
         {tr("CPU"), {cpu_tab.get()}},
         {tr("Graphics"), {graphics_tab.get(), graphics_advanced_tab.get()}},
         {tr("Audio"), {audio_tab.get()}},
         {tr("Controls"), input_tab->GetSubTabs()}},
    };

    [[maybe_unused]] const QSignalBlocker blocker(ui->selectorList);

    ui->selectorList->clear();
    for (const auto& entry : items) {
        auto* const item = new QListWidgetItem(entry.first);
        item->setData(Qt::UserRole, QVariant::fromValue(entry.second));

        ui->selectorList->addItem(item);
    }
}

void ConfigureDialog::OnLanguageChanged(const QString& locale) {
    emit LanguageChanged(locale);
    //  Reloading the game list is needed to force retranslation.
    UISettings::values.is_game_list_reload_pending = true;
    // first apply the configuration, and then restore the display
    ApplyConfiguration();
    RetranslateUI();
    SetConfiguration();
}

void ConfigureDialog::UpdateVisibleTabs() {
    const auto items = ui->selectorList->selectedItems();
    if (items.isEmpty()) {
        return;
    }

    [[maybe_unused]] const QSignalBlocker blocker(ui->tabWidget);

    ui->tabWidget->clear();

    const auto tabs = qvariant_cast<QList<QWidget*>>(items[0]->data(Qt::UserRole));

    for (auto* const tab : tabs) {
        LOG_DEBUG(Frontend, "{}", tab->accessibleName().toStdString());
        ui->tabWidget->addTab(tab, tab->accessibleName());
    }
}


code:
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <memory>
#include <vector>
#include <QDialog>
#include "configuration/shared_widget.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/shared_translation.h"
#include "yuzu/vk_device_info.h"

namespace Core {
class System;
}

class ConfigureApplets;
class ConfigureAudio;
class ConfigureCpu;
class ConfigureDebugTab;
class ConfigureFilesystem;
class ConfigureGeneral;
class ConfigureGraphics;
class ConfigureGraphicsAdvanced;
class ConfigureHotkeys;
class ConfigureInput;
class ConfigureProfileManager;
class ConfigureSystem;
class ConfigureNetwork;
class ConfigureUi;
class ConfigureWeb;

class HotkeyRegistry;

namespace InputCommon {
class InputSubsystem;
}

namespace Ui {
class ConfigureDialog;
}

class ConfigureDialog : public QDialog {
    Q_OBJECT

public:
    explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
                             InputCommon::InputSubsystem* input_subsystem,
                             std::vector<VkDeviceInfo::Record>& vk_device_records,
                             Core::System& system_, bool enable_web_config = true);
    ~ConfigureDialog() override;

    void ApplyConfiguration();

private slots:
    void OnLanguageChanged(const QString& locale);

signals:
    void LanguageChanged(const QString& locale);

private:
    void changeEvent(QEvent* event) override;
    void RetranslateUI();

    void HandleApplyButtonClicked();

    void SetConfiguration();
    void UpdateVisibleTabs();
    void PopulateSelectionList();

    std::unique_ptr<Ui::ConfigureDialog> ui;
    HotkeyRegistry& registry;

    Core::System& system;
    std::unique_ptr<ConfigurationShared::Builder> builder;
    std::vector<ConfigurationShared::Tab*> tab_group;

    std::unique_ptr<ConfigureApplets> applets_tab;
    std::unique_ptr<ConfigureAudio> audio_tab;
    std::unique_ptr<ConfigureCpu> cpu_tab;
    std::unique_ptr<ConfigureDebugTab> debug_tab_tab;
    std::unique_ptr<ConfigureFilesystem> filesystem_tab;
    std::unique_ptr<ConfigureGeneral> general_tab;
    std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab;
    std::unique_ptr<ConfigureUi> ui_tab;
    std::unique_ptr<ConfigureGraphics> graphics_tab;
    std::unique_ptr<ConfigureHotkeys> hotkeys_tab;
    std::unique_ptr<ConfigureInput> input_tab;
    std::unique_ptr<ConfigureNetwork> network_tab;
    std::unique_ptr<ConfigureProfileManager> profile_tab;
    std::unique_ptr<ConfigureSystem> system_tab;
    std::unique_ptr<ConfigureWeb> web_tab;
};